diff --git a/.circleci/config.yml b/.circleci/config.yml index bcb01f2a8..73b81fb16 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -75,29 +75,6 @@ restore_cache: &restore-gradle-cache name: Restore gradle cache key: android-{{ checksum "android/build.gradle" }}-{{ checksum "android/app/build.gradle" }} -restore-brew-cache: &restore-brew-cache - name: Restore Brew cache - key: brew-{{ checksum "yarn.lock" }}-{{ checksum ".circleci/config.yml" }} - -save-brew-cache: &save-brew-cache - name: Save brew cache - key: brew-{{ checksum "yarn.lock" }}-{{ checksum ".circleci/config.yml" }} - paths: - - /usr/local/Homebrew - -install-apple-sim-utils: &install-apple-sim-utils - name: Install appleSimUtils - command: | - brew update - brew tap wix/brew - brew install wix/brew/applesimutils - -rebuild-detox: &rebuild-detox - name: Rebuild Detox framework cache - command: | - npx detox clean-framework-cache - npx detox build-framework-cache - version: 2.1 # EXECUTORS @@ -107,35 +84,6 @@ executors: environment: <<: *bash-env -# COMMANDS -commands: - detox-test: - parameters: - folder: - type: string - steps: - - checkout - - - attach_workspace: - at: . - - - restore_cache: *restore-npm-cache-mac - - - restore_cache: *restore-brew-cache - - - run: *install-node - - - run: *install-apple-sim-utils - - - run: *install-npm-modules - - - run: *rebuild-detox - - - run: - name: Test - command: | - npx detox test << parameters.folder >> --configuration ios.sim.release --cleanup - # JOBS jobs: lint-testunit: @@ -170,57 +118,6 @@ jobs: - save_cache: *save-npm-cache-linux - # E2E - e2e-build: - executor: mac-env - - steps: - - checkout - - - restore_cache: *restore-npm-cache-mac - - - restore_cache: *restore-brew-cache - - - run: *install-node - - - run: *install-apple-sim-utils - - - run: *install-npm-modules - - - run: *rebuild-detox - - - run: - name: Build - command: | - npx detox build --configuration ios.sim.release - - - persist_to_workspace: - root: . - paths: - - ios/build/Build/Products/Release-iphonesimulator/RocketChatRN.app - - - save_cache: *save-npm-cache-mac - - - save_cache: *save-brew-cache - - e2e-test-onboarding: - executor: mac-env - steps: - - detox-test: - folder: "./e2e/tests/onboarding" - - e2e-test-room: - executor: mac-env - steps: - - detox-test: - folder: "./e2e/tests/room" - - e2e-test-assorted: - executor: mac-env - steps: - - detox-test: - folder: "./e2e/tests/assorted" - # Android builds android-build: <<: *defaults @@ -429,23 +326,6 @@ workflows: jobs: - lint-testunit - - e2e-hold: - type: approval - requires: - - lint-testunit - - e2e-build: - requires: - - e2e-hold - - e2e-test-onboarding: - requires: - - e2e-build - - e2e-test-room: - requires: - - e2e-build - - e2e-test-assorted: - requires: - - e2e-build - - ios-build: requires: - lint-testunit diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index c868686af..3cbbc7560 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,7 +1,34 @@ - -@RocketChat/ReactNative + - -Closes #ISSUE_NUMBER +## Proposed changes + - +## Issue(s) + + +## How to test or reproduce + + +## Screenshots + +## Types of changes + + + +- [ ] Bugfix (non-breaking change which fixes an issue) +- [ ] Improvement (non-breaking change which improves a current function) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Documentation update (if none of the other choices apply) + +## Checklist + + +- [ ] I have read the [CONTRIBUTING](https://github.com/RocketChat/Rocket.Chat/blob/develop/.github/CONTRIBUTING.md#contributing-to-rocketchat) doc +- [ ] I have signed the [CLA](https://cla-assistant.io/RocketChat/Rocket.Chat.ReactNative) +- [ ] Lint and unit tests pass locally with my changes +- [ ] I have added tests that prove my fix is effective or that my feature works (if applicable) +- [ ] I have added necessary documentation (if applicable) +- [ ] Any dependent changes have been merged and published in downstream modules + +## Further comments + diff --git a/.github/workflows/ios_detox.yml b/.github/workflows/ios_detox.yml new file mode 100644 index 000000000..c8c33c583 --- /dev/null +++ b/.github/workflows/ios_detox.yml @@ -0,0 +1,221 @@ +name: iOS Detox + +on: [pull_request] + +jobs: + detox-build: + runs-on: macos-latest + timeout-minutes: 60 + + env: + DEVELOPER_DIR: /Applications/Xcode_11.5.app + + steps: + - name: Checkout + uses: actions/checkout@v1 + with: + fetch-depth: 1 + + - name: Generate Detox app cache key + run: echo $(git rev-parse HEAD:app) > "./app-git-revision.txt" + + - name: Cache Detox app + uses: actions/cache@v1 + id: detoxappcache + with: + path: ios/build/Build/Products/Release-iphonesimulator + key: iOSDetoxRelease-v4-${{ hashFiles('yarn.lock') }}-${{ hashFiles('ios/Podfile.lock') }}-${{ hashFiles('./app-git-revision.txt') }} + + - name: Node + if: steps.detoxappcache.outputs.cache-hit != 'true' + uses: actions/setup-node@v1 + + - name: Cache node modules + if: steps.detoxappcache.outputs.cache-hit != 'true' + uses: actions/cache@v1 + id: npmcache + with: + path: node_modules + key: node-modules-${{ hashFiles('**/yarn.lock') }} + + - name: Rebuild detox + if: steps.detoxappcache.outputs.cache-hit != 'true' && steps.npmcache.outputs.cache-hit == 'true' + run: yarn detox clean-framework-cache && yarn detox build-framework-cache + + - name: Install Dependencies + if: steps.detoxappcache.outputs.cache-hit != 'true' && steps.npmcache.outputs.cache-hit != 'true' + run: yarn install + + - run: yarn detox build e2e --configuration ios.sim.release + if: steps.detoxappcache.outputs.cache-hit != 'true' + + detox-test-rooms: + needs: detox-build + runs-on: macos-latest + timeout-minutes: 60 + + env: + DEVELOPER_DIR: /Applications/Xcode_11.5.app + + steps: + - name: Checkout + uses: actions/checkout@v1 + with: + fetch-depth: 1 + + - name: Generate Detox app cache key + run: echo $(git rev-parse HEAD:app) > "./app-git-revision.txt" + + - name: Cache Detox app + uses: actions/cache@v1 + id: detoxappcache + with: + path: ios/build/Build/Products/Release-iphonesimulator + key: iOSDetoxRelease-v4-${{ hashFiles('yarn.lock') }}-${{ hashFiles('ios/Podfile.lock') }}-${{ hashFiles('./app-git-revision.txt') }} + + - name: Check for Detox app + if: steps.detoxappcache.outputs.cache-hit != 'true' + run: exit 1 + + - name: Node + uses: actions/setup-node@v1 + + - name: Cache node modules + uses: actions/cache@v1 + id: npmcache + with: + path: node_modules + key: node-modules-${{ hashFiles('**/yarn.lock') }} + + - name: Rebuild detox + if: steps.npmcache.outputs.cache-hit == 'true' + run: yarn detox clean-framework-cache && yarn detox build-framework-cache + + - name: Install Dependencies + if: steps.npmcache.outputs.cache-hit != 'true' + run: yarn install + + - run: brew tap wix/brew + - run: brew install applesimutils + - run: yarn detox test e2e/tests/room --configuration ios.sim.release --cleanup + + - name: Upload test artifacts + if: ${{ failure() }} + uses: actions/upload-artifact@v2 + with: + name: artifacts + path: artifacts + + detox-test-assorted: + needs: detox-build + runs-on: macos-latest + timeout-minutes: 60 + + env: + DEVELOPER_DIR: /Applications/Xcode_11.5.app + + steps: + - name: Checkout + uses: actions/checkout@v1 + with: + fetch-depth: 1 + + - name: Generate Detox app cache key + run: echo $(git rev-parse HEAD:app) > "./app-git-revision.txt" + + - name: Cache Detox app + uses: actions/cache@v1 + id: detoxappcache + with: + path: ios/build/Build/Products/Release-iphonesimulator + key: iOSDetoxRelease-v4-${{ hashFiles('yarn.lock') }}-${{ hashFiles('ios/Podfile.lock') }}-${{ hashFiles('./app-git-revision.txt') }} + + - name: Check for Detox app + if: steps.detoxappcache.outputs.cache-hit != 'true' + run: exit 1 + + - name: Node + uses: actions/setup-node@v1 + + - name: Cache node modules + uses: actions/cache@v1 + id: npmcache + with: + path: node_modules + key: node-modules-${{ hashFiles('**/yarn.lock') }} + + - name: Rebuild detox + if: steps.npmcache.outputs.cache-hit == 'true' + run: yarn detox clean-framework-cache && yarn detox build-framework-cache + + - name: Install Dependencies + if: steps.npmcache.outputs.cache-hit != 'true' + run: yarn install + + - run: brew tap wix/brew + - run: brew install applesimutils + - run: yarn detox test e2e/tests/assorted --configuration ios.sim.release --cleanup + + - name: Upload test artifacts + if: ${{ failure() }} + uses: actions/upload-artifact@v2 + with: + name: artifacts + path: artifacts + + detox-test-onboarding: + needs: detox-build + runs-on: macos-latest + timeout-minutes: 60 + + env: + DEVELOPER_DIR: /Applications/Xcode_11.5.app + + steps: + - name: Checkout + uses: actions/checkout@v1 + with: + fetch-depth: 1 + + - name: Generate Detox app cache key + run: echo $(git rev-parse HEAD:app) > "./app-git-revision.txt" + + - name: Cache Detox app + uses: actions/cache@v1 + id: detoxappcache + with: + path: ios/build/Build/Products/Release-iphonesimulator + key: iOSDetoxRelease-v4-${{ hashFiles('yarn.lock') }}-${{ hashFiles('ios/Podfile.lock') }}-${{ hashFiles('./app-git-revision.txt') }} + + - name: Check for Detox app + if: steps.detoxappcache.outputs.cache-hit != 'true' + run: exit 1 + + - name: Node + uses: actions/setup-node@v1 + + - name: Cache node modules + uses: actions/cache@v1 + id: npmcache + with: + path: node_modules + key: node-modules-${{ hashFiles('**/yarn.lock') }} + + - name: Rebuild detox + if: steps.npmcache.outputs.cache-hit == 'true' + run: yarn detox clean-framework-cache && yarn detox build-framework-cache + + - name: Install Dependencies + if: steps.npmcache.outputs.cache-hit != 'true' + run: yarn install + + - run: brew tap wix/brew + - run: brew install applesimutils + - run: yarn detox test e2e/tests/onboarding --configuration ios.sim.release --cleanup + + - name: Upload test artifacts + if: ${{ failure() }} + uses: actions/upload-artifact@v2 + with: + name: artifacts + path: artifacts diff --git a/.gitignore b/.gitignore index fee7bf865..18624dd0b 100644 --- a/.gitignore +++ b/.gitignore @@ -58,6 +58,7 @@ buck-out/ coverage +artifacts .vscode/ e2e/docker/rc_test_env/docker-compose.yml e2e/docker/data/db \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..1990eb949 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,93 @@ +# Contributing Guidelines + +Great to have you here! Here are a few ways you can help make this project better! + +## Setting up a development environment + +Refer to [React Native environment setup](https://reactnative.dev/docs/environment-setup) to make sure everything is up and running. +Follow the `React Native CLI Quickstart` section as we don't support Expo managed flow. + +*Note: you'll need a MacOS to run iOS apps* + +### How to run + +Clone repository and install dependencies: +```sh +git clone git@github.com:RocketChat/Rocket.Chat.ReactNative.git +cd Rocket.Chat.ReactNative +yarn +``` + +Run the app: +```sh +npx react-native run-ios +``` + +or + +```sh +npx react-native run-android +``` + +At this point, the app should be running on the simulator or on your device! + +*Note: npm won't work on this project* + +## Issues needing help + +Didn't find a bug or want a new feature not already reported? Check out the [help wanted](https://github.com/RocketChat/Rocket.Chat.ReactNative/issues?q=is%3Aissue+is%3Aopen+label%3A%22%F0%9F%91%8B+help+wanted%22) or the [good first issue](https://github.com/RocketChat/Rocket.Chat.ReactNative/issues?q=is%3Aissue+is%3Aopen+label%3A%22%F0%9F%8D%AD+good+first+issue%22) labels. + +Can't help coding? Triaging issues is a **great** way of helping. + +## Code style + +We use [ESLint](https://eslint.org/) to enforce code style and best practices. We have a pre-commit hook enforcing commits to follow our lint rules. + +To check for lint issues on your code, run this on your terminal: + +```sh +yarn lint +``` + +## Tests + +It's always important to ensure everything is working properly and that's why tests are great. We have unit and e2e tests on this project. + +### Unit tests + +We use [Jest](https://jestjs.io/) and [Storybook](https://storybook.js.org/) on our tests. + +#### Storybook + +Storybook is a tool for developing UI Components and has some plugins to make Jest generate snapshots of them. + +[On the root of the project](https://github.com/RocketChat/Rocket.Chat.ReactNative/blob/develop/index.js#L24), comment everything leaving only the last import to Storybook left and refresh your project. +You'll see some tests like this: + + + +#### Jest + +We use Jest for our unit tests and to generate Storybook snapshots. We have a pre-commit hook enforcing preventing commits that breaks any test. + +To check for test issues on your code, run this on your terminal: + +```sh +yarn test +``` + +### E2E tests + +We use [Detox](https://github.com/wix/Detox) framework to end-to-end test our app and ensure everything is working properly. + +[Follow this documentation to learn how to run it](https://github.com/RocketChat/Rocket.Chat.ReactNative/blob/develop/e2e). + +### Pull request + +As soon as your changes are ready, you can open a Pull Request. + +The title of your PR should be descriptive, including either [NEW], [IMPROVEMENT] or [FIX] at the beginning, e.g. [FIX] App crashing on startup. + +You may share working results prior to finishing, please include [WIP] in the title. This way anyone can look at your code: you can ask for help within the PR if you don't know how to solve a problem. + +Your PR is automatically inspected by various tools, check their response and try to improve your code accordingly. Requests that fail to build or have wrong coding style won't be merged. diff --git a/README.md b/README.md index 1f0c5deea..f5197c4ca 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,12 @@ [![codecov](https://codecov.io/gh/RocketChat/Rocket.Chat.ReactNative/branch/master/graph/badge.svg)](https://codecov.io/gh/RocketChat/Rocket.Chat.ReactNative) [![CodeFactor](https://www.codefactor.io/repository/github/rocketchat/rocket.chat.reactnative/badge)](https://www.codefactor.io/repository/github/rocketchat/rocket.chat.reactnative) -**Supported Server Versions:** 0.70.0+ +- **Supported server versions:** 0.70.0+ +- **Supported iOS versions**: 11+ +- **Supported Android versions**: 5.0+ ## Download -### Official apps Download on Google Play @@ -17,29 +18,7 @@ Download on App Store -### Experimental apps - - Download on Google Play - - - Download on App Store - - -## Beta Access - -### TestFlight - -You can signup to our TestFlight builds by accessing these links: - -- Official: https://testflight.apple.com/join/3gcYeoMr -- Experimental: https://testflight.apple.com/join/7I3dLCNT. - -### Google Play beta - -You can subscribe to Google Play Beta program and download latest versions: - -- Official: https://play.google.com/store/apps/details?id=chat.rocket.android -- Experimental: https://play.google.com/store/apps/details?id=chat.rocket.reactnative +Check [our docs](https://docs.rocket.chat/installation/mobile-and-desktop-apps#mobile-apps) for beta and Experimental versions. ## Reporting an Issue @@ -47,195 +26,16 @@ You can subscribe to Google Play Beta program and download latest versions: Also check the [#react-native](https://open.rocket.chat/channel/react-native) community on [open.rocket.chat](https://open.rocket.chat). We'd like to help. -## Installing dependencies +## Contributing -Follow the [React Native Getting Started Guide](https://facebook.github.io/react-native/docs/getting-started.html) for detailed instructions on setting up your local machine for development. +Are you a dev and would like to help? Found a bug that you would like to report or a missing feature that you would like to work on? Great! We have written down a [Contribution guide](https://github.com/RocketChat/Rocket.Chat.ReactNative/blob/develop/CONTRIBUTING.md) so you can start easily. -## How to run -- Clone repository and install dependencies: - ```bash - $ git clone git@github.com:RocketChat/Rocket.Chat.ReactNative.git - $ cd Rocket.Chat.ReactNative - $ yarn - ``` +## Whitelabel +Do you want to make the app run on your own server only? [Follow our whitelabel documentation.](https://docs.rocket.chat/guides/developer/mobile-apps/whitelabeling-mobile-apps) -- Run application - ```bash - $ npx react-native run-ios - ``` - ```bash - $ npx react-native run-android - ``` +## Engage with us +### Share your story +We’d love to hear about [your experience](https://survey.zohopublic.com/zs/e4BUFG) and potentially feature it on our [Blog](https://rocket.chat/case-studies/?utm_source=github&utm_medium=readme&utm_campaign=community). -### Running single server -If you don't need multiple servers, there is a branch `single-server` just for that. -Readme will guide you on how to config. - -## Current priorities -1) Omnichannel support -2) E2E encryption - -## Features -| Feature | Status | -|--------------------------------------------------------------- |-------- | -| Jitsi Integration | ✅ | -| Federation (Directory) | ✅ | -| Discussions | ✅ | -| Omnichannel | ❌ | -| Threads | ✅ | -| Record Audio | ✅ | -| Record Video | ✅ | -| Commands | ✅ | -| Draft message per room | ✅ | -| Share Extension | ✅ | -| Notifications Preferences | ✅ | -| Edited status | ✅ | -| Upload video | ✅ | -| Grouped messages | ✅ | -| Mark room as read | ✅ | -| Mark room as unread | ✅ | -| Tablet Support | ✅ | -| Read receipt | ✅ | -| Broadbast Channel | ✅ | -| Authentication via SAML | ✅ | -| Authentication via CAS | ✅ | -| Custom Fields on Signup | ✅ | -| Report message | ✅ | -| Theming | ✅ | -| Settings -> Review the App | ✅ | -| Settings -> Default Browser | ✅ | -| Admin panel | ✅ | -| Reply message from notification | ✅ | -| Unread counter banner on message list | ✅ | -| E2E Encryption | ❌ | -| Join a Protected Room | ❌ | -| Optional Analytics | ✅ | -| Settings -> About us | ❌ | -| Settings -> Contact us | ✅ | -| Settings -> Update App Icon | ❌ | -| Settings -> Share | ✅ | -| Accessibility (Medium) | ❌ | -| Accessibility (Advanced) | ❌ | -| Authentication via Meteor | ❌ | -| Authentication via Wordpress | ✅ | -| Authentication via Custom OAuth | ✅ | -| Add user to the room | ✅ | -| Send message | ✅ | -| Authentication via Email | ✅ | -| Authentication via Username | ✅ | -| Authentication via LDAP | ✅ | -| Message format: Markdown | ✅ | -| Message format: System messages (Welcome, Message removed...) | ✅ | -| Message format: links | ✅ | -| Message format: images | ✅ | -| Message format: replies | ✅ | -| Message format: alias with custom message (title & text) | ✅ | -| Messages list: day separation | ✅ | -| Messages list: load more on scroll | ✅ | -| Messages list: receive new messages via subscription | ✅ | -| Subscriptions list | ✅ | -| Segmented subscriptions list: Favorites | ✅ | -| Segmented subscriptions list: Unreads | ✅ | -| Segmented subscriptions list: DMs | ✅ | -| Segmented subscriptions list: Channels | ✅ | -| Subscriptions list: update user status via subscription | ✅ | -| Numbers os messages unread in the Subscriptions list | ✅ | -| Status change | ✅ | -| Upload image | ✅ | -| Take picture & upload it | ✅ | -| 2FA | ✅ | -| Signup | ✅ | -| Autocomplete with usernames | ✅ | -| Autocomplete with @all & @here | ✅ | -| Autocomplete room/channel name | ✅ | -| Upload audio | ✅ | -| Forgot your password | ✅ | -| Login screen: terms of service | ✅ | -| Login screen: privacy policy | ✅ | -| Authentication via Google | ✅ | -| Authentication via Facebook | ✅ | -| Authentication via Twitter | ✅ | -| Authentication via GitHub | ✅ | -| Authentication via GitLab | ✅ | -| Authentication via LinkedIn | ✅ | -| Create channel | ✅ | -| Search Local | ✅ | -| Search in the API | ✅ | -| Settings -> License | ✅ | -| Settings -> App version | ✅ | -| Autocomplete emoji | ✅ | -| Upload file (documents, PDFs, spreadsheets, zip files, etc) | ✅ | -| Copy message | ✅ | -| Pin message | ✅ | -| Unpin message | ✅ | -| Channel Info screen -> Members | ✅ | -| Channel Info screen -> Pinned | ✅ | -| Channel Info screen -> Starred | ✅ | -| Channel Info screen -> Uploads | ✅ | -| Star message | ✅ | -| Unstar message | ✅ | -| Channel Info screen -> Topic | ✅ | -| Channel Info screen -> Description | ✅ | -| Star a channel | ✅ | -| Message format: videos | ✅ | -| Message format: audios | ✅ | -| Edit message | ✅ | -| Delete a message | ✅ | -| Reply message | ✅ | -| Quote message | ✅ | -| Muted state | ✅ | -| Offline reading | ✅ | -| Offline writing | ✅ | -| Edit profile | ✅ | -| Reactions | ✅ | -| Custom emojis | ✅ | -| Accessibility (Basic) | ✅ | -| Tap notification, go to the channel | ✅ | -| Deep links: Authentication | ✅ | -| Deep links: Rooms | ✅ | -| Full name setting | ✅ | -| Read only rooms | ✅ | -| Typing status | ✅ | -| Create channel/group | ✅ | -| Disable registration setting | ✅ | -| Unread red line indicator on message list | ✅ | -| Search Messages in Channel | ✅ | -| Mentions List | ✅ | -| Attachment List | ✅ | -| Join a Room | ✅ | - -## Detox (end-to-end tests) -- Build your app - -```bash -$ npx detox build --configuration ios.sim.release -``` - -- Run tests - -```bash -$ npx detox test ./e2e/tests/onboarding --configuration ios.sim.release -$ npx detox test ./e2e/tests/room --configuration ios.sim.release -$ npx detox test ./e2e/tests/assorted --configuration ios.sim.release -``` - -## Storybook -- Open index.js - -- Uncomment following line - -```bash -import './storybook'; -``` - -- Comment out following lines -```bash -import './app/ReactotronConfig'; -import { AppRegistry } from 'react-native'; -import App from './app/index'; -import { name as appName } from './app.json'; - -AppRegistry.registerComponent(appName, () => App); -``` - -- Start your application again \ No newline at end of file +### Subscribe for Updates +Once a month our marketing team releases an email update with news about product releases, company related topics, events and use cases. [Sign Up!](https://rocket.chat/newsletter/?utm_source=github&utm_medium=readme&utm_campaign=community) diff --git a/__mocks__/react-native-firebase.js b/__mocks__/@react-native-firebase/analytics.js similarity index 100% rename from __mocks__/react-native-firebase.js rename to __mocks__/@react-native-firebase/analytics.js diff --git a/__mocks__/@react-native-firebase/crashlytics.js b/__mocks__/@react-native-firebase/crashlytics.js new file mode 100644 index 000000000..8e8b4e8db --- /dev/null +++ b/__mocks__/@react-native-firebase/crashlytics.js @@ -0,0 +1,3 @@ +export default { + crashlytics: null +}; diff --git a/__tests__/__snapshots__/Storyshots.test.js.snap b/__tests__/__snapshots__/Storyshots.test.js.snap index e881064aa..b9d4dc1ee 100644 --- a/__tests__/__snapshots__/Storyshots.test.js.snap +++ b/__tests__/__snapshots__/Storyshots.test.js.snap @@ -22,10 +22,9 @@ exports[`Storyshots Markdown list Markdown 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, Object { @@ -89,10 +88,9 @@ exports[`Storyshots Markdown list Markdown 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, Object { @@ -156,10 +154,9 @@ exports[`Storyshots Markdown list Markdown 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, Object { @@ -355,10 +352,9 @@ exports[`Storyshots Markdown list Markdown 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, Object { @@ -441,10 +437,9 @@ exports[`Storyshots Markdown list Markdown 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, Object { @@ -547,10 +542,9 @@ exports[`Storyshots Markdown list Markdown 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, Object { @@ -584,13 +578,17 @@ exports[`Storyshots Markdown list Markdown 1`] = ` style={ Array [ Object { - "backgroundColor": "#1d74f5", - "color": "#ffffff", + "backgroundColor": "transparent", "fontFamily": "System", "fontSize": 16, "fontWeight": "500", + "letterSpacing": 0.5, "padding": 5, }, + Object { + "backgroundColor": "#ffe9ec", + "color": "#f5455c", + }, ] } > @@ -627,13 +625,17 @@ exports[`Storyshots Markdown list Markdown 1`] = ` style={ Array [ Object { - "backgroundColor": "#E8F2FF", - "color": "#1d74f5", + "backgroundColor": "transparent", "fontFamily": "System", "fontSize": 16, "fontWeight": "500", + "letterSpacing": 0.5, "padding": 5, }, + Object { + "backgroundColor": "#fff6d6", + "color": "#b68d00", + }, ] } > @@ -669,15 +671,16 @@ exports[`Storyshots Markdown list Markdown 1`] = ` style={ Array [ Object { - "backgroundColor": "#E8F2FF", - "color": "#ffffff", + "backgroundColor": "transparent", "fontFamily": "System", "fontSize": 16, "fontWeight": "500", + "letterSpacing": 0.5, "padding": 5, }, Object { - "backgroundColor": "#FF5B5A", + "backgroundColor": "#fde8d7", + "color": "#f38c39", }, ] } @@ -714,15 +717,16 @@ exports[`Storyshots Markdown list Markdown 1`] = ` style={ Array [ Object { - "backgroundColor": "#E8F2FF", - "color": "#ffffff", + "backgroundColor": "transparent", "fontFamily": "System", "fontSize": 16, "fontWeight": "500", + "letterSpacing": 0.5, "padding": 5, }, Object { - "backgroundColor": "#FF5B5A", + "backgroundColor": "#fde8d7", + "color": "#f38c39", }, ] } @@ -781,10 +785,9 @@ exports[`Storyshots Markdown list Markdown 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, Object { @@ -818,13 +821,17 @@ exports[`Storyshots Markdown list Markdown 1`] = ` style={ Array [ Object { - "backgroundColor": "#1d74f5", - "color": "#ffffff", + "backgroundColor": "transparent", "fontFamily": "System", "fontSize": 16, "fontWeight": "500", + "letterSpacing": 0.5, "padding": 5, }, + Object { + "backgroundColor": "#ffe9ec", + "color": "#f5455c", + }, ] } > @@ -861,13 +868,17 @@ exports[`Storyshots Markdown list Markdown 1`] = ` style={ Array [ Object { - "backgroundColor": "#E8F2FF", - "color": "#1d74f5", + "backgroundColor": "transparent", "fontFamily": "System", "fontSize": 16, "fontWeight": "500", + "letterSpacing": 0.5, "padding": 5, }, + Object { + "backgroundColor": "#fff6d6", + "color": "#b68d00", + }, ] } > @@ -903,15 +914,16 @@ exports[`Storyshots Markdown list Markdown 1`] = ` style={ Array [ Object { - "backgroundColor": "#E8F2FF", - "color": "#ffffff", + "backgroundColor": "transparent", "fontFamily": "System", "fontSize": 16, "fontWeight": "500", + "letterSpacing": 0.5, "padding": 5, }, Object { - "backgroundColor": "#FF5B5A", + "backgroundColor": "#fde8d7", + "color": "#f38c39", }, ] } @@ -948,15 +960,16 @@ exports[`Storyshots Markdown list Markdown 1`] = ` style={ Array [ Object { - "backgroundColor": "#E8F2FF", - "color": "#ffffff", + "backgroundColor": "transparent", "fontFamily": "System", "fontSize": 16, "fontWeight": "500", + "letterSpacing": 0.5, "padding": 5, }, Object { - "backgroundColor": "#FF5B5A", + "backgroundColor": "#fde8d7", + "color": "#f38c39", }, ] } @@ -1015,10 +1028,9 @@ exports[`Storyshots Markdown list Markdown 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, Object { @@ -1052,17 +1064,21 @@ exports[`Storyshots Markdown list Markdown 1`] = ` style={ Array [ Object { - "backgroundColor": "#E8F2FF", - "color": "#0072FE", + "backgroundColor": "transparent", "fontFamily": "System", "fontSize": 16, "fontWeight": "500", + "letterSpacing": 0.5, "padding": 5, }, + Object { + "backgroundColor": "#fff6d6", + "color": "#b68d00", + }, ] } > - test-channel + #test-channel + User status + + View + View + View + View + View + `; @@ -5157,10 +5118,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, undefined, @@ -5176,10 +5136,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, undefined, @@ -5195,10 +5154,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, undefined, @@ -5214,10 +5172,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, undefined, @@ -5233,10 +5190,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, undefined, @@ -5252,10 +5208,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, undefined, @@ -5271,10 +5226,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, undefined, @@ -5290,10 +5244,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, undefined, @@ -5309,10 +5262,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, undefined, @@ -5328,10 +5280,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, undefined, @@ -5347,10 +5298,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, undefined, @@ -5366,10 +5316,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, undefined, @@ -5385,10 +5334,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, undefined, @@ -5434,10 +5382,9 @@ exports[`Storyshots UiKitModal list UiKitModal 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, undefined, @@ -5453,10 +5400,9 @@ exports[`Storyshots UiKitModal list UiKitModal 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, undefined, @@ -5472,10 +5418,9 @@ exports[`Storyshots UiKitModal list UiKitModal 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, undefined, @@ -5491,10 +5436,9 @@ exports[`Storyshots UiKitModal list UiKitModal 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, undefined, @@ -5510,10 +5454,9 @@ exports[`Storyshots UiKitModal list UiKitModal 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, undefined, @@ -5529,10 +5472,9 @@ exports[`Storyshots UiKitModal list UiKitModal 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, undefined, @@ -5548,10 +5490,9 @@ exports[`Storyshots UiKitModal list UiKitModal 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, undefined, @@ -5567,10 +5508,9 @@ exports[`Storyshots UiKitModal list UiKitModal 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, undefined, @@ -5586,10 +5526,9 @@ exports[`Storyshots UiKitModal list UiKitModal 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, undefined, @@ -5605,10 +5544,9 @@ exports[`Storyshots UiKitModal list UiKitModal 1`] = ` "fontSize": 20, "fontWeight": "300", "marginLeft": 10, - "marginTop": 30, + "marginVertical": 30, }, Object { - "backgroundColor": "#ffffff", "color": "#0d0e12", }, undefined, diff --git a/android/app/build.gradle b/android/app/build.gradle index 8bf5d0f93..3a6635823 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,7 +1,7 @@ apply plugin: "com.android.application" +apply plugin: 'com.google.gms.google-services' +apply plugin: 'com.google.firebase.crashlytics' apply plugin: 'kotlin-android' -apply plugin: "io.fabric" -apply plugin: "com.google.firebase.firebase-perf" apply plugin: 'com.bugsnag.android.gradle' import com.android.build.OutputFile @@ -168,15 +168,18 @@ android { minifyEnabled enableProguardInReleaseBuilds setProguardFiles([getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro']) signingConfig signingConfigs.release + firebaseCrashlytics { + nativeSymbolUploadEnabled true + } } } - packagingOptions { - pickFirst '**/armeabi-v7a/libc++_shared.so' - pickFirst '**/x86/libc++_shared.so' - pickFirst '**/arm64-v8a/libc++_shared.so' - pickFirst '**/x86_64/libc++_shared.so' - } + // packagingOptions { + // pickFirst '**/armeabi-v7a/libc++_shared.so' + // pickFirst '**/x86/libc++_shared.so' + // pickFirst '**/arm64-v8a/libc++_shared.so' + // pickFirst '**/x86_64/libc++_shared.so' + // } // applicationVariants are e.g. debug, release applicationVariants.all { variant -> @@ -215,11 +218,6 @@ dependencies { //noinspection GradleDynamicVersion implementation "com.facebook.react:react-native:+" // From node_modules implementation "com.google.firebase:firebase-messaging:18.0.0" - implementation "com.google.firebase:firebase-core:16.0.9" - implementation "com.google.firebase:firebase-perf:17.0.2" - implementation('com.crashlytics.sdk.android:crashlytics:2.9.9@aar') { - transitive = true - } implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") { exclude group:'com.facebook.fbjni' @@ -251,5 +249,4 @@ task copyDownloadableDepsToLibs(type: Copy) { into 'libs' } -apply plugin: 'com.google.gms.google-services' apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) \ No newline at end of file diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml index 5cf3292c2..ed773abe1 100644 --- a/android/app/src/debug/AndroidManifest.xml +++ b/android/app/src/debug/AndroidManifest.xml @@ -1,8 +1,13 @@ + xmlns:tools="http://schemas.android.com/tools" + package="chat.rocket.reactnative"> - + - + \ No newline at end of file diff --git a/android/app/src/debug/java/chat/rocket/reactnative/MainDebugApplication.java b/android/app/src/debug/java/chat/rocket/reactnative/MainDebugApplication.java new file mode 100644 index 000000000..e6abf3b05 --- /dev/null +++ b/android/app/src/debug/java/chat/rocket/reactnative/MainDebugApplication.java @@ -0,0 +1,25 @@ +package chat.rocket.reactnative; + +import android.content.Context; + +import com.facebook.react.ReactInstanceManager; + +public class MainDebugApplication extends MainApplication { + + @Override + public void onCreate() { + super.onCreate(); + initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); + } + + /** + * Loads Flipper in React Native templates. Call this in the onCreate method with something like + * initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); + * + * @param context + * @param reactInstanceManager + */ + private static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { + ReactNativeFlipper.initializeFlipper(context, reactInstanceManager); + } +} diff --git a/android/app/src/debug/java/chat/rocket/reactnative/ReactNativeFlipper.java b/android/app/src/debug/java/chat/rocket/reactnative/ReactNativeFlipper.java index 07e08afd4..42eaf35c8 100644 --- a/android/app/src/debug/java/chat/rocket/reactnative/ReactNativeFlipper.java +++ b/android/app/src/debug/java/chat/rocket/reactnative/ReactNativeFlipper.java @@ -4,7 +4,7 @@ *

This source code is licensed under the MIT license found in the LICENSE file in the root * directory of this source tree. */ -package com.rndiffapp; +package chat.rocket.reactnative; import android.content.Context; import com.facebook.flipper.android.AndroidFlipperClient; import com.facebook.flipper.android.utils.FlipperUtils; diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index a672c0e28..ebfb8c74d 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -37,8 +37,10 @@ + + diff --git a/android/app/src/main/assets/fonts/custom.ttf b/android/app/src/main/assets/fonts/custom.ttf index 6f30643ad..a96927b90 100644 Binary files a/android/app/src/main/assets/fonts/custom.ttf and b/android/app/src/main/assets/fonts/custom.ttf differ diff --git a/android/app/src/main/java/chat/rocket/reactnative/Callback.java b/android/app/src/main/java/chat/rocket/reactnative/Callback.java new file mode 100644 index 000000000..2c2b2833a --- /dev/null +++ b/android/app/src/main/java/chat/rocket/reactnative/Callback.java @@ -0,0 +1,10 @@ +package chat.rocket.reactnative; + +import android.os.Bundle; +import androidx.annotation.Nullable; + +public class Callback { + public void call(@Nullable Bundle bundle) { + + } +} diff --git a/android/app/src/main/java/chat/rocket/reactnative/CustomPushNotification.java b/android/app/src/main/java/chat/rocket/reactnative/CustomPushNotification.java index 17002faa0..46c086eae 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/CustomPushNotification.java +++ b/android/app/src/main/java/chat/rocket/reactnative/CustomPushNotification.java @@ -14,8 +14,9 @@ import android.graphics.drawable.Icon; import android.os.Build; import android.os.Bundle; import android.app.Person; +import androidx.annotation.Nullable; -import com.google.gson.*; +import com.google.gson.Gson; import com.bumptech.glide.Glide; import com.bumptech.glide.load.resource.bitmap.RoundedCorners; import com.bumptech.glide.request.RequestOptions; @@ -33,15 +34,18 @@ import java.util.List; import java.util.Map; import java.util.ArrayList; import java.util.Date; +import java.util.Iterator; import static com.wix.reactnativenotifications.Defs.NOTIFICATION_RECEIVED_EVENT_NAME; public class CustomPushNotification extends PushNotification { public static ReactApplicationContext reactApplicationContext; + final NotificationManager notificationManager; public CustomPushNotification(Context context, Bundle bundle, AppLifecycleFacade appLifecycleFacade, AppLaunchHelper appLaunchHelper, JsIOHelper jsIoHelper) { super(context, bundle, appLifecycleFacade, appLaunchHelper, jsIoHelper); reactApplicationContext = new ReactApplicationContext(context); + notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); } private static Map> notificationMessages = new HashMap>(); @@ -54,29 +58,39 @@ public class CustomPushNotification extends PushNotification { @Override public void onReceived() throws InvalidNotificationException { - final Bundle bundle = mNotificationProps.asBundle(); + Bundle received = mNotificationProps.asBundle(); + Ejson receivedEjson = new Gson().fromJson(received.getString("ejson", "{}"), Ejson.class); + if (receivedEjson.notificationType != null && receivedEjson.notificationType.equals("message-id-only")) { + notificationLoad(receivedEjson, new Callback() { + @Override + public void call(@Nullable Bundle bundle) { + if (bundle != null) { + mNotificationProps = createProps(bundle); + } + } + }); + } + + // We should re-read these values since that can be changed by notificationLoad + Bundle bundle = mNotificationProps.asBundle(); + Ejson loadedEjson = new Gson().fromJson(bundle.getString("ejson", "{}"), Ejson.class); String notId = bundle.getString("notId", "1"); - String title = bundle.getString("title"); if (notificationMessages.get(notId) == null) { notificationMessages.put(notId, new ArrayList()); } - Gson gson = new Gson(); - Ejson ejson = gson.fromJson(bundle.getString("ejson", "{}"), Ejson.class); - - boolean hasSender = ejson.sender != null; + boolean hasSender = loadedEjson.sender != null; + String title = bundle.getString("title"); bundle.putLong("time", new Date().getTime()); - bundle.putString("username", hasSender ? ejson.sender.username : title); - bundle.putString("senderId", hasSender ? ejson.sender._id : "1"); - bundle.putString("avatarUri", ejson.getAvatarUri()); + bundle.putString("username", hasSender ? loadedEjson.sender.username : title); + bundle.putString("senderId", hasSender ? loadedEjson.sender._id : "1"); + bundle.putString("avatarUri", loadedEjson.getAvatarUri()); notificationMessages.get(notId).add(bundle); - - super.postNotification(Integer.parseInt(notId)); - + postNotification(Integer.parseInt(notId)); notifyReceivedToJS(); } @@ -96,9 +110,11 @@ public class CustomPushNotification extends PushNotification { String notId = bundle.getString("notId", "1"); String title = bundle.getString("title"); String message = bundle.getString("message"); + Boolean notificationLoaded = bundle.getBoolean("notificationLoaded", false); + Ejson ejson = new Gson().fromJson(bundle.getString("ejson", "{}"), Ejson.class); notification - .setContentTitle(title) + .setContentTitle(title) .setContentText(message) .setContentIntent(intent) .setPriority(Notification.PRIORITY_HIGH) @@ -109,10 +125,34 @@ public class CustomPushNotification extends PushNotification { notificationColor(notification); notificationChannel(notification); notificationIcons(notification, bundle); - notificationStyle(notification, notificationId, bundle); - notificationReply(notification, notificationId, bundle); notificationDismiss(notification, notificationId); + // if notificationType is null (RC < 3.5) or notificationType is different of message-id-only or notification was loaded successfully + if (ejson.notificationType == null || !ejson.notificationType.equals("message-id-only") || notificationLoaded) { + notificationStyle(notification, notificationId, bundle); + notificationReply(notification, notificationId, bundle); + + // message couldn't be loaded from server (Fallback notification) + } else { + Gson gson = new Gson(); + // iterate over the current notification ids to dismiss fallback notifications from same server + for (Map.Entry> bundleList : notificationMessages.entrySet()) { + // iterate over the notifications with this id (same host + rid) + Iterator iterator = bundleList.getValue().iterator(); + while (iterator.hasNext()) { + Bundle not = (Bundle) iterator.next(); + // get the notification info + Ejson notEjson = gson.fromJson(not.getString("ejson", "{}"), Ejson.class); + // if already has a notification from same server + if (ejson.serverURL().equals(notEjson.serverURL())) { + String id = not.getString("notId"); + // cancel this notification + notificationManager.cancel(Integer.parseInt(id)); + } + } + } + } + return notification; } @@ -300,4 +340,7 @@ public class CustomPushNotification extends PushNotification { notification.setDeleteIntent(dismissPendingIntent); } + private void notificationLoad(Ejson ejson, Callback callback) { + LoadNotification.load(reactApplicationContext, ejson, callback); + } } diff --git a/android/app/src/main/java/chat/rocket/reactnative/Ejson.java b/android/app/src/main/java/chat/rocket/reactnative/Ejson.java index 48c370370..0c68e4755 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/Ejson.java +++ b/android/app/src/main/java/chat/rocket/reactnative/Ejson.java @@ -9,6 +9,8 @@ public class Ejson { String rid; String type; Sender sender; + String messageId; + String notificationType; private String TOKEN_KEY = "reactnativemeteor_usertoken-"; private SharedPreferences sharedPreferences = RNUserDefaultsModule.getPreferences(CustomPushNotification.reactApplicationContext); diff --git a/android/app/src/main/java/chat/rocket/reactnative/LoadNotification.java b/android/app/src/main/java/chat/rocket/reactnative/LoadNotification.java new file mode 100644 index 000000000..9c4c03744 --- /dev/null +++ b/android/app/src/main/java/chat/rocket/reactnative/LoadNotification.java @@ -0,0 +1,101 @@ +package chat.rocket.reactnative; + +import android.os.Bundle; +import android.content.Context; + +import okhttp3.Call; +import okhttp3.OkHttpClient; +import okhttp3.HttpUrl; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.Interceptor; + +import com.google.gson.Gson; +import java.io.IOException; + +import com.facebook.react.bridge.ReactApplicationContext; + +import chat.rocket.userdefaults.RNUserDefaultsModule; + +class JsonResponse { + Data data; + + class Data { + Notification notification; + + class Notification { + String notId; + String title; + String text; + Payload payload; + + class Payload { + String host; + String rid; + String type; + Sender sender; + String messageId; + String notificationType; + String name; + String messageType; + + class Sender { + String _id; + String username; + String name; + } + } + } + } +} + +public class LoadNotification { + private static int RETRY_COUNT = 0; + private static int[] TIMEOUT = new int[]{ 0, 1, 3, 5, 10 }; + private static String TOKEN_KEY = "reactnativemeteor_usertoken-"; + + public static void load(ReactApplicationContext reactApplicationContext, final Ejson ejson, Callback callback) { + final OkHttpClient client = new OkHttpClient(); + HttpUrl.Builder url = HttpUrl.parse(ejson.serverURL().concat("/api/v1/push.get")).newBuilder(); + + Request request = new Request.Builder() + .header("x-user-id", ejson.userId()) + .header("x-auth-token", ejson.token()) + .url(url.addQueryParameter("id", ejson.messageId).build()) + .build(); + + runRequest(client, request, callback); + } + + private static void runRequest(OkHttpClient client, Request request, Callback callback) { + try { + Thread.sleep(TIMEOUT[RETRY_COUNT] * 1000); + + Response response = client.newCall(request).execute(); + String body = response.body().string(); + if (!response.isSuccessful()) { + throw new Exception("Error"); + } + + Gson gson = new Gson(); + JsonResponse json = gson.fromJson(body, JsonResponse.class); + + Bundle bundle = new Bundle(); + bundle.putString("notId", json.data.notification.notId); + bundle.putString("title", json.data.notification.title); + bundle.putString("message", json.data.notification.text); + bundle.putString("ejson", gson.toJson(json.data.notification.payload)); + bundle.putBoolean("notificationLoaded", true); + + callback.call(bundle); + + } catch (Exception e) { + if (RETRY_COUNT <= TIMEOUT.length) { + RETRY_COUNT++; + runRequest(client, request, callback); + } else { + callback.call(null); + } + } + } +} diff --git a/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java b/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java index 530a2a857..6bcc62be8 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java +++ b/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java @@ -29,10 +29,6 @@ import com.wix.reactnativenotifications.core.notification.INotificationsApplicat import com.wix.reactnativenotifications.core.notification.IPushNotification; import com.wix.reactnativekeyboardinput.KeyboardInputPackage; -import io.invertase.firebase.fabric.crashlytics.RNFirebaseCrashlyticsPackage; -import io.invertase.firebase.analytics.RNFirebaseAnalyticsPackage; -import io.invertase.firebase.perf.RNFirebasePerformancePackage; - import com.nozbe.watermelondb.WatermelonDBPackage; import com.reactnativecommunity.viewpager.RNCViewPagerPackage; @@ -53,9 +49,6 @@ public class MainApplication extends Application implements ReactApplication, IN protected List getPackages() { @SuppressWarnings("UnnecessaryLocalVariable") List packages = new PackageList(this).getPackages(); - packages.add(new RNFirebaseCrashlyticsPackage()); - packages.add(new RNFirebaseAnalyticsPackage()); - packages.add(new RNFirebasePerformancePackage()); packages.add(new KeyboardInputPackage(MainApplication.this)); packages.add(new RNNotificationsPackage(MainApplication.this)); packages.add(new WatermelonDBPackage()); @@ -88,38 +81,6 @@ public class MainApplication extends Application implements ReactApplication, IN public void onCreate() { super.onCreate(); SoLoader.init(this, /* native exopackage */ false); - initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); - } - - /** - * Loads Flipper in React Native templates. Call this in the onCreate method with something like - * initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); - * - * @param context - * @param reactInstanceManager - */ - private static void initializeFlipper( - Context context, ReactInstanceManager reactInstanceManager) { - if (BuildConfig.DEBUG) { - try { - /* - We use reflection here to pick up the class that initializes Flipper, - since Flipper library is not available in release mode - */ - Class aClass = Class.forName("chat.rocket.reactnative"); - aClass - .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class) - .invoke(null, context, reactInstanceManager); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - } } @Override diff --git a/android/build.gradle b/android/build.gradle index f1e95820c..52f6ff0f0 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,10 +1,10 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { ext { - buildToolsVersion = "28.0.3" + buildToolsVersion = "29.0.2" minSdkVersion = 21 - compileSdkVersion = 28 - targetSdkVersion = 28 + compileSdkVersion = 29 + targetSdkVersion = 29 glideVersion = "4.9.0" kotlin_version = "1.3.50" supportLibVersion = "28.0.0" @@ -18,10 +18,9 @@ buildscript { } } dependencies { - classpath 'com.android.tools.build:gradle:3.5.2' + classpath 'com.android.tools.build:gradle:3.5.3' classpath 'com.google.gms:google-services:4.2.0' - classpath 'io.fabric.tools:gradle:1.28.1' - classpath 'com.google.firebase:perf-plugin:1.2.1' + classpath 'com.google.firebase:firebase-crashlytics-gradle:2.0.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'com.bugsnag:bugsnag-android-gradle-plugin:4.+' @@ -57,10 +56,10 @@ subprojects { subproject -> afterEvaluate { if ((subproject.plugins.hasPlugin('android') || subproject.plugins.hasPlugin('android-library'))) { android { - compileSdkVersion 28 - buildToolsVersion "28.0.3" + compileSdkVersion 29 + buildToolsVersion "29.0.2" defaultConfig { - targetSdkVersion 28 + targetSdkVersion 29 } variantFilter { variant -> def names = variant.flavors*.name diff --git a/android/gradle.properties b/android/gradle.properties index a7df71591..26d0e8372 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -27,7 +27,7 @@ android.useAndroidX=true android.enableJetifier=true # Version of flipper SDK to use with React Native -FLIPPER_VERSION=0.33.1 +FLIPPER_VERSION=0.51.0 # App properties VERSIONCODE=999999999 diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index e8758b6d5..7578b974b 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists \ No newline at end of file diff --git a/android/gradlew b/android/gradlew index 77564ddb2..645f6ca31 100755 --- a/android/gradlew +++ b/android/gradlew @@ -154,19 +154,19 @@ if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then else eval `echo args$i`="\"$arg\"" fi - i=$((i+1)) + i=`expr $i + 1` done case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi @@ -175,14 +175,9 @@ save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } -APP_ARGS=$(save "$@") +APP_ARGS=`save "$@"` # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - exec "$JAVACMD" "$@" \ No newline at end of file diff --git a/android/gradlew.bat b/android/gradlew.bat index 7d3e0e477..8d8accd7c 100644 --- a/android/gradlew.bat +++ b/android/gradlew.bat @@ -5,7 +5,7 @@ @rem you may not use this file except in compliance with the License. @rem You may obtain a copy of the License at @rem -@rem http://www.apache.org/licenses/LICENSE-2.0 +@rem https://www.apache.org/licenses/LICENSE-2.0 @rem @rem Unless required by applicable law or agreed to in writing, software @rem distributed under the License is distributed on an "AS IS" BASIS, @@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" diff --git a/app/actions/actionsTypes.js b/app/actions/actionsTypes.js index 65c39d9c6..3fec00201 100644 --- a/app/actions/actionsTypes.js +++ b/app/actions/actionsTypes.js @@ -33,6 +33,7 @@ export const ROOMS = createRequestTypes('ROOMS', [ 'CLOSE_SEARCH_HEADER' ]); export const ROOM = createRequestTypes('ROOM', ['SUBSCRIBE', 'UNSUBSCRIBE', 'LEAVE', 'DELETE', 'REMOVED', 'CLOSE', 'FORWARD', 'USER_TYPING']); +export const INQUIRY = createRequestTypes('INQUIRY', [...defaultTypes, 'SET_ENABLED', 'RESET', 'QUEUE_ADD', 'QUEUE_UPDATE', 'QUEUE_REMOVE']); export const APP = createRequestTypes('APP', ['START', 'READY', 'INIT', 'INIT_LOCAL_SETTINGS', 'SET_MASTER_DETAIL']); export const MESSAGES = createRequestTypes('MESSAGES', ['REPLY_BROADCAST']); export const CREATE_CHANNEL = createRequestTypes('CREATE_CHANNEL', [...defaultTypes]); diff --git a/app/actions/inquiry.js b/app/actions/inquiry.js new file mode 100644 index 000000000..0f3402119 --- /dev/null +++ b/app/actions/inquiry.js @@ -0,0 +1,55 @@ +import * as types from './actionsTypes'; + +export function inquirySetEnabled(enabled) { + return { + type: types.INQUIRY.SET_ENABLED, + enabled + }; +} + +export function inquiryReset() { + return { + type: types.INQUIRY.RESET + }; +} + +export function inquiryQueueAdd(inquiry) { + return { + type: types.INQUIRY.QUEUE_ADD, + inquiry + }; +} + +export function inquiryQueueUpdate(inquiry) { + return { + type: types.INQUIRY.QUEUE_UPDATE, + inquiry + }; +} + +export function inquiryQueueRemove(inquiryId) { + return { + type: types.INQUIRY.QUEUE_REMOVE, + inquiryId + }; +} + +export function inquiryRequest() { + return { + type: types.INQUIRY.REQUEST + }; +} + +export function inquirySuccess(inquiries) { + return { + type: types.INQUIRY.SUCCESS, + inquiries + }; +} + +export function inquiryFailure(error) { + return { + type: types.INQUIRY.FAILURE, + error + }; +} diff --git a/app/constants/colors.js b/app/constants/colors.js index 0b0a8ae7f..f3ad72dc4 100644 --- a/app/constants/colors.js +++ b/app/constants/colors.js @@ -10,6 +10,16 @@ export const SWITCH_TRACK_COLOR = { true: '#2de0a5' }; +const mentions = { + unreadBackground: '#414852', + mentionMeColor: '#f5455c', + mentionMeBackground: '#ffe9ec', + mentionGroupColor: '#f38c39', + mentionGroupBackground: '#fde8d7', + mentionOtherColor: '#b68d00', + mentionOtherBackground: '#fff6d6' +}; + export const themes = { light: { backgroundColor: '#ffffff', @@ -53,7 +63,8 @@ export const themes = { passcodeDotEmpty: '#CBCED1', passcodeDotFull: '#6C727A', previewBackground: '#1F2329', - previewTintColor: '#ffffff' + previewTintColor: '#ffffff', + ...mentions }, dark: { backgroundColor: '#030b1b', @@ -97,7 +108,8 @@ export const themes = { passcodeDotEmpty: '#CBCED1', passcodeDotFull: '#6C727A', previewBackground: '#030b1b', - previewTintColor: '#ffffff' + previewTintColor: '#ffffff', + ...mentions }, black: { backgroundColor: '#000000', @@ -141,6 +153,7 @@ export const themes = { passcodeDotEmpty: '#CBCED1', passcodeDotFull: '#6C727A', previewBackground: '#000000', - previewTintColor: '#ffffff' + previewTintColor: '#ffffff', + ...mentions } }; diff --git a/app/containers/Avatar.js b/app/containers/Avatar.js index 66bef8411..c4ed0ba7c 100644 --- a/app/containers/Avatar.js +++ b/app/containers/Avatar.js @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { View } from 'react-native'; -import FastImage from 'react-native-fast-image'; +import FastImage from '@rocket.chat/react-native-fast-image'; import Touchable from 'react-native-platform-touchable'; import { settings as RocketChatSettings } from '@rocket.chat/sdk'; diff --git a/app/containers/EmojiPicker/CustomEmoji.js b/app/containers/EmojiPicker/CustomEmoji.js index 381695d05..934155fec 100644 --- a/app/containers/EmojiPicker/CustomEmoji.js +++ b/app/containers/EmojiPicker/CustomEmoji.js @@ -1,5 +1,5 @@ import React from 'react'; -import FastImage from 'react-native-fast-image'; +import FastImage from '@rocket.chat/react-native-fast-image'; import PropTypes from 'prop-types'; const CustomEmoji = React.memo(({ baseUrl, emoji, style }) => ( diff --git a/app/containers/HeaderButton.js b/app/containers/HeaderButton.js index e712a7e1e..cd1808d2f 100644 --- a/app/containers/HeaderButton.js +++ b/app/containers/HeaderButton.js @@ -28,7 +28,7 @@ export const CustomHeaderButtons = React.memo(props => ( export const DrawerButton = React.memo(({ navigation, testID, ...otherProps }) => ( - + )); @@ -36,7 +36,7 @@ export const CloseModalButton = React.memo(({ navigation, testID, onPress = () => navigation.pop(), ...props }) => ( - + )); @@ -44,14 +44,14 @@ export const CancelModalButton = React.memo(({ onPress, testID }) => ( {isIOS ? - : + : } )); export const MoreButton = React.memo(({ onPress, testID }) => ( - + )); diff --git a/app/containers/InAppNotification/NotifierComponent.js b/app/containers/InAppNotification/NotifierComponent.js index 084c2fc0c..be0896c7a 100644 --- a/app/containers/InAppNotification/NotifierComponent.js +++ b/app/containers/InAppNotification/NotifierComponent.js @@ -90,6 +90,8 @@ const NotifierComponent = React.memo(({ if (isMasterDetail) { Navigation.navigate('DrawerNavigator'); + } else { + Navigation.navigate('RoomsListView'); } goRoom({ item, isMasterDetail }); hideNotification(); @@ -125,7 +127,7 @@ const NotifierComponent = React.memo(({ hitSlop={BUTTON_HIT_SLOP} background={Touchable.SelectableBackgroundBorderless()} > - + ); diff --git a/app/containers/InAppNotification/index.js b/app/containers/InAppNotification/index.js index fd0ad6368..dd6573f33 100644 --- a/app/containers/InAppNotification/index.js +++ b/app/containers/InAppNotification/index.js @@ -14,7 +14,7 @@ const InAppNotification = memo(() => { const state = Navigation.navigationRef.current?.getRootState(); const route = getActiveRoute(state); if (payload.rid) { - if (route?.name === 'RoomView' && route.params?.rid === payload.rid) { + if ((route?.name === 'RoomView' && route.params?.rid === payload.rid) || route?.name === 'JitsiMeetView') { return; } Notifier.showNotification({ diff --git a/app/containers/LoginServices.js b/app/containers/LoginServices.js index 11ffc6d97..417e6523a 100644 --- a/app/containers/LoginServices.js +++ b/app/containers/LoginServices.js @@ -15,6 +15,7 @@ import OrSeparator from './OrSeparator'; import Touch from '../utils/touch'; import I18n from '../i18n'; import random from '../utils/random'; +import { logEvent, events } from '../utils/log'; import RocketChat from '../lib/rocketchat'; const BUTTON_HEIGHT = 48; @@ -77,6 +78,7 @@ class LoginServices extends React.PureComponent { } onPressFacebook = () => { + logEvent(events.ENTER_WITH_FACEBOOK); const { services, server } = this.props; const { clientId } = services.facebook; const endpoint = 'https://m.facebook.com/v2.9/dialog/oauth'; @@ -88,6 +90,7 @@ class LoginServices extends React.PureComponent { } onPressGithub = () => { + logEvent(events.ENTER_WITH_GITHUB); const { services, server } = this.props; const { clientId } = services.github; const endpoint = `https://github.com/login?client_id=${ clientId }&return_to=${ encodeURIComponent('/login/oauth/authorize') }`; @@ -99,6 +102,7 @@ class LoginServices extends React.PureComponent { } onPressGitlab = () => { + logEvent(events.ENTER_WITH_GITLAB); const { services, server, Gitlab_URL } = this.props; const { clientId } = services.gitlab; const baseURL = Gitlab_URL ? Gitlab_URL.trim().replace(/\/*$/, '') : 'https://gitlab.com'; @@ -111,6 +115,7 @@ class LoginServices extends React.PureComponent { } onPressGoogle = () => { + logEvent(events.ENTER_WITH_GOOGLE); const { services, server } = this.props; const { clientId } = services.google; const endpoint = 'https://accounts.google.com/o/oauth2/auth'; @@ -122,6 +127,7 @@ class LoginServices extends React.PureComponent { } onPressLinkedin = () => { + logEvent(events.ENTER_WITH_LINKEDIN); const { services, server } = this.props; const { clientId } = services.linkedin; const endpoint = 'https://www.linkedin.com/oauth/v2/authorization'; @@ -133,6 +139,7 @@ class LoginServices extends React.PureComponent { } onPressMeteor = () => { + logEvent(events.ENTER_WITH_METEOR); const { services, server } = this.props; const { clientId } = services['meteor-developer']; const endpoint = 'https://www.meteor.com/oauth2/authorize'; @@ -143,6 +150,7 @@ class LoginServices extends React.PureComponent { } onPressTwitter = () => { + logEvent(events.ENTER_WITH_TWITTER); const { server } = this.props; const state = this.getOAuthState(); const url = `${ server }/_oauth/twitter/?requestTokenAndRedirect=true&state=${ state }`; @@ -150,6 +158,7 @@ class LoginServices extends React.PureComponent { } onPressWordpress = () => { + logEvent(events.ENTER_WITH_WORDPRESS); const { services, server } = this.props; const { clientId, serverURL } = services.wordpress; const endpoint = `${ serverURL }/oauth/authorize`; @@ -161,6 +170,7 @@ class LoginServices extends React.PureComponent { } onPressCustomOAuth = (loginService) => { + logEvent(events.ENTER_WITH_CUSTOM_OAUTH); const { server } = this.props; const { serverURL, authorizePath, clientId, scope, service @@ -175,6 +185,7 @@ class LoginServices extends React.PureComponent { } onPressSaml = (loginService) => { + logEvent(events.ENTER_WITH_SAML); const { server } = this.props; const { clientConfig } = loginService; const { provider } = clientConfig; @@ -184,6 +195,7 @@ class LoginServices extends React.PureComponent { } onPressCas = () => { + logEvent(events.ENTER_WITH_CAS); const { server, CAS_login_url } = this.props; const ssoToken = random(17); const url = `${ CAS_login_url }?service=${ server }/_cas/${ ssoToken }`; @@ -191,6 +203,7 @@ class LoginServices extends React.PureComponent { } onPressAppleLogin = async() => { + logEvent(events.ENTER_WITH_APPLE); try { const { fullName, email, identityToken } = await AppleAuthentication.signInAsync({ requestedScopes: [ @@ -201,7 +214,7 @@ class LoginServices extends React.PureComponent { await RocketChat.loginOAuthOrSso({ fullName, email, identityToken }); } catch { - // Do nothing + logEvent(events.ENTER_WITH_APPLE_F); } } diff --git a/app/containers/MessageActions/Header.js b/app/containers/MessageActions/Header.js index 7847069e1..b7d981d7e 100644 --- a/app/containers/MessageActions/Header.js +++ b/app/containers/MessageActions/Header.js @@ -78,7 +78,7 @@ const HeaderFooter = React.memo(({ onReaction, theme }) => ( style={[styles.headerItem, { backgroundColor: themes[theme].auxiliaryBackground }]} theme={theme} > - + )); HeaderFooter.propTypes = { diff --git a/app/containers/MessageActions/index.js b/app/containers/MessageActions/index.js index 7846e1d70..ff4c4dbf2 100644 --- a/app/containers/MessageActions/index.js +++ b/app/containers/MessageActions/index.js @@ -7,7 +7,7 @@ import moment from 'moment'; import RocketChat from '../../lib/rocketchat'; import database from '../../lib/database'; import I18n from '../../i18n'; -import log from '../../utils/log'; +import log, { logEvent } from '../../utils/log'; import Navigation from '../../lib/Navigation'; import { getMessageTranslation } from '../message/utils'; import { LISTENER } from '../Toast'; @@ -15,6 +15,7 @@ import EventEmitter from '../../utils/events'; import { showConfirmationAlert } from '../../utils/info'; import { useActionSheet } from '../ActionSheet'; import Header, { HEADER_HEIGHT } from './Header'; +import events from '../../utils/log/events'; const MessageActions = React.memo(forwardRef(({ room, @@ -112,11 +113,18 @@ const MessageActions = React.memo(forwardRef(({ const getPermalink = message => RocketChat.getPermalinkMessage(message); - const handleReply = message => replyInit(message, true); + const handleReply = (message) => { + logEvent(events.ROOM_MSG_ACTION_REPLY); + replyInit(message, true); + }; - const handleEdit = message => editInit(message); + const handleEdit = (message) => { + logEvent(events.ROOM_MSG_ACTION_EDIT); + editInit(message); + }; const handleCreateDiscussion = (message) => { + logEvent(events.ROOM_MSG_ACTION_DISCUSSION); const params = { message, channel: room, showCloseModal: true }; if (isMasterDetail) { Navigation.navigate('ModalStackNavigator', { screen: 'CreateDiscussionView', params }); @@ -126,6 +134,7 @@ const MessageActions = React.memo(forwardRef(({ }; const handleUnread = async(message) => { + logEvent(events.ROOM_MSG_ACTION_UNREAD); const { id: messageId, ts } = message; const { rid } = room; try { @@ -144,54 +153,66 @@ const MessageActions = React.memo(forwardRef(({ Navigation.navigate('RoomsListView'); } } catch (e) { + logEvent(events.ROOM_MSG_ACTION_UNREAD_F); log(e); } }; const handlePermalink = async(message) => { + logEvent(events.ROOM_MSG_ACTION_PERMALINK); try { const permalink = await getPermalink(message); Clipboard.setString(permalink); EventEmitter.emit(LISTENER, { message: I18n.t('Permalink_copied_to_clipboard') }); } catch { - // Do nothing + logEvent(events.ROOM_MSG_ACTION_PERMALINK_F); } }; const handleCopy = async(message) => { + logEvent(events.ROOM_MSG_ACTION_COPY); await Clipboard.setString(message.msg); EventEmitter.emit(LISTENER, { message: I18n.t('Copied_to_clipboard') }); }; const handleShare = async(message) => { + logEvent(events.ROOM_MSG_ACTION_SHARE); try { const permalink = await getPermalink(message); Share.share({ message: permalink }); } catch { - // Do nothing + logEvent(events.ROOM_MSG_ACTION_SHARE_F); } }; - const handleQuote = message => replyInit(message, false); + const handleQuote = (message) => { + logEvent(events.ROOM_MSG_ACTION_QUOTE); + replyInit(message, false); + }; const handleStar = async(message) => { + logEvent(message.starred ? events.ROOM_MSG_ACTION_UNSTAR : events.ROOM_MSG_ACTION_STAR); try { await RocketChat.toggleStarMessage(message.id, message.starred); EventEmitter.emit(LISTENER, { message: message.starred ? I18n.t('Message_unstarred') : I18n.t('Message_starred') }); } catch (e) { + logEvent(events.ROOM_MSG_ACTION_STAR_F); log(e); } }; const handlePin = async(message) => { + logEvent(events.ROOM_MSG_ACTION_PIN); try { await RocketChat.togglePinMessage(message.id, message.pinned); } catch (e) { + logEvent(events.ROOM_MSG_ACTION_PIN_F); log(e); } }; const handleReaction = (shortname, message) => { + logEvent(events.ROOM_MSG_ACTION_REACTION); if (shortname) { onReactionPress(shortname, message.id); } else { @@ -201,7 +222,13 @@ const MessageActions = React.memo(forwardRef(({ hideActionSheet(); }; - const handleReadReceipt = message => Navigation.navigate('ReadReceiptsView', { messageId: message.id }); + const handleReadReceipt = (message) => { + if (isMasterDetail) { + Navigation.navigate('ModalStackNavigator', { screen: 'ReadReceiptsView', params: { messageId: message.id } }); + } else { + Navigation.navigate('ReadReceiptsView', { messageId: message.id }); + } + }; const handleToggleTranslation = async(message) => { try { @@ -228,10 +255,12 @@ const MessageActions = React.memo(forwardRef(({ }; const handleReport = async(message) => { + logEvent(events.ROOM_MSG_ACTION_REPORT); try { await RocketChat.reportMessage(message.id); Alert.alert(I18n.t('Message_Reported')); } catch (e) { + logEvent(events.ROOM_MSG_ACTION_REPORT_F); log(e); } }; @@ -242,8 +271,10 @@ const MessageActions = React.memo(forwardRef(({ callToAction: I18n.t('Delete'), onPress: async() => { try { + logEvent(events.ROOM_MSG_ACTION_DELETE); await RocketChat.deleteMessage(message.id, message.subscription.id); } catch (e) { + logEvent(events.ROOM_MSG_ACTION_DELETE_F); log(e); } } @@ -290,7 +321,7 @@ const MessageActions = React.memo(forwardRef(({ // Create Discussion options.push({ title: I18n.t('Start_a_Discussion'), - icon: 'chat', + icon: 'discussions', onPress: () => handleCreateDiscussion(message) }); @@ -365,7 +396,7 @@ const MessageActions = React.memo(forwardRef(({ if (allowDelete(message)) { options.push({ title: I18n.t('Delete'), - icon: 'trash', + icon: 'delete', danger: true, onPress: () => handleDelete(message) }); @@ -375,6 +406,7 @@ const MessageActions = React.memo(forwardRef(({ }; const showMessageActions = async(message) => { + logEvent(events.ROOM_SHOW_MSG_ACTIONS); await getPermissions(); showActionSheet({ options: getOptions(message), diff --git a/app/containers/MessageBox/CommandsPreview/Item.js b/app/containers/MessageBox/CommandsPreview/Item.js index 2909f57ee..9fa026dd5 100644 --- a/app/containers/MessageBox/CommandsPreview/Item.js +++ b/app/containers/MessageBox/CommandsPreview/Item.js @@ -1,7 +1,7 @@ import React, { useContext, useState } from 'react'; import PropTypes from 'prop-types'; import { TouchableOpacity } from 'react-native'; -import FastImage from 'react-native-fast-image'; +import FastImage from '@rocket.chat/react-native-fast-image'; import styles from '../styles'; import { CustomIcon } from '../../../lib/Icons'; @@ -32,7 +32,7 @@ const Item = ({ item, theme }) => { { loading ? : null } ) - : + : } ); diff --git a/app/containers/MessageBox/RecordAudio.js b/app/containers/MessageBox/RecordAudio.js index b9e94988c..5d277023b 100644 --- a/app/containers/MessageBox/RecordAudio.js +++ b/app/containers/MessageBox/RecordAudio.js @@ -10,6 +10,7 @@ import styles from './styles'; import I18n from '../../i18n'; import { themes } from '../../constants/colors'; import { CustomIcon } from '../../lib/Icons'; +import { logEvent, events } from '../../utils/log'; const RECORDING_EXTENSION = '.aac'; const RECORDING_SETTINGS = { @@ -103,6 +104,7 @@ export default class RecordAudio extends React.PureComponent { } startRecordingAudio = async() => { + logEvent(events.ROOM_AUDIO_RECORD); if (!this.isRecorderBusy) { this.isRecorderBusy = true; try { @@ -120,13 +122,14 @@ export default class RecordAudio extends React.PureComponent { await Audio.requestPermissionsAsync(); } } catch (error) { - // Do nothing + logEvent(events.ROOM_AUDIO_RECORD_F); } this.isRecorderBusy = false; } }; finishRecordingAudio = async() => { + logEvent(events.ROOM_AUDIO_FINISH); if (!this.isRecorderBusy) { const { onFinish } = this.props; @@ -147,7 +150,7 @@ export default class RecordAudio extends React.PureComponent { onFinish(fileInfo); } catch (error) { - // Do nothing + logEvent(events.ROOM_AUDIO_FINISH_F); } this.setState({ isRecording: false, recordingDurationMillis: 0 }); deactivateKeepAwake(); @@ -156,12 +159,13 @@ export default class RecordAudio extends React.PureComponent { }; cancelRecordingAudio = async() => { + logEvent(events.ROOM_AUDIO_CANCEL); if (!this.isRecorderBusy) { this.isRecorderBusy = true; try { await this.recording.stopAndUnloadAsync(); } catch (error) { - // Do nothing + logEvent(events.ROOM_AUDIO_CANCEL_F); } this.setState({ isRecording: false, recordingDurationMillis: 0 }); deactivateKeepAwake(); @@ -182,7 +186,7 @@ export default class RecordAudio extends React.PureComponent { accessibilityLabel={I18n.t('Send_audio_message')} accessibilityTraits='button' > - + ); } @@ -199,7 +203,7 @@ export default class RecordAudio extends React.PureComponent { - + ); }, (prevProps, nextProps) => prevProps.replying === nextProps.replying && prevProps.theme === nextProps.theme && isEqual(prevProps.message, nextProps.message)); diff --git a/app/containers/MessageBox/buttons/ActionsButton.js b/app/containers/MessageBox/buttons/ActionsButton.js index ddfdb94e6..5738e71ba 100644 --- a/app/containers/MessageBox/buttons/ActionsButton.js +++ b/app/containers/MessageBox/buttons/ActionsButton.js @@ -8,7 +8,7 @@ const ActionsButton = React.memo(({ theme, onPress }) => ( onPress={onPress} testID='messagebox-actions' accessibilityLabel='Message_actions' - icon='plus' + icon='add' theme={theme} /> )); diff --git a/app/containers/MessageBox/buttons/CancelEditingButton.js b/app/containers/MessageBox/buttons/CancelEditingButton.js index 04f1db9d8..1a6e69bb1 100644 --- a/app/containers/MessageBox/buttons/CancelEditingButton.js +++ b/app/containers/MessageBox/buttons/CancelEditingButton.js @@ -8,7 +8,7 @@ const CancelEditingButton = React.memo(({ theme, onPress }) => ( onPress={onPress} testID='messagebox-cancel-editing' accessibilityLabel='Cancel_editing' - icon='Cross' + icon='close' theme={theme} /> )); diff --git a/app/containers/MessageBox/buttons/SendButton.js b/app/containers/MessageBox/buttons/SendButton.js index ef7896dae..4419a316d 100644 --- a/app/containers/MessageBox/buttons/SendButton.js +++ b/app/containers/MessageBox/buttons/SendButton.js @@ -8,7 +8,7 @@ const SendButton = React.memo(({ theme, onPress }) => ( onPress={onPress} testID='messagebox-send-message' accessibilityLabel='Send_message' - icon='send-active' + icon='send-filled' theme={theme} /> )); diff --git a/app/containers/MessageBox/index.js b/app/containers/MessageBox/index.js index 813d7d64c..cf1396240 100644 --- a/app/containers/MessageBox/index.js +++ b/app/containers/MessageBox/index.js @@ -17,8 +17,8 @@ import RocketChat from '../../lib/rocketchat'; import styles from './styles'; import database from '../../lib/database'; import { emojis } from '../../emojis'; +import log, { logEvent, events } from '../../utils/log'; import RecordAudio from './RecordAudio'; -import log from '../../utils/log'; import I18n from '../../i18n'; import ReplyPreview from './ReplyPreview'; import debounce from '../../utils/debounce'; @@ -122,6 +122,7 @@ class MessageBox extends Component { command: {} }; this.text = ''; + this.selection = { start: 0, end: 0 }; this.focused = false; // MessageBox Actions @@ -133,7 +134,7 @@ class MessageBox extends Component { }, { title: I18n.t('Take_a_video'), - icon: 'video-1', + icon: 'camera', onPress: this.takeVideo }, { @@ -143,12 +144,12 @@ class MessageBox extends Component { }, { title: I18n.t('Choose_file'), - icon: 'folder', + icon: 'attach', onPress: this.chooseFile }, { title: I18n.t('Create_Discussion'), - icon: 'chat', + icon: 'discussions', onPress: this.createDiscussion } ]; @@ -331,6 +332,10 @@ class MessageBox extends Component { this.setInput(text); } + onSelectionChange = (e) => { + this.selection = e.nativeEvent.selection; + } + // eslint-disable-next-line react/sort-comp debouncedOnChangeText = debounce(async(text) => { const { sharing } = this.props; @@ -358,9 +363,9 @@ class MessageBox extends Component { if (!isTextEmpty) { try { - const { start, end } = this.component?.lastNativeSelection; + const { start, end } = this.selection; const cursor = Math.max(start, end); - const lastNativeText = this.component?.lastNativeText || ''; + const lastNativeText = this.text; // matches if text either starts with '/' or have (@,#,:) then it groups whatever comes next of mention type let regexp = /(#|@|:|^\/)([a-z0-9._-]+)$/im; @@ -399,7 +404,7 @@ class MessageBox extends Component { } const { trackingType } = this.state; const msg = this.text; - const { start, end } = this.component?.lastNativeSelection; + const { start, end } = this.selection; const cursor = Math.max(start, end); const regexp = /([a-z0-9._-]+)$/im; const result = msg.substr(0, cursor).replace(regexp, ''); @@ -410,7 +415,8 @@ class MessageBox extends Component { if ((trackingType === MENTIONS_TRACKING_TYPE_COMMANDS) && item.providesPreview) { this.setState({ showCommandPreview: true }); } - this.setInput(text); + const newCursor = cursor + mentionName.length; + this.setInput(text, { start: newCursor, end: newCursor }); this.focus(); requestAnimationFrame(() => this.stopTrackingMention()); } @@ -443,15 +449,11 @@ class MessageBox extends Component { let newText = ''; // if messagebox has an active cursor - if (this.component?.lastNativeSelection) { - const { start, end } = this.component.lastNativeSelection; - const cursor = Math.max(start, end); - newText = `${ text.substr(0, cursor) }${ emoji }${ text.substr(cursor) }`; - } else { - // if messagebox doesn't have a cursor, just append selected emoji - newText = `${ text }${ emoji }`; - } - this.setInput(newText); + const { start, end } = this.selection; + const cursor = Math.max(start, end); + newText = `${ text.substr(0, cursor) }${ emoji }${ text.substr(cursor) }`; + const newCursor = cursor + emoji.length; + this.setInput(newText, { start: newCursor, end: newCursor }); this.setShowSend(true); } @@ -551,11 +553,12 @@ class MessageBox extends Component { this.setState({ commandPreview: [], showCommandPreview: true, command: {} }); } - setInput = (text) => { + setInput = (text, selection) => { this.text = text; - if (this.component && this.component.setNativeProps) { - this.component.setNativeProps({ text }); + if (selection) { + return this.component.setTextAndSelection(text, selection); } + this.component.setNativeProps({ text }); } setShowSend = (showSend) => { @@ -582,37 +585,41 @@ class MessageBox extends Component { } takePhoto = async() => { + logEvent(events.ROOM_BOX_ACTION_PHOTO); try { const image = await ImagePicker.openCamera(this.imagePickerConfig); if (this.canUploadFile(image)) { this.openShareView([image]); } } catch (e) { - // Do nothing + logEvent(events.ROOM_BOX_ACTION_PHOTO_F); } } takeVideo = async() => { + logEvent(events.ROOM_BOX_ACTION_VIDEO); try { const video = await ImagePicker.openCamera(this.videoPickerConfig); if (this.canUploadFile(video)) { this.openShareView([video]); } } catch (e) { - // Do nothing + logEvent(events.ROOM_BOX_ACTION_VIDEO_F); } } chooseFromLibrary = async() => { + logEvent(events.ROOM_BOX_ACTION_LIBRARY); try { const attachments = await ImagePicker.openPicker(this.libraryPickerConfig); this.openShareView(attachments); } catch (e) { - // Do nothing + logEvent(events.ROOM_BOX_ACTION_LIBRARY_F); } } chooseFile = async() => { + logEvent(events.ROOM_BOX_ACTION_FILE); try { const res = await DocumentPicker.pick({ type: [DocumentPicker.types.allFiles] @@ -628,6 +635,7 @@ class MessageBox extends Component { } } catch (e) { if (!DocumentPicker.isCancel(e)) { + logEvent(events.ROOM_BOX_ACTION_FILE_F); log(e); } } @@ -645,6 +653,7 @@ class MessageBox extends Component { } createDiscussion = () => { + logEvent(events.ROOM_BOX_ACTION_DISCUSSION); const { isMasterDetail } = this.props; const params = { channel: this.room, showCloseModal: true }; if (isMasterDetail) { @@ -655,6 +664,7 @@ class MessageBox extends Component { } showMessageBoxActions = () => { + logEvent(events.ROOM_SHOW_BOX_ACTIONS); const { showActionSheet } = this.props; showActionSheet({ options: this.options }); } @@ -665,10 +675,9 @@ class MessageBox extends Component { this.clearInput(); } - openEmoji = async() => { - await this.setState({ - showEmojiKeyboard: true - }); + openEmoji = () => { + logEvent(events.ROOM_OPEN_EMOJI); + this.setState({ showEmojiKeyboard: true }); } recordingCallback = (recording) => { @@ -729,6 +738,7 @@ class MessageBox extends Component { Q.where('id', Q.like(`${ Q.sanitizeLikeString(command) }%`)) ).fetch(); if (slashCommand.length > 0) { + logEvent(events.COMMAND_RUN); try { const messageWithoutCommand = message.replace(/([^\s]+)/, '').trim(); const [{ appId }] = slashCommand; @@ -736,6 +746,7 @@ class MessageBox extends Component { RocketChat.runSlashCommand(command, roomId, messageWithoutCommand, triggerId, tmid || messageTmid); replyCancel(); } catch (e) { + logEvent(events.COMMAND_RUN_F); log(e); } this.clearInput(); @@ -888,6 +899,7 @@ class MessageBox extends Component { blurOnSubmit={false} placeholder={I18n.t('New_Message')} onChangeText={this.onChangeText} + onSelectionChange={this.onSelectionChange} underlineColorAndroid='transparent' defaultValue='' multiline diff --git a/app/containers/MessageErrorActions.js b/app/containers/MessageErrorActions.js index bc7b6bc05..c9975b0e3 100644 --- a/app/containers/MessageErrorActions.js +++ b/app/containers/MessageErrorActions.js @@ -81,7 +81,7 @@ const MessageErrorActions = forwardRef(({ tmid }, ref) => { }, { title: I18n.t('Delete'), - icon: 'trash', + icon: 'delete', danger: true, onPress: () => handleDelete(message) } diff --git a/app/containers/Passcode/Base/LockIcon.js b/app/containers/Passcode/Base/LockIcon.js index 023a355c7..133485cba 100644 --- a/app/containers/Passcode/Base/LockIcon.js +++ b/app/containers/Passcode/Base/LockIcon.js @@ -10,7 +10,7 @@ import { CustomIcon } from '../../../lib/Icons'; const LockIcon = React.memo(({ theme }) => ( - + )); diff --git a/app/containers/ReactionsModal.js b/app/containers/ReactionsModal.js index 97812d0e7..68e95a33f 100644 --- a/app/containers/ReactionsModal.js +++ b/app/containers/ReactionsModal.js @@ -104,7 +104,7 @@ const ModalContent = React.memo(({ {I18n.t('Reactions')} diff --git a/app/containers/RoomTypeIcon.js b/app/containers/RoomTypeIcon.js index 42b8b90b9..77b70c0a9 100644 --- a/app/containers/RoomTypeIcon.js +++ b/app/containers/RoomTypeIcon.js @@ -20,19 +20,19 @@ const RoomTypeIcon = React.memo(({ const color = themes[theme].auxiliaryText; - let icon = 'lock'; + let icon = 'channel-private'; if (type === 'discussion') { - icon = 'chat'; + icon = 'discussions'; } else if (type === 'c') { - icon = 'hash'; + icon = 'channel-public'; } else if (type === 'd') { if (isGroupChat) { icon = 'team'; } else { - icon = 'at'; + icon = 'mention'; } } else if (type === 'l') { - icon = 'livechat'; + icon = 'omnichannel'; } return ( diff --git a/app/containers/SearchBox.js b/app/containers/SearchBox.js index 89c51def1..75ed7f080 100644 --- a/app/containers/SearchBox.js +++ b/app/containers/SearchBox.js @@ -61,7 +61,7 @@ const SearchBox = ({ ]} > - + { InteractionManager.runAfterInteractions(() => e?.getNativeRef()?.focus())} returnKeyType='send' autoCapitalize='none' onChangeText={setCode} diff --git a/app/containers/TwoFactor/styles.js b/app/containers/TwoFactor/styles.js index 36608408a..1c5c789cb 100644 --- a/app/containers/TwoFactor/styles.js +++ b/app/containers/TwoFactor/styles.js @@ -14,9 +14,10 @@ export default StyleSheet.create({ borderRadius: 4 }, title: { - fontSize: 14, + fontSize: 16, paddingBottom: 8, - ...sharedStyles.textBold + ...sharedStyles.textBold, + ...sharedStyles.textAlignCenter }, subtitle: { fontSize: 14, diff --git a/app/containers/UIKit/Image.js b/app/containers/UIKit/Image.js index b21805e3d..dd7eaa944 100644 --- a/app/containers/UIKit/Image.js +++ b/app/containers/UIKit/Image.js @@ -1,6 +1,6 @@ import React from 'react'; import { View, StyleSheet } from 'react-native'; -import FastImage from 'react-native-fast-image'; +import FastImage from '@rocket.chat/react-native-fast-image'; import PropTypes from 'prop-types'; import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit'; diff --git a/app/containers/UIKit/MultiSelect/Chips.js b/app/containers/UIKit/MultiSelect/Chips.js index 9d0eb0a20..47827141d 100644 --- a/app/containers/UIKit/MultiSelect/Chips.js +++ b/app/containers/UIKit/MultiSelect/Chips.js @@ -2,7 +2,7 @@ import React from 'react'; import { Text, View } from 'react-native'; import PropTypes from 'prop-types'; import Touchable from 'react-native-platform-touchable'; -import FastImage from 'react-native-fast-image'; +import FastImage from '@rocket.chat/react-native-fast-image'; import { themes } from '../../../constants/colors'; import { textParser } from '../utils'; @@ -24,7 +24,7 @@ const Chip = ({ <> {item.imageUrl ? : null} {textParser([item.text])} - + ); diff --git a/app/containers/UIKit/MultiSelect/Items.js b/app/containers/UIKit/MultiSelect/Items.js index 7a460ac47..4418600f5 100644 --- a/app/containers/UIKit/MultiSelect/Items.js +++ b/app/containers/UIKit/MultiSelect/Items.js @@ -2,7 +2,7 @@ import React from 'react'; import { Text, FlatList } from 'react-native'; import PropTypes from 'prop-types'; import Touchable from 'react-native-platform-touchable'; -import FastImage from 'react-native-fast-image'; +import FastImage from '@rocket.chat/react-native-fast-image'; import Separator from '../../Separator'; import Check from '../../Check'; diff --git a/app/containers/UIKit/Overflow.js b/app/containers/UIKit/Overflow.js index 6d76f6f3f..5acc4e9fe 100644 --- a/app/containers/UIKit/Overflow.js +++ b/app/containers/UIKit/Overflow.js @@ -82,7 +82,7 @@ export const Overflow = ({ hitSlop={BUTTON_HIT_SLOP} style={styles.menu} > - {!loading ? : } + {!loading ? : } { - let mentionStyle = { ...styles.mention, color: themes[theme].buttonText }; if (mention === 'all' || mention === 'here') { - return {mention}; + return ( + {mention} + + ); } + let mentionStyle = {}; if (mention === username) { mentionStyle = { - ...mentionStyle, - backgroundColor: themes[theme].actionTintColor + color: themes[theme].mentionMeColor, + backgroundColor: themes[theme].mentionMeBackground }; } else { mentionStyle = { - ...mentionStyle, - color: themes[theme].actionTintColor + color: themes[theme].mentionOtherColor, + backgroundColor: themes[theme].mentionOtherBackground }; } - const user = mentions && mentions.length && mentions.find(m => m.username === mention); + const user = mentions?.find?.(m => m && m.username === mention); const handlePress = () => { + logEvent(events.ROOM_MENTION_GO_USER_INFO); const navParam = { t: 'd', rid: user && user._id @@ -39,7 +53,7 @@ const AtMention = React.memo(({ if (user) { return ( {useRealName && user.name ? user.name : user.username} diff --git a/app/containers/markdown/Hashtag.js b/app/containers/markdown/Hashtag.js index 655d3a737..cccb1fb27 100644 --- a/app/containers/markdown/Hashtag.js +++ b/app/containers/markdown/Hashtag.js @@ -21,10 +21,16 @@ const Hashtag = React.memo(({ if (channels && channels.length && channels.findIndex(channel => channel.name === hashtag) !== -1) { return ( - {hashtag} + {`#${ hashtag }`} ); } diff --git a/app/containers/markdown/index.js b/app/containers/markdown/index.js index 4da997194..99fb38424 100644 --- a/app/containers/markdown/index.js +++ b/app/containers/markdown/index.js @@ -383,9 +383,9 @@ class Markdown extends PureComponent { m = m.replace(/^\[([\s]]*)\]\(([^)]*)\)\s/, '').trim(); if (preview) { - m = m.replace(/\n+/g, ' '); m = shortnameToUnicode(m); m = removeMarkdown(m); + m = m.replace(/\n+/g, ' '); return ( {m} diff --git a/app/containers/markdown/styles.js b/app/containers/markdown/styles.js index c60c77c9d..d005f90f1 100644 --- a/app/containers/markdown/styles.js +++ b/app/containers/markdown/styles.js @@ -54,13 +54,9 @@ export default StyleSheet.create({ temp: { opacity: 0.3 }, mention: { fontSize: 16, - color: '#0072FE', padding: 5, ...sharedStyles.textMedium, - backgroundColor: '#E8F2FF' - }, - mentionAll: { - backgroundColor: '#FF5B5A' + letterSpacing: 0.5 }, paragraph: { marginTop: 0, diff --git a/app/containers/message/Audio.js b/app/containers/message/Audio.js index 74410fa3f..fad195890 100644 --- a/app/containers/message/Audio.js +++ b/app/containers/message/Audio.js @@ -79,7 +79,7 @@ const Button = React.memo(({ { loading ? - : + : } )); diff --git a/app/containers/message/Broadcast.js b/app/containers/message/Broadcast.js index d4ebe1264..58de1d0dc 100644 --- a/app/containers/message/Broadcast.js +++ b/app/containers/message/Broadcast.js @@ -26,7 +26,7 @@ const Broadcast = React.memo(({ testID='message-broadcast-reply' > <> - + {I18n.t('Reply')} diff --git a/app/containers/message/CallButton.js b/app/containers/message/CallButton.js index 2a68237e0..83dcd370d 100644 --- a/app/containers/message/CallButton.js +++ b/app/containers/message/CallButton.js @@ -22,7 +22,7 @@ const CallButton = React.memo(({ hitSlop={BUTTON_HIT_SLOP} > <> - + {I18n.t('Click_to_join')} diff --git a/app/containers/message/Discussion.js b/app/containers/message/Discussion.js index 4cdc81abf..c45906c97 100644 --- a/app/containers/message/Discussion.js +++ b/app/containers/message/Discussion.js @@ -29,7 +29,7 @@ const Discussion = React.memo(({ hitSlop={BUTTON_HIT_SLOP} > <> - + {buttonText} diff --git a/app/containers/message/Image.js b/app/containers/message/Image.js index 499e793a7..1471b449e 100644 --- a/app/containers/message/Image.js +++ b/app/containers/message/Image.js @@ -1,7 +1,7 @@ import React, { useContext } from 'react'; import { View } from 'react-native'; import PropTypes from 'prop-types'; -import FastImage from 'react-native-fast-image'; +import FastImage from '@rocket.chat/react-native-fast-image'; import equal from 'deep-equal'; import { createImageProgress } from 'react-native-image-progress'; import * as Progress from 'react-native-progress'; diff --git a/app/containers/message/Reactions.js b/app/containers/message/Reactions.js index 6ff654221..7502057f6 100644 --- a/app/containers/message/Reactions.js +++ b/app/containers/message/Reactions.js @@ -23,7 +23,7 @@ const AddReaction = React.memo(({ theme }) => { hitSlop={BUTTON_HIT_SLOP} > - + ); diff --git a/app/containers/message/Urls.js b/app/containers/message/Urls.js index b5e43bf6d..946433d43 100644 --- a/app/containers/message/Urls.js +++ b/app/containers/message/Urls.js @@ -3,7 +3,7 @@ import { View, Text, StyleSheet, Clipboard } from 'react-native'; import PropTypes from 'prop-types'; -import FastImage from 'react-native-fast-image'; +import FastImage from '@rocket.chat/react-native-fast-image'; import isEqual from 'lodash/isEqual'; import Touchable from './Touchable'; diff --git a/app/containers/message/Video.js b/app/containers/message/Video.js index 3998f2fa0..2e9ef6c2a 100644 --- a/app/containers/message/Video.js +++ b/app/containers/message/Video.js @@ -49,7 +49,7 @@ const Video = React.memo(({ background={Touchable.Ripple(themes[theme].bannerBackground)} > diff --git a/app/i18n/locales/en.js b/app/i18n/locales/en.js index e6038732e..72ebbdb4e 100644 --- a/app/i18n/locales/en.js +++ b/app/i18n/locales/en.js @@ -483,6 +483,7 @@ export default { Tags: 'Tags', Take_a_photo: 'Take a photo', Take_a_video: 'Take a video', + Take_it: 'Take it!', tap_to_change_status: 'tap to change status', Tap_to_view_servers_list: 'Tap to view servers list', Terms_of_Service: ' Terms of Service ', @@ -621,5 +622,7 @@ export default { Passcode_app_locked_title: 'App locked', Passcode_app_locked_subtitle: 'Try again in {{timeLeft}} seconds', After_seconds_set_by_admin: 'After {{seconds}} seconds (set by admin)', - Dont_activate: 'Don\'t activate now' + Dont_activate: 'Don\'t activate now', + Queued_chats: 'Queued chats', + Queue_is_empty: 'Queue is empty' }; diff --git a/app/i18n/locales/pt-BR.js b/app/i18n/locales/pt-BR.js index 5e1d2342b..8ed4e76da 100644 --- a/app/i18n/locales/pt-BR.js +++ b/app/i18n/locales/pt-BR.js @@ -108,8 +108,10 @@ export default { are_typing: 'estão digitando', Are_you_sure_question_mark: 'Você tem certeza?', Are_you_sure_you_want_to_leave_the_room: 'Tem certeza de que deseja sair da sala {{room}}?', + Audio: 'Áudio', Authenticating: 'Autenticando', Automatic: 'Automático', + Auto_Translate: 'Tradução automática', Avatar_changed_successfully: 'Avatar alterado com sucesso!', Avatar_Url: 'Avatar URL', Away: 'Ausente', @@ -172,6 +174,7 @@ export default { DELETE: 'EXCLUIR', deleting_room: 'excluindo sala', Direct_Messages: 'Mensagens Diretas', + DESKTOP_OPTIONS: 'OPÇÕES DE ÁREA DE TRABALHO', Directory: 'Diretório', description: 'descrição', Description: 'Descrição', @@ -192,6 +195,7 @@ export default { Email: 'Email', email: 'e-mail', Empty_title: 'Título vazio', + Enable_Auto_Translate: 'Ativar a tradução automática', Enable_notifications: 'Habilitar notificações', Everyone_can_access_this_channel: 'Todos podem acessar este canal', Error_uploading: 'Erro subindo', @@ -234,6 +238,7 @@ export default { Message_HideType_room_unarchived: 'Sala desarquivada', IP: 'IP', In_app: 'No app', + In_App_and_Desktop_Alert_info: 'Exibe um banner na parte superior da tela quando o aplicativo é aberto e exibe uma notificação na área de trabalho', Invisible: 'Invisível', Invite: 'Convidar', is_typing: 'está digitando', @@ -299,6 +304,9 @@ export default { Nothing_to_save: 'Nada para salvar!', Notify_active_in_this_room: 'Notificar usuários ativos nesta sala', Notify_all_in_this_room: 'Notificar todos nesta sala', + Notifications: 'Notificações', + Notification_Duration: 'Duração da notificação', + Notification_Preferences: 'Preferências de notificação', Not_RC_Server: 'Este não é um servidor Rocket.Chat.\n{{contact}}', No_available_agents_to_transfer: 'Nenhum agente disponível para transferência', Offline: 'Offline', @@ -340,6 +348,7 @@ export default { Profile: 'Perfil', Public_Channel: 'Canal Público', Public: 'Público', + Push_Notifications_Alert_Info: 'Essas notificações são entregues a você quando o aplicativo não está aberto', Quote: 'Citar', Reactions_are_disabled: 'Reagir está desabilitado', Reactions_are_enabled: 'Reagir está habilitado', @@ -348,6 +357,8 @@ export default { Read_External_Permission: 'Permissão de acesso à arquivos', Read_Only_Channel: 'Canal Somente Leitura', Read_Only: 'Somente Leitura', + Receive_Group_Mentions: 'Receber menções de grupo', + Receive_Group_Mentions_Info: 'Receber menções @all e @here', Register: 'Registrar', Read_Receipt: 'Lida por', Repeat_Password: 'Repetir Senha', @@ -355,6 +366,8 @@ export default { replies: 'respostas', reply: 'resposta', Reply: 'Responder', + Receive_Notification: 'Receber Notificação', + Receive_notifications_from: 'Receber notificação de {{name}}', Resend: 'Reenviar', Reset_password: 'Resetar senha', resetting_password: 'redefinindo senha', @@ -411,10 +424,13 @@ export default { Share: 'Compartilhar', Share_Link: 'Share Link', Show_more: 'Mostrar mais..', + Show_Unread_Counter: 'Mostrar contador não lido', + Show_Unread_Counter_Info: 'O contador não lido é exibido como um emblema à direita do canal, na lista', Sign_in_your_server: 'Entrar no seu servidor', Sign_Up: 'Registrar', Some_field_is_invalid_or_empty: 'Algum campo está inválido ou vazio', Sorting_by: 'Ordenando por {{key}}', + Sound: 'Som da notificação', Star_room: 'Favoritar sala', Star: 'Favorito', Starred_Messages: 'Mensagens Favoritas', @@ -551,5 +567,7 @@ export default { Passcode_app_locked_title: 'Aplicativo bloqueado', Passcode_app_locked_subtitle: 'Tente novamente em {{timeLeft}} segundos', After_seconds_set_by_admin: 'Após {{seconds}} segundos (Configurado pelo adm)', - Dont_activate: 'Não ativar agora' + Dont_activate: 'Não ativar agora', + Queued_chats: 'Bate-papos na fila', + Queue_is_empty: 'A fila está vazia' }; diff --git a/app/index.js b/app/index.js index 220f50839..e4d9e52cf 100644 --- a/app/index.js +++ b/app/index.js @@ -50,6 +50,13 @@ const parseDeepLinking = (url) => { return parseQuery(url); } } + const call = /^(https:\/\/)?jitsi.rocket.chat\//; + if (url.match(call)) { + url = url.replace(call, '').trim(); + if (url) { + return { path: url, isCall: true }; + } + } } return null; }; diff --git a/app/lib/database/model/Server.js b/app/lib/database/model/Server.js index 5ff103fac..d30b3a3f4 100644 --- a/app/lib/database/model/Server.js +++ b/app/lib/database/model/Server.js @@ -25,4 +25,6 @@ export default class Server extends Model { @field('auto_lock_time') autoLockTime; @field('biometry') biometry; + + @field('unique_id') uniqueID; } diff --git a/app/lib/database/model/Subscription.js b/app/lib/database/model/Subscription.js index 77efd3783..a94e09423 100644 --- a/app/lib/database/model/Subscription.js +++ b/app/lib/database/model/Subscription.js @@ -40,6 +40,8 @@ export default class Subscription extends Model { @field('user_mentions') userMentions; + @field('group_mentions') groupMentions; + @date('room_updated_at') roomUpdatedAt; @field('ro') ro; diff --git a/app/lib/database/model/migrations.js b/app/lib/database/model/migrations.js index 260209427..db3b92dc3 100644 --- a/app/lib/database/model/migrations.js +++ b/app/lib/database/model/migrations.js @@ -118,6 +118,17 @@ export default schemaMigrations({ ] }) ] + }, + { + toVersion: 9, + steps: [ + addColumns({ + table: 'subscriptions', + columns: [ + { name: 'group_mentions', type: 'number', isOptional: true } + ] + }) + ] } ] }); diff --git a/app/lib/database/model/serversMigrations.js b/app/lib/database/model/serversMigrations.js index 0163d3bde..8d74b0434 100644 --- a/app/lib/database/model/serversMigrations.js +++ b/app/lib/database/model/serversMigrations.js @@ -26,6 +26,17 @@ export default schemaMigrations({ ] }) ] + }, + { + toVersion: 5, + steps: [ + addColumns({ + table: 'servers', + columns: [ + { name: 'unique_id', type: 'string', isOptional: true } + ] + }) + ] } ] }); diff --git a/app/lib/database/schema/app.js b/app/lib/database/schema/app.js index 97784b3f9..59336e3f0 100644 --- a/app/lib/database/schema/app.js +++ b/app/lib/database/schema/app.js @@ -1,7 +1,7 @@ import { appSchema, tableSchema } from '@nozbe/watermelondb'; export default appSchema({ - version: 8, + version: 9, tables: [ tableSchema({ name: 'subscriptions', @@ -19,6 +19,7 @@ export default appSchema({ { name: 'roles', type: 'string', isOptional: true }, { name: 'unread', type: 'number' }, { name: 'user_mentions', type: 'number' }, + { name: 'group_mentions', type: 'number' }, { name: 'room_updated_at', type: 'number' }, { name: 'ro', type: 'boolean' }, { name: 'last_open', type: 'number', isOptional: true }, diff --git a/app/lib/database/schema/servers.js b/app/lib/database/schema/servers.js index 7557f8b1c..b02859e10 100644 --- a/app/lib/database/schema/servers.js +++ b/app/lib/database/schema/servers.js @@ -1,7 +1,7 @@ import { appSchema, tableSchema } from '@nozbe/watermelondb'; export default appSchema({ - version: 4, + version: 5, tables: [ tableSchema({ name: 'users', @@ -28,7 +28,8 @@ export default appSchema({ { name: 'last_local_authenticated_session', type: 'number', isOptional: true }, { name: 'auto_lock', type: 'boolean', isOptional: true }, { name: 'auto_lock_time', type: 'number', isOptional: true }, - { name: 'biometry', type: 'boolean', isOptional: true } + { name: 'biometry', type: 'boolean', isOptional: true }, + { name: 'unique_id', type: 'string', isOptional: true } ] }) ] diff --git a/app/lib/methods/callJitsi.js b/app/lib/methods/callJitsi.js index 92f7bc447..7410ed8bd 100644 --- a/app/lib/methods/callJitsi.js +++ b/app/lib/methods/callJitsi.js @@ -1,41 +1,41 @@ import reduxStore from '../createStore'; import Navigation from '../Navigation'; +import { logEvent, events } from '../../utils/log'; + +async function jitsiURL({ rid }) { + const { settings } = reduxStore.getState(); + const { Jitsi_Enabled } = settings; -const jitsiBaseUrl = ({ - Jitsi_Enabled, Jitsi_SSL, Jitsi_Domain, Jitsi_URL_Room_Prefix, uniqueID -}) => { if (!Jitsi_Enabled) { return ''; } - const uniqueIdentifier = uniqueID || 'undefined'; - const domain = Jitsi_Domain; + + const { + Jitsi_Domain, Jitsi_URL_Room_Prefix, Jitsi_SSL, Jitsi_Enabled_TokenAuth, uniqueID + } = settings; + + const domain = `${ Jitsi_Domain }/`; const prefix = Jitsi_URL_Room_Prefix; + const uniqueIdentifier = uniqueID || 'undefined'; + const protocol = Jitsi_SSL ? 'https://' : 'http://'; - const urlProtocol = Jitsi_SSL ? 'https://' : 'http://'; - const urlDomain = `${ domain }/`; - - return `${ urlProtocol }${ urlDomain }${ prefix }${ uniqueIdentifier }`; -}; - -async function callJitsi(rid, onlyAudio = false) { - let accessToken; let queryString = ''; - const { settings } = reduxStore.getState(); - const { Jitsi_Enabled_TokenAuth } = settings; - if (Jitsi_Enabled_TokenAuth) { try { - accessToken = await this.methodCallWrapper('jitsi:generateAccessToken', rid); - } catch (e) { - // do nothing + const accessToken = await this.methodCallWrapper('jitsi:generateAccessToken', rid); + queryString = `?jwt=${ accessToken }`; + } catch { + logEvent(events.RA_JITSI_F); } } - if (accessToken) { - queryString = `?jwt=${ accessToken }`; - } + return `${ protocol }${ domain }${ prefix }${ uniqueIdentifier }${ rid }${ queryString }`; +} - Navigation.navigate('JitsiMeetView', { url: `${ jitsiBaseUrl(settings) }${ rid }${ queryString }`, onlyAudio, rid }); +async function callJitsi(rid, onlyAudio = false) { + logEvent(onlyAudio ? events.RA_JITSI_AUDIO : events.RA_JITSI_VIDEO); + const url = await jitsiURL.call(this, { rid }); + Navigation.navigate('JitsiMeetView', { url, onlyAudio, rid }); } export default callJitsi; diff --git a/app/lib/methods/canOpenRoom.js b/app/lib/methods/canOpenRoom.js index 1578837aa..b85728727 100644 --- a/app/lib/methods/canOpenRoom.js +++ b/app/lib/methods/canOpenRoom.js @@ -1,4 +1,5 @@ import database from '../database'; +import store from '../createStore'; const restTypes = { channel: 'channels', direct: 'im', group: 'groups' @@ -53,11 +54,17 @@ async function open({ type, rid, name }) { } } -export default async function canOpenRoom({ rid, path }) { +export default async function canOpenRoom({ rid, path, isCall }) { try { const db = database.active; const subsCollection = db.collections.get('subscriptions'); - const [type, name] = path.split('/'); + + if (isCall && !rid) { + // Extract rid from a Jitsi URL + // Eg.: [Jitsi_URL_Room_Prefix][uniqueID][rid][?jwt] + const { Jitsi_URL_Room_Prefix, uniqueID } = store.getState().settings; + rid = path.replace(`${ Jitsi_URL_Room_Prefix }${ uniqueID }`, '').replace(/\?(.*)/g, ''); + } if (rid) { try { @@ -75,8 +82,10 @@ export default async function canOpenRoom({ rid, path }) { } } + const [type, name] = path.split('/'); try { - return await open.call(this, { type, rid, name }); + const result = await open.call(this, { type, rid, name }); + return result; } catch (e) { return false; } diff --git a/app/lib/methods/getSettings.js b/app/lib/methods/getSettings.js index e635807e9..2ebad1ed2 100644 --- a/app/lib/methods/getSettings.js +++ b/app/lib/methods/getSettings.js @@ -11,7 +11,7 @@ import protectedFunction from './helpers/protectedFunction'; import fetch from '../../utils/fetch'; import { DEFAULT_AUTO_LOCK } from '../../constants/localAuthentication'; -const serverInfoKeys = ['Site_Name', 'UI_Use_Real_Name', 'FileUpload_MediaTypeWhiteList', 'FileUpload_MaxFileSize', 'Force_Screen_Lock', 'Force_Screen_Lock_After']; +const serverInfoKeys = ['Site_Name', 'UI_Use_Real_Name', 'FileUpload_MediaTypeWhiteList', 'FileUpload_MaxFileSize', 'Force_Screen_Lock', 'Force_Screen_Lock_After', 'uniqueID']; // these settings are used only on onboarding process const loginSettings = [ @@ -68,6 +68,9 @@ const serverInfoUpdate = async(serverInfo, iconSetting) => { return { ...allSettings, autoLockTime: setting.valueAsNumber }; } } + if (setting._id === 'uniqueID') { + return { ...allSettings, uniqueID: setting.valueAsString }; + } return allSettings; }, {}); diff --git a/app/lib/methods/subscriptions/inquiry.js b/app/lib/methods/subscriptions/inquiry.js new file mode 100644 index 000000000..014335dc1 --- /dev/null +++ b/app/lib/methods/subscriptions/inquiry.js @@ -0,0 +1,95 @@ +import log from '../../../utils/log'; +import store from '../../createStore'; +import RocketChat from '../../rocketchat'; +import { + inquiryRequest, + inquiryQueueAdd, + inquiryQueueUpdate, + inquiryQueueRemove +} from '../../../actions/inquiry'; + +const removeListener = listener => listener.stop(); + +let connectedListener; +let disconnectedListener; +let queueListener; + +const streamTopic = 'stream-livechat-inquiry-queue-observer'; + +export default function subscribeInquiry() { + const handleConnection = () => { + store.dispatch(inquiryRequest()); + }; + + const handleQueueMessageReceived = (ddpMessage) => { + const [{ type, ...sub }] = ddpMessage.fields.args; + + // added can be ignored, since it is handled by 'changed' event + if (/added/.test(type)) { + return; + } + + // if the sub isn't on the queue anymore + if (sub.status !== 'queued') { + // remove it from the queue + store.dispatch(inquiryQueueRemove(sub._id)); + return; + } + + const { queued } = store.getState().inquiry; + // check if this sub is on the current queue + const idx = queued.findIndex(item => item._id === sub._id); + if (idx >= 0) { + // if it is on the queue let's update + store.dispatch(inquiryQueueUpdate(sub)); + } else { + // if it is not on the queue let's add + store.dispatch(inquiryQueueAdd(sub)); + } + }; + + const stop = () => { + if (connectedListener) { + connectedListener.then(removeListener); + connectedListener = false; + } + if (disconnectedListener) { + disconnectedListener.then(removeListener); + disconnectedListener = false; + } + if (queueListener) { + queueListener.then(removeListener); + queueListener = false; + } + }; + + connectedListener = this.sdk.onStreamData('connected', handleConnection); + disconnectedListener = this.sdk.onStreamData('close', handleConnection); + queueListener = this.sdk.onStreamData(streamTopic, handleQueueMessageReceived); + + try { + const { user } = store.getState().login; + RocketChat.getAgentDepartments(user.id).then((result) => { + if (result.success) { + const { departments } = result; + + if (!departments.length || RocketChat.hasRole('livechat-manager')) { + this.sdk.subscribe(streamTopic, 'public').catch(e => console.log(e)); + } + + const departmentIds = departments.map(({ departmentId }) => departmentId); + departmentIds.forEach((departmentId) => { + // subscribe to all departments of the agent + this.sdk.subscribe(streamTopic, `department/${ departmentId }`).catch(e => console.log(e)); + }); + } + }); + + return { + stop: () => stop() + }; + } catch (e) { + log(e); + return Promise.reject(); + } +} diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index cfa959919..52c09f93f 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -20,6 +20,7 @@ import { } from '../actions/share'; import subscribeRooms from './methods/subscriptions/rooms'; +import subscribeInquiry from './methods/subscriptions/inquiry'; import getUsersPresence, { getUserPresence, subscribeUsersPresence } from './methods/getUsersPresence'; import protectedFunction from './methods/helpers/protectedFunction'; @@ -72,6 +73,15 @@ const RocketChat = { } } }, + async subscribeInquiry() { + if (!this.inquirySub) { + try { + this.inquirySub = await subscribeInquiry.call(this); + } catch (e) { + log(e); + } + } + }, canOpenRoom, createChannel({ name, users, type, readOnly, broadcast @@ -203,6 +213,11 @@ const RocketChat = { this.roomsSub = null; } + if (this.inquirySub) { + this.inquirySub.stop(); + this.inquirySub = null; + } + if (this.sdk) { this.sdk.disconnect(); this.sdk = null; @@ -680,7 +695,7 @@ const RocketChat = { c: 'channel', d: 'direct' }[room.t]; - return `${ server }/${ roomType }/${ room.name }?msg=${ message.id }`; + return `${ server }/${ roomType }/${ this.isGroupChat(room) ? room.rid : room.name }?msg=${ message.id }`; }, getPermalinkChannel(channel) { const { server } = reduxStore.getState().server; @@ -816,7 +831,7 @@ const RocketChat = { }, getAgentDepartments(uid) { // RC 2.4.0 - return this.sdk.get(`livechat/agents/${ uid }/departments`); + return this.sdk.get(`livechat/agents/${ uid }/departments?enabledDepartmentsOnly=true`); }, getCustomFields() { // RC 2.2.0 @@ -826,6 +841,16 @@ const RocketChat = { // RC 0.26.0 return this.methodCallWrapper('livechat:changeLivechatStatus'); }, + getInquiriesQueued() { + // RC 2.4.0 + return this.sdk.get('livechat/inquiries.queued'); + }, + takeInquiry(inquiryId) { + // this inquiry is added to the db by the subscriptions stream + // and will be removed by the queue stream + // RC 2.4.0 + return this.methodCallWrapper('livechat:takeInquiry', inquiryId); + }, getUidDirectMessage(room) { const { id: userId } = reduxStore.getState().login.user; @@ -845,6 +870,12 @@ const RocketChat = { return other && other.length ? other[0] : me; }, + isRead(item) { + let isUnread = item.archived !== true && item.open === true; // item is not archived and not opened + isUnread = isUnread && (item.unread > 0 || item.alert === true); // either its unread count > 0 or its alert + return !isUnread; + }, + isGroupChat(room) { return (room.uids && room.uids.length > 2) || (room.usernames && room.usernames.length > 2); }, @@ -957,6 +988,14 @@ const RocketChat = { // RC 0.47.0 return this.sdk.get('chat.getMessage', { msgId }); }, + hasRole(role) { + const shareUser = reduxStore.getState().share.user; + const loginUser = reduxStore.getState().login.user; + // get user roles on the server from redux + const userRoles = (shareUser?.roles || loginUser?.roles) || []; + + return userRoles.indexOf(r => r === role) > -1; + }, async hasPermission(permissions, rid) { const db = database.active; const subsCollection = db.collections.get('subscriptions'); diff --git a/app/lib/selection.json b/app/lib/selection.json index 3b26c8ae9..7a375d65a 100644 --- a/app/lib/selection.json +++ b/app/lib/selection.json @@ -1 +1 @@ -{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M821.811 544c0 176.73-143.266 320-320 320-176.73 0-319.999-143.27-319.999-320 0-176.731 143.269-320 319.999-320v-64c-212.076 0-383.999 171.923-383.999 384 0 212.079 171.923 384 383.999 384 212.079 0 384-171.921 384-384 0-10.778-0.444-21.449-1.314-32h-64.265c1.045 10.526 1.579 21.201 1.579 32zM821.811 112c0-17.673-14.327-32-32-32s-32 14.327-32 32v112h-112c-17.673 0-32 14.327-32 32s14.327 32 32 32h112v112c0 17.673 14.327 32 32 32s32-14.327 32-32v-112h112c17.673 0 32-14.327 32-32s-14.327-32-32-32h-112v-112zM405.812 512c35.348 0 63.999-28.655 63.999-64 0-35.346-28.651-64-63.999-64-35.346 0-64 28.654-64 64 0 35.345 28.654 64 64 64zM661.811 448c0 35.345-28.651 64-64 64-35.345 0-64-28.655-64-64 0-35.346 28.655-64 64-64 35.349 0 64 28.654 64 64zM351.617 589.077c-10.451-14.251-30.477-17.335-44.728-6.882-14.252 10.449-17.332 30.477-6.881 44.727 37.658 51.354 77.753 84.625 119.178 102.665 41.738 18.18 82.796 19.989 120.36 11.652 73.468-16.307 132.215-70.874 164.070-114.317 10.453-14.251 7.373-34.278-6.878-44.727-14.255-10.453-34.278-7.369-44.732 6.882-26.807 36.557-73.664 77.99-126.327 89.681-25.502 5.662-52.646 4.476-80.939-7.846-28.609-12.459-60.381-37.188-93.123-81.835z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["add-reaction"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":300,"id":145,"name":"add-reaction","prevSize":32,"code":59648},"setIdx":0,"setId":0,"iconIdx":0},{"icon":{"paths":["M568.461 325.606c0 91.58-75.849 165.821-169.411 165.821s-169.412-74.241-169.412-165.821c0-91.579 75.849-165.819 169.412-165.819s169.411 74.24 169.411 165.819zM500.698 325.606c0-54.947-45.508-99.491-101.648-99.491-56.138 0-101.647 44.544-101.647 99.491s45.509 99.492 101.647 99.492c56.14 0 101.648-44.544 101.648-99.492z","M218.476 510.558c28.952-9.109 60.004-9.668 89.28-1.613l51.341 14.135c25.632 7.057 52.819 6.566 78.168-1.408l31.872-10.027c31.206-9.822 64.678-10.423 96.235-1.737 71.957 19.81 121.677 84.049 121.677 157.218v96.239c0 54.946-45.508 99.49-101.645 99.49h-372.707c-56.138 0-101.647-44.544-101.647-99.49v-108.565c0-65.818 43.411-124.105 107.427-144.243zM289.409 572.796c-16.46-4.531-33.918-4.215-50.196 0.905-35.992 11.324-60.399 44.096-60.399 81.101v108.565c0 18.317 15.17 33.165 33.882 33.165h372.707c18.709 0 33.882-14.848 33.882-33.165v-96.239c0-43.452-29.525-81.604-72.26-93.367-18.743-5.158-38.618-4.8-57.152 1.028l-31.872 10.031c-38.023 11.959-78.804 12.698-117.251 2.112l-51.342-14.135z","M812.139 188.646c0-15.913-13.022-28.812-29.090-28.812-16.064 0-29.090 12.9-29.090 28.812v100.844h-101.82c-16.064 0-29.090 12.9-29.090 28.812s13.026 28.813 29.090 28.813h101.82v100.842c0 15.915 13.026 28.813 29.090 28.813 16.068 0 29.090-12.898 29.090-28.813v-100.842h101.82c16.068 0 29.090-12.9 29.090-28.813s-13.022-28.812-29.090-28.812h-101.82v-100.844z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["add-user"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":301,"id":144,"name":"add-user","prevSize":32,"code":59649},"setIdx":0,"setId":0,"iconIdx":1},{"icon":{"paths":["M512 768c0 0 0 0 0 0s0 0 0 0 0 0 0 0c-4.267 0-8.533 0-12.8-4.267 0 0 0 0-4.267 0 0 0 0 0 0 0s0 0 0 0 0 0 0 0v0c-4.267 0-4.267-4.267-8.533-4.267 0 0 0 0 0 0s0 0 0 0l-187.733-187.733c-12.8-12.8-12.8-34.133 0-46.933s29.867-12.8 42.667 0l136.533 136.533v-371.2c4.267-21.333 17.067-34.133 34.133-34.133s34.133 12.8 34.133 34.133v371.2l136.533-136.533c12.8-12.8 34.133-12.8 46.933 0s12.8 34.133 0 46.933l-192 187.733c-4.267 4.267-4.267 4.267-8.533 4.267v0c0 0 0 0 0 0s0 0 0 0 0 0 0 0v0c0 0 0 0 0 0s0 0 0 0v0c-8.533 4.267-12.8 4.267-17.067 4.267 0 0 0 0 0 0s0 0 0 0 0 0 0 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-down"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":302,"id":143,"name":"arrow-down","prevSize":32,"code":59650},"setIdx":0,"setId":0,"iconIdx":2},{"icon":{"paths":["M512 768c-17.067 0-34.133-12.8-34.133-34.133v-371.2l-136.533 136.533c-12.8 12.8-29.867 12.8-42.667 0s-12.8-34.133 0-46.933l192-187.733c0 0 0 0 0 0s0 0 0 0v0c0 0 4.267-4.267 8.533-4.267v0c0 0 0 0 0 0s0 0 0 0v0c0 0 0 0 0 0s0 0 4.267 0c0 0 0 0 0 0s0 0 0 0c0-4.267 4.267-4.267 8.533-4.267v0c0 0 0 0 0 0s0 0 0 0v0c0 0 0 0 0 0s0 0 0 0c4.267 0 8.533 0 12.8 4.267v0c0 0 0 0 0 0s0 0 0 0v0c0 0 0 0 0 0v0c0 0 0 0 0 0v0c4.267 0 8.533 4.267 8.533 4.267s0 0 0 0l192 187.733c12.8 12.8 12.8 34.133 0 46.933s-34.133 12.8-46.933 0l-136.533-136.533v371.2c4.267 21.333-12.8 34.133-29.867 34.133z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-up"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":303,"id":142,"name":"arrow-up","prevSize":32,"code":59651},"setIdx":0,"setId":0,"iconIdx":3},{"icon":{"paths":["M686.699 116.071c-57.242-19.989-105.792-20.069-138.359-20.071v64l-1.003-64c-92.002 0.342-297.343 47.824-381.24 242.996-17.896 38.968-34.758 103.342-34.758 173.004 0 69.961 17.020 146.283 52.216 207.876 23.229 40.653 92.799 131.375 191.179 173.538 94.86 40.653 206.37 52.343 296.49 16.299 16.41-6.566 24.388-25.19 17.826-41.596-6.562-16.41-25.186-24.393-41.596-17.83-69.879 27.955-163.17 20.446-247.51-15.701-80.82-34.637-141.385-112.448-160.822-146.462-28.804-50.406-43.784-115.418-43.784-176.124 0-60.766 15.020-116.183 29.055-146.59l0.184-0.4 0.173-0.404c69.507-162.182 243.823-204.605 323.588-204.605 31.595 0.002 70.878 0.296 117.261 16.493 46.144 16.113 101.389 48.779 161.822 116.767 43.657 49.114 63.535 114.976 69.389 177.712 5.892 63.121-2.854 118.187-11.546 142.093-6.4 17.6-20.429 45.44-59.392 45.7-18.261-0.806-72.823-14.673-83.123-69.568v-235.063c0-17.673-3.413-34.133-29.013-34.133-19.337 0-26.453 16.46-26.453 34.133v34.133c-35.179-39.86-95.398-68.267-152.747-68.267-106.035 0-191.998 85.961-191.998 192s85.963 192 191.998 192c62.182 0 117.662-29.555 152.747-75.388 25.715 71.078 102.571 93.030 137.015 94.135l0.512 0.017h0.516c82.645 0 111.714-64.806 120.085-87.829 12.642-34.761 21.675-99.695 15.121-169.907-6.588-70.597-29.38-151.402-85.278-214.288-66.901-75.265-131.076-114.598-188.557-134.67zM662.537 512c0 70.694-57.306 128-128 128-70.69 0-127.998-57.306-127.998-128s57.308-128 127.998-128c70.694 0 128 57.306 128 128z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["at"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":304,"id":141,"name":"at","prevSize":32,"code":59652},"setIdx":0,"setId":0,"iconIdx":4},{"icon":{"paths":["M869.030 166.758c7.782 6.063 12.331 15.377 12.331 25.242v448h-0.111c0.073 1.732 0.111 3.477 0.111 5.231 0 69.052-57.31 125.026-128 125.026-70.694 0-128-55.974-128-125.026s57.306-125.030 128-125.030c23.313 0 45.171 6.089 64 16.725v-303.858l-384 96.797v409.139c0 69.052-57.308 125.035-128 125.035s-128-55.979-128-125.030c0-69.052 57.308-125.026 128-125.026 23.314 0 45.173 6.089 64 16.725v-325.777c0-14.66 9.963-27.446 24.178-31.029l448.001-112.929c9.566-2.412 19.708-0.276 27.49 5.787z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["audio"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":305,"id":140,"name":"audio","prevSize":32,"code":59653},"setIdx":0,"setId":0,"iconIdx":5},{"icon":{"paths":["M545.084 554.018c66.466 0 120.346-52.493 120.346-117.239 0-64.753-53.879-117.243-120.346-117.243s-120.347 52.491-120.347 117.243c0 64.747 53.881 117.239 120.347 117.239zM545.084 490.018c-32.708 0-56.346-25.404-56.346-53.239 0-27.84 23.637-53.243 56.346-53.243 32.704 0 56.346 25.403 56.346 53.243 0 27.836-23.642 53.239-56.346 53.239z","M397.208 894.144h-172.125c-17.673 0-32-14.327-32-32v-702.144c0-17.673 14.327-32 32-32h640c17.673 0 32 14.327 32 32v702.144c0 17.673-14.327 32-32 32h-172.126c-6.242 1.276-12.702 1.946-19.319 1.946h-257.11c-6.618 0-13.079-0.67-19.32-1.946zM257.083 830.144h68.244c-3.114-9.455-4.799-19.558-4.799-30.054v-93.449c0-56.107 37.881-105.143 92.172-119.309 19.172-5.005 39.264-5.312 58.583-0.9l42.773 9.766c20.049 4.578 40.909 4.254 60.813-0.939l28.070-7.326c20.689-5.397 42.381-5.73 63.228-0.973 60.535 13.824 103.471 67.665 103.471 129.758v83.371c0 10.496-1.685 20.599-4.8 30.054h68.245v-638.144h-576v638.144zM684.646 830.144c12.25-4.489 20.992-16.252 20.992-30.054v-83.371c0-32.235-22.289-60.186-53.713-67.362-10.825-2.47-22.084-2.3-32.828 0.503l-28.070 7.326c-29.854 7.791-61.141 8.273-91.217 1.404l-42.773-9.766c-9.293-2.121-18.957-1.971-28.177 0.435-26.112 6.814-44.331 30.396-44.331 57.382v93.449c0 13.803 8.74 25.566 20.989 30.054h279.129z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["avatar"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":306,"id":139,"name":"avatar","prevSize":32,"code":59654},"setIdx":0,"setId":0,"iconIdx":6},{"icon":{"paths":["M412.221 297.373c-12.497-12.497-32.758-12.497-45.255 0l-192 192.001c-12.497 12.497-12.497 32.755 0 45.252l192 192c12.497 12.497 32.758 12.497 45.255 0s12.497-32.755 0-45.252l-137.373-137.374h578.745v128c0 17.673 14.327 32 32 32s32-14.327 32-32v-160c0-17.673-14.327-32-32-32h-610.745l137.373-137.373c12.497-12.497 12.497-32.758 0-45.255z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["back"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":307,"id":138,"name":"back","prevSize":32,"code":59655},"setIdx":0,"setId":0,"iconIdx":7},{"icon":{"paths":["M761.847 361.376c12.497 12.497 12.497 32.758 0 45.255l-110.95 110.95 110.95 110.946c12.497 12.497 12.497 32.759 0 45.257s-32.759 12.497-45.257 0l-110.946-110.95-110.95 110.95c-12.497 12.497-32.759 12.497-45.257 0s-12.497-32.759 0-45.257l110.95-110.946-110.95-110.95c-12.497-12.497-12.497-32.758 0-45.255s32.759-12.497 45.257 0l110.95 110.948 110.946-110.948c12.497-12.497 32.759-12.497 45.257 0z","M336.313 218.073c12.061-16.393 31.2-26.073 51.552-26.073h468.204c35.345 0 64 28.654 64 64v512c0 35.345-28.655 64-64 64h-468.204c-20.352 0-39.491-9.681-51.551-26.074l-188.343-256c-16.598-22.562-16.598-53.291 0-75.853l188.343-256zM387.864 256l-188.343 256 188.343 256h468.204v-512h-468.204z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["backspace"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":308,"id":137,"name":"backspace","prevSize":32,"code":59656},"setIdx":0,"setId":0,"iconIdx":8},{"icon":{"paths":["M682.539 288v-32c0-88.366-71.633-160-160-160s-160 71.634-160 160v32h-96c-53.019 0-96 42.981-96 96v352c0 106.039 85.961 192 192 192h320c106.039 0 192-85.961 192-192v-352c0-53.019-42.982-96-96-96h-96zM618.539 288h-192v-32c0-53.019 42.982-96 96-96 53.022 0 96 42.981 96 96v32zM618.539 352v160c0 17.673 14.327 32 32 32s32-14.327 32-32v-160h96c17.673 0 32 14.327 32 32v352c0 70.694-57.306 128-128 128h-320c-70.693 0-128-57.306-128-128v-352c0-17.673 14.327-32 32-32h96v160c0 17.673 14.327 32 32 32s32-14.327 32-32v-160h192z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["bag"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":309,"id":136,"name":"bag","prevSize":32,"code":59657},"setIdx":0,"setId":0,"iconIdx":9},{"icon":{"paths":["M876.796 512c0-86.89-31.484-166.427-83.665-227.826l-496.163 496.161c61.399 52.181 140.937 83.665 227.828 83.665 194.402 0 352-157.598 352-352zM252.144 734.652l495.299-495.302c-60.659-49.597-138.18-79.349-222.647-79.349-194.406 0-352.001 157.596-352.001 352 0 84.467 29.752 161.988 79.349 222.652zM940.796 512c0 229.751-186.253 416-416 416-229.752 0-416.001-186.249-416.001-416s186.249-416 416.001-416c229.747 0 416 186.249 416 416z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["ban"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":310,"id":135,"name":"ban","prevSize":32,"code":59658},"setIdx":0,"setId":0,"iconIdx":10},{"icon":{"paths":["M833.084 384v306.743l54.626 54.63c9.152 9.152 11.891 22.916 6.938 34.871-4.954 11.959-16.623 19.755-29.564 19.755h-465.731l63.999-64h305.732v-305.732l63.492-63.492c0.337 5.699 0.508 11.441 0.508 17.224zM748.105 179.728l-45.257 45.255c-40.486-40.169-96.226-64.983-157.764-64.983-123.712 0-224 100.288-224 224v222.746l-64 64v-286.746c0-159.058 128.942-288 288-288 79.211 0 150.95 31.978 203.021 83.728zM449.084 832c0 53.018 42.978 96 96 96 53.018 0 96-42.982 96-96h-192zM912.956 150.62c-12.497-12.497-32.755-12.497-45.252 0l-675.618 675.616c-12.497 12.497-12.497 32.759 0 45.257s32.758 12.497 45.255 0l675.615-675.618c12.497-12.497 12.497-32.758 0-45.255z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["bell-off"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":311,"id":134,"name":"bell-off","prevSize":32,"code":59659},"setIdx":0,"setId":0,"iconIdx":11},{"icon":{"paths":["M638.831 832h-192c0 53.018 42.982 96 96 96s96-42.982 96-96zM766.831 736v-352c0-123.712-100.288-224-224-224s-224 100.288-224 224v352h448zM222.831 800c-12.943 0-24.611-7.795-29.564-19.755-4.953-11.955-2.215-25.719 6.937-34.871l54.627-54.63v-306.743c0-159.058 128.942-288 288-288 159.057 0 288 128.942 288 288v309.333l41.6 55.467c7.27 9.698 8.444 22.669 3.021 33.51-5.419 10.842-16.499 17.69-28.621 17.69h-624z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["bell"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":312,"id":133,"name":"bell","prevSize":32,"code":59660},"setIdx":0,"setId":0,"iconIdx":12},{"icon":{"paths":["M403.558 775.415c-17.673 0-32-14.327-32-32v-453.166c0-17.673 14.327-32 32-32h137.075c56.119 0 98.27 11.603 126.447 34.81 28.416 23.206 42.624 57.542 42.624 103.007 0 24.153-6.865 45.585-20.599 64.29-13.734 18.47-32.444 32.798-56.124 42.978 27.942 7.817 49.967 22.733 66.069 44.757 16.337 21.786 24.508 47.834 24.508 78.144 0 46.409-15.036 82.876-45.111 109.397-30.071 26.522-72.576 39.782-127.514 39.782h-147.375zM439.757 533.53v186.121h112.597c31.731 0 56.713-8.171 74.948-24.508 18.466-16.576 27.703-39.309 27.703-68.198 0-62.276-33.86-93.414-101.585-93.414h-113.664zM439.757 478.827h103.006c29.837 0 53.636-7.458 71.394-22.379 17.997-14.916 26.995-35.163 26.995-60.737 0-28.416-8.286-49.017-24.862-61.804-16.576-13.024-41.796-19.536-75.657-19.536h-100.877v164.456z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["bold"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":313,"id":132,"name":"bold","prevSize":32,"code":59661},"setIdx":0,"setId":0,"iconIdx":13},{"icon":{"paths":["M371.558 445.44c0-17.677 14.327-32.002 32-32.002h256c17.673 0 32 14.325 32 32.002 0 17.673-14.327 32-32 32h-256c-17.673 0-32-14.327-32-32z","M371.558 322.558c0-17.673 14.327-32 32-32h256c17.673 0 32 14.327 32 32s-14.327 32-32 32h-256c-17.673 0-32-14.327-32-32z","M883.558 679.68c0 17.673-14.327 32-32 32h-18.509c-8.218 40.546-8.218 82.334 0 122.88h19.789c16.969 0 30.72 13.756 30.72 30.72s-13.751 30.72-30.72 30.72h-545.28c-70.692 0-128-55.014-128-122.88v-453.12c0-106.039 85.961-192 192-192h480c17.673 0 32 14.327 32 32v519.68zM767.979 834.56c-6.788-40.678-6.788-82.202 0-122.88h-460.42c-35.346 0-64 27.507-64 61.44s28.654 61.44 64 61.44h460.42zM243.558 647.68h576v-455.68h-448c-70.692 0-128 57.308-128 128v327.68z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["book"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":314,"id":131,"name":"book","prevSize":32,"code":59662},"setIdx":0,"setId":0,"iconIdx":14},{"icon":{"paths":["M241.303 224h319.998v576h-96v-112c0-8.836-7.159-16-16-16h-95.998c-8.837 0-16 7.164-16 16v112h-96v-576zM625.301 448h192v352h-192v-352zM849.301 384h-224v-192c0-17.673-14.323-32-32-32h-383.998c-17.673 0-32 14.327-32 32v640c0 17.673 14.327 32 32 32h639.998c17.677 0 32-14.327 32-32v-416c0-17.673-14.323-32-32-32zM321.303 288c-8.837 0-16 7.163-16 16v32c0 8.837 7.163 16 16 16h32c8.836 0 16-7.163 16-16v-32c0-8.837-7.164-16-16-16h-32zM305.303 432c0-8.837 7.163-16 16-16h32c8.836 0 16 7.163 16 16v32c0 8.836-7.164 16-16 16h-32c-8.837 0-16-7.164-16-16v-32zM321.303 544c-8.837 0-16 7.164-16 16v32c0 8.836 7.163 16 16 16h32c8.836 0 16-7.164 16-16v-32c0-8.836-7.164-16-16-16h-32zM433.301 304c0-8.837 7.164-16 16-16h32c8.841 0 16 7.163 16 16v32c0 8.837-7.159 16-16 16h-32c-8.836 0-16-7.163-16-16v-32zM449.301 416c-8.836 0-16 7.163-16 16v32c0 8.836 7.164 16 16 16h32c8.841 0 16-7.164 16-16v-32c0-8.837-7.159-16-16-16h-32zM433.301 560c0-8.836 7.164-16 16-16h32c8.841 0 16 7.164 16 16v32c0 8.836-7.159 16-16 16h-32c-8.836 0-16-7.164-16-16v-32zM705.301 512c-8.836 0-16 7.164-16 16v32c0 8.836 7.164 16 16 16h32c8.841 0 16-7.164 16-16v-32c0-8.836-7.159-16-16-16h-32zM689.301 656c0-8.836 7.164-16 16-16h32c8.841 0 16 7.164 16 16v32c0 8.836-7.159 16-16 16h-32c-8.836 0-16-7.164-16-16v-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["business"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":315,"id":130,"name":"business","prevSize":32,"code":59663},"setIdx":0,"setId":0,"iconIdx":15},{"icon":{"paths":["M293.783 157.44c0-16.259 13.181-29.44 29.44-29.44s29.44 13.181 29.44 29.44v58.877h353.278v-58.877c0-16.259 13.184-29.44 29.44-29.44 16.26 0 29.44 13.181 29.44 29.44v58.877h85.764c17.673 0 32 14.327 32 32v583.679c0 17.673-14.327 32-32 32h-642.562c-17.673 0-32-14.327-32-32v-583.679c0-1.105 0.056-2.196 0.165-3.272 1.639-16.136 15.266-28.728 31.835-28.728h85.76v-58.877zM818.586 392.957h-578.562v407.039h578.562v-407.039zM440.986 644.476c0-8.836 7.164-16 16-16h26.88c8.836 0 16 7.164 16 16v26.88c0 8.836-7.164 16-16 16h-26.88c-8.836 0-16-7.164-16-16v-26.88zM339.223 510.72c-8.837 0-16 7.164-16 16v26.88c0 8.836 7.163 16 16 16h26.88c8.837 0 16-7.164 16-16v-26.88c0-8.836-7.163-16-16-16h-26.88zM558.741 526.72c0-8.836 7.164-16 16-16h26.88c8.841 0 16 7.164 16 16v26.88c0 8.836-7.159 16-16 16h-26.88c-8.836 0-16-7.164-16-16v-26.88zM339.223 628.476c-8.837 0-16 7.164-16 16v26.88c0 8.836 7.163 16 16 16h26.88c8.837 0 16-7.164 16-16v-26.88c0-8.836-7.163-16-16-16h-26.88zM558.741 644.476c0-8.836 7.164-16 16-16h26.88c8.841 0 16 7.164 16 16v26.88c0 8.836-7.159 16-16 16h-26.88c-8.836 0-16-7.164-16-16v-26.88zM456.981 510.72c-8.836 0-16 7.164-16 16v26.88c0 8.836 7.164 16 16 16h26.88c8.841 0 16-7.164 16-16v-26.88c0-8.836-7.159-16-16-16h-26.88zM676.501 526.72c0-8.836 7.164-16 16-16h26.88c8.836 0 16 7.164 16 16v26.88c0 8.836-7.164 16-16 16h-26.88c-8.836 0-16-7.164-16-16v-26.88zM692.501 628.476c-8.836 0-16 7.164-16 16v26.88c0 8.836 7.164 16 16 16h26.88c8.836 0 16-7.164 16-16v-26.88c0-8.836-7.164-16-16-16h-26.88z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["calendar"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":316,"id":129,"name":"calendar","prevSize":32,"code":59664},"setIdx":0,"setId":0,"iconIdx":16},{"icon":{"paths":["M195.378 192.002c0-15.807 12.815-28.622 28.622-28.622h128c15.807 0 28.622 12.815 28.622 28.622s-12.815 28.622-28.622 28.622h-128c-15.807 0-28.622-12.814-28.622-28.622z","M736 560c0 97.203-78.797 176-176 176s-176-78.797-176-176c0-97.199 78.797-175.998 176-175.998s176 78.799 176 175.998zM672 560c0-61.854-50.146-112-112-112s-112 50.146-112 112c0 61.858 50.146 112 112 112s112-50.142 112-112z","M192 256.002c-35.346 0-64 28.654-64 64v447.998c0 35.349 28.654 64 64 64h640c35.345 0 64-28.651 64-64v-447.998c0-35.346-28.655-64-64-64h-640zM832 320.002v447.998h-640v-447.998h640z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Camera"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":317,"id":128,"name":"Camera","prevSize":32,"code":59665},"setIdx":0,"setId":0,"iconIdx":17},{"icon":{"paths":["M522.539 864c-194.404 0-352-157.598-352-352 0-194.404 157.596-352 352-352 194.406 0 352 157.596 352 352 0 194.402-157.594 352-352 352zM522.539 928c229.751 0 416-186.249 416-416s-186.249-416-416-416c-229.75 0-416 186.249-416 416s186.249 416 416 416zM673.165 361.373c12.497 12.497 12.497 32.758 0 45.255l-105.37 105.373 105.37 105.374c12.497 12.497 12.497 32.755 0 45.252s-32.755 12.497-45.252 0l-105.374-105.37-105.372 105.37c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l105.375-105.374-105.375-105.373c-12.497-12.497-12.497-32.758 0-45.255s32.758-12.497 45.255 0l105.372 105.371 105.374-105.371c12.497-12.497 32.755-12.497 45.252 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["cancel"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":318,"id":127,"name":"cancel","prevSize":32,"code":59666},"setIdx":0,"setId":0,"iconIdx":18},{"icon":{"paths":["M261.842 304.026c-49.642 68.947-66.502 152.644-66.502 207.97v1.451l-0.131 1.446c-9.702 106.718 28.59 181.931 90.135 234.005 62.938 53.257 152.153 83.733 244.198 93.961 91.964 10.219 193.271 1.446 273.306-15.479 40.021-8.465 73.613-18.735 97.442-29.077 9.246-4.015 16.439-7.787 21.734-11.127-2.462-1.566-5.444-3.302-9.003-5.197-9.22-4.911-19.776-9.579-30.733-14.366l-1.911-0.836c-9.668-4.224-20.471-8.943-28.659-13.521-14.831-8.294-29.385-17.732-40-27.772-5.227-4.941-11.17-11.571-15.147-19.827-4.211-8.742-7.228-21.794-1.31-35.601 31.979-74.62 47.181-115.49 54.541-142.481 6.874-25.199 6.874-37.888 6.874-58.061v-0.183c0-16.038-9.323-89.517-55.812-158.033-45.018-66.338-125.99-129.968-274.854-129.968-134.639 0-215.698 55.382-264.166 122.698zM209.904 266.63c60.332-83.796 160.606-149.302 316.104-149.302 171.136 0 271.492 75.037 327.812 158.032 54.839 80.818 66.854 167.337 66.854 193.969 0 22.383-0.021 41.694-9.131 75.085-8.128 29.807-23.479 70.929-51.942 137.924 5.261 4.169 13.069 9.306 23.36 15.061 5.312 2.974 13.483 6.554 24.964 11.571 10.654 4.655 23.437 10.266 35.174 16.512 11.26 5.995 24.414 14.033 34.202 24.542 10.231 10.991 20.971 29.845 13.299 52.864-5.056 15.164-16.798 25.937-26.577 33.092-10.628 7.774-23.817 14.763-38.255 21.030-29.005 12.587-67.029 23.962-109.679 32.981-85.312 18.039-193.583 27.588-293.619 16.474-99.953-11.106-202.739-44.629-278.468-108.71-76.833-65.011-123.811-159.996-112.66-287.223 0.286-65.549 19.841-162.346 78.561-243.902zM531.337 320c17.677 0 32 14.327 32 32v224c0 17.673-14.323 32-32 32-17.673 0-32-14.327-32-32v-224c0-17.673 14.327-32 32-32zM563.337 672c0-17.673-14.323-32-32-32-17.673 0-32 14.327-32 32s14.327 32 32 32c17.677 0 32-14.327 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["canned_responsed"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":319,"id":126,"name":"canned_responsed","prevSize":32,"code":59667},"setIdx":0,"setId":0,"iconIdx":19},{"icon":{"paths":["M332.711 105.235c12.497-12.48 32.758-12.48 45.255 0s12.497 32.715 0 45.195l-105.373 105.233h610.743c17.677 0 32 14.308 32 31.958v111.852c0 17.65-14.323 31.959-32 31.959-17.673 0-32-14.309-32-31.959v-79.894h-578.743l105.373 105.233c12.497 12.482 12.497 32.715 0 45.195s-32.758 12.48-45.255 0l-160-159.788c-12.497-12.48-12.497-32.715 0-45.195l160-159.789zM745.967 917.414c-12.497 12.48-32.759 12.48-45.257 0s-12.497-32.713 0-45.193l105.374-105.233h-610.746c-17.673 0-32-14.31-32-31.957v-111.855c0-17.647 14.327-31.957 32-31.957s32 14.31 32 31.957v79.898h578.746l-105.374-105.237c-12.497-12.48-12.497-32.713 0-45.193s32.759-12.48 45.257 0l160 159.787c12.497 12.48 12.497 32.717 0 45.197l-160 159.787z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["change"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":320,"id":125,"name":"change","prevSize":32,"code":59668},"setIdx":0,"setId":0,"iconIdx":20},{"icon":{"paths":["M578.97 127.99c-121.694 0-200.971 50.509-248.812 115.801-46.216 63.073-61.638 137.752-61.933 188.615-8.705 98.748 28.601 172.898 89.423 223.471 59.686 49.626 140.201 75.26 217.85 83.738 77.751 8.486 161.715 1.195 227.857-12.548 33.062-6.869 62.771-15.578 85.641-25.331 11.366-4.847 22.029-10.368 30.797-16.67 7.872-5.662 18.539-14.976 23.241-28.834 7.287-21.474-3.132-38.784-11.964-48.102-8.41-8.879-19.426-15.403-28.241-20.015-9.306-4.868-19.379-9.207-27.533-12.71-8.973-3.853-14.857-6.396-18.56-8.431-4.843-2.662-8.841-5.086-12.028-7.202 20.258-47.142 31.552-77.043 37.7-99.191 7.292-26.27 7.313-41.723 7.313-58.907 0-21.523-9.604-88.542-52.809-151.109-44.702-64.73-124.075-122.573-257.941-122.573zM332.22 433.894c0-40.414 12.606-101.841 49.562-152.276 35.784-48.835 95.884-89.628 197.188-89.628 112.090 0 172.092 46.886 205.278 94.94 34.679 50.219 41.472 104.040 41.472 114.741v0.2c0 14.918 0 23.638-4.983 41.594-5.491 19.776-16.964 50.189-41.54 106.534-5.798 13.295-2.756 25.771 1.156 33.754 3.665 7.479 9.007 13.244 13.333 17.263 8.836 8.213 20.651 15.684 32.222 22.046 6.618 3.635 15.236 7.334 22.562 10.475l1.566 0.67c5.901 2.539 11.52 4.971 16.687 7.42-0.913 0.41-1.856 0.823-2.837 1.237-17.741 7.569-43.076 15.206-73.553 21.542-60.949 12.663-138.065 19.209-207.889 11.584-69.926-7.633-136.981-30.336-183.878-69.325-45.46-37.798-73.675-92.066-66.481-169.822l0.136-1.472v-1.476zM836.463 553.348l-0.073-0.081c0 0 0.009 0.009 0.030 0.034 0.009 0.013 0.026 0.030 0.043 0.047z","M195.856 502.468c7.496-11.255 16.26-22.259 26.436-32.589 0.876 31.744 6.169 61.227 15.216 88.358-15.094 30.878-18.374 59.315-18.374 65.357v0.188c0 11.379 0 17.532 3.524 30.699 3.993 14.916 12.441 38.212 30.867 82.022 5.256 12.497 2.48 24.098-0.985 31.428-3.249 6.874-7.925 12.058-11.511 15.514-7.319 7.057-16.852 13.257-25.751 18.33-5.008 2.854-11.334 5.705-16.546 8.026 11.182 3.942 24.979 7.817 40.802 11.226 44.977 9.694 101.833 14.673 153.062 8.87 51.282-5.807 99.777-23.014 133.351-51.964l0.606-0.525c14.797 2.782 29.53 4.937 44.053 6.519 10.884 1.19 21.858 2.091 32.875 2.722-10.121 14.797-22.161 28.045-35.742 39.753-46.362 39.974-108.544 60.365-167.943 67.089-59.451 6.729-123.406 0.947-173.745-9.899-25.169-5.427-48.056-12.352-65.901-20.245-8.86-3.917-17.457-8.503-24.686-13.892-6.431-4.791-15.831-13.171-20.001-25.92-6.422-19.631 2.792-35.443 10.458-43.831 7.193-7.872 16.405-13.461 23.248-17.173 7.309-3.968 15.158-7.467 21.234-10.176 6.907-3.076 10.854-4.855 13.183-6.182 1.35-0.768 2.591-1.502 3.727-2.197-13.937-33.886-21.975-56.119-26.479-72.947-5.68-21.222-5.7-33.873-5.7-47.433 0-17.711 7.436-71.138 40.721-121.126zM172.64 797.244c-0.011 0.004 0.084 0.107 0.318 0.303-0.19-0.205-0.306-0.303-0.318-0.303zM196.89 737.084c-0.003 0-0.052 0.051-0.137 0.149l0.112-0.119c0.019-0.021 0.027-0.030 0.025-0.030z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["chat"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":321,"id":124,"name":"chat","prevSize":32,"code":59669},"setIdx":0,"setId":0,"iconIdx":21},{"icon":{"paths":["M883.081 233.251c12.565 12.43 12.676 32.691 0.243 45.254l-474.874 480.001c-6.013 6.076-14.208 9.498-22.758 9.493s-16.742-3.426-22.752-9.506l-165.124-167.091c-12.423-12.57-12.303-32.828 0.268-45.252s32.832-12.305 45.254 0.269l142.376 144.068 452.115-456.993c12.429-12.564 32.691-12.672 45.252-0.243z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["check"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":322,"id":123,"name":"check","prevSize":32,"code":59670},"setIdx":0,"setId":0,"iconIdx":22},{"icon":{"paths":["M310.004 393.373c12.497-12.497 32.758-12.497 45.255 0l185.375 185.371 185.37-185.371c12.497-12.497 32.759-12.497 45.257 0s12.497 32.758 0 45.254l-208 208c-12.497 12.497-32.759 12.497-45.257 0l-207.999-208c-12.497-12.495-12.497-32.757 0-45.254z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["chevron-down"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":323,"id":122,"name":"chevron-down","prevSize":32,"code":59671},"setIdx":0,"setId":0,"iconIdx":23},{"icon":{"paths":["M663.77 281.373c12.497 12.497 12.497 32.758 0 45.255l-185.374 185.373 185.374 185.374c12.497 12.497 12.497 32.755 0 45.252s-32.759 12.497-45.257 0l-208-208c-12.497-12.497-12.497-32.755 0-45.252l208-208.001c12.497-12.497 32.759-12.497 45.257 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["chevron-left"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":324,"id":121,"name":"chevron-left","prevSize":32,"code":59672},"setIdx":0,"setId":0,"iconIdx":24},{"icon":{"paths":["M428.77 742.626c-12.498-12.497-12.498-32.755 0-45.252l185.37-185.374-185.37-185.373c-12.498-12.497-12.498-32.758 0-45.255 12.497-12.497 32.755-12.497 45.252 0l208 208.001c12.497 12.497 12.497 32.755 0 45.252l-208 208c-12.497 12.497-32.755 12.497-45.252 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["chevron-right"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":325,"id":120,"name":"chevron-right","prevSize":32,"code":59673},"setIdx":0,"setId":0,"iconIdx":25},{"icon":{"paths":["M773.513 630.626c-12.497 12.497-32.759 12.497-45.257 0l-185.37-185.37-185.373 185.37c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l207.998-208.001c12.497-12.497 32.759-12.497 45.257 0l208 208.001c12.497 12.497 12.497 32.755 0 45.252z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["chevron-up"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":326,"id":119,"name":"chevron-up","prevSize":32,"code":59674},"setIdx":0,"setId":0,"iconIdx":26},{"icon":{"paths":["M538.321 864c194.406 0 352-157.598 352-352 0-46.519-9.024-90.932-25.417-131.582l48.516-48.518c26.214 54.496 40.9 115.584 40.9 180.1 0 229.751-186.249 416-416 416-229.75 0-416-186.249-416-416s186.25-416 416-416c95.377 0 183.253 32.096 253.423 86.076l-45.709 45.712c-58.223-42.623-130.031-67.788-207.714-67.788-194.404 0-352 157.596-352 352 0 194.402 157.596 352 352 352zM928.951 230.624c12.497-12.499 12.493-32.76-0.004-45.255-12.501-12.495-32.764-12.491-45.257 0.008l-345.387 345.504-105.34-105.491c-12.487-12.506-32.748-12.52-45.254-0.032-12.506 12.489-12.52 32.747-0.032 45.253l127.97 128.158c6.003 6.007 14.144 9.387 22.635 9.387 8.495 0.004 16.64-3.371 22.643-9.374l368.026-368.156z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["circle-check"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":327,"id":118,"name":"circle-check","prevSize":32,"code":59675},"setIdx":0,"setId":0,"iconIdx":27},{"icon":{"paths":["M501.884 229.047c19.767-23.931 49.89-36.827 80.849-34.615l143.936 10.281c42.052 3.004 77.222 33.091 86.703 74.17l30.349 131.517c6.643 28.785-0.337 59.028-18.923 81.991l-252.369 311.744c-11.119 13.739-31.27 15.859-45.005 4.74-13.734-11.123-15.859-31.27-4.736-45.009l252.365-311.744c6.195-7.654 8.521-17.737 6.306-27.331l-30.349-131.517c-3.157-13.693-14.882-23.722-28.898-24.723l-143.936-10.281c-10.321-0.737-20.361 3.561-26.953 11.538l-265.998 322c-5.439 6.583-8.020 15.066-7.171 23.565l7.581 75.81c1.636 16.358 15.401 28.817 31.841 28.817h104.305c9.44 0 18.396-4.169 24.476-11.388l227.597-270.268-10.052-70.344h-69.257l-230.406 276.488c-11.314 13.577-31.492 15.411-45.069 4.096s-15.411-31.492-4.097-45.069l230.403-276.487c12.16-14.592 30.174-23.028 49.169-23.028h69.257c31.851 0 58.854 23.419 63.36 54.949l10.048 70.345c2.577 18.044-2.662 36.331-14.404 50.274l-227.593 270.268c-18.24 21.662-45.116 34.163-73.432 34.163h-104.305c-49.32 0-90.616-37.372-95.523-86.447l-7.581-75.814c-2.549-25.489 5.196-50.944 21.511-70.694l266-321.997z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["clip"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":328,"id":117,"name":"clip","prevSize":32,"code":59676},"setIdx":0,"setId":0,"iconIdx":28},{"icon":{"paths":["M629.756 192c0-53.019-42.978-96-96-96-53.018 0-96 42.981-96 96h-191.999c-17.673 0-32 14.327-32 32v672c0 17.673 14.327 32 32 32h575.999c17.673 0 32-14.327 32-32v-672c0-17.673-14.327-32-32-32h-192zM277.757 864v-608h96v64c0 17.673 14.327 32 32 32h255.999c17.673 0 32-14.327 32-32v-64h96v608h-511.999zM533.756 224c17.673 0 32-14.327 32-32s-14.327-32-32-32c-17.673 0-32 14.327-32 32s14.327 32 32 32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Clipboard"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":329,"id":116,"name":"Clipboard","prevSize":32,"code":59677},"setIdx":0,"setId":0,"iconIdx":29},{"icon":{"paths":["M901.594 512c0 194.402-157.594 352-352 352-194.404 0-352-157.598-352-352 0-194.404 157.596-352 352-352 194.406 0 352 157.596 352 352zM965.594 512c0-229.751-186.249-416-416-416-229.75 0-416 186.249-416 416s186.25 416 416 416c229.751 0 416-186.249 416-416zM581.594 288c0-17.673-14.327-32-32-32s-32 14.327-32 32v224c0 8.486 3.371 16.627 9.374 22.626l96 96c12.497 12.497 32.755 12.497 45.252 0s12.497-32.755 0-45.252l-86.626-86.63v-210.743z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["clock"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":330,"id":115,"name":"clock","prevSize":32,"code":59678},"setIdx":0,"setId":0,"iconIdx":30},{"icon":{"paths":["M285.923 356.674c6.747-28.299 25.696-52.006 51.209-67.153 25.601-15.2 56.323-20.858 84.699-14.531 27.64 6.163 55.113 24.12 74.872 60.34l22.541 41.324 30.135-36.161c27.238-32.687 85.129-39.712 134.716-14.063 23.561 12.187 42.206 30.617 52.062 53.489 9.655 22.406 12.109 51.898-1.434 89.15l-15.616 42.935h45.687c53.606 0 82.419 15.881 97.638 33.749 15.654 18.377 21.897 44.651 18.556 74.718-3.341 30.080-16.051 60.514-33.455 82.889-17.937 23.066-36.646 32.644-50.739 32.644h-544c-18.791 0-37.068-10.359-52.195-31.578-15.217-21.342-24.977-51.051-25.818-81.31-0.84-30.229 7.237-57.916 23.733-77.495 15.796-18.743 42.268-33.617 86.279-33.617h59.792l-33.166-49.749c-27.882-41.826-32.117-77.816-25.498-105.581zM531.012 272.079c-26.342-32.073-59.665-51.619-95.253-59.554-45.623-10.174-92.901-0.833-131.299 21.965-38.487 22.85-69.538 60.142-80.791 107.342-8.278 34.72-5.369 72.759 10.731 111.77-35.67 8.465-64.099 26.185-84.825 50.782-29.004 34.423-39.927 78.733-38.766 120.508 1.159 41.737 14.399 84.032 37.682 116.689 23.373 32.781 59.096 58.423 104.305 58.423h544c41.907 0 77.201-26.419 101.261-57.353 24.597-31.629 41.886-73.199 46.545-115.115 4.659-41.933-3.098-87.659-33.446-123.285-24.107-28.297-59.503-46.771-105.617-53.453 5.833-35.196 1.69-67.676-10.603-96.207-16.644-38.627-47.002-67.196-81.438-85.009-54.903-28.397-128.734-32.652-182.485 2.495zM524.796 437.329c17.673 0 32 14.323 32 32v53.325h53.333c17.673 0 32 14.327 32 32s-14.327 32-32 32h-53.333v53.342c0 17.673-14.327 32-32 32s-32-14.327-32-32v-53.342h-53.333c-17.673 0-32-14.327-32-32s14.327-32 32-32h53.333v-53.325c0-17.677 14.327-32 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["cloud_Plus"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":331,"id":114,"name":"cloud_Plus","prevSize":32,"code":59679},"setIdx":0,"setId":0,"iconIdx":31},{"icon":{"paths":["M515.776 928c-14.217 0-28.275-0.713-42.142-2.112-16.695-1.681-30.558-12.531-36.689-27.392l-40.54-98.308-98.161 40.841c-14.837 6.174-32.3 4.045-45.292-6.554-21.839-17.818-41.831-37.811-59.65-59.648-10.601-12.992-12.726-30.455-6.553-45.295l40.839-98.159-98.307-40.542c-14.864-6.127-25.713-19.994-27.395-36.689-1.396-13.867-2.111-27.925-2.111-42.142s0.714-28.275 2.11-42.142c1.681-16.695 12.531-30.558 27.395-36.685l98.308-40.543-40.84-98.163c-6.173-14.836-4.047-32.3 6.553-45.292 17.818-21.838 37.81-41.83 59.648-59.648 12.992-10.601 30.455-12.726 45.292-6.554l98.163 40.84 40.54-98.309c6.131-14.865 19.994-25.714 36.689-27.395 13.867-1.396 27.925-2.111 42.142-2.111s28.275 0.714 42.142 2.111c16.695 1.681 30.558 12.53 36.689 27.395l40.542 98.309 98.163-40.84c14.835-6.173 32.299-4.047 45.291 6.554 21.837 17.818 41.83 37.81 59.648 59.648 10.598 12.992 12.723 30.455 6.554 45.292l-40.841 98.163 98.308 40.543c14.861 6.127 25.711 19.994 27.392 36.685 1.399 13.867 2.112 27.925 2.112 42.142s-0.713 28.275-2.112 42.142c-1.681 16.695-12.531 30.562-27.392 36.689l-98.308 40.542 40.841 98.159c6.17 14.839 4.045 32.303-6.554 45.295-17.822 21.837-37.811 41.83-59.652 59.648-12.992 10.598-30.455 12.727-45.291 6.554l-98.159-40.841-40.542 98.308c-6.131 14.861-19.994 25.711-36.689 27.392-13.867 1.399-27.925 2.112-42.142 2.112zM448.23 757.982l43.383 105.203c7.979 0.542 16.034 0.815 24.162 0.815s16.183-0.273 24.162-0.815l43.383-105.203c9.455-22.921 35.733-33.805 58.628-24.282l105.054 43.708c12.156-10.598 23.578-22.020 34.18-34.176l-43.708-105.058c-9.527-22.895 1.357-49.173 24.282-58.624l105.203-43.383c0.542-7.983 0.815-16.038 0.815-24.166 0-8.124-0.273-16.183-0.815-24.162l-105.203-43.383c-22.925-9.455-33.809-35.731-24.282-58.625l43.708-105.058c-10.603-12.156-22.020-23.577-34.176-34.177l-105.058 43.709c-22.895 9.525-49.173-1.359-58.628-24.283l-43.383-105.204c-7.979-0.54-16.038-0.815-24.162-0.815s-16.183 0.275-24.162 0.815l-43.383 105.204c-9.455 22.924-35.732 33.809-58.627 24.283l-105.058-43.709c-12.155 10.6-23.577 22.022-34.177 34.177l43.709 105.058c9.525 22.895-1.359 49.17-24.283 58.625l-105.203 43.383c-0.54 7.979-0.815 16.038-0.815 24.162 0 8.128 0.275 16.183 0.815 24.166l105.202 43.383c22.924 9.451 33.809 35.729 24.283 58.624l-43.708 105.058c10.601 12.156 22.022 23.578 34.179 34.176l105.056-43.708c22.895-9.523 49.172 1.361 58.627 24.282zM419.776 512c0-53.018 42.982-96 96-96s96 42.982 96 96c0 53.018-42.982 96-96 96s-96-42.982-96-96zM515.776 352c-88.367 0-160 71.634-160 160 0 88.367 71.633 160 160 160s160-71.633 160-160c0-88.366-71.633-160-160-160z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["cog"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":332,"id":113,"name":"cog","prevSize":32,"code":59680},"setIdx":0,"setId":0,"iconIdx":32},{"icon":{"paths":["M470.033 272c-35.349 0-64.002 28.654-64.002 64v480c0 35.345 28.652 64 64.002 64h352c35.345 0 64-28.655 64-64v-304c0-6.511-1.988-12.864-5.692-18.214l-134.455-194.215c-11.955-17.267-31.62-27.57-52.621-27.57h-223.232zM470.033 336h144v144c0 35.345 28.651 64 64 64h144v272h-352v-480zM678.033 480v-144h15.232l99.691 144h-114.923zM150.031 208c0-35.346 28.654-64 64-64h241.845c18.031 0 35.226 7.607 47.356 20.949l39.138 43.051h-328.339v480h128v64h-128c-35.346 0-64-28.655-64-64v-480z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["copy"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":333,"id":112,"name":"copy","prevSize":32,"code":59681},"setIdx":0,"setId":0,"iconIdx":33},{"icon":{"paths":["M225.083 181.328c-53.019 0-96 42.98-96 96v469.334c0 53.018 42.981 96 96 96h640c53.018 0 96-42.982 96-96v-469.334c0-53.019-42.982-96-96-96h-640zM193.083 277.328c0-17.673 14.327-32 32-32h640c17.673 0 32 14.327 32 32v202.672h-704v-202.672zM193.083 544h704v202.662c0 17.673-14.327 32-32 32h-640c-17.673 0-32-14.327-32-32v-202.662zM843.75 661.329c0-35.349-28.655-64-64-64-35.349 0-64 28.651-64 64 0 35.345 28.651 64 64 64 35.345 0 64-28.655 64-64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["creditcard"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":334,"id":111,"name":"creditcard","prevSize":32,"code":59682},"setIdx":0,"setId":0,"iconIdx":34},{"icon":{"paths":["M826.185 262.627c12.497-12.497 12.497-32.758 0-45.255s-32.755-12.497-45.252 0l-249.374 249.371-249.373-249.371c-12.497-12.497-32.758-12.497-45.255 0s-12.497 32.758 0 45.255l249.371 249.373-249.371 249.374c-12.497 12.497-12.497 32.755 0 45.252s32.758 12.497 45.255 0l249.373-249.37 249.374 249.37c12.497 12.497 32.755 12.497 45.252 0s12.497-32.755 0-45.252l-249.37-249.374 249.37-249.373z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Cross"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":335,"id":110,"name":"Cross","prevSize":32,"code":59683},"setIdx":0,"setId":0,"iconIdx":35},{"icon":{"paths":["M511.488 141.563l-298.665 136.533c-11.39 5.207-18.696 16.58-18.696 29.103v386.846c0 11.819 6.513 22.673 16.941 28.233l298.666 159.292c9.412 5.018 20.706 5.018 30.118 0l298.667-159.292c10.428-5.559 16.943-16.414 16.943-28.233v-386.846c0-12.524-7.309-23.896-18.697-29.103l-298.667-136.533c-8.448-3.862-18.159-3.862-26.611 0zM258.128 357.014l234.668 107.276v335.71l-234.668-125.154v-317.832zM556.796 800v-335.71l234.667-107.276v317.832l-234.667 125.154zM524.796 408.548l-221.701-101.348 221.701-101.348 221.696 101.348-221.696 101.348z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["cube"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":336,"id":109,"name":"cube","prevSize":32,"code":59684},"setIdx":0,"setId":0,"iconIdx":36},{"icon":{"paths":["M431.872 256c0-44.183-35.816-80-79.999-80s-80 35.817-80 80c0 44.183 35.817 80 80 80s79.999-35.817 79.999-80zM475.84 288c-14.208 55.207-64.324 96-123.967 96s-109.758-40.793-123.968-96h-89.367c-17.673 0-32-14.327-32-32s14.327-32 32-32h89.367c14.209-55.207 64.325-96 123.968-96s109.759 40.793 123.967 96h430.699c17.673 0 32 14.327 32 32s-14.327 32-32 32h-430.699zM106.539 768c0-17.673 14.327-32 32-32h89.367c14.209-55.206 64.325-96 123.968-96 60.782 0 111.67 42.368 124.743 99.179 4.207-2.035 8.93-3.179 13.922-3.179h416c17.673 0 32 14.327 32 32s-14.327 32-32 32h-416c-4.992 0-9.715-1.143-13.922-3.179-13.073 56.811-63.961 99.179-124.743 99.179-59.643 0-109.758-40.794-123.968-96h-89.367c-17.673 0-32-14.327-32-32zM351.873 848c44.183 0 79.999-35.819 79.999-80s-35.816-80-79.999-80c-44.183 0-80 35.819-80 80s35.817 80 80 80zM806.571 543.757c-14.127 55.33-64.299 96.243-124.032 96.243-59.729 0-109.905-40.913-124.028-96.243-1.301 0.162-2.628 0.243-3.972 0.243h-416c-17.673 0-32-14.327-32-32s14.327-32 32-32h416c1.344 0 2.671 0.081 3.972 0.243 14.123-55.331 64.299-96.243 124.028-96.243 59.733 0 109.905 40.913 124.032 96.243 1.301-0.162 2.624-0.243 3.968-0.243h96c17.673 0 32 14.327 32 32s-14.327 32-32 32h-96c-1.344 0-2.667-0.081-3.968-0.243zM762.539 512c0-44.181-35.819-80-80-80s-80 35.819-80 80c0 44.181 35.819 80 80 80s80-35.819 80-80z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["customize"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":337,"id":108,"name":"customize","prevSize":32,"code":59685},"setIdx":0,"setId":0,"iconIdx":37},{"icon":{"paths":["M738.735 298.663c0-17.673-14.327-32-32-32s-32 14.327-32 32v426.666c0 17.673 14.327 32 32 32s32-14.327 32-32v-426.666z","M536.064 394.671c17.677 0 32 14.327 32 32v298.667c0 17.673-14.323 32-32 32-17.673 0-32-14.327-32-32v-298.667c0-17.673 14.327-32 32-32z","M397.399 554.671c0-17.673-14.327-32-32-32s-32 14.327-32 32v170.667c0 17.677 14.327 32 32 32s32-14.323 32-32v-170.667z","M152.067 199.555v624.888c0 39.518 32.036 71.556 71.555 71.556h624.89c39.518 0 71.556-32.038 71.556-71.556v-624.888c0-39.519-32.038-71.555-71.556-71.555h-624.89c-39.519 0-71.555 32.037-71.555 71.555zM223.622 192h624.89c4.173 0 7.556 3.383 7.556 7.555v624.888c0 4.173-3.383 7.556-7.556 7.556h-624.89c-4.173 0-7.555-3.383-7.555-7.556v-624.888c0-4.173 3.383-7.555 7.555-7.555z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["dashboard"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":338,"id":107,"name":"dashboard","prevSize":32,"code":59686},"setIdx":0,"setId":0,"iconIdx":38},{"icon":{"paths":["M582.033 672c-17.677 0-32 14.327-32 32s14.323 32 32 32h224c17.673 0 32-14.327 32-32v-208c0-17.673-14.327-32-32-32-17.677 0-32 14.327-32 32v130.743l-233.374-233.371c-12.497-12.497-32.759-12.497-45.257 0l-73.371 73.371-169.373-169.371c-12.497-12.497-32.758-12.497-45.255 0s-12.497 32.758 0 45.255l192 191.999c12.497 12.497 32.758 12.497 45.255 0l73.374-73.37 210.743 210.743h-146.743z"],"attrs":[{"fill":"rgb(245, 69, 92)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Decreasing Arrow"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":4}]}},"attrs":[{"fill":"rgb(245, 69, 92)"}],"properties":{"order":339,"id":106,"name":"Decreasing-Arrow","prevSize":32,"code":59687},"setIdx":0,"setId":0,"iconIdx":39},{"icon":{"paths":["M358.638 778.671c-17.673 0-32 14.327-32 32s14.327 32 32 32h341.334c17.673 0 32-14.327 32-32s-14.327-32-32-32h-341.334z","M102.638 298.672c0-70.692 57.307-128 128-128h597.334c70.69 0 128 57.308 128 128v298.666c0 70.694-57.31 128-128 128h-597.334c-70.693 0-128-57.306-128-128v-298.666zM230.638 234.672c-35.346 0-64 28.654-64 64v298.666c0 35.349 28.654 64 64 64h597.334c35.345 0 64-28.655 64-64v-298.666c0-35.346-28.655-64-64-64h-597.334z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["desktop"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":340,"id":105,"name":"desktop","prevSize":32,"code":59688},"setIdx":0,"setId":0,"iconIdx":40},{"icon":{"paths":["M328.285 159.791c0-17.649-14.327-31.958-32-31.958h-64c-17.673 0-32 14.308-32 31.958v63.916c0 17.65 14.327 31.958 32 31.958h64c17.673 0 32-14.308 32-31.958v-63.916zM328.285 585.894c0-17.651-14.327-31.957-32-31.957h-64c-17.673 0-32 14.306-32 31.957v63.915c0 17.651 14.327 31.957 32 31.957h64c17.673 0 32-14.306 32-31.957v-63.915zM456.286 159.791c0-17.649 14.327-31.958 32-31.958h64c17.673 0 32 14.308 32 31.958v63.916c0 17.65-14.327 31.958-32 31.958h-64c-17.673 0-32-14.308-32-31.958v-63.916zM584.286 372.843c0-17.65-14.327-31.958-32-31.958h-64c-17.673 0-32 14.308-32 31.958v63.914c0 17.651 14.327 31.957 32 31.957h64c17.673 0 32-14.306 32-31.957v-63.914zM456.286 585.894c0-17.651 14.327-31.957 32-31.957h64c17.673 0 32 14.306 32 31.957v63.915c0 17.651-14.327 31.957-32 31.957h-64c-17.673 0-32-14.306-32-31.957v-63.915zM584.286 798.946c0-17.651-14.327-31.957-32-31.957h-64c-17.673 0-32 14.306-32 31.957v63.915c0 17.651 14.327 31.957 32 31.957h64c17.673 0 32-14.306 32-31.957v-63.915zM712.286 159.791c0-17.649 14.327-31.958 32-31.958h64c17.673 0 32 14.308 32 31.958v63.916c0 17.65-14.327 31.958-32 31.958h-64c-17.673 0-32-14.308-32-31.958v-63.916zM840.286 372.843c0-17.65-14.327-31.958-32-31.958h-64c-17.673 0-32 14.308-32 31.958v63.914c0 17.651 14.327 31.957 32 31.957h64c17.673 0 32-14.306 32-31.957v-63.914zM712.286 585.894c0-17.651 14.327-31.957 32-31.957h64c17.673 0 32 14.306 32 31.957v63.915c0 17.651-14.327 31.957-32 31.957h-64c-17.673 0-32-14.306-32-31.957v-63.915zM328.285 372.843c0-17.65-14.327-31.958-32-31.958h-64c-17.673 0-32 14.308-32 31.958v63.914c0 17.651 14.327 31.957 32 31.957h64c17.673 0 32-14.306 32-31.957v-63.914z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["dialpad"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":341,"id":104,"name":"dialpad","prevSize":32,"code":59689},"setIdx":0,"setId":0,"iconIdx":41},{"icon":{"paths":["M520.286 96c80.094 0 154.901 22.636 218.377 61.859l-46.746 46.746c-24.742-13.843-51.324-24.785-79.287-32.368 12.169 22.394 23.078 49.096 32.405 79.249l-51.998 51.999c-5.658-22.993-12.169-44.004-19.349-62.666-12.821-33.338-26.522-55.927-38.473-69.070-8.397-9.235-13.431-11.29-14.929-11.698-1.498 0.407-6.532 2.463-14.929 11.698-11.951 13.143-25.651 35.731-38.473 69.070-16.299 42.377-29.175 96.867-36.339 159.182h65.975l-64 63.999h-7.116c-0.116 2.47-0.223 4.949-0.322 7.437l-64.536 64.538c-0.173-7.936-0.261-15.927-0.261-23.974 0-16.23 0.358-32.247 1.053-48h-189.809c-2.14 15.697-3.245 31.718-3.245 48 0 33.28 4.619 65.485 13.251 96h106.984l-64 64h-17.852c2.004 3.921 4.079 7.799 6.223 11.631l-46.746 46.746c-39.223-63.475-61.859-138.283-61.859-218.377 0-229.751 186.25-416 416.001-416zM874.428 293.623l-46.746 46.746c10.56 18.873 19.43 38.819 26.411 59.632h-86.046l-64 63.999h164.992c2.142 15.697 3.247 31.718 3.247 48 0 33.28-4.621 65.485-13.252 96h-183.027c2.799-30.814 4.279-62.959 4.279-96 0-8.047-0.090-16.038-0.26-23.974l-64.538 64.538c-0.751 19.008-2.022 37.517-3.763 55.437h-51.678l-64 64h107.093c-7.373 42.458-17.489 80.081-29.453 111.185-12.821 33.335-26.522 55.923-38.473 69.069-8.397 9.233-13.431 11.29-14.929 11.695-1.498-0.405-6.532-2.462-14.929-11.695-11.951-13.146-25.651-35.733-38.473-69.069-7.181-18.662-13.692-39.676-19.349-62.673l-51.998 52.002c9.327 30.153 20.238 56.853 32.406 79.249-27.966-7.582-54.548-18.526-79.287-32.367l-46.746 46.746c63.347 39.142 137.984 61.769 217.899 61.858h0.956c229.53-0.26 415.522-186.411 415.522-416 0-80.094-22.635-154.903-61.858-218.377zM427.942 172.237c-113.551 30.788-204.311 116.98-241.465 227.764h179.674c10-93.227 32.176-173.254 61.791-227.764zM612.629 851.763c24.397-44.902 43.742-107.119 55.394-179.763h165.879c-44.651 87.347-124.723 153.583-221.274 179.763zM833.66 153.373c12.497-12.497 32.755-12.497 45.252 0s12.497 32.758 0 45.255l-672 671.999c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l672.002-672.001z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["directory-off"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":342,"id":103,"name":"directory-off","prevSize":32,"code":59690},"setIdx":0,"setId":0,"iconIdx":42},{"icon":{"paths":["M870.033 511.326c0 33.237-4.621 65.399-13.252 95.876h-183.031c2.799-30.78 4.284-62.878 4.284-95.876 0-16.209-0.358-32.205-1.054-47.936h189.807c2.138 15.676 3.247 31.676 3.247 47.936zM612.911 463.39c0.738 15.65 1.122 31.646 1.122 47.936 0 33.353-1.604 65.468-4.565 95.876h-182.874c-2.958-30.409-4.562-62.524-4.562-95.876 0-16.29 0.383-32.286 1.12-47.936h189.76zM672.166 399.476c-10.001-93.104-32.175-173.025-61.79-227.464 113.549 30.747 204.309 116.826 241.463 227.464h-179.674zM425.689 172.012c-29.615 54.438-51.791 134.359-61.791 227.464h-179.674c37.154-110.638 127.914-196.717 241.465-227.464zM428.288 399.476c7.164-62.232 20.041-116.651 36.339-158.972 12.826-33.295 26.526-55.853 38.477-68.979 8.397-9.223 13.427-11.276 14.929-11.683 1.498 0.407 6.528 2.46 14.929 11.683 11.951 13.126 25.651 35.684 38.473 68.979 16.299 42.321 29.175 96.739 36.339 158.972h-179.486zM359.085 463.39c-0.696 15.731-1.053 31.727-1.053 47.936 0 32.998 1.481 65.097 4.281 95.876h-183.031c-8.632-30.477-13.251-62.639-13.251-95.876 0-16.26 1.105-32.26 3.245-47.936h189.809zM370.294 671.117c11.652 72.55 30.998 134.682 55.392 179.524-96.549-26.146-176.621-92.292-221.273-179.524h165.881zM518.511 926.775c229.53-0.256 415.522-186.163 415.522-415.45 0-229.447-186.253-415.451-416-415.451-229.752 0-416.002 186.004-416.002 415.451 0 229.291 185.992 415.194 415.524 415.45 0.158 0.004 0.316 0.004 0.478 0.004 0.158 0 0.316 0 0.478-0.004zM610.377 850.641c24.393-44.843 43.742-106.978 55.394-179.524h165.879c-44.655 87.232-124.723 153.378-221.274 179.524zM600.883 671.117c-7.369 42.398-17.485 79.974-29.449 111.036-12.821 33.293-26.522 55.851-38.473 68.979-8.401 9.22-13.431 11.273-14.929 11.682-1.498-0.41-6.532-2.462-14.929-11.682-11.951-13.129-25.651-35.686-38.477-68.979-11.959-31.061-22.080-68.638-29.449-111.036h165.705z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["directory"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":343,"id":102,"name":"directory","prevSize":32,"code":59691},"setIdx":0,"setId":0,"iconIdx":43},{"icon":{"paths":["M901.594 511.326c0-194.147-157.594-351.535-352-351.535-194.404 0-352 157.388-352 351.535 0 194.15 157.596 351.535 352 351.535 194.406 0 352-157.385 352-351.535zM965.594 511.326c0 229.449-186.249 415.454-416 415.454-229.75 0-416-186.005-416-415.454 0-229.447 186.25-415.451 416-415.451 229.751 0 416 186.004 416 415.451zM731.853 570.615l-159.97 155.511c-12.42 12.079-32.218 12.079-44.642 0l-159.968-155.511c-12.664-12.309-12.937-32.542-0.609-45.188 12.327-12.651 32.587-12.924 45.251-0.61l105.65 102.707v-275.987c0-17.65 14.327-31.958 32-31.958s32 14.308 32 31.958v275.987l105.647-102.707c12.668-12.314 32.926-12.041 45.252 0.61 12.326 12.646 12.053 32.879-0.61 45.188z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["download"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":344,"id":101,"name":"download","prevSize":32,"code":59692},"setIdx":0,"setId":0,"iconIdx":44},{"icon":{"paths":["M835.046 154.27c-37.385-39.598-100.237-40.213-138.394-1.354l-487.64 496.646c-12.266 12.493-20.875 28.1-24.894 45.129l-34.767 147.307c-6.682 28.309 17.085 54.537 45.958 50.714l133.245-17.643c20.625-2.731 39.803-12.079 54.648-26.637l507.782-498.004c37.286-36.567 38.434-96.202 2.581-134.174l-58.517-61.983zM742.349 197.665c12.719-12.953 33.673-12.748 46.131 0.451l58.522 61.983c11.947 12.657 11.567 32.536-0.862 44.725l-112.183 110.023-103.428-103.293 111.821-113.889zM585.715 357.193l102.575 102.438-349.932 343.198c-4.948 4.851-11.341 7.97-18.216 8.879l-101.046 13.38 27.316-115.733c1.34-5.675 4.209-10.88 8.298-15.044l331.006-337.118z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["edit"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":345,"id":100,"name":"edit","prevSize":32,"code":59693},"setIdx":0,"setId":0,"iconIdx":45},{"icon":{"paths":["M340.612 644.885c-21.571-19.618-6.007-52.885 23.151-52.885 8.965 0 17.527 3.529 24.272 9.438 21.605 18.918 42.642 31.957 62.704 40.508 36.561 15.59 71.804 17.109 104.794 9.941 37.628-8.179 72.657-27.81 102.106-51.345 6.729-5.376 14.997-8.542 23.607-8.542 30.217 0 45.619 34.257 22.4 53.594-36.915 30.741-82.795 57.591-134.524 68.834-44.796 9.732-93.67 7.629-143.484-13.606-28.791-12.275-57.233-30.656-85.026-55.936z","M410.707 480c35.347 0 63.998-28.655 63.998-64 0-35.346-28.651-64-63.998-64s-64 28.654-64 64c0 35.345 28.654 64 64 64z","M634.705 480c35.349 0 64-28.655 64-64 0-35.346-28.651-64-64-64-35.345 0-64 28.654-64 64 0 35.345 28.655 64 64 64z","M938.539 512c0 229.751-186.249 416-416 416-229.75 0-416-186.249-416-416s186.249-416 416-416c229.751 0 416 186.249 416 416zM874.539 512c0-194.404-157.594-352-352-352-194.404 0-352 157.596-352 352 0 194.402 157.596 352 352 352 194.406 0 352-157.598 352-352z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["emoji"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":346,"id":99,"name":"emoji","prevSize":32,"code":59694},"setIdx":0,"setId":0,"iconIdx":46},{"icon":{"paths":["M352.456 430.882l224.491 224.491-126.118 126.118-224.492-224.491 126.12-126.118zM397.711 385.626l192.117-192.116 224.491 224.49-192.119 192.116-224.489-224.49zM612.454 125.628c-12.497-12.497-32.759-12.497-45.257 0l-408.744 408.747c-12.497 12.497-12.497 32.755 0 45.252l269.744 269.747c5.231 5.231 11.823 8.269 18.633 9.122v0.068h0.572c2.274 0.243 4.574 0.243 6.848 0h440.58c17.673 0 32-14.327 32-32s-14.327-32-32-32h-366.566l353.937-353.937c12.493-12.497 12.493-32.757 0-45.254l-269.747-269.745z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["eraser"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":347,"id":98,"name":"eraser","prevSize":32,"code":59695},"setIdx":0,"setId":0,"iconIdx":47},{"icon":{"paths":["M193.303 96c-17.673 0-32 14.327-32 32v768c0 17.673 14.327 32 32 32h511.998c17.677 0 32-14.327 32-32v-96c0-17.673-14.323-32-32-32-17.673 0-32 14.327-32 32v64h-447.998v-704h447.998v64c0 17.673 14.327 32 32 32 17.677 0 32-14.327 32-32v-96c0-17.673-14.323-32-32-32h-511.998zM919.932 489.374l-160-160.001c-12.497-12.497-32.759-12.497-45.257 0s-12.497 32.758 0 45.255l105.374 105.373h-418.746c-17.673 0-32 14.327-32 32s14.327 32 32 32h418.746l-105.374 105.374c-12.497 12.497-12.497 32.755 0 45.252s32.759 12.497 45.257 0l160-160c12.497-12.497 12.497-32.755 0-45.252z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["exit"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":348,"id":97,"name":"exit","prevSize":32,"code":59696},"setIdx":0,"setId":0,"iconIdx":48},{"icon":{"paths":["M878.182 398.148c-0.188 17.672-14.669 31.847-32.337 31.655-17.673-0.188-31.846-14.666-31.659-32.338l1.318-123.488-193.438 193.437c-12.497 12.497-32.759 12.497-45.257 0s-12.497-32.755 0-45.254l193.442-193.439-123.49 1.319c-17.673 0.189-32.149-13.984-32.341-31.657-0.188-17.672 13.986-32.151 31.659-32.34l201.92-2.156c8.606-0.092 16.883 3.286 22.967 9.37s9.463 14.365 9.374 22.969l-2.159 201.921zM185.6 626.517c0.189-17.673 14.668-31.842 32.34-31.654s31.845 14.669 31.657 32.341l-1.318 123.486 193.438-193.438c12.497-12.497 32.759-12.497 45.257 0s12.497 32.759 0 45.257l-193.44 193.438 123.488-1.318c17.672-0.192 32.153 13.982 32.34 31.654s-13.986 32.154-31.657 32.341l-201.92 2.155c-8.605 0.094-16.884-3.285-22.969-9.37s-9.463-14.366-9.371-22.967l2.156-201.924z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["expand-arrow"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":349,"id":96,"name":"expand-arrow","prevSize":32,"code":59697},"setIdx":0,"setId":0,"iconIdx":49},{"icon":{"paths":["M831.403 153.173c12.497-12.48 32.759-12.48 45.257 0s12.497 32.715 0 45.195l-672.001 671.115c-12.497 12.48-32.758 12.48-45.255 0s-12.497-32.717 0-45.197l671.999-671.113zM113.338 479.424c101.801-153.5 303.397-327.248 541.399-225.142l-49.515 49.446c-56.452-19.184-107.934-19.478-153.318-9.713-114.756 24.688-215.372 118.236-280.423 213.585 38.582 47.94 75.869 86.711 111.715 117.73l-45.303 45.244c-39.632-34.692-80.083-77.333-121.158-129.007-14.229-17.903-16.035-43.089-3.397-62.144zM800.256 349.994l-45.269 45.21c35.499 31.386 72.243 70.857 110.042 119.924-61.466 95.061-158.447 188.433-271.765 213.342-46.69 10.266-100.493 9.719-160.38-11.588l-49.268 49.203c244.34 107.191 442.804-69.069 540.067-223.957 11.657-18.564 9.882-42.598-3.392-60.049-40.439-53.163-80.533-96.801-120.034-132.084zM517.632 346.974c13.687 0 26.999 1.57 39.748 4.534l-203.469 203.201c-3.895-13.82-5.974-28.365-5.974-43.379 0-90.772 75.974-164.356 169.694-164.356zM681.527 468.57l-202.999 202.726c12.553 2.867 25.647 4.386 39.104 4.386 93.717 0 169.694-73.583 169.694-164.352 0-14.793-2.018-29.129-5.798-42.761z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["eye-off"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":350,"id":95,"name":"eye-off","prevSize":32,"code":59698},"setIdx":0,"setId":0,"iconIdx":50},{"icon":{"paths":["M591.010 728.469c-107.23 23.569-251.957-9.865-421.785-220.873 65.051-95.349 165.667-188.897 280.422-213.585 108.169-23.272 250.953 10.59 413.124 221.112-61.461 95.061-158.443 188.433-271.761 213.346zM918.033 482.074c-347.132-456.358-668.857-210.875-806.95-2.654-12.638 19.055-10.832 44.241 3.398 62.144 362.307 455.817 676.142 208.862 806.945 0.559 11.657-18.564 9.882-42.598-3.392-60.049zM621.069 511.326c0-53.641-45.457-100.44-105.694-100.44s-105.693 46.8-105.693 100.44c0 53.636 45.456 100.437 105.693 100.437s105.694-46.801 105.694-100.437zM685.069 511.326c0 90.769-75.972 164.352-169.694 164.352-93.718 0-169.693-73.583-169.693-164.352 0-90.772 75.975-164.356 169.693-164.356 93.722 0 169.694 73.584 169.694 164.356z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["eye"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":351,"id":94,"name":"eye","prevSize":32,"code":59699},"setIdx":0,"setId":0,"iconIdx":51},{"icon":{"paths":["M172.794 256c0-17.673 14.327-32 32-32h640.001c17.673 0 32 14.327 32 32s-14.327 32-32 32h-640.001c-17.673 0-32-14.327-32-32zM172.794 421.161c0-17.673 14.327-32 32-32h640.001c17.673 0 32 14.327 32 32s-14.327 32.001-32 32.001h-640.001c-17.673 0-32-14.327-32-32.001zM172.794 602.837c0-17.673 14.327-32 32-32h640.001c17.673 0 32 14.327 32 32s-14.327 32-32 32h-640.001c-17.673 0-32-14.327-32-32zM172.794 768c0-17.673 14.327-32 32-32h344.616c17.673 0 32 14.327 32 32s-14.327 32-32 32h-344.616c-17.673 0-32-14.327-32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["File-doc"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":352,"id":93,"name":"File-doc","prevSize":32,"code":59700},"setIdx":0,"setId":0,"iconIdx":52},{"icon":{"paths":["M899.776 572.574h-269.013l-250.606-423.241h269.063l250.556 423.241zM362.605 190.906l134.483 238.078-230.78 408.354-134.532-237.922 230.829-408.51zM442.718 615.979h455.706l-134.532 258.688h-465.642l144.468-258.688z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["File-GoogleDrive"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":353,"id":92,"name":"File-GoogleDrive","prevSize":32,"code":59701},"setIdx":0,"setId":0,"iconIdx":53},{"icon":{"paths":["M541.619 128c200.294 0 362.667 162.371 362.667 362.667h-362.667v-362.667z","M136.285 533.333c0-200.295 162.371-362.667 362.668-362.667v362.667h362.667c0 200.294-162.372 362.667-362.667 362.667-200.296 0-362.668-162.372-362.668-362.667z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["File-Keynote"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":354,"id":91,"name":"File-Keynote","prevSize":32,"code":59702},"setIdx":0,"setId":0,"iconIdx":54},{"icon":{"paths":["M886.575 567.625c-41.856-41.139-161.237-29.828-220.928-22.285-59.004-35.998-98.458-85.705-126.242-158.727 13.376-55.195 34.645-139.187 18.522-191.982-14.404-89.82-129.673-80.907-146.138-20.227-15.095 55.194-1.372 131.987 24.014 230.035-34.305 81.935-85.42 191.981-121.441 255.059-68.611 35.311-161.235 89.822-174.957 158.387-11.321 54.165 89.194 189.239 261.063-106.961 76.845-25.37 160.548-56.567 234.647-68.907 64.836 34.965 140.651 58.278 191.424 58.278 87.479 0 96.055-96.674 60.036-132.672zM206.985 834.342c17.495-46.967 84.048-101.133 104.288-119.991-65.18 103.876-104.288 122.389-104.288 119.991zM486.916 180.918c25.387 0 22.985 110.047 6.174 139.872-15.091-47.653-14.75-139.872-6.174-139.872zM403.212 649.216c33.277-57.937 61.748-126.844 84.733-187.524 28.476 51.767 64.836 93.248 103.262 121.702-71.356 14.741-133.449 44.911-187.995 65.822zM854.669 632.077c0 0-17.152 20.57-127.957-26.743 120.41-8.913 140.309 18.513 127.957 26.743z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["File-pdf"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":355,"id":90,"name":"File-pdf","prevSize":32,"code":59703},"setIdx":0,"setId":0,"iconIdx":55},{"icon":{"paths":["M143.105 192.005c-17.673 0-32 14.327-32 32v576.020c0 17.673 14.327 32 32 32h767.999c17.677 0 32-14.327 32-32v-576.020c0-17.673-14.323-32-32-32h-767.999zM175.105 378.307v-122.302h149.334v122.302h-149.334zM175.105 442.308h149.334v141.722h-149.334v-141.722zM175.105 648.030h149.334v119.996h-149.334v-119.996zM388.439 768.026v-119.996h490.665v119.996h-490.665zM879.104 584.030h-490.665v-141.722h490.665v141.722zM879.104 378.307h-490.665v-122.302h490.665v122.302z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["File-sheets"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":356,"id":89,"name":"File-sheets","prevSize":32,"code":59704},"setIdx":0,"setId":0,"iconIdx":56},{"icon":{"paths":["M390.031 149.138c0-11.766 9.551-21.305 21.333-21.305h85.335c11.78 0 21.333 9.539 21.333 21.305v106.526h-106.668c-11.782 0-21.333-9.539-21.333-21.305v-85.221z","M518.033 255.665h106.667c11.78 0 21.333 9.539 21.333 21.305v85.221c0 11.767-9.553 21.305-21.333 21.305h-106.667v-127.831z","M390.031 404.801c0-11.767 9.551-21.305 21.333-21.305h106.668v127.83h-106.668c-11.782 0-21.333-9.536-21.333-21.303v-85.222z","M518.033 511.326h106.667c11.78 0 21.333 9.54 21.333 21.308v106.526h-128v-127.834z","M432.7 639.159h213.333v213.052c0 23.531-19.106 42.611-42.667 42.611h-170.667c-23.566 0-42.668-19.081-42.668-42.611v-170.445c0-23.531 19.102-42.607 42.668-42.607zM496.7 724.378c-11.785 0-21.333 9.54-21.333 21.308v42.607c0 11.767 9.549 21.308 21.333 21.308h42.667c11.78 0 21.333-9.54 21.333-21.308v-42.607c0-11.767-9.553-21.308-21.333-21.308h-42.667z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["file-zip"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":357,"id":88,"name":"file-zip","prevSize":32,"code":59705},"setIdx":0,"setId":0,"iconIdx":57},{"icon":{"paths":["M147.558 351.536c0-17.649 14.327-31.958 32-31.958h704c17.673 0 32 14.308 32 31.958s-14.327 31.958-32 31.958h-704c-17.673 0-32-14.308-32-31.958zM232.892 521.98c0-17.651 14.327-31.957 32-31.957h533.333c17.673 0 32 14.306 32 31.957s-14.327 31.957-32 31.957h-533.333c-17.673 0-32-14.31-32-31.957zM350.225 660.459c-17.673 0-32 14.31-32 31.957 0 17.651 14.327 31.962 32 31.962h362.667c17.673 0 32-14.31 32-31.962 0-17.647-14.327-31.957-32-31.957h-362.667z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["filter"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":358,"id":87,"name":"filter","prevSize":32,"code":59706},"setIdx":0,"setId":0,"iconIdx":58},{"icon":{"paths":["M649.412 896c-2.803 0-5.295-0.623-7.168-0.939-61.999-16.858-102.814-39.646-145.813-80.858-55.147-54.007-85.368-125.815-85.368-202.3 0-65.873 56.705-119.573 126.495-119.573 69.794 0 126.498 53.7 126.498 119.573 0 34.965 31.467 63.373 69.79 63.373s69.794-28.407 69.794-63.373c0-135.808-119.642-246.636-266.705-246.636-104.998 0-200.337 57.132-243.333 145.793-14.332 29.35-21.498 63.066-21.498 100.843 0 28.719 2.493 73.365 24.925 131.746 2.804 7.181 2.493 14.673-0.623 21.854-3.116 6.865-9.036 11.861-16.202 14.357-2.804 1.25-6.231 1.562-9.658 1.562-11.84 0-22.433-7.181-26.483-18.108-19.006-50.261-28.353-99.9-28.353-151.727 0-46.204 9.036-88.35 26.795-125.5 52.343-108.020 167.935-177.64 294.43-177.64 178.53 0 323.721 135.805 323.721 302.828 0 65.873-56.704 119.573-126.81 119.573-70.101 0-126.805-53.7-126.805-119.573 0-34.965-31.471-63.373-69.794-63.373-38.635 0-69.79 28.407-69.79 63.373 0 61.504 24.303 119.262 68.544 162.342 35.209 34.031 68.86 53.073 120.58 67.123 7.164 1.873 13.397 6.554 17.135 13.111s4.672 14.362 2.803 21.231c-2.803 11.861-14.020 20.915-27.106 20.915zM453.124 888.196c-7.791 0-15.266-3.123-20.254-8.742-33.336-32.781-51.718-54.012-77.89-100.527-26.795-47.142-41.127-105.212-41.127-167.339 0-116.446 100.948-211.354 224.954-211.354 124.002 0 224.951 94.908 224.951 211.354 0 15.612-12.463 28.1-28.352 28.1-15.893 0-28.668-12.177-28.668-28.1 0-85.538-75.396-155.157-168.243-155.157-92.851 0-168.249 69.619-168.249 155.157 0 52.45 11.84 100.527 34.272 139.554 23.367 41.519 38.945 59.004 68.858 88.661 10.901 11.238 10.901 28.723 0 39.65-5.922 5.931-13.086 8.742-20.254 8.742zM726.059 818.889c-47.36 0-88.798-11.866-123.383-34.965-59.196-39.65-94.716-103.962-94.716-172.335 0-15.607 12.463-28.096 28.352-28.096 15.893 0 28.356 12.489 28.356 28.096 0 49.643 26.172 96.781 69.79 125.504 25.237 16.858 55.147 24.977 91.601 24.977 7.787 0 22.434-0.939 38.012-3.746 1.557-0.311 3.426-0.311 4.983-0.311 13.709 0 25.237 9.988 27.729 23.411 1.246 7.181-0.311 14.673-4.361 20.608-4.361 6.242-10.906 10.611-18.697 11.861-23.364 4.685-43.93 4.996-47.667 4.996zM215.087 435.823c-5.609 0-11.217-1.562-16.202-4.992-6.543-4.062-10.593-10.616-12.151-18.109-1.246-7.493 0.311-14.985 4.985-21.229 38.634-53.698 87.862-95.844 146.125-125.502 60.133-30.595 129.612-46.829 200.963-46.829 71.036 0 140.203 15.922 200.026 46.205 58.573 29.658 107.802 71.493 146.125 124.566 4.361 5.932 6.229 13.425 4.983 20.917s-5.606 14.049-11.84 18.42c-4.983 3.435-10.59 4.992-16.512 4.992-9.037 0-17.758-4.369-23.057-11.861-33.335-45.893-75.708-82.107-125.559-107.083-52.343-26.224-112.789-40.273-174.477-40.273-62.315 0-122.76 14.049-175.103 40.585-49.851 25.912-92.536 62.127-126.185 108.644-3.739 6.869-12.463 11.55-22.121 11.55zM760.017 239.142c-4.672 0-9.344-1.249-13.397-3.434-71.347-35.902-133.35-51.512-207.501-51.512-74.466 0-144.258 17.483-207.818 51.825-4.050 2.185-8.724 3.122-13.397 3.122-10.282 0-19.629-5.62-24.925-14.361-3.739-6.556-4.674-14.361-2.493-21.542s7.166-13.424 13.709-16.858c72.595-38.712 151.732-58.38 234.924-58.38 82.564 0 154.846 17.795 233.984 58.068 6.857 3.434 11.84 9.366 14.332 16.858 2.185 7.18 1.25 14.673-2.18 21.229-4.983 9.053-14.643 14.985-25.237 14.985z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["fingerprint"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":359,"id":86,"name":"fingerprint","prevSize":32,"code":59707},"setIdx":0,"setId":0,"iconIdx":59},{"icon":{"paths":["M292.988 170.667c0-17.673 14.327-32 32-32h500.62c12.122 0 23.202 6.848 28.625 17.689 5.419 10.841 4.25 23.814-3.025 33.511l-122.133 162.845 122.133 162.843c7.275 9.698 8.444 22.673 3.025 33.51-5.423 10.842-16.503 17.69-28.625 17.69h-468.62v286.579c0 17.673-14.327 32-32 32s-32-14.327-32-32v-682.667zM356.988 502.754h404.62l-98.133-130.843c-8.533-11.378-8.533-27.023 0-38.4l98.133-130.845h-404.62v300.087z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["flag"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":360,"id":85,"name":"flag","prevSize":32,"code":59708},"setIdx":0,"setId":0,"iconIdx":60},{"icon":{"paths":["M158.225 213.333c0-17.673 14.327-32 32-32h234.057c7.184 0 14.156 2.416 19.796 6.86l88.815 69.94h339.998c17.673 0 32 14.327 32 32v520.533c0 17.673-14.327 32-32 32h-682.667c-17.673 0-32-14.327-32-32v-597.333zM222.225 245.333v533.333h618.667v-456.533h-319.087c-7.181 0-14.153-2.416-19.797-6.86l-88.812-69.94h-190.97z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["folder"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":361,"id":84,"name":"folder","prevSize":32,"code":59709},"setIdx":0,"setId":0,"iconIdx":61},{"icon":{"paths":["M374.031 544c0-17.673-14.327-32-32-32s-32 14.327-32 32v32h-32c-17.673 0-32 14.327-32 32s14.327 32 32 32h32v32c0 17.673 14.327 32 32 32s32-14.327 32-32v-32h32c17.673 0 32.002-14.327 32.002-32s-14.329-32-32.002-32h-32v-32z","M750.033 624c30.925 0 56-25.071 56-56s-25.075-56-56-56c-30.929 0-56 25.071-56 56s25.071 56 56 56z","M678.033 664c0 30.929-25.075 56-56 56-30.929 0-56-25.071-56-56s25.071-56 56-56c30.925 0 56 25.071 56 56z","M710.033 128c0-17.673-14.327-32-32-32-17.677 0-32 14.327-32 32v96h-128c-17.677 0-32 14.327-32 32v96h-192.002c-106.039 0-192 85.961-192 192v128c0 106.039 85.961 192 192 192h448.002c106.035 0 192-85.961 192-192v-128c0-106.039-85.965-192-192-192h-192v-64h128c17.673 0 32-14.327 32-32v-128zM870.033 544v128c0 70.694-57.31 128-128 128h-448.002c-70.693 0-128-57.306-128-128v-128c0-70.694 57.307-128 128-128h448.002c70.69 0 128 57.306 128 128z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["game"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":362,"id":83,"name":"game","prevSize":32,"code":59710},"setIdx":0,"setId":0,"iconIdx":62},{"icon":{"paths":["M143.049 272c0-17.673 14.327-32 32-32h703.999c17.673 0 32 14.327 32 32s-14.327 32-32 32h-703.999c-17.673 0-32-14.327-32-32zM303.049 432c0 17.673-14.327 32-32 32s-32-14.327-32-32c0-17.673 14.327-32 32-32s32 14.327 32 32zM303.049 752c0 17.673-14.327 32-32 32s-32-14.327-32-32c0-17.673 14.327-32 32-32s32 14.327 32 32zM463.049 624c17.673 0 32-14.327 32-32s-14.327-32-32-32c-17.673 0-32 14.327-32 32s14.327 32 32 32zM399.049 400c-17.673 0-32 14.327-32 32s14.327 32 32 32h479.999c17.673 0 32-14.327 32-32s-14.327-32-32-32h-479.999zM367.049 752c0-17.673 14.327-32 32-32h479.999c17.673 0 32 14.327 32 32s-14.327 32-32 32h-479.999c-17.673 0-32-14.327-32-32zM591.049 560c-17.673 0-32 14.327-32 32s14.327 32 32 32h288c17.673 0 32-14.327 32-32s-14.327-32-32-32h-288z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["group-by-type"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":363,"id":82,"name":"group-by-type","prevSize":32,"code":59711},"setIdx":0,"setId":0,"iconIdx":63},{"icon":{"paths":["M579.776 352c-17.673 0-32-14.327-32-32s14.327-32 32-32h224c17.673 0 32 14.327 32 32v208c0 17.673-14.327 32-32 32s-32-14.327-32-32v-130.745l-233.374 233.371c-12.497 12.497-32.755 12.497-45.252 0l-73.374-73.37-169.373 169.37c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l192-192c12.497-12.497 32.756-12.497 45.254 0l73.374 73.37 210.743-210.743h-146.743z"],"attrs":[{"fill":"rgb(45, 224, 165)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Growing Arrow"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":2}]}},"attrs":[{"fill":"rgb(45, 224, 165)"}],"properties":{"order":364,"id":81,"name":"Growing-Arrow","prevSize":32,"code":59712},"setIdx":0,"setId":0,"iconIdx":64},{"icon":{"paths":["M371.339 128c17.673 0 32 14.327 32 32v144h287.998v-144c0-17.673 14.327-32 32-32 17.677 0 32 14.327 32 32v144h144c17.677 0 32 14.327 32 32s-14.323 32-32 32h-144v288h144c17.677 0 32 14.327 32 32s-14.323 32-32 32h-144v144c0 17.673-14.323 32-32 32-17.673 0-32-14.327-32-32v-144h-287.998v144c0 17.673-14.327 32-32 32s-32-14.327-32-32v-144h-144c-17.673 0-32-14.327-32-32s14.327-32 32-32h144v-288h-144c-17.673 0-32-14.327-32-32s14.327-32 32-32h144v-144c0-17.673 14.327-32 32-32zM403.339 368v288h287.998v-288h-287.998z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["hash"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":365,"id":80,"name":"hash","prevSize":32,"code":59713},"setIdx":0,"setId":0,"iconIdx":65},{"icon":{"paths":["M954.321 512c0 229.751-186.249 416-416 416-229.75 0-416-186.249-416-416s186.25-416 416-416c229.751 0 416 186.249 416 416zM594.108 859.605l-41.83-156.105c-4.608 0.333-9.263 0.499-13.956 0.499-4.57 0-9.101-0.158-13.594-0.474l-41.835 156.134c18.057 2.854 36.57 4.339 55.428 4.339 18.982 0 37.615-1.502 55.787-4.395zM462.511 688.452c-47.551-20.459-85.181-59.571-103.676-108.126l-155.029 41.54c33.968 103.484 114.617 185.805 217.045 222.054l41.66-155.469zM186.321 512c0 16.090 1.079 31.927 3.17 47.445l156.905-42.044c-0.049-1.796-0.075-3.597-0.075-5.402 0-4.911 0.184-9.779 0.547-14.596l-156.051-41.813c-2.959 18.368-4.496 37.21-4.496 56.41zM419.926 180.407c-99.159 35.408-177.785 114.033-213.196 213.191l155.535 41.675c19.357-44.352 54.982-79.977 99.337-99.331l-41.676-155.535zM538.321 160c-19.196 0-38.037 1.537-56.401 4.495l41.813 156.051c4.817-0.361 9.681-0.546 14.588-0.546 5.030 0 10.018 0.194 14.95 0.573l41.805-156.022c-18.475-2.995-37.431-4.552-56.755-4.552zM656.128 843.802c102.66-36.45 183.394-119.194 217.097-223.121l-154.974-41.523c-18.291 48.981-56.013 88.491-103.787 109.15l41.664 155.494zM887.317 558.199c1.98-15.121 3.004-30.541 3.004-46.199 0-18.769-1.468-37.197-4.297-55.172l-156.16 41.843c0.303 4.403 0.457 8.849 0.457 13.329 0 1.378-0.013 2.752-0.043 4.122l157.039 42.078zM870.332 394.775c-35.166-99.601-113.886-178.641-213.278-214.248l-41.681 155.559c44.582 19.556 80.311 55.564 99.503 100.343l155.456-41.653zM666.321 512c0-70.694-57.306-128-128-128-70.69 0-128 57.306-128 128s57.309 128 128 128c70.694 0 128-57.306 128-128z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["help"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":366,"id":79,"name":"help","prevSize":32,"code":59714},"setIdx":0,"setId":0,"iconIdx":66},{"icon":{"paths":["M860.578 512c0 176.73-143.27 320-320 320-176.733 0-320.001-143.27-320.001-320h-64c0 212.079 171.923 384 384.001 384 212.075 0 384-171.921 384-384 0-212.077-171.925-384-384-384-123.72 0-233.773 58.508-304.001 149.364v-101.364c0-17.673-14.327-32-32-32s-32 14.327-32 32v192c0 17.673 14.327 32 32 32h176c17.673 0 32-14.327 32-32s-14.327-32-32-32h-107.295c57.239-86.755 155.582-144 267.296-144 176.73 0 320 143.269 320 320z","M572.578 320c0-17.673-14.327-32-32-32s-32 14.327-32 32v224c0 8.486 3.371 16.627 9.37 22.626l96 96c12.497 12.497 32.759 12.497 45.257 0s12.497-32.755 0-45.252l-86.626-86.63v-210.743z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["history"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":367,"id":78,"name":"history","prevSize":32,"code":59715},"setIdx":0,"setId":0,"iconIdx":67},{"icon":{"paths":["M523.78 195.090l224.166 259.702v365.751c0 5.85-4.745 10.59-10.603 10.59h-136.235v-149.623c0-23.394-18.991-42.359-42.415-42.359h-85.841c-23.424 0-42.411 18.965-42.411 42.359v149.623h-136.23c-5.856 0-10.603-4.74-10.603-10.59v-365.824l224.107-259.63c4.228-4.9 11.831-4.9 16.064 0zM562.257 894.669h175.087c40.99 0 74.223-33.186 74.223-74.125v-243.883h56.154c12.437 0 23.735-7.241 28.915-18.534 5.184-11.294 3.298-24.567-4.826-33.975l-319.846-370.545c-29.606-34.302-82.825-34.301-112.435 0l-319.846 370.545c-8.122 9.408-10.007 22.682-4.825 33.975s16.479 18.534 28.918 18.534h56.214v243.883c0 40.939 33.23 74.125 74.222 74.125h175.083c1.173 0.098 2.359 0.145 3.558 0.145h85.841c1.199 0 2.389-0.047 3.563-0.145z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["home"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":368,"id":77,"name":"home","prevSize":32,"code":59716},"setIdx":0,"setId":0,"iconIdx":68},{"icon":{"paths":["M440.67 405.333c0 47.13-38.203 85.333-85.331 85.333s-85.333-38.204-85.333-85.333c0-47.128 38.205-85.333 85.333-85.333s85.331 38.205 85.331 85.333z","M131.339 192c0-17.673 14.327-32 32-32h767.998c17.677 0 32 14.327 32 32v640c0 17.673-14.323 32-32 32h-767.998c-17.673 0-32-14.327-32-32v-640zM195.339 764.164l151.704-176.99c9.27-10.816 24.571-14.199 37.538-8.307l153.122 69.602 160.474-204.241c6.012-7.646 15.172-12.147 24.9-12.228 9.728-0.077 18.965 4.271 25.097 11.823l151.164 186.048v-405.871h-703.998v540.164zM248.914 800h650.423v-68.638l-175.578-216.102-166.784 212.271-176.988-80.448-131.073 152.917z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["image"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":369,"id":76,"name":"image","prevSize":32,"code":59717},"setIdx":0,"setId":0,"iconIdx":69},{"icon":{"paths":["M527.049 873.024c-199.388 0-361.025-161.634-361.025-361.024s161.637-361.026 361.025-361.026c199.39 0 361.028 161.637 361.028 361.026s-161.638 361.024-361.028 361.024zM527.049 938.667c235.644 0 426.667-191.027 426.667-426.667 0-235.642-191.023-426.667-426.667-426.667-235.641 0-426.666 191.025-426.666 426.667 0 235.639 191.025 426.667 426.666 426.667zM559.872 347.898c0 18.126-14.694 32.82-32.823 32.82-18.125 0-32.819-14.694-32.819-32.82s14.694-32.82 32.819-32.82c18.129 0 32.823 14.694 32.823 32.82zM527.049 413.539c-18.125 0-32.819 14.694-32.819 32.819v229.747c0 18.125 14.694 32.819 32.819 32.819 18.129 0 32.823-14.694 32.823-32.819v-229.747c0-18.125-14.694-32.819-32.823-32.819z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["info"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":370,"id":75,"name":"info","prevSize":32,"code":59718},"setIdx":0,"setId":0,"iconIdx":70},{"icon":{"paths":["M357.949 550.626c-12.497-12.497-12.497-32.755 0-45.252s32.758-12.497 45.255 0l105.374 105.37v-418.743c0-17.673 14.327-32 32-32s32 14.327 32 32v418.743l105.37-105.37c12.497-12.497 32.759-12.497 45.257 0s12.497 32.755 0 45.252l-160 160c-12.497 12.497-32.759 12.497-45.257 0l-159.998-160zM140.577 864c0 17.673 14.327 32 32 32h768.001c17.673 0 32-14.327 32-32v-512c0-17.673-14.327-32-32-32h-96c-17.673 0-32 14.327-32 32s14.327 32 32 32h64v448h-704.001v-448h64c17.673 0 32-14.327 32-32s-14.327-32-32-32h-96c-17.673 0-32 14.327-32 32v512z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["inport"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":371,"id":74,"name":"inport","prevSize":32,"code":59719},"setIdx":0,"setId":0,"iconIdx":71},{"icon":{"paths":["M190.831 512c0-17.673 13.133-32 29.333-32h645.333c16.201 0 29.333 14.327 29.333 32s-13.133 32-29.333 32h-645.333c-16.201 0-29.333-14.327-29.333-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["intermediate"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":372,"id":73,"name":"intermediate","prevSize":32,"code":59720},"setIdx":0,"setId":0,"iconIdx":72},{"icon":{"paths":["M565.811 352c17.673 0 32-14.327 32-32s-14.327-32-32-32c-17.673 0-32 14.327-32 32s14.327 32 32 32zM581.423 436.996c2.756-17.457-9.161-33.844-26.62-36.6-17.455-2.756-33.843 9.161-36.599 26.616l-48 304c-2.756 17.459 9.161 33.843 26.62 36.599 17.455 2.756 33.843-9.161 36.599-26.615l48-304z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["italic"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":373,"id":72,"name":"italic","prevSize":32,"code":59721},"setIdx":0,"setId":0,"iconIdx":73},{"icon":{"paths":["M376.067 512c-88.366 0-160-71.633-160-160 0-88.366 71.634-160 160-160 88.364 0 160.002 71.634 160.002 160 0 26.934-6.656 52.313-18.411 74.583l11.913 11.915-0.132 0.128 299.136 299.136c3.533 9.924 6.413 20.975 7.74 31.607 1.651 13.218 0.563 22.967-1.873 28.937-1.771 4.335-4.22 7.232-10.773 9.015-8.316 2.261-24.516 2.795-52.821-5.504-8.525-3.806-27.721-16.282-45.133-35.379-18.18-19.938-29.645-41.856-29.645-62.438 0-15.642-11.311-28.992-26.739-31.565l-91.75-15.292c-3.767-2.658-18.769-15.693-10.133-58.867 2.099-10.492-1.186-21.338-8.751-28.902l-88.201-88.196c-26.466 19.379-59.11 30.822-94.427 30.822zM592.239 410.916c5.103-18.773 7.829-38.527 7.829-58.916 0-123.712-100.288-224-224.002-224-123.712 0-224 100.288-224 224s100.288 224 224 224c29.287 0 57.26-5.619 82.903-15.842l43.008 43.008c-7.155 65.493 23.991 104.533 55.97 115.191l2.381 0.794 74.859 12.476c7.083 31.407 25.173 58.125 43.234 77.935 23.121 25.357 50.957 44.629 69.76 52.151l1.323 0.529 1.37 0.41c34.714 10.415 64.73 13.188 89.591 6.426 26.782-7.283 44.331-24.785 53.227-46.583 8.23-20.164 8.474-42.283 6.127-61.065-2.402-19.217-7.898-37.956-14.042-53.312-1.609-4.023-4.019-7.68-7.083-10.743l-286.455-286.458zM408.067 336c0 26.51-21.49 48-48 48s-48-21.49-48-48c0-26.51 21.49-48 48-48s48 21.49 48 48z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["key"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":374,"id":71,"name":"key","prevSize":32,"code":59722},"setIdx":0,"setId":0,"iconIdx":74},{"icon":{"paths":["M186.321 224c-35.346 0-64 28.654-64 64v448c0 35.345 28.654 64 64 64h704c35.345 0 64-28.655 64-64v-448c0-35.346-28.655-64-64-64h-704zM186.321 288h704v448h-704v-448zM282.321 352c-17.673 0-32 14.327-32 32s14.327 32 32 32h64c17.673 0 32-14.327 32-32s-14.327-32-32-32h-64zM282.321 512c0-17.673 14.327-32 32-32h64c17.673 0 32 14.327 32 32s-14.327 32-32 32h-64c-17.673 0-32-14.327-32-32zM506.321 480c-17.673 0-32 14.327-32 32s14.327 32 32 32h64c17.673 0 32-14.327 32-32s-14.327-32-32-32h-64zM666.321 512c0-17.673 14.327-32 32-32h64c17.673 0 32 14.327 32 32s-14.327 32-32 32h-64c-17.673 0-32-14.327-32-32zM506.321 352c-17.673 0-32 14.327-32 32s14.327 32 32 32h64c17.673 0 32-14.327 32-32s-14.327-32-32-32h-64zM346.321 640c0-17.673 14.327-32 32-32h320c17.673 0 32 14.327 32 32s-14.327 32-32 32h-320c-17.673 0-32-14.327-32-32zM730.321 352c-17.673 0-32 14.327-32 32s14.327 32 32 32h64c17.673 0 32-14.327 32-32s-14.327-32-32-32h-64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["keyboard"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":375,"id":70,"name":"keyboard","prevSize":32,"code":59723},"setIdx":0,"setId":0,"iconIdx":75},{"icon":{"paths":["M711.381 256c0-17.673-14.327-32-32-32s-32 14.327-32 32v56.876l-80.346 13.999c-17.412 3.034-29.065 19.607-26.031 37.018s19.605 29.066 37.018 26.032l69.359-12.085v69.371c-30.383 6.852-60.459 20.075-84.151 43.14-27.925 27.183-44.075 65.242-44.075 113.809 0 25.741 6.263 48.26 18.453 66.62 12.186 18.351 29.065 30.682 47.253 37.999 35.354 14.225 76.719 10.176 108.126-4.578l1.207-0.567c31.125-14.618 62.494-29.35 90.722-57.818 21.325-21.504 39.71-49.536 56.849-88.674 5.653 9.498 9.591 20.966 10.287 34.338 1.63 31.526-14.281 82.812-87.957 153.417-12.757 12.228-13.193 32.486-0.964 45.244 12.228 12.762 32.486 13.193 45.248 0.964 80.192-76.851 110.583-145.033 107.588-202.935-2.987-57.655-38.588-96.021-70.677-113.954-20.774-13.013-50.214-22.827-81.216-28.288-16.623-2.931-34.47-4.749-52.693-4.996v-74.242l101.722-17.723c17.408-3.034 29.065-19.607 26.031-37.018s-19.61-29.066-37.018-26.032l-90.735 15.809v-45.724zM607.872 536.209c10.163-9.894 23.565-17.476 39.509-22.703v138.65c-13.444 2.547-27.486 1.732-38.635-2.752-7.71-3.102-13.658-7.757-17.822-14.029-4.156-6.259-7.77-15.996-7.77-31.215 0-33.348 10.569-54.174 24.717-67.951zM739.473 600.751c-8.683 8.755-17.783 15.706-28.092 22.076v-117.888c14.127 0.239 28.224 1.66 41.587 4.015 13.589 2.394 25.685 5.623 35.763 9.165-16.879 42.039-33.067 66.304-49.259 82.633zM277.182 565.333h98.385l-49.193-184.882-49.193 184.882zM420.328 733.559l-27.732-104.226h-132.442l-27.732 104.226c-4.544 17.079-22.073 27.243-39.152 22.699s-27.24-22.076-22.696-39.151l106.323-399.601c13.494-50.714 85.463-50.713 98.957 0l106.323 399.601c4.544 17.075-5.615 34.607-22.694 39.151s-34.609-5.619-39.153-22.699z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["language"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":376,"id":69,"name":"language","prevSize":32,"code":59724},"setIdx":0,"setId":0,"iconIdx":76},{"icon":{"paths":["M260.423 275.61l-13.972 14.271c-37.092 37.884-36.449 98.665 1.435 135.757l145.621 142.576c37.883 37.090 98.666 36.446 135.756-1.438l13.973-14.268c0.721-0.742 1.434-1.489 2.125-2.244l0.102 0.098c5.807-5.905 13.888-9.566 22.822-9.566 17.673 0 32 14.327 32 32 0 9.6-4.228 18.21-10.923 24.077l-14.37 14.677c-61.82 63.142-163.119 64.213-226.26 2.394l-145.621-142.575c-63.141-61.82-64.212-163.121-2.392-226.262l13.972-14.271c61.82-63.141 163.121-64.212 226.263-2.392l74.692 73.131c0.977 0.847 1.899 1.752 2.769 2.71l0.371 0.366-0.026 0.026c4.932 5.63 7.923 13.005 7.923 21.079 0 17.673-14.327 32-32 32-7.829 0-15.002-2.813-20.565-7.482l-0.107 0.108-77.834-76.207c-37.884-37.092-98.665-36.449-135.757 1.435zM796.147 768l13.973-14.268c37.090-37.884 36.45-98.667-1.438-135.757l-145.617-142.575c-37.888-37.090-98.667-36.45-135.761 1.434l-13.969 14.272c-0.725 0.738-1.434 1.485-2.129 2.244l-0.102-0.102c-5.803 5.905-13.884 9.57-22.818 9.57-17.677 0-32-14.327-32-32 0-9.6 4.224-18.214 10.918-24.077l14.37-14.682c61.82-63.139 163.123-64.21 226.261-2.389l145.621 142.575c63.142 61.82 64.213 163.119 2.394 226.261l-13.973 14.268c-61.82 63.142-163.119 64.213-226.261 2.394l-74.692-73.131c-0.977-0.849-1.903-1.754-2.769-2.709l-0.371-0.367 0.021-0.026c-4.932-5.632-7.919-13.005-7.919-21.077 0-17.673 14.323-32 32-32 7.829 0 15.002 2.812 20.565 7.479l0.102-0.107 77.837 76.207c37.884 37.090 98.667 36.45 135.757-1.438z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["link"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":377,"id":68,"name":"link","prevSize":32,"code":59725},"setIdx":0,"setId":0,"iconIdx":77},{"icon":{"paths":["M234.667 672c35.346 0 64-28.655 64-64s-28.654-64-64-64c-35.346 0-64 28.655-64 64s28.654 64 64 64z","M362.667 576c-17.673 0-32 14.327-32 32s14.327 32 32 32h544c17.673 0 32-14.327 32-32s-14.327-32-32-32h-544z","M234.667 480c35.346 0 64-28.655 64-64 0-35.346-28.654-64-64-64s-64 28.654-64 64c0 35.345 28.654 64 64 64z","M362.667 384c-17.673 0-32 14.327-32 32s14.327 32 32 32h544c17.673 0 32-14.327 32-32s-14.327-32-32-32h-544z","M234.667 288c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z","M362.667 192c-17.673 0-32 14.327-32 32s14.327 32 32 32h544c17.673 0 32-14.327 32-32s-14.327-32-32-32h-544z","M234.667 864c35.346 0 64-28.655 64-64s-28.654-64-64-64c-35.346 0-64 28.655-64 64s28.654 64 64 64z","M362.667 768c-17.673 0-32 14.327-32 32s14.327 32 32 32h544c17.673 0 32-14.327 32-32s-14.327-32-32-32h-544z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["list-condensed"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":378,"id":67,"name":"list-condensed","prevSize":32,"code":59726},"setIdx":0,"setId":0,"iconIdx":78},{"icon":{"paths":["M316.577 192c0-17.673 14.327-32 32-32h544.001c17.673 0 32 14.327 32 32s-14.327 32-32 32h-544.001c-17.673 0-32-14.327-32-32zM316.577 288c0-17.673 14.327-32 32-32h448.001c17.673 0 32 14.327 32 32s-14.327 32-32 32h-448.001c-17.673 0-32-14.327-32-32zM220.577 304c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z","M316.577 464c0-17.673 14.327-32 32-32h544.001c17.673 0 32 14.327 32 32s-14.327 32-32 32h-544.001c-17.673 0-32-14.327-32-32zM316.577 560c0-17.673 14.327-32 32-32h448.001c17.673 0 32 14.327 32 32s-14.327 32-32 32h-448.001c-17.673 0-32-14.327-32-32zM220.577 576c35.346 0 64-28.655 64-64s-28.654-64-64-64c-35.346 0-64 28.655-64 64s28.654 64 64 64z","M316.577 736c0-17.673 14.327-32 32-32h544.001c17.673 0 32 14.327 32 32s-14.327 32-32 32h-544.001c-17.673 0-32-14.327-32-32zM316.577 832c0-17.673 14.327-32 32-32h448.001c17.673 0 32 14.327 32 32s-14.327 32-32 32h-448.001c-17.673 0-32-14.327-32-32zM220.577 848c35.346 0 64-28.655 64-64s-28.654-64-64-64c-35.346 0-64 28.655-64 64s28.654 64 64 64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["list-extended"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":379,"id":66,"name":"list-extended","prevSize":32,"code":59727},"setIdx":0,"setId":0,"iconIdx":79},{"icon":{"paths":["M222.831 320c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z","M350.831 224c-17.673 0-32 14.327-32 32s14.327 32 32 32h544c17.673 0 32-14.327 32-32s-14.327-32-32-32h-544z","M222.831 576c35.346 0 64-28.655 64-64s-28.654-64-64-64c-35.346 0-64 28.655-64 64s28.654 64 64 64z","M350.831 480c-17.673 0-32 14.327-32 32s14.327 32 32 32h544c17.673 0 32-14.327 32-32s-14.327-32-32-32h-544z","M222.831 832c35.346 0 64-28.655 64-64s-28.654-64-64-64c-35.346 0-64 28.655-64 64s28.654 64 64 64z","M350.831 736c-17.673 0-32 14.327-32 32s14.327 32 32 32h544c17.673 0 32-14.327 32-32s-14.327-32-32-32h-544z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["list-medium"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":380,"id":65,"name":"list-medium","prevSize":32,"code":59728},"setIdx":0,"setId":0,"iconIdx":80},{"icon":{"paths":["M700.147 361.892c4.681-24.975 34.701-34.093 49.126-13.174 31.991 46.404 50.726 102.656 50.726 163.281 0 60.629-18.735 116.881-50.726 163.285-14.426 20.919-44.446 11.802-49.126-13.175l-1.707-9.101c-1.583-8.431 0.384-17.084 4.855-24.401 20.749-33.967 32.704-73.89 32.704-116.608 0-42.714-11.955-82.637-32.704-116.604-4.471-7.319-6.438-15.972-4.855-24.402l1.707-9.102z","M320.705 395.396c-20.749 33.967-32.705 73.891-32.705 116.604 0 42.718 11.956 82.641 32.705 116.608 4.471 7.317 6.436 15.97 4.856 24.401l-1.707 9.101c-4.683 24.977-34.703 34.095-49.127 13.175-31.994-46.404-50.728-102.656-50.728-163.285 0-60.625 18.734-116.878 50.728-163.281 14.423-20.919 44.444-11.801 49.127 13.174l1.707 9.102c1.58 8.43-0.385 17.083-4.856 24.402z","M728.764 209.256l-0.512 2.747c-2.236 11.911 2.534 23.968 11.763 31.822 75.861 64.565 123.985 160.751 123.985 268.175 0 107.426-48.124 203.614-123.985 268.177-9.229 7.855-13.999 19.913-11.763 31.821l0.512 2.748c4.194 22.362 29.692 33.195 47.262 18.743 92.796-76.292 151.974-191.979 151.974-321.489 0-129.507-59.179-245.193-151.974-321.489-17.57-14.448-43.068-3.615-47.262 18.745z","M283.986 243.825c9.229-7.854 13.998-19.911 11.764-31.822l-0.515-2.747c-4.192-22.359-29.69-33.193-47.262-18.745-92.793 76.296-151.973 191.982-151.973 321.489 0 129.51 59.18 245.197 151.973 321.489 17.572 14.451 43.070 3.618 47.262-18.743l0.515-2.748c2.233-11.908-2.536-23.966-11.764-31.821-75.863-64.563-123.986-160.751-123.986-268.177 0-107.424 48.122-203.61 123.986-268.175z","M608 512c0 53.022-42.982 96-96 96s-96-42.978-96-96c0-53.018 42.982-95.999 96-95.999s96 42.981 96 95.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Live"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":381,"id":64,"name":"Live","prevSize":32,"code":59729},"setIdx":0,"setId":0,"iconIdx":81},{"icon":{"paths":["M719.398 512v54.818c-0.196 76.634-43.682 143.091-107.298 176.209-5.525-25.634-28.326-44.847-55.612-44.847h-72.405c-31.42 0-56.887 25.472-56.887 56.892v41.374c0 31.415 25.468 56.887 56.887 56.887h72.405c28.471 0 52.062-20.919 56.23-48.226 69.171-26.795 123.797-82.773 148.77-152.828 4.719 1.267 9.677 1.941 14.797 1.941h28.446c31.415 0 56.887-25.468 56.887-56.887v-85.333c0-31.42-25.472-56.887-56.887-56.887h-28.446v-28.446c0-141.385-114.615-256-256-256s-256 114.615-256 256v23.275h-28.445c-31.419 0-56.889 25.468-56.889 56.887v103.433c0 31.42 25.47 56.892 56.889 56.892h28.444c31.419 0 56.889-25.472 56.889-56.892v-36.203h0.149c-0.099-2.573-0.148-5.158-0.148-7.757v-139.636c0-109.966 89.145-199.111 199.111-199.111 109.965 0 199.113 89.145 199.113 199.111v85.333z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["livechat"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":382,"id":63,"name":"livechat","prevSize":32,"code":59730},"setIdx":0,"setId":0,"iconIdx":82},{"icon":{"paths":["M357.812 304c0-97.202 78.8-176 175.999-176 97.203 0 176 78.798 176 176v142.477h16c53.022 0 96 42.978 96 96v257.523c0 53.018-42.978 96-96 96h-383.999c-53.019 0-96-42.982-96-96v-257.523c0-53.022 42.981-96 96-96h16v-142.477zM421.812 446.477h223.999v-142.477c0-61.856-50.142-112-112-112-61.854 0-111.999 50.144-111.999 112v142.477zM341.812 510.477c-17.673 0-32 14.327-32 32v257.523c0 17.673 14.327 32 32 32h383.999c17.673 0 32-14.327 32-32v-257.523c0-17.673-14.327-32-32-32h-383.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["lock"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":384,"id":61,"name":"lock","prevSize":32,"code":59731},"setIdx":0,"setId":0,"iconIdx":84},{"icon":{"paths":["M721.519 449.771c0-142.502-115.674-258.022-258.364-258.022-142.688 0-258.361 115.52-258.361 258.022s115.672 258.022 258.361 258.022c142.69 0 258.364-115.52 258.364-258.022zM667.174 699.042c-55.573 45.419-126.609 72.666-204.019 72.666-178.035 0-322.361-144.137-322.361-321.937s144.326-321.937 322.361-321.937c178.035 0 322.364 144.137 322.364 321.937 0 77.303-27.285 148.245-72.759 203.742l186.594 186.347c12.587 12.574 12.587 32.956 0 45.53-12.591 12.574-33.003 12.574-45.589 0l-186.59-186.347z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["magnifier"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":385,"id":60,"name":"magnifier","prevSize":32,"code":59732},"setIdx":0,"setId":0,"iconIdx":85},{"icon":{"paths":["M213.812 736h639.999v-448h-639.999v448zM149.812 256c0-17.673 14.327-32 32-32h703.999c17.673 0 32 14.327 32 32v512c0 17.673-14.327 32-32 32h-703.999c-17.673 0-32-14.327-32-32v-512zM327.117 389.082c-14.866-9.557-34.665-5.253-44.222 9.613s-5.253 34.665 9.613 44.223l241.303 155.123 241.306-155.123c14.865-9.557 19.17-29.356 9.613-44.223s-29.355-19.17-44.22-9.613l-206.699 132.876-206.694-132.876z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["mail"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":386,"id":59,"name":"mail","prevSize":32,"code":59733},"setIdx":0,"setId":0,"iconIdx":86},{"icon":{"paths":["M840.533 802.133h-640c-17.067 0-34.133-12.8-34.133-34.133s12.8-34.133 34.133-34.133h640c17.067 0 34.133 12.8 34.133 34.133s-17.067 34.133-34.133 34.133zM840.533 546.133h-640c-17.067 0-34.133-12.8-34.133-34.133s12.8-34.133 34.133-34.133h640c17.067 0 34.133 12.8 34.133 34.133s-17.067 34.133-34.133 34.133zM840.533 290.133h-640c-21.333 0-34.133-17.067-34.133-34.133s12.8-34.133 34.133-34.133h640c17.067 0 34.133 12.8 34.133 34.133s-17.067 34.133-34.133 34.133z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["menu_hamburguer"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":387,"id":58,"name":"menu_hamburguer","prevSize":32,"code":59734},"setIdx":0,"setId":0,"iconIdx":87},{"icon":{"paths":["M576 256c0 35.346-28.655 64-64 64s-64-28.654-64-64c0-35.346 28.655-64 64-64s64 28.654 64 64z","M576 512c0 35.345-28.655 64-64 64s-64-28.655-64-64c0-35.345 28.655-64 64-64s64 28.655 64 64z","M576 768c0 35.345-28.655 64-64 64s-64-28.655-64-64c0-35.345 28.655-64 64-64s64 28.655 64 64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["menu"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":388,"id":57,"name":"menu","prevSize":32,"code":59735},"setIdx":0,"setId":0,"iconIdx":88},{"icon":{"paths":["M492.89 128c104.256 0 181.252 29.018 237.495 70.652l-44.318 44.317c-45.521-31.22-107.746-53.057-193.178-53.057-129.726 0-207.83 53.576-254.53 118.696-47.831 66.699-64.077 147.668-64.077 201.185v1.404l-0.127 1.399c-7.328 80.926 13.761 143.13 51.784 190.498l-43.879 43.883c-50.179-59.904-78.131-139.046-69.44-238.596 0.276-63.411 19.117-157.053 75.696-235.949 58.132-81.062 154.749-144.433 304.573-144.433zM837.897 332.498l-47.006 47.009c16.503 42.634 20.608 78.524 20.608 89.011v0.179c0 19.516 0 31.791-6.622 56.171-7.091 26.108-21.739 65.647-52.553 137.835-5.7 13.355-2.795 25.98 1.259 34.436 3.836 7.987 9.562 14.4 14.596 19.183 10.227 9.711 24.252 18.837 38.545 26.867 7.885 4.429 18.295 8.994 27.61 13.077l1.843 0.806c10.556 4.634 20.727 9.148 29.615 13.897 3.426 1.835 6.298 3.516 8.674 5.030-5.107 3.23-12.036 6.882-20.945 10.765-22.959 10.005-55.326 19.938-93.888 28.126-77.116 16.375-174.724 24.862-263.339 14.976-43.746-4.881-86.827-14.528-126.534-29.231l-47.543 47.543c52.771 23.019 110.495 36.89 167.267 43.221 96.388 10.752 200.708 1.515 282.91-15.936 41.097-8.725 77.73-19.729 105.681-31.906 13.909-6.063 26.615-12.821 36.855-20.343 9.425-6.925 20.736-17.344 25.609-32.017 7.394-22.268-2.957-40.503-12.813-51.136-9.429-10.167-22.106-17.941-32.956-23.74-11.311-6.046-23.625-11.469-33.89-15.979-11.059-4.851-18.935-8.316-24.055-11.191-9.911-5.568-17.438-10.534-22.507-14.571 27.422-64.806 42.219-104.589 50.048-133.423 8.777-32.303 8.798-50.982 8.798-72.64 0-20.105-7.053-75.5-35.268-136.020zM851.089 153.373c12.497-12.497 32.759-12.497 45.257 0 12.493 12.497 12.493 32.758 0 45.255l-682.669 682.665c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l682.667-682.668z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["message_off"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":389,"id":56,"name":"message_off","prevSize":32,"code":59736},"setIdx":0,"setId":0,"iconIdx":89},{"icon":{"paths":["M236.105 308.609c-47.832 66.699-64.077 147.668-64.077 201.185v1.404l-0.127 1.399c-9.347 103.236 27.547 175.996 86.848 226.377 60.642 51.516 146.603 80.998 235.293 90.893 88.61 9.886 186.219 1.399 263.339-14.976 38.558-8.188 70.929-18.121 93.888-28.126 8.905-3.883 15.838-7.535 20.941-10.765-2.372-1.515-5.248-3.196-8.674-5.030-8.883-4.749-19.055-9.263-29.611-13.897l-1.843-0.806c-9.314-4.083-19.725-8.649-27.614-13.077-14.293-8.030-28.314-17.156-38.545-26.867-5.035-4.783-10.761-11.196-14.592-19.183-4.058-8.457-6.963-21.082-1.259-34.436 30.81-72.188 45.457-111.727 52.548-137.835 6.622-24.38 6.622-36.655 6.622-56.171v-0.179c0-15.514-8.981-86.595-53.777-152.876-43.375-64.175-121.395-125.729-264.828-125.729-129.729 0-207.832 53.576-254.532 118.696zM186.061 272.433c58.132-81.062 154.749-144.433 304.576-144.433 164.894 0 261.589 72.589 315.857 152.878 52.838 78.182 64.414 161.879 64.414 187.641 0 21.658-0.021 40.337-8.794 72.64-7.834 28.834-22.626 68.617-50.048 133.423 5.069 4.036 12.591 9.003 22.507 14.571 5.12 2.876 12.992 6.34 24.051 11.191 10.266 4.51 22.583 9.933 33.894 15.979 10.846 5.798 23.522 13.572 32.951 23.74 9.86 10.633 20.207 28.868 12.817 51.136-4.873 14.673-16.183 25.092-25.613 32.017-10.24 7.522-22.946 14.281-36.855 20.343-27.947 12.177-64.585 23.181-105.681 31.906-82.197 17.451-186.522 26.688-282.906 15.936-96.312-10.743-195.348-43.174-268.316-105.165-74.031-62.891-119.296-154.778-108.551-277.854 0.276-63.411 19.117-157.053 75.696-235.949z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["message"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":390,"id":55,"name":"message","prevSize":32,"code":59737},"setIdx":0,"setId":0,"iconIdx":90},{"icon":{"paths":["M520.286 128c75.546 0 138.859 52.355 155.644 122.761l-59.644 59.644v-22.406c0-53.019-42.982-96-96-96-53.022 0-96.001 42.981-96.001 96v128c0 24.068 8.858 46.067 23.489 62.916l-45.322 45.321c-26.182-28.484-42.167-66.496-42.167-108.237v-128c0-88.366 71.634-160 160.001-160zM569.634 568.243l102.895-102.895c-15.765 48.674-54.221 87.13-102.895 102.895zM296.285 416c0 72.154 23.182 123.102 55.327 159.078l-45.303 45.303c-43.427-47.351-74.024-113.993-74.024-204.382 0-17.673 14.327-32 32-32s32 14.327 32 32zM486.942 650.935l-51.806 51.81c18.56 6.374 36.582 10.807 53.15 13.636v115.618h-160.001c-17.673 0-32 14.327-32 32s14.327 32 32 32h384.001c17.673 0 32-14.327 32-32s-14.327-32-32-32h-160v-115.618c44.638-7.62 99.819-26.897 147.721-64.38 60.702-47.501 108.279-123.29 108.279-236.002 0-17.673-14.327-32-32-32s-32 14.327-32 32c0 92.087-37.76 149.632-83.721 185.6-46.468 36.361-102.737 51.58-140.279 54.327-9.971-0.73-21.265-2.338-33.344-4.992zM833.66 153.373c12.493-12.497 32.755-12.497 45.252 0s12.497 32.758 0 45.255l-672 671.999c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l672.002-672.001z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["mic-off"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":391,"id":54,"name":"mic-off","prevSize":32,"code":59738},"setIdx":0,"setId":0,"iconIdx":91},{"icon":{"paths":["M614.033 288c0-53.019-42.982-96-96-96-53.022 0-96.002 42.981-96.002 96v128c0 53.018 42.98 96 96.002 96 53.018 0 96-42.982 96-96v-128zM358.031 288c0-88.366 71.635-160 160.002-160 88.363 0 160 71.634 160 160v128c0 88.367-71.637 160-160 160-88.367 0-160.002-71.633-160.002-160v-128zM262.031 384c17.673 0 32 14.327 32 32 0 92.087 37.758 149.632 83.72 185.6 46.466 36.361 102.735 51.58 140.282 54.327 37.542-2.748 93.811-17.967 140.279-54.327 45.961-35.968 83.721-93.513 83.721-185.6 0-17.673 14.323-32 32-32 17.673 0 32 14.327 32 32 0 112.713-47.578 188.501-108.284 236.002-47.902 37.483-103.078 56.759-147.716 64.38v115.618h160c17.673 0 32 14.327 32 32s-14.327 32-32 32h-384.002c-17.673 0-32-14.327-32-32s14.327-32 32-32h160.002v-115.618c-44.642-7.62-99.82-26.897-147.722-64.38-60.705-47.501-108.28-123.29-108.28-236.002 0-17.673 14.327-32 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["mic"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":392,"id":53,"name":"mic","prevSize":32,"code":59739},"setIdx":0,"setId":0,"iconIdx":92},{"icon":{"paths":["M571.797 242.504c0.188-17.672 14.665-31.845 32.337-31.657s31.846 14.668 31.659 32.34l-1.318 123.488 193.438-193.438c12.497-12.497 32.759-12.497 45.252 0 12.497 12.497 12.497 32.758 0 45.255l-193.438 193.438 123.49-1.319c17.673-0.189 32.149 13.984 32.341 31.658 0.188 17.673-13.986 32.149-31.659 32.337l-201.92 2.159c-8.606 0.090-16.883-3.285-22.967-9.374-6.089-6.084-9.463-14.362-9.374-22.967l2.159-201.921zM496.384 782.148c-0.188 17.673-14.669 31.846-32.341 31.659-17.673-0.192-31.842-14.669-31.654-32.341l1.318-123.49-193.439 193.438c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l193.438-193.438-123.488 1.318c-17.672 0.188-32.151-13.986-32.34-31.659s13.984-32.149 31.656-32.337l201.923-2.159c8.602-0.090 16.883 3.285 22.967 9.37 6.084 6.089 9.463 14.366 9.37 22.972l-2.155 201.92z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["minimize-arrow"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":393,"id":52,"name":"minimize-arrow","prevSize":32,"code":59740},"setIdx":0,"setId":0,"iconIdx":93},{"icon":{"paths":["M265.497 170.662c0-47.128 38.205-85.333 85.333-85.333h384.001c47.13 0 85.333 38.205 85.333 85.333v682.668c0 47.125-38.204 85.333-85.333 85.333h-384.001c-47.128 0-85.333-38.208-85.333-85.333v-682.668zM329.497 170.662v682.668c0 11.78 9.551 21.333 21.333 21.333h384.001c11.78 0 21.333-9.553 21.333-21.333v-682.668c0-11.782-9.553-21.333-21.333-21.333h-96.294c-2.65 24.002-22.997 42.672-47.706 42.672h-96c-24.708 0-45.056-18.67-47.71-42.672h-96.291c-11.782 0-21.333 9.551-21.333 21.333z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["mobile"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":394,"id":51,"name":"mobile","prevSize":32,"code":59741},"setIdx":0,"setId":0,"iconIdx":94},{"icon":{"paths":["M353.234 231.569c-62.881 49.504-135.086 136.548-141.94 266.125-5.762 108.924 37.404 187.187 89.915 241.51 53.259 55.1 115.701 84.924 144.247 94.443 41.865 13.952 114.274 29.534 234.645-15.607 34.859-13.069 73.165-42.095 108.305-78.426 14.272-14.754 27.614-30.293 39.599-45.773-28.774 9.293-61.7 17.758-96.589 23.595-56.192 9.404-119.287 12.322-179.409-0.235-2.492-0.521-4.962-1.033-7.411-1.536-22.195-4.578-42.735-8.815-62.588-17.651-23.091-10.274-43.806-25.89-69.299-51.383-42.097-42.095-89.142-107.221-89.372-213.841-1.569-34.084 4.622-81.88 13.763-129.219 4.625-23.946 10.142-48.465 16.132-72.002zM379.548 138.22c32.8-17.15 63.708 15.843 53.877 45.907-12.236 37.414-24.587 85.511-33.484 131.58-9.024 46.731-13.946 88.633-12.643 114.698l0.040 0.798v0.802c0 84.915 36.173 134.916 70.629 169.374 22.507 22.507 36.834 32.277 50.061 38.165 13.231 5.884 26.833 8.717 51.085 13.764 1.924 0.397 3.917 0.815 5.982 1.246 49.911 10.423 104.529 8.337 155.755-0.239 65.434-10.953 122.385-31.979 152.375-47.386 17.566-9.020 34.991-2.466 44.48 5.965 9.66 8.589 19.371 27.153 8.883 46.955-20.634 38.95-53.645 84.42-92.181 124.262-38.212 39.509-84.318 76.036-131.831 93.854-135.629 50.863-223.219 34.441-277.356 16.397-36.516-12.173-108.392-46.912-170.026-110.677-62.381-64.533-114.684-159.428-107.81-289.37 10.79-203.98 157.584-317.1 232.164-356.095z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["moon"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":395,"id":50,"name":"moon","prevSize":32,"code":59742},"setIdx":0,"setId":0,"iconIdx":95},{"icon":{"paths":["M405.458 769.293c-12.497 12.497-32.758 12.497-45.255 0l-192-192c-12.497-12.497-12.497-32.755 0-45.252l192-192.001c12.497-12.497 32.758-12.497 45.255 0s12.497 32.758 0 45.255l-137.373 137.373h578.745v-192h-192c-17.673 0-32-14.327-32-32s14.327-32 32-32h224c17.673 0 32 14.327 32 32v256c0 17.673-14.327 32-32 32h-610.745l137.373 137.374c12.497 12.497 12.497 32.755 0 45.252z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["multiline"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":396,"id":49,"name":"multiline","prevSize":32,"code":59743},"setIdx":0,"setId":0,"iconIdx":96},{"icon":{"paths":["M211.776 176c-35.346 0-64 28.654-64 64v576c0 35.345 28.654 64 64 64h576c35.345 0 64-28.655 64-64v-576c0-35.346-28.655-64-64-64h-576zM211.776 240h576v576h-576v-576zM702.404 558.153c-0.192 17.673-14.669 31.842-32.341 31.654s-31.846-14.669-31.659-32.341l1.323-123.588-309.344 308.77c-12.508 12.484-32.77 12.467-45.255-0.043-12.485-12.506-12.466-32.768 0.042-45.252l309.199-308.627-123.388 1.318c-17.673 0.189-32.149-13.984-32.337-31.657-0.192-17.672 13.982-32.151 31.654-32.34l201.92-2.156c8.606-0.092 16.887 3.286 22.972 9.371s9.459 14.364 9.37 22.969l-2.155 201.922z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["new_window"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":397,"id":48,"name":"new_window","prevSize":32,"code":59744},"setIdx":0,"setId":0,"iconIdx":97},{"icon":{"paths":["M832.781 183.279c-37.141-37.936-98.074-38.532-135.953-1.331l-348.017 341.786c-12.722 12.497-21.706 28.284-25.943 45.594l-23.65 96.623c-6.931 28.318 16.732 54.771 45.686 51.072l90.574-11.563c20.198-2.577 39.049-11.503 53.833-25.485l360.013-340.471c38.933-36.82 40.119-98.352 2.633-136.64l-19.174-19.584zM741.705 227.52c12.625-12.4 32.934-12.201 45.316 0.444l19.174 19.584c12.497 12.762 12.1 33.273-0.879 45.547l-69.871 66.081-63.364-63.28 69.623-68.376zM626.445 340.713l62.511 62.427-243.648 230.426c-4.928 4.659-11.213 7.633-17.946 8.495l-58.232 7.433 15.908-64.99c1.412-5.769 4.407-11.034 8.648-15.198l232.759-228.593zM202.54 265.251c0-17.65 14.327-31.958 32-31.958h280.958c17.677 0 32-14.308 32-31.958s-14.323-31.958-32-31.958h-280.958c-53.019 0-96 42.924-96 95.874v533.695c0 52.949 42.981 95.872 96 95.872h529.065c53.022 0 96-42.923 96-95.872v-279.044c0-17.651-14.323-31.962-32-31.962-17.673 0-32 14.31-32 31.962v279.044c0 17.651-14.323 31.957-32 31.957h-529.065c-17.673 0-32-14.306-32-31.957v-533.695z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["new-chat"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":398,"id":47,"name":"new-chat","prevSize":32,"code":59745},"setIdx":0,"setId":0,"iconIdx":98},{"icon":{"paths":["M879.049 512c0-194.404-157.598-352-352-352-194.405 0-352 157.596-352 352 0 194.402 157.596 352 352 352 194.402 0 352-157.598 352-352zM943.049 512c0 229.751-186.249 416-416 416s-416-186.249-416-416c0-229.751 186.25-416 416-416s416 186.249 416 416zM415.047 383.995v256.001c0 17.673 14.325 32 32.002 32 17.673 0 32-14.327 32-32v-256.001c0-17.673-14.327-32-32-32-17.677 0-32.002 14.327-32.002 32zM575.044 383.995v256.001c0 17.673 14.327 32 32 32s32-14.327 32-32v-256.001c0-17.673-14.327-32-32-32s-32 14.327-32 32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["pause_outline"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":399,"id":46,"name":"pause_outline","prevSize":32,"code":59746},"setIdx":0,"setId":0,"iconIdx":99},{"icon":{"paths":["M529.301 928c229.751 0 416-186.249 416-416s-186.249-416-416-416c-229.75 0-415.999 186.249-415.999 416s186.249 416 415.999 416zM417.301 383.995c0-17.673 14.328-32 32-32s32 14.327 32 32v256.001c0 17.673-14.327 32-32 32s-32-14.327-32-32v-256.001zM577.301 383.995c0-17.673 14.323-32 32-32 17.673 0 32 14.327 32 32v256.001c0 17.673-14.327 32-32 32-17.677 0-32-14.327-32-32v-256.001z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["pause"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":400,"id":45,"name":"pause","prevSize":32,"code":59747},"setIdx":0,"setId":0,"iconIdx":100},{"icon":{"paths":["M838.165 153.373c12.497-12.497 32.759-12.497 45.257 0s12.497 32.758 0 45.255l-672 671.999c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l671.998-672.001zM588.407 569.067l-44.71 44.71c7.851 5.905 15.851 11.452 23.535 16.013 9.203 5.461 22.839 12.578 36.975 13.222 16.222 0.738 31.445-5.299 42.47-10.974 11.742-6.042 22.788-13.824 31.74-20.945 1.058-0.836 2.138-1.229 2.884-1.34 0.405-0.060 0.614-0.030 0.687-0.013l121.097 59.076c-5.577 29.329-20.378 66.769-42.389 92.621-11.23 13.184-23.198 22.037-35.388 26.317-11.597 4.075-25.404 4.766-42.654-1.673-48.422-18.074-103.407-53.154-151.689-89.263-14.029-10.492-27.298-20.919-39.467-30.844l-44.39 44.39c14.187 11.686 29.837 24.064 46.443 36.48 49.809 37.248 110.451 76.561 167.262 97.762 30.276 11.298 59.149 11.238 85.197 2.086 25.451-8.939 46.093-25.783 62.246-44.757 31.868-37.423 50.637-88.141 57.058-126.246 4.723-27.985-11.772-51.767-33.135-62.191l-122.807-59.908c-24.41-11.908-51.465-6.003-69.837 8.61-7.006 5.572-14.541 10.739-21.444 14.289-5.572 2.867-8.93 3.742-10.308 4.006l-0.094-0.038c-0.994-0.401-3.733-1.515-8.572-4.386-3.277-1.946-6.869-4.301-10.709-7.006zM326.431 589.683l44.39-44.39c-9.92-12.164-20.351-25.438-30.839-39.462-36.109-48.286-71.191-103.267-89.262-151.691-6.437-17.249-5.748-31.055-1.676-42.651 4.283-12.192 13.134-24.16 26.319-35.388 25.85-22.012 63.29-36.814 92.622-42.392l59.075 121.096c0.017 0.076 0.047 0.285-0.013 0.687-0.111 0.75-0.503 1.83-1.341 2.884-7.118 8.951-14.901 20.001-20.943 31.741-5.673 11.025-11.714 26.246-10.976 42.472 0.643 14.135 7.761 27.772 13.222 36.971 4.562 7.689 10.109 15.684 16.014 23.535l44.707-44.71c-2.701-3.836-5.056-7.433-7.002-10.709-2.871-4.838-3.985-7.578-4.386-8.567l-0.038-0.094c0.265-1.382 1.139-4.738 4.006-10.312 3.55-6.9 8.717-14.437 14.289-21.443 14.613-18.374 20.518-45.425 8.61-69.835l-59.91-122.809c-10.421-21.361-34.203-37.856-62.191-33.137-38.103 6.425-88.824 25.194-126.246 57.060-18.972 16.155-35.817 36.795-44.758 62.246-9.15 26.048-9.211 54.92 2.087 85.196 21.202 56.813 60.513 117.455 97.761 167.26 12.417 16.606 24.795 32.256 36.478 46.443z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["phone_disabled"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":401,"id":44,"name":"phone_disabled","prevSize":32,"code":59748},"setIdx":0,"setId":0,"iconIdx":101},{"icon":{"paths":["M835.362 700.309c23.612 8.508 53.538 2.842 70.827-22.601 23.539-34.637 47.279-88.691 51.405-142.588 2.095-27.324-0.725-56.482-12.992-83.234-12.557-27.379-33.963-49.885-64.853-64.647-57.963-27.7-132.228-44.291-196.911-54.061-65.092-9.831-123.46-13.179-151.275-13.179v68.72c24.375 0 79.603 3.066 141.901 12.475 62.703 9.471 129.621 24.95 179.029 48.558 17.596 8.414 27.345 19.686 32.934 31.876 5.875 12.813 8.192 29.009 6.737 48-2.85 37.227-19.674 77.867-37.321 105.020l-133.867-48.243c-0.073-0.043-0.247-0.183-0.503-0.542-0.474-0.67-0.986-1.818-1.148-3.29-1.361-12.497-3.789-27.149-8.021-40.981-3.977-12.988-10.799-29.525-23.403-41.574-10.978-10.492-26.402-15.565-37.295-18.47-12.518-3.345-26.863-5.7-40.922-7.39-28.22-3.396-58.603-4.501-78.127-4.501v68.719c17.762 0 45.538 1.033 70.63 4.053 12.599 1.515 23.701 3.435 32.196 5.705 5.73 1.532 8.589 2.795 9.626 3.255l0.098 0.043c0.832 1.28 2.675 4.57 4.685 11.136 2.492 8.128 4.25 18.010 5.316 27.793 2.795 25.66 18.505 51.298 45.487 61.022l135.765 48.926zM227.756 700.305c-23.615 8.512-53.54 2.842-70.828-22.596-23.537-34.637-47.277-88.691-51.405-142.588-2.093-27.324 0.727-56.482 12.995-83.234 12.556-27.38 33.962-49.886 64.852-64.648 57.966-27.701 132.23-44.292 196.913-54.063 65.089-9.832 123.462-13.176 151.28-13.176v68.72c-24.38 0-79.607 3.062-141.907 12.472-62.705 9.472-129.623 24.951-179.029 48.561-17.599 8.41-27.345 19.686-32.934 31.872-5.877 12.817-8.193 29.013-6.738 48 2.851 37.231 19.671 77.867 37.321 105.024l133.868-48.243c0.070-0.047 0.247-0.188 0.502-0.546 0.475-0.67 0.985-1.813 1.145-3.285 1.362-12.501 3.79-27.149 8.024-40.981 3.976-12.992 10.798-29.53 23.401-41.574 10.981-10.496 26.402-15.569 37.295-18.475 12.521-3.345 26.868-5.7 40.922-7.39 28.224-3.396 58.607-4.497 78.127-4.497v68.719c-17.758 0-45.538 1.028-70.63 4.049-12.599 1.515-23.701 3.439-32.196 5.705-5.728 1.532-8.59 2.795-9.627 3.255l-0.097 0.043c-0.831 1.28-2.675 4.57-4.686 11.136-2.489 8.132-4.249 18.010-5.315 27.797-2.796 25.655-18.505 51.294-45.49 61.018l-135.762 48.926z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["phone-off"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":402,"id":43,"name":"phone-off","prevSize":32,"code":59749},"setIdx":0,"setId":0,"iconIdx":102},{"icon":{"paths":["M421.043 204.615c-10.421-21.361-34.203-37.856-62.191-33.137-38.103 6.425-88.824 25.194-126.246 57.060-18.972 16.155-35.817 36.795-44.758 62.246-9.15 26.048-9.211 54.92 2.087 85.196 21.202 56.813 60.514 117.455 97.761 167.26 37.482 50.125 74.609 91.554 93.327 110.272l44.173-44.173c-16.405-16.405-51.598-55.539-87.472-103.509-36.108-48.286-71.191-103.267-89.262-151.691-6.437-17.249-5.748-31.055-1.675-42.651 4.282-12.192 13.134-24.16 26.319-35.388 25.85-22.012 63.29-36.814 92.622-42.392l59.075 121.096c0.018 0.075 0.047 0.285-0.012 0.687-0.111 0.75-0.504 1.83-1.343 2.884-7.118 8.951-14.9 20.001-20.943 31.741-5.673 11.025-11.714 26.246-10.976 42.472 0.643 14.135 7.761 27.772 13.222 36.971 6.277 10.577 14.417 21.743 22.792 32.29 16.806 21.175 36.54 42.33 49.677 55.467l44.173-44.173c-11.951-11.951-29.978-31.309-44.924-50.133-7.505-9.455-13.739-18.159-17.997-25.335-2.871-4.838-3.985-7.578-4.39-8.567l-0.038-0.094c0.265-1.382 1.139-4.738 4.006-10.312 3.554-6.9 8.721-14.437 14.289-21.443 14.613-18.374 20.523-45.425 8.614-69.835l-59.913-122.809zM829.922 613.5c21.363 10.423 37.858 34.206 33.139 62.191-6.426 38.106-25.195 88.823-57.062 126.246-16.154 18.974-36.791 35.819-62.246 44.757-26.048 9.152-54.921 9.212-85.193-2.086-56.815-21.201-117.457-60.514-167.262-97.762-50.125-37.483-91.554-74.607-110.273-93.325l44.173-44.173c16.406 16.405 55.54 51.597 103.51 87.471 48.286 36.109 103.266 71.189 151.693 89.263 17.246 6.434 31.053 5.747 42.65 1.673 12.19-4.279 24.158-13.133 35.388-26.317 22.012-25.852 36.813-63.292 42.394-92.621l-121.097-59.076c-0.077-0.017-0.286-0.047-0.687 0.013-0.751 0.111-1.83 0.503-2.884 1.34-8.951 7.121-20.002 14.903-31.744 20.945-11.025 5.675-26.244 11.712-42.47 10.974-14.135-0.644-27.772-7.761-36.971-13.222-10.577-6.276-21.743-14.417-32.29-22.788-21.171-16.811-42.33-36.544-55.467-49.681l44.173-44.173c11.951 11.951 31.309 29.982 50.133 44.928 9.455 7.501 18.159 13.734 25.335 17.997 4.838 2.871 7.578 3.985 8.567 4.386l0.094 0.038c1.382-0.265 4.736-1.139 10.313-4.006 6.899-3.55 14.434-8.717 21.444-14.289 18.372-14.613 45.423-20.518 69.833-8.61l122.807 59.908z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["phone"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":403,"id":42,"name":"phone","prevSize":32,"code":59750},"setIdx":0,"setId":0,"iconIdx":103},{"icon":{"paths":["M550.259 128.018c-72.38-1.375-144.906 25.78-199.307 80.524-54.654 54.999-89.302 136.056-89.301 239.466 0 80.23 44.5 174.869 97.546 252.804 53.065 77.965 120.829 148.16 176.142 175.821l15.194 7.603 14.805-8.333c217.161-122.15 272.311-333.879 272.311-427.895 0-101.732-27.921-181.775-80.179-236.931-52.343-55.247-125.295-81.503-207.211-83.060zM325.651 448.009c-0-88.591 29.353-152.747 70.698-194.353 41.598-41.862 97.069-62.705 152.694-61.648 68.992 1.311 124.041 23.055 161.967 63.089 38.020 40.126 62.639 102.647 62.639 192.913 0 74.551-44.689 253.679-224.175 363.034-39.684-25.613-92.186-79.855-137.369-146.24-50.954-74.863-86.454-156.22-86.454-216.794zM581.649 416c0-17.673-14.323-32-32-32-17.673 0-32 14.327-32 32s14.327 32 32 32c17.677 0 32-14.327 32-32zM645.649 416c0 53.018-42.978 96-96 96-53.018 0-96-42.982-96-96 0-53.019 42.982-96 96-96 53.022 0 96 42.981 96 96z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["pin-map"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":404,"id":41,"name":"pin-map","prevSize":32,"code":59751},"setIdx":0,"setId":0,"iconIdx":104},{"icon":{"paths":["M431.689 199.401c17.54-17.543 45.986-17.543 63.526 0 17.545 17.543 17.545 45.987 0 63.53l-43.657 43.659 177.826 177.827 60.343-60.338c24.99-24.994 65.515-24.994 90.509 0l45.252 45.256-331.866 331.87-45.257-45.257c-24.994-24.994-24.994-65.515 0-90.509l60.339-60.339-177.828-177.83-43.66 43.661c-17.543 17.545-45.987 17.545-63.53 0s-17.544-45.986 0-63.529l208.001-207.999zM178.433 362.145c-42.537 42.537-42.537 111.502 0 154.041 42.001 42.001 109.771 42.53 152.421 1.583l87.335 87.339-15.077 15.074c-49.987 49.988-49.987 131.034 0 181.022l67.881 67.878c12.497 12.497 32.759 12.497 45.257 0l167.932-167.932 88.017 92.002c12.215 12.77 32.474 13.222 45.244 1.003 12.77-12.215 13.218-32.474 1.003-45.244l-88.994-93.026 163.921-163.925c12.497-12.497 12.497-32.759 0-45.257l-67.883-67.88c-49.984-49.987-131.029-49.987-181.018 0l-15.906 15.907-87.326-87.322c41.766-42.596 41.51-110.984-0.768-153.262-42.539-42.537-111.501-42.537-154.039 0l-207.999 207.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["pin"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":405,"id":40,"name":"pin","prevSize":32,"code":59752},"setIdx":0,"setId":0,"iconIdx":105},{"icon":{"paths":["M520.286 928.004c229.751 0 416-186.249 416-416 0-229.749-186.249-415.999-416-415.999s-416.001 186.25-416.001 415.999c0 229.751 186.25 416 416.001 416zM460.134 357.193l195.255 136.768c14.204 9.95 18.496 30.874 9.579 46.729-2.432 4.322-5.705 7.979-9.579 10.692l-195.255 136.768c-14.208 9.95-32.956 5.163-41.87-10.692-3.036-5.397-4.646-11.644-4.646-18.018v-273.536c0-18.72 13.599-33.897 30.371-33.897 5.709 0 11.307 1.798 16.145 5.186z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["play"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":406,"id":39,"name":"play","prevSize":32,"code":59753},"setIdx":0,"setId":0,"iconIdx":106},{"icon":{"paths":["M547.776 208c0-17.673-14.323-32-32-32-17.673 0-32 14.327-32 32v271.996h-271.997c-17.673 0-32 14.327-32 32s14.327 32 32 32h271.997v272.004c0 17.673 14.327 32 32 32 17.677 0 32-14.327 32-32v-272.004h272.004c17.673 0 32-14.327 32-32-0.004-17.673-14.327-32-32.004-32h-272v-271.996z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["plus"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":407,"id":38,"name":"plus","prevSize":32,"code":59754},"setIdx":0,"setId":0,"iconIdx":107},{"icon":{"paths":["M476.924 704.371c0-33.643 26.278-47.676 72.73-47.676 46.447 0 72.725 14.033 72.725 47.676 0 32.96-13.188 111.070-23.91 149.764-4.966 17.805-22.080 25.169-48.815 25.169-26.739 0-43.853-7.364-48.815-25.173-10.714-38.665-23.915-116.689-23.915-149.76zM654.43 870.374l0.026-0.094c6.174-22.289 12.565-53.862 17.382-83.447 4.689-28.791 8.725-60.71 8.725-82.462 0-35.891-15.817-67.802-46.797-87.113-26.035-16.226-57.156-19.925-84.113-19.925-26.961 0-58.078 3.699-84.113 19.925-30.985 19.311-46.797 51.221-46.797 87.113 0 21.807 4.036 53.73 8.726 82.517 4.817 29.577 11.209 61.12 17.382 83.392l0.021 0.085c7.403 26.556 24.981 45.666 46.874 56.469 19.469 9.609 40.422 11.831 57.907 11.831 17.481 0 38.434-2.223 57.903-11.831 21.888-10.799 39.471-29.905 46.874-56.461zM497.289 460.8c0-28.275 23.441-51.2 52.365-51.2 28.919 0 52.361 22.925 52.361 51.2s-23.441 51.2-52.361 51.2c-28.924 0-52.365-22.925-52.365-51.2zM549.653 341.333c-67.482 0-122.185 53.487-122.185 119.467s54.703 119.467 122.185 119.467c67.477 0 122.18-53.487 122.18-119.467s-54.703-119.467-122.18-119.467zM715.456 537.254c-6.665 13.79-3.887 31.108 6.272 42.573 14.089 15.893 39.851 17.937 50.206-0.606 19.644-35.17 30.805-75.52 30.805-118.421 0-136.672-113.31-247.467-253.090-247.467-139.777 0-253.090 110.795-253.090 247.467 0 42.901 11.164 83.251 30.806 118.421 10.354 18.543 36.119 16.499 50.205 0.606 10.16-11.465 12.939-28.783 6.275-42.573-11.204-23.189-17.469-49.105-17.469-76.454 0-98.97 82.054-179.2 183.272-179.2s183.275 80.23 183.275 179.2c0 27.349-6.268 53.265-17.468 76.454zM767.812 699.793c-0.307-10.658 3.541-21.069 10.927-28.762 52.77-54.955 85.094-128.9 85.094-210.231 0-169.662-140.663-307.2-314.185-307.2-173.516 0-314.18 137.538-314.18 307.2 0 81.331 32.323 155.277 85.093 210.231 7.386 7.693 11.234 18.103 10.928 28.762-0.833 29.018-31.273 47.915-52.122 27.716-70.223-68.041-113.718-162.406-113.718-266.709 0-207.365 171.922-375.467 383.998-375.467 212.079 0 384 168.102 384 375.467 0 104.303-43.494 198.673-113.719 266.709-20.847 20.203-51.285 1.306-52.117-27.716z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["podcast"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":408,"id":37,"name":"podcast","prevSize":32,"code":59755},"setIdx":0,"setId":0,"iconIdx":108},{"icon":{"paths":["M395.145 448c0-17.673 14.327-32 31.999-32h213.333c17.673 0 32 14.327 32 32s-14.327 32-32 32h-213.333c-17.672 0-31.999-14.327-31.999-32z","M427.145 544c-17.672 0-31.999 14.327-31.999 32s14.327 32 31.999 32h213.333c17.673 0 32-14.327 32-32s-14.327-32-32-32h-213.333z","M277.812 128c-17.673 0-32 14.327-32 32v704c0 17.673 14.327 32 32 32h511.999c17.673 0 32-14.327 32-32v-501.745c0-6.67-2.082-13.172-5.961-18.6l-144.465-202.255c-6.007-8.41-15.706-13.4-26.039-13.4h-367.534zM757.811 372.51v459.49h-447.999v-640h319.064l128.934 180.51z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["post"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":409,"id":36,"name":"post","prevSize":32,"code":59756},"setIdx":0,"setId":0,"iconIdx":109},{"icon":{"paths":["M236.518 636.689c-14.92-9.472-34.694-5.056-44.167 9.86-9.473 14.921-5.057 34.697 9.863 44.169l298.667 189.632c10.466 6.643 23.834 6.643 34.304 0l298.667-189.632c14.921-9.472 19.337-29.248 9.865-44.169-9.476-14.916-29.248-19.332-44.169-9.86l-281.515 178.739-281.515-178.739zM192.351 494.848c9.473-14.921 29.247-19.337 44.167-9.865l281.515 178.743 281.515-178.743c14.921-9.472 34.692-5.056 44.169 9.865 9.472 14.921 5.056 34.692-9.865 44.169l-298.667 189.628c-10.47 6.647-23.838 6.647-34.304 0l-298.668-189.628c-14.92-9.476-19.335-29.248-9.862-44.169zM535.185 143.657l298.667 189.63c9.246 5.871 14.848 16.062 14.848 27.014s-5.602 21.144-14.848 27.015l-298.667 189.631c-10.47 6.647-23.838 6.647-34.304 0l-298.667-189.631c-9.246-5.871-14.848-16.062-14.848-27.015s5.602-21.144 14.848-27.014l298.667-189.63c10.466-6.647 23.834-6.647 34.304 0zM279.066 360.302l238.967 151.724 238.967-151.724-238.967-151.725-238.967 151.725z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["queue"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":410,"id":35,"name":"queue","prevSize":32,"code":59757},"setIdx":0,"setId":0,"iconIdx":110},{"icon":{"paths":["M197.594 224c-11.706 0-22.477 6.391-28.087 16.666s-5.161 22.792 1.169 32.638l112.304 174.696h-69.387c-17.673 0-32 14.327-32 32v288c0 17.673 14.327 32 32 32h256c17.673 0 32-14.327 32-32v-288c0-6.135-1.762-12.143-5.082-17.306l-144-223.999c-5.888-9.159-16.029-14.696-26.918-14.696h-128zM368.512 462.694l-112.305-174.694h51.916l129.47 201.399v246.601h-192v-224h96c11.706 0 22.478-6.391 28.087-16.666s5.161-22.793-1.169-32.64zM613.594 224c-11.708 0-22.477 6.391-28.087 16.666-5.606 10.274-5.158 22.792 1.169 32.638l112.307 174.696h-69.389c-17.673 0-32 14.327-32 32v288c0 17.673 14.327 32 32 32h256c17.673 0 32-14.327 32-32v-288c0-6.135-1.762-12.143-5.082-17.306l-144-223.999c-5.888-9.159-16.030-14.696-26.918-14.696h-128zM784.512 462.694l-112.303-174.694h51.913l129.472 201.399v246.601h-192v-224h96c11.708 0 22.477-6.391 28.087-16.666s5.158-22.793-1.169-32.64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["quote"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":411,"id":34,"name":"quote","prevSize":32,"code":59758},"setIdx":0,"setId":0,"iconIdx":111},{"icon":{"paths":["M865.084 512c0-176.731-143.27-320-320-320-176.732 0-320 143.269-320 320 0 176.73 143.269 320 320 320 176.73 0 320-143.27 320-320zM929.084 512c0 212.079-171.921 384-384 384-212.078 0-384-171.921-384-384 0-212.077 171.923-384 384-384 212.079 0 384 171.923 384 384zM545.084 704c-106.039 0-192-85.961-192-192s85.961-192 192-192c106.039 0 192 85.961 192 192s-85.961 192-192 192z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["rec"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":412,"id":33,"name":"rec","prevSize":32,"code":59759},"setIdx":0,"setId":0,"iconIdx":112},{"icon":{"paths":["M922.321 512h-63.983c0-175.415-145.754-320-328.521-320-115.27 0-215.817 57.513-274.36 144h110.768c17.673 0 32 14.327 32 32s-14.327 32-32 32h-179.904c-17.673 0-32-14.327-32-32v-192c0-17.673 14.327-32 32-32s32 14.327 32 32v102.32c71.751-91.401 184.591-150.32 311.496-150.32 216.781 0 392.503 171.923 392.503 384 0 1.114 0.009 2.227 0 3.337v-3.337z","M154.319 512h63.986c0 175.415 145.752 320 328.519 320 115.268 0 215.817-57.515 274.359-144h-110.767c-17.673 0-32-14.327-32-32s14.327-32 32-32h179.904c17.673 0 32 14.327 32 32v192c0 17.673-14.327 32-32 32s-32-14.327-32-32v-102.319c-71.753 91.401-184.593 150.319-311.497 150.319-216.783 0-392.505-171.921-392.505-384 0-1.084-0.009-2.163 0-3.247v3.247z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["refresh"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":413,"id":32,"name":"refresh","prevSize":32,"code":59760},"setIdx":0,"setId":0,"iconIdx":113},{"icon":{"paths":["M922.325 238.961l-297.476 637.446c-16.853 36.113-69.619 31.458-79.889-7.049l-66.001-247.501 151.249-189.056-219.993 109.995-226.834-113.417c-35.43-17.715-29.696-69.947 8.733-79.555l681.201-170.3c34.837-8.71 64.196 26.892 49.011 59.436z"],"attrs":[{"fill":"rgb(29, 116, 245)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["send-active"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":3}]}},"attrs":[{"fill":"rgb(29, 116, 245)"}],"properties":{"order":414,"id":31,"name":"send-active","prevSize":32,"code":59761},"setIdx":0,"setId":0,"iconIdx":114},{"icon":{"paths":["M906.598 192.976c7.851 9.521 9.527 22.708 4.309 33.891l-298.667 640c-5.692 12.194-18.406 19.529-31.812 18.342-13.406-1.182-24.636-10.628-28.105-23.629l-81.621-306.074-285.77-142.884c-11.978-5.989-18.959-18.802-17.498-32.113s11.056-24.305 24.048-27.553l682.668-170.667c11.972-2.993 24.597 1.165 32.448 10.686zM534.396 545.967l57.084 214.054 233.028-499.351-533.582 133.396 203.606 101.802 69.513-52.134c14.135-10.603 34.193-7.735 44.8 6.4 10.603 14.14 7.735 34.197-6.4 44.8l-68.049 51.034z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["send"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":415,"id":30,"name":"send","prevSize":32,"code":59762},"setIdx":0,"setId":0,"iconIdx":115},{"icon":{"paths":["M732.22 300.76c12.497-12.854 12.497-33.694 0-46.548l-160-164.571c-12.497-12.854-32.755-12.854-45.252 0l-160.001 164.571c-12.497 12.854-12.497 33.694 0 46.548s32.758 12.854 45.255 0l105.373-108.383v430.711c0 18.176 14.327 32.913 32 32.913s32-14.737 32-32.913v-430.711l105.374 108.384c12.497 12.854 32.755 12.854 45.252 0z","M229.594 384h160v64h-128v416h576v-416h-128v-64h160c17.673 0 32 14.327 32 32v480c0 17.673-14.327 32-32 32h-640c-17.673 0-32-14.327-32-32v-480c0-17.673 14.327-32 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["share"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":416,"id":29,"name":"share","prevSize":32,"code":59763},"setIdx":0,"setId":0,"iconIdx":116},{"icon":{"paths":["M697.165 405.072c11.639-13.3 10.291-33.517-3.008-45.155-13.303-11.638-33.519-10.29-45.154 3.011l-125.252 143.146-39.919-45.623c-11.635-13.299-31.855-14.647-45.154-3.008-13.3 11.635-14.647 31.855-3.008 45.154l64 73.143c6.076 6.942 14.852 10.927 24.081 10.927s18.005-3.985 24.081-10.927l149.333-170.668z","M575.074 143.050c-12.855-3.633-26.449-3.753-39.364-0.345l-264.723 69.849c-29.793 7.861-52.548 33.743-54.753 65.633-23.59 341.205 187.75 520.29 276.51 579.793 33.135 22.212 75.362 22.144 108.416-0.26 88.218-59.789 297.118-239.070 272.61-580.212-2.249-31.321-24.337-56.895-53.504-65.14l-245.193-69.318zM552.038 204.588c1.847-0.487 3.789-0.47 5.623 0.049l245.197 69.318c4.292 1.214 6.839 4.781 7.078 8.139 22.148 308.363-165.303 468.849-244.685 522.652-11.439 7.753-25.365 7.791-36.873 0.077-80.081-53.687-269.603-214.054-248.298-522.22 0.235-3.389 2.833-7.003 7.234-8.165l264.723-69.849z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["shield-check"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":417,"id":28,"name":"shield-check","prevSize":32,"code":59764},"setIdx":0,"setId":0,"iconIdx":117},{"icon":{"paths":["M548.638 142.705c12.919-3.408 26.509-3.288 39.364 0.345l245.197 69.318c29.163 8.245 51.251 33.818 53.504 65.14 24.503 341.142-184.397 520.423-272.614 580.212-33.050 22.404-75.281 22.473-108.416 0.26-88.759-59.503-300.099-238.588-276.509-579.793 2.205-31.89 24.96-57.772 54.753-65.633l264.722-69.849zM570.59 204.637c-1.835-0.519-3.776-0.536-5.623-0.049l-264.722 69.849c-4.4 1.161-6.999 4.776-7.233 8.165-21.305 308.166 168.216 468.533 248.301 522.22 11.507 7.714 25.434 7.676 36.873-0.077 79.377-53.803 266.833-214.289 244.681-522.652-0.239-3.358-2.786-6.925-7.078-8.139l-245.197-69.318z","M526.012 337.336c-19.759 4.672-47.249 12.307-81.152 24.553 20.813 108.772 53.222 187.014 81.152 238.833v-263.385zM528.205 271.316c33.771-6.898 61.807 19.742 61.807 51.124v360.965c0 17.024-10.334 31.748-25.643 37.521-15.671 5.909-33.779 1.331-44.86-12.676-32.657-41.267-106.324-152.947-141.192-354.563-3.241-18.744 7.065-37.694 25.329-44.726 56.185-21.63 99.095-32.442 124.559-37.644z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["shield"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":418,"id":27,"name":"shield","prevSize":32,"code":59765},"setIdx":0,"setId":0,"iconIdx":118},{"icon":{"paths":["M802.705 213.333c-17.673 0-32 14.327-32 32v533.333c0 17.673 14.327 32 32 32s32-14.327 32-32v-533.333c0-17.673-14.327-32-32-32z","M624.939 341.333c-17.677 0-32 14.327-32 32v405.333c0 17.673 14.323 32 32 32 17.673 0 32-14.327 32-32v-405.333c0-17.673-14.327-32-32-32z","M447.168 810.667c-17.673 0-31.999-14.327-31.999-32v-277.333c0-17.673 14.326-32 31.999-32s32 14.327 32 32v277.333c0 17.673-14.327 32-32 32z","M269.4 597.333c-17.673 0-32 14.327-32 32v149.333c0 17.673 14.327 32 32 32s32-14.327 32-32v-149.333c0-17.673-14.327-32-32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["signal"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":419,"id":26,"name":"signal","prevSize":32,"code":59766},"setIdx":0,"setId":0,"iconIdx":119},{"icon":{"paths":["M658.731 204.798c16.495 6.344 24.725 24.859 18.381 41.354l-213.333 554.667c-6.345 16.495-24.862 24.725-41.356 18.381-16.495-6.345-24.724-24.862-18.38-41.357l213.335-554.666c6.345-16.495 24.858-24.724 41.353-18.38zM349.871 361.371c12.497 12.497 12.497 32.758 0 45.255l-105.373 105.374 105.373 105.37c12.497 12.497 12.497 32.759 0 45.257s-32.758 12.497-45.255 0l-128-128c-12.497-12.497-12.497-32.759 0-45.257l128-127.999c12.497-12.497 32.758-12.497 45.255 0zM731.281 361.371c12.497-12.497 32.759-12.497 45.257 0l128 127.999c12.497 12.497 12.497 32.759 0 45.257l-128 128c-12.497 12.497-32.759 12.497-45.257 0s-12.497-32.759 0-45.257l105.374-105.37-105.374-105.374c-12.497-12.497-12.497-32.758 0-45.255z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["snippet"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":420,"id":25,"name":"snippet","prevSize":32,"code":59767},"setIdx":0,"setId":0,"iconIdx":120},{"icon":{"paths":["M312.019 192c13.364 0 25.321 8.305 29.987 20.829l96.002 257.699c6.17 16.559-2.257 34.987-18.817 41.156-16.561 6.17-34.988-2.253-41.158-18.816l-20.476-54.963h-91.075l-20.476 54.963c-6.17 16.563-24.596 24.986-41.158 18.816s-24.986-24.597-18.816-41.156l96-257.699c4.666-12.524 16.623-20.829 29.987-20.829zM333.714 373.904l-21.695-58.238-21.696 58.238h43.391z","M544.789 626.436c-12.156 12.826-11.61 33.079 1.22 45.235l160 151.586c12.343 11.695 31.676 11.695 44.019 0l160-151.586c12.83-12.156 13.376-32.41 1.22-45.235-12.156-12.83-32.41-13.38-45.239-1.225l-105.988 100.42v-501.632c0-17.673-14.327-32-32-32-17.677 0-32 14.327-32 32v501.632l-105.993-100.42c-12.83-12.156-33.084-11.605-45.239 1.225z","M216.019 570.944c-17.673 0-32 14.327-32 32 0 17.677 14.327 32 32 32h116.145l-139.065 142.733c-8.979 9.216-11.565 22.916-6.564 34.769 5.001 11.857 16.617 19.563 29.484 19.563h192c17.673 0 32.002-14.327 32.002-32s-14.329-32-32.002-32h-116.145l139.063-142.733c8.981-9.216 11.567-22.912 6.566-34.769-5.001-11.853-16.618-19.563-29.485-19.563h-192z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["sort az"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":421,"id":24,"name":"sort-az","prevSize":32,"code":59768},"setIdx":0,"setId":0,"iconIdx":121},{"icon":{"paths":["M930.837 666.347c12.591-12.237 12.86-32.35 0.606-44.924-12.254-12.57-32.393-12.843-44.979-0.602l-105.975 103.019v-500.14c0-17.545-14.242-31.768-31.808-31.768-17.57 0-31.808 14.223-31.808 31.768v500.14l-105.975-103.019c-12.587-12.241-32.725-11.968-44.979 0.602-12.254 12.574-11.985 32.687 0.606 44.924l159.97 155.511c12.348 12.006 32.026 12.006 44.373 0l159.97-155.511zM572.715 333.224c17.566 0 31.808-14.223 31.808-31.767s-14.242-31.767-31.808-31.767h-431.921c-17.568 0-31.81 14.223-31.81 31.767s14.242 31.767 31.81 31.767h431.921zM476.732 535.39c17.566 0 31.808-14.221 31.808-31.765 0-17.549-14.242-31.77-31.808-31.77h-335.938c-17.568 0-31.81 14.221-31.81 31.77 0 17.545 14.242 31.765 31.81 31.765h335.938zM396.746 722.005c17.568 0 31.811-14.225 31.811-31.77s-14.243-31.765-31.811-31.765h-255.952c-17.568 0-31.81 14.221-31.81 31.765s14.242 31.77 31.81 31.77h255.952z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["sort-1"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":422,"id":23,"name":"sort-1","prevSize":32,"code":59769},"setIdx":0,"setId":0,"iconIdx":122},{"icon":{"paths":["M724.019 626.56c12.676-12.314 32.934-12.023 45.252 0.649 12.318 12.676 12.023 32.934-0.649 45.252l-208 202.121c-12.42 12.066-32.183 12.066-44.604 0l-207.998-202.121c-12.675-12.318-12.965-32.576-0.649-45.252 12.317-12.672 32.576-12.962 45.25-0.649l185.699 180.45 185.698-180.45zM724.019 416.798c12.676 12.317 32.934 12.027 45.252-0.649 12.318-12.675 12.023-32.934-0.649-45.25l-208-202.119c-12.42-12.067-32.183-12.067-44.604 0l-207.998 202.119c-12.675 12.316-12.965 32.576-0.649 45.25 12.317 12.676 32.576 12.966 45.25 0.649l185.699-180.449 185.698 180.449z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["sort"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":423,"id":22,"name":"sort","prevSize":32,"code":59770},"setIdx":0,"setId":0,"iconIdx":123},{"icon":{"paths":["M207.049 405.333h213.333v-213.333h-213.333v213.333zM143.049 170.667c0-23.564 19.103-42.667 42.667-42.667h255.999c23.565 0 42.667 19.103 42.667 42.667v256c0 23.565-19.102 42.667-42.667 42.667h-255.999c-23.564 0-42.667-19.102-42.667-42.667v-256zM633.715 405.333h213.333v-213.333h-213.333v213.333zM569.715 170.667c0-23.564 19.102-42.667 42.667-42.667h256c23.565 0 42.667 19.103 42.667 42.667v256c0 23.565-19.102 42.667-42.667 42.667h-256c-23.565 0-42.667-19.102-42.667-42.667v-256zM633.715 618.667h213.333v213.333h-213.333v-213.333zM612.382 554.667c-23.565 0-42.667 19.102-42.667 42.667v256c0 23.565 19.102 42.667 42.667 42.667h256c23.565 0 42.667-19.102 42.667-42.667v-256c0-23.565-19.102-42.667-42.667-42.667h-256zM207.049 832h213.333v-213.333h-213.333v213.333zM143.049 597.333c0-23.565 19.103-42.667 42.667-42.667h255.999c23.565 0 42.667 19.102 42.667 42.667v256c0 23.565-19.102 42.667-42.667 42.667h-255.999c-23.564 0-42.667-19.102-42.667-42.667v-256z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["squares"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":424,"id":21,"name":"squares","prevSize":32,"code":59771},"setIdx":0,"setId":0,"iconIdx":124},{"icon":{"paths":["M618.005 170.244c-20.868-57.726-103.155-55.816-121.323 2.816l-58.974 190.35h-221.514c-58.947 0-86.549 72.943-42.37 111.965l157.591 139.204-53.209 216.93c-14.17 57.771 51.25 101.935 99.535 67.2l177.74-127.881 177.741 127.881c48.286 34.735 113.702-9.429 99.533-67.2l-53.385-217.651 147.891-139.968c42.031-39.778 13.875-110.481-43.994-110.481h-195.439l-69.824-193.165z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["star-filled"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":425,"id":20,"name":"star-filled","prevSize":32,"code":59772},"setIdx":0,"setId":0,"iconIdx":125},{"icon":{"paths":["M494.43 172.834c18.163-58.554 100.454-60.462 121.323-2.812l69.82 192.91h195.443c57.869 0 86.025 70.608 43.989 110.335l-147.887 139.785 53.385 217.361c14.17 57.694-51.251 101.803-99.533 67.11l-177.741-127.706-177.742 127.706c-48.284 34.692-113.705-9.417-99.535-67.11l53.209-216.64-157.591-139.021c-44.179-38.976-16.577-111.82 42.37-111.82h221.511l58.978-190.098zM625.387 384.66l-69.824-192.91-58.978 190.098c-8.299 26.758-33.079 44.998-61.133 44.998h-221.511l157.591 139.025c17.834 15.731 25.456 40.047 19.787 63.125l-53.209 216.644 177.743-127.706c22.327-16.047 52.425-16.047 74.752 0l177.741 127.706-53.385-217.361c-5.483-22.319 1.451-45.854 18.163-61.649l147.891-139.785h-195.443c-26.957 0-51.025-16.868-60.186-42.186z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["star"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":426,"id":19,"name":"star","prevSize":32,"code":59773},"setIdx":0,"setId":0,"iconIdx":126},{"icon":{"paths":["M556.403 548.215h-255.503c-20.173 0-36.527-16.354-36.527-36.527s16.354-36.527 36.527-36.527h102.99c-21.547-22.75-32.32-50.118-32.32-82.102 0-39.587 15.766-72.27 47.297-98.048 31.76-26.008 72.959-39.012 123.596-39.012 34.522 0 65.25 6.675 92.177 20.024 27.162 13.349 48.102 31.762 62.835 55.238 8.849 13.888 15.083 28.54 18.697 43.958 4.198 17.914-11.174 33.030-29.572 33.030s-32.499-15.279-37.828-32.89c-4.617-15.263-12.779-28.121-24.486-38.574-19.332-17.492-46.609-26.238-81.822-26.238-32.683 0-58.231 7.25-76.642 21.75-18.185 14.27-27.277 34.179-27.277 59.726 0 20.484 8.631 37.86 25.894 52.132 13.764 11.046 35.012 21.385 63.744 31.006h247.556c20.173 0 36.527 16.354 36.527 36.527s-16.354 36.527-36.527 36.527h-90.027c7.138 7.215 13.133 14.878 17.975 22.989 11.507 18.871 17.263 41.079 17.263 66.628 0 40.738-15.881 73.421-47.642 98.048-31.761 24.397-74.227 36.595-127.394 36.595-34.522 0-66.748-6.558-96.666-19.678-29.922-13.35-53.053-31.531-69.394-54.549-9.777-13.965-16.588-29.077-20.432-45.338-4.233-17.903 11.182-33.028 29.581-33.028s32.466 15.364 38.447 32.764c5.316 15.475 14.771 28.604 28.356 39.39 22.558 17.493 52.591 26.236 90.108 26.236 34.982 0 61.798-7.134 80.439-21.402 18.645-14.272 27.964-33.719 27.964-58.347s-8.627-43.614-25.89-56.964c-14.332-11.273-38.34-22.387-72.026-33.344z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["strike"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":427,"id":18,"name":"strike","prevSize":32,"code":59774},"setIdx":0,"setId":0,"iconIdx":127},{"icon":{"paths":["M513.084 117.333c0-17.673 14.327-32 32-32s32 14.327 32 32v106.667c0 17.673-14.327 32-32 32s-32-14.327-32-32v-106.667zM803.123 214.629c12.497-12.497 32.759-12.497 45.257 0s12.497 32.758 0 45.255l-75.413 75.412c-12.497 12.497-32.759 12.497-45.257 0s-12.497-32.758 0-45.255l75.413-75.412zM368.46 694.63c-12.497-12.497-32.758-12.497-45.255 0l-75.495 75.494c-12.497 12.497-12.497 32.755 0 45.252s32.758 12.497 45.255 0l75.495-75.494c12.497-12.497 12.497-32.755 0-45.252zM513.084 800c0-17.673 14.327-32 32-32s32 14.327 32 32v106.667c0 17.673-14.327 32-32 32s-32-14.327-32-32v-106.667zM245.084 211.999c-12.497 12.497-12.497 32.758 0 45.255l75.349 75.349c12.497 12.497 32.758 12.497 45.255 0s12.497-32.758 0-45.255l-75.349-75.349c-12.497-12.497-32.758-12.497-45.255 0zM727.71 739.883c-12.497-12.497-12.497-32.759 0-45.257s32.759-12.497 45.257 0l75.328 75.328c12.497 12.497 12.497 32.759 0 45.257s-32.759 12.497-45.257 0l-75.328-75.328zM119.483 512c0 17.673 14.327 32 32 32h106.666c17.673 0 32-14.327 32-32s-14.327-32-32-32h-106.667c-17.673 0-32 14.327-32 32zM833.084 544c-17.673 0-32-14.327-32-32s14.327-32 32-32h106.667c17.673 0 32 14.327 32 32s-14.327 32-32 32h-106.667zM699.9 512c0-85.505-69.316-154.82-154.82-154.82s-154.818 69.315-154.818 154.82c0 85.504 69.314 154.816 154.818 154.816s154.82-69.312 154.82-154.816zM758.413 512c0 117.82-95.509 213.333-213.333 213.333-117.82 0-213.332-95.514-213.332-213.333 0-117.822 95.512-213.335 213.332-213.335 117.824 0 213.333 95.513 213.333 213.335z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Sun"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":428,"id":17,"name":"Sun","prevSize":32,"code":59775},"setIdx":0,"setId":0,"iconIdx":128},{"icon":{"paths":["M376.285 412.435c-53.592 0-96-42.819-96-94.367s42.408-94.366 96-94.366c53.594 0 96.001 42.819 96.001 94.366s-42.406 94.367-96.001 94.367zM376.285 476.352c88.368 0 160.001-70.867 160.001-158.284s-71.633-158.282-160.001-158.282c-88.365 0-160 70.865-160 158.282s71.635 158.284 160 158.284zM721.886 396.606c-35.921 0-64-28.646-64-62.71s28.079-62.71 64-62.71c35.917 0 64 28.646 64 62.71s-28.083 62.71-64 62.71zM721.886 460.523c70.69 0 128-56.693 128-126.626s-57.31-126.626-128-126.626c-70.694 0-128 56.692-128 126.626s57.306 126.626 128 126.626zM205.744 526.571c27.344-8.695 56.671-9.229 84.32-1.536l48.489 13.491c24.207 6.733 49.884 6.268 73.824-1.348l30.102-9.57c29.474-9.37 61.086-9.946 90.889-1.655 67.959 18.91 114.918 80.226 114.918 150.071v91.866c0 52.45-42.982 94.967-96 94.967h-352.001c-53.019 0-96-42.517-96-94.967v-103.633c0-62.822 40.999-118.46 101.459-137.685zM272.736 585.98c-15.545-4.322-32.033-4.023-47.407 0.866-33.993 10.807-57.044 42.091-57.044 77.41v103.633c0 17.485 14.327 31.654 32 31.654h352.001c17.673 0 32-14.17 32-31.654v-91.866c0-41.476-27.887-77.892-68.25-89.122-17.698-4.924-36.471-4.582-53.973 0.981l-30.101 9.57c-35.91 11.422-74.425 12.122-110.737 2.018l-48.489-13.491zM699.486 777.685h140.8c53.018 0 96-42.923 96-95.872v-30.571c0-56.802-38.618-106.351-93.751-120.294-21.397-5.414-43.849-5.035-65.054 1.092l-16.401 4.745c-21.841 6.31-44.971 6.703-67.012 1.126l-29.811-7.539c-19.904-5.035-40.794-4.685-60.518 1.015-1.062 0.311-2.125 0.631-3.174 0.969 10.714 4.045 20.894 9.527 30.255 16.354l2.428 1.771 15.040 13.193c9.937 8.713 18.142 19.221 24.183 30.972l2.206 4.292 3.678 0.934c33.062 8.363 67.759 7.778 100.523-1.694l16.401-4.74c10.283-2.974 21.171-3.157 31.548-0.529 26.735 6.763 45.461 30.788 45.461 58.334v30.571c0 17.651-14.327 31.957-32 31.957h-140.8v63.915z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["team"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":429,"id":16,"name":"team","prevSize":32,"code":59776},"setIdx":0,"setId":0,"iconIdx":129},{"icon":{"paths":["M227.087 308.609c-47.831 66.699-64.077 147.668-64.077 201.185v1.404l-0.127 1.399c-9.348 103.236 27.547 175.996 86.848 226.377 60.643 51.516 146.604 80.998 235.291 90.893 88.61 9.886 186.223 1.399 263.339-14.976 38.562-8.188 70.929-18.121 93.888-28.126 8.909-3.883 15.838-7.535 20.945-10.765-2.377-1.515-5.248-3.196-8.678-5.030-8.883-4.749-19.055-9.263-29.611-13.897l-1.843-0.806c-9.314-4.083-19.725-8.649-27.61-13.077-14.293-8.030-28.318-17.156-38.545-26.867-5.035-4.783-10.761-11.196-14.596-19.183-4.058-8.457-6.959-21.082-1.259-34.436 30.814-72.188 45.457-111.727 52.548-137.835 6.622-24.38 6.622-36.655 6.622-56.171v-0.179c0-15.514-8.977-86.595-53.777-152.876-43.371-64.175-121.395-125.729-264.828-125.729-129.727 0-207.831 53.576-254.531 118.696zM177.043 272.433c58.132-81.062 154.749-144.433 304.574-144.433 164.894 0 261.594 72.589 315.857 152.878 52.838 78.182 64.414 161.879 64.414 187.641 0 21.658-0.017 40.337-8.794 72.64-7.834 28.834-22.626 68.617-50.048 133.423 5.069 4.036 12.591 9.003 22.507 14.571 5.12 2.876 12.992 6.34 24.055 11.191 10.261 4.51 22.579 9.933 33.89 15.979 10.846 5.798 23.526 13.572 32.951 23.74 9.86 10.633 20.211 28.868 12.817 51.136-4.873 14.673-16.183 25.092-25.609 32.017-10.24 7.522-22.946 14.281-36.86 20.343-27.947 12.177-64.58 23.181-105.681 31.906-82.197 17.451-186.522 26.688-282.906 15.936-96.31-10.743-195.347-43.174-268.314-105.165-74.031-62.891-119.295-154.778-108.551-277.854 0.276-63.411 19.118-157.053 75.696-235.949zM337.729 422.052c0-17.648 14.25-31.955 31.828-31.955h183.011c17.574 0 31.825 14.307 31.825 31.955s-14.251 31.955-31.825 31.955h-183.011c-17.578 0-31.828-14.306-31.828-31.955zM369.557 539.708c-17.578 0-31.828 14.306-31.828 31.957 0 17.647 14.25 31.953 31.828 31.953h224.12c17.579 0 31.825-14.306 31.825-31.953 0-17.651-14.246-31.957-31.825-31.957h-224.12z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["threads"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":430,"id":15,"name":"threads","prevSize":32,"code":59777},"setIdx":0,"setId":0,"iconIdx":130},{"icon":{"paths":["M485.811 318.068c0-51.548-42.406-94.366-95.999-94.366s-96 42.819-96 94.366c0 51.548 42.408 94.367 96 94.367s95.999-42.819 95.999-94.367zM549.811 318.068c0 87.417-71.633 158.284-159.999 158.284s-160-70.867-160-158.284c0-87.417 71.634-158.282 160-158.282s159.999 70.865 159.999 158.282zM303.591 525.035c-27.649-7.693-56.976-7.159-84.32 1.536-60.46 19.226-101.459 74.863-101.459 137.685v103.633c0 52.45 42.981 94.967 96 94.967h351.999c3.605 0 7.164-0.196 10.667-0.576v-64.538c-3.337 1.169-6.925 1.801-10.667 1.801h-351.999c-17.673 0-32-14.17-32-31.654v-103.633c0-35.319 23.051-66.603 57.043-77.41 15.374-4.89 31.862-5.188 47.407-0.866l48.489 13.491c36.311 10.103 74.826 9.404 110.739-2.018l30.097-9.57c17.506-5.564 36.279-5.905 53.978-0.981 18.901 5.257 35.068 16.038 46.912 30.281v-79.714c-9.31-4.749-19.2-8.627-29.585-11.516-29.803-8.29-61.414-7.714-90.889 1.655l-30.1 9.57c-23.941 7.616-49.617 8.081-73.825 1.348l-48.489-13.491zM785.182 489.033c-12.331-12.651-32.589-12.919-45.252-0.61s-12.937 32.542-0.61 45.193l102.844 105.506h-324.352c-17.673 0-32 14.31-32 31.962 0 17.647 14.327 31.957 32 31.957h324.352l-102.844 105.51c-12.326 12.646-12.053 32.879 0.61 45.188 12.663 12.314 32.922 12.041 45.252-0.606l155.716-159.761c12.092-12.407 12.092-32.175 0-44.582l-155.716-159.757z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["transfer"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":431,"id":14,"name":"transfer","prevSize":32,"code":59778},"setIdx":0,"setId":0,"iconIdx":131},{"icon":{"paths":["M769.084 864.209v-447.408h-448v447.408h448zM257.083 864.209v-447.408c-35.346 0-64-28.616-64-63.916v-127.831c0-35.299 28.654-63.916 64-63.916h224c0-35.299 28.655-63.915 64-63.915s64 28.616 64 63.915h224c35.345 0 64 28.616 64 63.916v127.831c0 35.299-28.655 63.916-64 63.916v447.408c0 35.298-28.655 63.915-64 63.915h-448c-35.346 0-64-28.617-64-63.915zM833.084 225.055h-576v127.831h576v-127.831zM449.084 544.631v191.748c0 17.647 14.327 31.957 32 31.957s32-14.31 32-31.957v-191.748c0-17.647-14.327-31.957-32-31.957s-32 14.31-32 31.957zM609.084 512.674c17.673 0 32 14.31 32 31.957v191.748c0 17.647-14.327 31.957-32 31.957s-32-14.31-32-31.957v-191.748c0-17.647 14.327-31.957 32-31.957z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["trash"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":432,"id":13,"name":"trash","prevSize":32,"code":59779},"setIdx":0,"setId":0,"iconIdx":132},{"icon":{"paths":["M810.667 576c-35.345 0-64-28.655-64-64s28.655-64 64-64c35.345 0 64 28.655 64 64s-28.655 64-64 64z","M554.667 576c-35.345 0-64-28.655-64-64s28.655-64 64-64c35.345 0 64 28.655 64 64s-28.655 64-64 64z","M298.667 576c-35.346 0-64-28.655-64-64s28.654-64 64-64c35.346 0 64 28.655 64 64s-28.654 64-64 64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["truncation"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":433,"id":12,"name":"truncation","prevSize":32,"code":59780},"setIdx":0,"setId":0,"iconIdx":133},{"icon":{"paths":["M408.067 320c0-17.673-14.327-32-32-32s-32 14.327-32 32v256c0 106.039 85.962 192 192.002 192 106.035 0 192-85.961 192-192v-256c0-17.673-14.327-32-32-32-17.677 0-32 14.327-32 32v256c0 70.694-57.31 128-128 128-70.694 0-128.002-57.306-128.002-128v-256zM376.067 848c-17.673 0-32 14.327-32 32s14.327 32 32 32h320.002c17.673 0 32-14.327 32-32s-14.327-32-32-32h-320.002z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["underline"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":434,"id":11,"name":"underline","prevSize":32,"code":59781},"setIdx":0,"setId":0,"iconIdx":134},{"icon":{"paths":["M536.068 832c176.73 0 320-143.27 320-320 0-176.731-143.27-320-320-320-111.715 0-210.058 57.245-267.297 144h107.296c17.673 0 32 14.327 32 32s-14.327 32-32 32h-176c-17.673 0-32-14.327-32-32v-192c0-17.673 14.327-32 32-32s32 14.327 32 32v101.364c70.228-90.856 180.282-149.364 304.002-149.364 212.075 0 384 171.923 384 384 0 212.079-171.925 384-384 384-212.079 0-384.002-171.921-384.002-384h64c0 176.73 143.269 320 320.002 320z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["undo"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":435,"id":10,"name":"undo","prevSize":32,"code":59782},"setIdx":0,"setId":0,"iconIdx":135},{"icon":{"paths":["M297.194 356.679c-6.619 27.765-2.384 63.755 25.498 105.58l33.166 49.749h-59.792c-44.011 0-70.483 14.874-86.279 33.621-16.496 19.575-24.573 47.262-23.733 77.491 0.841 30.259 10.601 59.968 25.818 81.31 15.127 21.218 33.403 31.578 52.195 31.578h144v64h-144.001c-45.209 0-80.932-25.638-104.305-58.423-23.283-32.657-36.523-74.948-37.682-116.689-1.161-41.771 9.763-86.084 38.766-120.508 20.726-24.597 49.155-42.317 84.825-50.782-16.1-39.010-19.008-77.050-10.731-111.77 11.253-47.2 42.304-84.492 80.791-107.342 38.399-22.798 85.676-32.138 131.301-21.965 35.584 7.935 68.911 27.48 95.253 59.554 53.751-35.147 127.582-30.892 182.485-2.495 34.436 17.812 64.789 46.382 81.434 85.009 12.297 28.531 16.439 61.011 10.607 96.206 46.114 6.682 81.51 25.156 105.617 53.453 30.349 35.627 38.101 81.353 33.442 123.285-4.655 41.92-21.943 83.486-46.545 115.115-24.060 30.933-59.354 57.353-101.257 57.353h-144v-64h144c14.093 0 32.798-9.579 50.739-32.644 17.399-22.374 30.114-52.804 33.455-82.889 3.341-30.067-2.906-56.341-18.556-74.718-15.219-17.869-44.036-33.749-97.638-33.749h-45.687l15.612-42.935c13.547-37.252 11.093-66.743 1.438-89.149-9.856-22.872-28.501-41.302-52.066-53.489-49.587-25.649-107.473-18.624-134.716 14.063l-30.131 36.162-22.545-41.324c-19.755-36.22-47.228-54.176-74.871-60.34-28.374-6.327-59.096-0.669-84.697 14.531-25.513 15.148-44.463 38.854-51.209 67.153zM655.044 588.779l-96-99.051c-6.029-6.217-14.319-9.728-22.976-9.728-8.661 0-16.951 3.511-22.98 9.728l-96 99.051c-12.3 12.689-11.983 32.947 0.707 45.248s32.948 11.985 45.249-0.708l41.024-42.321v273.003c0 17.673 14.323 32 32 32 17.673 0 32-14.327 32-32v-273.003l41.020 42.321c12.301 12.693 32.559 13.009 45.248 0.708 12.693-12.301 13.009-32.559 0.708-45.248z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["upload"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":436,"id":9,"name":"upload","prevSize":32,"code":59783},"setIdx":0,"setId":0,"iconIdx":136},{"icon":{"paths":["M618.539 336c0-53.019-42.978-96-96-96-53.018 0-96 42.981-96 96s42.982 96 96 96c53.022 0 96-42.981 96-96zM682.539 336c0 88.366-71.633 160-160 160s-160-71.634-160-160c0-88.366 71.633-160 160-160s160 71.634 160 160zM422.991 551.799c-24.621-5.769-50.286-5.363-74.713 1.178-67.087 17.971-113.738 78.763-113.738 148.215v66.807c0 53.018 42.981 96 96 96h384c53.022 0 96-42.982 96-96v-58.53c0-74.3-51.149-138.825-123.49-155.78l-6.455-1.51c-25.673-6.020-52.437-5.598-77.905 1.225l-49.63 13.295c-20.378 5.457-41.788 5.794-62.323 0.981l-67.744-15.881zM364.836 614.797c14.238-3.81 29.199-4.049 43.55-0.683l67.744 15.876c30.805 7.219 62.925 6.716 93.487-1.472l49.63-13.295c15.283-4.092 31.339-4.343 46.741-0.734l6.455 1.51c43.405 10.176 74.095 48.887 74.095 93.47v58.53c0 17.673-14.327 32-32 32h-384c-17.673 0-32-14.327-32-32v-66.807c0-40.486 27.193-75.921 66.297-86.396z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["user"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":437,"id":8,"name":"user","prevSize":32,"code":59784},"setIdx":0,"setId":0,"iconIdx":137},{"icon":{"paths":["M266.539 202.672c0-17.673 19.103-32 42.667-32h256c23.565 0 42.667 14.327 42.667 32s-19.102 32-42.667 32h-256c-23.564 0-42.667-14.327-42.667-32zM170.539 383.995c0-5.891 4.776-10.667 10.667-10.667h512c5.892 0 10.667 4.776 10.667 10.667v85.334c0 11.375 6.037 21.892 15.859 27.631 9.822 5.734 21.952 5.828 31.859 0.243l97.83-55.164c2.53-1.429 4.855-3.191 6.908-5.248 6.72-6.72 18.21-1.958 18.21 7.543v263.322c0 9.502-11.49 14.259-18.21 7.539-2.052-2.052-4.378-3.819-6.908-5.244l-97.83-55.164c-9.907-5.589-22.037-5.495-31.859 0.243-9.822 5.734-15.859 16.256-15.859 27.631v85.333c0 5.888-4.774 10.667-10.667 10.667h-512c-5.891 0-10.667-4.779-10.667-10.667v-384.001zM181.206 309.328c-41.237 0-74.667 33.429-74.667 74.667v384.001c0 41.237 33.429 74.667 74.667 74.667h512c41.237 0 74.667-33.429 74.667-74.667v-30.554l46.78 26.377c47.42 41.993 123.887 8.7 123.887-56.162v-263.322c0-64.864-76.467-98.155-123.887-56.164l-46.78 26.377v-30.553c0-41.237-33.429-74.667-74.667-74.667h-512z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["video-1"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":438,"id":7,"name":"video-1","prevSize":32,"code":59785},"setIdx":0,"setId":0,"iconIdx":138},{"icon":{"paths":["M313.716 170.672c-23.564 0-42.667 14.327-42.667 32s19.103 32 42.667 32h255.999c23.565 0 42.667-14.327 42.667-32s-19.102-32-42.667-32h-255.999z","M560.759 503.454c11.268-11.268 11.191-29.611-0.166-40.973-11.362-11.358-29.705-11.435-40.973-0.171l-71.403 71.403-71.995-71.996c-11.361-11.362-29.704-11.435-40.971-0.171-11.267 11.268-11.191 29.611 0.17 40.973l71.996 71.996-71.401 71.403c-11.267 11.264-11.191 29.606 0.17 40.969s29.704 11.439 40.971 0.171l71.401-71.403 71.996 71.996c11.362 11.362 29.705 11.439 40.973 0.171 11.264-11.264 11.187-29.611-0.171-40.969l-71.996-71.996 71.398-71.403z","M111.049 383.995c0-41.237 33.429-74.667 74.667-74.667h511.999c41.237 0 74.667 33.429 74.667 74.667v30.553l46.78-26.377c47.42-41.99 123.887-8.7 123.887 56.164v263.322c0 64.862-76.467 98.155-123.887 56.162l-46.78-26.377v30.554c0 41.237-33.429 74.667-74.667 74.667h-511.999c-41.237 0-74.667-33.429-74.667-74.667v-384.001zM185.716 373.328c-5.891 0-10.667 4.776-10.667 10.667v384.001c0 5.888 4.776 10.667 10.667 10.667h511.999c5.892 0 10.667-4.779 10.667-10.667v-85.333c0-11.375 6.037-21.897 15.859-27.631 9.822-5.739 21.952-5.833 31.859-0.243l97.83 55.164c2.53 1.425 4.855 3.191 6.908 5.244 6.72 6.72 18.21 1.963 18.21-7.539v-263.322c0-9.502-11.49-14.263-18.21-7.543-2.052 2.057-4.378 3.819-6.908 5.248l-97.83 55.164c-9.907 5.585-22.037 5.491-31.859-0.243-9.822-5.739-15.859-16.256-15.859-27.631v-85.334c0-5.891-4.774-10.667-10.667-10.667h-511.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["video-disabled"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":439,"id":6,"name":"video-disabled","prevSize":32,"code":59786},"setIdx":0,"setId":0,"iconIdx":139},{"icon":{"paths":["M878.921 153.128c-12.497-12.497-32.755-12.497-45.252 0l-668.247 668.244c-12.497 12.497-12.497 32.759 0 45.257s32.758 12.497 45.255 0l668.244-668.246c12.497-12.497 12.497-32.758 0-45.255zM311.461 170.672c-23.564 0-42.667 14.327-42.667 32s19.102 32 42.667 32h256.001c23.565 0 42.667-14.327 42.667-32s-19.102-32-42.667-32h-256.001zM586.965 309.329h-403.504c-41.237 0-74.667 33.429-74.667 74.667v384c0 6.012 0.71 11.853 2.051 17.455l61.949-61.952v-339.503c0-5.891 4.775-10.667 10.667-10.667h339.504l64-64zM389.133 778.662h306.33c5.888 0 10.667-4.774 10.667-10.667v-85.333c0-11.375 6.037-21.897 15.859-27.631 9.822-5.739 21.948-5.833 31.855-0.243l97.83 55.164c2.534 1.425 4.855 3.191 6.912 5.244 6.72 6.72 18.21 1.963 18.21-7.539v-263.322c0-9.502-11.49-14.263-18.21-7.543-2.057 2.057-4.378 3.819-6.912 5.248l-97.83 55.164c-9.907 5.585-22.033 5.495-31.855-0.243s-15.859-16.256-15.859-27.631v-7.663l110.775-73.495c47.42-41.99 123.891-8.7 123.891 56.164v263.322c0 64.862-76.471 98.155-123.891 56.162l-46.775-26.377v30.554c0 41.237-33.429 74.667-74.667 74.667h-370.33l64-64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["video-off"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":440,"id":5,"name":"video-off","prevSize":32,"code":59787},"setIdx":0,"setId":0,"iconIdx":140},{"icon":{"paths":["M307.615 224c-17.673 0-32 14.327-32 32s14.327 32 32 32h255.999c17.673 0 32-14.327 32-32s-14.327-32-32-32h-255.999z","M190.281 341.328c-23.564 0-42.667 19.102-42.667 42.667v384.001c0 23.565 19.102 42.667 42.667 42.667h511.999c23.565 0 42.667-19.102 42.667-42.667v-128l97.83 97.83c26.88 26.876 72.836 7.842 72.836-30.17v-263.322c0-38.012-45.956-57.049-72.836-30.17l-97.83 97.831v-128.001c0-23.564-19.102-42.667-42.667-42.667h-511.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["video"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":441,"id":4,"name":"video","prevSize":32,"code":59788},"setIdx":0,"setId":0,"iconIdx":141},{"icon":{"paths":["M319.276 661.342h-118.991v-298.665h118.991l12.367-48.047c11.845-46.020 53.695-79.953 103.311-79.953h64v554.665h-64c-49.615 0-91.466-33.933-103.311-79.949l-12.367-48.051zM178.952 725.342h90.71c18.946 73.613 85.766 128 165.291 128h85.333c23.565 0 42.667-19.102 42.667-42.667v-597.332c0-23.564-19.102-42.667-42.667-42.667h-85.333c-79.524 0-146.345 54.391-165.291 128h-90.71c-23.564 0-42.667 19.103-42.667 42.667v341.332c0 23.565 19.103 42.667 42.667 42.667zM894.912 393.373c12.497 12.497 12.497 32.758 0 45.254l-73.374 73.374 73.374 73.374c12.497 12.497 12.497 32.755 0 45.252s-32.759 12.497-45.252 0l-73.374-73.37-73.374 73.37c-12.497 12.497-32.759 12.497-45.252 0-12.497-12.497-12.497-32.755 0-45.252l73.37-73.374-73.37-73.374c-12.497-12.495-12.497-32.757 0-45.254 12.493-12.497 32.755-12.497 45.252 0l73.374 73.371 73.374-73.371c12.493-12.497 32.755-12.497 45.252 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["volume-disabled"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":442,"id":3,"name":"volume-disabled","prevSize":32,"code":59789},"setIdx":0,"setId":0,"iconIdx":142},{"icon":{"paths":["M872.158 153.127c-12.497-12.497-32.755-12.497-45.252 0l-668.247 668.244c-12.497 12.497-12.497 32.759 0 45.257s32.758 12.497 45.255 0l668.244-668.246c12.497-12.497 12.497-32.758 0-45.255zM680.674 480.358l55.923-55.923c16.256 79.564 14.511 161.864-5.231 240.844l-11.622 46.485c-4.288 17.148-21.662 27.571-38.805 23.283-17.148-4.284-27.571-21.658-23.283-38.805l11.622-46.485c13.875-55.509 17.673-112.875 11.396-169.399zM823.194 385.922l-11.315-36.77 51.209-51.206 21.278 69.154c33.344 108.369 31.991 224.448-3.861 332.010l-33.446 100.343c-5.589 16.764-23.71 25.826-40.478 20.237s-25.826-23.71-20.237-40.478l33.446-100.339c31.637-94.912 32.828-197.333 3.405-292.952zM496.7 664.333l64-64v210.342c0 23.565-19.106 42.667-42.667 42.667h-85.333c-35.462 0-68.396-10.812-95.687-29.325l46.612-46.609c14.701 7.629 31.395 11.934 49.075 11.934h64v-125.009zM134.031 682.675c0 19.742 13.403 36.348 31.604 41.22l62.552-62.554h-30.156v-298.665h118.99l12.367-48.047c11.845-46.020 53.696-79.953 103.312-79.953h64v158.156l64-64v-115.49c0-23.564-19.106-42.667-42.667-42.667h-85.333c-79.526 0-146.346 54.391-165.292 128h-90.71c-23.564 0-42.667 19.103-42.667 42.667v341.332z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["volume-off"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":443,"id":2,"name":"volume-off","prevSize":32,"code":59790},"setIdx":0,"setId":0,"iconIdx":143},{"icon":{"paths":["M303.875 631.121h-113.433v-280.89h113.433l12.367-48.048c11.055-42.953 50.122-74.619 96.423-74.619h58.665v526.223h-58.665c-46.301 0-85.368-31.667-96.423-74.62l-12.367-48.047zM167.331 695.121h86.931c18.156 70.541 82.193 122.667 158.403 122.667h81.777c22.583 0 40.887-18.308 40.887-40.892v-572.443c0-22.582-18.304-40.889-40.887-40.889h-81.778c-76.21 0-140.246 52.124-158.403 122.667h-86.931c-22.582 0-40.889 18.307-40.889 40.889v327.11c0 22.583 18.307 40.892 40.889 40.892zM650.236 316.516c17.148-4.286 34.522 6.138 38.805 23.284l11.14 44.551c20.804 83.229 20.804 170.303 0 253.529l-11.14 44.553c-4.284 17.148-21.658 27.571-38.805 23.283-17.143-4.284-27.567-21.658-23.283-38.805l11.14-44.553c18.257-73.037 18.257-149.444 0-222.484l-11.14-44.551c-4.284-17.146 6.14-34.519 23.283-38.806zM811.251 235.938c-5.201-16.892-23.108-26.372-39.996-21.175-16.892 5.198-26.372 23.104-21.175 39.996l35.533 115.49c28.117 91.37 26.978 189.239-3.251 279.931l-32.055 96.158c-5.589 16.768 3.473 34.889 20.237 40.478 16.768 5.589 34.889-3.473 40.478-20.237l32.055-96.162c34.449-103.343 35.746-214.869 3.708-318.99l-35.533-115.49z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["volume"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":444,"id":1,"name":"volume","prevSize":32,"code":59791},"setIdx":0,"setId":0,"iconIdx":144},{"icon":{"paths":["M540.578 351.999c17.673 0 32 14.327 32 32v224.001c0 17.673-14.327 32-32 32s-32-14.327-32-32v-224.001c0-17.673 14.327-32 32-32z","M540.578 672c17.673 0 32 14.327 32 32s-14.327 32-32 32c-17.673 0-32-14.327-32-32s14.327-32 32-32z","M595.678 158.342c-24.772-41.922-85.427-41.922-110.199 0l-359.923 609.099c-25.21 42.662 5.545 96.559 55.1 96.559h719.842c49.557 0 80.311-53.897 55.1-96.559l-359.919-609.099zM540.578 190.901l359.919 609.099h-719.842l359.923-609.099z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["warning"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":445,"id":0,"name":"warning","prevSize":32,"code":59792},"setIdx":0,"setId":0,"iconIdx":145}],"height":1024,"metadata":{"name":"custom"},"preferences":{"showGlyphs":true,"showCodes":true,"showQuickUse":true,"showQuickUse2":true,"showSVGs":true,"fontPref":{"prefix":"icon-","metadata":{"fontFamily":"custom","majorVersion":1,"minorVersion":0},"metrics":{"emSize":1024,"baseline":6.25,"whitespace":50},"embed":false,"showVersion":false,"showMetadata":false,"showMetrics":false,"showSelector":false},"imagePref":{"prefix":"icon-","png":true,"useClassSelector":true,"color":0,"bgColor":16777215,"name":"icomoon","classSelector":".icon"},"historySize":50,"gridSize":16}} \ No newline at end of file +{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M794.598 131.828c-24.994-24.994-65.515-24.994-90.509 0l-529.769 529.769c-9.564 9.562-15.852 21.909-17.962 35.273l-19.585 124.019c-1.384 8.764-0.941 17.28 1.005 25.229 7.587 30.997 38.032 53.367 72.195 47.974l124.022-19.584c13.36-2.112 25.708-8.401 35.272-17.963l529.771-529.769c12.497-12.497 18.743-28.877 18.743-45.257 0-10.365-2.505-20.73-7.509-30.111-2.901-5.443-6.647-10.556-11.238-15.144l-104.435-104.437zM629.845 296.585l119.497-119.5 104.439 104.436-119.501 119.5-104.435-104.436zM199.991 830.874l19.585-124.019 365.013-365.015 104.435 104.436-365.012 365.013-124.021 19.584z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["edit"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":544,"id":172,"name":"edit","prevSize":32,"code":59835},"setIdx":0,"setId":3,"iconIdx":0},{"icon":{"paths":["M410.708 527.33c26.575 0 48.121-21.585 48.121-48.213s-21.547-48.213-48.121-48.213c-26.576 0-48.12 21.585-48.12 48.213s21.544 48.213 48.12 48.213z","M603.187 479.117c0 26.628-21.542 48.213-48.119 48.213s-48.119-21.585-48.119-48.213c0-26.628 21.542-48.213 48.119-48.213s48.119 21.585 48.119 48.213z","M747.55 479.117c0 26.628-21.542 48.213-48.119 48.213s-48.119-21.585-48.119-48.213c0-26.628 21.542-48.213 48.119-48.213s48.119 21.585 48.119 48.213z","M101.734 813.683l119.625 31.279c85.312 22.31 173.449-16.252 238.694-79.71 29.5 4.796 59.874 7.245 90.675 7.245 218.295 0 404.339-122.863 404.339-294.519 0-171.663-186.039-294.519-404.339-294.519-218.313 0-404.35 122.852-404.339 294.524 0 65.071 27.642 125.013 75.655 173.585-2.847 24.836-14.596 44.732-36.049 68.553l-84.261 93.564zM550.729 258.994c183.13 0 331.601 98.043 331.601 218.984 0 120.93-148.471 218.982-331.601 218.982-40.781 0-79.834-4.877-115.913-13.76-36.667 45.598-117.332 109.005-195.694 88.516 25.489-28.305 63.251-76.13 55.168-154.91-46.968-37.781-75.162-86.135-75.162-138.829-0.008-120.949 148.46-218.984 331.599-218.984z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["baloon-ellipsis"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":372,"id":171,"name":"baloon-ellipsis","prevSize":32,"code":59648},"setIdx":0,"setId":3,"iconIdx":1},{"icon":{"paths":["M912.401 572.574h-269.013l-250.606-423.241h269.063l250.556 423.241zM375.23 190.906l134.483 238.078-230.78 408.354-134.532-237.922 230.829-408.51zM455.343 615.979h455.706l-134.532 258.688h-465.642l144.468-258.688z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["file-google-drive"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":373,"id":170,"name":"file-google-drive","prevSize":32,"code":59649},"setIdx":0,"setId":3,"iconIdx":2},{"icon":{"paths":["M892.437 567.625c-41.856-41.139-161.237-29.828-220.928-22.285-59.004-35.998-98.458-85.705-126.242-158.727 13.376-55.195 34.645-139.187 18.526-191.982-14.409-89.82-129.677-80.907-146.143-20.227-15.094 55.194-1.372 131.987 24.014 230.035-34.305 81.935-85.42 191.981-121.44 255.059-68.611 35.311-161.235 89.822-174.957 158.387-11.321 54.165 89.194 189.239 261.063-106.961 76.845-25.37 160.548-56.567 234.647-68.907 64.836 34.965 140.651 58.278 191.424 58.278 87.479 0 96.055-96.674 60.036-132.672zM212.848 834.342c17.496-46.967 84.048-101.133 104.288-119.991-65.18 103.876-104.288 122.389-104.288 119.991zM492.779 180.918c25.387 0 22.985 110.047 6.174 139.872-15.091-47.653-14.75-139.872-6.174-139.872zM409.074 649.216c33.277-57.937 61.748-126.844 84.733-187.524 28.476 51.767 64.836 93.248 103.262 121.702-71.356 14.741-133.449 44.911-187.995 65.822zM860.531 632.077c0 0-17.152 20.57-127.957-26.743 120.41-8.913 140.309 18.513 127.957 26.743z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["file-pdf"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":374,"id":169,"name":"file-pdf","prevSize":32,"code":59650},"setIdx":0,"setId":3,"iconIdx":3},{"icon":{"paths":["M862.455 324.045c-35.2-60.31-82.944-108.058-143.249-143.253-60.314-35.197-126.161-52.792-197.581-52.792-71.415 0-137.28 17.6-197.58 52.792-60.31 35.194-108.054 82.943-143.253 143.253-35.194 60.308-52.792 126.165-52.792 197.568 0 85.773 25.024 162.901 75.086 231.407 50.056 68.51 114.721 115.917 193.99 142.225 9.227 1.711 16.058 0.508 20.499-3.584 4.443-4.096 6.662-9.225 6.662-15.369 0-1.024-0.088-10.249-0.259-27.678-0.176-17.429-0.259-32.631-0.259-45.606l-11.789 2.039c-7.516 1.378-16.998 1.963-28.446 1.796-11.442-0.162-23.321-1.361-35.619-3.588-12.304-2.21-23.748-7.334-34.342-15.364-10.588-8.030-18.104-18.543-22.547-31.518l-5.125-11.793c-3.416-7.851-8.794-16.576-16.142-26.138-7.347-9.57-14.778-16.055-22.294-19.473l-3.589-2.569c-2.391-1.707-4.61-3.767-6.662-6.157-2.050-2.389-3.585-4.779-4.61-7.172-1.027-2.398-0.176-4.365 2.562-5.905 2.737-1.545 7.685-2.291 14.864-2.291l10.247 1.532c6.834 1.37 15.287 5.461 25.371 12.297 10.078 6.835 18.362 15.718 24.856 26.645 7.863 14.012 17.335 24.691 28.446 32.038 11.101 7.347 22.294 11.017 33.568 11.017s21.010-0.858 29.214-2.556c8.195-1.711 15.884-4.279 23.062-7.693 3.075-22.903 11.446-40.495 25.112-52.796-19.473-2.048-36.983-5.129-52.535-9.229-15.542-4.1-31.604-10.761-48.173-19.998-16.578-9.22-30.331-20.672-41.262-34.334-10.932-13.666-19.904-31.612-26.904-53.815-7.003-22.212-10.505-47.838-10.505-76.881 0-41.348 13.5-76.538 40.493-105.584-12.645-31.088-11.451-65.94 3.585-104.55 9.909-3.079 24.604-0.768 44.078 6.917 19.477 7.689 33.738 14.275 42.796 19.736 9.058 5.459 16.316 10.085 21.784 13.837 31.782-8.881 64.58-13.322 98.406-13.322s66.633 4.441 98.415 13.322l19.477-12.295c13.316-8.204 29.043-15.722 47.142-22.556 18.112-6.831 31.957-8.712 41.532-5.633 15.369 38.612 16.738 73.461 4.092 104.55 26.991 29.045 40.495 64.243 40.495 105.587 0 29.039-3.516 54.746-10.509 77.129-6.997 22.387-16.047 40.316-27.149 53.82-11.115 13.5-24.956 24.862-41.523 34.082-16.576 9.225-32.64 15.885-48.183 19.989-15.548 4.105-33.058 7.189-52.531 9.237 17.762 15.373 26.641 39.633 26.641 72.772v108.139c0 6.14 2.138 11.268 6.413 15.369 4.271 4.092 11.017 5.295 20.245 3.58 79.279-26.304 143.945-73.711 193.997-142.221 50.048-68.506 75.081-145.634 75.081-231.407-0.017-71.394-17.621-137.247-52.8-197.555z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Github"]},"attrs":[{}],"properties":{"order":375,"id":168,"name":"Github","prevSize":32,"code":59651},"setIdx":0,"setId":3,"iconIdx":4},{"icon":{"paths":["M510.144 910.66l156.407-481.412h-312.813l156.406 481.412z","M510.144 910.66l-156.405-481.412h-219.199l375.604 481.412z","M134.541 429.248l-47.612 146.287c-4.37 13.342 0.46 28.062 11.73 36.113l411.484 299.012-375.603-481.412z","M134.54 429.252h219.199l-94.304-290.039c-4.83-14.95-25.991-14.95-30.821 0l-94.074 290.039z","M510.144 910.66l156.407-481.412h219.196l-375.603 481.412z","M885.747 429.248l47.612 146.287c4.373 13.342-0.457 28.062-11.729 36.113l-411.486 299.012 375.603-481.412z","M885.747 429.252h-219.196l94.302-290.039c4.83-14.95 25.993-14.95 30.822 0l94.071 290.039z"],"attrs":[{"fill":"rgb(226, 67, 41)"},{"fill":"rgb(252, 109, 38)"},{"fill":"rgb(252, 163, 38)"},{"fill":"rgb(226, 67, 41)"},{"fill":"rgb(252, 109, 38)"},{"fill":"rgb(252, 163, 38)"},{"fill":"rgb(226, 67, 41)"}],"isMulticolor":true,"isMulticolor2":false,"grid":0,"tags":["Gitlab"]},"attrs":[{"fill":"rgb(226, 67, 41)"},{"fill":"rgb(252, 109, 38)"},{"fill":"rgb(252, 163, 38)"},{"fill":"rgb(226, 67, 41)"},{"fill":"rgb(252, 109, 38)"},{"fill":"rgb(252, 163, 38)"},{"fill":"rgb(226, 67, 41)"}],"properties":{"order":376,"id":167,"name":"Gitlab","prevSize":32,"code":59652,"codes":[59652,59653,59654,59655,59656,59657,59658]},"setIdx":0,"setId":3,"iconIdx":5},{"icon":{"paths":["M881.941 442.176h-361.655v148.54h206.66c-8.9 48-35.955 88.67-76.625 115.9v96.346h124.1c72.614-66.85 114.505-165.295 114.505-282.24 0-27.226-2.445-53.41-6.985-78.545z","M520.286 896c103.68 0 190.605-34.385 254.135-93.035l-124.1-96.35c-34.385 23.040-78.37 36.655-130.035 36.655-100.015 0-184.67-67.55-214.866-158.31h-128.291v99.49c63.185 125.495 193.047 211.55 343.157 211.55z","M305.42 584.964c-7.68-23.040-12.044-47.65-12.044-72.96s4.364-49.92 12.044-72.96v-99.492h-128.291c-26.007 51.84-40.844 110.487-40.844 172.452 0 61.961 14.836 120.61 40.844 172.45l128.291-99.49z","M520.286 280.727c56.375 0 106.995 19.375 146.79 57.425l110.14-110.138c-66.5-61.964-153.425-100.015-256.93-100.015-150.11 0-279.971 86.051-343.157 211.549l128.291 99.491c30.196-90.764 114.851-158.313 214.866-158.313z"],"attrs":[{"fill":"rgb(66, 133, 244)"},{"fill":"rgb(52, 168, 83)"},{"fill":"rgb(251, 188, 5)"},{"fill":"rgb(234, 67, 53)"}],"width":1067,"isMulticolor":true,"isMulticolor2":false,"grid":0,"tags":["Google"]},"attrs":[{"fill":"rgb(66, 133, 244)"},{"fill":"rgb(52, 168, 83)"},{"fill":"rgb(251, 188, 5)"},{"fill":"rgb(234, 67, 53)"}],"properties":{"order":377,"id":166,"name":"Google","prevSize":32,"code":59659,"codes":[59659,59660,59661,59662]},"setIdx":0,"setId":3,"iconIdx":6},{"icon":{"paths":["M839.189 128h-654.548c-31.254 0-56.642 24.79-56.642 55.383v657.214c0 30.592 25.388 55.424 56.642 55.424h654.548c31.317 0 56.811-24.832 56.811-55.424v-657.214c0-30.593-25.493-55.383-56.811-55.383z","M298.842 233.729c36.438 0 66.007 29.59 66.007 66.050 0 36.481-29.569 66.071-66.007 66.071-36.588 0-66.092-29.59-66.092-66.071 0-36.46 29.505-66.050 66.092-66.050zM241.795 782.438h114.030v-366.515h-114.030v366.515z","M427.273 415.921h109.188v50.114h1.579c15.189-28.821 52.352-59.202 107.755-59.202 115.354 0 136.666 75.884 136.666 174.598v201.007h-113.903v-178.244c0-42.496-0.725-97.178-59.179-97.178-59.285 0-68.331 46.319-68.331 94.148v181.274h-113.775v-366.517z"],"attrs":[{"fill":"rgb(0, 113, 161)"},{"fill":"rgb(255, 255, 254)"},{"fill":"rgb(255, 255, 254)"}],"isMulticolor":true,"isMulticolor2":false,"grid":0,"tags":["Linkedin"]},"attrs":[{"fill":"rgb(0, 113, 161)"},{"fill":"rgb(255, 255, 254)"},{"fill":"rgb(255, 255, 254)"}],"properties":{"order":378,"id":165,"name":"Linkedin","prevSize":32,"code":59663,"codes":[59663,59664,59665]},"setIdx":0,"setId":3,"iconIdx":7},{"icon":{"paths":["M85.333 85.333l730.795 774.089c0 0 24.896 17.557 43.934-2.927 19.038-20.489 4.395-40.973 4.395-40.973l-779.123-730.189zM316.727 158.5l556.515 599.956c0 0 24.896 17.557 43.938-2.927 19.038-20.489 4.39-40.973 4.39-40.973l-604.844-556.056zM710.682 915.025l-556.516-599.952 604.845 556.057c0 0 14.643 20.484-4.395 40.969-19.038 20.489-43.934 2.927-43.934 2.927zM512.337 221.417l388.804 419.151c0 0 17.395 12.271 30.694-2.044 13.303-14.31 3.072-28.625 3.072-28.625l-422.571-388.482zM596.523 915.674l-388.803-419.153 422.569 388.484c0 0 10.231 14.31-3.068 28.625-13.303 14.31-30.699 2.044-30.699 2.044zM712.145 312.141l176.222 190.549c0 0 8.602 5.751 15.181-0.956s1.519-13.414 1.519-13.414l-192.922-176.179zM481.229 880.226l-176.218-190.549 192.922 176.179c0 0 5.060 6.707-1.519 13.414s-15.185 0.956-15.185 0.956z"],"attrs":[{"fill":"rgb(222, 79, 79)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Meteor"]},"attrs":[{"fill":"rgb(222, 79, 79)"}],"properties":{"order":379,"id":164,"name":"Meteor","prevSize":32,"code":59666},"setIdx":0,"setId":3,"iconIdx":8},{"icon":{"paths":["M385.058 837.38c290.193 0 448.922-240.111 448.922-448.329 0-6.82 0-13.609-0.465-20.367 30.878-22.306 57.536-49.924 78.716-81.562-28.791 12.742-59.341 21.099-90.62 24.791 32.939-19.692 57.587-50.665 69.367-87.153-30.972 18.354-64.853 31.289-100.19 38.246-48.905-51.936-126.618-64.647-189.559-31.006s-95.458 105.266-79.317 174.714c-126.86-6.351-245.054-66.192-325.169-164.628-41.876 71.997-20.487 164.102 48.848 210.338-25.108-0.742-49.67-7.505-71.61-19.721 0 0.644 0 1.323 0 1.997 0.020 75.004 52.962 139.61 126.58 154.462-23.228 6.323-47.599 7.249-71.241 2.701 20.669 64.188 79.903 108.16 147.404 109.427-55.869 43.849-124.886 67.652-195.945 67.584-12.553-0.026-25.094-0.785-37.559-2.274 72.153 46.242 156.107 70.771 241.839 70.656z"],"attrs":[{"fill":"rgb(29, 161, 242)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Twitter"]},"attrs":[{"fill":"rgb(29, 161, 242)"}],"properties":{"order":380,"id":163,"name":"Twitter","prevSize":32,"code":59667},"setIdx":0,"setId":3,"iconIdx":9},{"icon":{"paths":["M317.896 231.569c-62.882 49.504-135.086 136.548-141.94 266.125-5.762 108.924 37.404 187.187 89.916 241.51 53.259 55.1 115.701 84.924 144.248 94.443 41.861 13.952 114.271 29.534 234.646-15.607 34.859-13.069 73.161-42.095 108.301-78.426 14.272-14.754 27.614-30.293 39.599-45.773-28.774 9.293-61.696 17.758-96.589 23.595-56.188 9.404-119.287 12.322-179.409-0.235-2.492-0.521-4.958-1.033-7.411-1.536-22.191-4.578-42.731-8.815-62.583-17.651-23.095-10.274-43.808-25.89-69.3-51.383-42.097-42.095-89.143-107.221-89.372-213.841-1.569-34.084 4.621-81.88 13.763-129.219 4.624-23.946 10.142-48.465 16.132-72.002zM344.209 138.22c32.8-17.15 63.709 15.843 53.877 45.907-12.235 37.414-24.586 85.511-33.483 131.58-9.024 46.731-13.946 88.633-12.643 114.698l0.040 0.798v0.802c0 84.915 36.172 134.916 70.627 169.374 22.505 22.507 36.833 32.277 50.064 38.165 13.227 5.884 26.829 8.717 51.085 13.764 1.924 0.397 3.913 0.815 5.978 1.246 49.911 10.423 104.533 8.337 155.759-0.239 65.434-10.953 122.385-31.979 152.375-47.386 17.562-9.020 34.991-2.466 44.476 5.965 9.664 8.589 19.375 27.153 8.887 46.955-20.638 38.95-53.645 84.42-92.181 124.262-38.217 39.509-84.318 76.036-131.836 93.854-135.625 50.863-223.215 34.441-277.353 16.397-36.516-12.173-108.392-46.912-170.026-110.677-62.381-64.533-114.683-159.428-107.809-289.37 10.79-203.98 157.583-317.1 232.164-356.095z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["moon"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":381,"id":162,"name":"moon","prevSize":32,"code":59668},"setIdx":0,"setId":3,"iconIdx":10},{"icon":{"paths":["M480 117.333c0-17.673 14.327-32 32-32s32 14.327 32 32v106.667c0 17.673-14.327 32-32 32s-32-14.327-32-32v-106.667zM770.039 214.629c12.497-12.497 32.759-12.497 45.257 0s12.497 32.758 0 45.255l-75.413 75.412c-12.497 12.497-32.759 12.497-45.257 0s-12.497-32.758 0-45.255l75.413-75.412zM335.377 694.63c-12.497-12.497-32.758-12.497-45.255 0l-75.495 75.494c-12.497 12.497-12.497 32.755 0 45.252s32.758 12.497 45.255 0l75.495-75.494c12.497-12.497 12.497-32.755 0-45.252zM480 800c0-17.673 14.327-32 32-32s32 14.327 32 32v106.667c0 17.673-14.327 32-32 32s-32-14.327-32-32v-106.667zM212 211.999c-12.497 12.497-12.497 32.758 0 45.255l75.349 75.349c12.497 12.497 32.758 12.497 45.255 0s12.497-32.758 0-45.255l-75.349-75.349c-12.497-12.497-32.758-12.497-45.255 0zM694.626 739.883c-12.497-12.497-12.497-32.759 0-45.257s32.759-12.497 45.257 0l75.328 75.328c12.497 12.497 12.497 32.759 0 45.257s-32.759 12.497-45.257 0l-75.328-75.328zM86.4 512c0 17.673 14.327 32 32 32h106.667c17.673 0 32-14.327 32-32s-14.327-32-32-32h-106.667c-17.673 0-32 14.327-32 32zM800 544c-17.673 0-32-14.327-32-32s14.327-32 32-32h106.667c17.673 0 32 14.327 32 32s-14.327 32-32 32h-106.667zM666.816 512c0-85.505-69.316-154.82-154.82-154.82-85.503 0-154.817 69.315-154.817 154.82 0 85.504 69.315 154.816 154.817 154.816 85.504 0 154.82-69.312 154.82-154.816zM725.329 512c0 117.82-95.509 213.333-213.333 213.333-117.819 0-213.332-95.514-213.332-213.333 0-117.822 95.512-213.335 213.332-213.335 117.824 0 213.333 95.513 213.333 213.335z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["sun"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":382,"id":161,"name":"sun","prevSize":32,"code":59669},"setIdx":0,"setId":3,"iconIdx":11},{"icon":{"paths":["M195.378 191.997c0-15.807 12.815-28.622 28.622-28.622h128c15.807 0 28.622 12.815 28.622 28.622s-12.815 28.622-28.622 28.622h-128c-15.807 0-28.622-12.814-28.622-28.622z","M736 559.996c0 97.203-78.797 176-176 176s-176-78.797-176-176c0-97.203 78.797-175.999 176-175.999s176 78.796 176 175.999zM672 559.996c0-61.854-50.146-112-112-112s-112 50.146-112 112c0 61.858 50.146 112 112 112s112-50.142 112-112z","M192 255.997c-35.346 0-64 28.654-64 64v447.999c0 35.345 28.654 64 64 64h640c35.345 0 64-28.655 64-64v-447.999c0-35.346-28.655-64-64-64h-640zM832 319.997v447.999h-640v-447.999h640z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["camera-photo"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":383,"id":160,"name":"camera-photo","prevSize":32,"code":59670},"setIdx":0,"setId":3,"iconIdx":12},{"icon":{"paths":["M700.147 361.892c4.681-24.975 34.701-34.093 49.126-13.174 31.991 46.404 50.726 102.656 50.726 163.281 0 60.629-18.735 116.881-50.726 163.285-14.426 20.919-44.446 11.802-49.126-13.175l-1.707-9.101c-1.583-8.431 0.384-17.084 4.855-24.401 20.749-33.967 32.704-73.89 32.704-116.608 0-42.714-11.955-82.637-32.704-116.604-4.471-7.319-6.438-15.972-4.855-24.402l1.707-9.102z","M320.705 395.396c-20.749 33.967-32.705 73.891-32.705 116.604 0 42.718 11.956 82.641 32.705 116.608 4.471 7.317 6.436 15.97 4.856 24.401l-1.707 9.101c-4.683 24.977-34.703 34.095-49.127 13.175-31.994-46.404-50.728-102.656-50.728-163.285 0-60.625 18.734-116.878 50.728-163.281 14.423-20.919 44.444-11.801 49.127 13.174l1.707 9.102c1.58 8.43-0.385 17.083-4.856 24.402z","M728.764 209.256l-0.512 2.747c-2.236 11.911 2.534 23.968 11.763 31.822 75.861 64.565 123.985 160.751 123.985 268.175 0 107.426-48.124 203.614-123.985 268.177-9.229 7.855-13.999 19.913-11.763 31.821l0.512 2.748c4.194 22.362 29.692 33.195 47.262 18.743 92.796-76.292 151.974-191.979 151.974-321.489 0-129.507-59.179-245.193-151.974-321.489-17.57-14.448-43.068-3.615-47.262 18.745z","M283.986 243.825c9.229-7.854 13.998-19.911 11.764-31.822l-0.515-2.747c-4.192-22.359-29.69-33.193-47.262-18.745-92.793 76.296-151.973 191.982-151.973 321.489 0 129.51 59.18 245.197 151.973 321.489 17.572 14.451 43.070 3.618 47.262-18.743l0.515-2.748c2.233-11.908-2.536-23.966-11.764-31.821-75.863-64.563-123.986-160.751-123.986-268.177 0-107.424 48.122-203.61 123.986-268.175z","M608 512c0 53.022-42.982 96-96 96s-96-42.978-96-96c0-53.018 42.982-95.999 96-95.999s96 42.981 96 95.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["live"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":384,"id":159,"name":"live","prevSize":32,"code":59671},"setIdx":0,"setId":3,"iconIdx":13},{"icon":{"paths":["M527.782 128c75.546 0 138.859 52.355 155.644 122.761l-59.644 59.644v-22.406c0-53.019-42.982-96-96-96-53.022 0-96 42.981-96 96v128c0 24.068 8.858 46.067 23.488 62.916l-45.322 45.321c-26.182-28.484-42.167-66.496-42.167-108.237v-128c0-88.366 71.634-160 160.001-160zM577.131 568.243l102.895-102.895c-15.765 48.674-54.221 87.13-102.895 102.895zM303.781 416c0 72.154 23.182 123.102 55.327 159.078l-45.303 45.303c-43.427-47.351-74.024-113.993-74.024-204.382 0-17.673 14.327-32 32-32s32 14.327 32 32zM494.438 650.935l-51.806 51.81c18.56 6.374 36.578 10.807 53.15 13.636v115.618h-160.001c-17.673 0-32 14.327-32 32s14.327 32 32 32h384.001c17.673 0 32-14.327 32-32s-14.327-32-32-32h-160v-115.618c44.638-7.62 99.819-26.897 147.721-64.38 60.702-47.501 108.279-123.29 108.279-236.002 0-17.673-14.327-32-32-32s-32 14.327-32 32c0 92.087-37.76 149.632-83.721 185.6-46.468 36.361-102.737 51.58-140.279 54.327-9.971-0.73-21.265-2.338-33.344-4.992zM841.152 153.373c12.497-12.497 32.759-12.497 45.257 0s12.497 32.758 0 45.255l-672 671.999c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l671.998-672.001z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["microphone-disabled"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":385,"id":158,"name":"microphone-disabled","prevSize":32,"code":59672},"setIdx":0,"setId":3,"iconIdx":14},{"icon":{"paths":["M621.53 288c0-53.019-42.982-96-96-96-53.022 0-96 42.981-96 96v128c0 53.018 42.978 96 96 96 53.018 0 96-42.982 96-96v-128zM365.529 288c0-88.366 71.634-160 160.001-160 88.363 0 160 71.634 160 160v128c0 88.367-71.637 160-160 160-88.367 0-160.001-71.633-160.001-160v-128zM269.529 384c17.673 0 32 14.327 32 32 0 92.087 37.758 149.632 83.72 185.6 46.465 36.361 102.734 51.58 140.281 54.327 37.542-2.748 93.811-17.967 140.279-54.327 45.961-35.968 83.721-93.513 83.721-185.6 0-17.673 14.327-32 32-32s32 14.327 32 32c0 112.713-47.578 188.501-108.279 236.002-47.902 37.483-103.083 56.759-147.721 64.38v115.618h160c17.673 0 32 14.327 32 32s-14.327 32-32 32h-384.001c-17.673 0-32-14.327-32-32s14.327-32 32-32h160.001v-115.618c-44.642-7.62-99.819-26.897-147.721-64.38-60.705-47.501-108.28-123.29-108.28-236.002 0-17.673 14.327-32 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["microphone"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":386,"id":157,"name":"microphone","prevSize":32,"code":59673},"setIdx":0,"setId":3,"iconIdx":15},{"icon":{"paths":["M384 149.138c0-11.766 9.551-21.305 21.333-21.305h85.333c11.78 0 21.333 9.539 21.333 21.305v106.526h-106.667c-11.782 0-21.333-9.539-21.333-21.305v-85.221z","M512 255.665h106.667c11.78 0 21.333 9.539 21.333 21.305v85.221c0 11.767-9.553 21.305-21.333 21.305h-106.667v-127.831z","M384 404.801c0-11.767 9.551-21.305 21.333-21.305h106.667v127.83h-106.667c-11.782 0-21.333-9.536-21.333-21.303v-85.222z","M512 511.326h106.667c11.78 0 21.333 9.54 21.333 21.308v106.526h-128v-127.834z","M426.667 639.159c-23.564 0-42.667 19.076-42.667 42.607v170.445c0 23.531 19.103 42.611 42.667 42.611h170.667c23.565 0 42.667-19.081 42.667-42.611v-213.052h-213.333zM490.667 724.378c-11.78 0-21.333 9.54-21.333 21.308v42.607c0 11.767 9.553 21.308 21.333 21.308h42.667c11.78 0 21.333-9.54 21.333-21.308v-42.607c0-11.767-9.553-21.308-21.333-21.308h-42.667z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["zip"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":387,"id":156,"name":"zip","prevSize":32,"code":59674},"setIdx":0,"setId":3,"iconIdx":16},{"icon":{"paths":["M288 224c-17.673 0-32 14.327-32 32s14.327 32 32 32h256c17.673 0 32-14.327 32-32s-14.327-32-32-32h-256z","M170.667 341.328c-23.564 0-42.667 19.102-42.667 42.667v384.001c0 23.565 19.103 42.667 42.667 42.667h512c23.565 0 42.667-19.102 42.667-42.667v-128l97.83 97.83c26.88 26.876 72.836 7.842 72.836-30.17v-263.322c0-38.012-45.956-57.049-72.836-30.17l-97.83 97.831v-128.001c0-23.564-19.102-42.667-42.667-42.667h-512z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["camera-filled"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":388,"id":155,"name":"camera-filled","prevSize":32,"code":59675},"setIdx":0,"setId":3,"iconIdx":17},{"icon":{"paths":["M809.003 166.758c7.782 6.063 12.331 15.377 12.331 25.242v448h-0.111c0.073 1.732 0.111 3.477 0.111 5.231 0 69.052-57.306 125.026-128 125.026s-128-55.974-128-125.026c0-69.052 57.306-125.030 128-125.030 23.313 0 45.171 6.089 64 16.725v-303.858l-384 96.797v409.139c0 69.052-57.308 125.035-128 125.035s-128-55.979-128-125.030c0-69.052 57.308-125.026 128-125.026 23.314 0 45.173 6.089 64 16.725v-325.777c0-14.66 9.963-27.446 24.178-31.029l448.001-112.929c9.566-2.412 19.708-0.276 27.49 5.787z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["musical-note"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":389,"id":154,"name":"musical-note","prevSize":32,"code":59676},"setIdx":0,"setId":3,"iconIdx":18},{"icon":{"paths":["M533.333 128c200.294 0 362.667 162.371 362.667 362.667h-362.667v-362.667z","M128 533.333c0-200.295 162.371-362.667 362.667-362.667v362.667h362.667c0 200.294-162.372 362.667-362.667 362.667s-362.667-162.372-362.667-362.667z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["pizza-graph"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":390,"id":153,"name":"pizza-graph","prevSize":32,"code":59677},"setIdx":0,"setId":3,"iconIdx":19},{"icon":{"paths":["M405.333 405.333c0 47.13-38.205 85.333-85.333 85.333s-85.333-38.204-85.333-85.333c0-47.128 38.205-85.333 85.333-85.333s85.333 38.205 85.333 85.333z","M96 192c0-17.673 14.327-32 32-32h768c17.673 0 32 14.327 32 32v640c0 17.673-14.327 32-32 32h-768c-17.673 0-32-14.327-32-32v-640zM160 764.164l151.704-176.99c9.269-10.816 24.571-14.199 37.538-8.307l153.124 69.602 160.474-204.241c6.007-7.646 15.172-12.147 24.9-12.228 9.728-0.077 18.961 4.271 25.097 11.823l151.164 186.048v-405.871h-704v540.164zM213.575 800h650.425v-68.638l-175.582-216.102-166.78 212.271-176.99-80.448-131.073 152.917z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["image"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":391,"id":152,"name":"image","prevSize":32,"code":59678},"setIdx":0,"setId":3,"iconIdx":20},{"icon":{"paths":["M671.057 183.163c16.683 16.663 16.683 43.677 0 60.34l-268.852 268.497 268.852 268.497c16.683 16.661 16.683 43.678 0 60.339-16.687 16.661-43.738 16.661-60.42 0l-299.061-298.667c-8.012-8-12.513-18.854-12.513-30.17s4.501-22.17 12.513-30.17l299.061-298.667c16.683-16.662 43.733-16.662 60.42 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["chevron-left-big"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":392,"id":151,"name":"chevron-left-big","prevSize":32,"code":59679},"setIdx":0,"setId":3,"iconIdx":21},{"icon":{"paths":["M160.253 256c0-17.673 14.327-32 32-32h640.844c17.677 0 32 14.327 32 32s-14.323 32-32 32h-640.844c-17.673 0-32-14.327-32-32zM160.253 512c0-17.673 14.327-32 32-32h640.844c17.677 0 32 14.327 32 32s-14.323 32-32 32h-640.844c-17.673 0-32-14.327-32-32zM160.253 768c0-17.673 14.327-32 32-32h640.844c17.677 0 32 14.327 32 32s-14.323 32-32 32h-640.844c-17.673 0-32-14.327-32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["hamburguer"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":393,"id":150,"name":"hamburguer","prevSize":32,"code":59680},"setIdx":0,"setId":3,"iconIdx":22},{"icon":{"paths":["M512 96c80.094 0 154.901 22.636 218.377 61.859l-46.746 46.746c-24.738-13.843-51.324-24.785-79.287-32.368 12.169 22.394 23.078 49.096 32.405 79.249l-51.998 51.999c-5.658-22.993-12.169-44.004-19.349-62.666-12.821-33.338-26.522-55.927-38.473-69.070-8.397-9.235-13.431-11.29-14.929-11.698-1.498 0.407-6.532 2.463-14.929 11.698-11.951 13.143-25.651 35.731-38.473 69.070-16.299 42.377-29.175 96.867-36.34 159.182h65.976l-64 63.999h-7.114c-0.116 2.47-0.224 4.949-0.322 7.437l-64.536 64.538c-0.174-7.936-0.262-15.927-0.262-23.974 0-16.23 0.358-32.247 1.054-48h-189.809c-2.14 15.697-3.245 31.718-3.245 48 0 33.28 4.619 65.485 13.251 96h106.984l-64 64h-17.852c2.004 3.921 4.079 7.799 6.223 11.631l-46.746 46.746c-39.223-63.475-61.859-138.283-61.859-218.377 0-229.751 186.249-416 416-416zM866.142 293.623l-46.746 46.746c10.56 18.873 19.43 38.819 26.411 59.632h-86.046l-64 63.999h164.992c2.142 15.697 3.247 31.718 3.247 48 0 33.28-4.617 65.485-13.252 96h-183.027c2.799-30.814 4.279-62.959 4.279-96 0-8.047-0.085-16.038-0.26-23.974l-64.538 64.538c-0.751 19.008-2.022 37.517-3.763 55.437h-51.678l-64 64h107.093c-7.369 42.458-17.489 80.081-29.453 111.185-12.821 33.335-26.522 55.923-38.473 69.069-8.397 9.233-13.431 11.29-14.929 11.695-1.498-0.405-6.532-2.462-14.929-11.695-11.951-13.146-25.651-35.733-38.473-69.069-7.177-18.662-13.692-39.676-19.349-62.673l-51.998 52.002c9.327 30.153 20.238 56.853 32.404 79.249-27.964-7.582-54.546-18.526-79.285-32.367l-46.746 46.746c63.347 39.142 137.984 61.769 217.899 61.858h0.956c229.53-0.26 415.522-186.411 415.522-416 0-80.094-22.635-154.903-61.858-218.377zM419.657 172.237c-113.551 30.788-204.311 116.98-241.465 227.764h179.674c10-93.227 32.176-173.254 61.791-227.764zM604.348 851.763c24.393-44.902 43.738-107.119 55.39-179.763h165.879c-44.651 87.347-124.723 153.583-221.269 179.763zM825.374 153.373c12.497-12.497 32.755-12.497 45.252 0s12.497 32.758 0 45.255l-671.999 671.999c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l672.001-672.001z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["directory-disabled"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":394,"id":149,"name":"directory-disabled","prevSize":32,"code":59681},"setIdx":0,"setId":3,"iconIdx":23},{"icon":{"paths":["M864 511.326c0 33.237-4.621 65.399-13.252 95.876h-183.027c2.799-30.78 4.279-62.878 4.279-95.876 0-16.209-0.358-32.205-1.054-47.936h189.807c2.142 15.676 3.247 31.676 3.247 47.936zM606.882 463.39c0.734 15.65 1.118 31.646 1.118 47.936 0 33.353-1.604 65.468-4.561 95.876h-182.876c-2.958-30.409-4.562-62.524-4.562-95.876 0-16.29 0.383-32.286 1.12-47.936h189.762zM666.133 399.476c-9.997-93.104-32.175-173.025-61.79-227.464 113.553 30.747 204.309 116.826 241.463 227.464h-179.674zM419.657 172.012c-29.615 54.438-51.791 134.359-61.791 227.464h-179.674c37.155-110.638 127.914-196.717 241.465-227.464zM422.259 399.476c7.164-62.232 20.041-116.651 36.34-158.972 12.821-33.295 26.522-55.853 38.473-68.979 8.397-9.223 13.431-11.276 14.929-11.683 1.498 0.407 6.532 2.46 14.929 11.683 11.951 13.126 25.651 35.684 38.473 68.979 16.299 42.321 29.175 96.739 36.339 158.972h-179.482zM353.054 463.39c-0.696 15.731-1.054 31.727-1.054 47.936 0 32.998 1.482 65.097 4.282 95.876h-183.031c-8.632-30.477-13.251-62.639-13.251-95.876 0-16.26 1.105-32.26 3.245-47.936h189.809zM364.263 671.117c11.652 72.55 30.999 134.682 55.392 179.524-96.549-26.146-176.621-92.292-221.273-179.524h165.881zM512.478 926.775c229.53-0.256 415.522-186.163 415.522-415.45 0-229.447-186.249-415.451-416-415.451s-416 186.004-416 415.451c0 229.291 185.992 415.194 415.522 415.45 0.158 0.004 0.32 0.004 0.478 0.004s0.32 0 0.478-0.004zM604.348 850.641c24.393-44.843 43.738-106.978 55.39-179.524h165.879c-44.651 87.232-124.723 153.378-221.269 179.524zM594.854 671.117c-7.369 42.398-17.489 79.974-29.453 111.036-12.821 33.293-26.522 55.851-38.473 68.979-8.397 9.22-13.431 11.273-14.929 11.682-1.498-0.41-6.532-2.462-14.929-11.682-11.951-13.129-25.651-35.686-38.473-68.979-11.964-31.061-22.080-68.638-29.453-111.036h165.709z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["directory"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":395,"id":148,"name":"directory","prevSize":32,"code":59682},"setIdx":0,"setId":3,"iconIdx":24},{"icon":{"paths":["M864 512c0 194.402-157.598 352-352 352-194.404 0-352-157.598-352-352 0-194.404 157.596-352 352-352 194.402 0 352 157.596 352 352zM928 512c0-229.751-186.249-416-416-416s-416 186.249-416 416c0 229.751 186.249 416 416 416s416-186.249 416-416zM544 288c0-17.673-14.327-32-32-32s-32 14.327-32 32v224c0 8.486 3.371 16.627 9.374 22.626l96 96c12.497 12.497 32.755 12.497 45.252 0s12.497-32.755 0-45.252l-86.626-86.63v-210.743z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["clock"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":396,"id":147,"name":"clock","prevSize":32,"code":59683},"setIdx":0,"setId":3,"iconIdx":25},{"icon":{"paths":["M577.353 256c0 35.346-28.655 64-64 64s-64-28.654-64-64c0-35.346 28.655-64 64-64s64 28.654 64 64z","M577.353 512c0 35.345-28.655 64-64 64s-64-28.655-64-64c0-35.345 28.655-64 64-64s64 28.655 64 64z","M577.353 768c0 35.345-28.655 64-64 64s-64-28.655-64-64c0-35.345 28.655-64 64-64s64 28.655 64 64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["kebab"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":397,"id":146,"name":"kebab","prevSize":32,"code":59684},"setIdx":0,"setId":3,"iconIdx":26},{"icon":{"paths":["M512 873.024c-199.389 0-361.026-161.634-361.026-361.024s161.637-361.026 361.026-361.026c199.39 0 361.024 161.637 361.024 361.026s-161.634 361.024-361.024 361.024zM512 938.667c235.639 0 426.667-191.027 426.667-426.667 0-235.642-191.027-426.667-426.667-426.667-235.642 0-426.667 191.025-426.667 426.667 0 235.639 191.025 426.667 426.667 426.667zM544.819 347.898c0 18.126-14.694 32.82-32.819 32.82s-32.819-14.694-32.819-32.82c0-18.127 14.694-32.82 32.819-32.82s32.819 14.694 32.819 32.82zM512 413.539c-18.125 0-32.819 14.694-32.819 32.819v229.747c0 18.125 14.694 32.819 32.819 32.819s32.819-14.694 32.819-32.819v-229.747c0-18.125-14.694-32.819-32.819-32.819z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["info"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":398,"id":145,"name":"info","prevSize":32,"code":59685},"setIdx":0,"setId":3,"iconIdx":27},{"icon":{"paths":["M864 511.326c0-194.147-157.598-351.535-352-351.535-194.404 0-352 157.388-352 351.535 0 194.15 157.596 351.535 352 351.535 194.402 0 352-157.385 352-351.535zM928 511.326c0 229.449-186.249 415.454-416 415.454s-416-186.005-416-415.454c0-229.447 186.249-415.451 416-415.451s416 186.004 416 415.451zM694.259 570.615l-159.97 155.511c-12.425 12.079-32.218 12.079-44.642 0l-159.968-155.511c-12.664-12.309-12.937-32.542-0.61-45.188 12.328-12.651 32.587-12.924 45.251-0.61l105.65 102.707v-275.987c0-17.65 14.327-31.958 32-31.958s32 14.308 32 31.958v275.987l105.647-102.707c12.668-12.314 32.926-12.041 45.252 0.61 12.326 12.646 12.053 32.879-0.61 45.188z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-down-circle"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":399,"id":144,"name":"arrow-down-circle","prevSize":32,"code":59686},"setIdx":0,"setId":3,"iconIdx":28},{"icon":{"paths":["M512 864c194.402 0 352-157.598 352-352 0-46.519-9.024-90.932-25.417-131.582l48.516-48.518c26.214 54.496 40.9 115.584 40.9 180.1 0 229.751-186.249 416-416 416s-416-186.249-416-416c0-229.751 186.249-416 416-416 95.377 0 183.253 32.096 253.423 86.076l-45.709 45.712c-58.223-42.623-130.031-67.788-207.714-67.788-194.404 0-352 157.596-352 352 0 194.402 157.596 352 352 352zM902.63 230.624c12.497-12.499 12.493-32.76-0.009-45.255-12.497-12.495-32.759-12.491-45.252 0.008l-345.387 345.504-105.339-105.491c-12.488-12.506-32.749-12.52-45.255-0.032-12.506 12.489-12.52 32.747-0.032 45.253l127.971 128.158c6.003 6.007 14.144 9.387 22.635 9.387 8.495 0.004 16.636-3.371 22.643-9.374l368.026-368.156z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["circle-check"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":400,"id":143,"name":"circle-check","prevSize":32,"code":59687},"setIdx":0,"setId":3,"iconIdx":29},{"icon":{"paths":["M512 352.004c17.673 0 32 14.327 32 32v224c0 17.673-14.327 32-32 32s-32-14.327-32-32v-224c0-17.673 14.327-32 32-32z","M512 672.004c17.673 0 32 14.327 32 32s-14.327 32-32 32c-17.673 0-32-14.327-32-32s14.327-32 32-32z","M567.1 158.348c-24.772-41.922-85.427-41.922-110.199 0l-359.921 609.098c-25.21 42.662 5.544 96.559 55.099 96.559h719.845c49.553 0 80.307-53.897 55.095-96.559l-359.919-609.098zM512 190.906l359.923 609.098h-719.845l359.922-609.098z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["warning"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":401,"id":142,"name":"warning","prevSize":32,"code":59688},"setIdx":0,"setId":3,"iconIdx":30},{"icon":{"paths":["M512.606 128.018c-72.375-1.375-144.904 25.78-199.305 80.524-54.654 54.999-89.301 136.056-89.301 239.466 0 80.23 44.5 174.869 97.546 252.804 53.065 77.965 120.83 148.16 176.139 175.821l15.194 7.603 14.81-8.333c217.156-122.15 272.311-333.879 272.311-427.895 0-101.732-27.925-181.775-80.179-236.931-52.343-55.247-125.295-81.503-207.215-83.060zM288 448.009c0-88.591 29.353-152.747 70.699-194.353 41.599-41.862 97.071-62.705 152.691-61.648 68.992 1.311 124.041 23.055 161.971 63.089 38.016 40.126 62.639 102.647 62.639 192.913 0 74.551-44.689 253.679-224.175 363.034-39.684-25.613-92.187-79.855-137.371-146.24-50.954-74.863-86.454-156.22-86.454-216.794zM544 416c0-17.673-14.327-32-32-32s-32 14.327-32 32c0 17.673 14.327 32 32 32s32-14.327 32-32zM608 416c0 53.018-42.982 96-96 96s-96-42.982-96-96c0-53.019 42.982-96 96-96s96 42.981 96 96z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["pin-map"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":402,"id":141,"name":"pin-map","prevSize":32,"code":59689},"setIdx":0,"setId":3,"iconIdx":31},{"icon":{"paths":["M192 736h640v-448h-640v448zM128 256c0-17.673 14.327-32 32-32h704c17.673 0 32 14.327 32 32v512c0 17.673-14.327 32-32 32h-704c-17.673 0-32-14.327-32-32v-512zM305.304 389.082c-14.866-9.557-34.665-5.253-44.222 9.613s-5.253 34.665 9.613 44.223l241.304 155.123 241.306-155.123c14.865-9.557 19.17-29.356 9.613-44.223s-29.355-19.17-44.224-9.613l-206.694 132.876-206.696-132.876z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["mail"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":403,"id":140,"name":"mail","prevSize":32,"code":59690},"setIdx":0,"setId":3,"iconIdx":32},{"icon":{"paths":["M160 224c-35.346 0-64 28.654-64 64v448c0 35.345 28.654 64 64 64h704c35.345 0 64-28.655 64-64v-448c0-35.346-28.655-64-64-64h-704zM160 288h704v448h-704v-448zM256 352c-17.673 0-32 14.327-32 32s14.327 32 32 32h64c17.673 0 32-14.327 32-32s-14.327-32-32-32h-64zM256 512c0-17.673 14.327-32 32-32h64c17.673 0 32 14.327 32 32s-14.327 32-32 32h-64c-17.673 0-32-14.327-32-32zM480 480c-17.673 0-32 14.327-32 32s14.327 32 32 32h64c17.673 0 32-14.327 32-32s-14.327-32-32-32h-64zM640 512c0-17.673 14.327-32 32-32h64c17.673 0 32 14.327 32 32s-14.327 32-32 32h-64c-17.673 0-32-14.327-32-32zM480 352c-17.673 0-32 14.327-32 32s14.327 32 32 32h64c17.673 0 32-14.327 32-32s-14.327-32-32-32h-64zM320 640c0-17.673 14.327-32 32-32h320c17.673 0 32 14.327 32 32s-14.327 32-32 32h-320c-17.673 0-32-14.327-32-32zM704 352c-17.673 0-32 14.327-32 32s14.327 32 32 32h64c17.673 0 32-14.327 32-32s-14.327-32-32-32h-64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["keyboard"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":404,"id":139,"name":"keyboard","prevSize":32,"code":59691},"setIdx":0,"setId":3,"iconIdx":33},{"icon":{"paths":["M266.667 170.667c0-17.673 14.327-32 32-32h500.621c12.122 0 23.202 6.848 28.625 17.689 5.419 10.841 4.25 23.814-3.025 33.511l-122.133 162.845 122.133 162.843c7.275 9.698 8.444 22.673 3.025 33.51-5.423 10.842-16.503 17.69-28.625 17.69h-468.621v286.579c0 17.673-14.327 32-32 32s-32-14.327-32-32v-682.667zM330.667 502.754h404.621l-98.133-130.843c-8.533-11.378-8.533-27.023 0-38.4l98.133-130.845h-404.621v300.087z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["flag"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":405,"id":138,"name":"flag","prevSize":32,"code":59692},"setIdx":0,"setId":3,"iconIdx":34},{"icon":{"paths":["M354.254 512c-88.366 0-160-71.633-160-160 0-88.366 71.634-160 160-160s159.999 71.634 159.999 160c0 26.934-6.656 52.313-18.411 74.583l11.917 11.915-0.132 0.128 299.136 299.136c3.533 9.924 6.409 20.975 7.74 31.607 1.651 13.218 0.563 22.967-1.877 28.937-1.766 4.335-4.22 7.232-10.769 9.015-8.316 2.261-24.521 2.795-52.821-5.504-8.525-3.806-27.721-16.282-45.133-35.379-18.18-19.938-29.649-41.856-29.649-62.438 0-15.642-11.307-28.992-26.739-31.565l-91.75-15.292c-3.763-2.658-18.765-15.693-10.129-58.867 2.095-10.492-1.186-21.338-8.751-28.902l-88.201-88.196c-26.467 19.379-59.111 30.822-94.429 30.822zM570.423 410.916c5.107-18.773 7.829-38.527 7.829-58.916 0-123.712-100.288-224-223.999-224-123.712 0-224 100.288-224 224s100.288 224 224 224c29.287 0 57.261-5.619 82.904-15.842l43.008 43.008c-7.155 65.493 23.991 104.533 55.97 115.191l2.381 0.794 74.854 12.476c7.083 31.407 25.173 58.125 43.234 77.935 23.125 25.357 50.961 44.629 69.764 52.151l1.323 0.529 1.365 0.41c34.714 10.415 64.73 13.188 89.596 6.426 26.782-7.283 44.331-24.785 53.227-46.583 8.23-20.164 8.474-42.283 6.127-61.065-2.402-19.217-7.898-37.956-14.042-53.312-1.609-4.023-4.019-7.68-7.083-10.743l-286.46-286.458zM386.254 336c0 26.51-21.49 48-48 48s-48-21.49-48-48c0-26.51 21.49-48 48-48s48 21.49 48 48z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["encrypted"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":406,"id":137,"name":"encrypted","prevSize":32,"code":59693},"setIdx":0,"setId":3,"iconIdx":35},{"icon":{"paths":["M694.626 300.76c12.497-12.854 12.497-33.694 0-46.548l-160-164.571c-12.497-12.854-32.755-12.854-45.252 0l-160.001 164.571c-12.497 12.854-12.497 33.694 0 46.548s32.758 12.854 45.255 0l105.373-108.383v430.711c0 18.176 14.327 32.913 32 32.913s32-14.737 32-32.913v-430.711l105.374 108.384c12.497 12.854 32.755 12.854 45.252 0z","M192 384h160v64h-128v416h576v-416h-128v-64h160c17.673 0 32 14.327 32 32v480c0 17.673-14.327 32-32 32h-640c-17.673 0-32-14.327-32-32v-480c0-17.673 14.327-32 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["share"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":407,"id":136,"name":"share","prevSize":32,"code":59694},"setIdx":0,"setId":3,"iconIdx":36},{"icon":{"paths":["M273.128 356.679c-6.619 27.765-2.384 63.755 25.498 105.58l21.374 32.060v17.69h-48c-44.011 0-70.483 14.874-86.278 33.621-16.496 19.575-24.573 47.262-23.734 77.491 0.841 30.259 10.601 59.968 25.818 81.31 15.127 21.218 33.403 31.578 52.194 31.578h80v64h-80c-45.209 0-80.933-25.638-104.305-58.423-23.283-32.657-36.523-74.948-37.682-116.689-1.161-41.771 9.763-86.084 38.767-120.508 20.726-24.597 49.155-42.317 84.825-50.782-16.1-39.010-19.009-77.050-10.731-111.77 11.253-47.2 42.304-84.492 80.791-107.342 38.399-22.798 85.676-32.138 131.301-21.965 35.587 7.935 68.909 27.48 95.252 59.554 53.751-35.147 127.582-30.892 182.485-2.495 34.436 17.812 64.794 46.382 81.438 85.009 12.292 28.531 16.435 61.011 10.603 96.206 46.114 6.682 81.51 25.156 105.617 53.453 30.349 35.627 38.106 81.353 33.446 123.285-4.659 41.92-21.948 83.486-46.545 115.115-24.060 30.933-59.354 57.353-101.261 57.353h-80v-64h80c14.093 0 32.802-9.579 50.739-32.644 17.404-22.374 30.114-52.804 33.455-82.889 3.341-30.067-2.901-56.341-18.556-74.718-15.219-17.869-44.032-33.749-97.638-33.749h-45.687l15.616-42.935c13.542-37.252 11.089-66.743 1.434-89.149-9.856-22.872-28.501-41.302-52.062-53.489-49.587-25.649-107.477-18.624-134.716 14.063l-30.135 36.162-22.541-41.324c-19.759-36.22-47.232-54.176-74.872-60.34-28.375-6.327-59.098-0.669-84.699 14.531-25.513 15.148-44.462 38.854-51.209 67.153zM630.98 787.221c12.297-12.689 11.981-32.947-0.708-45.248-12.693-12.301-32.951-11.985-45.252 0.708l-41.020 42.321v-273.003c0-17.673-14.327-32-32-32s-32 14.327-32 32v273.003l-41.020-42.321c-12.301-12.693-32.561-13.009-45.251-0.708s-13.007 32.559-0.707 45.248l95.998 99.051c6.029 6.217 14.319 9.728 22.98 9.728s16.951-3.511 22.98-9.728l96-99.051z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["download"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":408,"id":135,"name":"download","prevSize":32,"code":59695},"setIdx":0,"setId":3,"iconIdx":37},{"icon":{"paths":["M273.128 356.679c-6.619 27.765-2.384 63.755 25.498 105.58l33.166 49.749h-59.792c-44.011 0-70.483 14.874-86.278 33.621-16.496 19.575-24.573 47.262-23.734 77.491 0.841 30.259 10.601 59.968 25.818 81.31 15.127 21.218 33.403 31.578 52.194 31.578h144v64h-144c-45.209 0-80.933-25.638-104.305-58.423-23.283-32.657-36.523-74.948-37.682-116.689-1.161-41.771 9.763-86.084 38.767-120.508 20.726-24.597 49.155-42.317 84.825-50.782-16.1-39.010-19.009-77.050-10.731-111.77 11.253-47.2 42.304-84.492 80.791-107.342 38.399-22.798 85.676-32.138 131.301-21.965 35.587 7.935 68.909 27.48 95.252 59.554 53.751-35.147 127.582-30.892 182.485-2.495 34.436 17.812 64.794 46.382 81.438 85.009 12.292 28.531 16.435 61.011 10.603 96.206 46.114 6.682 81.51 25.156 105.617 53.453 30.349 35.627 38.106 81.353 33.446 123.285-4.659 41.92-21.948 83.486-46.545 115.115-24.060 30.933-59.354 57.353-101.261 57.353h-144v-64h144c14.093 0 32.802-9.579 50.739-32.644 17.404-22.374 30.114-52.804 33.455-82.889 3.341-30.067-2.901-56.341-18.556-74.718-15.219-17.869-44.032-33.749-97.638-33.749h-45.687l15.616-42.935c13.547-37.252 11.089-66.743 1.434-89.149-9.856-22.872-28.501-41.302-52.062-53.489-49.587-25.649-107.477-18.624-134.716 14.063l-30.135 36.162-22.541-41.324c-19.759-36.22-47.232-54.176-74.872-60.34-28.375-6.327-59.098-0.669-84.699 14.531-25.513 15.148-44.462 38.854-51.209 67.153zM630.98 588.779l-96-99.051c-6.029-6.217-14.319-9.728-22.98-9.728s-16.951 3.511-22.98 9.728l-95.998 99.051c-12.3 12.689-11.983 32.947 0.707 45.248s32.951 11.985 45.251-0.708l41.020-42.321v273.003c0 17.673 14.327 32 32 32s32-14.327 32-32v-273.003l41.020 42.321c12.301 12.693 32.559 13.009 45.252 0.708 12.689-12.301 13.005-32.559 0.708-45.248z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["upload"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":409,"id":134,"name":"upload","prevSize":32,"code":59696},"setIdx":0,"setId":3,"iconIdx":38},{"icon":{"paths":["M444.156 742.626c-12.497-12.497-12.497-32.755 0-45.252l185.374-185.374-185.374-185.373c-12.497-12.497-12.497-32.758 0-45.255s32.759-12.497 45.257 0l208 208.001c12.497 12.497 12.497 32.755 0 45.252l-208 208c-12.497 12.497-32.759 12.497-45.257 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["chevron-right"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":410,"id":133,"name":"chevron-right","prevSize":32,"code":59697},"setIdx":0,"setId":3,"iconIdx":39},{"icon":{"paths":["M593.822 281.373c12.497 12.497 12.497 32.758 0 45.255l-185.372 185.373 185.372 185.374c12.497 12.497 12.497 32.755 0 45.252s-32.755 12.497-45.252 0l-208.002-208c-12.497-12.497-12.497-32.755 0-45.252l208.002-208.001c12.497-12.497 32.755-12.497 45.252 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["chevron-left"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":411,"id":132,"name":"chevron-left","prevSize":32,"code":59698},"setIdx":0,"setId":3,"iconIdx":40},{"icon":{"paths":["M746.236 587.959c-12.497 12.497-32.759 12.497-45.257 0l-185.374-185.371-185.371 185.371c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l208-208.001c12.497-12.497 32.759-12.497 45.257 0l208 208.001c12.497 12.497 12.497 32.755 0 45.252z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["chevron-up"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":412,"id":131,"name":"chevron-up","prevSize":32,"code":59699},"setIdx":0,"setId":3,"iconIdx":41},{"icon":{"paths":["M282.726 436.041c12.497-12.498 32.758-12.498 45.255 0l185.372 185.37 185.374-185.37c12.497-12.498 32.755-12.498 45.252 0s12.497 32.755 0 45.252l-208 208c-12.497 12.497-32.755 12.497-45.252 0l-208.001-208c-12.497-12.497-12.497-32.755 0-45.252z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["chevron-down"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":413,"id":130,"name":"chevron-down","prevSize":32,"code":59700},"setIdx":0,"setId":3,"iconIdx":42},{"icon":{"paths":["M697.698 626.56c12.676-12.314 32.934-12.023 45.252 0.649 12.314 12.676 12.023 32.934-0.649 45.252l-208 202.121c-12.42 12.066-32.183 12.066-44.604 0l-207.999-202.121c-12.675-12.318-12.965-32.576-0.649-45.252 12.317-12.672 32.576-12.962 45.25-0.649l185.699 180.45 185.698-180.45zM697.698 416.798c12.676 12.317 32.934 12.027 45.252-0.649 12.314-12.675 12.023-32.934-0.649-45.25l-208-202.119c-12.42-12.067-32.183-12.067-44.604 0l-207.999 202.119c-12.675 12.316-12.965 32.576-0.649 45.25 12.316 12.676 32.576 12.966 45.25 0.649l185.699-180.449 185.698 180.449z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["order"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":414,"id":129,"name":"order","prevSize":32,"code":59701},"setIdx":0,"setId":3,"iconIdx":43},{"icon":{"paths":["M930.253 512c0 229.751-186.249 416-416 416-229.749 0-415.999-186.249-415.999-416s186.249-416 415.999-416c229.751 0 416 186.249 416 416zM570.039 859.605l-41.83-156.105c-4.608 0.333-9.263 0.499-13.956 0.499-4.57 0-9.101-0.158-13.594-0.474l-41.835 156.134c18.057 2.854 36.57 4.339 55.428 4.339 18.982 0 37.615-1.502 55.787-4.395zM438.443 688.452c-47.551-20.459-85.181-59.571-103.675-108.126l-155.028 41.54c33.967 103.484 114.617 185.805 217.044 222.054l41.659-155.469zM162.254 512c0 16.090 1.079 31.927 3.17 47.445l156.904-42.044c-0.049-1.796-0.074-3.597-0.074-5.402 0-4.911 0.184-9.779 0.546-14.596l-156.051-41.813c-2.958 18.368-4.495 37.21-4.495 56.41zM395.858 180.407c-99.159 35.408-177.785 114.033-213.195 213.191l155.535 41.675c19.356-44.352 54.982-79.977 99.336-99.331l-41.676-155.535zM514.253 160c-19.196 0-38.037 1.537-56.401 4.495l41.813 156.051c4.817-0.361 9.681-0.546 14.588-0.546 5.030 0 10.018 0.194 14.95 0.573l41.805-156.022c-18.475-2.995-37.431-4.552-56.755-4.552zM632.064 843.802c102.656-36.45 183.39-119.194 217.092-223.121l-154.974-41.523c-18.291 48.981-56.009 88.491-103.787 109.15l41.668 155.494zM863.249 558.199c1.984-15.121 3.004-30.541 3.004-46.199 0-18.769-1.468-37.197-4.297-55.172l-156.156 41.843c0.299 4.403 0.452 8.849 0.452 13.329 0 1.378-0.013 2.752-0.043 4.122l157.039 42.078zM846.263 394.775c-35.166-99.601-113.886-178.641-213.278-214.248l-41.681 155.559c44.587 19.556 80.311 55.564 99.507 100.343l155.452-41.653zM642.253 512c0-70.694-57.306-128-128-128-70.69 0-127.999 57.306-127.999 128s57.309 128 127.999 128c70.694 0 128-57.306 128-128z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["support"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":415,"id":128,"name":"support","prevSize":32,"code":59702},"setIdx":0,"setId":3,"iconIdx":44},{"icon":{"paths":["M336 128c17.673 0 32 14.327 32 32v144h288v-144c0-17.673 14.327-32 32-32s32 14.327 32 32v144h144c17.673 0 32 14.327 32 32s-14.327 32-32 32h-144v288h144c17.673 0 32 14.327 32 32s-14.327 32-32 32h-144v144c0 17.673-14.327 32-32 32s-32-14.327-32-32v-144h-288v144c0 17.673-14.327 32-32 32s-32-14.327-32-32v-144h-144c-17.673 0-32-14.327-32-32s14.327-32 32-32h144v-288h-144c-17.673 0-32-14.327-32-32s14.327-32 32-32h144v-144c0-17.673 14.327-32 32-32zM368 368v288h288v-288h-288z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["channel-public"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":416,"id":127,"name":"channel-public","prevSize":32,"code":59703},"setIdx":0,"setId":3,"iconIdx":45},{"icon":{"paths":["M138.667 213.333c0-17.673 14.327-32 32-32h234.057c7.183 0 14.156 2.416 19.798 6.86l88.814 69.94h339.998c17.673 0 32 14.327 32 32v520.533c0 17.673-14.327 32-32 32h-682.667c-17.673 0-32-14.327-32-32v-597.333zM202.667 245.333v533.333h618.667v-456.533h-319.087c-7.181 0-14.153-2.416-19.797-6.86l-88.813-69.94h-190.97z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["folder"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":417,"id":126,"name":"folder","prevSize":32,"code":59704},"setIdx":0,"setId":3,"iconIdx":46},{"icon":{"paths":["M160 800c-11.706 0-22.478-6.391-28.087-16.666s-5.161-22.793 1.169-32.64l112.304-174.694h-69.387c-17.673 0-32-14.327-32-32v-288c0-17.673 14.327-32 32-32h256c17.673 0 32 14.327 32 32v288c0 6.135-1.762 12.143-5.082 17.306l-144.001 224c-5.888 9.156-16.029 14.694-26.918 14.694h-128zM330.918 561.306l-112.304 174.694h51.916l129.47-201.399v-246.601h-192v224h96c11.706 0 22.478 6.391 28.087 16.666s5.161 22.793-1.169 32.64zM576 800c-11.708 0-22.477-6.391-28.087-16.666s-5.158-22.793 1.169-32.64l112.307-174.694h-69.389c-17.673 0-32-14.327-32-32v-288c0-17.673 14.327-32 32-32h256c17.673 0 32 14.327 32 32v288c0 6.135-1.762 12.143-5.082 17.306l-144 224c-5.888 9.156-16.030 14.694-26.918 14.694h-128zM746.918 561.306l-112.307 174.694h51.917l129.472-201.399v-246.601h-192v224h96c11.708 0 22.477 6.391 28.087 16.666s5.158 22.793-1.169 32.64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["quote"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":418,"id":125,"name":"quote","prevSize":32,"code":59705},"setIdx":0,"setId":3,"iconIdx":47},{"icon":{"paths":["M321.626 430.882l224.49 224.491-126.12 126.118-224.49-224.491 126.12-126.118zM366.881 385.626l192.116-192.116 224.491 224.49-192.115 192.116-224.492-224.49zM581.623 125.628c-12.497-12.497-32.759-12.497-45.257 0l-408.743 408.747c-12.497 12.497-12.497 32.755 0 45.252l269.745 269.747c5.23 5.231 11.82 8.269 18.631 9.122v0.068h0.571c2.276 0.243 4.573 0.243 6.85 0h440.579c17.673 0 32-14.327 32-32s-14.327-32-32-32h-366.566l353.937-353.937c12.497-12.497 12.497-32.757 0-45.254l-269.747-269.745z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["prune"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":419,"id":124,"name":"prune","prevSize":32,"code":59706},"setIdx":0,"setId":3,"iconIdx":48},{"icon":{"paths":["M536.845 548.215h-255.502c-20.173 0-36.527-16.354-36.527-36.527s16.354-36.527 36.527-36.527h102.99c-21.546-22.75-32.32-50.118-32.32-82.102 0-39.587 15.766-72.27 47.297-98.048 31.764-26.008 72.959-39.012 123.596-39.012 34.526 0 65.25 6.675 92.177 20.024 27.162 13.349 48.107 31.762 62.835 55.238 8.849 13.888 15.083 28.54 18.697 43.958 4.198 17.914-11.17 33.030-29.572 33.030-18.398 0-32.499-15.279-37.828-32.89-4.617-15.263-12.779-28.121-24.486-38.574-19.332-17.492-46.609-26.238-81.822-26.238-32.683 0-58.231 7.25-76.642 21.75-18.185 14.27-27.275 34.179-27.275 59.726 0 20.484 8.629 37.86 25.892 52.132 13.764 11.046 35.012 21.385 63.744 31.006h247.556c20.173 0 36.527 16.354 36.527 36.527s-16.354 36.527-36.527 36.527h-90.027c7.138 7.215 13.133 14.878 17.975 22.989 11.511 18.871 17.263 41.079 17.263 66.628 0 40.738-15.881 73.421-47.642 98.048-31.761 24.397-74.227 36.595-127.394 36.595-34.522 0-66.743-6.558-96.666-19.678-29.921-13.35-53.052-31.531-69.393-54.549-9.777-13.965-16.588-29.077-20.432-45.338-4.233-17.903 11.182-33.028 29.581-33.028s32.466 15.364 38.446 32.764c5.318 15.475 14.771 28.604 28.356 39.39 22.558 17.493 52.591 26.236 90.108 26.236 34.987 0 61.798-7.134 80.439-21.402 18.645-14.272 27.968-33.719 27.968-58.347s-8.631-43.614-25.894-56.964c-14.332-11.273-38.34-22.387-72.026-33.344z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["strike"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":420,"id":123,"name":"strike","prevSize":32,"code":59707},"setIdx":0,"setId":3,"iconIdx":49},{"icon":{"paths":["M388.508 320c0-17.673-14.327-32-32-32s-32 14.327-32 32v256c0 106.039 85.961 192 192.002 192 106.035 0 192-85.961 192-192v-256c0-17.673-14.327-32-32-32-17.677 0-32 14.327-32 32v256c0 70.694-57.31 128-128 128-70.694 0-128.002-57.306-128.002-128v-256zM356.508 848c-17.673 0-32 14.327-32 32s14.327 32 32 32h320.002c17.673 0 32-14.327 32-32s-14.327-32-32-32h-320.002z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["underline"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":421,"id":122,"name":"underline","prevSize":32,"code":59708},"setIdx":0,"setId":3,"iconIdx":50},{"icon":{"paths":["M546.253 352c17.673 0 32-14.327 32-32s-14.327-32-32-32c-17.673 0-32 14.327-32 32s14.327 32 32 32zM561.865 436.996c2.756-17.457-9.161-33.844-26.62-36.6-17.455-2.756-33.843 9.161-36.599 26.616l-48 304c-2.756 17.459 9.161 33.843 26.62 36.599 17.455 2.756 33.843-9.161 36.599-26.615l48-304z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["italic"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":422,"id":121,"name":"italic","prevSize":32,"code":59709},"setIdx":0,"setId":3,"iconIdx":51},{"icon":{"paths":["M384 775.415c-17.673 0-32-14.327-32-32v-453.166c0-17.673 14.327-32 32-32h137.075c56.119 0 98.27 11.603 126.447 34.81 28.416 23.206 42.624 57.542 42.624 103.007 0 24.153-6.865 45.585-20.599 64.29-13.734 18.47-32.444 32.798-56.124 42.978 27.942 7.817 49.967 22.733 66.069 44.757 16.337 21.786 24.508 47.834 24.508 78.144 0 46.409-15.036 82.876-45.111 109.397-30.071 26.522-72.576 39.782-127.514 39.782h-147.375zM420.198 533.53v186.121h112.598c31.731 0 56.713-8.171 74.944-24.508 18.47-16.576 27.708-39.309 27.708-68.198 0-62.276-33.865-93.414-101.585-93.414h-113.664zM420.198 478.827h103.006c29.837 0 53.636-7.458 71.394-22.379 17.997-14.916 26.995-35.163 26.995-60.737 0-28.416-8.286-49.017-24.862-61.804-16.576-13.024-41.796-19.536-75.657-19.536h-100.877v164.456z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["bold"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":423,"id":120,"name":"bold","prevSize":32,"code":59710},"setIdx":0,"setId":3,"iconIdx":52},{"icon":{"paths":["M639.172 204.798c16.495 6.344 24.725 24.859 18.381 41.354l-213.333 554.667c-6.345 16.495-24.861 24.725-41.356 18.381s-24.724-24.862-18.38-41.357l213.335-554.666c6.34-16.495 24.858-24.724 41.353-18.38zM330.312 361.371c12.497 12.497 12.497 32.758 0 45.255l-105.373 105.374 105.373 105.37c12.497 12.497 12.497 32.759 0 45.257s-32.758 12.497-45.255 0l-128-128c-12.497-12.497-12.497-32.759 0-45.257l128-127.999c12.497-12.497 32.758-12.497 45.255 0zM711.723 361.371c12.497-12.497 32.759-12.497 45.257 0l128 127.999c12.497 12.497 12.497 32.759 0 45.257l-128 128c-12.497 12.497-32.759 12.497-45.257 0s-12.497-32.759 0-45.257l105.374-105.37-105.374-105.374c-12.497-12.497-12.497-32.758 0-45.255z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["code"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":424,"id":119,"name":"code","prevSize":32,"code":59711},"setIdx":0,"setId":3,"iconIdx":53},{"icon":{"paths":["M769.293 649.374c12.497 12.497 12.497 32.755 0 45.252l-192 192c-12.497 12.497-32.755 12.497-45.252 0l-192.001-192c-12.497-12.497-12.497-32.755 0-45.252s32.758-12.497 45.255 0l137.373 137.37v-578.743h-192v192c0 17.673-14.327 32-32 32s-32-14.327-32-32v-224c0-17.673 14.327-32 32-32h256c17.673 0 32 14.327 32 32v610.743l137.374-137.37c12.497-12.497 32.755-12.497 45.252 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["jump-to-message"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":425,"id":118,"name":"jump-to-message","prevSize":32,"code":59712},"setIdx":0,"setId":3,"iconIdx":54},{"icon":{"paths":["M385 769.293c-12.497 12.497-32.758 12.497-45.255 0l-192-192c-12.497-12.497-12.497-32.755 0-45.252l192-192.001c12.497-12.497 32.758-12.497 45.255 0s12.497 32.758 0 45.255l-137.373 137.373h578.745v-192h-192c-17.673 0-32-14.327-32-32s14.327-32 32-32h224c17.673 0 32 14.327 32 32v256c0 17.673-14.327 32-32 32h-610.745l137.373 137.374c12.497 12.497 12.497 32.755 0 45.252z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-return"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":426,"id":117,"name":"arrow-return","prevSize":32,"code":59713},"setIdx":0,"setId":3,"iconIdx":55},{"icon":{"paths":["M385 297.373c-12.497-12.497-32.758-12.497-45.255 0l-192 192.001c-12.497 12.497-12.497 32.755 0 45.252l192 192c12.497 12.497 32.758 12.497 45.255 0s12.497-32.755 0-45.252l-137.373-137.374h578.745v128c0 17.673 14.327 32 32 32s32-14.327 32-32v-160c0-17.673-14.327-32-32-32h-610.745l137.373-137.373c12.497-12.497 12.497-32.758 0-45.255z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-back"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":427,"id":116,"name":"arrow-back","prevSize":32,"code":59714},"setIdx":0,"setId":3,"iconIdx":56},{"icon":{"paths":["M307.745 105.235c12.497-12.48 32.758-12.48 45.255 0s12.497 32.715 0 45.195l-105.373 105.233h610.745c17.673 0 32 14.308 32 31.958v111.852c0 17.65-14.327 31.959-32 31.959s-32-14.309-32-31.959v-79.894h-578.745l105.373 105.233c12.497 12.482 12.497 32.715 0 45.195s-32.758 12.48-45.255 0l-160-159.788c-12.497-12.48-12.497-32.715 0-45.195l160-159.789zM720.998 917.414c-12.497 12.48-32.755 12.48-45.252 0s-12.497-32.713 0-45.193l105.37-105.233h-610.743c-17.673 0-32-14.31-32-31.957v-111.855c0-17.647 14.327-31.957 32-31.957s32 14.31 32 31.957v79.898h578.743l-105.37-105.237c-12.497-12.48-12.497-32.713 0-45.193s32.755-12.48 45.252 0l160 159.787c12.497 12.48 12.497 32.717 0 45.197l-160 159.787z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-looping"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":428,"id":115,"name":"arrow-looping","prevSize":32,"code":59715},"setIdx":0,"setId":3,"iconIdx":57},{"icon":{"paths":["M276.48 157.44c0-16.259 13.181-29.44 29.44-29.44s29.44 13.181 29.44 29.44v58.877h353.28v-58.877c0-16.259 13.18-29.44 29.44-29.44s29.44 13.181 29.44 29.44v58.877h85.76c17.673 0 32 14.327 32 32v583.679c0 17.673-14.327 32-32 32h-642.56c-17.673 0-32-14.327-32-32v-583.679c0-1.105 0.056-2.196 0.165-3.272 1.639-16.136 15.267-28.728 31.835-28.728h85.76v-58.877zM801.28 392.957h-578.56v407.039h578.56v-407.039zM423.68 644.476c0-8.836 7.163-16 16-16h26.88c8.836 0 16 7.164 16 16v26.88c0 8.836-7.164 16-16 16h-26.88c-8.836 0-16-7.164-16-16v-26.88zM321.92 510.72c-8.836 0-16 7.164-16 16v26.88c0 8.836 7.164 16 16 16h26.88c8.837 0 16-7.164 16-16v-26.88c0-8.836-7.163-16-16-16h-26.88zM541.44 526.72c0-8.836 7.164-16 16-16h26.88c8.836 0 16 7.164 16 16v26.88c0 8.836-7.164 16-16 16h-26.88c-8.836 0-16-7.164-16-16v-26.88zM321.92 628.476c-8.836 0-16 7.164-16 16v26.88c0 8.836 7.164 16 16 16h26.88c8.837 0 16-7.164 16-16v-26.88c0-8.836-7.163-16-16-16h-26.88zM541.44 644.476c0-8.836 7.164-16 16-16h26.88c8.836 0 16 7.164 16 16v26.88c0 8.836-7.164 16-16 16h-26.88c-8.836 0-16-7.164-16-16v-26.88zM439.68 510.72c-8.836 0-16 7.164-16 16v26.88c0 8.836 7.164 16 16 16h26.88c8.836 0 16-7.164 16-16v-26.88c0-8.836-7.164-16-16-16h-26.88zM659.2 526.72c0-8.836 7.164-16 16-16h26.88c8.836 0 16 7.164 16 16v26.88c0 8.836-7.164 16-16 16h-26.88c-8.836 0-16-7.164-16-16v-26.88zM675.2 628.476c-8.836 0-16 7.164-16 16v26.88c0 8.836 7.164 16 16 16h26.88c8.836 0 16-7.164 16-16v-26.88c0-8.836-7.164-16-16-16h-26.88z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["calendar"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":429,"id":114,"name":"calendar","prevSize":32,"code":59716},"setIdx":0,"setId":3,"iconIdx":58},{"icon":{"paths":["M774.426 576c-35.345 0-64-28.655-64-64s28.655-64 64-64c35.345 0 64 28.655 64 64s-28.655 64-64 64z","M518.426 576c-35.345 0-64-28.655-64-64s28.655-64 64-64c35.345 0 64 28.655 64 64s-28.655 64-64 64z","M262.426 576c-35.346 0-64-28.655-64-64s28.654-64 64-64c35.346 0 64 28.655 64 64s-28.654 64-64 64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["meatballs"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":430,"id":113,"name":"meatballs","prevSize":32,"code":59717},"setIdx":0,"setId":3,"iconIdx":59},{"icon":{"paths":["M521.357 195.096l224.171 259.701v365.751c0 5.85-4.749 10.59-10.607 10.59h-136.235v-149.623c0-23.394-18.987-42.355-42.411-42.355h-85.841c-23.424 0-42.415 18.961-42.415 42.355v149.623h-136.229c-5.856 0-10.603-4.74-10.603-10.59v-365.824l224.105-259.628c4.233-4.9 11.836-4.9 16.064 0zM559.834 894.673h175.087c40.994 0 74.223-33.186 74.223-74.125v-243.883h56.154c12.437 0 23.735-7.241 28.919-18.534 5.18-11.294 3.294-24.567-4.826-33.975l-319.846-370.544c-29.611-34.302-82.829-34.302-112.435 0l-319.848 370.544c-8.122 9.408-10.007 22.682-4.825 33.975s16.48 18.534 28.918 18.534h56.214v243.883c0 40.939 33.231 74.125 74.223 74.125h175.085c1.173 0.098 2.359 0.149 3.558 0.149h85.841c1.199 0 2.385-0.051 3.558-0.149z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["home"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":431,"id":112,"name":"home","prevSize":32,"code":59718},"setIdx":0,"setId":3,"iconIdx":60},{"icon":{"paths":["M832 512c0 176.73-143.27 320-320 320-176.731 0-320-143.27-320-320h-64c0 212.079 171.923 384 384 384 212.079 0 384-171.921 384-384 0-212.077-171.921-384-384-384-123.718 0-233.772 58.508-304 149.364v-101.364c0-17.673-14.327-32-32-32s-32 14.327-32 32v192c0 17.673 14.327 32 32 32h176c17.673 0 32-14.327 32-32s-14.327-32-32-32h-107.295c57.239-86.755 155.582-144 267.295-144 176.73 0 320 143.269 320 320z","M544 320c0-17.673-14.327-32-32-32s-32 14.327-32 32v224c0 8.486 3.371 16.627 9.374 22.626l96 96c12.497 12.497 32.755 12.497 45.252 0s12.497-32.755 0-45.252l-86.626-86.63v-210.743z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["history"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":432,"id":111,"name":"history","prevSize":32,"code":59719},"setIdx":0,"setId":3,"iconIdx":61},{"icon":{"paths":["M854.507 233.251c12.561 12.43 12.672 32.691 0.243 45.254l-474.877 480.001c-6.013 6.076-14.208 9.498-22.757 9.493s-16.743-3.426-22.752-9.506l-165.124-167.091c-12.423-12.57-12.303-32.828 0.268-45.252s32.832-12.305 45.254 0.269l142.376 144.068 452.113-456.993c12.429-12.564 32.691-12.672 45.257-0.243z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["check"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":433,"id":110,"name":"check","prevSize":32,"code":59720},"setIdx":0,"setId":3,"iconIdx":62},{"icon":{"paths":["M711.113 512v54.818c-0.196 76.634-43.682 143.091-107.298 176.209-5.525-25.634-28.326-44.847-55.612-44.847h-72.405c-31.42 0-56.888 25.472-56.888 56.892v41.374c0 31.415 25.469 56.887 56.888 56.887h72.405c28.471 0 52.062-20.919 56.235-48.226 69.167-26.795 123.797-82.773 148.77-152.828 4.715 1.267 9.677 1.941 14.793 1.941h28.446c31.415 0 56.887-25.468 56.887-56.887v-85.333c0-31.42-25.472-56.887-56.887-56.887h-28.446v-28.446c0-141.385-114.615-256-256-256s-256 114.615-256 256v23.275h-28.445c-31.419 0-56.889 25.468-56.889 56.887v103.433c0 31.42 25.47 56.892 56.889 56.892h28.445c31.419 0 56.889-25.472 56.889-56.892v-36.203h0.149c-0.099-2.573-0.148-5.158-0.148-7.757v-139.636c0-109.966 89.145-199.111 199.11-199.111s199.113 89.145 199.113 199.111v85.333z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["omnichannel"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":434,"id":109,"name":"omnichannel","prevSize":32,"code":59721},"setIdx":0,"setId":3,"iconIdx":63},{"icon":{"paths":["M512 554.018c66.466 0 120.346-52.493 120.346-117.239 0-64.753-53.879-117.243-120.346-117.243s-120.347 52.491-120.347 117.243c0 64.747 53.881 117.239 120.347 117.239zM512 490.018c-32.708 0-56.346-25.404-56.346-53.239 0-27.84 23.637-53.243 56.346-53.243 32.704 0 56.346 25.403 56.346 53.243 0 27.836-23.642 53.239-56.346 53.239z","M364.125 894.144h-172.125c-17.673 0-32-14.327-32-32v-702.144c0-17.673 14.327-32 32-32h640c17.673 0 32 14.327 32 32v702.144c0 17.673-14.327 32-32 32h-172.126c-6.242 1.276-12.702 1.946-19.319 1.946h-257.109c-6.618 0-13.079-0.67-19.32-1.946zM224 830.144h68.244c-3.114-9.455-4.799-19.558-4.799-30.054v-93.449c0-56.107 37.881-105.143 92.172-119.309 19.171-5.005 39.265-5.312 58.583-0.9l42.773 9.766c20.049 4.578 40.909 4.254 60.813-0.939l28.070-7.326c20.693-5.397 42.381-5.73 63.232-0.973 60.531 13.824 103.467 67.665 103.467 129.758v83.371c0 10.496-1.685 20.599-4.8 30.054h68.245v-638.144h-576v638.144zM651.567 830.144c12.245-4.489 20.988-16.252 20.988-30.054v-83.371c0-32.235-22.289-60.186-53.713-67.362-10.825-2.47-22.084-2.3-32.828 0.503l-28.070 7.326c-29.85 7.791-61.141 8.273-91.217 1.404l-42.775-9.766c-9.29-2.121-18.955-1.971-28.175 0.435-26.112 6.814-44.331 30.396-44.331 57.382v93.449c0 13.803 8.74 25.566 20.989 30.054h279.133z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["avatar"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":435,"id":108,"name":"avatar","prevSize":32,"code":59722},"setIdx":0,"setId":3,"iconIdx":64},{"icon":{"paths":["M651.358 116.071c-57.242-19.989-105.788-20.069-138.355-20.071l-0.004 64-0.998-64c-92.005 0.342-297.345 47.824-381.242 242.996-17.897 38.968-34.758 103.342-34.758 173.004 0 69.961 17.020 146.283 52.216 207.876 23.229 40.653 92.798 131.375 191.178 173.538 94.863 40.653 206.368 52.343 296.488 16.299 16.41-6.566 24.393-25.19 17.83-41.596-6.566-16.41-25.19-24.393-41.596-17.83-69.879 27.955-163.174 20.446-247.512-15.701-80.82-34.637-141.385-112.448-160.822-146.462-28.804-50.406-43.784-115.418-43.784-176.124 0-60.766 15.020-116.183 29.055-146.59l0.184-0.4 0.174-0.404c69.507-162.182 243.825-204.605 323.586-204.605 31.599 0.002 70.882 0.296 117.261 16.493 46.144 16.113 101.389 48.779 161.822 116.767 43.657 49.114 63.535 114.976 69.389 177.712 5.892 63.121-2.85 118.187-11.541 142.093-6.404 17.6-20.429 45.44-59.392 45.7-18.261-0.806-72.823-14.673-83.123-69.568v-235.063c0-17.673-3.413-34.133-29.013-34.133-19.337 0-26.453 16.46-26.453 34.133v34.133c-35.183-39.86-95.403-68.267-152.747-68.267-106.039 0-192 85.961-192 192s85.961 192 192 192c62.178 0 117.658-29.555 152.747-75.388 25.711 71.078 102.571 93.030 137.011 94.135l0.516 0.017h0.512c82.645 0 111.714-64.806 120.085-87.829 12.642-34.761 21.675-99.695 15.125-169.907-6.592-70.597-29.38-151.402-85.278-214.288-66.906-75.265-131.076-114.598-188.561-134.67zM627.2 512c0 70.694-57.306 128-128 128s-128-57.306-128-128c0-70.694 57.306-128 128-128s128 57.306 128 128z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["mention"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":436,"id":107,"name":"mention","prevSize":32,"code":59723},"setIdx":0,"setId":3,"iconIdx":65},{"icon":{"paths":["M370.254 544c0-17.673-14.327-32-32-32s-32 14.327-32 32v32h-32c-17.673 0-32 14.327-32 32s14.327 32 32 32h32v32c0 17.673 14.327 32 32 32s32-14.327 32-32v-32h32c17.673 0 31.999-14.327 31.999-32s-14.326-32-31.999-32h-32v-32z","M746.253 624c30.929 0 56-25.071 56-56s-25.071-56-56-56c-30.925 0-56 25.071-56 56s25.075 56 56 56z","M674.253 664c0 30.929-25.071 56-56 56-30.925 0-56-25.071-56-56s25.075-56 56-56c30.929 0 56 25.071 56 56z","M706.253 128c0-17.673-14.327-32-32-32s-32 14.327-32 32v96h-128c-17.673 0-32 14.327-32 32v96h-191.999c-106.039 0-192 85.961-192 192v128c0 106.039 85.961 192 192 192h447.999c106.039 0 192-85.961 192-192v-128c0-106.039-85.961-192-192-192h-192v-64h128c17.673 0 32-14.327 32-32v-128zM866.253 544v128c0 70.694-57.306 128-128 128h-447.999c-70.693 0-128-57.306-128-128v-128c0-70.694 57.307-128 128-128h447.999c70.694 0 128 57.306 128 128z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["game"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":437,"id":106,"name":"game","prevSize":32,"code":59724},"setIdx":0,"setId":3,"iconIdx":66},{"icon":{"paths":["M550.037 242.504c0.192-17.672 14.669-31.845 32.341-31.657s31.846 14.668 31.659 32.34l-1.318 123.488 193.438-193.438c12.497-12.497 32.755-12.497 45.252 0s12.497 32.758 0 45.255l-193.438 193.438 123.49-1.319c17.673-0.189 32.149 13.984 32.337 31.658 0.192 17.673-13.982 32.149-31.654 32.337l-201.92 2.159c-8.606 0.090-16.887-3.285-22.972-9.374-6.084-6.084-9.459-14.362-9.37-22.967l2.155-201.921zM474.628 782.148c-0.192 17.673-14.669 31.846-32.341 31.659-17.672-0.192-31.845-14.669-31.656-32.341l1.318-123.49-193.438 193.438c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l193.438-193.438-123.488 1.318c-17.672 0.188-32.151-13.986-32.34-31.659s13.984-32.149 31.657-32.337l201.919-2.159c8.606-0.090 16.887 3.285 22.972 9.37 6.084 6.089 9.463 14.366 9.37 22.972l-2.155 201.92z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-collapse"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":438,"id":105,"name":"arrow-collapse","prevSize":32,"code":59725},"setIdx":0,"setId":3,"iconIdx":67},{"icon":{"paths":["M858.624 398.148c-0.188 17.672-14.669 31.847-32.337 31.655-17.673-0.188-31.846-14.666-31.659-32.338l1.318-123.488-193.438 193.437c-12.497 12.497-32.759 12.497-45.257 0s-12.497-32.755 0-45.254l193.442-193.439-123.49 1.319c-17.673 0.189-32.154-13.984-32.341-31.657s13.986-32.151 31.659-32.34l201.92-2.156c8.606-0.092 16.883 3.286 22.967 9.37s9.463 14.365 9.374 22.969l-2.159 201.921zM166.041 626.517c0.189-17.673 14.668-31.842 32.34-31.654s31.845 14.669 31.657 32.341l-1.319 123.486 193.438-193.438c12.497-12.497 32.759-12.497 45.257 0s12.497 32.759 0 45.257l-193.44 193.438 123.488-1.318c17.672-0.192 32.153 13.982 32.341 31.654s-13.985 32.154-31.657 32.341l-201.921 2.155c-8.605 0.094-16.884-3.285-22.969-9.37s-9.463-14.366-9.37-22.967l2.156-201.924z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-expand"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":439,"id":104,"name":"arrow-expand","prevSize":32,"code":59726},"setIdx":0,"setId":3,"iconIdx":68},{"icon":{"paths":["M586.372 672c-17.673 0-32 14.327-32 32s14.327 32 32 32h224c17.673 0 32-14.327 32-32v-208c0-17.673-14.327-32-32-32s-32 14.327-32 32v130.743l-233.374-233.371c-12.497-12.497-32.755-12.497-45.252 0l-73.374 73.371-169.373-169.371c-12.497-12.497-32.758-12.497-45.255 0s-12.497 32.758 0 45.255l192 191.999c12.497 12.497 32.756 12.497 45.254 0l73.374-73.37 210.743 210.743h-146.743z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-decrease"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":440,"id":103,"name":"arrow-decrease","prevSize":32,"code":59727},"setIdx":0,"setId":3,"iconIdx":69},{"icon":{"paths":["M584.115 352c-17.673 0-32-14.327-32-32s14.327-32 32-32h224c17.677 0 32 14.327 32 32v208c0 17.673-14.323 32-32 32-17.673 0-32-14.327-32-32v-130.745l-233.37 233.371c-12.497 12.497-32.759 12.497-45.257 0l-73.372-73.37-169.373 169.37c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l192-192c12.497-12.497 32.759-12.497 45.256 0l73.37 73.37 210.748-210.743h-146.748z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-increase"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":441,"id":102,"name":"arrow-increase","prevSize":32,"code":59728},"setIdx":0,"setId":3,"iconIdx":70},{"icon":{"paths":["M498.697 141.563l-298.668 136.533c-11.39 5.207-18.696 16.58-18.696 29.103v386.846c0 11.819 6.513 22.673 16.941 28.233l298.668 159.292c9.408 5.018 20.706 5.018 30.114 0l298.667-159.292c10.428-5.559 16.943-16.414 16.943-28.233v-386.846c0-12.524-7.305-23.896-18.697-29.103l-298.667-136.533c-8.448-3.862-18.159-3.862-26.607 0zM245.333 357.014l234.667 107.276v335.71l-234.667-125.154v-317.832zM544 800l234.667-125.154v-317.832l-234.667 107.276v335.71zM512 408.548l-221.699-101.348 221.699-101.348 221.7 101.348-221.7 101.348z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["apps"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":442,"id":101,"name":"apps","prevSize":32,"code":59729},"setIdx":0,"setId":3,"iconIdx":71},{"icon":{"paths":["M129.353 351.541c0-17.65 14.327-31.958 32-31.958h704c17.673 0 32 14.308 32 31.958s-14.327 31.958-32 31.958h-704c-17.673 0-32-14.308-32-31.958zM214.686 521.984c0-17.651 14.327-31.957 32-31.957h533.333c17.673 0 32 14.306 32 31.957s-14.327 31.957-32 31.957h-533.333c-17.673 0-32-14.306-32-31.957zM332.019 660.467c-17.673 0-32 14.306-32 31.957 0 17.647 14.327 31.957 32 31.957h362.667c17.673 0 32-14.31 32-31.957 0-17.651-14.327-31.957-32-31.957h-362.667z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["donner"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":443,"id":100,"name":"donner","prevSize":32,"code":59730},"setIdx":0,"setId":3,"iconIdx":72},{"icon":{"paths":["M192 181.333c-53.019 0-96 42.981-96 96v469.333c0 53.018 42.981 96 96 96h640c53.018 0 96-42.982 96-96v-469.333c0-53.019-42.982-96-96-96h-640zM160 277.333c0-17.673 14.327-32 32-32h640c17.673 0 32 14.327 32 32v202.671h-704v-202.671zM160 544.004h704v202.662c0 17.673-14.327 32-32 32h-640c-17.673 0-32-14.327-32-32v-202.662zM810.667 661.333c0-35.345-28.655-64-64-64s-64 28.655-64 64c0 35.345 28.655 64 64 64s64-28.655 64-64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["card"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":444,"id":99,"name":"card","prevSize":32,"code":59731},"setIdx":0,"setId":3,"iconIdx":73},{"icon":{"paths":["M192 405.333h213.333v-213.333h-213.333v213.333zM128 170.667c0-23.564 19.103-42.667 42.667-42.667h256c23.565 0 42.667 19.103 42.667 42.667v256c0 23.565-19.102 42.667-42.667 42.667h-256c-23.564 0-42.667-19.102-42.667-42.667v-256zM618.667 405.333h213.333v-213.333h-213.333v213.333zM554.667 170.667c0-23.564 19.102-42.667 42.667-42.667h256c23.565 0 42.667 19.103 42.667 42.667v256c0 23.565-19.102 42.667-42.667 42.667h-256c-23.565 0-42.667-19.102-42.667-42.667v-256zM618.667 618.667h213.333v213.333h-213.333v-213.333zM597.333 554.667c-23.565 0-42.667 19.102-42.667 42.667v256c0 23.565 19.102 42.667 42.667 42.667h256c23.565 0 42.667-19.102 42.667-42.667v-256c0-23.565-19.102-42.667-42.667-42.667h-256zM192 832h213.333v-213.333h-213.333v213.333zM128 597.333c0-23.565 19.103-42.667 42.667-42.667h256c23.565 0 42.667 19.102 42.667 42.667v256c0 23.565-19.102 42.667-42.667 42.667h-256c-23.564 0-42.667-19.102-42.667-42.667v-256z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["squares"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":445,"id":98,"name":"squares","prevSize":32,"code":59732},"setIdx":0,"setId":3,"iconIdx":74},{"icon":{"paths":["M694.626 473.374c12.497 12.497 12.497 32.755 0 45.252s-32.755 12.497-45.252 0l-105.374-105.371v418.745c0 17.673-14.327 32-32 32s-32-14.327-32-32v-418.745l-105.373 105.371c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l160.001-160.001c12.497-12.497 32.755-12.497 45.252 0l160 160.001zM912 160c0-17.673-14.327-32-32-32h-768c-17.673 0-32 14.327-32 32v512c0 17.673 14.327 32 32 32h96c17.673 0 32-14.327 32-32s-14.327-32-32-32h-64v-448h704v448h-64c-17.673 0-32 14.327-32 32s14.327 32 32 32h96c17.673 0 32-14.327 32-32v-512z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-up-box"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":446,"id":97,"name":"arrow-up-box","prevSize":32,"code":59733},"setIdx":0,"setId":3,"iconIdx":75},{"icon":{"paths":["M329.373 550.626c-12.497-12.497-12.497-32.755 0-45.252s32.758-12.497 45.255 0l105.373 105.37v-418.743c0-17.673 14.327-32 32-32s32 14.327 32 32v418.743l105.374-105.37c12.497-12.497 32.755-12.497 45.252 0s12.497 32.755 0 45.252l-160 160c-12.497 12.497-32.755 12.497-45.252 0l-160.001-160zM112 864c0 17.673 14.327 32 32 32h768c17.673 0 32-14.327 32-32v-512c0-17.673-14.327-32-32-32h-96c-17.673 0-32 14.327-32 32s14.327 32 32 32h64v448h-704v-448h64c17.673 0 32-14.327 32-32s-14.327-32-32-32h-96c-17.673 0-32 14.327-32 32v512z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-down-box"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":447,"id":96,"name":"arrow-down-box","prevSize":32,"code":59734},"setIdx":0,"setId":3,"iconIdx":76},{"icon":{"paths":["M128 192c-17.673 0-32 14.327-32 32v576.021c0 17.673 14.327 32 32 32h768c17.673 0 32-14.327 32-32v-576.021c0-17.673-14.327-32-32-32h-768zM160 378.302v-122.302h149.333v122.302h-149.333zM160 442.304h149.333v141.722h-149.333v-141.722zM160 648.026h149.333v119.996h-149.333v-119.996zM373.333 768.021v-119.996h490.667v119.996h-490.667zM864 584.026h-490.667v-141.722h490.667v141.722zM864 378.302h-490.667v-122.302h490.667v122.302z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["file-sheet"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":448,"id":95,"name":"file-sheet","prevSize":32,"code":59735},"setIdx":0,"setId":3,"iconIdx":77},{"icon":{"paths":["M905.088 512c0-194.404-157.598-352-352-352-194.405 0-352.001 157.596-352.001 352 0 194.402 157.596 352 352.001 352 194.402 0 352-157.598 352-352zM969.088 512c0 229.751-186.249 416-416 416s-416.001-186.249-416.001-416c0-229.751 186.25-416 416.001-416s416 186.249 416 416zM441.088 383.995v256.001c0 17.673 14.323 32 32 32 17.673 0 32-14.327 32-32v-256.001c0-17.673-14.327-32-32-32-17.677 0-32 14.327-32 32zM601.084 383.995v256.001c0 17.673 14.327 32 32 32s32-14.327 32-32v-256.001c0-17.673-14.327-32-32-32s-32 14.327-32 32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["pause"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":449,"id":94,"name":"pause","prevSize":32,"code":59736},"setIdx":0,"setId":3,"iconIdx":78},{"icon":{"paths":["M512.674 928c229.751 0 416-186.249 416-416s-186.249-416-416-416c-229.749 0-415.998 186.249-415.998 416s186.249 416 415.998 416zM400.675 383.995c0-17.673 14.327-32 32-32s32 14.327 32 32v256.001c0 17.673-14.327 32-32 32s-32-14.327-32-32v-256.001zM560.674 383.995c0-17.673 14.327-32 32-32s32 14.327 32 32v256.001c0 17.673-14.327 32-32 32s-32-14.327-32-32v-256.001z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["pause-filled"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":450,"id":93,"name":"pause-filled","prevSize":32,"code":59737},"setIdx":0,"setId":3,"iconIdx":79},{"icon":{"paths":["M512.678 928.004c229.747 0 416-186.249 416-416 0-229.749-186.253-415.999-416-415.999-229.752 0-416.001 186.25-416.001 415.999 0 229.751 186.249 416 416.001 416zM452.523 357.193l195.255 136.768c14.208 9.95 18.496 30.874 9.583 46.729-2.432 4.322-5.709 7.979-9.583 10.692l-195.255 136.768c-14.204 9.95-32.95 5.163-41.866-10.692-3.036-5.397-4.646-11.644-4.646-18.018v-273.536c0-18.72 13.597-33.897 30.372-33.897 5.709 0 11.307 1.798 16.141 5.186z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["play-filled"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":451,"id":92,"name":"play-filled","prevSize":32,"code":59738},"setIdx":0,"setId":3,"iconIdx":80},{"icon":{"paths":["M230.487 636.693c-14.92-9.472-34.694-5.056-44.167 9.865-9.473 14.916-5.058 34.692 9.862 44.164l298.665 189.632c10.47 6.647 23.838 6.647 34.304 0l298.667-189.632c14.921-9.472 19.337-29.248 9.865-44.164-9.472-14.921-29.248-19.337-44.169-9.865l-281.515 178.739-281.513-178.739zM186.32 494.852c9.473-14.921 29.247-19.337 44.167-9.86l281.513 178.739 281.515-178.739c14.921-9.476 34.697-5.060 44.169 9.86s5.056 34.697-9.865 44.169l-298.667 189.628c-10.466 6.647-23.834 6.647-34.304 0l-298.665-189.628c-14.92-9.472-19.336-29.248-9.862-44.169zM529.152 143.663l298.667 189.63c9.25 5.871 14.848 16.062 14.848 27.015s-5.598 21.144-14.848 27.015l-298.667 189.629c-10.466 6.647-23.834 6.647-34.304 0l-298.665-189.629c-9.246-5.871-14.848-16.062-14.848-27.015s5.602-21.144 14.848-27.015l298.665-189.63c10.47-6.647 23.838-6.647 34.304 0zM273.035 360.307l238.965 151.723 238.967-151.723-238.967-151.725-238.965 151.725z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["queue"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":452,"id":91,"name":"queue","prevSize":32,"code":59739},"setIdx":0,"setId":3,"iconIdx":81},{"icon":{"paths":["M512 928c-14.217 0-28.275-0.713-42.142-2.112-16.695-1.681-30.558-12.531-36.689-27.392l-40.54-98.308-98.161 40.841c-14.837 6.174-32.3 4.045-45.292-6.554-21.839-17.818-41.831-37.811-59.65-59.648-10.601-12.992-12.726-30.455-6.553-45.295l40.839-98.159-98.307-40.542c-14.864-6.127-25.714-19.994-27.395-36.689-1.396-13.867-2.111-27.925-2.111-42.142s0.714-28.275 2.11-42.142c1.681-16.695 12.531-30.558 27.395-36.685l98.307-40.543-40.84-98.163c-6.173-14.836-4.047-32.3 6.553-45.292 17.818-21.838 37.81-41.83 59.648-59.648 12.992-10.601 30.455-12.726 45.292-6.554l98.163 40.84 40.54-98.309c6.131-14.865 19.994-25.714 36.689-27.395 13.867-1.396 27.925-2.111 42.142-2.111s28.275 0.714 42.142 2.111c16.695 1.681 30.558 12.53 36.689 27.395l40.542 98.309 98.163-40.84c14.835-6.173 32.299-4.047 45.291 6.554 21.837 17.818 41.83 37.81 59.648 59.648 10.598 12.992 12.723 30.455 6.554 45.292l-40.841 98.163 98.308 40.543c14.861 6.127 25.711 19.994 27.392 36.685 1.399 13.867 2.112 27.925 2.112 42.142s-0.713 28.275-2.112 42.142c-1.681 16.695-12.531 30.562-27.392 36.689l-98.308 40.542 40.836 98.159c6.174 14.839 4.049 32.303-6.549 45.295-17.822 21.837-37.811 41.83-59.652 59.648-12.992 10.598-30.455 12.727-45.291 6.554l-98.159-40.841-40.542 98.308c-6.131 14.861-19.994 25.711-36.689 27.392-13.867 1.399-27.925 2.112-42.142 2.112zM444.454 757.982l43.383 105.203c7.979 0.542 16.034 0.815 24.162 0.815s16.183-0.273 24.162-0.815l43.383-105.203c9.455-22.921 35.733-33.805 58.628-24.282l105.054 43.708c12.156-10.598 23.578-22.020 34.18-34.176l-43.708-105.058c-9.527-22.895 1.357-49.173 24.282-58.624l105.203-43.383c0.542-7.983 0.815-16.038 0.815-24.166 0-8.124-0.273-16.183-0.815-24.162l-105.203-43.383c-22.925-9.455-33.809-35.731-24.282-58.625l43.708-105.058c-10.603-12.156-22.020-23.577-34.176-34.177l-105.058 43.709c-22.895 9.525-49.173-1.359-58.628-24.283l-43.383-105.204c-7.979-0.54-16.038-0.815-24.162-0.815s-16.183 0.275-24.162 0.815l-43.383 105.204c-9.455 22.924-35.732 33.809-58.627 24.283l-105.058-43.709c-12.156 10.6-23.577 22.022-34.177 34.177l43.709 105.058c9.525 22.895-1.359 49.17-24.283 58.625l-105.203 43.383c-0.54 7.979-0.815 16.038-0.815 24.162 0 8.128 0.275 16.183 0.815 24.166l105.202 43.383c22.924 9.451 33.809 35.729 24.283 58.624l-43.708 105.058c10.601 12.156 22.022 23.578 34.179 34.176l105.056-43.708c22.895-9.523 49.172 1.361 58.627 24.282zM416 512c0-53.018 42.982-96 96-96s96 42.982 96 96c0 53.018-42.982 96-96 96s-96-42.982-96-96zM512 352c-88.366 0-160 71.634-160 160 0 88.367 71.634 160 160 160 88.367 0 160-71.633 160-160 0-88.366-71.633-160-160-160z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["administration"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":453,"id":90,"name":"administration","prevSize":32,"code":59740},"setIdx":0,"setId":3,"iconIdx":82},{"icon":{"paths":["M561.668 127.99c-121.698 0-200.973 50.509-248.815 115.801-46.216 63.073-61.638 137.752-61.933 188.615-8.705 98.748 28.601 172.898 89.423 223.471 59.685 49.626 140.202 75.26 217.847 83.738 77.751 8.486 161.715 1.195 227.857-12.548 33.067-6.869 62.775-15.578 85.641-25.331 11.366-4.847 22.029-10.368 30.797-16.67 7.876-5.662 18.543-14.976 23.245-28.834 7.283-21.474-3.136-38.784-11.968-48.102-8.41-8.879-19.426-15.403-28.237-20.015-9.306-4.868-19.379-9.207-27.533-12.71-8.977-3.853-14.861-6.396-18.56-8.431-4.847-2.662-8.845-5.086-12.028-7.202 20.254-47.142 31.548-77.043 37.696-99.191 7.292-26.27 7.313-41.723 7.313-58.907 0-21.523-9.6-88.542-52.809-151.109-44.702-64.73-124.070-122.573-257.937-122.573zM314.916 433.894c0-40.414 12.606-101.841 49.562-152.276 35.783-48.835 95.882-89.628 197.19-89.628 112.085 0 172.087 46.886 205.274 94.94 34.679 50.219 41.472 104.040 41.472 114.741v0.2c0.004 14.918 0.004 23.638-4.979 41.594-5.491 19.776-16.964 50.189-41.54 106.534-5.798 13.295-2.761 25.771 1.156 33.754 3.665 7.479 9.003 13.244 13.329 17.263 8.836 8.213 20.655 15.684 32.226 22.046 6.618 3.635 15.236 7.334 22.562 10.475l1.562 0.67c5.905 2.539 11.52 4.971 16.687 7.42-0.909 0.41-1.856 0.823-2.833 1.237-17.741 7.569-43.081 15.206-73.557 21.542-60.945 12.663-138.065 19.209-207.885 11.584-69.926-7.633-136.986-30.336-183.881-69.325-45.46-37.798-73.674-92.066-66.481-169.822l0.136-1.472v-1.476zM819.162 553.348l-0.073-0.081c0 0 0.009 0.009 0.026 0.034 0.013 0.013 0.026 0.030 0.047 0.047z","M178.552 502.468c7.496-11.255 16.26-22.259 26.436-32.589 0.876 31.744 6.169 61.227 15.216 88.358-15.094 30.878-18.374 59.315-18.374 65.357v0.188c-0 11.379-0 17.532 3.523 30.699 3.993 14.916 12.441 38.212 30.867 82.022 5.256 12.497 2.48 24.098-0.985 31.428-3.249 6.874-7.925 12.058-11.511 15.514-7.319 7.057-16.852 13.257-25.751 18.33-5.008 2.854-11.333 5.705-16.546 8.026 11.182 3.942 24.979 7.817 40.803 11.226 44.976 9.694 101.833 14.673 153.062 8.87 51.281-5.807 99.779-23.014 133.353-51.964l0.606-0.525c14.793 2.782 29.53 4.937 44.053 6.519 10.88 1.19 21.858 2.091 32.875 2.722-10.121 14.797-22.165 28.045-35.742 39.753-46.362 39.974-108.544 60.365-167.945 67.089-59.451 6.729-123.406 0.947-173.745-9.899-25.169-5.427-48.056-12.352-65.902-20.245-8.86-3.917-17.457-8.503-24.686-13.892-6.431-4.791-15.831-13.171-20.001-25.92-6.422-19.631 2.792-35.443 10.458-43.831 7.193-7.872 16.405-13.461 23.247-17.173 7.309-3.968 15.158-7.467 21.235-10.176 6.906-3.076 10.854-4.855 13.183-6.182 1.35-0.768 2.59-1.502 3.727-2.197-13.937-33.886-21.975-56.119-26.479-72.947-5.68-21.222-5.7-33.873-5.7-47.433 0-17.711 7.436-71.138 40.721-121.126zM155.337 797.244c-0.012 0.004 0.084 0.107 0.317 0.303-0.19-0.205-0.306-0.303-0.317-0.303zM179.587 737.084c-0.003 0-0.052 0.051-0.137 0.149l0.112-0.119c0.019-0.021 0.027-0.030 0.025-0.030z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["discussions"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":454,"id":89,"name":"discussions","prevSize":32,"code":59741},"setIdx":0,"setId":3,"iconIdx":83},{"icon":{"paths":["M223.311 308.609c-47.831 66.699-64.077 147.668-64.077 201.185v1.404l-0.127 1.399c-9.348 103.236 27.547 175.996 86.848 226.377 60.643 51.516 146.604 80.998 235.291 90.893 88.61 9.886 186.223 1.399 263.339-14.976 38.562-8.188 70.929-18.121 93.888-28.126 8.909-3.883 15.838-7.535 20.945-10.765-2.377-1.515-5.248-3.196-8.678-5.030-8.883-4.749-19.055-9.263-29.611-13.897l-1.843-0.806c-9.314-4.083-19.725-8.649-27.61-13.077-14.293-8.030-28.318-17.156-38.545-26.867-5.035-4.783-10.761-11.196-14.596-19.183-4.058-8.457-6.959-21.082-1.259-34.436 30.814-72.188 45.457-111.727 52.548-137.835 6.622-24.38 6.622-36.655 6.622-56.171v-0.179c0-15.514-8.977-86.595-53.777-152.876-43.371-64.175-121.395-125.729-264.828-125.729-129.727 0-207.831 53.576-254.531 118.696zM173.267 272.433c58.132-81.062 154.749-144.433 304.574-144.433 164.894 0 261.594 72.589 315.857 152.878 52.838 78.182 64.414 161.879 64.414 187.641 0 21.658-0.017 40.337-8.794 72.64-7.834 28.834-22.626 68.617-50.048 133.423 5.069 4.036 12.591 9.003 22.507 14.571 5.12 2.876 12.992 6.34 24.055 11.191 10.261 4.51 22.579 9.933 33.89 15.979 10.846 5.798 23.526 13.572 32.951 23.74 9.86 10.633 20.211 28.868 12.817 51.136-4.873 14.673-16.183 25.092-25.609 32.017-10.24 7.522-22.946 14.281-36.86 20.343-27.947 12.177-64.585 23.181-105.681 31.906-82.197 17.451-186.522 26.688-282.906 15.936-96.311-10.743-195.347-43.174-268.314-105.165-74.031-62.891-119.295-154.778-108.551-277.854 0.276-63.411 19.118-157.053 75.696-235.949zM333.953 422.052c0-17.648 14.25-31.955 31.828-31.955h183.011c17.574 0 31.825 14.307 31.825 31.955s-14.251 31.955-31.825 31.955h-183.011c-17.578 0-31.828-14.306-31.828-31.955zM365.781 539.708c-17.578 0-31.828 14.306-31.828 31.957 0 17.647 14.25 31.953 31.828 31.953h224.12c17.579 0 31.825-14.306 31.825-31.953 0-17.651-14.246-31.957-31.825-31.957h-224.12z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["threads"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":455,"id":88,"name":"threads","prevSize":32,"code":59742},"setIdx":0,"setId":3,"iconIdx":84},{"icon":{"paths":["M877.402 153.128c-12.497-12.497-32.759-12.497-45.257 0l-668.244 668.244c-12.497 12.497-12.497 32.759 0 45.257s32.758 12.497 45.255 0l668.246-668.246c12.497-12.497 12.497-32.758 0-45.255zM309.94 170.672c-23.564 0-42.667 14.327-42.667 32s19.103 32 42.667 32h255.999c23.565 0 42.667-14.327 42.667-32s-19.102-32-42.667-32h-255.999zM585.446 309.329h-403.506c-41.237 0-74.667 33.429-74.667 74.667v384c0 6.012 0.71 11.853 2.051 17.455l61.949-61.952v-339.503c0-5.891 4.776-10.667 10.667-10.667h339.506l64-64zM387.612 778.662h306.327c5.892 0 10.667-4.774 10.667-10.667v-85.333c0-11.375 6.037-21.897 15.859-27.631 9.822-5.739 21.952-5.833 31.859-0.243l97.83 55.164c2.53 1.425 4.855 3.191 6.908 5.244 6.72 6.72 18.21 1.963 18.21-7.539v-263.322c0-9.502-11.49-14.263-18.206-7.543-2.057 2.057-4.382 3.819-6.912 5.248l-97.83 55.164c-9.907 5.585-22.037 5.495-31.859-0.243s-15.859-16.256-15.859-27.631v-7.663l110.78-73.495c47.42-41.99 123.887-8.7 123.887 56.164v263.322c0 64.862-76.467 98.155-123.887 56.162l-46.78-26.377v30.554c0 41.237-33.429 74.667-74.667 74.667h-370.327l64-64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["camera-disabled"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":456,"id":87,"name":"camera-disabled","prevSize":32,"code":59743},"setIdx":0,"setId":3,"iconIdx":85},{"icon":{"paths":["M312.195 170.672c-23.564 0-42.667 14.327-42.667 32s19.102 32 42.667 32h256.001c23.565 0 42.667-14.327 42.667-32s-19.102-32-42.667-32h-256.001z","M559.241 503.454c11.268-11.268 11.191-29.611-0.171-40.973-11.362-11.358-29.705-11.435-40.969-0.171l-71.403 71.403-71.997-71.996c-11.36-11.362-29.704-11.435-40.971-0.171-11.267 11.268-11.191 29.611 0.17 40.973l71.997 71.996-71.402 71.403c-11.267 11.264-11.191 29.606 0.17 40.969s29.704 11.439 40.971 0.171l71.404-71.403 71.996 71.996c11.358 11.362 29.705 11.439 40.969 0.171 11.268-11.264 11.191-29.611-0.171-40.969l-71.996-71.996 71.403-71.403z","M109.529 383.995c0-41.237 33.429-74.667 74.667-74.667h512.001c41.237 0 74.667 33.429 74.667 74.667v30.553l46.78-26.377c47.415-41.99 123.887-8.7 123.887 56.164v263.322c0 64.862-76.471 98.155-123.887 56.162l-46.78-26.377v30.554c0 41.237-33.429 74.667-74.667 74.667h-512.001c-41.237 0-74.667-33.429-74.667-74.667v-384.001zM184.195 373.328c-5.891 0-10.667 4.776-10.667 10.667v384.001c0 5.888 4.776 10.667 10.667 10.667h512.001c5.888 0 10.667-4.779 10.667-10.667v-85.333c0-11.375 6.037-21.897 15.859-27.631 9.822-5.739 21.948-5.833 31.859-0.243l97.826 55.164c2.534 1.425 4.855 3.191 6.912 5.244 6.72 6.72 18.21 1.963 18.21-7.539v-263.322c0-9.502-11.49-14.263-18.21-7.543-2.052 2.057-4.378 3.819-6.912 5.248l-97.826 55.164c-9.911 5.585-22.037 5.491-31.859-0.243-9.822-5.739-15.859-16.256-15.859-27.631v-85.334c0-5.891-4.779-10.667-10.667-10.667h-512.001z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["camera-unavailable"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":457,"id":86,"name":"camera-unavailable","prevSize":32,"code":59744},"setIdx":0,"setId":3,"iconIdx":86},{"icon":{"paths":["M265.018 202.672c0-17.673 19.102-32 42.667-32h256.001c23.565 0 42.667 14.327 42.667 32s-19.102 32-42.667 32h-256.001c-23.564 0-42.667-14.327-42.667-32zM169.018 383.995c0-5.891 4.776-10.667 10.667-10.667h512.001c5.888 0 10.667 4.776 10.667 10.667v85.334c0 11.375 6.037 21.892 15.859 27.631 9.822 5.734 21.948 5.828 31.855 0.243l97.83-55.164c2.534-1.429 4.855-3.191 6.912-5.248 6.72-6.72 18.21-1.958 18.21 7.543v263.322c0 9.502-11.49 14.259-18.21 7.539-2.057-2.052-4.378-3.819-6.912-5.244l-97.83-55.164c-9.907-5.589-22.033-5.495-31.855 0.243-9.822 5.734-15.859 16.256-15.859 27.631v85.333c0 5.888-4.779 10.667-10.667 10.667h-512.001c-5.891 0-10.667-4.779-10.667-10.667v-384.001zM179.685 309.328c-41.237 0-74.667 33.429-74.667 74.667v384.001c0 41.237 33.43 74.667 74.667 74.667h512.001c41.237 0 74.667-33.429 74.667-74.667v-30.554l46.775 26.377c47.42 41.993 123.891 8.7 123.891-56.162v-263.322c0-64.864-76.471-98.155-123.891-56.164l-46.775 26.377v-30.553c0-41.237-33.429-74.667-74.667-74.667h-512.001z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["camera"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":458,"id":85,"name":"camera","prevSize":32,"code":59745},"setIdx":0,"setId":3,"iconIdx":87},{"icon":{"paths":["M317.754 661.342h-118.99v-298.665h118.99l12.367-48.047c11.845-46.020 53.696-79.953 103.308-79.953h64v554.665h-64c-49.613 0-91.464-33.933-103.308-79.949l-12.367-48.051zM177.431 725.342h90.71c18.946 73.613 85.766 128 165.288 128h85.333c23.565 0 42.667-19.102 42.667-42.667v-597.332c0-23.564-19.102-42.667-42.667-42.667h-85.333c-79.522 0-146.342 54.391-165.288 128h-90.71c-23.564 0-42.667 19.103-42.667 42.667v341.332c0 23.565 19.103 42.667 42.667 42.667zM893.393 393.373c12.497 12.497 12.497 32.758 0 45.254l-73.374 73.374 73.374 73.374c12.497 12.497 12.497 32.755 0 45.252s-32.759 12.497-45.257 0l-73.374-73.37-73.37 73.37c-12.497 12.497-32.759 12.497-45.257 0s-12.497-32.755 0-45.252l73.374-73.374-73.374-73.374c-12.497-12.495-12.497-32.757 0-45.254s32.759-12.497 45.257 0l73.37 73.371 73.374-73.371c12.497-12.497 32.759-12.497 45.257 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["audio-unavailable"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":459,"id":84,"name":"audio-unavailable","prevSize":32,"code":59746},"setIdx":0,"setId":3,"iconIdx":88},{"icon":{"paths":["M870.639 153.127c-12.497-12.497-32.759-12.497-45.257 0l-668.244 668.244c-12.497 12.497-12.497 32.759 0 45.257s32.758 12.497 45.255 0l668.246-668.246c12.497-12.497 12.497-32.758 0-45.255zM679.155 480.358l55.919-55.923c16.256 79.564 14.515 161.864-5.231 240.844l-11.622 46.485c-4.284 17.148-21.658 27.571-38.805 23.283-17.143-4.284-27.567-21.658-23.283-38.805l11.622-46.485c13.875-55.509 17.677-112.875 11.401-169.399zM821.675 385.922l-11.315-36.77 51.204-51.206 21.278 69.154c33.344 108.369 31.996 224.448-3.857 332.010l-33.451 100.343c-5.589 16.764-23.71 25.826-40.474 20.237-16.768-5.589-25.83-23.71-20.241-40.478l33.446-100.339c31.637-94.912 32.828-197.333 3.409-292.952zM495.177 664.333l64-64v210.342c0 23.565-19.102 42.667-42.667 42.667h-85.333c-35.46 0-68.394-10.812-95.684-29.325l46.611-46.609c14.701 7.629 31.395 11.934 49.073 11.934h64v-125.009zM132.51 682.675c0 19.742 13.403 36.348 31.604 41.22l62.552-62.554h-30.156v-298.665h118.991l12.367-48.047c11.845-46.020 53.695-79.953 103.309-79.953h64v158.156l64-64v-115.49c0-23.564-19.102-42.667-42.667-42.667h-85.333c-79.523 0-146.343 54.391-165.289 128h-90.71c-23.564 0-42.667 19.103-42.667 42.667v341.332z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["audio-disabled"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":460,"id":83,"name":"audio-disabled","prevSize":32,"code":59747},"setIdx":0,"setId":3,"iconIdx":89},{"icon":{"paths":["M300.099 631.121h-113.433v-280.89h113.433l12.367-48.048c11.055-42.953 50.122-74.619 96.423-74.619h58.665v526.223h-58.665c-46.301 0-85.367-31.667-96.423-74.62l-12.367-48.047zM163.555 695.121h86.931c18.156 70.541 82.193 122.667 158.403 122.667h81.778c22.583 0 40.887-18.308 40.887-40.892v-572.443c0-22.582-18.304-40.889-40.887-40.889h-81.778c-76.21 0-140.246 52.124-158.403 122.667h-86.931c-22.582 0-40.889 18.307-40.889 40.889v327.11c0 22.583 18.307 40.892 40.889 40.892zM646.46 316.516c17.148-4.286 34.522 6.138 38.805 23.284l11.14 44.551c20.804 83.229 20.804 170.303 0 253.529l-11.14 44.553c-4.284 17.148-21.658 27.571-38.805 23.283-17.143-4.284-27.571-21.658-23.283-38.805l11.14-44.553c18.257-73.037 18.257-149.444 0-222.484l-11.14-44.551c-4.288-17.146 6.14-34.519 23.283-38.806zM807.475 235.938c-5.201-16.892-23.108-26.372-39.996-21.175-16.892 5.198-26.372 23.104-21.175 39.996l35.533 115.49c28.117 91.37 26.978 189.239-3.251 279.931l-32.055 96.158c-5.589 16.768 3.473 34.889 20.237 40.478 16.768 5.589 34.889-3.473 40.478-20.237l32.055-96.162c34.449-103.343 35.746-214.869 3.708-318.99l-35.533-115.49z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["audio"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":461,"id":82,"name":"audio","prevSize":32,"code":59748},"setIdx":0,"setId":3,"iconIdx":90},{"icon":{"paths":["M439.275 704.371c0-33.643 26.278-47.676 72.725-47.676s72.73 14.033 72.73 47.676c0 32.96-13.193 111.070-23.915 149.764-4.962 17.805-22.076 25.169-48.815 25.169-26.735 0-43.853-7.364-48.815-25.173-10.714-38.665-23.91-116.689-23.91-149.76zM616.781 870.374l0.021-0.094c6.178-22.289 12.57-53.862 17.387-83.447 4.685-28.791 8.721-60.71 8.721-82.462 0-35.891-15.812-67.802-46.797-87.113-26.035-16.226-57.152-19.925-84.113-19.925-26.957 0-58.078 3.699-84.113 19.925-30.982 19.311-46.795 51.221-46.795 87.113 0 21.807 4.036 53.73 8.726 82.517 4.819 29.577 11.21 61.12 17.381 83.392l0.024 0.085c7.401 26.556 24.983 45.666 46.871 56.469 19.473 9.609 40.427 11.831 57.907 11.831 17.485 0 38.434-2.223 57.907-11.831 21.888-10.799 39.471-29.905 46.874-56.461zM459.635 460.8c0-28.275 23.445-51.2 52.365-51.2s52.365 22.925 52.365 51.2c0 28.275-23.445 51.2-52.365 51.2s-52.365-22.925-52.365-51.2zM512 341.333c-67.477 0-122.182 53.487-122.182 119.467s54.704 119.467 122.182 119.467c67.477 0 122.18-53.487 122.18-119.467s-54.703-119.467-122.18-119.467zM677.803 537.254c-6.665 13.79-3.883 31.108 6.276 42.573 14.084 15.893 39.851 17.937 50.206-0.606 19.639-35.17 30.805-75.52 30.805-118.421 0-136.672-113.314-247.467-253.090-247.467-139.779 0-253.092 110.795-253.092 247.467 0 42.901 11.164 83.251 30.806 118.421 10.355 18.543 36.119 16.499 50.205 0.606 10.16-11.465 12.939-28.783 6.275-42.573-11.203-23.189-17.469-49.105-17.469-76.454 0-98.97 82.054-179.2 183.274-179.2 101.218 0 183.27 80.23 183.27 179.2 0 27.349-6.263 53.265-17.468 76.454zM730.159 699.793c-0.303-10.658 3.546-21.069 10.931-28.762 52.77-54.955 85.090-128.9 85.090-210.231 0-169.662-140.663-307.2-314.18-307.2s-314.182 137.538-314.182 307.2c0 81.331 32.323 155.277 85.094 210.231 7.386 7.693 11.234 18.103 10.928 28.762-0.832 29.018-31.273 47.915-52.121 27.716-70.223-68.041-113.718-162.406-113.718-266.709 0-207.365 171.923-375.467 384-375.467 212.079 0 384 168.102 384 375.467 0 104.303-43.494 198.673-113.719 266.709-20.851 20.203-51.29 1.306-52.122-27.716z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["live-streaming"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":462,"id":81,"name":"live-streaming","prevSize":32,"code":59749},"setIdx":0,"setId":3,"iconIdx":91},{"icon":{"paths":["M680.55 256c0-17.673-14.327-32-32-32s-32 14.327-32 32v56.876l-80.346 13.999c-17.412 3.034-29.069 19.607-26.035 37.018s19.61 29.066 37.022 26.032l69.359-12.085v69.371c-30.383 6.852-60.459 20.075-84.151 43.14-27.925 27.183-44.075 65.242-44.075 113.809 0 25.741 6.263 48.26 18.453 66.62 12.186 18.351 29.065 30.682 47.253 37.999 35.354 14.225 76.719 10.176 108.126-4.578l1.207-0.567c31.125-14.618 62.494-29.35 90.722-57.818 21.325-21.504 39.71-49.536 56.849-88.674 5.653 9.498 9.591 20.966 10.287 34.338 1.63 31.526-14.281 82.812-87.957 153.417-12.762 12.228-13.193 32.486-0.964 45.244 12.228 12.762 32.486 13.193 45.244 0.964 80.196-76.851 110.588-145.033 107.593-202.935-2.987-57.655-38.588-96.021-70.677-113.954-20.774-13.013-50.214-22.827-81.216-28.288-16.623-2.931-34.47-4.749-52.693-4.996v-74.242l101.717-17.723c17.412-3.034 29.069-19.607 26.035-37.018s-19.61-29.066-37.018-26.032l-90.735 15.809v-45.724zM577.041 536.209c10.163-9.894 23.565-17.476 39.509-22.703v138.65c-13.444 2.547-27.486 1.732-38.635-2.752-7.71-3.102-13.658-7.757-17.822-14.029-4.156-6.259-7.77-15.996-7.77-31.215 0-33.348 10.564-54.174 24.717-67.951zM708.642 600.751c-8.683 8.755-17.783 15.706-28.092 22.076v-117.888c14.127 0.239 28.224 1.66 41.587 4.015 13.589 2.394 25.681 5.623 35.763 9.165-16.879 42.039-33.067 66.304-49.259 82.633zM246.351 565.333h98.385l-49.193-184.882-49.193 184.882zM389.497 733.559l-27.732-104.226h-132.443l-27.732 104.226c-4.544 17.079-22.073 27.243-39.152 22.699s-27.241-22.076-22.696-39.151l106.323-399.601c13.494-50.714 85.464-50.713 98.957 0l106.323 399.601c4.544 17.075-5.615 34.607-22.694 39.151s-34.609-5.619-39.153-22.699z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["language"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":463,"id":80,"name":"language","prevSize":32,"code":59750},"setIdx":0,"setId":3,"iconIdx":92},{"icon":{"paths":["M224 224h320v576h-96v-112c0-8.836-7.164-16-16-16h-96c-8.837 0-16 7.164-16 16v112h-96v-576zM608 448h192v352h-192v-352zM832 384h-224v-192c0-17.673-14.327-32-32-32h-384c-17.673 0-32 14.327-32 32v640c0 17.673 14.327 32 32 32h640c17.673 0 32-14.327 32-32v-416c0-17.673-14.327-32-32-32zM304 288c-8.837 0-16 7.163-16 16v32c0 8.837 7.163 16 16 16h32c8.837 0 16-7.163 16-16v-32c0-8.837-7.163-16-16-16h-32zM288 432c0-8.837 7.163-16 16-16h32c8.837 0 16 7.163 16 16v32c0 8.836-7.163 16-16 16h-32c-8.837 0-16-7.164-16-16v-32zM304 544c-8.837 0-16 7.164-16 16v32c0 8.836 7.163 16 16 16h32c8.837 0 16-7.164 16-16v-32c0-8.836-7.163-16-16-16h-32zM416 304c0-8.837 7.163-16 16-16h32c8.836 0 16 7.163 16 16v32c0 8.837-7.164 16-16 16h-32c-8.837 0-16-7.163-16-16v-32zM432 416c-8.837 0-16 7.163-16 16v32c0 8.836 7.163 16 16 16h32c8.836 0 16-7.164 16-16v-32c0-8.837-7.164-16-16-16h-32zM416 560c0-8.836 7.163-16 16-16h32c8.836 0 16 7.164 16 16v32c0 8.836-7.164 16-16 16h-32c-8.837 0-16-7.164-16-16v-32zM688 512c-8.836 0-16 7.164-16 16v32c0 8.836 7.164 16 16 16h32c8.836 0 16-7.164 16-16v-32c0-8.836-7.164-16-16-16h-32zM672 656c0-8.836 7.164-16 16-16h32c8.836 0 16 7.164 16 16v32c0 8.836-7.164 16-16 16h-32c-8.836 0-16-7.164-16-16v-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["business"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":464,"id":79,"name":"business","prevSize":32,"code":59751},"setIdx":0,"setId":3,"iconIdx":93},{"icon":{"paths":["M714.667 298.663c0-17.673-14.327-32-32-32s-32 14.327-32 32v426.666c0 17.673 14.327 32 32 32s32-14.327 32-32v-426.666z","M512 394.671c17.673 0 32 14.327 32 32v298.667c0 17.673-14.327 32-32 32s-32-14.327-32-32v-298.667c0-17.673 14.327-32 32-32z","M373.333 554.671c0-17.673-14.327-32-32-32s-32 14.327-32 32v170.667c0 17.677 14.327 32 32 32s32-14.323 32-32v-170.667z","M128 199.555v624.888c0 39.518 32.037 71.556 71.555 71.556h624.888c39.518 0 71.556-32.038 71.556-71.556v-624.888c0-39.519-32.038-71.555-71.556-71.555h-624.888c-39.519 0-71.555 32.037-71.555 71.555zM199.555 192h624.888c4.173 0 7.556 3.383 7.556 7.555v624.888c0 4.173-3.383 7.556-7.556 7.556h-624.888c-4.173 0-7.555-3.383-7.555-7.556v-624.888c0-4.173 3.383-7.555 7.555-7.555z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["dashboard"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":465,"id":78,"name":"dashboard","prevSize":32,"code":59752},"setIdx":0,"setId":3,"iconIdx":94},{"icon":{"paths":["M160 256c0-17.673 14.327-32 32-32h640c17.673 0 32 14.327 32 32s-14.327 32-32 32h-640c-17.673 0-32-14.327-32-32zM160 421.161c0-17.673 14.327-32 32-32h640c17.673 0 32 14.327 32 32s-14.327 32.001-32 32.001h-640c-17.673 0-32-14.327-32-32.001zM160 602.837c0-17.673 14.327-32 32-32h640c17.673 0 32 14.327 32 32s-14.327 32-32 32h-640c-17.673 0-32-14.327-32-32zM160 768c0-17.673 14.327-32 32-32h344.614c17.673 0 32 14.327 32 32s-14.327 32-32 32h-344.614c-17.673 0-32-14.327-32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["document"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":466,"id":77,"name":"document","prevSize":32,"code":59753},"setIdx":0,"setId":3,"iconIdx":95},{"icon":{"paths":["M421.334 256c0-44.183-35.817-80-80-80s-80 35.817-80 80c0 44.183 35.817 80 80 80s80-35.817 80-80zM465.301 288c-14.208 55.207-64.324 96-123.967 96s-109.758-40.793-123.968-96h-89.367c-17.673 0-32-14.327-32-32s14.327-32 32-32h89.367c14.209-55.207 64.325-96 123.968-96s109.759 40.793 123.967 96h430.699c17.673 0 32 14.327 32 32s-14.327 32-32 32h-430.699zM96 768c0-17.673 14.327-32 32-32h89.367c14.209-55.206 64.325-96 123.968-96 60.782 0 111.671 42.368 124.744 99.179 4.207-2.035 8.93-3.179 13.922-3.179h416c17.673 0 32 14.327 32 32s-14.327 32-32 32h-416c-4.992 0-9.715-1.143-13.922-3.179-13.073 56.811-63.962 99.179-124.744 99.179-59.643 0-109.758-40.794-123.968-96h-89.367c-17.673 0-32-14.327-32-32zM341.334 848c44.183 0 80-35.819 80-80s-35.817-80-80-80c-44.183 0-80 35.819-80 80s35.817 80 80 80zM796.032 543.757c-14.127 55.33-64.303 96.243-124.032 96.243s-109.905-40.913-124.028-96.243c-1.301 0.162-2.628 0.243-3.972 0.243h-416c-17.673 0-32-14.327-32-32s14.327-32 32-32h416c1.344 0 2.671 0.081 3.972 0.243 14.123-55.331 64.299-96.243 124.028-96.243s109.905 40.913 124.032 96.243c1.297-0.162 2.624-0.243 3.968-0.243h96c17.673 0 32 14.327 32 32s-14.327 32-32 32h-96c-1.344 0-2.671-0.081-3.968-0.243zM752 512c0-44.181-35.819-80-80-80s-80 35.819-80 80c0 44.181 35.819 80 80 80s80-35.819 80-80z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["settings"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":467,"id":76,"name":"settings","prevSize":32,"code":59754},"setIdx":0,"setId":3,"iconIdx":96},{"icon":{"paths":["M464 272c-35.345 0-64 28.654-64 64v480c0 35.345 28.655 64 64 64h352c35.345 0 64-28.655 64-64v-304c0-6.511-1.984-12.864-5.692-18.214l-134.455-194.215c-11.955-17.267-31.616-27.57-52.621-27.57h-223.232zM464 336h144v144c0 35.345 28.655 64 64 64h144v272h-352v-480zM672 480v-144h15.232l99.695 144h-114.927zM144 208c0-35.346 28.654-64 64-64h241.843c18.031 0 35.226 7.607 47.356 20.949l39.138 43.051h-328.337v480h128v64h-128c-35.346 0-64-28.655-64-64v-480z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["copy"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":468,"id":75,"name":"copy","prevSize":32,"code":59755},"setIdx":0,"setId":3,"iconIdx":97},{"icon":{"paths":["M825.135 560.657l-84.617-11.038c1.237-9.481 1.882-19.187 1.882-29.086s-0.644-19.605-1.882-29.086l84.617-11.038c1.715 13.133 2.598 26.526 2.598 40.124s-0.883 26.991-2.598 40.124zM804.425 402.941l-78.827 32.686c-7.458-17.989-17.242-34.822-28.996-50.116l67.665-51.996c16.243 21.139 29.798 44.451 40.158 69.426zM707.55 276.801l-51.994 67.663c-15.296-11.753-32.128-21.534-50.116-28.995l32.687-78.825c24.973 10.356 48.286 23.913 69.423 40.157zM560.657 215.93l-11.038 84.617c-9.481-1.237-19.187-1.88-29.086-1.88s-19.605 0.643-29.086 1.88l-11.038-84.617c13.133-1.713 26.526-2.597 40.124-2.597s26.991 0.884 40.124 2.597zM402.941 236.644l32.686 78.825c-17.989 7.461-34.822 17.242-50.116 28.995l-51.996-67.663c21.139-16.244 44.451-29.801 69.426-40.157zM276.801 333.515l67.663 51.996c-11.753 15.294-21.534 32.126-28.995 50.116l-78.825-32.686c10.356-24.975 23.913-48.287 40.157-69.426zM215.93 480.41c-1.713 13.133-2.597 26.526-2.597 40.124s0.884 26.991 2.597 40.124l84.617-11.038c-1.237-9.481-1.88-19.187-1.88-29.086s0.643-19.605 1.88-29.086l-84.617-11.038zM236.644 638.127l78.825-32.687c7.461 17.988 17.242 34.82 28.995 50.116l-67.663 51.994c-16.244-21.137-29.801-44.45-40.157-69.423zM333.515 764.267l51.996-67.665c15.294 11.755 32.126 21.538 50.116 28.996l-32.686 78.827c-24.975-10.359-48.287-23.915-69.426-40.158zM480.41 825.135l11.038-84.617c9.481 1.237 19.187 1.882 29.086 1.882s19.605-0.644 29.086-1.882l11.038 84.617c-13.133 1.715-26.526 2.598-40.124 2.598s-26.991-0.883-40.124-2.598zM638.127 804.425l-32.687-78.827c17.988-7.458 34.82-17.242 50.116-28.996l51.994 67.665c-21.137 16.243-44.45 29.798-69.423 40.158zM764.267 707.55l-67.665-51.994c11.755-15.296 21.538-32.128 28.996-50.116l78.827 32.687c-10.359 24.973-23.915 48.286-40.158 69.423z"],"attrs":[{"fill":"rgb(158, 162, 168)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["status-loading"]},"attrs":[{"fill":"rgb(158, 162, 168)"}],"properties":{"order":469,"id":74,"name":"status-loading","prevSize":32,"code":59756},"setIdx":0,"setId":3,"iconIdx":98},{"icon":{"paths":["M520.533 742.4c-122.534 0-221.867-99.332-221.867-221.867s99.333-221.867 221.867-221.867c122.534 0 221.867 99.333 221.867 221.867s-99.332 221.867-221.867 221.867zM520.533 827.733c169.66 0 307.2-137.54 307.2-307.2 0-169.662-137.54-307.2-307.2-307.2-169.662 0-307.2 137.538-307.2 307.2 0 169.66 137.538 307.2 307.2 307.2z"],"attrs":[{"fill":"rgb(158, 162, 168)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["status-invisible"]},"attrs":[{"fill":"rgb(158, 162, 168)"}],"properties":{"order":470,"id":73,"name":"status-invisible","prevSize":32,"code":59757},"setIdx":0,"setId":3,"iconIdx":99},{"icon":{"paths":["M520.533 827.733c-169.662 0-307.2-137.54-307.2-307.2 0-169.662 137.538-307.2 307.2-307.2 169.66 0 307.2 137.538 307.2 307.2 0 169.66-137.54 307.2-307.2 307.2zM563.2 341.333c0-23.564-19.102-42.667-42.667-42.667s-42.667 19.103-42.667 42.667v199.706l144.013 115.213c18.402 14.72 45.252 11.738 59.972-6.665s11.738-45.252-6.665-59.972l-111.987-89.587v-158.694z"],"attrs":[{"fill":"rgb(243, 190, 8)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["status-away"]},"attrs":[{"fill":"rgb(243, 190, 8)"}],"properties":{"order":471,"id":72,"name":"status-away","prevSize":32,"code":59758},"setIdx":0,"setId":3,"iconIdx":100},{"icon":{"paths":["M520.533 827.733c169.66 0 307.2-137.54 307.2-307.2 0-169.662-137.54-307.2-307.2-307.2-169.662 0-307.2 137.538-307.2 307.2 0 169.66 137.538 307.2 307.2 307.2zM418.133 477.867c-23.564 0-42.667 19.102-42.667 42.667 0 23.561 19.103 42.667 42.667 42.667h204.8c23.565 0 42.667-19.106 42.667-42.667 0-23.565-19.102-42.667-42.667-42.667h-204.8z"],"attrs":[{"fill":"rgb(245, 69, 92)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["status-busy"]},"attrs":[{"fill":"rgb(245, 69, 92)"}],"properties":{"order":472,"id":71,"name":"status-busy","prevSize":32,"code":59759},"setIdx":0,"setId":3,"iconIdx":101},{"icon":{"paths":["M819.2 512c0 169.662-137.538 307.2-307.2 307.2s-307.2-137.538-307.2-307.2c0-169.662 137.538-307.2 307.2-307.2s307.2 137.538 307.2 307.2z"],"attrs":[{"fill":"rgb(45, 224, 165)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["status-online"]},"attrs":[{"fill":"rgb(45, 224, 165)"}],"properties":{"order":473,"id":70,"name":"status-online","prevSize":32,"code":59760},"setIdx":0,"setId":3,"iconIdx":102},{"icon":{"paths":["M430.844 103.994c80.695-16.052 164.339-7.814 240.354 23.673 76.011 31.486 140.983 84.806 186.692 153.216 45.713 68.411 70.11 148.839 70.11 231.117h-64c0-69.619-20.642-137.674-59.324-195.561-38.677-57.886-93.653-103.003-157.973-129.645-64.316-26.642-135.091-33.613-203.375-20.031-68.281 13.582-131.001 47.107-180.23 96.335s-82.753 111.949-96.335 180.23c-13.582 68.284-6.611 139.059 20.031 203.375 26.642 64.32 71.759 119.296 129.645 157.973 57.886 38.682 125.941 59.324 195.561 59.324v64c-82.278 0-162.706-24.397-231.117-70.11-68.41-45.709-121.731-110.682-153.216-186.692v0c-31.486-76.015-39.724-159.659-23.673-240.354 16.051-80.697 55.671-154.821 113.85-213s132.303-97.799 213-113.85z","M593.156 920.009c-80.695 16.051-164.339 7.812-240.353-23.676-76.014-31.484-140.984-84.804-186.695-153.216s-70.109-148.838-70.109-231.117h64c0 69.619 20.644 137.673 59.322 195.558 38.678 57.89 93.653 103.006 157.973 129.647 64.317 26.641 135.093 33.613 203.377 20.032 68.279-13.585 130.999-47.108 180.228-96.337s82.752-111.949 96.337-180.228c13.581-68.284 6.609-139.059-20.032-203.377-26.641-64.32-71.757-119.295-129.643-157.973-57.89-38.678-125.943-59.322-195.563-59.322v-64c82.278 0 162.705 24.398 231.117 70.109s121.732 110.681 153.216 186.695v0c31.488 76.014 39.727 159.657 23.676 240.353-16.055 80.695-55.676 154.82-113.852 213.001-58.18 58.176-132.305 97.796-213.001 113.852z"],"attrs":[{"fill":"rgb(228, 231, 234)"},{"fill":"rgb(9, 90, 210)"}],"isMulticolor":true,"isMulticolor2":false,"grid":0,"tags":["loading"]},"attrs":[{"fill":"rgb(228, 231, 234)"},{"fill":"rgb(9, 90, 210)"}],"properties":{"order":474,"id":69,"name":"loading","prevSize":32,"code":59761,"codes":[59761,59762]},"setIdx":0,"setId":3,"iconIdx":103},{"icon":{"paths":["M305.297 498.091c-12.356-12.634-12.129-32.896 0.507-45.252l191.971-187.717c12.437-12.161 32.307-12.161 44.745 0l191.97 187.717c12.638 12.356 12.864 32.619 0.508 45.252-12.356 12.638-32.619 12.864-45.252 0.508l-137.6-134.55v372.11c0 17.673-14.323 32-32 32-17.673 0-32-14.327-32-32v-372.11l-137.595 134.55c-12.636 12.356-32.896 12.13-45.252-0.508z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-up"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":475,"id":68,"name":"arrow-up","prevSize":32,"code":59763},"setIdx":0,"setId":3,"iconIdx":104},{"icon":{"paths":["M734.997 526.067c12.356 12.634 12.13 32.896-0.508 45.248l-191.97 187.721c-12.437 12.16-32.307 12.16-44.745 0l-191.97-187.721c-12.636-12.352-12.863-32.614-0.507-45.248 12.356-12.638 32.616-12.864 45.252-0.508l137.595 134.549v-372.109c0-17.673 14.327-32 32-32 17.677 0 32 14.327 32 32v372.109l137.6-134.549c12.634-12.356 32.896-12.13 45.252 0.508z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-down"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":476,"id":67,"name":"arrow-down","prevSize":32,"code":59764},"setIdx":0,"setId":3,"iconIdx":105},{"icon":{"paths":["M832.678 512c0-176.731-143.27-320-320-320-176.733 0-320.001 143.269-320.001 320 0 176.73 143.269 320 320.001 320 176.73 0 320-143.27 320-320zM896.678 512c0 212.079-171.925 384-384 384-212.079 0-384.001-171.921-384.001-384 0-212.077 171.923-384 384.001-384 212.075 0 384 171.923 384 384zM512.678 704c-106.040 0-192.001-85.961-192.001-192s85.961-192 192.001-192c106.039 0 192 85.961 192 192s-85.961 192-192 192z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["record"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":477,"id":66,"name":"record","prevSize":32,"code":59765},"setIdx":0,"setId":3,"iconIdx":106},{"icon":{"paths":["M132.506 272c0-17.673 14.327-32 32-32h703.999c17.673 0 32 14.327 32 32s-14.327 32-32 32h-703.999c-17.673 0-32-14.327-32-32zM292.506 432c0 17.673-14.327 32-32 32s-32-14.327-32-32c0-17.673 14.327-32 32-32s32 14.327 32 32zM292.506 752c0 17.673-14.327 32-32 32s-32-14.327-32-32c0-17.673 14.327-32 32-32s32 14.327 32 32zM452.506 624c17.673 0 32-14.327 32-32s-14.327-32-32-32c-17.673 0-31.999 14.327-31.999 32s14.327 32 31.999 32zM388.506 400c-17.673 0-32 14.327-32 32s14.327 32 32 32h479.999c17.673 0 32-14.327 32-32s-14.327-32-32-32h-479.999zM356.506 752c0-17.673 14.327-32 32-32h479.999c17.673 0 32 14.327 32 32s-14.327 32-32 32h-479.999c-17.673 0-32-14.327-32-32zM580.506 560c-17.673 0-32 14.327-32 32s14.327 32 32 32h288c17.673 0 32-14.327 32-32s-14.327-32-32-32h-288z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["group-by-type"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":478,"id":65,"name":"group-by-type","prevSize":32,"code":59766},"setIdx":0,"setId":3,"iconIdx":107},{"icon":{"paths":["M825.374 153.373c12.497-12.497 32.755-12.497 45.252 0s12.497 32.758 0 45.255l-671.999 671.999c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l672.001-672.001zM575.612 569.067l-44.706 44.71c7.846 5.905 15.846 11.452 23.535 16.013 9.199 5.461 22.835 12.578 36.971 13.222 16.226 0.738 31.445-5.299 42.47-10.974 11.742-6.042 22.793-13.824 31.744-20.945 1.054-0.836 2.133-1.229 2.884-1.34 0.401-0.060 0.61-0.030 0.687-0.013l121.097 59.076c-5.581 29.329-20.382 66.769-42.394 92.621-11.23 13.184-23.198 22.037-35.388 26.317-11.597 4.075-25.404 4.766-42.65-1.673-48.427-18.074-103.407-53.154-151.693-89.263-14.029-10.492-27.298-20.919-39.467-30.844l-44.39 44.39c14.187 11.686 29.841 24.064 46.447 36.48 49.805 37.248 110.447 76.561 167.258 97.762 30.276 11.298 59.149 11.238 85.197 2.086 25.455-8.939 46.093-25.783 62.246-44.757 31.868-37.423 50.637-88.141 57.062-126.246 4.719-27.985-11.776-51.767-33.139-62.191l-122.807-59.908c-24.41-11.908-51.46-6.003-69.837 8.61-7.006 5.572-14.541 10.739-21.44 14.289-5.577 2.867-8.93 3.742-10.313 4.006l-0.094-0.038c-0.99-0.401-3.729-1.515-8.567-4.386-3.277-1.946-6.874-4.301-10.714-7.006zM313.636 589.683l44.39-44.39c-9.92-12.164-20.35-25.438-30.839-39.462-36.108-48.286-71.191-103.267-89.262-151.691-6.437-17.249-5.748-31.055-1.675-42.651 4.282-12.192 13.134-24.16 26.319-35.388 25.85-22.012 63.29-36.814 92.623-42.392l59.075 121.096c0.018 0.076 0.047 0.285-0.012 0.687-0.111 0.75-0.504 1.83-1.343 2.884-7.118 8.951-14.9 20.001-20.943 31.741-5.673 11.025-11.714 26.246-10.976 42.472 0.643 14.135 7.761 27.772 13.222 36.971 4.562 7.689 10.109 15.684 16.014 23.535l44.705-44.71c-2.701-3.836-5.056-7.433-7.002-10.709-2.867-4.838-3.981-7.578-4.386-8.567l-0.038-0.094c0.265-1.382 1.139-4.738 4.006-10.312 3.55-6.9 8.717-14.437 14.289-21.443 14.613-18.374 20.523-45.425 8.614-69.835l-59.913-122.809c-10.421-21.361-34.203-37.856-62.191-33.137-38.103 6.425-88.824 25.194-126.246 57.060-18.972 16.155-35.817 36.795-44.758 62.246-9.15 26.048-9.211 54.92 2.088 85.196 21.201 56.813 60.513 117.455 97.761 167.26 12.417 16.606 24.795 32.256 36.478 46.443z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["phone-disabled"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":479,"id":64,"name":"phone-disabled","prevSize":32,"code":59767},"setIdx":0,"setId":3,"iconIdx":108},{"icon":{"paths":["M801.122 657.591c22.477 7.735 50.957 2.581 67.409-20.544 22.4-31.488 44.992-80.623 48.922-129.617 1.993-24.841-0.691-51.345-12.365-75.665-11.951-24.887-32.324-45.347-61.722-58.766-55.164-25.181-125.841-40.262-187.396-49.144-61.948-8.937-117.495-11.981-143.966-11.981v62.47c23.198 0 75.755 2.787 135.044 11.341 59.674 8.61 123.358 22.681 170.377 44.143 16.751 7.646 26.027 17.894 31.347 28.975 5.589 11.648 7.795 26.372 6.409 43.635-2.714 33.839-18.718 70.784-35.516 95.467l-127.398-43.853c-0.068-0.043-0.239-0.171-0.478-0.495-0.452-0.61-0.939-1.651-1.092-2.991-1.297-11.362-3.605-24.678-7.633-37.252-3.785-11.806-10.278-26.842-22.272-37.794-10.449-9.54-25.126-14.148-35.494-16.794-11.917-3.038-25.566-5.18-38.946-6.716-26.859-3.085-55.77-4.092-74.351-4.092v62.468c16.9 0 43.341 0.939 67.217 3.686 11.994 1.374 22.554 3.123 30.643 5.184 5.449 1.391 8.175 2.543 9.161 2.957l0.094 0.043c0.789 1.161 2.543 4.151 4.459 10.121 2.368 7.39 4.041 16.375 5.056 25.267 2.662 23.326 17.613 46.63 43.294 55.471l129.199 44.476zM222.876 657.587c-22.474 7.735-50.954 2.581-67.407-20.544-22.4-31.488-44.993-80.623-48.922-129.617-1.992-24.841 0.691-51.345 12.367-75.665 11.948-24.887 32.321-45.347 61.719-58.765 55.165-25.181 125.841-40.263 187.399-49.144 61.946-8.937 117.494-11.981 143.964-11.981v62.47c-23.198 0-75.755 2.787-135.043 11.341-59.675 8.61-123.36 22.681-170.38 44.143-16.748 7.646-26.025 17.894-31.343 28.975-5.593 11.648-7.797 26.372-6.412 43.635 2.714 33.843 18.721 70.784 35.518 95.467l127.4-43.853c0.067-0.043 0.235-0.171 0.478-0.495 0.452-0.61 0.937-1.651 1.090-2.991 1.296-11.362 3.606-24.678 7.636-37.252 3.784-11.806 10.276-26.842 22.27-37.794 10.45-9.54 25.127-14.148 35.493-16.794 11.916-3.038 25.568-5.18 38.947-6.716 26.859-3.085 55.77-4.092 74.351-4.092v62.468c-16.9 0-43.341 0.939-67.221 3.686-11.989 1.378-22.551 3.123-30.638 5.184-5.452 1.391-8.175 2.543-9.162 2.957l-0.092 0.043c-0.791 1.161-2.546 4.151-4.459 10.121-2.368 7.39-4.044 16.375-5.058 25.267-2.66 23.326-17.611 46.63-43.292 55.471l-129.202 44.476z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["phone-end"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":480,"id":63,"name":"phone-end","prevSize":32,"code":59768},"setIdx":0,"setId":3,"iconIdx":109},{"icon":{"paths":["M410.504 204.615c-10.421-21.361-34.203-37.856-62.191-33.137-38.103 6.425-88.824 25.194-126.246 57.060-18.972 16.155-35.817 36.795-44.758 62.246-9.15 26.048-9.211 54.92 2.088 85.196 21.201 56.813 60.513 117.455 97.761 167.26 37.482 50.125 74.609 91.554 93.327 110.272l44.173-44.173c-16.405-16.405-51.598-55.539-87.472-103.509-36.108-48.286-71.191-103.267-89.262-151.691-6.437-17.249-5.748-31.055-1.675-42.651 4.282-12.192 13.134-24.16 26.319-35.388 25.85-22.012 63.29-36.814 92.623-42.392l59.075 121.096c0.018 0.075 0.047 0.285-0.012 0.687-0.111 0.75-0.504 1.83-1.343 2.884-7.118 8.951-14.9 20.001-20.943 31.741-5.673 11.025-11.714 26.246-10.976 42.472 0.643 14.135 7.761 27.772 13.222 36.971 6.277 10.577 14.417 21.743 22.79 32.29 16.809 21.175 36.542 42.33 49.679 55.467l44.173-44.173c-11.951-11.951-29.978-31.309-44.924-50.133-7.505-9.455-13.739-18.159-18.001-25.335-2.867-4.838-3.981-7.578-4.386-8.567l-0.038-0.094c0.265-1.382 1.139-4.738 4.006-10.312 3.55-6.9 8.717-14.437 14.289-21.443 14.613-18.374 20.523-45.425 8.614-69.835l-59.913-122.809zM819.383 613.5c21.363 10.423 37.858 34.206 33.139 62.191-6.426 38.106-25.195 88.823-57.062 126.246-16.154 18.974-36.791 35.819-62.246 44.757-26.048 9.152-54.921 9.212-85.197-2.086-56.811-21.201-117.453-60.514-167.258-97.762-50.125-37.483-91.555-74.607-110.273-93.325l44.173-44.173c16.407 16.405 55.54 51.597 103.511 87.471 48.286 36.109 103.266 71.189 151.693 89.263 17.246 6.434 31.053 5.747 42.65 1.673 12.19-4.279 24.158-13.133 35.388-26.317 22.012-25.852 36.813-63.292 42.394-92.621l-121.097-59.076c-0.077-0.017-0.286-0.047-0.687 0.013-0.751 0.111-1.83 0.503-2.884 1.34-8.951 7.121-20.002 14.903-31.744 20.945-11.025 5.675-26.244 11.712-42.47 10.974-14.135-0.644-27.772-7.761-36.971-13.222-10.577-6.276-21.743-14.417-32.29-22.788-21.175-16.811-42.33-36.544-55.467-49.681l44.173-44.173c11.951 11.951 31.309 29.982 50.133 44.928 9.455 7.501 18.159 13.734 25.335 17.997 4.838 2.871 7.578 3.985 8.567 4.386l0.094 0.038c1.382-0.265 4.736-1.139 10.313-4.006 6.899-3.55 14.434-8.717 21.44-14.289 18.377-14.613 45.427-20.518 69.837-8.61l122.807 59.908z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["phone"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":481,"id":62,"name":"phone","prevSize":32,"code":59769},"setIdx":0,"setId":3,"iconIdx":110},{"icon":{"paths":["M802.257 544c0 176.73-143.27 320-320 320-176.733 0-320.002-143.27-320.002-320 0-176.731 143.269-320 320.002-320v-64c-212.079 0-384.002 171.923-384.002 384 0 212.079 171.922 384 384.002 384 212.075 0 384-171.921 384-384 0-10.778-0.444-21.449-1.314-32h-64.269c1.045 10.526 1.583 21.201 1.583 32zM802.257 112c0-17.673-14.327-32-32-32-17.677 0-32 14.327-32 32v112h-112c-17.677 0-32 14.327-32 32s14.323 32 32 32h112v112c0 17.673 14.323 32 32 32 17.673 0 32-14.327 32-32v-112h112c17.673 0 32-14.327 32-32s-14.327-32-32-32h-112v-112zM386.255 512c35.346 0 64.002-28.655 64.002-64 0-35.346-28.656-64-64.002-64s-64 28.654-64 64c0 35.345 28.654 64 64 64zM642.257 448c0 35.345-28.655 64-64 64-35.349 0-64-28.655-64-64 0-35.346 28.651-64 64-64 35.345 0 64 28.654 64 64zM332.060 589.077c-10.451-14.251-30.477-17.335-44.729-6.882-14.252 10.449-17.332 30.477-6.881 44.727 37.658 51.354 77.753 84.625 119.178 102.665 41.737 18.18 82.796 19.989 120.364 11.652 73.468-16.307 132.211-70.874 164.070-114.317 10.449-14.251 7.369-34.278-6.882-44.727-14.251-10.453-34.278-7.369-44.727 6.882-26.812 36.557-73.668 77.99-126.332 89.681-25.502 5.662-52.642 4.476-80.938-7.846-28.608-12.459-60.38-37.188-93.122-81.835z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["reaction-add"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":482,"id":61,"name":"reaction-add","prevSize":32,"code":59770},"setIdx":0,"setId":3,"iconIdx":111},{"icon":{"paths":["M226.503 304.026c-49.642 68.947-66.502 152.644-66.502 207.97v1.451l-0.131 1.446c-9.702 106.718 28.59 181.931 90.135 234.005 62.938 53.257 152.152 83.733 244.195 93.961 91.968 10.219 193.271 1.446 273.31-15.479 40.017-8.465 73.613-18.735 97.438-29.077 9.246-4.015 16.439-7.787 21.739-11.127-2.466-1.566-5.449-3.302-9.003-5.197-9.225-4.911-19.78-9.579-30.733-14.366l-1.916-0.836c-9.664-4.224-20.471-8.943-28.655-13.521-14.835-8.294-29.389-17.732-40.004-27.772-5.227-4.941-11.166-11.571-15.147-19.827-4.211-8.742-7.223-21.794-1.306-35.601 31.979-74.62 47.177-115.49 54.537-142.481 6.874-25.199 6.874-37.888 6.874-58.061v-0.183c0-16.038-9.318-89.517-55.812-158.033-45.013-66.338-125.99-129.968-274.854-129.968-134.636 0-215.696 55.382-264.163 122.698zM174.565 266.63c60.333-83.796 160.607-149.302 316.102-149.302 171.136 0 271.497 75.037 327.812 158.032 54.839 80.818 66.854 167.337 66.854 193.969 0 22.383-0.021 41.694-9.126 75.085-8.128 29.807-23.484 70.929-51.942 137.924 5.261 4.169 13.069 9.306 23.356 15.061 5.316 2.974 13.487 6.554 24.964 11.571 10.654 4.655 23.437 10.266 35.174 16.512 11.26 5.995 24.418 14.033 34.202 24.542 10.231 10.991 20.975 29.845 13.299 52.864-5.056 15.164-16.794 25.937-26.577 33.092-10.628 7.774-23.817 14.763-38.251 21.030-29.009 12.587-67.029 23.962-109.683 32.981-85.312 18.039-193.583 27.588-293.615 16.474-99.956-11.106-202.741-44.629-278.47-108.71-76.833-65.011-123.811-159.996-112.66-287.223 0.286-65.549 19.841-162.346 78.561-243.902zM496 320c17.673 0 32 14.327 32 32v224c0 17.673-14.327 32-32 32s-32-14.327-32-32v-224c0-17.673 14.327-32 32-32zM528 672c0-17.673-14.327-32-32-32s-32 14.327-32 32c0 17.673 14.327 32 32 32s32-14.327 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["canned-response"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":483,"id":60,"name":"canned-response","prevSize":32,"code":59771},"setIdx":0,"setId":3,"iconIdx":112},{"icon":{"paths":["M332.328 644.885c-21.571-19.618-6.007-52.885 23.151-52.885 8.965 0 17.527 3.529 24.272 9.438 21.605 18.918 42.641 31.957 62.702 40.508 36.565 15.59 71.808 17.109 104.794 9.941 37.632-8.179 72.657-27.81 102.11-51.345 6.724-5.376 14.997-8.542 23.607-8.542 30.217 0 45.615 34.257 22.396 53.594-36.911 30.741-82.79 57.591-134.519 68.834-44.8 9.732-93.67 7.629-143.486-13.606-28.791-12.275-57.234-30.656-85.026-55.936z","M402.423 480c35.345 0 64-28.655 64-64 0-35.346-28.655-64-64-64s-64 28.654-64 64c0 35.345 28.654 64 64 64z","M626.423 480c35.345 0 64-28.655 64-64 0-35.346-28.655-64-64-64s-64 28.654-64 64c0 35.345 28.655 64 64 64z","M930.257 512c0 229.751-186.253 416-416 416-229.752 0-416.002-186.249-416.002-416s186.249-416 416.002-416c229.747 0 416 186.249 416 416zM866.257 512c0-194.404-157.598-352-352-352-194.406 0-352.002 157.596-352.002 352 0 194.402 157.596 352 352.002 352 194.402 0 352-157.598 352-352z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["emoji"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":484,"id":59,"name":"emoji","prevSize":32,"code":59772},"setIdx":0,"setId":3,"iconIdx":113},{"icon":{"paths":["M480.094 128c104.26 0 181.252 29.018 237.495 70.652l-44.318 44.317c-45.521-31.22-107.746-53.057-193.178-53.057-129.725 0-207.828 53.576-254.528 118.696-47.832 66.699-64.077 147.668-64.077 201.185v1.404l-0.127 1.399c-7.328 80.926 13.761 143.13 51.784 190.498l-43.879 43.883c-50.179-59.904-78.131-139.046-69.44-238.596 0.276-63.411 19.117-157.053 75.696-235.949 58.132-81.062 154.749-144.433 304.572-144.433zM825.105 332.498l-47.010 47.009c16.503 42.634 20.608 78.524 20.608 89.011v0.179c0 19.516 0 31.791-6.622 56.171-7.091 26.108-21.739 65.647-52.553 137.835-5.7 13.355-2.795 25.98 1.263 34.436 3.831 7.987 9.557 14.4 14.592 19.183 10.227 9.711 24.252 18.837 38.545 26.867 7.889 4.429 18.3 8.994 27.614 13.077l1.843 0.806c10.556 4.634 20.727 9.148 29.611 13.897 3.426 1.835 6.302 3.516 8.674 5.030-5.103 3.23-12.036 6.882-20.941 10.765-22.959 10.005-55.33 19.938-93.888 28.126-77.12 16.375-174.729 24.862-263.339 14.976-43.746-4.881-86.83-14.528-126.537-29.231l-47.543 47.543c52.771 23.019 110.493 36.89 167.266 43.221 96.388 10.752 200.708 1.515 282.91-15.936 41.097-8.725 77.734-19.729 105.681-31.906 13.909-6.063 26.615-12.821 36.855-20.343 9.425-6.925 20.74-17.344 25.609-32.017 7.394-22.268-2.953-40.503-12.813-51.136-9.429-10.167-22.106-17.941-32.956-23.74-11.311-6.046-23.625-11.469-33.89-15.979-11.059-4.851-18.931-8.316-24.051-11.191-9.916-5.568-17.442-10.534-22.507-14.571 27.422-64.806 42.214-104.589 50.048-133.423 8.772-32.303 8.794-50.982 8.794-72.64 0-20.105-7.053-75.5-35.264-136.020zM838.293 153.373c12.497-12.497 32.759-12.497 45.257 0s12.497 32.758 0 45.255l-682.667 682.665c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l682.665-682.668z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["message-disabled"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":485,"id":58,"name":"message-disabled","prevSize":32,"code":59773},"setIdx":0,"setId":3,"iconIdx":114},{"icon":{"paths":["M223.311 308.609c-47.831 66.699-64.077 147.668-64.077 201.185v1.404l-0.127 1.399c-9.348 103.236 27.547 175.996 86.848 226.377 60.643 51.516 146.604 80.998 235.291 90.893 88.61 9.886 186.223 1.399 263.339-14.976 38.562-8.188 70.929-18.121 93.888-28.126 8.909-3.883 15.838-7.535 20.945-10.765-2.377-1.515-5.248-3.196-8.678-5.030-8.883-4.749-19.055-9.263-29.611-13.897l-1.843-0.806c-9.314-4.083-19.725-8.649-27.61-13.077-14.293-8.030-28.318-17.156-38.545-26.867-5.035-4.783-10.761-11.196-14.596-19.183-4.058-8.457-6.959-21.082-1.259-34.436 30.814-72.188 45.457-111.727 52.553-137.835 6.622-24.38 6.622-36.655 6.618-56.171v-0.179c0-15.514-8.977-86.595-53.777-152.876-43.371-64.175-121.395-125.729-264.828-125.729-129.727 0-207.831 53.576-254.531 118.696zM173.267 272.433c58.132-81.062 154.749-144.433 304.574-144.433 164.894 0 261.594 72.589 315.857 152.878 52.838 78.182 64.414 161.879 64.414 187.641 0 21.658-0.017 40.337-8.794 72.64-7.834 28.834-22.626 68.617-50.048 133.423 5.069 4.036 12.591 9.003 22.507 14.571 5.12 2.876 12.992 6.34 24.055 11.191 10.261 4.51 22.579 9.933 33.89 15.979 10.846 5.798 23.526 13.572 32.951 23.74 9.86 10.633 20.211 28.868 12.817 51.136-4.873 14.673-16.183 25.092-25.609 32.017-10.24 7.522-22.946 14.281-36.86 20.343-27.947 12.177-64.58 23.181-105.681 31.906-82.197 17.451-186.522 26.688-282.906 15.936-96.31-10.743-195.347-43.174-268.314-105.165-74.031-62.891-119.295-154.778-108.551-277.854 0.276-63.411 19.118-157.053 75.696-235.949z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["message"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":486,"id":57,"name":"message","prevSize":32,"code":59774},"setIdx":0,"setId":3,"iconIdx":115},{"icon":{"paths":["M273.129 356.679c6.747-28.299 25.696-52.005 51.209-67.153 25.601-15.2 56.323-20.858 84.699-14.531 27.639 6.164 55.116 24.12 74.871 60.34l22.541 41.324 30.135-36.162c27.238-32.687 85.129-39.712 134.716-14.063 23.561 12.187 42.206 30.617 52.062 53.489 9.655 22.406 12.113 51.897-1.434 89.149l-15.616 42.935h45.687c53.606 0 82.419 15.881 97.643 33.749 15.65 18.377 21.897 44.651 18.556 74.718-3.345 30.084-16.055 60.514-33.455 82.889-17.941 23.066-36.651 32.644-50.743 32.644h-543.998c-18.791 0-37.067-10.359-52.194-31.578-15.217-21.342-24.977-51.051-25.818-81.31-0.84-30.229 7.238-57.916 23.734-77.491 15.795-18.748 42.268-33.621 86.278-33.621h59.792l-33.166-49.749c-27.882-41.825-32.118-77.815-25.498-105.58zM518.221 272.084c-26.342-32.073-59.669-51.619-95.255-59.554-45.624-10.173-92.902-0.833-131.301 21.965-38.487 22.85-69.538 60.142-80.791 107.342-8.278 34.72-5.369 72.759 10.731 111.77-35.67 8.465-64.099 26.185-84.825 50.782-29.004 34.423-39.927 78.737-38.767 120.508 1.159 41.741 14.399 84.032 37.682 116.689 23.373 32.785 59.097 58.423 104.305 58.423h543.999c41.907 0 77.201-26.419 101.261-57.353 24.597-31.629 41.886-73.195 46.545-115.115 4.659-41.933-3.098-87.659-33.446-123.285-24.102-28.297-59.503-46.771-105.613-53.453 5.833-35.195 1.685-67.675-10.607-96.206-16.644-38.627-46.997-67.197-81.438-85.009-54.899-28.397-128.734-32.652-182.481 2.495zM512 437.333c17.673 0 32 14.327 32 32v53.329h53.333c17.673 0 32 14.323 32 32 0 17.673-14.327 32-32 32h-53.333v53.338c0 17.673-14.327 32-32 32s-32-14.327-32-32v-53.338h-53.333c-17.672 0-31.999-14.327-31.999-32 0-17.677 14.327-32 31.999-32h53.333v-53.329c0-17.673 14.327-32 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["cloud-connectivity"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":487,"id":56,"name":"cloud-connectivity","prevSize":32,"code":59775},"setIdx":0,"setId":3,"iconIdx":116},{"icon":{"paths":["M515.558 142.7c12.915-3.408 26.505-3.288 39.36 0.345l245.197 69.318c29.163 8.245 51.255 33.818 53.504 65.14 24.503 341.143-184.397 520.424-272.614 580.213-33.050 22.404-75.277 22.473-108.416 0.26-88.759-59.503-300.099-238.588-276.509-579.794 2.205-31.89 24.96-57.772 54.753-65.632l264.726-69.849zM537.506 204.631c-1.835-0.519-3.776-0.536-5.623-0.049l-264.722 69.849c-4.4 1.161-6.999 4.776-7.233 8.165-21.305 308.167 168.215 468.534 248.301 522.217 11.507 7.714 25.434 7.68 36.873-0.073 79.377-53.803 266.833-214.289 244.681-522.653-0.239-3.358-2.786-6.925-7.078-8.139l-245.197-69.318z","M492.928 337.331c-19.759 4.672-47.249 12.307-81.151 24.553 20.812 108.773 53.221 187.015 81.151 238.829v-263.382zM495.125 271.311c33.766-6.897 61.803 19.742 61.803 51.124v360.966c0 17.024-10.334 31.748-25.643 37.521-15.671 5.909-33.779 1.327-44.86-12.676-32.657-41.267-106.324-152.951-141.192-354.565-3.241-18.744 7.065-37.694 25.329-44.725 56.185-21.63 99.095-32.442 124.562-37.644z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["shield"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":488,"id":55,"name":"shield","prevSize":32,"code":59776},"setIdx":0,"setId":3,"iconIdx":117},{"icon":{"paths":["M664.081 405.067c11.639-13.3 10.291-33.517-3.008-45.155s-33.519-10.29-45.154 3.011l-125.252 143.142-39.919-45.619c-11.635-13.299-31.852-14.647-45.153-3.008-13.3 11.635-14.648 31.851-3.011 45.154l64.001 73.143c6.076 6.942 14.852 10.927 24.081 10.927s18.005-3.985 24.081-10.927l149.333-170.669z","M541.99 143.045c-12.855-3.633-26.449-3.753-39.364-0.345l-264.722 69.849c-29.793 7.861-52.548 33.743-54.753 65.632-23.59 341.206 187.75 520.291 276.51 579.794 33.135 22.212 75.362 22.144 108.416-0.26 88.218-59.789 297.118-239.070 272.614-580.213-2.253-31.321-24.341-56.895-53.508-65.14l-245.193-69.318zM518.955 204.582c1.847-0.487 3.789-0.47 5.623 0.049l245.197 69.318c4.292 1.214 6.839 4.781 7.078 8.139 22.153 308.364-165.303 468.85-244.685 522.653-11.435 7.753-25.365 7.787-36.873 0.073-80.083-53.683-269.603-214.050-248.298-522.217 0.234-3.389 2.833-7.004 7.234-8.165l264.723-69.849z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["shield-check"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":489,"id":54,"name":"shield-check","prevSize":32,"code":59777},"setIdx":0,"setId":3,"iconIdx":118},{"icon":{"paths":["M373.333 448c0-17.673 14.327-32 32-32h213.334c17.673 0 32 14.327 32 32s-14.327 32-32 32h-213.334c-17.673 0-32-14.327-32-32z","M405.333 544c-17.673 0-32 14.327-32 32s14.327 32 32 32h213.334c17.673 0 32-14.327 32-32s-14.327-32-32-32h-213.334z","M256 128c-17.673 0-32 14.327-32 32v704c0 17.673 14.327 32 32 32h512c17.673 0 32-14.327 32-32v-501.745c0-6.67-2.082-13.172-5.961-18.6l-144.469-202.255c-6.003-8.41-15.701-13.4-26.039-13.4h-367.531zM736 372.51v459.49h-448v-640h319.066l128.934 180.51z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["file-document"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":490,"id":53,"name":"file-document","prevSize":32,"code":59778},"setIdx":0,"setId":3,"iconIdx":119},{"icon":{"paths":["M352 445.44c0-17.677 14.327-32.002 32-32.002h256c17.673 0 32 14.325 32 32.002 0 17.673-14.327 32-32 32h-256c-17.673 0-32-14.327-32-32z","M352 322.558c0-17.673 14.327-32 32-32h256c17.673 0 32 14.327 32 32s-14.327 32-32 32h-256c-17.673 0-32-14.327-32-32z","M864 679.68c0 17.673-14.327 32-32 32h-18.509c-8.218 40.546-8.218 82.334 0 122.88h19.789c16.964 0 30.72 13.756 30.72 30.72s-13.756 30.72-30.72 30.72h-545.28c-70.692 0-128-55.014-128-122.88v-453.12c0-106.039 85.961-192 192-192h480c17.673 0 32 14.327 32 32v519.68zM748.42 834.56c-6.788-40.678-6.788-82.202 0-122.88h-460.42c-35.346 0-64 27.507-64 61.44s28.654 61.44 64 61.44h460.42zM224 647.68h576v-455.68h-448c-70.692 0-128 57.308-128 128v327.68z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["book"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":491,"id":52,"name":"book","prevSize":32,"code":59779},"setIdx":0,"setId":3,"iconIdx":120},{"icon":{"paths":["M778.641 213.333c-17.673 0-32 14.327-32 32v533.333c0 17.673 14.327 32 32 32s32-14.327 32-32v-533.333c0-17.673-14.327-32-32-32z","M600.87 341.333c-17.673 0-32 14.327-32 32v405.333c0 17.673 14.327 32 32 32s32-14.327 32-32v-405.333c0-17.673-14.327-32-32-32z","M423.103 810.667c-17.673 0-32-14.327-32-32v-277.333c0-17.673 14.327-32 32-32s32.001 14.327 32.001 32v277.333c0 17.673-14.327 32-32.001 32z","M245.333 597.333c-17.673 0-32 14.327-32 32v149.333c0 17.673 14.327 32 32 32s32-14.327 32-32v-149.333c0-17.673-14.327-32-32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["signal"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":492,"id":51,"name":"signal","prevSize":32,"code":59780},"setIdx":0,"setId":3,"iconIdx":121},{"icon":{"paths":["M160 512c0-17.673 13.133-32 29.333-32h645.333c16.201 0 29.333 14.327 29.333 32s-13.133 32-29.333 32h-645.333c-16.201 0-29.333-14.327-29.333-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["h-bar"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":493,"id":50,"name":"h-bar","prevSize":32,"code":59781},"setIdx":0,"setId":3,"iconIdx":122},{"icon":{"paths":["M292.515 192c13.364 0 25.321 8.305 29.987 20.829l96 257.699c6.17 16.559-2.255 34.987-18.816 41.156s-34.988-2.253-41.158-18.816l-20.476-54.963h-91.075l-20.476 54.963c-6.17 16.563-24.596 24.986-41.158 18.816s-24.985-24.597-18.816-41.156l96-257.699c4.666-12.524 16.623-20.829 29.987-20.829zM314.211 373.904l-21.695-58.238-21.696 58.238h43.391z","M525.286 626.436c-12.156 12.826-11.61 33.079 1.22 45.235l160 151.586c12.343 11.695 31.676 11.695 44.019 0l160-151.586c12.826-12.156 13.376-32.41 1.22-45.235-12.156-12.83-32.41-13.38-45.239-1.225l-105.993 100.42v-501.632c0-17.673-14.327-32-32-32s-32 14.327-32 32v501.632l-105.988-100.42c-12.83-12.156-33.084-11.605-45.239 1.225z","M196.515 570.944c-17.673 0-32 14.327-32 32 0 17.677 14.327 32 32 32h116.145l-139.065 142.733c-8.979 9.216-11.565 22.916-6.564 34.769 5.001 11.857 16.617 19.563 29.484 19.563h192c17.673 0 32-14.327 32-32s-14.327-32-32-32h-116.145l139.065-142.733c8.979-9.216 11.565-22.912 6.564-34.769-5.001-11.853-16.617-19.563-29.484-19.563h-192z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["sort-az"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":494,"id":49,"name":"sort-az","prevSize":32,"code":59782},"setIdx":0,"setId":3,"iconIdx":123},{"icon":{"paths":["M922.551 666.351c12.587-12.237 12.86-32.35 0.606-44.919-12.254-12.574-32.393-12.843-44.983-0.606l-105.971 103.019v-500.139c0-17.545-14.242-31.767-31.808-31.767-17.57 0-31.812 14.223-31.812 31.767v500.139l-105.971-103.019c-12.591-12.237-32.73-11.968-44.983 0.606-12.254 12.57-11.981 32.683 0.606 44.919l159.97 155.511c12.352 12.006 32.026 12.006 44.378 0l159.97-155.511zM564.425 333.229c17.57 0 31.808-14.223 31.808-31.767s-14.238-31.767-31.808-31.767h-431.919c-17.568 0-31.809 14.223-31.809 31.767s14.242 31.767 31.809 31.767h431.919zM468.442 535.394c17.57 0 31.812-14.221 31.812-31.765s-14.242-31.77-31.812-31.77h-335.936c-17.568 0-31.809 14.225-31.809 31.77s14.242 31.765 31.809 31.765h335.936zM388.458 722.010c17.568 0 31.809-14.221 31.809-31.765s-14.241-31.77-31.809-31.77h-255.952c-17.568 0-31.809 14.225-31.809 31.77s14.241 31.765 31.809 31.765h255.952z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["sort"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":495,"id":48,"name":"sort","prevSize":32,"code":59783},"setIdx":0,"setId":3,"iconIdx":124},{"icon":{"paths":["M822.242 183.279c-37.141-37.936-98.074-38.532-135.953-1.331l-348.017 341.786c-12.722 12.497-21.706 28.284-25.943 45.594l-23.65 96.623c-6.931 28.318 16.732 54.771 45.685 51.072l90.573-11.563c20.195-2.577 39.050-11.503 53.834-25.485l360.013-340.471c38.933-36.82 40.119-98.352 2.633-136.64l-19.174-19.584zM731.166 227.52c12.625-12.4 32.934-12.201 45.316 0.444l19.174 19.584c12.497 12.762 12.1 33.273-0.879 45.547l-69.871 66.081-63.364-63.28 69.623-68.376zM615.906 340.713l62.511 62.427-243.652 230.426c-4.928 4.659-11.211 7.633-17.943 8.495l-58.231 7.433 15.908-64.99c1.412-5.769 4.407-11.034 8.648-15.198l232.76-228.593zM192.001 265.251c0-17.65 14.327-31.958 32-31.958h280.959c17.673 0 32-14.308 32-31.958s-14.327-31.958-32-31.958h-280.959c-53.019 0-96 42.924-96 95.874v533.695c0 52.949 42.981 95.872 96 95.872h529.065c53.022 0 96-42.923 96-95.872v-279.044c0-17.651-14.327-31.962-32-31.962s-32 14.31-32 31.962v279.044c0 17.651-14.327 31.957-32 31.957h-529.065c-17.673 0-32-14.306-32-31.957v-533.695z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["create"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":496,"id":47,"name":"create","prevSize":32,"code":59784},"setIdx":0,"setId":3,"iconIdx":125},{"icon":{"paths":["M252.138 275.61l-13.972 14.271c-37.092 37.884-36.449 98.665 1.435 135.757l145.62 142.576c37.885 37.090 98.665 36.446 135.756-1.438l13.973-14.268c0.725-0.742 1.434-1.489 2.129-2.244l0.098 0.098c5.807-5.905 13.888-9.566 22.822-9.566 17.673 0 32 14.327 32 32 0 9.6-4.228 18.21-10.923 24.077l-14.37 14.677c-61.82 63.142-163.119 64.213-226.26 2.394l-145.62-142.575c-63.141-61.82-64.212-163.121-2.392-226.262l13.972-14.271c61.82-63.141 163.121-64.212 226.263-2.392l74.692 73.131c0.977 0.847 1.899 1.752 2.769 2.71l0.371 0.366-0.026 0.026c4.937 5.63 7.923 13.005 7.923 21.079 0 17.673-14.327 32-32 32-7.829 0-15.002-2.813-20.565-7.482l-0.107 0.108-77.833-76.207c-37.885-37.092-98.665-36.449-135.757 1.435zM787.861 768l13.973-14.268c37.090-37.884 36.45-98.667-1.434-135.757l-145.621-142.575c-37.888-37.090-98.667-36.45-135.757 1.434l-13.973 14.272c-0.725 0.738-1.434 1.485-2.129 2.244l-0.098-0.102c-5.807 5.905-13.888 9.57-22.822 9.57-17.673 0-32-14.327-32-32 0-9.6 4.228-18.214 10.923-24.077l0.397-0.41 13.973-14.272c61.82-63.139 163.119-64.21 226.261-2.389l145.617 142.575c63.142 61.82 64.213 163.119 2.394 226.261l-13.973 14.268c-61.82 63.142-163.119 64.213-226.261 2.394l-74.692-73.131c-0.977-0.849-1.899-1.754-2.769-2.709l-0.371-0.367 0.026-0.026c-4.937-5.632-7.923-13.005-7.923-21.077 0-17.673 14.327-32 32-32 7.829 0 15.002 2.812 20.565 7.479l0.107-0.107 77.833 76.207c37.884 37.090 98.667 36.45 135.757-1.438z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["link"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":497,"id":46,"name":"link","prevSize":32,"code":59785},"setIdx":0,"setId":3,"iconIdx":126},{"icon":{"paths":["M234.667 170.662c0-47.128 38.205-85.333 85.333-85.333h384c47.13 0 85.333 38.205 85.333 85.333v682.668c0 47.125-38.204 85.333-85.333 85.333h-384c-47.128 0-85.333-38.208-85.333-85.333v-682.668zM298.667 170.662v682.668c0 11.78 9.551 21.333 21.333 21.333h384c11.78 0 21.333-9.553 21.333-21.333v-682.668c0-11.782-9.553-21.333-21.333-21.333h-96.29c-2.654 24.002-23.002 42.672-47.71 42.672h-96c-24.708 0-45.056-18.67-47.707-42.672h-96.293c-11.782 0-21.333 9.551-21.333 21.333z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["mobile"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":498,"id":45,"name":"mobile","prevSize":32,"code":59786},"setIdx":0,"setId":3,"iconIdx":127},{"icon":{"paths":["M261.333 96c-17.673 0-32 14.327-32 32v768c0 17.673 14.327 32 32 32h512c17.673 0 32-14.327 32-32v-96c0-17.673-14.327-32-32-32s-32 14.327-32 32v64h-448v-704h448v64c0 17.673 14.327 32 32 32s32-14.327 32-32v-96c0-17.673-14.327-32-32-32h-512zM987.959 489.374l-160-160.001c-12.497-12.497-32.755-12.497-45.252 0s-12.497 32.758 0 45.255l105.37 105.373h-418.743c-17.673 0-32 14.327-32 32s14.327 32 32 32h418.743l-105.37 105.374c-12.497 12.497-12.497 32.755 0 45.252s32.755 12.497 45.252 0l160-160c12.497-12.497 12.497-32.755 0-45.252z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["logout"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":499,"id":44,"name":"logout","prevSize":32,"code":59787},"setIdx":0,"setId":3,"iconIdx":128},{"icon":{"paths":["M736 864.209v-447.408h-448v447.408h448zM224 864.209v-447.408c-35.346 0-64-28.616-64-63.916v-127.831c0-35.299 28.654-63.916 64-63.916h224c0-35.299 28.655-63.915 64-63.915s64 28.616 64 63.915h224c35.345 0 64 28.616 64 63.916v127.831c0 35.299-28.655 63.916-64 63.916v447.408c0 35.298-28.655 63.915-64 63.915h-448c-35.346 0-64-28.617-64-63.915zM800 225.055h-576v127.831h576v-127.831zM416 544.631v191.748c0 17.647 14.327 31.957 32 31.957s32-14.31 32-31.957v-191.748c0-17.647-14.327-31.957-32-31.957s-32 14.31-32 31.957zM576 512.674c17.673 0 32 14.31 32 31.957v191.748c0 17.647-14.327 31.957-32 31.957s-32-14.31-32-31.957v-191.748c0-17.647 14.327-31.957 32-31.957z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["delete"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":500,"id":43,"name":"delete","prevSize":32,"code":59788},"setIdx":0,"setId":3,"iconIdx":129},{"icon":{"paths":["M891.494 238.961l-297.476 637.446c-16.853 36.113-69.619 31.458-79.889-7.049l-66.001-247.501 151.249-189.056-219.993 109.995-226.834-113.417c-35.43-17.715-29.696-69.947 8.733-79.555l681.2-170.3c34.837-8.71 64.196 26.892 49.011 59.436z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["send-filled"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":501,"id":42,"name":"send-filled","prevSize":32,"code":59789},"setIdx":0,"setId":3,"iconIdx":130},{"icon":{"paths":["M878.020 192.976c7.851 9.521 9.527 22.708 4.309 33.891l-298.667 640c-5.692 12.194-18.402 19.529-31.808 18.342-13.406-1.182-24.64-10.628-28.109-23.629l-81.617-306.074-285.774-142.884c-11.977-5.989-18.959-18.802-17.498-32.113s11.056-24.305 24.048-27.553l682.667-170.667c11.972-2.993 24.597 1.165 32.448 10.686zM505.822 545.967l57.079 214.054 233.028-499.351-533.581 133.396 203.605 101.802 69.513-52.134c14.14-10.603 34.197-7.735 44.8 6.4 10.603 14.14 7.74 34.197-6.4 44.8l-68.045 51.034z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["send"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":502,"id":41,"name":"send","prevSize":32,"code":59790},"setIdx":0,"setId":3,"iconIdx":131},{"icon":{"paths":["M800 384v306.743l54.626 54.63c9.152 9.152 11.891 22.916 6.938 34.871-4.954 11.959-16.619 19.755-29.564 19.755h-465.73l64.002-64h305.728v-305.732l63.492-63.492c0.337 5.699 0.508 11.441 0.508 17.224zM715.021 179.728l-45.257 45.255c-40.486-40.169-96.226-64.983-157.764-64.983-123.711 0-224 100.288-224 224v222.746l-64 64v-286.746c0-159.058 128.942-288 288-288 79.211 0 150.95 31.978 203.021 83.728zM416 832c0 53.018 42.982 96 96 96 53.022 0 96-42.982 96-96h-192zM879.872 150.62c-12.493-12.497-32.755-12.497-45.252 0l-675.617 675.616c-12.497 12.497-12.497 32.759 0 45.257s32.758 12.497 45.255 0l675.614-675.618c12.497-12.497 12.497-32.758 0-45.255z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["notification-disabled"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":503,"id":40,"name":"notification-disabled","prevSize":32,"code":59791},"setIdx":0,"setId":3,"iconIdx":132},{"icon":{"paths":["M608 832h-192c0 53.018 42.983 96 96 96s96-42.982 96-96zM736 736v-352c0-123.712-100.288-224-224-224s-224 100.288-224 224v352h448zM192 800c-12.943 0-24.611-7.795-29.564-19.755-4.953-11.955-2.215-25.719 6.937-34.871l54.627-54.63v-306.743c0-159.058 128.942-288 288-288 159.057 0 288 128.942 288 288v309.333l41.6 55.467c7.27 9.698 8.444 22.669 3.021 33.51-5.419 10.842-16.499 17.69-28.621 17.69h-624z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["notification"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":504,"id":39,"name":"notification","prevSize":32,"code":59792},"setIdx":0,"setId":3,"iconIdx":133},{"icon":{"paths":["M194.254 320c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z","M322.254 224c-17.673 0-32 14.327-32 32s14.327 32 32 32h543.999c17.673 0 32-14.327 32-32s-14.327-32-32-32h-543.999z","M194.254 576c35.346 0 64-28.655 64-64s-28.654-64-64-64c-35.346 0-64 28.655-64 64s28.654 64 64 64z","M322.254 480c-17.673 0-32 14.327-32 32s14.327 32 32 32h543.999c17.673 0 32-14.327 32-32s-14.327-32-32-32h-543.999z","M194.254 832c35.346 0 64-28.655 64-64s-28.654-64-64-64c-35.346 0-64 28.655-64 64s28.654 64 64 64z","M322.254 736c-17.673 0-32 14.327-32 32s14.327 32 32 32h543.999c17.673 0 32-14.327 32-32s-14.327-32-32-32h-543.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["view-medium"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":505,"id":38,"name":"view-medium","prevSize":32,"code":59793},"setIdx":0,"setId":3,"iconIdx":134},{"icon":{"paths":["M206.090 672c35.346 0 64-28.655 64-64s-28.654-64-64-64c-35.346 0-64 28.655-64 64s28.654 64 64 64z","M334.090 576c-17.673 0-32 14.327-32 32s14.327 32 32 32h543.999c17.673 0 32-14.327 32-32s-14.327-32-32-32h-543.999z","M206.090 480c35.346 0 64-28.655 64-64 0-35.346-28.654-64-64-64s-64 28.654-64 64c0 35.345 28.654 64 64 64z","M334.090 384c-17.673 0-32 14.327-32 32s14.327 32 32 32h543.999c17.673 0 32-14.327 32-32s-14.327-32-32-32h-543.999z","M206.090 288c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z","M334.090 192c-17.673 0-32 14.327-32 32s14.327 32 32 32h543.999c17.673 0 32-14.327 32-32s-14.327-32-32-32h-543.999z","M206.090 864c35.346 0 64-28.655 64-64s-28.654-64-64-64c-35.346 0-64 28.655-64 64s28.654 64 64 64z","M334.090 768c-17.673 0-32 14.327-32 32s14.327 32 32 32h543.999c17.673 0 32-14.327 32-32s-14.327-32-32-32h-543.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["view-condensed"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":506,"id":37,"name":"view-condensed","prevSize":32,"code":59794},"setIdx":0,"setId":3,"iconIdx":135},{"icon":{"paths":["M288 192c0-17.673 14.327-32 32-32h544c17.673 0 32 14.327 32 32s-14.327 32-32 32h-544c-17.673 0-32-14.327-32-32zM288 288c0-17.673 14.327-32 32-32h448c17.673 0 32 14.327 32 32s-14.327 32-32 32h-448c-17.673 0-32-14.327-32-32zM192 304c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z","M288 464c0-17.673 14.327-32 32-32h544c17.673 0 32 14.327 32 32s-14.327 32-32 32h-544c-17.673 0-32-14.327-32-32zM288 560c0-17.673 14.327-32 32-32h448c17.673 0 32 14.327 32 32s-14.327 32-32 32h-448c-17.673 0-32-14.327-32-32zM192 576c35.346 0 64-28.655 64-64s-28.654-64-64-64c-35.346 0-64 28.655-64 64s28.654 64 64 64z","M288 736c0-17.673 14.327-32 32-32h544c17.673 0 32 14.327 32 32s-14.327 32-32 32h-544c-17.673 0-32-14.327-32-32zM288 832c0-17.673 14.327-32 32-32h448c17.673 0 32 14.327 32 32s-14.327 32-32 32h-448c-17.673 0-32-14.327-32-32zM192 848c35.346 0 64-28.655 64-64s-28.654-64-64-64c-35.346 0-64 28.655-64 64s28.654 64 64 64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["view-extended"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":507,"id":36,"name":"view-extended","prevSize":32,"code":59795},"setIdx":0,"setId":3,"iconIdx":136},{"icon":{"paths":["M825.374 153.173c12.497-12.48 32.755-12.48 45.252 0s12.497 32.715 0 45.195l-671.999 671.115c-12.497 12.48-32.758 12.48-45.255 0s-12.497-32.717 0-45.197l672.002-671.113zM107.307 479.424c101.801-153.5 303.397-327.248 541.397-225.142l-49.51 49.446c-56.452-19.184-107.934-19.478-153.323-9.713-114.755 24.688-215.37 118.236-280.422 213.585 38.582 47.94 75.869 86.711 111.715 117.73l-45.303 45.244c-39.632-34.692-80.083-77.333-121.157-129.007-14.229-17.903-16.035-43.089-3.398-62.144zM794.227 349.994l-45.269 45.21c35.494 31.386 72.239 70.857 110.037 119.924-61.461 95.061-158.443 188.433-271.761 213.342-46.694 10.266-100.493 9.719-160.384-11.588l-49.266 49.203c244.342 107.191 442.802-69.069 540.065-223.957 11.657-18.564 9.882-42.598-3.392-60.049-40.439-53.163-80.533-96.801-120.030-132.084zM511.599 346.974c13.692 0 26.999 1.57 39.753 4.534l-203.471 203.201c-3.895-13.82-5.974-28.365-5.974-43.379 0-90.772 75.975-164.356 169.693-164.356zM675.494 468.57l-202.995 202.726c12.553 2.867 25.643 4.386 39.1 4.386 93.722 0 169.694-73.583 169.694-164.352 0-14.793-2.018-29.129-5.798-42.761z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["unread-on-top-disabled"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":508,"id":35,"name":"unread-on-top-disabled","prevSize":32,"code":59796},"setIdx":0,"setId":3,"iconIdx":137},{"icon":{"paths":["M587.234 728.474c-107.23 23.573-251.957-9.865-421.785-220.868 65.051-95.352 165.667-188.9 280.422-213.588 108.169-23.272 250.953 10.59 413.124 221.111-61.461 95.061-158.443 188.433-271.761 213.346zM914.257 482.082c-347.132-456.361-668.857-210.879-806.95-2.658-12.638 19.055-10.832 44.241 3.398 62.144 362.307 455.817 676.142 208.862 806.945 0.563 11.657-18.569 9.882-42.598-3.392-60.049zM617.293 511.33c0-53.641-45.457-100.439-105.694-100.439s-105.693 46.799-105.693 100.439c0 53.636 45.456 100.437 105.693 100.437s105.694-46.801 105.694-100.437zM681.293 511.33c0 90.769-75.972 164.352-169.694 164.352-93.718 0-169.693-73.583-169.693-164.352 0-90.771 75.975-164.355 169.693-164.355 93.722 0 169.694 73.584 169.694 164.355z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["unread-on-top"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":509,"id":34,"name":"unread-on-top","prevSize":32,"code":59797},"setIdx":0,"setId":3,"iconIdx":138},{"icon":{"paths":["M544 208c0-17.673-14.323-32-32-32-17.673 0-32 14.327-32 32v271.996h-271.997c-17.673 0-32 14.327-32 32s14.327 32 32 32h271.997v272.004c0 17.673 14.327 32 32 32 17.677 0 32-14.327 32-32v-272.004h272.004c17.673 0 32-14.327 31.996-32 0-17.673-14.323-32-32-32h-272v-271.996z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["add"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":510,"id":33,"name":"add","prevSize":32,"code":59798},"setIdx":0,"setId":3,"iconIdx":139},{"icon":{"paths":["M806.626 262.627c12.497-12.497 12.497-32.758 0-45.255s-32.755-12.497-45.252 0l-249.374 249.371-249.373-249.371c-12.497-12.497-32.758-12.497-45.255 0s-12.497 32.758 0 45.255l249.371 249.373-249.371 249.374c-12.497 12.497-12.497 32.755 0 45.252s32.758 12.497 45.255 0l249.373-249.37 249.374 249.37c12.497 12.497 32.755 12.497 45.252 0s12.497-32.755 0-45.252l-249.37-249.374 249.37-249.373z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["close"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":511,"id":32,"name":"close","prevSize":32,"code":59799},"setIdx":0,"setId":3,"iconIdx":140},{"icon":{"paths":["M416 128c-35.346 0-64 28.654-64 64v226.636c20.775-2.822 42.133-3.455 64-1.527v-225.11h176v180.706c0 35.346 28.655 64 64 64h176v331.294h-120.555c-17.156 22.178-36.322 43.87-57.31 64h177.865c35.345 0 64-28.655 64-64v-363.294c0-6.41-1.924-12.672-5.525-17.975l-156.634-230.682c-11.913-17.545-31.74-28.049-52.945-28.049h-264.896zM656 372.706v-180.706h24.896l122.697 180.706h-147.593zM165.234 668.544c120.524 156.143 218.24 174.588 285.134 158.741 73.293-17.361 139.23-81.647 183.462-151.761-115.153-155.87-211.58-174.588-279.148-158.916-74.361 17.25-142.706 81.685-189.449 151.936zM101.723 649.037c100.621-162.799 337.62-357.19 593.253 1.788 9.071 12.74 10.321 29.82 2.423 43.315-95.275 162.854-326.394 358.345-593.236-0.222-9.745-13.094-11.022-30.997-2.44-44.881zM398.961 735.991c31.512 0 60.269-26.854 60.269-64 0-37.141-28.757-64-60.269-64-31.514 0-60.268 26.859-60.268 64 0 37.146 28.755 64 60.268 64zM398.961 799.991c68.632 0 124.269-57.306 124.269-128 0-70.69-55.637-128-124.269-128s-124.268 57.31-124.268 128c0 70.694 55.637 128 124.268 128z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["auditing"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":512,"id":31,"name":"auditing","prevSize":32,"code":59800},"setIdx":0,"setId":3,"iconIdx":141},{"icon":{"paths":["M416 586.445v177.233l75.516-62.929c11.866-9.89 29.103-9.89 40.969 0l75.516 62.929v-177.233c-29.094 13.82-61.645 21.555-96 21.555s-66.906-7.735-96-21.555zM352 540.766v291.234c0 12.416 7.183 23.71 18.427 28.979 11.244 5.265 24.521 3.554 34.059-4.395l107.514-89.596 107.516 89.596c9.536 7.949 22.814 9.66 34.057 4.395 11.247-5.269 18.428-16.563 18.428-28.979v-291.234c39.59-40.401 64-95.731 64-156.766 0-123.712-100.288-224-224-224s-224 100.288-224 224c0 61.035 24.41 116.365 64 156.766zM416 512.013l-0.015-0.013c-38.854-29.193-63.985-75.661-63.985-128 0-88.366 71.634-160 160-160 88.367 0 160 71.634 160 160 0 52.34-25.131 98.808-63.983 128l-0.017 0.013c-26.739 20.083-59.981 31.987-96 31.987s-69.261-11.904-96-31.987z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["enterprise-feature"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":513,"id":30,"name":"enterprise-feature","prevSize":32,"code":59801},"setIdx":0,"setId":3,"iconIdx":142},{"icon":{"paths":["M749.756 660.215c16.887-16.435 17.259-43.447 0.823-60.335-16.431-16.887-43.443-17.259-60.335-0.823l59.511 61.158zM512 832.021l-29.756 30.579c16.563 16.115 42.948 16.115 59.511 0l-29.756-30.579zM333.754 599.057c-16.889-16.435-43.901-16.064-60.334 0.823s-16.064 43.9 0.825 60.335l59.509-61.158zM690.244 599.057l-208 202.385 59.511 61.158 208-202.385-59.511-61.158zM541.756 801.442l-208.001-202.385-59.509 61.158 207.999 202.385 59.511-61.158z","M749.756 363.805c16.887 16.433 17.259 43.445 0.823 60.334-16.431 16.889-43.443 17.26-60.335 0.826l59.511-61.16zM512 191.999l-29.756-30.58c16.563-16.116 42.948-16.116 59.511 0l-29.756 30.58zM333.754 424.965c-16.889 16.434-43.901 16.063-60.334-0.825s-16.064-43.901 0.825-60.334l59.509 61.159zM690.244 424.965l-208-202.386 59.511-61.159 208 202.386-59.511 61.16zM541.756 222.579l-208.001 202.386-59.509-61.159 207.999-202.386 59.511 61.159z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(158, 162, 168)","opacity":0.7}],"isMulticolor":true,"isMulticolor2":true,"grid":0,"tags":["ordering-ascending"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(158, 162, 168)","opacity":0.7}],"properties":{"order":514,"id":29,"name":"ordering-ascending","prevSize":32,"code":59802,"codes":[59802,59803]},"setIdx":0,"setId":3,"iconIdx":143},{"icon":{"paths":["M274.246 363.785c-16.889 16.433-17.258 43.445-0.825 60.334s43.445 17.259 60.334 0.825l-59.509-61.159zM512 191.978l29.756-30.58c-16.563-16.116-42.948-16.116-59.511 0l29.756 30.58zM690.244 424.944c16.892 16.434 43.904 16.063 60.335-0.825 16.435-16.889 16.064-43.901-0.823-60.334l-59.511 61.159zM333.754 424.944l208.001-202.386-59.511-61.16-207.999 202.386 59.509 61.159zM482.244 222.558l208 202.386 59.511-61.159-208-202.386-59.511 61.16z","M274.246 660.194c-16.889-16.431-17.258-43.443-0.825-60.335 16.433-16.887 43.445-17.259 60.334-0.823l-59.509 61.158zM512 832l29.756 30.579c-16.563 16.115-42.948 16.115-59.511 0l29.756-30.579zM690.244 599.036c16.892-16.435 43.904-16.064 60.335 0.823 16.435 16.892 16.064 43.904-0.823 60.335l-59.511-61.158zM333.754 599.036l208.001 202.385-59.511 61.158-207.999-202.385 59.509-61.158zM482.244 801.421l208-202.385 59.511 61.158-208 202.385-59.511-61.158z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(158, 162, 168)","opacity":0.7}],"isMulticolor":true,"isMulticolor2":true,"grid":0,"tags":["ordering-descending"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(158, 162, 168)","opacity":0.7}],"properties":{"order":515,"id":28,"name":"ordering-descending","prevSize":32,"code":59804,"codes":[59804,59805]},"setIdx":0,"setId":3,"iconIdx":144},{"icon":{"paths":["M448 192c-17.673 0-32 14.327-32 32v128c0 17.673 14.327 32 32 32h128c17.673 0 32-14.327 32-32v-128c0-17.673-14.327-32-32-32h-128z","M416 448c0-17.673 14.327-32 32-32h128c17.673 0 32 14.327 32 32v128c0 17.673-14.327 32-32 32h-128c-17.673 0-32-14.327-32-32v-128z","M416 672c0-17.673 14.327-32 32-32h128c17.673 0 32 14.327 32 32v128c0 17.673-14.327 32-32 32h-128c-17.673 0-32-14.327-32-32v-128z"],"attrs":[{"fill":"rgb(245, 69, 92)"},{"fill":"rgb(245, 69, 92)"},{"fill":"rgb(245, 69, 92)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["priority-high"]},"attrs":[{"fill":"rgb(245, 69, 92)"},{"fill":"rgb(245, 69, 92)"},{"fill":"rgb(245, 69, 92)"}],"properties":{"order":516,"id":27,"name":"priority-high","prevSize":32,"code":59806},"setIdx":0,"setId":3,"iconIdx":145},{"icon":{"paths":["M448 416c-17.673 0-32 14.327-32 32v128c0 17.673 14.327 32 32 32h128c17.673 0 32-14.327 32-32v-128c0-17.673-14.327-32-32-32h-128zM448 640c-17.673 0-32 14.327-32 32v128c0 17.673 14.327 32 32 32h128c17.673 0 32-14.327 32-32v-128c0-17.673-14.327-32-32-32h-128z","M448 192h128c17.673 0 32 14.327 32 32v128c0 17.673-14.327 32-32 32h-128c-17.673 0-32-14.327-32-32v-128c0-17.673 14.327-32 32-32z"],"attrs":[{"fill":"rgb(243, 190, 8)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":true,"isMulticolor2":false,"grid":0,"tags":["priority-medium"]},"attrs":[{"fill":"rgb(243, 190, 8)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":517,"id":26,"name":"priority-medium","prevSize":32,"code":59807,"codes":[59807,59808]},"setIdx":0,"setId":3,"iconIdx":146},{"icon":{"paths":["M448 640h128c17.673 0 32 14.327 32 32v128c0 17.673-14.327 32-32 32h-128c-17.673 0-32-14.327-32-32v-128c0-17.673 14.327-32 32-32z","M448 192c-17.673 0-32 14.327-32 32v128c0 17.673 14.327 32 32 32h128c17.673 0 32-14.327 32-32v-128c0-17.673-14.327-32-32-32h-128zM448 416c-17.673 0-32 14.327-32 32v128c0 17.673 14.327 32 32 32h128c17.673 0 32-14.327 32-32v-128c0-17.673-14.327-32-32-32h-128z"],"attrs":[{"fill":"rgb(45, 224, 165)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":true,"isMulticolor2":false,"grid":0,"tags":["priority-low"]},"attrs":[{"fill":"rgb(45, 224, 165)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":518,"id":25,"name":"priority-low","prevSize":32,"code":59809,"codes":[59809,59810]},"setIdx":0,"setId":3,"iconIdx":147},{"icon":{"paths":["M768 224c17.673 0 32 14.327 32 32v544c0 17.673-14.327 32-32 32h-544c-17.673 0-32-14.327-32-32v-128c17.673 0 32-14.327 32-32s-14.327-32-32-32v-192c17.673 0 32-14.327 32-32s-14.327-32-32-32v-96c0-17.673 14.327-32 32-32h544zM128 608c-17.673 0-32 14.327-32 32s14.327 32 32 32v128c0 53.018 42.981 96 96 96h544c53.018 0 96-42.982 96-96v-544c0-53.019-42.982-96-96-96h-544c-53.019 0-96 42.981-96 96v96c-17.673 0-32 14.327-32 32s14.327 32 32 32v192zM425.205 514.266c13.315-3.567 27.309-3.789 40.732-0.644l31.518 7.39c8.73 2.044 17.83 1.903 26.492-0.418l22.182-5.943c14.289-3.823 29.329-4.036 43.682-0.674 40.431 9.476 69.325 45.585 69.325 87.279v24.337c0 31.812-25.788 57.6-57.6 57.6h-180.736c-31.812 0-57.6-25.788-57.6-57.6v-30.528c0-37.862 25.432-71.002 62.005-80.798zM454.251 563.473c-5.205-1.22-10.633-1.135-15.799 0.247-14.186 3.802-24.051 16.657-24.051 31.343v30.528c0 3.533 2.865 6.4 6.4 6.4h180.736c3.537 0 6.4-2.867 6.4-6.4v-24.337c0-17.749-12.365-33.34-29.807-37.427-6.182-1.451-12.659-1.353-18.752 0.282l-22.187 5.943c-16.811 4.501-34.475 4.779-51.418 0.806l-31.522-7.386zM536.448 420.48c0-13.962-11.315-25.28-25.28-25.28-13.961 0-25.28 11.319-25.28 25.28 0 13.96 11.319 25.28 25.28 25.28 13.965 0 25.28-11.319 25.28-25.28zM587.648 420.48c0 42.24-34.24 76.48-76.48 76.48s-76.48-34.24-76.48-76.48c0-42.239 34.24-76.48 76.48-76.48s76.48 34.242 76.48 76.48z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["contacts"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":519,"id":24,"name":"contacts","prevSize":32,"code":59811},"setIdx":0,"setId":3,"iconIdx":148},{"icon":{"paths":["M302.769 192h418.464l23.185 72.727h-0.213l23.795 64c0 41.27-31.305 69.818-64 69.818s-64-28.548-64-69.818c0-18.477-14.327-33.455-32-33.455s-32 14.978-32 33.455c0 41.27-31.305 69.818-64 69.818s-64-28.548-64-69.818c0-18.477-14.327-33.455-32-33.455s-32 14.978-32 33.455c0 41.27-31.305 69.818-64 69.818s-64-28.548-64-69.818l23.793-64h-0.213l23.188-72.727zM212.406 264.727l36.491-114.448c4.231-13.27 16.56-22.279 30.488-22.279h465.23c13.931 0 26.257 9.009 30.49 22.279l56.896 178.448c0 33.937-12.083 64.925-32 88.515v350.775c0 53.022-42.982 96-96 96h-384c-53.019 0-96-42.978-96-96v-350.775c-19.916-23.59-32-54.577-32-88.515l20.406-64zM288 458.33v309.687c0 17.673 14.327 32 32 32h128v-192.017h128v192.017h128c17.673 0 32-14.327 32-32v-309.687c-10.227 2.752-20.949 4.215-32 4.215-38.229 0-72.546-17.523-96-45.303-23.454 27.78-57.771 45.303-96 45.303s-72.546-17.523-96-45.303c-23.454 27.78-57.77 45.303-96 45.303-11.049 0-21.772-1.463-32-4.215z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["marketplace"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":520,"id":23,"name":"marketplace","prevSize":32,"code":59812},"setIdx":0,"setId":3,"iconIdx":149},{"icon":{"paths":["M224 224c-17.673 0-32 14.327-32 32v544c0 17.673 14.327 32 32 32h544c17.673 0 32-14.327 32-32v-544c0-17.673-14.327-32-32-32h-544zM128 256c0-53.019 42.981-96 96-96h544c53.018 0 96 42.981 96 96v544c0 53.018-42.982 96-96 96h-544c-53.019 0-96-42.982-96-96v-544zM608 460.813c0 41.801-26.714 77.359-64 90.539v133.461h-64v-133.461c-37.286-13.18-64-48.738-64-90.539 0-53.020 42.982-96 96-96s96 42.981 96 96zM608 588.826c38.861-29.193 64-75.665 64-128.013 0-88.366-71.633-160-160-160-88.366 0-160 71.635-160 160 0 52.348 25.138 98.82 64 128.013v127.987c0 17.673 14.327 32 32 32h128c17.673 0 32-14.327 32-32v-127.987z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["auth"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":521,"id":22,"name":"auth","prevSize":32,"code":59813},"setIdx":0,"setId":3,"iconIdx":150},{"icon":{"paths":["M623.091 896c-2.803 0-5.299-0.623-7.168-0.939-61.999-16.858-102.818-39.646-145.813-80.858-55.147-54.007-85.369-125.815-85.369-202.3 0-65.873 56.705-119.573 126.495-119.573 69.794 0 126.498 53.7 126.498 119.573 0 34.965 31.467 63.373 69.79 63.373s69.794-28.407 69.794-63.373c0-135.808-119.646-246.636-266.705-246.636-104.997 0-200.337 57.132-243.334 145.793-14.332 29.35-21.498 63.066-21.498 100.843 0 28.719 2.493 73.365 24.925 131.746 2.804 7.181 2.493 14.673-0.623 21.854-3.116 6.865-9.036 11.861-16.201 14.357-2.804 1.25-6.231 1.562-9.658 1.562-11.84 0-22.433-7.181-26.484-18.108-19.005-50.261-28.352-99.9-28.352-151.727 0-46.204 9.036-88.35 26.795-125.5 52.343-108.020 167.935-177.64 294.431-177.64 178.53 0 323.721 135.805 323.721 302.828 0 65.873-56.704 119.573-126.81 119.573-70.101 0-126.805-53.7-126.805-119.573 0-34.965-31.471-63.373-69.794-63.373-38.635 0-69.79 28.407-69.79 63.373 0 61.504 24.303 119.262 68.544 162.342 35.209 34.031 68.855 53.073 120.576 67.123 7.168 1.873 13.397 6.554 17.139 13.111 3.738 6.558 4.672 14.362 2.803 21.231-2.803 11.861-14.020 20.915-27.106 20.915zM426.803 888.196c-7.79 0-15.267-3.123-20.253-8.742-33.338-32.781-51.72-54.012-77.892-100.527-26.795-47.142-41.127-105.212-41.127-167.339 0-116.446 100.948-211.354 224.95-211.354 124.006 0 224.956 94.908 224.956 211.354 0 15.612-12.463 28.1-28.356 28.1-15.889 0-28.663-12.177-28.663-28.1 0-85.538-75.401-155.157-168.247-155.157-92.846 0-168.245 69.619-168.245 155.157 0 52.45 11.84 100.527 34.272 139.554 23.368 41.519 38.946 59.004 68.855 88.661 10.906 11.238 10.906 28.723 0 39.65-5.918 5.931-13.086 8.742-20.25 8.742zM699.738 818.889c-47.36 0-88.798-11.866-123.383-34.965-59.196-39.65-94.716-103.962-94.716-172.335 0-15.607 12.463-28.096 28.352-28.096s28.352 12.489 28.352 28.096c0 49.643 26.172 96.781 69.794 125.504 25.237 16.858 55.147 24.977 91.601 24.977 7.787 0 22.43-0.939 38.012-3.746 1.557-0.311 3.426-0.311 4.983-0.311 13.709 0 25.237 9.988 27.729 23.411 1.246 7.181-0.311 14.673-4.361 20.608-4.365 6.242-10.906 10.611-18.697 11.861-23.364 4.685-43.93 4.996-47.667 4.996zM188.765 435.823c-5.608 0-11.216-1.562-16.201-4.992-6.543-4.062-10.593-10.616-12.151-18.109-1.246-7.493 0.311-14.985 4.985-21.229 38.634-53.698 87.862-95.844 146.125-125.502 60.133-30.595 129.612-46.829 200.96-46.829 71.040 0 140.207 15.922 200.030 46.205 58.573 29.658 107.802 71.493 146.125 124.566 4.361 5.932 6.229 13.425 4.983 20.917s-5.606 14.049-11.84 18.42c-4.983 3.435-10.594 4.992-16.512 4.992-9.037 0-17.758-4.369-23.057-11.861-33.335-45.893-75.712-82.107-125.559-107.083-52.343-26.224-112.789-40.273-174.481-40.273-62.31 0-122.756 14.049-175.1 40.585-49.851 25.912-92.535 62.127-126.185 108.644-3.739 6.869-12.463 11.55-22.121 11.55zM733.696 239.142c-4.672 0-9.344-1.249-13.397-3.434-71.347-35.902-133.35-51.512-207.505-51.512-74.462 0-144.254 17.483-207.814 51.825-4.050 2.185-8.724 3.122-13.397 3.122-10.282 0-19.629-5.62-24.925-14.361-3.739-6.556-4.674-14.361-2.493-21.542s7.166-13.424 13.709-16.858c72.596-38.712 151.733-58.38 234.921-58.38 82.569 0 154.85 17.795 233.988 58.068 6.857 3.434 11.84 9.366 14.332 16.858 2.185 7.18 1.246 14.673-2.18 21.229-4.983 9.053-14.643 14.985-25.237 14.985z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["fingerprint"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":522,"id":21,"name":"fingerprint","prevSize":32,"code":59814},"setIdx":0,"setId":3,"iconIdx":151},{"icon":{"paths":["M737.779 361.376c12.497 12.497 12.497 32.758 0 45.255l-110.946 110.95 110.946 110.946c12.497 12.497 12.497 32.759 0 45.257s-32.759 12.497-45.252 0l-110.95-110.95-110.95 110.95c-12.497 12.497-32.755 12.497-45.254 0-12.497-12.497-12.497-32.759 0-45.257l110.947-110.946-110.947-110.95c-12.497-12.497-12.497-32.758 0-45.255 12.498-12.497 32.756-12.497 45.254 0l110.95 110.948 110.95-110.948c12.493-12.497 32.755-12.497 45.252 0z","M312.247 218.073c12.061-16.393 31.199-26.073 51.551-26.073h468.202c35.345 0 64 28.654 64 64v512c0 35.345-28.655 64-64 64h-468.202c-20.352 0-39.491-9.681-51.551-26.074l-188.343-256c-16.598-22.562-16.598-53.291 0-75.853l188.343-256zM363.798 256l-188.343 256 188.343 256h468.202v-512h-468.202z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["backspace"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":523,"id":20,"name":"backspace","prevSize":32,"code":59815},"setIdx":0,"setId":3,"iconIdx":152},{"icon":{"paths":["M208 176c-35.346 0-64 28.654-64 64v576c0 35.345 28.654 64 64 64h576c35.345 0 64-28.655 64-64v-576c0-35.346-28.655-64-64-64h-576zM208 240h576v576h-576v-576zM698.628 558.153c-0.192 17.673-14.669 31.842-32.341 31.654s-31.846-14.669-31.659-32.341l1.323-123.588-309.344 308.77c-12.508 12.484-32.77 12.467-45.255-0.043-12.485-12.506-12.466-32.768 0.042-45.252l309.199-308.627-123.388 1.318c-17.673 0.189-32.149-13.984-32.337-31.657-0.192-17.672 13.982-32.151 31.654-32.34l201.92-2.156c8.606-0.092 16.887 3.286 22.972 9.371s9.459 14.364 9.37 22.969l-2.155 201.922z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["new-window"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":524,"id":19,"name":"new-window","prevSize":32,"code":59816},"setIdx":0,"setId":3,"iconIdx":153},{"icon":{"paths":["M464 318.068c0-51.548-42.408-94.366-96-94.366s-96 42.819-96 94.366c0 51.548 42.408 94.367 96 94.367s96-42.819 96-94.367zM528 318.068c0 87.417-71.633 158.284-160 158.284-88.366 0-160-70.867-160-158.284s71.634-158.282 160-158.282c88.367 0 160 70.865 160 158.282zM281.778 525.035c-27.649-7.693-56.976-7.159-84.32 1.536-60.46 19.226-101.459 74.863-101.459 137.685v103.633c0 52.45 42.981 94.967 96 94.967h352c3.605 0 7.164-0.196 10.667-0.576v-64.538c-3.337 1.169-6.925 1.801-10.667 1.801h-352c-17.673 0-32-14.17-32-31.654v-103.633c0-35.319 23.051-66.603 57.043-77.41 15.374-4.89 31.862-5.188 47.407-0.866l48.489 13.491c36.311 10.103 74.826 9.404 110.737-2.018l30.1-9.57c17.502-5.564 36.275-5.905 53.978-0.981 18.901 5.257 35.063 16.038 46.912 30.281v-79.714c-9.31-4.749-19.204-8.627-29.585-11.516-29.803-8.29-61.414-7.714-90.889 1.655l-30.101 9.57c-23.941 7.616-49.617 8.081-73.825 1.348l-48.489-13.491zM763.366 489.033c-12.326-12.651-32.585-12.919-45.248-0.61s-12.937 32.542-0.61 45.193l102.839 105.506h-324.348c-17.673 0-32 14.31-32 31.962 0 17.647 14.327 31.957 32 31.957h324.348l-102.839 105.51c-12.326 12.646-12.053 32.879 0.61 45.188 12.663 12.314 32.922 12.041 45.248-0.606l155.721-159.761c12.092-12.407 12.092-32.175 0-44.582l-155.721-159.757z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["user-forward"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":525,"id":18,"name":"user-forward","prevSize":32,"code":59817},"setIdx":0,"setId":3,"iconIdx":154},{"icon":{"paths":["M320 159.791c0-17.649-14.327-31.958-32-31.958h-64c-17.673 0-32 14.308-32 31.958v63.916c0 17.65 14.327 31.958 32 31.958h64c17.673 0 32-14.308 32-31.958v-63.916zM320 585.894c0-17.651-14.327-31.957-32-31.957h-64c-17.673 0-32 14.306-32 31.957v63.915c0 17.651 14.327 31.957 32 31.957h64c17.673 0 32-14.306 32-31.957v-63.915zM448 159.791c0-17.649 14.327-31.958 32-31.958h64c17.673 0 32 14.308 32 31.958v63.916c0 17.65-14.327 31.958-32 31.958h-64c-17.673 0-32-14.308-32-31.958v-63.916zM576 372.843c0-17.65-14.327-31.958-32-31.958h-64c-17.673 0-32 14.308-32 31.958v63.914c0 17.651 14.327 31.957 32 31.957h64c17.673 0 32-14.306 32-31.957v-63.914zM448 585.894c0-17.651 14.327-31.957 32-31.957h64c17.673 0 32 14.306 32 31.957v63.915c0 17.651-14.327 31.957-32 31.957h-64c-17.673 0-32-14.306-32-31.957v-63.915zM576 798.946c0-17.651-14.327-31.957-32-31.957h-64c-17.673 0-32 14.306-32 31.957v63.915c0 17.651 14.327 31.957 32 31.957h64c17.673 0 32-14.306 32-31.957v-63.915zM704 159.791c0-17.649 14.327-31.958 32-31.958h64c17.673 0 32 14.308 32 31.958v63.916c0 17.65-14.327 31.958-32 31.958h-64c-17.673 0-32-14.308-32-31.958v-63.916zM832 372.843c0-17.65-14.327-31.958-32-31.958h-64c-17.673 0-32 14.308-32 31.958v63.914c0 17.651 14.327 31.957 32 31.957h64c17.673 0 32-14.306 32-31.957v-63.914zM704 585.894c0-17.651 14.327-31.957 32-31.957h64c17.673 0 32 14.306 32 31.957v63.915c0 17.651-14.327 31.957-32 31.957h-64c-17.673 0-32-14.306-32-31.957v-63.915zM320 372.843c0-17.65-14.327-31.958-32-31.958h-64c-17.673 0-32 14.308-32 31.958v63.914c0 17.651 14.327 31.957 32 31.957h64c17.673 0 32-14.306 32-31.957v-63.914z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["dialpad"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":526,"id":17,"name":"dialpad","prevSize":32,"code":59818},"setIdx":0,"setId":3,"iconIdx":155},{"icon":{"paths":["M482.325 229.047c19.767-23.931 49.89-36.827 80.849-34.615l143.936 10.281c42.052 3.004 77.222 33.091 86.703 74.17l30.349 131.517c6.643 28.785-0.337 59.028-18.923 81.991l-252.369 311.744c-11.119 13.739-31.27 15.859-45.005 4.74-13.734-11.123-15.859-31.27-4.736-45.009l252.365-311.744c6.195-7.654 8.521-17.737 6.306-27.331l-30.349-131.517c-3.157-13.693-14.882-23.722-28.898-24.723l-143.936-10.281c-10.321-0.737-20.361 3.561-26.953 11.538l-265.999 322c-5.438 6.583-8.020 15.066-7.17 23.565l7.581 75.81c1.636 16.358 15.401 28.817 31.841 28.817h104.305c9.439 0 18.397-4.169 24.476-11.388l227.597-270.268-10.052-70.344h-69.257l-230.406 276.488c-11.314 13.577-31.492 15.411-45.069 4.096s-15.412-31.492-4.097-45.069l230.403-276.487c12.16-14.592 30.174-23.028 49.169-23.028h69.257c31.851 0 58.854 23.419 63.356 54.949l10.052 70.345c2.577 18.044-2.662 36.331-14.404 50.274l-227.593 270.268c-18.24 21.662-45.116 34.163-73.432 34.163h-104.305c-49.321 0-90.616-37.372-95.524-86.447l-7.581-75.814c-2.549-25.489 5.196-50.944 21.511-70.694l266-321.997z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["attach"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":527,"id":16,"name":"attach","prevSize":32,"code":59819},"setIdx":0,"setId":3,"iconIdx":156},{"icon":{"paths":["M896 512h-63.987c0-175.415-145.749-320-328.516-320-115.27 0-215.817 57.513-274.36 144h110.768c17.673 0 32 14.327 32 32s-14.327 32-32 32h-179.904c-17.673 0-32-14.327-32-32v-192c0-17.673 14.327-32 32-32s32 14.327 32 32v102.32c71.751-91.401 184.591-150.32 311.497-150.32 216.781 0 392.503 171.923 392.503 384 0 1.114 0.009 2.227 0 3.337v-3.337z","M127.997 512h63.986c0 175.415 145.751 320 328.52 320 115.268 0 215.817-57.515 274.359-144h-110.767c-17.677 0-32-14.327-32-32s14.323-32 32-32h179.904c17.673 0 32 14.327 32 32v192c0 17.673-14.327 32-32 32s-32-14.327-32-32v-102.319c-71.753 91.401-184.593 150.319-311.497 150.319-216.783 0-392.506-171.921-392.506-384 0-1.084-0.009-2.163 0-3.247v3.247z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["refresh"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":528,"id":15,"name":"refresh","prevSize":32,"code":59820},"setIdx":0,"setId":3,"iconIdx":157},{"icon":{"paths":["M512 832c176.73 0 320-143.27 320-320 0-176.731-143.27-320-320-320-111.713 0-210.056 57.245-267.295 144h107.295c17.673 0 32 14.327 32 32s-14.327 32-32 32h-176c-17.673 0-32-14.327-32-32v-192c0-17.673 14.327-32 32-32s32 14.327 32 32v101.364c70.228-90.856 180.282-149.364 304-149.364 212.079 0 384 171.923 384 384 0 212.079-171.921 384-384 384-212.077 0-384-171.921-384-384h64c0 176.73 143.269 320 320 320z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["undo"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":529,"id":14,"name":"undo","prevSize":32,"code":59821},"setIdx":0,"setId":3,"iconIdx":158},{"icon":{"paths":["M553.412 325.606c0 91.58-75.849 165.821-169.412 165.821s-169.412-74.241-169.412-165.821c0-91.579 75.848-165.819 169.412-165.819s169.412 74.24 169.412 165.819zM485.649 325.606c0-54.947-45.513-99.491-101.649-99.491-56.138 0-101.647 44.544-101.647 99.491s45.509 99.492 101.647 99.492c56.137 0 101.649-44.544 101.649-99.492z","M203.427 510.558c28.952-9.109 60.004-9.668 89.279-1.613l51.342 14.135c25.632 7.057 52.819 6.566 78.167-1.408l31.873-10.027c31.206-9.822 64.678-10.423 96.23-1.737 71.962 19.81 121.681 84.049 121.681 157.218v96.239c0 54.946-45.508 99.49-101.649 99.49h-372.704c-56.138 0-101.647-44.544-101.647-99.49v-108.565c0-65.818 43.411-124.105 107.427-144.243zM274.359 572.796c-16.46-4.531-33.918-4.215-50.196 0.905-35.992 11.324-60.399 44.096-60.399 81.101v108.565c0 18.317 15.169 33.165 33.882 33.165h372.704c18.714 0 33.886-14.848 33.886-33.165v-96.239c0-43.452-29.53-81.604-72.265-93.367-18.739-5.158-38.618-4.8-57.148 1.028l-31.872 10.031c-38.024 11.959-78.804 12.698-117.251 2.112l-51.342-14.135z","M797.090 188.646c0-15.913-13.022-28.812-29.090-28.812s-29.090 12.9-29.090 28.812v100.844h-101.82c-16.064 0-29.090 12.9-29.090 28.812s13.026 28.813 29.090 28.813h101.82v100.842c0 15.915 13.022 28.813 29.090 28.813s29.090-12.898 29.090-28.813v-100.842h101.82c16.064 0 29.090-12.9 29.090-28.813s-13.026-28.812-29.090-28.812h-101.82v-100.844z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["user-add"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":530,"id":13,"name":"user-add","prevSize":32,"code":59822},"setIdx":0,"setId":3,"iconIdx":159},{"icon":{"paths":["M608 192c0-53.019-42.982-96-96-96s-96 42.981-96 96h-192c-17.673 0-32 14.327-32 32v672c0 17.673 14.327 32 32 32h576c17.673 0 32-14.327 32-32v-672c0-17.673-14.327-32-32-32h-192zM256 864v-608h96v64c0 17.673 14.327 32 32 32h256c17.673 0 32-14.327 32-32v-64h96v608h-512zM512 224c17.673 0 32-14.327 32-32s-14.327-32-32-32c-17.673 0-32 14.327-32 32s14.327 32 32 32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["clipboard"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":531,"id":12,"name":"clipboard","prevSize":32,"code":59823},"setIdx":0,"setId":3,"iconIdx":160},{"icon":{"paths":["M341.335 778.671c-17.673 0-32 14.327-32 32s14.327 32 32 32h341.332c17.673 0 32-14.327 32-32s-14.327-32-32-32h-341.332zM85.335 298.672c0-70.692 57.308-128 128-128h597.332c70.694 0 128 57.308 128 128v298.666c0 70.694-57.306 128-128 128h-597.332c-70.693 0-128-57.306-128-128v-298.666zM213.335 234.672c-35.346 0-64 28.654-64 64v298.666c0 35.349 28.654 64 64 64h597.332c35.349 0 64-28.655 64-64v-298.666c0-35.346-28.651-64-64-64h-597.332zM256 320c0-11.782 9.551-21.333 21.333-21.333h170.667c11.78 0 21.333 9.551 21.333 21.333s-9.553 21.333-21.333 21.333h-170.667c-11.782 0-21.333-9.551-21.333-21.333zM277.333 554.667c-11.782 0-21.333 9.553-21.333 21.333s9.551 21.333 21.333 21.333h85.333c11.782 0 21.333-9.553 21.333-21.333s-9.551-21.333-21.333-21.333h-85.333zM554.667 320c0-11.782 9.553-21.333 21.333-21.333h170.667c11.78 0 21.333 9.551 21.333 21.333s-9.553 21.333-21.333 21.333h-170.667c-11.78 0-21.333-9.551-21.333-21.333zM448 554.667c-11.78 0-21.333 9.553-21.333 21.333s9.553 21.333 21.333 21.333h298.667c11.78 0 21.333-9.553 21.333-21.333s-9.553-21.333-21.333-21.333h-298.667zM256 448c0-11.78 9.551-21.333 21.333-21.333h213.333c11.78 0 21.333 9.553 21.333 21.333s-9.553 21.333-21.333 21.333h-213.333c-11.782 0-21.333-9.553-21.333-21.333zM618.667 426.667c-11.78 0-21.333 9.553-21.333 21.333s9.553 21.333 21.333 21.333h128c11.78 0 21.333-9.553 21.333-21.333s-9.553-21.333-21.333-21.333h-128z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["log-view"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":532,"id":11,"name":"log-view","prevSize":32,"code":59824},"setIdx":0,"setId":3,"iconIdx":161},{"icon":{"paths":["M341.335 778.671c-17.673 0-32 14.327-32 32s14.327 32 32 32h341.332c17.673 0 32-14.327 32-32s-14.327-32-32-32h-341.332z","M85.335 298.672c0-70.692 57.308-128 128-128h597.332c70.694 0 128 57.308 128 128v298.666c0 70.694-57.306 128-128 128h-597.332c-70.693 0-128-57.306-128-128v-298.666zM213.335 234.672c-35.346 0-64 28.654-64 64v298.666c0 35.349 28.654 64 64 64h597.332c35.349 0 64-28.655 64-64v-298.666c0-35.346-28.651-64-64-64h-597.332z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["desktop"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":533,"id":10,"name":"desktop","prevSize":32,"code":59825},"setIdx":0,"setId":3,"iconIdx":162},{"icon":{"paths":["M403.11 199.401c17.543-17.543 45.987-17.543 63.531 0 17.54 17.543 17.54 45.987 0 63.53l-43.66 43.659 177.83 177.827 60.339-60.338c24.994-24.994 65.515-24.994 90.509 0l45.257 45.256-331.87 331.87-45.255-45.257c-24.994-24.994-24.994-65.515 0-90.509l60.338-60.339-177.827-177.83-43.66 43.661c-17.543 17.545-45.987 17.545-63.53 0s-17.543-45.986 0-63.529l207.999-207.999zM149.856 362.145c-42.537 42.537-42.537 111.502 0 154.041 42.001 42.001 109.771 42.53 152.421 1.583l87.335 87.339-15.077 15.074c-49.987 49.988-49.987 131.034 0 181.022l67.884 67.878c12.497 12.497 32.755 12.497 45.252 0l167.936-167.932 88.013 92.002c12.215 12.77 32.474 13.222 45.244 1.003 12.77-12.215 13.218-32.474 1.003-45.244l-88.994-93.026 163.925-163.925c12.493-12.497 12.493-32.759 0-45.257l-67.883-67.88c-49.988-49.987-131.034-49.987-181.022 0l-15.906 15.907-87.322-87.322c41.762-42.596 41.506-110.984-0.772-153.262-42.534-42.537-111.502-42.537-154.038 0l-207.999 207.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["pin"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":534,"id":9,"name":"pin","prevSize":32,"code":59826},"setIdx":0,"setId":3,"iconIdx":163},{"icon":{"paths":["M593.937 170.244c-20.864-57.726-103.155-55.816-121.318 2.816l-58.978 190.35h-221.512c-58.947 0-86.549 72.943-42.37 111.965l157.591 139.204-53.209 216.93c-14.17 57.771 51.25 101.935 99.535 67.2l177.739-127.881 177.741 127.881c48.286 34.735 113.707-9.429 99.537-67.2l-53.389-217.651 147.891-139.968c42.031-39.778 13.879-110.481-43.994-110.481h-195.439l-69.824-193.165z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["star-filled"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":535,"id":8,"name":"star-filled","prevSize":32,"code":59827},"setIdx":0,"setId":3,"iconIdx":164},{"icon":{"paths":["M472.619 172.834c18.163-58.554 100.454-60.462 121.318-2.812l69.824 192.91h195.439c57.873 0 86.025 70.608 43.994 110.335l-147.891 139.785 53.389 217.361c14.17 57.694-51.251 101.803-99.537 67.11l-177.741-127.706-177.739 127.706c-48.284 34.692-113.705-9.417-99.535-67.11l53.209-216.64-157.591-139.021c-44.179-38.976-16.577-111.82 42.37-111.82h221.512l58.978-190.098zM603.571 384.66l-69.82-192.91-58.978 190.098c-8.303 26.758-33.084 44.998-61.133 44.998h-221.512l157.591 139.025c17.834 15.731 25.456 40.047 19.787 63.125l-53.209 216.644 177.74-127.706c22.332-16.047 52.425-16.047 74.756 0l177.741 127.706-53.389-217.361c-5.478-22.319 1.455-45.854 18.167-61.649l147.887-139.785h-195.439c-26.957 0-51.025-16.868-60.19-42.186z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["star"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":536,"id":7,"name":"star","prevSize":32,"code":59828},"setIdx":0,"setId":3,"iconIdx":165},{"icon":{"paths":["M708.723 449.771c0-142.502-115.674-258.022-258.364-258.022-142.687 0-258.359 115.52-258.359 258.022s115.673 258.022 258.359 258.022c142.69 0 258.364-115.52 258.364-258.022zM654.379 699.042c-55.573 45.419-126.609 72.666-204.019 72.666-178.033 0-322.359-144.137-322.359-321.937s144.326-321.937 322.359-321.937c178.035 0 322.364 144.137 322.364 321.937 0 77.303-27.281 148.245-72.755 203.742l186.59 186.347c12.591 12.574 12.591 32.956 0 45.53-12.587 12.574-32.998 12.574-45.589 0l-186.59-186.347z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["search"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":537,"id":6,"name":"search","prevSize":32,"code":59829},"setIdx":0,"setId":3,"iconIdx":166},{"icon":{"paths":["M336 304c0-97.202 78.798-176 176-176 97.203 0 176 78.798 176 176v142.477h16c53.018 0 96 42.978 96 96v257.523c0 53.018-42.982 96-96 96h-384c-53.019 0-96-42.982-96-96v-257.523c0-53.022 42.981-96 96-96h16v-142.477zM400 446.477h224v-142.477c0-61.856-50.146-112-112-112s-112 50.144-112 112v142.477zM320 510.477c-17.673 0-32 14.327-32 32v257.523c0 17.673 14.327 32 32 32h384c17.673 0 32-14.327 32-32v-257.523c0-17.673-14.327-32-32-32h-384z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["channel-private"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":538,"id":5,"name":"channel-private","prevSize":32,"code":59830},"setIdx":0,"setId":3,"iconIdx":167},{"icon":{"paths":["M512 864c-194.404 0-352-157.598-352-352 0-194.404 157.596-352 352-352 194.406 0 352 157.596 352 352 0 194.402-157.594 352-352 352zM512 928c229.751 0 416-186.249 416-416s-186.249-416-416-416c-229.751 0-416 186.249-416 416s186.249 416 416 416zM662.626 361.373c12.497 12.497 12.497 32.758 0 45.255l-105.37 105.373 105.37 105.374c12.497 12.497 12.497 32.755 0 45.252s-32.755 12.497-45.252 0l-105.374-105.37-105.373 105.37c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l105.371-105.374-105.371-105.373c-12.497-12.497-12.497-32.758 0-45.255s32.758-12.497 45.255 0l105.373 105.371 105.374-105.371c12.497-12.497 32.755-12.497 45.252 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["input-clear"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":539,"id":4,"name":"input-clear","prevSize":32,"code":59831},"setIdx":0,"setId":3,"iconIdx":168},{"icon":{"paths":["M875.273 512c0-86.89-31.484-166.427-83.665-227.826l-496.163 496.161c61.399 52.181 140.937 83.665 227.828 83.665 194.402 0 352-157.598 352-352zM250.62 734.652l495.3-495.302c-60.659-49.597-138.18-79.349-222.647-79.349-194.406 0-352.002 157.596-352.002 352 0 84.467 29.752 161.988 79.349 222.652zM939.273 512c0 229.751-186.253 416-416 416-229.752 0-416.002-186.249-416.002-416s186.249-416 416.002-416c229.747 0 416 186.249 416 416z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["ban"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":540,"id":3,"name":"ban","prevSize":32,"code":59832},"setIdx":0,"setId":3,"iconIdx":169},{"icon":{"paths":["M368 412.435c-53.592 0-96-42.819-96-94.367s42.408-94.366 96-94.366c53.592 0 96 42.819 96 94.366s-42.408 94.367-96 94.367zM368 476.352c88.367 0 160-70.867 160-158.284s-71.633-158.282-160-158.282c-88.366 0-160 70.865-160 158.282s71.634 158.284 160 158.284zM713.6 396.606c-35.921 0-64-28.646-64-62.71s28.079-62.71 64-62.71c35.921 0 64 28.646 64 62.71s-28.079 62.71-64 62.71zM713.6 460.523c70.69 0 128-56.693 128-126.626s-57.31-126.626-128-126.626c-70.694 0-128 56.692-128 126.626s57.306 126.626 128 126.626zM197.459 526.571c27.344-8.695 56.671-9.229 84.32-1.536l48.489 13.491c24.207 6.733 49.884 6.268 73.824-1.348l30.101-9.57c29.474-9.37 61.086-9.946 90.889-1.655 67.964 18.91 114.918 80.226 114.918 150.071v91.866c0 52.45-42.982 94.967-96 94.967h-352c-53.019 0-96-42.517-96-94.967v-103.633c0-62.822 40.999-118.46 101.459-137.685zM264.451 585.98c-15.545-4.322-32.034-4.023-47.407 0.866-33.993 10.807-57.044 42.091-57.044 77.41v103.633c0 17.485 14.327 31.654 32 31.654h352c17.673 0 32-14.17 32-31.654v-91.866c0-41.476-27.887-77.892-68.245-89.122-17.702-4.924-36.476-4.582-53.978 0.981l-30.1 9.57c-35.91 11.422-74.426 12.122-110.737 2.018l-48.489-13.491zM691.2 777.685h140.8c53.018 0 96-42.923 96-95.872v-30.571c0-56.802-38.613-106.351-93.747-120.294-21.397-5.414-43.853-5.035-65.058 1.092l-16.397 4.745c-21.845 6.31-44.975 6.703-67.017 1.126l-29.807-7.539c-19.908-5.035-40.798-4.685-60.523 1.015-1.062 0.311-2.121 0.631-3.174 0.969 10.714 4.045 20.898 9.527 30.255 16.354l2.428 1.771 15.040 13.193c9.937 8.713 18.142 19.221 24.183 30.972l2.206 4.292 3.678 0.934c33.062 8.363 67.759 7.778 100.523-1.694l16.401-4.74c10.283-2.974 21.171-3.157 31.548-0.529 26.735 6.763 45.461 30.788 45.461 58.334v30.571c0 17.651-14.327 31.957-32 31.957h-140.8v63.915z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["team"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":541,"id":2,"name":"team","prevSize":32,"code":59833},"setIdx":0,"setId":3,"iconIdx":170},{"icon":{"paths":["M608 336c0-53.019-42.982-96-96-96s-96 42.981-96 96c0 53.019 42.982 96 96 96s96-42.981 96-96zM672 336c0 88.366-71.633 160-160 160-88.366 0-160-71.634-160-160s71.634-160 160-160c88.367 0 160 71.634 160 160zM412.451 551.799c-24.621-5.769-50.286-5.363-74.713 1.178-67.087 17.971-113.738 78.763-113.738 148.215v66.807c0 53.018 42.981 96 96 96h384c53.018 0 96-42.982 96-96v-58.53c0-74.3-51.149-138.825-123.49-155.78l-6.455-1.51c-25.673-6.020-52.437-5.598-77.909 1.225l-49.626 13.295c-20.378 5.457-41.788 5.794-62.327 0.981l-67.741-15.881zM354.297 614.797c14.238-3.81 29.199-4.049 43.55-0.683l67.744 15.876c30.805 7.219 62.921 6.716 93.487-1.472l49.626-13.295c15.283-4.092 31.343-4.343 46.746-0.734l6.455 1.51c43.405 10.176 74.095 48.887 74.095 93.47v58.53c0 17.673-14.327 32-32 32h-384c-17.673 0-32-14.327-32-32v-66.807c0-40.486 27.193-75.921 66.297-86.396z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["user"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":542,"id":1,"name":"user","prevSize":32,"code":59834},"setIdx":0,"setId":3,"iconIdx":171}],"height":1024,"metadata":{"name":"custom"},"preferences":{"showGlyphs":true,"showQuickUse":true,"showQuickUse2":true,"showSVGs":true,"fontPref":{"prefix":"icon-","metadata":{"fontFamily":"custom","majorVersion":1,"minorVersion":0},"metrics":{"emSize":1024,"baseline":6.25,"whitespace":50},"embed":false,"noie8":true,"ie7":false,"showSelector":false,"showMetrics":false,"showMetadata":false,"showVersion":false},"imagePref":{"prefix":"icon-","png":true,"useClassSelector":true,"color":0,"bgColor":16777215,"classSelector":".icon"},"historySize":50,"showCodes":true,"gridSize":16}} \ No newline at end of file diff --git a/app/notifications/push/index.js b/app/notifications/push/index.js index 865a6ad61..40ccbea16 100644 --- a/app/notifications/push/index.js +++ b/app/notifications/push/index.js @@ -10,7 +10,7 @@ export const onNotification = (notification) => { if (data) { try { const { - rid, name, sender, type, host + rid, name, sender, type, host, messageType } = EJSON.parse(data.ejson); const types = { @@ -24,7 +24,8 @@ export const onNotification = (notification) => { const params = { host, rid, - path: `${ types[type] }/${ roomName }` + path: `${ types[type] }/${ roomName }`, + isCall: messageType === 'jitsi_call_started' }; store.dispatch(deepLinkingOpen(params)); } catch (e) { diff --git a/app/presentation/ImageViewer/ImageComponent.js b/app/presentation/ImageViewer/ImageComponent.js index cb365f03e..cf00e4322 100644 --- a/app/presentation/ImageViewer/ImageComponent.js +++ b/app/presentation/ImageViewer/ImageComponent.js @@ -6,7 +6,7 @@ export const ImageComponent = (type) => { const { Image } = require('react-native'); Component = Image; } else { - const FastImage = require('react-native-fast-image').default; + const FastImage = require('@rocket.chat/react-native-fast-image').default; Component = FastImage; } return Component; diff --git a/app/presentation/KeyboardView.js b/app/presentation/KeyboardView.js index 9bd25191e..628213825 100644 --- a/app/presentation/KeyboardView.js +++ b/app/presentation/KeyboardView.js @@ -1,6 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'; +import { KeyboardAwareScrollView } from '@codler/react-native-keyboard-aware-scroll-view'; import scrollPersistTaps from '../utils/scrollPersistTaps'; export default class KeyboardView extends React.PureComponent { diff --git a/app/presentation/RoomItem/Actions.js b/app/presentation/RoomItem/Actions.js index 20e5efad6..c10dd716a 100644 --- a/app/presentation/RoomItem/Actions.js +++ b/app/presentation/RoomItem/Actions.js @@ -107,7 +107,7 @@ export const RightActions = React.memo(({ > <> - + {I18n.t('Hide')} diff --git a/app/presentation/RoomItem/RoomItem.js b/app/presentation/RoomItem/RoomItem.js new file mode 100644 index 000000000..d0496ef98 --- /dev/null +++ b/app/presentation/RoomItem/RoomItem.js @@ -0,0 +1,190 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { View } from 'react-native'; + +import styles from './styles'; +import Wrapper from './Wrapper'; +import UnreadBadge from '../UnreadBadge'; +import TypeIcon from './TypeIcon'; +import LastMessage from './LastMessage'; +import Title from './Title'; +import UpdatedAt from './UpdatedAt'; +import Touchable from './Touchable'; + +const RoomItem = ({ + rid, + type, + prid, + name, + avatar, + width, + avatarSize, + baseUrl, + userId, + username, + token, + showLastMessage, + status, + useRealName, + theme, + isFocused, + isGroupChat, + isRead, + date, + accessibilityLabel, + favorite, + lastMessage, + alert, + hideUnreadStatus, + unread, + userMentions, + groupMentions, + roomUpdatedAt, + testID, + swipeEnabled, + onPress, + toggleFav, + toggleRead, + hideChannel +}) => ( + + + {showLastMessage + ? ( + <> + + + + <UpdatedAt + roomUpdatedAt={roomUpdatedAt} + date={date} + theme={theme} + hideUnreadStatus={hideUnreadStatus} + alert={alert} + /> + </View> + <View style={styles.row}> + <LastMessage + lastMessage={lastMessage} + type={type} + showLastMessage={showLastMessage} + username={username} + alert={alert && !hideUnreadStatus} + useRealName={useRealName} + theme={theme} + /> + <UnreadBadge + unread={unread} + userMentions={userMentions} + groupMentions={groupMentions} + theme={theme} + /> + </View> + </> + ) + : ( + <View style={[styles.titleContainer, styles.flex]}> + <TypeIcon + type={type} + prid={prid} + status={status} + isGroupChat={isGroupChat} + theme={theme} + /> + <Title + name={name} + theme={theme} + hideUnreadStatus={hideUnreadStatus} + alert={alert} + /> + <UnreadBadge + unread={unread} + userMentions={userMentions} + groupMentions={groupMentions} + theme={theme} + /> + </View> + ) + } + </Wrapper> + </Touchable> +); + +RoomItem.propTypes = { + rid: PropTypes.string.isRequired, + type: PropTypes.string.isRequired, + prid: PropTypes.string, + name: PropTypes.string.isRequired, + avatar: PropTypes.string.isRequired, + baseUrl: PropTypes.string.isRequired, + showLastMessage: PropTypes.bool, + userId: PropTypes.string, + username: PropTypes.string, + token: PropTypes.string, + avatarSize: PropTypes.number, + testID: PropTypes.string, + width: PropTypes.number, + status: PropTypes.string, + useRealName: PropTypes.bool, + theme: PropTypes.string, + isFocused: PropTypes.bool, + isGroupChat: PropTypes.bool, + isRead: PropTypes.bool, + date: PropTypes.string, + accessibilityLabel: PropTypes.string, + lastMessage: PropTypes.object, + favorite: PropTypes.bool, + alert: PropTypes.bool, + hideUnreadStatus: PropTypes.bool, + unread: PropTypes.number, + userMentions: PropTypes.number, + groupMentions: PropTypes.number, + roomUpdatedAt: PropTypes.instanceOf(Date), + swipeEnabled: PropTypes.bool, + toggleFav: PropTypes.func, + toggleRead: PropTypes.func, + onPress: PropTypes.func, + hideChannel: PropTypes.func +}; + +RoomItem.defaultProps = { + avatarSize: 48, + status: 'offline', + swipeEnabled: true +}; + +export default RoomItem; diff --git a/app/presentation/RoomItem/Title.js b/app/presentation/RoomItem/Title.js new file mode 100644 index 000000000..6f4f848d6 --- /dev/null +++ b/app/presentation/RoomItem/Title.js @@ -0,0 +1,31 @@ +import React from 'react'; +import { Text } from 'react-native'; +import PropTypes from 'prop-types'; + +import styles from './styles'; +import { themes } from '../../constants/colors'; + +const Title = React.memo(({ + name, theme, hideUnreadStatus, alert +}) => ( + <Text + style={[ + styles.title, + alert && !hideUnreadStatus && styles.alert, + { color: themes[theme].titleText } + ]} + ellipsizeMode='tail' + numberOfLines={1} + > + {name} + </Text> +)); + +Title.propTypes = { + name: PropTypes.string, + theme: PropTypes.string, + hideUnreadStatus: PropTypes.bool, + alert: PropTypes.bool +}; + +export default Title; diff --git a/app/presentation/RoomItem/Touchable.js b/app/presentation/RoomItem/Touchable.js index 911436fe0..b0c9fe3e0 100644 --- a/app/presentation/RoomItem/Touchable.js +++ b/app/presentation/RoomItem/Touchable.js @@ -26,7 +26,8 @@ class Touchable extends React.Component { hideChannel: PropTypes.func, children: PropTypes.element, theme: PropTypes.string, - isFocused: PropTypes.bool + isFocused: PropTypes.bool, + swipeEnabled: PropTypes.bool } constructor(props) { @@ -168,7 +169,7 @@ class Touchable extends React.Component { render() { const { - testID, isRead, width, favorite, children, theme, isFocused + testID, isRead, width, favorite, children, theme, isFocused, swipeEnabled } = this.props; return ( @@ -177,6 +178,7 @@ class Touchable extends React.Component { minDeltaX={20} onGestureEvent={this._onGestureEvent} onHandlerStateChange={this._onHandlerStateChange} + enabled={swipeEnabled} > <Animated.View> <LeftActions diff --git a/app/presentation/RoomItem/UnreadBadge.js b/app/presentation/RoomItem/UnreadBadge.js deleted file mode 100644 index af745f811..000000000 --- a/app/presentation/RoomItem/UnreadBadge.js +++ /dev/null @@ -1,44 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { View, Text } from 'react-native'; - -import styles from './styles'; -import { themes } from '../../constants/colors'; - -const UnreadBadge = React.memo(({ - theme, unread, userMentions, type -}) => { - if (!unread || unread <= 0) { - return; - } - if (unread >= 1000) { - unread = '999+'; - } - const mentioned = userMentions > 0 && type !== 'd'; - - return ( - <View - style={[ - styles.unreadNumberContainer, - { backgroundColor: mentioned ? themes[theme].tintColor : themes[theme].borderColor } - ]} - > - <Text - style={[ - styles.unreadText, - { color: mentioned ? themes[theme].buttonText : themes[theme].bodyText } - ]} - >{ unread } - </Text> - </View> - ); -}); - -UnreadBadge.propTypes = { - theme: PropTypes.string, - unread: PropTypes.number, - userMentions: PropTypes.number, - type: PropTypes.string -}; - -export default UnreadBadge; diff --git a/app/presentation/RoomItem/UpdatedAt.js b/app/presentation/RoomItem/UpdatedAt.js new file mode 100644 index 000000000..667a05bf0 --- /dev/null +++ b/app/presentation/RoomItem/UpdatedAt.js @@ -0,0 +1,49 @@ +import React from 'react'; +import { Text } from 'react-native'; +import PropTypes from 'prop-types'; + +import styles from './styles'; +import { themes } from '../../constants/colors'; +import { capitalize } from '../../utils/room'; + +const UpdatedAt = React.memo(({ + roomUpdatedAt, date, theme, hideUnreadStatus, alert +}) => { + if (!roomUpdatedAt) { + return null; + } + return ( + <Text + style={[ + styles.date, + { + color: + themes[theme] + .auxiliaryText + }, + alert && !hideUnreadStatus && [ + styles.updateAlert, + { + color: + themes[theme] + .tintColor + } + ] + ]} + ellipsizeMode='tail' + numberOfLines={1} + > + {capitalize(date)} + </Text> + ); +}); + +UpdatedAt.propTypes = { + roomUpdatedAt: PropTypes.instanceOf(Date), + date: PropTypes.string, + theme: PropTypes.string, + hideUnreadStatus: PropTypes.bool, + alert: PropTypes.bool +}; + +export default UpdatedAt; diff --git a/app/presentation/RoomItem/Wrapper.js b/app/presentation/RoomItem/Wrapper.js new file mode 100644 index 000000000..a7473cae2 --- /dev/null +++ b/app/presentation/RoomItem/Wrapper.js @@ -0,0 +1,58 @@ +import React from 'react'; +import { View } from 'react-native'; +import PropTypes from 'prop-types'; + +import styles from './styles'; +import { themes } from '../../constants/colors'; +import Avatar from '../../containers/Avatar'; + +const RoomItemInner = ({ + accessibilityLabel, + avatar, + avatarSize, + type, + baseUrl, + userId, + token, + theme, + children +}) => ( + <View + style={styles.container} + accessibilityLabel={accessibilityLabel} + > + <Avatar + text={avatar} + size={avatarSize} + type={type} + baseUrl={baseUrl} + style={styles.avatar} + userId={userId} + token={token} + /> + <View + style={[ + styles.centerContainer, + { + borderColor: themes[theme].separatorColor + } + ]} + > + {children} + </View> + </View> +); + +RoomItemInner.propTypes = { + accessibilityLabel: PropTypes.string, + avatar: PropTypes.string, + avatarSize: PropTypes.number, + type: PropTypes.string, + baseUrl: PropTypes.string, + userId: PropTypes.string, + token: PropTypes.string, + theme: PropTypes.string, + children: PropTypes.element +}; + +export default RoomItemInner; diff --git a/app/presentation/RoomItem/index.js b/app/presentation/RoomItem/index.js index 1b3ee93f2..395d8d81e 100644 --- a/app/presentation/RoomItem/index.js +++ b/app/presentation/RoomItem/index.js @@ -1,97 +1,89 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; import PropTypes from 'prop-types'; -import { View, Text } from 'react-native'; import { connect } from 'react-redux'; -import Avatar from '../../containers/Avatar'; import I18n from '../../i18n'; -import styles, { ROW_HEIGHT } from './styles'; -import UnreadBadge from './UnreadBadge'; -import TypeIcon from './TypeIcon'; -import LastMessage from './LastMessage'; -import { capitalize, formatDate } from '../../utils/room'; -import Touchable from './Touchable'; -import { themes } from '../../constants/colors'; +import { ROW_HEIGHT } from './styles'; +import { formatDate } from '../../utils/room'; +import RoomItem from './RoomItem'; export { ROW_HEIGHT }; const attrs = [ - 'name', - 'unread', - 'userMentions', - 'showLastMessage', - 'useRealName', - 'alert', - 'type', 'width', - 'isRead', - 'favorite', 'status', 'connected', 'theme', - 'isFocused' + 'isFocused', + 'forceUpdate', + 'showLastMessage' ]; -const arePropsEqual = (oldProps, newProps) => { - const { _updatedAt: _updatedAtOld } = oldProps; - const { _updatedAt: _updatedAtNew } = newProps; - if (_updatedAtOld && _updatedAtNew && _updatedAtOld.toISOString() !== _updatedAtNew.toISOString()) { - return false; - } - return attrs.every(key => oldProps[key] === newProps[key]); -}; +const arePropsEqual = (oldProps, newProps) => attrs.every(key => oldProps[key] === newProps[key]); -const RoomItem = React.memo(({ +const RoomItemContainer = React.memo(({ + item, onPress, width, - favorite, toggleFav, - isRead, - rid, toggleRead, hideChannel, testID, - unread, - userMentions, - name, - _updatedAt, - alert, - type, avatarSize, baseUrl, userId, username, token, id, - prid, showLastMessage, - hideUnreadStatus, - lastMessage, status, - avatar, useRealName, getUserPresence, - isGroupChat, connected, theme, - isFocused + isFocused, + getRoomTitle, + getRoomAvatar, + getIsGroupChat, + getIsRead, + swipeEnabled }) => { + const [, setForceUpdate] = useState(1); + useEffect(() => { - if (connected && type === 'd' && id) { + if (connected && item.t === 'd' && id) { getUserPresence(id); } }, [connected]); - const date = lastMessage && formatDate(lastMessage.ts); + useEffect(() => { + if (item?.observe) { + const observable = item.observe(); + const subscription = observable?.subscribe?.(() => { + setForceUpdate(prevForceUpdate => prevForceUpdate + 1); + }); + + return () => { + subscription?.unsubscribe?.(); + }; + } + }, []); + + const name = getRoomTitle(item); + const avatar = getRoomAvatar(item); + const isGroupChat = getIsGroupChat(item); + const isRead = getIsRead(item); + const _onPress = () => onPress(item); + const date = item.lastMessage?.ts && formatDate(item.lastMessage.ts); let accessibilityLabel = name; - if (unread === 1) { - accessibilityLabel += `, ${ unread } ${ I18n.t('alert') }`; - } else if (unread > 1) { - accessibilityLabel += `, ${ unread } ${ I18n.t('alerts') }`; + if (item.unread === 1) { + accessibilityLabel += `, ${ item.unread } ${ I18n.t('alert') }`; + } else if (item.unread > 1) { + accessibilityLabel += `, ${ item.unread } ${ I18n.t('alerts') }`; } - if (userMentions > 0) { + if (item.userMentions > 0) { accessibilityLabel += `, ${ I18n.t('you_were_mentioned') }`; } @@ -100,120 +92,50 @@ const RoomItem = React.memo(({ } return ( - <Touchable - onPress={onPress} - width={width} - favorite={favorite} - toggleFav={toggleFav} + <RoomItem + name={name} + avatar={avatar} + isGroupChat={isGroupChat} isRead={isRead} - rid={rid} + onPress={_onPress} + date={date} + accessibilityLabel={accessibilityLabel} + userMentions={item.userMentions} + width={width} + favorite={item.f} + toggleFav={toggleFav} + rid={item.rid} toggleRead={toggleRead} hideChannel={hideChannel} testID={testID} - type={type} + type={item.t} theme={theme} isFocused={isFocused} - > - <View - style={styles.container} - accessibilityLabel={accessibilityLabel} - > - <Avatar - text={avatar} - size={avatarSize} - type={type} - baseUrl={baseUrl} - style={styles.avatar} - userId={userId} - token={token} - /> - <View - style={[ - styles.centerContainer, - { - borderColor: themes[theme].separatorColor - } - ]} - > - <View style={styles.titleContainer}> - <TypeIcon - type={type} - prid={prid} - status={status} - isGroupChat={isGroupChat} - theme={theme} - /> - <Text - style={[ - styles.title, - alert && !hideUnreadStatus && styles.alert, - { color: themes[theme].titleText } - ]} - ellipsizeMode='tail' - numberOfLines={1} - > - {name} - </Text> - {_updatedAt ? ( - <Text - style={[ - styles.date, - { - color: - themes[theme] - .auxiliaryText - }, - alert && !hideUnreadStatus && [ - styles.updateAlert, - { - color: - themes[theme] - .tintColor - } - ] - ]} - ellipsizeMode='tail' - numberOfLines={1} - > - {capitalize(date)} - </Text> - ) : null} - </View> - <View style={styles.row}> - <LastMessage - lastMessage={lastMessage} - type={type} - showLastMessage={showLastMessage} - username={username} - alert={alert && !hideUnreadStatus} - useRealName={useRealName} - theme={theme} - /> - <UnreadBadge - unread={unread} - userMentions={userMentions} - type={type} - theme={theme} - /> - </View> - </View> - </View> - </Touchable> + size={avatarSize} + baseUrl={baseUrl} + userId={userId} + token={token} + prid={item.prid} + status={status} + hideUnreadStatus={item.hideUnreadStatus} + alert={item.alert} + roomUpdatedAt={item.roomUpdatedAt} + lastMessage={item.lastMessage} + showLastMessage={showLastMessage} + username={username} + useRealName={useRealName} + unread={item.unread} + groupMentions={item.groupMentions} + swipeEnabled={swipeEnabled} + /> ); }, arePropsEqual); -RoomItem.propTypes = { - type: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, +RoomItemContainer.propTypes = { + item: PropTypes.object.isRequired, baseUrl: PropTypes.string.isRequired, showLastMessage: PropTypes.bool, - _updatedAt: PropTypes.string, - lastMessage: PropTypes.object, - alert: PropTypes.bool, - unread: PropTypes.number, - userMentions: PropTypes.number, id: PropTypes.string, - prid: PropTypes.string, onPress: PropTypes.func, userId: PropTypes.string, username: PropTypes.string, @@ -221,27 +143,31 @@ RoomItem.propTypes = { avatarSize: PropTypes.number, testID: PropTypes.string, width: PropTypes.number, - favorite: PropTypes.bool, - isRead: PropTypes.bool, - rid: PropTypes.string, status: PropTypes.string, toggleFav: PropTypes.func, toggleRead: PropTypes.func, hideChannel: PropTypes.func, - avatar: PropTypes.bool, - hideUnreadStatus: PropTypes.bool, useRealName: PropTypes.bool, getUserPresence: PropTypes.func, connected: PropTypes.bool, - isGroupChat: PropTypes.bool, theme: PropTypes.string, - isFocused: PropTypes.bool + isFocused: PropTypes.bool, + getRoomTitle: PropTypes.func, + getRoomAvatar: PropTypes.func, + getIsGroupChat: PropTypes.func, + getIsRead: PropTypes.func, + swipeEnabled: PropTypes.bool }; -RoomItem.defaultProps = { +RoomItemContainer.defaultProps = { avatarSize: 48, status: 'offline', - getUserPresence: () => {} + getUserPresence: () => {}, + getRoomTitle: () => 'title', + getRoomAvatar: () => '', + getIsGroupChat: () => false, + getIsRead: () => false, + swipeEnabled: true }; const mapStateToProps = (state, ownProps) => { @@ -260,4 +186,4 @@ const mapStateToProps = (state, ownProps) => { }; }; -export default connect(mapStateToProps)(RoomItem); +export default connect(mapStateToProps)(RoomItemContainer); diff --git a/app/presentation/RoomItem/styles.js b/app/presentation/RoomItem/styles.js index 93c70a845..fb110e4ce 100644 --- a/app/presentation/RoomItem/styles.js +++ b/app/presentation/RoomItem/styles.js @@ -8,6 +8,9 @@ export const SMALL_SWIPE = ACTION_WIDTH / 2; export const LONG_SWIPE = ACTION_WIDTH * 3; export default StyleSheet.create({ + flex: { + flex: 1 + }, container: { flexDirection: 'row', alignItems: 'center', @@ -48,23 +51,6 @@ export default StyleSheet.create({ updateAlert: { ...sharedStyles.textSemibold }, - unreadNumberContainer: { - minWidth: 21, - height: 21, - paddingVertical: 3, - paddingHorizontal: 5, - borderRadius: 10.5, - alignItems: 'center', - justifyContent: 'center', - marginLeft: 10 - }, - unreadText: { - overflow: 'hidden', - fontSize: 13, - ...sharedStyles.textMedium, - letterSpacing: 0.56, - textAlign: 'center' - }, status: { marginLeft: 4, marginRight: 7, diff --git a/app/presentation/ServerItem/index.js b/app/presentation/ServerItem/index.js index 094b86a94..53163a43c 100644 --- a/app/presentation/ServerItem/index.js +++ b/app/presentation/ServerItem/index.js @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { View, Text } from 'react-native'; -import FastImage from 'react-native-fast-image'; +import FastImage from '@rocket.chat/react-native-fast-image'; import Touch from '../../utils/touch'; import Check from '../../containers/Check'; diff --git a/app/presentation/UnreadBadge.js b/app/presentation/UnreadBadge.js new file mode 100644 index 000000000..88f7db416 --- /dev/null +++ b/app/presentation/UnreadBadge.js @@ -0,0 +1,73 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { View, Text, StyleSheet } from 'react-native'; + +import sharedStyles from '../views/Styles'; +import { themes } from '../constants/colors'; + +const styles = StyleSheet.create({ + unreadNumberContainer: { + minWidth: 21, + height: 21, + paddingVertical: 3, + paddingHorizontal: 5, + borderRadius: 10.5, + alignItems: 'center', + justifyContent: 'center', + marginLeft: 10 + }, + unreadText: { + overflow: 'hidden', + fontSize: 13, + ...sharedStyles.textMedium, + letterSpacing: 0.56, + textAlign: 'center' + } +}); + +const UnreadBadge = React.memo(({ + theme, unread, userMentions, groupMentions, style +}) => { + if (!unread || unread <= 0) { + return; + } + if (unread >= 1000) { + unread = '999+'; + } + + let backgroundColor = themes[theme].unreadBackground; + const color = themes[theme].buttonText; + if (userMentions > 0) { + backgroundColor = themes[theme].mentionMeColor; + } else if (groupMentions > 0) { + backgroundColor = themes[theme].mentionGroupColor; + } + + return ( + <View + style={[ + styles.unreadNumberContainer, + { backgroundColor }, + style + ]} + > + <Text + style={[ + styles.unreadText, + { color } + ]} + >{unread} + </Text> + </View> + ); +}); + +UnreadBadge.propTypes = { + theme: PropTypes.string, + unread: PropTypes.number, + userMentions: PropTypes.number, + groupMentions: PropTypes.number, + style: PropTypes.object +}; + +export default UnreadBadge; diff --git a/app/presentation/UserItem.js b/app/presentation/UserItem.js index 1f536af06..fb61e2bc9 100644 --- a/app/presentation/UserItem.js +++ b/app/presentation/UserItem.js @@ -1,13 +1,14 @@ import React from 'react'; -import { Text, View, StyleSheet } from 'react-native'; +import { + Text, View, StyleSheet, Pressable +} from 'react-native'; import PropTypes from 'prop-types'; import Avatar from '../containers/Avatar'; import { CustomIcon } from '../lib/Icons'; import sharedStyles from '../views/Styles'; import { themes } from '../constants/colors'; -import Touch from '../utils/touch'; -import LongPress from '../utils/longPress'; +import { isIOS } from '../utils/deviceInfo'; const styles = StyleSheet.create({ button: { @@ -43,23 +44,28 @@ const styles = StyleSheet.create({ const UserItem = ({ name, username, onPress, testID, onLongPress, style, icon, baseUrl, user, theme }) => ( - <LongPress onLongPress={onLongPress}> - <Touch - onPress={onPress} - style={{ backgroundColor: themes[theme].backgroundColor }} - testID={testID} - theme={theme} - > - <View style={[styles.container, styles.button, style]}> - <Avatar text={username} size={30} type='d' style={styles.avatar} baseUrl={baseUrl} userId={user.id} token={user.token} /> - <View style={styles.textContainer}> - <Text style={[styles.name, { color: themes[theme].titleText }]} numberOfLines={1}>{name}</Text> - <Text style={[styles.username, { color: themes[theme].auxiliaryText }]} numberOfLines={1}>@{username}</Text> - </View> - {icon ? <CustomIcon name={icon} size={22} style={[styles.icon, { color: themes[theme].actionTintColor }]} /> : null} + <Pressable + onPress={onPress} + onLongPress={onLongPress} + testID={testID} + android_ripple={{ + color: themes[theme].bannerBackground + }} + style={({ pressed }) => ({ + backgroundColor: isIOS && pressed + ? themes[theme].bannerBackground + : 'transparent' + })} + > + <View style={[styles.container, styles.button, style]}> + <Avatar text={username} size={30} type='d' style={styles.avatar} baseUrl={baseUrl} userId={user.id} token={user.token} /> + <View style={styles.textContainer}> + <Text style={[styles.name, { color: themes[theme].titleText }]} numberOfLines={1}>{name}</Text> + <Text style={[styles.username, { color: themes[theme].auxiliaryText }]} numberOfLines={1}>@{username}</Text> </View> - </Touch> - </LongPress> + {icon ? <CustomIcon name={icon} size={22} style={[styles.icon, { color: themes[theme].actionTintColor }]} /> : null} + </View> + </Pressable> ); UserItem.propTypes = { diff --git a/app/reducers/index.js b/app/reducers/index.js index 1ac810c33..968254ffd 100644 --- a/app/reducers/index.js +++ b/app/reducers/index.js @@ -16,6 +16,7 @@ import activeUsers from './activeUsers'; import usersTyping from './usersTyping'; import inviteLinks from './inviteLinks'; import createDiscussion from './createDiscussion'; +import inquiry from './inquiry'; export default combineReducers({ settings, @@ -34,5 +35,6 @@ export default combineReducers({ activeUsers, usersTyping, inviteLinks, - createDiscussion + createDiscussion, + inquiry }); diff --git a/app/reducers/inquiry.js b/app/reducers/inquiry.js new file mode 100644 index 000000000..230280c83 --- /dev/null +++ b/app/reducers/inquiry.js @@ -0,0 +1,51 @@ +import { INQUIRY } from '../actions/actionsTypes'; + +const initialState = { + enabled: false, + queued: [], + error: {} +}; + +export default function inquiry(state = initialState, action) { + switch (action.type) { + case INQUIRY.SUCCESS: + return { + ...state, + queued: action.inquiries + }; + case INQUIRY.FAILURE: + return { + ...state, + error: action.error + }; + case INQUIRY.SET_ENABLED: + return { + ...state, + enabled: action.enabled + }; + case INQUIRY.QUEUE_ADD: + return { + ...state, + queued: [...state.queued, action.inquiry] + }; + case INQUIRY.QUEUE_UPDATE: + return { + ...state, + queued: state.queued.map((item) => { + if (item._id === action.inquiry._id) { + return action.inquiry; + } + return item; + }) + }; + case INQUIRY.QUEUE_REMOVE: + return { + ...state, + queued: state.queued.filter(({ _id }) => _id !== action.inquiryId) + }; + case INQUIRY.RESET: + return initialState; + default: + return state; + } +} diff --git a/app/sagas/createChannel.js b/app/sagas/createChannel.js index 062a0092b..2c642006c 100644 --- a/app/sagas/createChannel.js +++ b/app/sagas/createChannel.js @@ -10,6 +10,7 @@ import RocketChat from '../lib/rocketchat'; import Navigation from '../lib/Navigation'; import database from '../lib/database'; import I18n from '../i18n'; +import { logEvent, events } from '../utils/log'; import { goRoom } from '../utils/goRoom'; const createChannel = function createChannel(data) { @@ -29,11 +30,14 @@ const handleRequest = function* handleRequest({ data }) { let sub; if (data.group) { + logEvent(events.SELECTED_USERS_CREATE_GROUP); const result = yield call(createGroupChat); if (result.success) { ({ room: sub } = result); } } else { + const { type, readOnly, broadcast } = data; + logEvent(events.CREATE_CHANNEL_CREATE, { type: type ? 'private' : 'public', readOnly, broadcast }); sub = yield call(createChannel, data); } @@ -52,6 +56,7 @@ const handleRequest = function* handleRequest({ data }) { yield put(createChannelSuccess(sub)); } catch (err) { + logEvent(events[data.group ? 'SELECTED_USERS_CREATE_GROUP_F' : 'CREATE_CHANNEL_CREATE_F']); yield put(createChannelFailure(err)); } }; diff --git a/app/sagas/createDiscussion.js b/app/sagas/createDiscussion.js index 1e53e57d4..a185e6671 100644 --- a/app/sagas/createDiscussion.js +++ b/app/sagas/createDiscussion.js @@ -7,12 +7,14 @@ import { CREATE_DISCUSSION, LOGIN } from '../actions/actionsTypes'; import { createDiscussionSuccess, createDiscussionFailure } from '../actions/createDiscussion'; import RocketChat from '../lib/rocketchat'; import database from '../lib/database'; +import { logEvent, events } from '../utils/log'; const create = function* create(data) { return yield RocketChat.createDiscussion(data); }; const handleRequest = function* handleRequest({ data }) { + logEvent(events.CREATE_DISCUSSION_CREATE); try { const auth = yield select(state => state.login.isAuthenticated); if (!auth) { @@ -35,12 +37,13 @@ const handleRequest = function* handleRequest({ data }) { } catch { // do nothing } - yield put(createDiscussionSuccess(sub)); } else { + logEvent(events.CREATE_DISCUSSION_CREATE_F); yield put(createDiscussionFailure(result)); } } catch (err) { + logEvent(events.CREATE_DISCUSSION_CREATE_F); yield put(createDiscussionFailure(err)); } }; diff --git a/app/sagas/deepLinking.js b/app/sagas/deepLinking.js index 2069cbd07..b650a06a9 100644 --- a/app/sagas/deepLinking.js +++ b/app/sagas/deepLinking.js @@ -5,14 +5,17 @@ import RNUserDefaults from 'rn-user-defaults'; import Navigation from '../lib/Navigation'; import * as types from '../actions/actionsTypes'; -import { selectServerRequest } from '../actions/server'; +import { selectServerRequest, serverInitAdd } from '../actions/server'; import { inviteLinksSetToken, inviteLinksRequest } from '../actions/inviteLinks'; import database from '../lib/database'; import RocketChat from '../lib/rocketchat'; import EventEmitter from '../utils/events'; -import { appStart, ROOT_INSIDE } from '../actions/app'; +import { + appStart, ROOT_INSIDE, ROOT_NEW_SERVER, appInit +} from '../actions/app'; import { localAuthenticate } from '../utils/localAuthentication'; import { goRoom } from '../utils/goRoom'; +import callJitsi from '../lib/methods/callJitsi'; const roomTypes = { channel: 'c', direct: 'd', group: 'p', channels: 'l' @@ -48,7 +51,11 @@ const navigate = function* navigate({ params }) { roomUserId: RocketChat.getUidDirectMessage(room), ...room }; - goRoom({ item, isMasterDetail }); + yield goRoom({ item, isMasterDetail }); + + if (params.isCall) { + callJitsi(item.rid); + } } } else { yield handleInviteLink({ params }); @@ -56,14 +63,41 @@ const navigate = function* navigate({ params }) { } }; +const fallbackNavigation = function* fallbackNavigation() { + const currentRoot = yield select(state => state.app.root); + if (currentRoot) { + return; + } + yield put(appInit()); +}; + const handleOpen = function* handleOpen({ params }) { - if (!params.host) { + const serversDB = database.servers; + const serversCollection = serversDB.collections.get('servers'); + + let { host } = params; + if (params.isCall && !host) { + const servers = yield serversCollection.query().fetch(); + // search from which server is that call + servers.forEach(({ uniqueID, id }) => { + if (params.path.includes(uniqueID)) { + host = id; + } + }); + } + + // If there's no host on the deep link params and the app is opened, just call appInit() + if (!host) { + yield fallbackNavigation(); return; } - let { host } = params; + // If there's host, continue if (!/^(http|https)/.test(host)) { - host = `https://${ params.host }`; + host = `https://${ host }`; + } else { + // Notification should always come from https + host = host.replace('http://', 'https://'); } // remove last "/" from host if (host.slice(-1) === '/') { @@ -87,8 +121,6 @@ const handleOpen = function* handleOpen({ params }) { yield navigate({ params }); } else { // search if deep link's server already exists - const serversDB = database.servers; - const serversCollection = serversDB.collections.get('servers'); try { const servers = yield serversCollection.find(host); if (servers && user) { @@ -104,9 +136,12 @@ const handleOpen = function* handleOpen({ params }) { // if deep link is from a different server const result = yield RocketChat.getServerInfo(host); if (!result.success) { + // Fallback to prevent the app from being stuck on splash screen + yield fallbackNavigation(); return; } - Navigation.navigate('NewServerView', { previousServer: server }); + yield put(appStart({ root: ROOT_NEW_SERVER })); + yield put(serverInitAdd(server)); yield delay(1000); EventEmitter.emit('NewServer', { server: host }); diff --git a/app/sagas/index.js b/app/sagas/index.js index 27886be83..772df5717 100644 --- a/app/sagas/index.js +++ b/app/sagas/index.js @@ -10,6 +10,7 @@ import state from './state'; import deepLinking from './deepLinking'; import inviteLinks from './inviteLinks'; import createDiscussion from './createDiscussion'; +import inquiry from './inquiry'; const root = function* root() { yield all([ @@ -23,7 +24,8 @@ const root = function* root() { state(), deepLinking(), inviteLinks(), - createDiscussion() + createDiscussion(), + inquiry() ]); }; diff --git a/app/sagas/inquiry.js b/app/sagas/inquiry.js new file mode 100644 index 000000000..9ee7e27fe --- /dev/null +++ b/app/sagas/inquiry.js @@ -0,0 +1,38 @@ +import { put, takeLatest, select } from 'redux-saga/effects'; + +import * as types from '../actions/actionsTypes'; +import RocketChat from '../lib/rocketchat'; +import { inquirySuccess, inquiryFailure, inquirySetEnabled } from '../actions/inquiry'; + +const handleRequest = function* handleRequest() { + try { + const routingConfig = yield RocketChat.getRoutingConfig(); + const statusLivechat = yield select(state => state.login.user.statusLivechat); + // if routingConfig showQueue is enabled and omnichannel is enabled + const showQueue = routingConfig.showQueue && statusLivechat === 'available'; + + if (showQueue) { + // get all the current chats on the queue + const result = yield RocketChat.getInquiriesQueued(); + if (result.success) { + const { inquiries } = result; + + // subscribe to inquiry queue changes + RocketChat.subscribeInquiry(); + + // put request result on redux state + yield put(inquirySuccess(inquiries)); + } + } + + // set enabled to know if we should show the queue button + yield put(inquirySetEnabled(showQueue)); + } catch (e) { + yield put(inquiryFailure(e)); + } +}; + +const root = function* root() { + yield takeLatest(types.INQUIRY.REQUEST, handleRequest); +}; +export default root; diff --git a/app/sagas/login.js b/app/sagas/login.js index 587b9b7ba..01ab28453 100644 --- a/app/sagas/login.js +++ b/app/sagas/login.js @@ -15,9 +15,10 @@ import { loginFailure, loginSuccess, setUser, logout } from '../actions/login'; import { roomsRequest } from '../actions/rooms'; +import { inquiryRequest } from '../actions/inquiry'; import { toMomentLocale } from '../utils/moment'; import RocketChat from '../lib/rocketchat'; -import log from '../utils/log'; +import log, { logEvent, events } from '../utils/log'; import I18n from '../i18n'; import database from '../lib/database'; import EventEmitter from '../utils/events'; @@ -32,6 +33,7 @@ const loginCall = args => RocketChat.login(args); const logoutCall = args => RocketChat.logout(args); const handleLoginRequest = function* handleLoginRequest({ credentials, logoutOnError = false }) { + logEvent(events.LOGIN_DEFAULT_LOGIN); try { let result; if (credentials.resume) { @@ -52,6 +54,7 @@ const handleLoginRequest = function* handleLoginRequest({ credentials, logoutOnE if (logoutOnError && (e.data && e.data.message && /you've been logged out by the server/i.test(e.data.message))) { yield put(logout(true)); } else { + logEvent(events.LOGIN_DEFAULT_LOGIN_F); yield put(loginFailure(e)); } } @@ -91,6 +94,7 @@ const handleLoginSuccess = function* handleLoginSuccess({ user }) { const server = yield select(getServer); yield put(roomsRequest()); + yield put(inquiryRequest()); yield fork(fetchPermissions); yield fork(fetchCustomEmojis); yield fork(fetchRoles); @@ -204,6 +208,10 @@ const handleSetUser = function* handleSetUser({ user }) { const userId = yield select(state => state.login.user.id); yield put(setActiveUsers({ [userId]: user })); } + + if (user && user.statusLivechat) { + yield put(inquiryRequest()); + } }; const root = function* root() { diff --git a/app/sagas/room.js b/app/sagas/room.js index c7402f93a..3b1b321ad 100644 --- a/app/sagas/room.js +++ b/app/sagas/room.js @@ -8,7 +8,7 @@ import Navigation from '../lib/Navigation'; import * as types from '../actions/actionsTypes'; import { removedRoom } from '../actions/room'; import RocketChat from '../lib/rocketchat'; -import log from '../utils/log'; +import log, { logEvent, events } from '../utils/log'; import I18n from '../i18n'; import { showErrorAlert } from '../utils/info'; @@ -48,12 +48,14 @@ const handleRemovedRoom = function* handleRemovedRoom() { }; const handleLeaveRoom = function* handleLeaveRoom({ rid, t }) { + logEvent(events.RA_LEAVE); try { const result = yield RocketChat.leaveRoom(rid, t); if (result.success) { yield handleRemovedRoom(); } } catch (e) { + logEvent(events.RA_LEAVE_F); if (e.data && e.data.errorType === 'error-you-are-last-owner') { Alert.alert(I18n.t('Oops'), I18n.t(e.data.errorType)); } else { @@ -63,12 +65,14 @@ const handleLeaveRoom = function* handleLeaveRoom({ rid, t }) { }; const handleDeleteRoom = function* handleDeleteRoom({ rid, t }) { + logEvent(events.RI_EDIT_DELETE); try { const result = yield RocketChat.deleteRoom(rid, t); if (result.success) { yield handleRemovedRoom(); } } catch (e) { + logEvent(events.RI_EDIT_DELETE_F); Alert.alert(I18n.t('Oops'), I18n.t('There_was_an_error_while_action', { action: I18n.t('deleting_room') })); } }; diff --git a/app/sagas/selectServer.js b/app/sagas/selectServer.js index 429b2642c..51728b8a8 100644 --- a/app/sagas/selectServer.js +++ b/app/sagas/selectServer.js @@ -19,6 +19,7 @@ import I18n from '../i18n'; import { SERVERS, TOKEN, SERVER_URL } from '../constants/userDefaults'; import { BASIC_AUTH_KEY, setBasicAuth } from '../utils/fetch'; import { appStart, ROOT_INSIDE, ROOT_OUTSIDE } from '../actions/app'; +import { inquiryReset } from '../actions/inquiry'; const getServerInfo = function* getServerInfo({ server, raiseError = true }) { try { @@ -65,6 +66,7 @@ const getServerInfo = function* getServerInfo({ server, raiseError = true }) { const handleSelectServer = function* handleSelectServer({ server, version, fetchVersion }) { try { + yield put(inquiryReset()); const serversDB = database.servers; yield RNUserDefaults.set('currentServer', server); const userId = yield RNUserDefaults.get(`${ RocketChat.TOKEN_KEY }-${ server }`); diff --git a/app/selectors/inquiry.js b/app/selectors/inquiry.js new file mode 100644 index 000000000..baeb09ef8 --- /dev/null +++ b/app/selectors/inquiry.js @@ -0,0 +1,8 @@ +import { createSelector } from 'reselect'; + +const getInquiryQueue = state => state.inquiry.queued; + +export const getInquiryQueueSelector = createSelector( + [getInquiryQueue], + queue => queue +); diff --git a/app/stacks/InsideStack.js b/app/stacks/InsideStack.js index e29c39dd9..e9a4a7a74 100644 --- a/app/stacks/InsideStack.js +++ b/app/stacks/InsideStack.js @@ -30,6 +30,7 @@ import PickerView from '../views/PickerView'; import ThreadMessagesView from '../views/ThreadMessagesView'; import MarkdownTableView from '../views/MarkdownTableView'; import ReadReceiptsView from '../views/ReadReceiptView'; +import QueueListView from '../views/QueueListView'; // Profile Stack import ProfileView from '../views/ProfileView'; @@ -112,7 +113,6 @@ const ChatsStackNavigator = () => { <ChatsStack.Screen name='MessagesView' component={MessagesView} - options={MessagesView.navigationOptions} /> <ChatsStack.Screen name='AutoTranslateView' @@ -164,6 +164,11 @@ const ChatsStackNavigator = () => { component={ReadReceiptsView} options={ReadReceiptsView.navigationOptions} /> + <ChatsStack.Screen + name='QueueListView' + component={QueueListView} + options={QueueListView.navigationOptions} + /> </ChatsStack.Navigator> ); }; diff --git a/app/stacks/MasterDetailStack/index.js b/app/stacks/MasterDetailStack/index.js index 0b27d89df..800bad1d7 100644 --- a/app/stacks/MasterDetailStack/index.js +++ b/app/stacks/MasterDetailStack/index.js @@ -41,6 +41,7 @@ import ScreenLockConfigView from '../../views/ScreenLockConfigView'; import AdminPanelView from '../../views/AdminPanelView'; import NewMessageView from '../../views/NewMessageView'; import CreateChannelView from '../../views/CreateChannelView'; +import QueueListView from '../../views/QueueListView'; // InsideStackNavigator import AttachmentView from '../../views/AttachmentView'; @@ -139,7 +140,6 @@ const ModalStackNavigator = React.memo(({ navigation }) => { <ModalStack.Screen name='MessagesView' component={MessagesView} - options={MessagesView.navigationOptions} /> <ModalStack.Screen name='AutoTranslateView' @@ -151,6 +151,11 @@ const ModalStackNavigator = React.memo(({ navigation }) => { component={DirectoryView} options={props => DirectoryView.navigationOptions({ ...props, isMasterDetail: true })} /> + <ModalStack.Screen + name='QueueListView' + component={QueueListView} + options={props => QueueListView.navigationOptions({ ...props, isMasterDetail: true })} + /> <ModalStack.Screen name='NotificationPrefView' component={NotificationPrefView} @@ -189,7 +194,7 @@ const ModalStackNavigator = React.memo(({ navigation }) => { <ModalStack.Screen name='ReadReceiptsView' component={ReadReceiptsView} - options={ReadReceiptsView.navigationOptions} + options={props => ReadReceiptsView.navigationOptions({ ...props, isMasterDetail: true })} /> <ModalStack.Screen name='SettingsView' diff --git a/app/utils/log/events.js b/app/utils/log/events.js new file mode 100644 index 000000000..c6d51d7e2 --- /dev/null +++ b/app/utils/log/events.js @@ -0,0 +1,290 @@ +export default { + // ONBOARDING VIEW + ONBOARD_JOIN_A_WORKSPACE: 'onboard_join_a_workspace', + ONBOARD_CREATE_NEW_WORKSPACE: 'onboard_create_new_workspace', + ONBOARD_CREATE_NEW_WORKSPACE_F: 'onboard_create_new_workspace_f', + + // NEW SERVER VIEW + NEWSERVER_CONNECT_TO_WORKSPACE: 'newserver_connect_to_workspace', + NEWSERVER_CONNECT_TO_WORKSPACE_F: 'newserver_connect_to_workspace_f', + NEWSERVER_JOIN_OPEN_WORKSPACE: 'newserver_join_open_workspace', + + // LOGIN VIEW + LOGIN_DEFAULT_LOGIN: 'login_default_login', + LOGIN_DEFAULT_LOGIN_F: 'login_default_login_f', + + // FORGOT PASSWORD VIEW + FP_FORGOT_PASSWORD: 'fp_forgot_password', + FP_FORGOT_PASSWORD_F: 'fp_forgot_password_f', + + // REGISTER VIEW + REGISTER_DEFAULT_SIGN_UP: 'register_default_sign_up', + REGISTER_DEFAULT_SIGN_UP_F: 'register_default_sign_up_f', + + // LOGIN AND REGISTER VIEW + ENTER_WITH_FACEBOOK: 'enter_with_facebook', + ENTER_WITH_GITHUB: 'enter_with_github', + ENTER_WITH_GITLAB: 'enter_with_gitlab', + ENTER_WITH_LINKEDIN: 'enter_with_linkedin', + ENTER_WITH_GOOGLE: 'enter_with_google', + ENTER_WITH_METEOR: 'enter_with_meteor', + ENTER_WITH_TWITTER: 'enter_with_twitter', + ENTER_WITH_WORDPRESS: 'enter_with_wordpress', + ENTER_WITH_CUSTOM_OAUTH: 'enter_with_custom_oauth', + ENTER_WITH_SAML: 'enter_with_saml', + ENTER_WITH_CAS: 'enter_with_cas', + ENTER_WITH_APPLE: 'enter_with_apple', + ENTER_WITH_APPLE_F: 'enter_with_apple_f', + + // SIDEBAR VIEW + SIDEBAR_GO_STATUS: 'sidebar_go_status', + SIDEBAR_GO_CHATS: 'sidebar_go_chats', + SIDEBAR_GO_PROFILE: 'sidebar_go_profile', + SIDEBAR_GO_SETTINGS: 'sidebar_go_settings', + SIDEBAR_GO_ADMINPANEL: 'sidebar_go_admin_panel', + + // STATUS VIEW + STATUS_DONE: 'status_done', + STATUS_ONLINE: 'status_online', + STATUS_BUSY: 'status_busy', + STATUS_AWAY: 'status_away', + STATUS_OFFLINE: 'status_offline', + STATUS_F: 'status_f', + STATUS_CUSTOM: 'status_custom', + STATUS_CUSTOM_F: 'status_custom_f', + + // ROOMS LIST VIEW + RL_TOGGLE_SERVER_DROPDOWN: 'rl_toggle_server_dropdown', + RL_ADD_SERVER: 'rl_add_server', + RL_CHANGE_SERVER: 'rl_change_server', + RL_GO_NEW_MSG: 'rl_go_new_msg', + RL_SEARCH: 'rl_search', + RL_GO_DIRECTORY: 'rl_go_directory', + RL_GO_QUEUE: 'rl_go_queue', + RL_GO_ROOM: 'rl_go_room', + RL_FAVORITE_CHANNEL: 'rl_favorite_channel', + RL_UNFAVORITE_CHANNEL: 'rl_unfavorite_channel', + RL_TOGGLE_FAVORITE_F: 'rl_toggle_favorite_f', + RL_READ_CHANNEL: 'rl_read_channel', + RL_UNREAD_CHANNEL: 'rl_unread_channel', + RL_TOGGLE_READ_F: 'rl_toggle_read_f', + RL_HIDE_CHANNEL: 'rl_hide_channel', + RL_HIDE_CHANNEL_F: 'rl_hide_channel_f', + RL_TOGGLE_SORT_DROPDOWN: 'rl_toggle_sort_dropdown', + RL_SORT_CHANNELS_BY_NAME: 'rl_sort_channels_by_name', + RL_SORT_CHANNELS_BY_ACTIVITY: 'rl_sort_channels_by_activity', + RL_SORT_CHANNELS_F: 'rl_sort_channels_f', + RL_GROUP_CHANNELS_BY_TYPE: 'rl_group_channels_by_type', + RL_GROUP_CHANNELS_BY_FAVORITE: 'rl_group_channels_by_favorite', + RL_GROUP_CHANNELS_BY_UNREAD: 'rl_group_channels_by_unread', + + // QUEUE LIST VIEW + QL_GO_ROOM: 'ql_go_room', + + // DIRECTORY VIEW + DIRECTORY_SEARCH_USERS: 'directory_search_users', + DIRECTORY_SEARCH_CHANNELS: 'directory_search_channels', + + // NEW MESSAGE VIEW + NEW_MSG_CREATE_CHANNEL: 'new_msg_create_channel', + NEW_MSG_CREATE_GROUP_CHAT: 'new_msg_create_group_chat', + NEW_MSG_CREATE_DISCUSSION: 'new_msg_create_discussion', + NEW_MSG_CHAT_WITH_USER: 'new_msg_chat_with_user', + + // SELECTED USERS VIEW + SELECTED_USERS_ADD_USER: 'selected_users_add_user', + SELECTED_USERS_REMOVE_USER: 'selected_users_remove_user', + SELECTED_USERS_CREATE_GROUP: 'selected_users_create_group', + SELECTED_USERS_CREATE_GROUP_F: 'selected_users_create_group_f', + + // CREATE CHANNEL VIEW + CREATE_CHANNEL_CREATE: 'create_channel_create', + CREATE_CHANNEL_CREATE_F: 'create_channel_create_f', + CREATE_CHANNEL_TOGGLE_TYPE: 'create_channel_toggle_type', + CREATE_CHANNEL_TOGGLE_READ_ONLY: 'create_channel_toggle_read_only', + CREATE_CHANNEL_TOGGLE_BROADCAST: 'create_channel_toggle_broadcast', + CREATE_CHANNEL_REMOVE_USER: 'create_channel_remove_user', + + // CREATE DISCUSSION VIEW + CREATE_DISCUSSION_CREATE: 'create_discussion_create', + CREATE_DISCUSSION_CREATE_F: 'create_discussion_create_f', + CREATE_DISCUSSION_SELECT_CHANNEL: 'create_discussion_select_channel', + CREATE_DISCUSSION_SELECT_USERS: 'create_discussion_select_users', + + // PROFILE VIEW + PROFILE_PICK_AVATAR: 'profile_pick_avatar', + PROFILE_PICK_AVATAR_F: 'profile_pick_avatar_f', + PROFILE_PICK_AVATAR_WITH_URL: 'profile_pick_avatar_with_url', + PROFILE_SAVE_AVATAR: 'profile_save_avatar', + PROFILE_SAVE_AVATAR_F: 'profile_save_avatar_f', + PROFILE_SAVE_CHANGES: 'profile_save_changes', + PROFILE_SAVE_CHANGES_F: 'profile_save_changes_f', + + // SETTINGS VIEW + SE_CONTACT_US: 'se_contact_us', + SE_CONTACT_US_F: 'se_contact_us_f', + SE_GO_LANGUAGE: 'se_go_language', + SE_REVIEW_THIS_APP: 'se_review_this_app', + SE_REVIEW_THIS_APP_F: 'se_review_this_app_f', + SE_SHARE_THIS_APP: 'se_share_this_app', + SE_GO_DEFAULTBROWSER: 'se_go_default_browser', + SE_GO_THEME: 'se_go_theme', + SE_GO_SCREENLOCKCONFIG: 'se_go_screen_lock_cfg', + SE_GO_PROFILE: 'se_go_profile', + SE_READ_LICENSE: 'se_read_license', + SE_COPY_APP_VERSION: 'se_copy_app_version', + SE_COPY_SERVER_VERSION: 'se_copy_server_version', + SE_TOGGLE_CRASH_REPORT: 'se_toggle_crash_report', + SE_CLEAR_LOCAL_SERVER_CACHE: 'se_clear_local_server_cache', + SE_LOG_OUT: 'se_log_out', + + // LANGUAGE VIEW + LANG_SET_LANGUAGE: 'lang_set_language', + LANG_SET_LANGUAGE_F: 'lang_set_language_f', + + // DEFAULT BROWSER VIEW + DB_CHANGE_DEFAULT_BROWSER: 'db_change_default_browser', + DB_CHANGE_DEFAULT_BROWSER_F: 'db_change_default_browser_f', + + // THEME VIEW + THEME_SET_THEME_GROUP: 'theme_set_theme_group', + THEME_SET_DARK_LEVEL: 'theme_set_dark_level', + + // SCREEN LOCK CONFIG VIEW + SLC_SAVE_SCREEN_LOCK: 'slc_save_screen_lock', + SLC_TOGGLE_AUTOLOCK: 'slc_toggle_autolock', + SLC_TOGGLE_BIOMETRY: 'slc_toggle_biometry', + SLC_CHANGE_PASSCODE: 'slc_change_passcode', + SLC_CHANGE_AUTOLOCK_TIME: 'slc_change_autolock_time', + + // ROOM VIEW + ROOM_SEND_MESSAGE: 'room_send_message', + ROOM_OPEN_EMOJI: 'room_open_emoji', + ROOM_AUDIO_RECORD: 'room_audio_record', + ROOM_AUDIO_RECORD_F: 'room_audio_record_f', + ROOM_AUDIO_FINISH: 'room_audio_finish', + ROOM_AUDIO_FINISH_F: 'room_audio_finish_f', + ROOM_AUDIO_CANCEL: 'room_audio_cancel', + ROOM_AUDIO_CANCEL_F: 'room_audio_cancel_f', + ROOM_SHOW_BOX_ACTIONS: 'room_show_box_actions', + ROOM_BOX_ACTION_PHOTO: 'room_box_action_photo', + ROOM_BOX_ACTION_PHOTO_F: 'room_box_action_photo_f', + ROOM_BOX_ACTION_VIDEO: 'room_box_action_video', + ROOM_BOX_ACTION_VIDEO_F: 'room_box_action_video_f', + ROOM_BOX_ACTION_LIBRARY: 'room_box_action_library', + ROOM_BOX_ACTION_LIBRARY_F: 'room_box_action_library_f', + ROOM_BOX_ACTION_FILE: 'room_box_action_file', + ROOM_BOX_ACTION_FILE_F: 'room_box_action_file_f', + ROOM_BOX_ACTION_DISCUSSION: 'room_box_action_discussion', + ROOM_SHOW_MSG_ACTIONS: 'room_show_msg_actions', + ROOM_MSG_ACTION_REPLY: 'room_msg_action_reply', + ROOM_MSG_ACTION_QUOTE: 'room_msg_action_quote', + ROOM_MSG_ACTION_EDIT: 'room_msg_action_edit', + ROOM_MSG_ACTION_DELETE: 'room_msg_action_delete', + ROOM_MSG_ACTION_DELETE_F: 'room_msg_action_delete_f', + ROOM_MSG_ACTION_PERMALINK: 'room_msg_action_permalink', + ROOM_MSG_ACTION_PERMALINK_F: 'room_msg_action_permalink_f', + ROOM_MSG_ACTION_DISCUSSION: 'room_msg_action_discussion', + ROOM_MSG_ACTION_UNREAD: 'room_msg_action_unread', + ROOM_MSG_ACTION_UNREAD_F: 'room_msg_action_unread_f', + ROOM_MSG_ACTION_COPY: 'room_msg_action_copy', + ROOM_MSG_ACTION_SHARE: 'room_msg_action_share', + ROOM_MSG_ACTION_SHARE_F: 'room_msg_action_share_f', + ROOM_MSG_ACTION_STAR: 'room_msg_action_star', + ROOM_MSG_ACTION_UNSTAR: 'room_msg_action_unstar', + ROOM_MSG_ACTION_STAR_F: 'room_msg_action_star_f', + ROOM_MSG_ACTION_PIN: 'room_msg_action_pin', + ROOM_MSG_ACTION_PIN_F: 'room_msg_action_pin_f', + ROOM_MSG_ACTION_REACTION: 'room_msg_action_reaction', + ROOM_MSG_ACTION_REPORT: 'room_msg_action_report', + ROOM_MSG_ACTION_REPORT_F: 'room_msg_action_report_f', + ROOM_JOIN: 'room_join', + ROOM_GO_RA: 'room_go_ra', + ROOM_TOGGLE_FOLLOW_THREADS: 'room_toggle_follow_threads', + ROOM_GO_SEARCH: 'room_go_search', + ROOM_GO_THREADS: 'room_go_threads', + ROOM_GO_ROOM_INFO: 'room_go_room_info', + ROOM_GO_USER_INFO: 'room_go_user_info', + ROOM_MENTION_GO_USER_INFO: 'room_mention_go_user_info', + COMMAND_RUN: 'command_run', + COMMAND_RUN_F: 'command_run_f', + + // ROOM ACTIONS VIEW + RA_JITSI_VIDEO: 'ra_jitsi_video', + RA_JITSI_AUDIO: 'ra_jitsi_audio', + RA_JITSI_F: 'ra_jitsi_f', + RA_GO_ROOMINFO: 'ra_go_room_info', + RA_GO_ROOMMEMBERS: 'ra_go_room_members', + RA_GO_SELECTEDUSERS: 'ra_go_selected_users', + RA_GO_INVITEUSERS: 'ra_go_invite_users', + RA_GO_MESSAGESFILES: 'ra_go_messages_files', + RA_GO_MESSAGESMENTIONS: 'ra_go_messages_mentions', + RA_GO_MESSAGESSTARRED: 'ra_go_messages_starred', + RA_GO_SEARCHMESSAGES: 'ra_go_search_messages', + RA_GO_MESSAGESPINNED: 'ra_go_messages_pinned', + RA_GO_AUTOTRANSLATE: 'ra_go_autotranslate', + RA_GO_NOTIFICATIONPREF: 'ra_go_notification_pref', + RA_GO_FORWARDLIVECHAT: 'ra_go_forward_livechat', + RA_GO_VISITORNAVIGATION: 'ra_go_visitor_navigation', + RA_SHARE: 'ra_share', + RA_LEAVE: 'ra_leave', + RA_LEAVE_F: 'ra_leave_f', + RA_TOGGLE_BLOCK_USER: 'ra_toggle_block_user', + RA_TOGGLE_BLOCK_USER_F: 'ra_toggle_block_user_f', + + // ROOM INFO VIEW + RI_GO_RI_EDIT: 'ri_go_ri_edit', + RI_GO_LIVECHAT_EDIT: 'ri_go_livechat_edit', + RI_GO_ROOM_USER: 'ri_go_room_user', + + // ROOM INFO EDIT VIEW + RI_EDIT_TOGGLE_ROOM_TYPE: 'ri_edit_toggle_room_type', + RI_EDIT_TOGGLE_READ_ONLY: 'ri_edit_toggle_read_only', + RI_EDIT_TOGGLE_REACTIONS: 'ri_edit_toggle_reactions', + RI_EDIT_TOGGLE_SYSTEM_MSG: 'ri_edit_toggle_system_msg', + RI_EDIT_SAVE: 'ri_edit_save', + RI_EDIT_SAVE_F: 'ri_edit_save_f', + RI_EDIT_RESET: 'ri_edit_reset', + RI_EDIT_TOGGLE_ARCHIVE: 'ri_edit_toggle_archive', + RI_EDIT_TOGGLE_ARCHIVE_F: 'ri_edit_toggle_archive_f', + RI_EDIT_DELETE: 'ri_edit_delete', + RI_EDIT_DELETE_F: 'ri_edit_delete_f', + + // JITSI MEET VIEW + JM_CONFERENCE_JOIN: 'jm_conference_join', + JM_CONFERENCE_TERMINATE: 'jm_conference_terminate', + + // INVITE USERS VIEW + IU_SHARE: 'iu_share', + IU_GO_IU_EDIT: 'iu_go_iu_edit', + + // INVITE USERS EDIT VIEW + IU_EDIT_SET_LINK_PARAM: 'iu_edit_set_link_param', + IU_EDIT_CREATE_LINK: 'iu_edit_create_link', + + // AUTO TRANSLATE VIEW + AT_TOGGLE_TRANSLATE: 'at_toggle_translate', + AT_TOGGLE_TRANSLATE_F: 'at_toggle_translate_f', + AT_SET_LANG: 'at_set_lang', + AT_SET_LANG_F: 'at_set_lang_f', + + // NOTIFICATION PREFERENCES VIEW + NP_DISABLENOTIFICATIONS: 'np_disable_notification', + NP_DISABLENOTIFICATIONS_F: 'np_disable_notification_f', + NP_MUTEGROUPMENTIONS: 'np_mute_group_mentions', + NP_MUTEGROUPMENTIONS_F: 'np_mute_group_mentions_f', + NP_HIDEUNREADSTATUS: 'np_hide_unread_status', + NP_HIDEUNREADSTATUS_F: 'np_hide_unread_status_f', + NP_DESKTOPNOTIFICATIONS: 'np_desktop_notifications', + NP_DESKTOPNOTIFICATIONS_F: 'np_desktop_notifications_f', + NP_MOBILEPUSHNOTIFICATIONS: 'np_mobile_push_notifications', + NP_MOBILEPUSHNOTIFICATIONS_F: 'np_mobile_push_notifications_f', + NP_AUDIONOTIFICATIONS: 'np_audio_notifications', + NP_AUDIONOTIFICATIONS_F: 'np_audio_notifications_f', + NP_AUDIONOTIFICATIONVALUE: 'np_audio_notification_value', + NP_AUDIONOTIFICATIONVALUE_F: 'np_audio_notification_value_f', + NP_DESKTOPNOTIFICATIONDURATION: 'np_desktopnotificationduration', + NP_DESKTOPNOTIFICATIONDURATION_F: 'np_desktopnotificationduration_f', + NP_EMAILNOTIFICATIONS: 'np_email_notifications', + NP_EMAILNOTIFICATIONS_F: 'np_email_notifications_f' +}; diff --git a/app/utils/log.js b/app/utils/log/index.js similarity index 61% rename from app/utils/log.js rename to app/utils/log/index.js index f2d0fe2f6..ea00ca325 100644 --- a/app/utils/log.js +++ b/app/utils/log/index.js @@ -1,12 +1,15 @@ import { Client } from 'bugsnag-react-native'; -import firebase from 'react-native-firebase'; -import config from '../../config'; +import analytics from '@react-native-firebase/analytics'; +import crashlytics from '@react-native-firebase/crashlytics'; +import config from '../../../config'; +import events from './events'; const bugsnag = new Client(config.BUGSNAG_API_KEY); -export const { analytics } = firebase; +export { analytics }; export const loggerConfig = bugsnag.config; export const { leaveBreadcrumb } = bugsnag; +export { events }; let metadata = {}; @@ -16,6 +19,15 @@ export const logServerVersion = (serverVersion) => { }; }; +export const logEvent = (eventName, payload) => { + try { + analytics().logEvent(eventName, payload); + leaveBreadcrumb(eventName, payload); + } catch { + // Do nothing + } +}; + export const setCurrentScreen = (currentScreen) => { analytics().setCurrentScreen(currentScreen); leaveBreadcrumb(currentScreen, { type: 'navigation' }); @@ -30,6 +42,7 @@ export default (e) => { } }; }); + crashlytics().recordError(e); } else { console.log(e); } diff --git a/app/utils/longPress.js b/app/utils/longPress.js deleted file mode 100644 index e491efcb9..000000000 --- a/app/utils/longPress.js +++ /dev/null @@ -1,44 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { State, LongPressGestureHandler } from 'react-native-gesture-handler'; - -class LongPress extends React.Component { - setNativeProps(props) { - this.ref.setNativeProps(props); - } - - getRef = (ref) => { - this.ref = ref; - }; - - longPress = ({ nativeEvent }) => { - const { onLongPress } = this.props; - if (nativeEvent.state === State.ACTIVE) { - if (onLongPress) { - onLongPress(); - } - } - }; - - render() { - const { children, ...props } = this.props; - - return ( - <LongPressGestureHandler - onHandlerStateChange={this.longPress} - minDurationMs={800} - ref={this.getRef} - {...props} - > - {children} - </LongPressGestureHandler> - ); - } -} - -LongPress.propTypes = { - children: PropTypes.node, - onLongPress: PropTypes.func -}; - -export default LongPress; diff --git a/app/utils/review.js b/app/utils/review.js index 1c38f67c8..17ba73c90 100644 --- a/app/utils/review.js +++ b/app/utils/review.js @@ -5,6 +5,7 @@ import { isIOS } from './deviceInfo'; import I18n from '../i18n'; import { showErrorAlert } from './info'; import { STORE_REVIEW_LINK } from '../constants/links'; +import { logEvent, events } from './log'; const store = isIOS ? 'App Store' : 'Play Store'; @@ -31,6 +32,7 @@ const onCancelPress = () => { }; export const onReviewPress = async() => { + logEvent(events.SE_REVIEW_THIS_APP); await onCancelPress(); try { const supported = await Linking.canOpenURL(STORE_REVIEW_LINK); @@ -38,6 +40,7 @@ export const onReviewPress = async() => { Linking.openURL(STORE_REVIEW_LINK); } } catch (e) { + logEvent(events.SE_REVIEW_THIS_APP_F); showErrorAlert(I18n.t('Review_app_unable_store', { store })); } }; diff --git a/app/views/AdminPanelView/index.js b/app/views/AdminPanelView/index.js index 283e2ef74..41005fc93 100644 --- a/app/views/AdminPanelView/index.js +++ b/app/views/AdminPanelView/index.js @@ -31,6 +31,8 @@ class AdminPanelView extends React.Component { <SafeAreaView theme={theme}> <StatusBar theme={theme} /> <WebView + // https://github.com/react-native-community/react-native-webview/issues/1311 + onMessage={() => {}} source={{ uri: `${ baseUrl }/admin/info?layout=embedded` }} injectedJavaScript={`Meteor.loginWithToken('${ token }', function() { })`} /> diff --git a/app/views/AutoTranslateView/index.js b/app/views/AutoTranslateView/index.js index 0f52db69f..5a1671b82 100644 --- a/app/views/AutoTranslateView/index.js +++ b/app/views/AutoTranslateView/index.js @@ -15,6 +15,7 @@ import { SWITCH_TRACK_COLOR, themes } from '../../constants/colors'; import scrollPersistTaps from '../../utils/scrollPersistTaps'; import { withTheme } from '../../theme'; import SafeAreaView from '../../containers/SafeAreaView'; +import { logEvent, events } from '../../utils/log'; const styles = StyleSheet.create({ contentContainerStyle: { @@ -48,13 +49,14 @@ SectionSeparator.propTypes = { }; class AutoTranslateView extends React.Component { - static navigationOptions = { + static navigationOptions = () => ({ title: I18n.t('Auto_Translate') - } + }) static propTypes = { route: PropTypes.object, - theme: PropTypes.string + theme: PropTypes.string, + navigation: PropTypes.object } constructor(props) { @@ -102,6 +104,7 @@ class AutoTranslateView extends React.Component { } toggleAutoTranslate = async() => { + logEvent(events.AT_TOGGLE_TRANSLATE); const { enableAutoTranslate } = this.state; try { await RocketChat.saveAutoTranslate({ @@ -112,11 +115,13 @@ class AutoTranslateView extends React.Component { }); this.setState({ enableAutoTranslate: !enableAutoTranslate }); } catch (error) { + logEvent(events.AT_TOGGLE_TRANSLATE_F); console.log(error); } } saveAutoTranslateLanguage = async(language) => { + logEvent(events.AT_SET_LANG); try { await RocketChat.saveAutoTranslate({ rid: this.rid, @@ -125,6 +130,7 @@ class AutoTranslateView extends React.Component { }); this.setState({ selectedLanguage: language }); } catch (error) { + logEvent(events.AT_SET_LANG_F); console.log(error); } } diff --git a/app/views/ChangePasscodeView.js b/app/views/ChangePasscodeView.js index ec4a5ab19..ddfdbd0a0 100644 --- a/app/views/ChangePasscodeView.js +++ b/app/views/ChangePasscodeView.js @@ -83,7 +83,7 @@ const ChangePasscodeView = React.memo(({ theme }) => { {!data?.force ? ( <Touchable onPress={onCancel} style={styles.close}> - <CustomIcon name='Cross' color={themes[theme].passcodePrimary} size={30} /> + <CustomIcon name='close' color={themes[theme].passcodePrimary} size={30} /> </Touchable> ) : null} diff --git a/app/views/CreateChannelView.js b/app/views/CreateChannelView.js index 09e32eb6b..c4f2c5407 100644 --- a/app/views/CreateChannelView.js +++ b/app/views/CreateChannelView.js @@ -21,6 +21,7 @@ import { SWITCH_TRACK_COLOR, themes } from '../constants/colors'; import { withTheme } from '../theme'; import { Review } from '../utils/review'; import { getUserSelector } from '../selectors/login'; +import { logEvent, events } from '../utils/log'; import SafeAreaView from '../containers/SafeAreaView'; const styles = StyleSheet.create({ @@ -72,9 +73,9 @@ const styles = StyleSheet.create({ }); class CreateChannelView extends React.Component { - static navigationOptions = { + static navigationOptions = () => ({ title: I18n.t('Create_Channel') - } + }); static propTypes = { navigation: PropTypes.object, @@ -166,6 +167,7 @@ class CreateChannelView extends React.Component { } removeUser = (user) => { + logEvent(events.CREATE_CHANNEL_REMOVE_USER); const { removeUser } = this.props; removeUser(user); } @@ -194,7 +196,10 @@ class CreateChannelView extends React.Component { id: 'type', value: type, label: 'Private_Channel', - onValueChange: value => this.setState({ type: value }) + onValueChange: (value) => { + logEvent(events.CREATE_CHANNEL_TOGGLE_TYPE); + this.setState({ type: value }); + } }); } @@ -204,7 +209,10 @@ class CreateChannelView extends React.Component { id: 'readonly', value: readOnly, label: 'Read_Only_Channel', - onValueChange: value => this.setState({ readOnly: value }), + onValueChange: (value) => { + logEvent(events.CREATE_CHANNEL_TOGGLE_READ_ONLY); + this.setState({ readOnly: value }); + }, disabled: broadcast }); } @@ -216,6 +224,7 @@ class CreateChannelView extends React.Component { value: broadcast, label: 'Broadcast_Channel', onValueChange: (value) => { + logEvent(events.CREATE_CHANNEL_TOGGLE_BROADCAST); this.setState({ broadcast: value, readOnly: value ? true : readOnly diff --git a/app/views/CreateDiscussionView/index.js b/app/views/CreateDiscussionView/index.js index 206a70203..7fe6e6977 100644 --- a/app/views/CreateDiscussionView/index.js +++ b/app/views/CreateDiscussionView/index.js @@ -25,6 +25,7 @@ import SelectUsers from './SelectUsers'; import styles from './styles'; import SafeAreaView from '../../containers/SafeAreaView'; import { goRoom } from '../../utils/goRoom'; +import { logEvent, events } from '../../utils/log'; class CreateChannelView extends React.Component { propTypes = { @@ -129,6 +130,16 @@ class CreateChannelView extends React.Component { ); }; + selectChannel = ({ value }) => { + logEvent(events.CREATE_DISCUSSION_SELECT_CHANNEL); + this.setState({ channel: { rid: value } }); + } + + selectUsers = ({ value }) => { + logEvent(events.CREATE_DISCUSSION_SELECT_USERS); + this.setState({ users: value }); + } + render() { const { name, users } = this.state; const { @@ -149,7 +160,7 @@ class CreateChannelView extends React.Component { userId={user.id} token={user.token} initial={this.channel && { text: RocketChat.getRoomTitle(this.channel) }} - onChannelSelect={({ value }) => this.setState({ channel: { rid: value } })} + onChannelSelect={this.selectChannel} theme={theme} /> <TextInput @@ -165,7 +176,7 @@ class CreateChannelView extends React.Component { userId={user.id} token={user.token} selected={users} - onUserSelect={({ value }) => this.setState({ users: value })} + onUserSelect={this.selectUsers} theme={theme} /> <TextInput diff --git a/app/views/DefaultBrowserView.js b/app/views/DefaultBrowserView.js index 3148952ae..e51b11f02 100644 --- a/app/views/DefaultBrowserView.js +++ b/app/views/DefaultBrowserView.js @@ -16,14 +16,15 @@ import { CustomIcon } from '../lib/Icons'; import { DEFAULT_BROWSER_KEY } from '../utils/openLink'; import { isIOS } from '../utils/deviceInfo'; import SafeAreaView from '../containers/SafeAreaView'; +import { logEvent, events } from '../utils/log'; const DEFAULT_BROWSERS = [ { - title: I18n.t('In_app'), + title: 'In_app', value: 'inApp' }, { - title: isIOS ? 'Safari' : I18n.t('Browser'), + title: isIOS ? 'Safari' : 'Browser', value: 'systemDefault:' } ]; @@ -59,9 +60,9 @@ const styles = StyleSheet.create({ }); class DefaultBrowserView extends React.Component { - static navigationOptions = { + static navigationOptions = () => ({ title: I18n.t('Default_browser') - } + }) static propTypes = { theme: PropTypes.string @@ -113,12 +114,13 @@ class DefaultBrowserView extends React.Component { } changeDefaultBrowser = async(newBrowser) => { + logEvent(events.DB_CHANGE_DEFAULT_BROWSER, { browser: newBrowser }); try { const browser = newBrowser !== 'inApp' ? newBrowser : null; await RNUserDefaults.set(DEFAULT_BROWSER_KEY, browser); this.setState({ browser }); } catch { - // do nothing + logEvent(events.DB_CHANGE_DEFAULT_BROWSER_F); } } @@ -137,7 +139,7 @@ class DefaultBrowserView extends React.Component { const { title, value } = item; return ( <ListItem - title={title} + title={I18n.t(title, { defaultValue: title })} onPress={() => this.changeDefaultBrowser(value)} testID={`default-browser-view-${ title }`} right={this.isSelected(value) ? this.renderIcon : null} diff --git a/app/views/DirectoryView/Options.js b/app/views/DirectoryView/Options.js index 223c88e75..18483bda9 100644 --- a/app/views/DirectoryView/Options.js +++ b/app/views/DirectoryView/Options.js @@ -61,7 +61,7 @@ export default class DirectoryOptions extends PureComponent { let icon = 'user'; if (itemType === 'channels') { text = 'Channels'; - icon = 'hash'; + icon = 'channel-public'; } return ( diff --git a/app/views/DirectoryView/index.js b/app/views/DirectoryView/index.js index 49c89781c..6a02092af 100644 --- a/app/views/DirectoryView/index.js +++ b/app/views/DirectoryView/index.js @@ -16,7 +16,7 @@ import StatusBar from '../../containers/StatusBar'; import ActivityIndicator from '../../containers/ActivityIndicator'; import { CloseModalButton } from '../../containers/HeaderButton'; import debounce from '../../utils/debounce'; -import log from '../../utils/log'; +import log, { logEvent, events } from '../../utils/log'; import Options from './Options'; import { withTheme } from '../../theme'; import { themes } from '../../constants/colors'; @@ -115,6 +115,12 @@ class DirectoryView extends React.Component { changeType = (type) => { this.setState({ type, data: [] }, () => this.search()); + + if (type === 'users') { + logEvent(events.DIRECTORY_SEARCH_USERS); + } else if (type === 'channels') { + logEvent(events.DIRECTORY_SEARCH_CHANNELS); + } } toggleWorkspace = () => { @@ -166,7 +172,7 @@ class DirectoryView extends React.Component { theme={theme} > <View style={[sharedStyles.separatorVertical, styles.toggleDropdownContainer, { borderColor: themes[theme].separatorColor }]}> - <CustomIcon style={[styles.toggleDropdownIcon, { color: themes[theme].tintColor }]} size={20} name={type === 'users' ? 'user' : 'hash'} /> + <CustomIcon style={[styles.toggleDropdownIcon, { color: themes[theme].tintColor }]} size={20} name={type === 'users' ? 'user' : 'channel-public'} /> <Text style={[styles.toggleDropdownText, { color: themes[theme].tintColor }]}>{type === 'users' ? I18n.t('Users') : I18n.t('Channels')}</Text> <CustomIcon name='chevron-down' size={20} style={[styles.toggleDropdownArrow, { color: themes[theme].auxiliaryTintColor }]} /> </View> diff --git a/app/views/ForgotPasswordView.js b/app/views/ForgotPasswordView.js index d233c0578..319682c75 100644 --- a/app/views/ForgotPasswordView.js +++ b/app/views/ForgotPasswordView.js @@ -12,6 +12,7 @@ import RocketChat from '../lib/rocketchat'; import { withTheme } from '../theme'; import { themes } from '../constants/colors'; import FormContainer, { FormContainerInner } from '../containers/FormContainer'; +import { logEvent, events } from '../utils/log'; class ForgotPasswordView extends React.Component { static navigationOptions = ({ route }) => ({ @@ -56,6 +57,7 @@ class ForgotPasswordView extends React.Component { } resetPassword = async() => { + logEvent(events.FP_FORGOT_PASSWORD); const { email, invalidEmail } = this.state; if (invalidEmail || !email) { return; @@ -69,6 +71,7 @@ class ForgotPasswordView extends React.Component { showErrorAlert(I18n.t('Forgot_password_If_this_email_is_registered'), I18n.t('Alert')); } } catch (e) { + logEvent(events.FP_FORGOT_PASSWORD_F); const msg = (e.data && e.data.error) || I18n.t('There_was_an_error_while_action', { action: I18n.t('resetting_password') }); showErrorAlert(msg, I18n.t('Alert')); } diff --git a/app/views/InviteUsersEditView/index.js b/app/views/InviteUsersEditView/index.js index ee9874298..d5f8d6fb4 100644 --- a/app/views/InviteUsersEditView/index.js +++ b/app/views/InviteUsersEditView/index.js @@ -18,12 +18,10 @@ import { themes } from '../../constants/colors'; import { withTheme } from '../../theme'; import Separator from '../../containers/Separator'; import SafeAreaView from '../../containers/SafeAreaView'; +import { logEvent, events } from '../../utils/log'; const OPTIONS = { days: [{ - label: I18n.t('Never'), value: 0 - }, - { label: '1', value: 1 }, { @@ -36,9 +34,6 @@ const OPTIONS = { label: '30', value: 30 }], maxUses: [{ - label: I18n.t('No_limit'), value: 0 - }, - { label: '1', value: 1 }, { @@ -59,9 +54,9 @@ const OPTIONS = { }; class InviteUsersView extends React.Component { - static navigationOptions = { + static navigationOptions = () => ({ title: I18n.t('Invite_users') - } + }) static propTypes = { navigation: PropTypes.object, @@ -78,6 +73,7 @@ class InviteUsersView extends React.Component { } onValueChangePicker = (key, value) => { + logEvent(events.IU_EDIT_SET_LINK_PARAM); const { inviteLinksSetParams } = this.props; const params = { [key]: value @@ -86,14 +82,18 @@ class InviteUsersView extends React.Component { } createInviteLink = () => { + logEvent(events.IU_EDIT_CREATE_LINK); const { createInviteLink, navigation } = this.props; createInviteLink(this.rid); navigation.pop(); } - renderPicker = (key) => { + renderPicker = (key, first) => { const { props } = this; const { theme } = props; + const firstEl = [{ + label: I18n.t(first), value: 0 + }]; return ( <RNPickerSelect style={{ viewContainer: styles.viewContainer }} @@ -102,7 +102,7 @@ class InviteUsersView extends React.Component { useNativeAndroidPickerStyle={false} placeholder={{}} onValueChange={value => this.onValueChangePicker(key, value)} - items={OPTIONS[key]} + items={firstEl.concat(OPTIONS[key])} /> ); } @@ -121,13 +121,13 @@ class InviteUsersView extends React.Component { <Separator theme={theme} /> <ListItem title={I18n.t('Expiration_Days')} - right={() => this.renderPicker('days')} + right={() => this.renderPicker('days', 'Never')} theme={theme} /> <Separator theme={theme} /> <ListItem title={I18n.t('Max_number_of_uses')} - right={() => this.renderPicker('maxUses')} + right={() => this.renderPicker('maxUses', 'No_limit')} theme={theme} /> <Separator theme={theme} /> diff --git a/app/views/InviteUsersView/index.js b/app/views/InviteUsersView/index.js index 5b7e4b010..875594b12 100644 --- a/app/views/InviteUsersView/index.js +++ b/app/views/InviteUsersView/index.js @@ -18,11 +18,12 @@ import StatusBar from '../../containers/StatusBar'; import { themes } from '../../constants/colors'; import { withTheme } from '../../theme'; import SafeAreaView from '../../containers/SafeAreaView'; +import { logEvent, events } from '../../utils/log'; class InviteUsersView extends React.Component { - static navigationOptions = { + static navigationOptions = () => ({ title: I18n.t('Invite_users') - } + }) static propTypes = { navigation: PropTypes.object, @@ -50,6 +51,7 @@ class InviteUsersView extends React.Component { } share = () => { + logEvent(events.IU_SHARE); const { invite } = this.props; if (!invite || !invite.url) { return; @@ -58,6 +60,7 @@ class InviteUsersView extends React.Component { } edit = () => { + logEvent(events.IU_GO_IU_EDIT); const { navigation } = this.props; navigation.navigate('InviteUsersEditView', { rid: this.rid }); } diff --git a/app/views/JitsiMeetView.js b/app/views/JitsiMeetView.js index 6c0fce96a..6b7a15688 100644 --- a/app/views/JitsiMeetView.js +++ b/app/views/JitsiMeetView.js @@ -8,6 +8,7 @@ import RocketChat from '../lib/rocketchat'; import { getUserSelector } from '../selectors/login'; import sharedStyles from './Styles'; +import { logEvent, events } from '../utils/log'; const formatUrl = (url, baseUrl, uriSize, avatarAuthURLFragment) => ( `${ baseUrl }/avatar/${ url }?format=png&width=${ uriSize }&height=${ uriSize }${ avatarAuthURLFragment }` @@ -59,6 +60,7 @@ class JitsiMeetView extends React.Component { } componentWillUnmount() { + logEvent(events.JM_CONFERENCE_TERMINATE); if (this.jitsiTimeout) { BackgroundTimer.clearInterval(this.jitsiTimeout); } @@ -68,6 +70,7 @@ class JitsiMeetView extends React.Component { // Jitsi Update Timeout needs to be called every 10 seconds to make sure // call is not ended and is available to web users. onConferenceJoined = () => { + logEvent(events.JM_CONFERENCE_JOIN); RocketChat.updateJitsiTimeout(this.rid).catch(e => console.log(e)); if (this.jitsiTimeout) { BackgroundTimer.clearInterval(this.jitsiTimeout); @@ -78,6 +81,7 @@ class JitsiMeetView extends React.Component { } onConferenceTerminated = () => { + logEvent(events.JM_CONFERENCE_TERMINATE); const { navigation } = this.props; if (this.jitsiTimeout) { BackgroundTimer.clearInterval(this.jitsiTimeout); diff --git a/app/views/LanguageView/index.js b/app/views/LanguageView/index.js index 640602d83..0420da72f 100644 --- a/app/views/LanguageView/index.js +++ b/app/views/LanguageView/index.js @@ -6,7 +6,7 @@ import { connect } from 'react-redux'; import RocketChat from '../../lib/rocketchat'; import I18n from '../../i18n'; import { showErrorAlert } from '../../utils/info'; -import log from '../../utils/log'; +import log, { logEvent, events } from '../../utils/log'; import { setUser as setUserAction } from '../../actions/login'; import StatusBar from '../../containers/StatusBar'; import { CustomIcon } from '../../lib/Icons'; @@ -58,9 +58,9 @@ const LANGUAGES = [ ]; class LanguageView extends React.Component { - static navigationOptions = { + static navigationOptions = () => ({ title: I18n.t('Change_Language') - } + }) static propTypes = { user: PropTypes.object, @@ -112,6 +112,7 @@ class LanguageView extends React.Component { } changeLanguage = async(language) => { + logEvent(events.LANG_SET_LANGUAGE); const { user, setUser } = this.props; const params = {}; @@ -134,10 +135,11 @@ class LanguageView extends React.Component { record.language = params.language; }); } catch (e) { - // do nothing + logEvent(events.LANG_SET_LANGUAGE_F); } }); } catch (e) { + logEvent(events.LANG_SET_LANGUAGE_F); showErrorAlert(I18n.t('There_was_an_error_while_action', { action: I18n.t('saving_preferences') })); log(e); } diff --git a/app/views/LivechatEditView.js b/app/views/LivechatEditView.js index 363413946..332eb3ca7 100644 --- a/app/views/LivechatEditView.js +++ b/app/views/LivechatEditView.js @@ -218,7 +218,7 @@ const LivechatEditView = ({ <TextInput inputRef={(e) => { inputs.tags = e; }} label={I18n.t('Tags')} - iconRight='plus' + iconRight='add' onIconRightPress={() => { const lastText = inputs.tags._lastNativeText || ''; if (lastText.length) { diff --git a/app/views/LoginView.js b/app/views/LoginView.js index abc901272..95d8a90d3 100644 --- a/app/views/LoginView.js +++ b/app/views/LoginView.js @@ -6,7 +6,6 @@ import { import { connect } from 'react-redux'; import equal from 'deep-equal'; -import { analytics } from '../utils/log'; import sharedStyles from './Styles'; import Button from '../containers/Button'; import I18n from '../i18n'; @@ -121,7 +120,6 @@ class LoginView extends React.Component { const { loginRequest } = this.props; Keyboard.dismiss(); loginRequest({ user, password }); - analytics().logEvent('login'); } renderUserForm = () => { diff --git a/app/views/MarkdownTableView.js b/app/views/MarkdownTableView.js index 049623444..3c552bcf1 100644 --- a/app/views/MarkdownTableView.js +++ b/app/views/MarkdownTableView.js @@ -8,9 +8,9 @@ import { themes } from '../constants/colors'; import { withTheme } from '../theme'; class MarkdownTableView extends React.Component { - static navigationOptions = { + static navigationOptions = () => ({ title: I18n.t('Table') - } + }) static propTypes = { route: PropTypes.object, diff --git a/app/views/MessagesView/index.js b/app/views/MessagesView/index.js index c01b63c25..4e826d3fc 100644 --- a/app/views/MessagesView/index.js +++ b/app/views/MessagesView/index.js @@ -18,10 +18,6 @@ import { withActionSheet } from '../../containers/ActionSheet'; import SafeAreaView from '../../containers/SafeAreaView'; class MessagesView extends React.Component { - static navigationOptions = ({ route }) => ({ - title: I18n.t(route.params?.name) - }); - static propTypes = { user: PropTypes.object, baseUrl: PropTypes.string, @@ -39,6 +35,7 @@ class MessagesView extends React.Component { messages: [], fileLoading: true }; + this.setHeader(); this.rid = props.route.params?.rid; this.t = props.route.params?.t; this.content = this.defineMessagesViewContent(props.route.params?.name); @@ -65,10 +62,16 @@ class MessagesView extends React.Component { if (fileLoading !== nextState.fileLoading) { return true; } - return false; } + setHeader = () => { + const { route, navigation } = this.props; + navigation.setOptions({ + title: I18n.t(route.params?.name) + }); + } + navToRoomInfo = (navParam) => { const { navigation, user } = this.props; if (navParam.rid === user.id) { @@ -78,9 +81,7 @@ class MessagesView extends React.Component { } defineMessagesViewContent = (name) => { - const { messages } = this.state; const { user, baseUrl, theme } = this.props; - const renderItemCommonProps = item => ({ item, baseUrl, @@ -101,6 +102,7 @@ class MessagesView extends React.Component { Files: { name: I18n.t('Files'), fetchFunc: async() => { + const { messages } = this.state; const result = await RocketChat.getFiles(this.rid, this.t, messages.length); return { ...result, messages: result.files }; }, @@ -125,12 +127,15 @@ class MessagesView extends React.Component { // Mentions Messages Screen Mentions: { name: I18n.t('Mentions'), - fetchFunc: () => RocketChat.getMessages( - this.rid, - this.t, - { 'mentions._id': { $in: [user.id] } }, - messages.length - ), + fetchFunc: () => { + const { messages } = this.state; + return RocketChat.getMessages( + this.rid, + this.t, + { 'mentions._id': { $in: [user.id] } }, + messages.length + ); + }, noDataMsg: I18n.t('No_mentioned_messages'), testID: 'mentioned-messages-view', renderItem: item => ( @@ -144,12 +149,15 @@ class MessagesView extends React.Component { // Starred Messages Screen Starred: { name: I18n.t('Starred'), - fetchFunc: () => RocketChat.getMessages( - this.rid, - this.t, - { 'starred._id': { $in: [user.id] } }, - messages.length - ), + fetchFunc: () => { + const { messages } = this.state; + return RocketChat.getMessages( + this.rid, + this.t, + { 'starred._id': { $in: [user.id] } }, + messages.length + ); + }, noDataMsg: I18n.t('No_starred_messages'), testID: 'starred-messages-view', renderItem: item => ( @@ -166,7 +174,10 @@ class MessagesView extends React.Component { // Pinned Messages Screen Pinned: { name: I18n.t('Pinned'), - fetchFunc: () => RocketChat.getMessages(this.rid, this.t, { pinned: true }, messages.length), + fetchFunc: () => { + const { messages } = this.state; + return RocketChat.getMessages(this.rid, this.t, { pinned: true }, messages.length); + }, noDataMsg: I18n.t('No_pinned_messages'), testID: 'pinned-messages-view', renderItem: item => ( diff --git a/app/views/ModalBlockView.js b/app/views/ModalBlockView.js index 57b415fdc..e88d30885 100644 --- a/app/views/ModalBlockView.js +++ b/app/views/ModalBlockView.js @@ -3,7 +3,7 @@ import { StyleSheet, View } from 'react-native'; import PropTypes from 'prop-types'; import isEqual from 'lodash/isEqual'; import { connect } from 'react-redux'; -import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'; +import { KeyboardAwareScrollView } from '@codler/react-native-keyboard-aware-scroll-view'; import { withTheme } from '../theme'; import EventEmitter from '../utils/events'; diff --git a/app/views/NewMessageView.js b/app/views/NewMessageView.js index 4e07d5409..9a1042900 100644 --- a/app/views/NewMessageView.js +++ b/app/views/NewMessageView.js @@ -14,7 +14,7 @@ import RocketChat from '../lib/rocketchat'; import UserItem from '../presentation/UserItem'; import sharedStyles from './Styles'; import I18n from '../i18n'; -import log from '../utils/log'; +import log, { logEvent, events } from '../utils/log'; import SearchBox from '../containers/SearchBox'; import { CustomIcon } from '../lib/Icons'; import { CloseModalButton } from '../containers/HeaderButton'; @@ -133,11 +133,13 @@ class NewMessageView extends React.Component { } createChannel = () => { + logEvent(events.NEW_MSG_CREATE_CHANNEL); const { navigation } = this.props; navigation.navigate('SelectedUsersViewCreateChannel', { nextAction: () => navigation.navigate('CreateChannelView') }); } createGroupChat = () => { + logEvent(events.NEW_MSG_CREATE_GROUP_CHAT); const { createChannel, maxUsers, navigation } = this.props; navigation.navigate('SelectedUsersViewCreateChannel', { nextAction: () => createChannel({ group: true }), @@ -147,6 +149,7 @@ class NewMessageView extends React.Component { } goRoom = (item) => { + logEvent(events.NEW_MSG_CHAT_WITH_USER); const { isMasterDetail, navigation } = this.props; if (isMasterDetail) { navigation.pop(); @@ -174,6 +177,7 @@ class NewMessageView extends React.Component { } createDiscussion = () => { + logEvent(events.NEW_MSG_CREATE_DISCUSSION); Navigation.navigate('CreateDiscussionView'); } @@ -186,7 +190,7 @@ class NewMessageView extends React.Component { {this.renderButton({ onPress: this.createChannel, title: I18n.t('Create_Channel'), - icon: 'hash', + icon: 'channel-public', testID: 'new-message-view-create-channel', first: true })} @@ -199,7 +203,7 @@ class NewMessageView extends React.Component { {this.renderButton({ onPress: this.createDiscussion, title: I18n.t('Create_Discussion'), - icon: 'chat', + icon: 'discussions', testID: 'new-message-view-create-discussion' })} </View> diff --git a/app/views/NewServerView.js b/app/views/NewServerView.js index b9429c05a..ec1229393 100644 --- a/app/views/NewServerView.js +++ b/app/views/NewServerView.js @@ -7,11 +7,12 @@ import { connect } from 'react-redux'; import * as FileSystem from 'expo-file-system'; import DocumentPicker from 'react-native-document-picker'; import RNUserDefaults from 'rn-user-defaults'; -import { encode } from 'base-64'; +import { Base64 } from 'js-base64'; import parse from 'url-parse'; import EventEmitter from '../utils/events'; import { selectServerRequest, serverRequest } from '../actions/server'; +import { inviteLinksClear as inviteLinksClearAction } from '../actions/inviteLinks'; import sharedStyles from './Styles'; import Button from '../containers/Button'; import TextInput from '../containers/TextInput'; @@ -20,7 +21,7 @@ import FormContainer, { FormContainerInner } from '../containers/FormContainer'; import I18n from '../i18n'; import { isIOS } from '../utils/deviceInfo'; import { themes } from '../constants/colors'; -import log from '../utils/log'; +import log, { logEvent, events } from '../utils/log'; import { animateNextTransition } from '../utils/layoutAnimation'; import { withTheme } from '../theme'; import { setBasicAuth, BASIC_AUTH_KEY } from '../utils/fetch'; @@ -61,9 +62,9 @@ const styles = StyleSheet.create({ }); class NewServerView extends React.Component { - static navigationOptions = { + static navigationOptions = () => ({ title: I18n.t('Workspaces') - } + }) static propTypes = { navigation: PropTypes.object, @@ -72,16 +73,13 @@ class NewServerView extends React.Component { connectServer: PropTypes.func.isRequired, selectServer: PropTypes.func.isRequired, adding: PropTypes.bool, - previousServer: PropTypes.string + previousServer: PropTypes.string, + inviteLinksClear: PropTypes.func } constructor(props) { super(props); - if (props.adding) { - props.navigation.setOptions({ - headerLeft: () => <CloseModalButton navigation={props.navigation} onPress={this.close} testID='new-server-view-close' /> - }); - } + this.setHeader(); this.state = { text: '', @@ -92,11 +90,27 @@ class NewServerView extends React.Component { BackHandler.addEventListener('hardwareBackPress', this.handleBackPress); } + componentDidUpdate(prevProps) { + const { adding } = this.props; + if (prevProps.adding !== adding) { + this.setHeader(); + } + } + componentWillUnmount() { EventEmitter.removeListener('NewServer', this.handleNewServerEvent); BackHandler.removeEventListener('hardwareBackPress', this.handleBackPress); } + setHeader = () => { + const { adding, navigation } = this.props; + if (adding) { + navigation.setOptions({ + headerLeft: () => <CloseModalButton navigation={navigation} onPress={this.close} testID='new-server-view-close' /> + }); + } + } + handleBackPress = () => { const { navigation, previousServer } = this.props; if (navigation.isFocused() && previousServer) { @@ -111,7 +125,8 @@ class NewServerView extends React.Component { } close = () => { - const { selectServer, previousServer } = this.props; + const { selectServer, previousServer, inviteLinksClear } = this.props; + inviteLinksClear(); selectServer(previousServer); } @@ -124,6 +139,7 @@ class NewServerView extends React.Component { } submit = async() => { + logEvent(events.NEWSERVER_CONNECT_TO_WORKSPACE); const { text, certificate } = this.state; const { connectServer } = this.props; let cert = null; @@ -135,6 +151,7 @@ class NewServerView extends React.Component { try { await FileSystem.copyAsync({ from: certificate.path, to: certificatePath }); } catch (e) { + logEvent(events.NEWSERVER_CONNECT_TO_WORKSPACE_F); log(e); } cert = { @@ -152,6 +169,7 @@ class NewServerView extends React.Component { } connectOpen = () => { + logEvent(events.NEWSERVER_JOIN_OPEN_WORKSPACE); this.setState({ connectingOpen: true }); const { connectServer } = this.props; connectServer('https://open.rocket.chat'); @@ -161,7 +179,7 @@ class NewServerView extends React.Component { try { const parsedUrl = parse(text, true); if (parsedUrl.auth.length) { - const credentials = encode(parsedUrl.auth); + const credentials = Base64.encode(parsedUrl.auth); await RNUserDefaults.set(`${ BASIC_AUTH_KEY }-${ server }`, credentials); setBasicAuth(credentials); } @@ -321,7 +339,8 @@ const mapStateToProps = state => ({ const mapDispatchToProps = dispatch => ({ connectServer: (server, certificate) => dispatch(serverRequest(server, certificate)), - selectServer: server => dispatch(selectServerRequest(server)) + selectServer: server => dispatch(selectServerRequest(server)), + inviteLinksClear: () => dispatch(inviteLinksClearAction()) }); export default connect(mapStateToProps, mapDispatchToProps)(withTheme(NewServerView)); diff --git a/app/views/NotificationPreferencesView/index.js b/app/views/NotificationPreferencesView/index.js index 31a0fc679..4fad41839 100644 --- a/app/views/NotificationPreferencesView/index.js +++ b/app/views/NotificationPreferencesView/index.js @@ -16,7 +16,7 @@ import RocketChat from '../../lib/rocketchat'; import { withTheme } from '../../theme'; import protectedFunction from '../../lib/methods/helpers/protectedFunction'; import SafeAreaView from '../../containers/SafeAreaView'; -import log from '../../utils/log'; +import log, { events, logEvent } from '../../utils/log'; const SectionTitle = React.memo(({ title, theme }) => ( <Text @@ -71,58 +71,58 @@ Info.propTypes = { const OPTIONS = { desktopNotifications: [{ - label: I18n.t('Default'), value: 'default' + label: 'Default', value: 'default' }, { - label: I18n.t('All_Messages'), value: 'all' + label: 'All_Messages', value: 'all' }, { - label: I18n.t('Mentions'), value: 'mentions' + label: 'Mentions', value: 'mentions' }, { - label: I18n.t('Nothing'), value: 'nothing' + label: 'Nothing', value: 'nothing' }], audioNotifications: [{ - label: I18n.t('Default'), value: 'default' + label: 'Default', value: 'default' }, { - label: I18n.t('All_Messages'), value: 'all' + label: 'All_Messages', value: 'all' }, { - label: I18n.t('Mentions'), value: 'mentions' + label: 'Mentions', value: 'mentions' }, { - label: I18n.t('Nothing'), value: 'nothing' + label: 'Nothing', value: 'nothing' }], mobilePushNotifications: [{ - label: I18n.t('Default'), value: 'default' + label: 'Default', value: 'default' }, { - label: I18n.t('All_Messages'), value: 'all' + label: 'All_Messages', value: 'all' }, { - label: I18n.t('Mentions'), value: 'mentions' + label: 'Mentions', value: 'mentions' }, { - label: I18n.t('Nothing'), value: 'nothing' + label: 'Nothing', value: 'nothing' }], emailNotifications: [{ - label: I18n.t('Default'), value: 'default' + label: 'Default', value: 'default' }, { - label: I18n.t('All_Messages'), value: 'all' + label: 'All_Messages', value: 'all' }, { - label: I18n.t('Mentions'), value: 'mentions' + label: 'Mentions', value: 'mentions' }, { - label: I18n.t('Nothing'), value: 'nothing' + label: 'Nothing', value: 'nothing' }], desktopNotificationDuration: [{ - label: I18n.t('Default'), value: 0 + label: 'Default', value: 0 }, { - label: I18n.t('Seconds', { second: 1 }), value: 1 + label: 'Seconds', second: 1, value: 1 }, { - label: I18n.t('Seconds', { second: 2 }), value: 2 + label: 'Seconds', second: 2, value: 2 }, { - label: I18n.t('Seconds', { second: 3 }), value: 3 + label: 'Seconds', second: 3, value: 3 }, { - label: I18n.t('Seconds', { second: 4 }), value: 4 + label: 'Seconds', second: 4, value: 4 }, { - label: I18n.t('Seconds', { second: 5 }), value: 5 + label: 'Seconds', second: 5, value: 5 }], audioNotificationValue: [{ label: 'None', value: 'none None' }, { - label: I18n.t('Default'), value: '0 Default' + label: 'Default', value: '0 Default' }, { label: 'Beep', value: 'beep Beep' }, { @@ -139,9 +139,9 @@ const OPTIONS = { }; class NotificationPreferencesView extends React.Component { - static navigationOptions = { + static navigationOptions = () => ({ title: I18n.t('Notification_Preferences') - } + }) static propTypes = { navigation: PropTypes.object, @@ -181,6 +181,7 @@ class NotificationPreferencesView extends React.Component { } saveNotificationSettings = async(key, value, params) => { + logEvent(events[`NP_${ key.toUpperCase() }`]); const { room } = this.state; const db = database.active; @@ -206,6 +207,7 @@ class NotificationPreferencesView extends React.Component { })); }); } catch (e) { + logEvent(events[`NP_${ key.toUpperCase() }_F`]); log(e); } } @@ -229,7 +231,7 @@ class NotificationPreferencesView extends React.Component { const { room } = this.state; const { theme } = this.props; const text = room[key] ? OPTIONS[key].find(option => option.value === room[key]) : OPTIONS[key][0]; - return <Text style={[styles.pickerText, { color: themes[theme].actionTintColor }]}>{text?.label}</Text>; + return <Text style={[styles.pickerText, { color: themes[theme].actionTintColor }]}>{I18n.t(text?.label, { defaultValue: text?.label, second: text?.second })}</Text>; } renderSwitch = (key) => { diff --git a/app/views/OnboardingView/index.js b/app/views/OnboardingView/index.js index 0a1ac7383..5be0446c1 100644 --- a/app/views/OnboardingView/index.js +++ b/app/views/OnboardingView/index.js @@ -14,6 +14,7 @@ import { isTablet } from '../../utils/deviceInfo'; import { themes } from '../../constants/colors'; import { withTheme } from '../../theme'; import FormContainer, { FormContainerInner } from '../../containers/FormContainer'; +import { logEvent, events } from '../../utils/log'; class OnboardingView extends React.Component { static navigationOptions = { @@ -69,15 +70,17 @@ class OnboardingView extends React.Component { } connectServer = () => { + logEvent(events.ONBOARD_JOIN_A_WORKSPACE); const { navigation } = this.props; navigation.navigate('NewServerView'); } createWorkspace = async() => { + logEvent(events.ONBOARD_CREATE_NEW_WORKSPACE); try { await Linking.openURL('https://cloud.rocket.chat/trial'); } catch { - // do nothing + logEvent(events.ONBOARD_CREATE_NEW_WORKSPACE_F); } } diff --git a/app/views/PickerView.js b/app/views/PickerView.js index 489d8a42f..062e373ab 100644 --- a/app/views/PickerView.js +++ b/app/views/PickerView.js @@ -42,7 +42,7 @@ const Item = React.memo(({ theme }) => ( <ListItem - title={item.label} + title={I18n.t(item.label, { defaultValue: item.label, second: item?.second })} right={selected && (() => <Check theme={theme} style={styles.check} />)} onPress={onItemPress} theme={theme} diff --git a/app/views/ProfileView/index.js b/app/views/ProfileView/index.js index f6155c2a2..8d289935b 100644 --- a/app/views/ProfileView/index.js +++ b/app/views/ProfileView/index.js @@ -18,7 +18,7 @@ import { LISTENER } from '../../containers/Toast'; import EventEmitter from '../../utils/events'; import RocketChat from '../../lib/rocketchat'; import RCTextInput from '../../containers/TextInput'; -import log from '../../utils/log'; +import log, { logEvent, events } from '../../utils/log'; import I18n from '../../i18n'; import Button from '../../containers/Button'; import Avatar from '../../containers/Avatar'; @@ -223,8 +223,10 @@ class ProfileView extends React.Component { try { if (avatar.url) { try { + logEvent(events.PROFILE_SAVE_AVATAR); await RocketChat.setAvatarFromService(avatar); } catch (e) { + logEvent(events.PROFILE_SAVE_AVATAR_F); this.setState({ saving: false, currentPassword: null }); return this.handleError(e, 'setAvatarFromService', 'changing_avatar'); } @@ -233,6 +235,7 @@ class ProfileView extends React.Component { const result = await RocketChat.saveUserProfile(params, customFields); if (result.success) { + logEvent(events.PROFILE_SAVE_CHANGES); if (customFields) { setUser({ customFields, ...params }); } else { @@ -243,6 +246,7 @@ class ProfileView extends React.Component { } this.setState({ saving: false }); } catch (e) { + logEvent(events.PROFILE_SAVE_CHANGES_F); this.setState({ saving: false, currentPassword: null }); this.handleError(e, 'saveUserProfile', 'saving_profile'); } @@ -281,13 +285,20 @@ class ProfileView extends React.Component { includeBase64: true }; try { + logEvent(events.PROFILE_PICK_AVATAR); const response = await ImagePicker.openPicker(options); this.setAvatar({ url: response.path, data: `data:image/jpeg;base64,${ response.data }`, service: 'upload' }); } catch (error) { + logEvent(events.PROFILE_PICK_AVATAR_F); console.warn(error); } } + pickImageWithURL = (avatarUrl) => { + logEvent(events.PROFILE_PICK_AVATAR_WITH_URL); + this.setAvatar({ url: avatarUrl, data: avatarUrl, service: 'url' }); + } + renderAvatarButton = ({ key, child, onPress, disabled = false }) => { @@ -331,7 +342,7 @@ class ProfileView extends React.Component { })} {this.renderAvatarButton({ child: <CustomIcon name='link' size={30} color={themes[theme].bodyText} />, - onPress: () => this.setAvatar({ url: avatarUrl, data: avatarUrl, service: 'url' }), + onPress: () => this.pickImageWithURL(avatarUrl), disabled: !avatarUrl, key: 'profile-view-avatar-url-button' })} diff --git a/app/views/QueueListView.js b/app/views/QueueListView.js new file mode 100644 index 000000000..301f09a0f --- /dev/null +++ b/app/views/QueueListView.js @@ -0,0 +1,160 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { FlatList } from 'react-native'; +import { connect } from 'react-redux'; +import isEqual from 'react-fast-compare'; + +import I18n from '../i18n'; +import RoomItem, { ROW_HEIGHT } from '../presentation/RoomItem'; +import { MAX_SIDEBAR_WIDTH } from '../constants/tablet'; +import { isTablet, isIOS } from '../utils/deviceInfo'; +import { getUserSelector } from '../selectors/login'; +import { withTheme } from '../theme'; +import { withDimensions } from '../dimensions'; +import SafeAreaView from '../containers/SafeAreaView'; +import { themes } from '../constants/colors'; +import StatusBar from '../containers/StatusBar'; +import { goRoom } from '../utils/goRoom'; +import { CloseModalButton } from '../containers/HeaderButton'; +import RocketChat from '../lib/rocketchat'; +import { logEvent, events } from '../utils/log'; +import { getInquiryQueueSelector } from '../selectors/inquiry'; + +const INITIAL_NUM_TO_RENDER = isTablet ? 20 : 12; +const getItemLayout = (data, index) => ({ + length: ROW_HEIGHT, + offset: ROW_HEIGHT * index, + index +}); +const keyExtractor = item => item.rid; + +class QueueListView extends React.Component { + static navigationOptions = ({ navigation, isMasterDetail }) => { + const options = { + title: I18n.t('Queued_chats') + }; + if (isMasterDetail) { + options.headerLeft = () => <CloseModalButton navigation={navigation} testID='directory-view-close' />; + } + return options; + } + + static propTypes = { + user: PropTypes.shape({ + id: PropTypes.string, + username: PropTypes.string, + token: PropTypes.string + }), + isMasterDetail: PropTypes.bool, + width: PropTypes.number, + queued: PropTypes.array, + server: PropTypes.string, + useRealName: PropTypes.bool, + navigation: PropTypes.object, + theme: PropTypes.string + } + + shouldComponentUpdate(nextProps) { + const { queued } = this.props; + if (!isEqual(nextProps.queued, queued)) { + return true; + } + + return false; + } + + onPressItem = (item = {}) => { + logEvent(events.QL_GO_ROOM); + const { navigation, isMasterDetail } = this.props; + if (isMasterDetail) { + navigation.navigate('DrawerNavigator'); + } else { + navigation.navigate('RoomsListView'); + } + + goRoom({ + item: { + ...item, + // we're calling v as visitor on our mergeSubscriptionsRooms + visitor: item.v + }, + isMasterDetail + }); + }; + + getRoomTitle = item => RocketChat.getRoomTitle(item) + + getRoomAvatar = item => RocketChat.getRoomAvatar(item) + + getUidDirectMessage = room => RocketChat.getUidDirectMessage(room) + + renderItem = ({ item }) => { + const { + user: { + id: userId, + username, + token + }, + server, + useRealName, + theme, + isMasterDetail, + width + } = this.props; + const id = this.getUidDirectMessage(item); + + return ( + <RoomItem + item={item} + theme={theme} + id={id} + type={item.t} + userId={userId} + username={username} + token={token} + baseUrl={server} + onPress={this.onPressItem} + testID={`queue-list-view-item-${ item.name }`} + width={isMasterDetail ? MAX_SIDEBAR_WIDTH : width} + useRealName={useRealName} + getRoomTitle={this.getRoomTitle} + getRoomAvatar={this.getRoomAvatar} + visitor={item.v} + swipeEnabled={false} + /> + ); + } + + render() { + const { queued, theme } = this.props; + return ( + <SafeAreaView testID='queue-list-view' theme={theme} style={{ backgroundColor: themes[theme].backgroundColor }}> + <StatusBar theme={theme} /> + <FlatList + ref={this.getScrollRef} + data={queued} + extraData={queued} + keyExtractor={keyExtractor} + style={{ backgroundColor: themes[theme].backgroundColor }} + renderItem={this.renderItem} + getItemLayout={getItemLayout} + removeClippedSubviews={isIOS} + keyboardShouldPersistTaps='always' + initialNumToRender={INITIAL_NUM_TO_RENDER} + windowSize={9} + onEndReached={this.onEndReached} + onEndReachedThreshold={0.5} + /> + </SafeAreaView> + ); + } +} + +const mapStateToProps = state => ({ + user: getUserSelector(state), + isMasterDetail: state.app.isMasterDetail, + server: state.server.server, + useRealName: state.settings.UI_Use_Real_Name, + queued: getInquiryQueueSelector(state) +}); +export default connect(mapStateToProps)(withDimensions(withTheme(QueueListView))); diff --git a/app/views/ReadReceiptView/index.js b/app/views/ReadReceiptView/index.js index c5ea398a9..9ec188d0d 100644 --- a/app/views/ReadReceiptView/index.js +++ b/app/views/ReadReceiptView/index.js @@ -8,6 +8,7 @@ import { connect } from 'react-redux'; import Avatar from '../../containers/Avatar'; import styles from './styles'; import ActivityIndicator from '../../containers/ActivityIndicator'; +import { CloseModalButton } from '../../containers/HeaderButton'; import I18n from '../../i18n'; import RocketChat from '../../lib/rocketchat'; import StatusBar from '../../containers/StatusBar'; @@ -17,8 +18,14 @@ import { getUserSelector } from '../../selectors/login'; import SafeAreaView from '../../containers/SafeAreaView'; class ReadReceiptView extends React.Component { - static navigationOptions = { - title: I18n.t('Read_Receipt') + static navigationOptions = ({ navigation, isMasterDetail }) => { + const options = { + title: I18n.t('Read_Receipt') + }; + if (isMasterDetail) { + options.headerLeft = () => <CloseModalButton navigation={navigation} testID='read-receipt-view-close' />; + } + return options; } static propTypes = { diff --git a/app/views/RegisterView.js b/app/views/RegisterView.js index 1e0ce2654..23711a7cd 100644 --- a/app/views/RegisterView.js +++ b/app/views/RegisterView.js @@ -6,7 +6,7 @@ import { import { connect } from 'react-redux'; import RNPickerSelect from 'react-native-picker-select'; -import log from '../utils/log'; +import log, { logEvent, events } from '../utils/log'; import sharedStyles from './Styles'; import Button from '../containers/Button'; import I18n from '../i18n'; @@ -114,6 +114,7 @@ class RegisterView extends React.Component { } submit = async() => { + logEvent(events.REGISTER_DEFAULT_SIGN_UP); if (!this.valid()) { return; } @@ -149,6 +150,7 @@ class RegisterView extends React.Component { return loginRequest({ user: email, password }); } if (e.data?.error) { + logEvent(events.REGISTER_DEFAULT_SIGN_UP_F); showErrorAlert(e.data.error, I18n.t('Oops')); } } diff --git a/app/views/RoomActionsView/index.js b/app/views/RoomActionsView/index.js index 67aff37e4..13070fb49 100644 --- a/app/views/RoomActionsView/index.js +++ b/app/views/RoomActionsView/index.js @@ -14,7 +14,7 @@ import sharedStyles from '../Styles'; import Avatar from '../../containers/Avatar'; import Status from '../../containers/Status'; import RocketChat from '../../lib/rocketchat'; -import log from '../../utils/log'; +import log, { logEvent, events } from '../../utils/log'; import RoomTypeIcon from '../../containers/RoomTypeIcon'; import I18n from '../../i18n'; import scrollPersistTaps from '../../utils/scrollPersistTaps'; @@ -91,7 +91,7 @@ class RoomActionsView extends React.Component { this.mounted = true; const { room, member } = this.state; if (room.rid) { - if (!room.id) { + if (!room.id && !this.isOmnichannelPreview) { try { const result = await RocketChat.getChannelInfo(room.rid); if (result.success) { @@ -135,13 +135,20 @@ class RoomActionsView extends React.Component { } } + get isOmnichannelPreview() { + const { room } = this.state; + return room.t === 'l' && room.status === 'queued'; + } + onPressTouchable = (item) => { - if (item.route) { + const { route, event, params } = item; + if (route) { + logEvent(events[`RA_GO_${ route.replace('View', '').toUpperCase() }${ params.name ? params.name.toUpperCase() : '' }`]); const { navigation } = this.props; - navigation.navigate(item.route, item.params); + navigation.navigate(route, params); } - if (item.event) { - return item.event(); + if (event) { + return event(); } } @@ -229,7 +236,7 @@ class RoomActionsView extends React.Component { const isGroupChat = RocketChat.isGroupChat(room); const notificationsAction = { - icon: 'bell', + icon: 'notification', name: I18n.t('Notifications'), route: 'NotificationPrefView', params: { rid, room }, @@ -238,13 +245,13 @@ class RoomActionsView extends React.Component { const jitsiActions = jitsiEnabled ? [ { - icon: 'mic', + icon: 'phone', name: I18n.t('Voice_call'), event: () => RocketChat.callJitsi(rid, true), testID: 'room-actions-voice' }, { - icon: 'video-1', + icon: 'camera', name: I18n.t('Video_call'), event: () => RocketChat.callJitsi(rid), testID: 'room-actions-video' @@ -270,14 +277,14 @@ class RoomActionsView extends React.Component { }, { data: [ { - icon: 'clip', + icon: 'attach', name: I18n.t('Files'), route: 'MessagesView', params: { rid, t, name: 'Files' }, testID: 'room-actions-files' }, { - icon: 'at', + icon: 'mention', name: I18n.t('Mentions'), route: 'MessagesView', params: { rid, t, name: 'Mentions' }, @@ -291,7 +298,7 @@ class RoomActionsView extends React.Component { testID: 'room-actions-starred' }, { - icon: 'magnifier', + icon: 'search', name: I18n.t('Search'), route: 'SearchMessagesView', params: { rid }, @@ -365,7 +372,7 @@ class RoomActionsView extends React.Component { if (canAddUser) { actions.push({ - icon: 'plus', + icon: 'add', name: I18n.t('Add_users'), route: 'SelectedUsersView', params: { @@ -378,7 +385,7 @@ class RoomActionsView extends React.Component { } if (canInviteUser) { actions.push({ - icon: 'add-user', + icon: 'user-add', name: I18n.t('Invite_users'), route: 'InviteUsersView', params: { @@ -394,7 +401,7 @@ class RoomActionsView extends React.Component { sections.push({ data: [ { - icon: 'exit', + icon: 'logout', name: I18n.t('Leave_channel'), type: 'danger', event: this.leaveChannel, @@ -407,36 +414,38 @@ class RoomActionsView extends React.Component { } else if (t === 'l') { sections[2].data = []; - sections[2].data.push({ - icon: 'cancel', - name: I18n.t('Close'), - event: this.closeLivechat - }); - - if (canForwardGuest) { + if (!this.isOmnichannelPreview) { sections[2].data.push({ - icon: 'transfer', - name: I18n.t('Forward'), - route: 'ForwardLivechatView', + icon: 'close', + name: I18n.t('Close'), + event: this.closeLivechat + }); + + if (canForwardGuest) { + sections[2].data.push({ + icon: 'user-forward', + name: I18n.t('Forward'), + route: 'ForwardLivechatView', + params: { rid } + }); + } + + if (canReturnQueue) { + sections[2].data.push({ + icon: 'undo', + name: I18n.t('Return'), + event: this.returnLivechat + }); + } + + sections[2].data.push({ + icon: 'history', + name: I18n.t('Navigation_history'), + route: 'VisitorNavigationView', params: { rid } }); } - if (canReturnQueue) { - sections[2].data.push({ - icon: 'undo', - name: I18n.t('Return'), - event: this.returnLivechat - }); - } - - sections[2].data.push({ - icon: 'history', - name: I18n.t('Navigation_history'), - route: 'VisitorNavigationView', - params: { rid } - }); - sections.push({ data: [notificationsAction], renderItem: this.renderItem @@ -506,17 +515,20 @@ class RoomActionsView extends React.Component { } toggleBlockUser = () => { + logEvent(events.RA_TOGGLE_BLOCK_USER); const { room } = this.state; const { rid, blocker } = room; const { member } = this.state; try { RocketChat.toggleBlockUser(rid, member._id, !blocker); } catch (e) { + logEvent(events.RA_TOGGLE_BLOCK_USER_F); log(e); } } handleShare = () => { + logEvent(events.RA_SHARE); const { room } = this.state; const permalink = RocketChat.getPermalinkChannel(room); if (!permalink) { diff --git a/app/views/RoomInfoEditView/index.js b/app/views/RoomInfoEditView/index.js index 5db7c7883..4d913e1cd 100644 --- a/app/views/RoomInfoEditView/index.js +++ b/app/views/RoomInfoEditView/index.js @@ -23,7 +23,7 @@ import RCTextInput from '../../containers/TextInput'; import Loading from '../../containers/Loading'; import SwitchContainer from './SwitchContainer'; import random from '../../utils/random'; -import log from '../../utils/log'; +import log, { logEvent, events } from '../../utils/log'; import I18n from '../../i18n'; import StatusBar from '../../containers/StatusBar'; import { themes } from '../../constants/colors'; @@ -48,9 +48,9 @@ const PERMISSIONS_ARRAY = [ ]; class RoomInfoEditView extends React.Component { - static navigationOptions = { + static navigationOptions = () => ({ title: I18n.t('Room_Info_Edit') - } + }) static propTypes = { route: PropTypes.object, @@ -150,6 +150,7 @@ class RoomInfoEditView extends React.Component { } reset = () => { + logEvent(events.RI_EDIT_RESET); this.clearErrors(); this.init(this.room); } @@ -173,6 +174,7 @@ class RoomInfoEditView extends React.Component { } submit = async() => { + logEvent(events.RI_EDIT_SAVE); Keyboard.dismiss(); const { room, name, description, topic, announcement, t, ro, reactWhenReadOnly, joinCode, systemMessages @@ -242,6 +244,7 @@ class RoomInfoEditView extends React.Component { await this.setState({ saving: false }); setTimeout(() => { if (error) { + logEvent(events.RI_EDIT_SAVE_F); showErrorAlert(I18n.t('There_was_an_error_while_action', { action: I18n.t('saving_settings') })); } else { EventEmitter.emit(LISTENER, { message: I18n.t('Settings_succesfully_changed') }); @@ -289,8 +292,10 @@ class RoomInfoEditView extends React.Component { style: 'destructive', onPress: async() => { try { + logEvent(events.RI_EDIT_TOGGLE_ARCHIVE); await RocketChat.toggleArchiveRoom(rid, t, !archived); } catch (e) { + logEvent(events.RI_EDIT_TOGGLE_ARCHIVE_F); log(e); } } @@ -333,6 +338,26 @@ class RoomInfoEditView extends React.Component { ); } + toggleRoomType = (value) => { + logEvent(events.RI_EDIT_TOGGLE_ROOM_TYPE); + this.setState({ t: value }); + } + + toggleReadOnly = (value) => { + logEvent(events.RI_EDIT_TOGGLE_READ_ONLY); + this.setState({ ro: value }); + } + + toggleReactions = (value) => { + logEvent(events.RI_EDIT_TOGGLE_REACTIONS); + this.setState({ reactWhenReadOnly: value }); + } + + toggleHideSystemMessages = (value) => { + logEvent(events.RI_EDIT_TOGGLE_SYSTEM_MSG); + this.setState(({ systemMessages }) => ({ enableSysMes: value, systemMessages: value ? systemMessages : [] })); + } + render() { const { name, nameError, description, topic, announcement, t, ro, reactWhenReadOnly, room, joinCode, saving, permissions, archived, enableSysMes @@ -410,7 +435,7 @@ class RoomInfoEditView extends React.Component { leftLabelSecondary={I18n.t('Everyone_can_access_this_channel')} rightLabelPrimary={I18n.t('Private')} rightLabelSecondary={I18n.t('Just_invited_people_can_access_this_channel')} - onValueChange={value => this.setState({ t: value })} + onValueChange={this.toggleRoomType} theme={theme} testID='room-info-edit-view-t' /> @@ -420,7 +445,7 @@ class RoomInfoEditView extends React.Component { leftLabelSecondary={I18n.t('All_users_in_the_channel_can_write_new_messages')} rightLabelPrimary={I18n.t('Read_Only')} rightLabelSecondary={I18n.t('Only_authorized_users_can_write_new_messages')} - onValueChange={value => this.setState({ ro: value })} + onValueChange={this.toggleReadOnly} disabled={!permissions[PERMISSION_SET_READONLY] || room.broadcast} theme={theme} testID='room-info-edit-view-ro' @@ -433,7 +458,7 @@ class RoomInfoEditView extends React.Component { leftLabelSecondary={I18n.t('Reactions_are_disabled')} rightLabelPrimary={I18n.t('Allow_Reactions')} rightLabelSecondary={I18n.t('Reactions_are_enabled')} - onValueChange={value => this.setState({ reactWhenReadOnly: value })} + onValueChange={this.toggleReactions} disabled={!permissions[PERMISSION_SET_REACT_WHEN_READONLY]} theme={theme} testID='room-info-edit-view-react-when-ro' @@ -455,7 +480,7 @@ class RoomInfoEditView extends React.Component { leftLabelSecondary={enableSysMes ? I18n.t('Overwrites_the_server_configuration_and_use_room_config') : I18n.t('Uses_server_configuration')} theme={theme} testID='room-info-edit-switch-system-messages' - onValueChange={value => this.setState(({ systemMessages }) => ({ enableSysMes: value, systemMessages: value ? systemMessages : [] }))} + onValueChange={this.toggleHideSystemMessages} labelContainerStyle={styles.hideSystemMessages} leftLabelStyle={styles.systemMessagesLabel} > diff --git a/app/views/RoomInfoView/Livechat.js b/app/views/RoomInfoView/Livechat.js index a93ea1714..09e14a608 100644 --- a/app/views/RoomInfoView/Livechat.js +++ b/app/views/RoomInfoView/Livechat.js @@ -44,7 +44,7 @@ const Livechat = ({ room, roomUser, theme }) => { } }; - useEffect(() => { getRoom(); }, []); + useEffect(() => { getRoom(); }, [room]); return ( <> diff --git a/app/views/RoomInfoView/index.js b/app/views/RoomInfoView/index.js index b3711b0f4..a0160d517 100644 --- a/app/views/RoomInfoView/index.js +++ b/app/views/RoomInfoView/index.js @@ -17,11 +17,13 @@ import RoomTypeIcon from '../../containers/RoomTypeIcon'; import I18n from '../../i18n'; import { CustomHeaderButtons, CloseModalButton } from '../../containers/HeaderButton'; import StatusBar from '../../containers/StatusBar'; -import log from '../../utils/log'; +import log, { logEvent, events } from '../../utils/log'; import { themes } from '../../constants/colors'; import { withTheme } from '../../theme'; import { getUserSelector } from '../../selectors/login'; import Markdown from '../../containers/markdown'; +import { LISTENER } from '../../containers/Toast'; +import EventEmitter from '../../utils/events'; import Livechat from './Livechat'; import Channel from './Channel'; @@ -59,7 +61,8 @@ class RoomInfoView extends React.Component { baseUrl: PropTypes.string, rooms: PropTypes.array, theme: PropTypes.string, - isMasterDetail: PropTypes.bool + isMasterDetail: PropTypes.bool, + jitsiEnabled: PropTypes.bool } constructor(props) { @@ -114,7 +117,11 @@ class RoomInfoView extends React.Component { <CustomHeaderButtons> <Item iconName='edit' - onPress={() => navigation.navigate(t === 'l' ? 'LivechatEditView' : 'RoomInfoEditView', { rid, room, roomUser })} + onPress={() => { + const isLivechat = t === 'l'; + logEvent(events[`RI_GO_${ isLivechat ? 'LIVECHAT' : 'RI' }_EDIT`]); + navigation.navigate(isLivechat ? 'LivechatEditView' : 'RoomInfoEditView', { rid, room, roomUser }); + }} testID='room-info-view-edit-button' /> </CustomHeaderButtons> @@ -167,11 +174,11 @@ class RoomInfoView extends React.Component { } loadUser = async() => { - const { room: roomState, roomUser } = this.state; + const { room, roomUser } = this.state; if (_.isEmpty(roomUser)) { try { - const roomUserId = RocketChat.getUidDirectMessage(roomState); + const roomUserId = RocketChat.getUidDirectMessage(room); const result = await RocketChat.getUserInfo(roomUserId); if (result.success) { const { user } = result; @@ -183,9 +190,7 @@ class RoomInfoView extends React.Component { })); } - const room = await this.getDirect(user.username); - - this.setState({ roomUser: user, room: { ...roomState, rid: room.rid } }); + this.setState({ roomUser: user }); } } catch { // do nothing @@ -194,6 +199,7 @@ class RoomInfoView extends React.Component { } loadRoom = async() => { + const { room: roomState } = this.state; const { route } = this.props; let room = route.params?.room; if (room && room.observe) { @@ -207,7 +213,7 @@ class RoomInfoView extends React.Component { const result = await RocketChat.getRoomInfo(this.rid); if (result.success) { ({ room } = result); - this.setState({ room }); + this.setState({ room: { ...roomState, ...room } }); } } catch (e) { log(e); @@ -220,18 +226,31 @@ class RoomInfoView extends React.Component { } } - getDirect = async(username) => { + createDirect = () => new Promise(async(resolve, reject) => { + const { route } = this.props; + + // We don't need to create a direct + const member = route.params?.member; + if (!_.isEmpty(member)) { + return resolve(); + } + + // TODO: Check if some direct with the user already exists on database try { + const { roomUser: { username } } = this.state; const result = await RocketChat.createDirectMessage(username); if (result.success) { - return result.room; + const { room: { rid } } = result; + return this.setState(({ room }) => ({ room: { ...room, rid } }), resolve); } } catch { // do nothing } - } + reject(); + }) goRoom = () => { + logEvent(events.RI_GO_ROOM_USER); const { roomUser, room } = this.state; const { name, username } = roomUser; const { rooms, navigation, isMasterDetail } = this.props; @@ -287,9 +306,19 @@ class RoomInfoView extends React.Component { renderButton = (onPress, iconName, text) => { const { theme } = this.props; + + const onActionPress = async() => { + try { + await this.createDirect(); + onPress(); + } catch { + EventEmitter.emit(LISTENER, { message: I18n.t('error-action-not-allowed', { action: I18n.t('Create_Direct_Messages') }) }); + } + }; + return ( <BorderlessButton - onPress={onPress} + onPress={onActionPress} style={styles.roomButton} > <CustomIcon @@ -302,12 +331,15 @@ class RoomInfoView extends React.Component { ); } - renderButtons = () => ( - <View style={styles.roomButtonsContainer}> - {this.renderButton(this.goRoom, 'message', I18n.t('Message'))} - {this.renderButton(this.videoCall, 'video-1', I18n.t('Video_call'))} - </View> - ) + renderButtons = () => { + const { jitsiEnabled } = this.props; + return ( + <View style={styles.roomButtonsContainer}> + {this.renderButton(this.goRoom, 'message', I18n.t('Message'))} + {jitsiEnabled ? this.renderButton(this.videoCall, 'camera', I18n.t('Video_call')) : null} + </View> + ); + } renderContent = () => { const { room, roomUser } = this.state; @@ -348,7 +380,8 @@ const mapStateToProps = state => ({ baseUrl: state.server.server, user: getUserSelector(state), rooms: state.room.rooms, - isMasterDetail: state.app.isMasterDetail + isMasterDetail: state.app.isMasterDetail, + jitsiEnabled: state.settings.Jitsi_Enabled || false }); export default connect(mapStateToProps)(withTheme(RoomInfoView)); diff --git a/app/views/RoomMembersView/index.js b/app/views/RoomMembersView/index.js index 8134e9183..cb6c7b7d4 100644 --- a/app/views/RoomMembersView/index.js +++ b/app/views/RoomMembersView/index.js @@ -146,7 +146,7 @@ class RoomMembersView extends React.Component { showActionSheet({ options: [{ - icon: userIsMuted ? 'volume' : 'volume-off', + icon: userIsMuted ? 'audio' : 'audio-disabled', title: I18n.t(userIsMuted ? 'Unmute' : 'Mute'), onPress: () => { showConfirmationAlert({ diff --git a/app/views/RoomView/Banner.js b/app/views/RoomView/Banner.js index af6cd3002..5ee5bb9a2 100644 --- a/app/views/RoomView/Banner.js +++ b/app/views/RoomView/Banner.js @@ -35,7 +35,7 @@ const Banner = React.memo(({ <BorderlessButton onPress={closeBanner}> <CustomIcon color={themes[theme].auxiliaryText} - name='Cross' + name='close' size={20} /> </BorderlessButton> diff --git a/app/views/RoomView/Header/Icon.js b/app/views/RoomView/Header/Icon.js index 7de286c24..7eaa02ad0 100644 --- a/app/views/RoomView/Header/Icon.js +++ b/app/views/RoomView/Header/Icon.js @@ -36,17 +36,17 @@ const Icon = React.memo(({ let icon; if (type === 'discussion') { - icon = 'chat'; + icon = 'discussions'; } else if (type === 'thread') { icon = 'threads'; } else if (type === 'c') { - icon = 'hash'; + icon = 'channel-public'; } else if (type === 'l') { - icon = 'livechat'; + icon = 'omnichannel'; } else if (type === 'd') { icon = 'team'; } else { - icon = 'lock'; + icon = 'channel-private'; } return ( <CustomIcon diff --git a/app/views/RoomView/Header/RightButtons.js b/app/views/RoomView/Header/RightButtons.js index 201866fe6..b554b41cc 100644 --- a/app/views/RoomView/Header/RightButtons.js +++ b/app/views/RoomView/Header/RightButtons.js @@ -5,6 +5,7 @@ import { connect } from 'react-redux'; import { CustomHeaderButtons, Item } from '../../../containers/HeaderButton'; import database from '../../../lib/database'; import { getUserSelector } from '../../../selectors/login'; +import { logEvent, events } from '../../../utils/log'; class RightButtonsContainer extends React.PureComponent { static propTypes = { @@ -58,6 +59,7 @@ class RightButtonsContainer extends React.PureComponent { } goThreadsView = () => { + logEvent(events.ROOM_GO_THREADS); const { rid, t, navigation, isMasterDetail } = this.props; @@ -69,6 +71,7 @@ class RightButtonsContainer extends React.PureComponent { } goSearchView = () => { + logEvent(events.ROOM_GO_SEARCH); const { rid, navigation, isMasterDetail } = this.props; @@ -80,6 +83,7 @@ class RightButtonsContainer extends React.PureComponent { } toggleFollowThread = () => { + logEvent(events.ROOM_TOGGLE_FOLLOW_THREADS); const { isFollowingThread } = this.state; const { toggleFollowThread } = this.props; if (toggleFollowThread) { @@ -98,7 +102,7 @@ class RightButtonsContainer extends React.PureComponent { <CustomHeaderButtons> <Item title='bell' - iconName={isFollowingThread ? 'bell' : 'bell-off'} + iconName={isFollowingThread ? 'notification' : 'notification-disabled'} onPress={this.toggleFollowThread} testID={isFollowingThread ? 'room-view-header-unfollow' : 'room-view-header-follow'} /> @@ -117,7 +121,7 @@ class RightButtonsContainer extends React.PureComponent { ) : null} <Item title='search' - iconName='magnifier' + iconName='search' onPress={this.goSearchView} testID='room-view-search' /> diff --git a/app/views/RoomView/List.js b/app/views/RoomView/List.js index d0dc7c88d..209ec18bb 100644 --- a/app/views/RoomView/List.js +++ b/app/views/RoomView/List.js @@ -1,7 +1,6 @@ import React from 'react'; import { FlatList, RefreshControl } from 'react-native'; import PropTypes from 'prop-types'; -import orderBy from 'lodash/orderBy'; import { Q } from '@nozbe/watermelondb'; import moment from 'moment'; import isEqual from 'lodash/isEqual'; @@ -15,9 +14,10 @@ import EmptyRoom from './EmptyRoom'; import { isIOS } from '../../utils/deviceInfo'; import { animateNextTransition } from '../../utils/layoutAnimation'; import ActivityIndicator from '../../containers/ActivityIndicator'; -import debounce from '../../utils/debounce'; import { themes } from '../../constants/colors'; +const QUERY_SIZE = 50; + class List extends React.Component { static propTypes = { onEndReached: PropTypes.func, @@ -47,7 +47,8 @@ class List extends React.Component { super(props); console.time(`${ this.constructor.name } init`); console.time(`${ this.constructor.name } mount`); - + this.count = 0; + this.needsFetch = false; this.mounted = false; this.state = { loading: true, @@ -56,7 +57,7 @@ class List extends React.Component { refreshing: false, animated: false }; - this.init(); + this.query(); this.unsubscribeFocus = props.navigation.addListener('focus', () => { if (this.mounted) { this.setState({ animated: true }); @@ -72,72 +73,6 @@ class List extends React.Component { console.timeEnd(`${ this.constructor.name } mount`); } - // eslint-disable-next-line react/sort-comp - async init() { - const { rid, tmid } = this.props; - const db = database.active; - - // handle servers with version < 3.0.0 - let { hideSystemMessages = [] } = this.props; - if (!Array.isArray(hideSystemMessages)) { - hideSystemMessages = []; - } - - if (tmid) { - try { - this.thread = await db.collections - .get('threads') - .find(tmid); - } catch (e) { - console.log(e); - } - this.messagesObservable = db.collections - .get('thread_messages') - .query(Q.where('rid', tmid), Q.or(Q.where('t', Q.notIn(hideSystemMessages)), Q.where('t', Q.eq(null)))) - .observe(); - } else if (rid) { - this.messagesObservable = db.collections - .get('messages') - .query(Q.where('rid', rid), Q.or(Q.where('t', Q.notIn(hideSystemMessages)), Q.where('t', Q.eq(null)))) - .observe(); - } - - if (rid) { - this.unsubscribeMessages(); - this.messagesSubscription = this.messagesObservable - .subscribe((data) => { - if (tmid && this.thread) { - data = [this.thread, ...data]; - } - const messages = orderBy(data, ['ts'], ['desc']); - if (this.mounted) { - this.setState({ messages }, () => this.update()); - } else { - this.state.messages = messages; - } - this.readThreads(); - }); - } - } - - // eslint-disable-next-line react/sort-comp - reload = () => { - this.unsubscribeMessages(); - this.init(); - } - - readThreads = async() => { - const { tmid } = this.props; - - if (tmid) { - try { - await RocketChat.readThreads(tmid); - } catch { - // Do nothing - } - } - } - shouldComponentUpdate(nextProps, nextState) { const { loading, end, refreshing } = this.state; const { hideSystemMessages, theme } = this.props; @@ -177,7 +112,7 @@ class List extends React.Component { console.countReset(`${ this.constructor.name }.render calls`); } - onEndReached = debounce(async() => { + fetchData = async() => { const { loading, end, messages, latest = messages[messages.length - 1]?.ts } = this.state; @@ -196,12 +131,99 @@ class List extends React.Component { result = await RocketChat.loadMessagesForRoom({ rid, t, latest }); } - this.setState({ end: result.length < 50, loading: false, latest: result[result.length - 1]?.ts }, () => this.loadMoreMessages(result)); + this.setState({ end: result.length < QUERY_SIZE, loading: false, latest: result[result.length - 1]?.ts }, () => this.loadMoreMessages(result)); } catch (e) { this.setState({ loading: false }); log(e); } - }, 300) + } + + query = async() => { + this.count += QUERY_SIZE; + const { rid, tmid } = this.props; + const db = database.active; + + // handle servers with version < 3.0.0 + let { hideSystemMessages = [] } = this.props; + if (!Array.isArray(hideSystemMessages)) { + hideSystemMessages = []; + } + + if (tmid) { + try { + this.thread = await db.collections + .get('threads') + .find(tmid); + } catch (e) { + console.log(e); + } + this.messagesObservable = db.collections + .get('thread_messages') + .query( + Q.where('rid', tmid), + Q.experimentalSortBy('ts', Q.desc), + Q.experimentalSkip(0), + Q.experimentalTake(this.count) + ) + .observe(); + } else if (rid) { + this.messagesObservable = db.collections + .get('messages') + .query( + Q.where('rid', rid), + Q.experimentalSortBy('ts', Q.desc), + Q.experimentalSkip(0), + Q.experimentalTake(this.count) + ) + .observe(); + } + + if (rid) { + this.unsubscribeMessages(); + this.messagesSubscription = this.messagesObservable + .subscribe((messages) => { + if (messages.length <= this.count) { + this.needsFetch = true; + } + if (tmid && this.thread) { + messages = [...messages, this.thread]; + } + messages = messages.filter(m => !m.t || !hideSystemMessages?.includes(m.t)); + + if (this.mounted) { + this.setState({ messages }, () => this.update()); + } else { + this.state.messages = messages; + } + this.readThreads(); + }); + } + } + + reload = () => { + this.count = 0; + this.query(); + } + + readThreads = async() => { + const { tmid } = this.props; + + if (tmid) { + try { + await RocketChat.readThreads(tmid); + } catch { + // Do nothing + } + } + } + + onEndReached = async() => { + if (this.needsFetch) { + this.needsFetch = false; + await this.fetchData(); + } + this.query(); + } loadMoreMessages = (result) => { const { end } = this.state; @@ -305,7 +327,7 @@ class List extends React.Component { removeClippedSubviews={isIOS} initialNumToRender={7} onEndReached={this.onEndReached} - onEndReachedThreshold={5} + onEndReachedThreshold={0.5} maxToRenderPerBatch={5} windowSize={10} ListFooterComponent={this.renderFooter} diff --git a/app/views/RoomView/UploadProgress.js b/app/views/RoomView/UploadProgress.js index d4d8f2a51..ab17efc8b 100644 --- a/app/views/RoomView/UploadProgress.js +++ b/app/views/RoomView/UploadProgress.js @@ -172,11 +172,11 @@ class UploadProgress extends Component { return ( [ <View key='row' style={styles.row}> - <CustomIcon name='clip' size={20} color={themes[theme].auxiliaryText} /> + <CustomIcon name='attach' size={20} color={themes[theme].auxiliaryText} /> <Text style={[styles.descriptionContainer, styles.descriptionText, { color: themes[theme].auxiliaryText }]} numberOfLines={1}> {I18n.t('Uploading')} {item.name} </Text> - <CustomIcon name='Cross' size={20} color={themes[theme].auxiliaryText} onPress={() => this.cancelUpload(item)} /> + <CustomIcon name='close' size={20} color={themes[theme].auxiliaryText} onPress={() => this.cancelUpload(item)} /> </View>, <View key='progress' style={[styles.progress, { width: (width * item.progress) / 100, backgroundColor: themes[theme].tintColor }]} /> ] @@ -191,7 +191,7 @@ class UploadProgress extends Component { <Text style={[styles.tryAgainButtonText, { color: themes[theme].tintColor }]}>{I18n.t('Try_again')}</Text> </TouchableOpacity> </View> - <CustomIcon name='Cross' size={20} color={themes[theme].auxiliaryText} onPress={() => this.deleteUpload(item)} /> + <CustomIcon name='close' size={20} color={themes[theme].auxiliaryText} onPress={() => this.deleteUpload(item)} /> </View> ); } diff --git a/app/views/RoomView/index.js b/app/views/RoomView/index.js index 0b6afd18f..00df625f1 100644 --- a/app/views/RoomView/index.js +++ b/app/views/RoomView/index.js @@ -24,7 +24,7 @@ import MessageBox from '../../containers/MessageBox'; import ReactionPicker from './ReactionPicker'; import UploadProgress from './UploadProgress'; import styles from './styles'; -import log from '../../utils/log'; +import log, { logEvent, events } from '../../utils/log'; import EventEmitter from '../../utils/events'; import I18n from '../../i18n'; import RoomHeaderView, { RightButtons, LeftButtons } from './Header'; @@ -206,12 +206,10 @@ class RoomView extends React.Component { const { appState, insets } = this.props; if (appState === 'foreground' && appState !== prevProps.appState && this.rid) { - this.onForegroundInteraction = InteractionManager.runAfterInteractions(() => { - // Fire List.init() just to keep observables working - if (this.list && this.list.current) { - this.list.current.init(); - } - }); + // Fire List.query() just to keep observables working + if (this.list && this.list.current) { + this.list.current?.query?.(); + } } // If it's not direct message if (this.t !== 'd') { @@ -267,9 +265,6 @@ class RoomView extends React.Component { if (this.didMountInteraction && this.didMountInteraction.cancel) { this.didMountInteraction.cancel(); } - if (this.onForegroundInteraction && this.onForegroundInteraction.cancel) { - this.onForegroundInteraction.cancel(); - } if (this.willBlurListener && this.willBlurListener.remove) { this.willBlurListener.remove(); } @@ -287,6 +282,11 @@ class RoomView extends React.Component { console.countReset(`${ this.constructor.name }.render calls`); } + get isOmnichannel() { + const { room } = this.state; + return room.t === 'l'; + } + setHeader = () => { const { room, unreadsCount, roomUserId: stateRoomUserId } = this.state; const { @@ -357,6 +357,7 @@ class RoomView extends React.Component { } goRoomActionsView = (screen) => { + logEvent(events.ROOM_GO_RA); const { room, member } = this.state; const { navigation, isMasterDetail } = this.props; if (isMasterDetail) { @@ -649,6 +650,7 @@ class RoomView extends React.Component { } sendMessage = (message, tmid) => { + logEvent(events.ROOM_SEND_MESSAGE); const { user } = this.props; RocketChat.sendMessage(this.rid, message, this.tmid || tmid, user).then(() => { if (this.list && this.list.current) { @@ -682,8 +684,15 @@ class RoomView extends React.Component { setLastOpen = lastOpen => this.setState({ lastOpen }); joinRoom = async() => { + logEvent(events.ROOM_JOIN); try { - await RocketChat.joinRoom(this.rid, this.t); + const { room } = this.state; + + if (this.isOmnichannel) { + await RocketChat.takeInquiry(room._id); + } else { + await RocketChat.joinRoom(this.rid, this.t); + } this.internalSetState({ joined: true }); @@ -742,6 +751,7 @@ class RoomView extends React.Component { navToRoomInfo = (navParam) => { const { navigation, user, isMasterDetail } = this.props; + logEvent(events[`ROOM_GO_${ navParam.t === 'd' ? 'USER' : 'ROOM' }_INFO`]); if (navParam.rid === user.id) { return; } @@ -900,7 +910,7 @@ class RoomView extends React.Component { style={[styles.joinRoomButton, { backgroundColor: themes[theme].actionTintColor }]} theme={theme} > - <Text style={[styles.joinRoomText, { color: themes[theme].buttonText }]} testID='room-view-join-button'>{I18n.t('Join')}</Text> + <Text style={[styles.joinRoomText, { color: themes[theme].buttonText }]} testID='room-view-join-button'>{I18n.t(this.isOmnichannel ? 'Take_it' : 'Join')}</Text> </Touch> </View> ); diff --git a/app/views/RoomsListView/Header/Header.js b/app/views/RoomsListView/Header/Header.js index 839048bc0..fb5d7eb9e 100644 --- a/app/views/RoomsListView/Header/Header.js +++ b/app/views/RoomsListView/Header/Header.js @@ -41,7 +41,7 @@ const Header = React.memo(({ const { isLandscape } = useOrientation(); const scale = isIOS && isLandscape && !isTablet ? 0.8 : 1; const titleFontSize = 16 * scale; - const subTitleFontSize = 12 * scale; + const subTitleFontSize = 14 * scale; if (showSearchHeader) { return ( @@ -78,11 +78,11 @@ const Header = React.memo(({ <CustomIcon name='chevron-down' color={themes[theme].headerTintColor} - style={[showServerDropdown && styles.upsideDown, { fontSize: subTitleFontSize }]} + style={[showServerDropdown && styles.upsideDown]} size={18} /> </View> - {subtitle ? <Text style={[styles.subtitle, { color: themes[theme].auxiliaryText }]} numberOfLines={1}>{subtitle}</Text> : null} + {subtitle ? <Text style={[styles.subtitle, { color: themes[theme].auxiliaryText, fontSize: subTitleFontSize }]} numberOfLines={1}>{subtitle}</Text> : null} </TouchableOpacity> </View> ); diff --git a/app/views/RoomsListView/Header/index.js b/app/views/RoomsListView/Header/index.js index 12a57dc00..97244fd5b 100644 --- a/app/views/RoomsListView/Header/index.js +++ b/app/views/RoomsListView/Header/index.js @@ -10,6 +10,7 @@ import { withTheme } from '../../../theme'; import EventEmitter from '../../../utils/events'; import { KEY_COMMAND, handleCommandOpenServerDropdown } from '../../../commands'; import { isTablet } from '../../../utils/deviceInfo'; +import { logEvent, events } from '../../../utils/log'; class RoomsListHeaderView extends PureComponent { static propTypes = { @@ -53,6 +54,7 @@ class RoomsListHeaderView extends PureComponent { } onPress = () => { + logEvent(events.RL_TOGGLE_SERVER_DROPDOWN); const { showServerDropdown, showSortDropdown, close, open, closeSort } = this.props; diff --git a/app/views/RoomsListView/ListHeader/Queue.js b/app/views/RoomsListView/ListHeader/Queue.js new file mode 100644 index 000000000..0a85d657a --- /dev/null +++ b/app/views/RoomsListView/ListHeader/Queue.js @@ -0,0 +1,49 @@ +import React from 'react'; +import { View, Text, StyleSheet } from 'react-native'; +import PropTypes from 'prop-types'; + +import Touch from '../../../utils/touch'; +import I18n from '../../../i18n'; +import styles from '../styles'; +import { themes } from '../../../constants/colors'; +import { withTheme } from '../../../theme'; +import UnreadBadge from '../../../presentation/UnreadBadge'; + +const Queue = React.memo(({ + searching, goQueue, queueSize, inquiryEnabled, theme +}) => { + if (searching > 0 || !inquiryEnabled) { + return null; + } + return ( + <Touch + onPress={goQueue} + theme={theme} + style={{ backgroundColor: themes[theme].headerSecondaryBackground }} + > + <View + style={[ + styles.dropdownContainerHeader, + { borderBottomWidth: StyleSheet.hairlineWidth, borderColor: themes[theme].separatorColor } + ]} + > + <Text style={[styles.sortToggleText, { color: themes[theme].auxiliaryText }]}>{I18n.t('Queued_chats')}</Text> + <UnreadBadge + style={styles.sortIcon} + unread={queueSize} + theme={theme} + /> + </View> + </Touch> + ); +}); + +Queue.propTypes = { + searching: PropTypes.bool, + goQueue: PropTypes.func, + queueSize: PropTypes.number, + inquiryEnabled: PropTypes.bool, + theme: PropTypes.string +}; + +export default withTheme(Queue); diff --git a/app/views/RoomsListView/ListHeader/index.js b/app/views/RoomsListView/ListHeader/index.js index dec38b506..5df248787 100644 --- a/app/views/RoomsListView/ListHeader/index.js +++ b/app/views/RoomsListView/ListHeader/index.js @@ -1,6 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; +import Queue from './Queue'; import Directory from './Directory'; import Sort from './Sort'; @@ -8,11 +9,15 @@ const ListHeader = React.memo(({ searching, sortBy, toggleSort, - goDirectory + goDirectory, + goQueue, + queueSize, + inquiryEnabled }) => ( <> <Directory searching={searching} goDirectory={goDirectory} /> <Sort searching={searching} sortBy={sortBy} toggleSort={toggleSort} /> + <Queue searching={searching} goQueue={goQueue} queueSize={queueSize} inquiryEnabled={inquiryEnabled} /> </> )); @@ -20,7 +25,10 @@ ListHeader.propTypes = { searching: PropTypes.bool, sortBy: PropTypes.string, toggleSort: PropTypes.func, - goDirectory: PropTypes.func + goDirectory: PropTypes.func, + goQueue: PropTypes.func, + queueSize: PropTypes.number, + inquiryEnabled: PropTypes.bool }; export default ListHeader; diff --git a/app/views/RoomsListView/ServerDropdown.js b/app/views/RoomsListView/ServerDropdown.js index be28fdbf7..afeb15eea 100644 --- a/app/views/RoomsListView/ServerDropdown.js +++ b/app/views/RoomsListView/ServerDropdown.js @@ -1,6 +1,6 @@ import React, { Component } from 'react'; import { - View, Text, Animated, Easing, TouchableWithoutFeedback, TouchableOpacity, FlatList, Image + View, Text, Animated, Easing, TouchableWithoutFeedback, TouchableOpacity, FlatList, Image, Pressable } from 'react-native'; import PropTypes from 'prop-types'; import { connect, batch } from 'react-redux'; @@ -12,7 +12,6 @@ import { toggleServerDropdown as toggleServerDropdownAction } from '../../action import { selectServerRequest as selectServerRequestAction, serverInitAdd as serverInitAddAction } from '../../actions/server'; import { appStart as appStartAction, ROOT_NEW_SERVER } from '../../actions/app'; import styles from './styles'; -import Touch from '../../utils/touch'; import RocketChat from '../../lib/rocketchat'; import I18n from '../../i18n'; import EventEmitter from '../../utils/events'; @@ -21,10 +20,10 @@ import database from '../../lib/database'; import { themes } from '../../constants/colors'; import { withTheme } from '../../theme'; import { KEY_COMMAND, handleCommandSelectServer } from '../../commands'; -import { isTablet } from '../../utils/deviceInfo'; +import { isTablet, isIOS } from '../../utils/deviceInfo'; import { localAuthenticate } from '../../utils/localAuthentication'; import { showConfirmationAlert } from '../../utils/info'; -import LongPress from '../../utils/longPress'; +import { logEvent, events } from '../../utils/log'; import { headerHeight } from '../../containers/Header'; import { goRoom } from '../../utils/goRoom'; @@ -136,6 +135,7 @@ class ServerDropdown extends Component { } addServer = () => { + logEvent(events.RL_ADD_SERVER); const { server } = this.props; this.close(); setTimeout(() => { @@ -149,6 +149,7 @@ class ServerDropdown extends Component { } = this.props; this.close(); if (currentServer !== server) { + logEvent(events.RL_CHANGE_SERVER); const userId = await RNUserDefaults.get(`${ RocketChat.TOKEN_KEY }-${ server }`); if (isMasterDetail) { goRoom({ item: {}, isMasterDetail }); @@ -201,37 +202,43 @@ class ServerDropdown extends Component { const { server, theme } = this.props; return ( - <LongPress onLongPress={() => (item.id === server || this.remove(item.id))}> - <Touch - onPress={() => this.select(item.id)} - testID={`rooms-list-header-server-${ item.id }`} - theme={theme} - > - <View style={styles.serverItemContainer}> - {item.iconURL - ? ( - <Image - source={{ uri: item.iconURL }} - defaultSource={{ uri: 'logo' }} - style={styles.serverIcon} - onError={() => console.warn('error loading serverIcon')} - /> - ) - : ( - <Image - source={{ uri: 'logo' }} - style={styles.serverIcon} - /> - ) - } - <View style={styles.serverTextContainer}> - <Text style={[styles.serverName, { color: themes[theme].titleText }]} numberOfLines={1}>{item.name || item.id}</Text> - <Text style={[styles.serverUrl, { color: themes[theme].auxiliaryText }]} numberOfLines={1}>{item.id}</Text> - </View> - {item.id === server ? <Check theme={theme} /> : null} + <Pressable + onPress={() => this.select(item.id)} + onLongPress={() => (item.id === server || this.remove(item.id))} + testID={`rooms-list-header-server-${ item.id }`} + android_ripple={{ + color: themes[theme].bannerBackground + }} + style={({ pressed }) => ({ + backgroundColor: isIOS && pressed + ? themes[theme].bannerBackground + : 'transparent' + })} + > + <View style={styles.serverItemContainer}> + {item.iconURL + ? ( + <Image + source={{ uri: item.iconURL }} + defaultSource={{ uri: 'logo' }} + style={styles.serverIcon} + onError={() => console.warn('error loading serverIcon')} + /> + ) + : ( + <Image + source={{ uri: 'logo' }} + style={styles.serverIcon} + /> + ) + } + <View style={styles.serverTextContainer}> + <Text style={[styles.serverName, { color: themes[theme].titleText }]} numberOfLines={1}>{item.name || item.id}</Text> + <Text style={[styles.serverUrl, { color: themes[theme].auxiliaryText }]} numberOfLines={1}>{item.id}</Text> </View> - </Touch> - </LongPress> + {item.id === server ? <Check theme={theme} /> : null} + </View> + </Pressable> ); } diff --git a/app/views/RoomsListView/SortDropdown/index.js b/app/views/RoomsListView/SortDropdown/index.js index b0c398b85..f50c939d7 100644 --- a/app/views/RoomsListView/SortDropdown/index.js +++ b/app/views/RoomsListView/SortDropdown/index.js @@ -10,7 +10,7 @@ import styles from '../styles'; import Touch from '../../../utils/touch'; import RocketChat from '../../../lib/rocketchat'; import { setPreference } from '../../../actions/sortPreferences'; -import log from '../../../utils/log'; +import log, { logEvent, events } from '../../../utils/log'; import I18n from '../../../i18n'; import { CustomIcon } from '../../../lib/Icons'; import { withTheme } from '../../../theme'; @@ -65,31 +65,37 @@ class Sort extends PureComponent { setSortPreference(param); RocketChat.saveSortPreference(param); } catch (e) { + logEvent(events.RL_SORT_CHANNELS_F); log(e); } } sortByName = () => { + logEvent(events.RL_SORT_CHANNELS_BY_NAME); this.setSortPreference({ sortBy: 'alphabetical' }); this.close(); } sortByActivity = () => { + logEvent(events.RL_SORT_CHANNELS_BY_ACTIVITY); this.setSortPreference({ sortBy: 'activity' }); this.close(); } toggleGroupByType = () => { + logEvent(events.RL_GROUP_CHANNELS_BY_TYPE); const { groupByType } = this.props; this.setSortPreference({ groupByType: !groupByType }); } toggleGroupByFavorites = () => { + logEvent(events.RL_GROUP_CHANNELS_BY_FAVORITE); const { showFavorites } = this.props; this.setSortPreference({ showFavorites: !showFavorites }); } toggleUnread = () => { + logEvent(events.RL_GROUP_CHANNELS_BY_UNREAD); const { showUnread } = this.props; this.setSortPreference({ showUnread: !showUnread }); } @@ -190,7 +196,7 @@ class Sort extends PureComponent { </SortItemButton> <SortItemButton onPress={this.toggleUnread} theme={theme}> <SortItemContent - icon='eye-off' + icon='unread-on-top-disabled' label='Unread_on_top' checked={showUnread} theme={theme} diff --git a/app/views/RoomsListView/index.js b/app/views/RoomsListView/index.js index 7543a46f4..513ce311d 100644 --- a/app/views/RoomsListView/index.js +++ b/app/views/RoomsListView/index.js @@ -9,7 +9,7 @@ import { RefreshControl } from 'react-native'; import { connect } from 'react-redux'; -import { isEqual, orderBy } from 'lodash'; +import isEqual from 'react-fast-compare'; import Orientation from 'react-native-orientation-locker'; import { Q } from '@nozbe/watermelondb'; import { withSafeAreaInsets } from 'react-native-safe-area-context'; @@ -18,7 +18,7 @@ import database from '../../lib/database'; import RocketChat from '../../lib/rocketchat'; import RoomItem, { ROW_HEIGHT } from '../../presentation/RoomItem'; import styles from './styles'; -import log from '../../utils/log'; +import log, { logEvent, events } from '../../utils/log'; import I18n from '../../i18n'; import SortDropdown from './SortDropdown'; import ServerDropdown from './ServerDropdown'; @@ -62,6 +62,8 @@ import { goRoom } from '../../utils/goRoom'; import SafeAreaView from '../../containers/SafeAreaView'; import Header, { getHeaderTitlePosition } from '../../containers/Header'; import { withDimensions } from '../../dimensions'; +import { showErrorAlert } from '../../utils/info'; +import { getInquiryQueueSelector } from '../../selectors/inquiry'; const INITIAL_NUM_TO_RENDER = isTablet ? 20 : 12; const CHATS_HEADER = 'Chats'; @@ -71,6 +73,7 @@ const DISCUSSIONS_HEADER = 'Discussions'; const CHANNELS_HEADER = 'Channels'; const DM_HEADER = 'Direct_Messages'; const GROUPS_HEADER = 'Private_Groups'; +const QUERY_SIZE = 20; const filterIsUnread = s => (s.unread > 0 || s.alert) && !s.hideUnreadStatus; const filterIsFavorite = s => s.f; @@ -89,7 +92,9 @@ const shouldUpdateProps = [ 'appState', 'theme', 'isMasterDetail', - 'refreshing' + 'refreshing', + 'queueSize', + 'inquiryEnabled' ]; const getItemLayout = (data, index) => ({ length: ROW_HEIGHT, @@ -130,7 +135,9 @@ class RoomsListView extends React.Component { isMasterDetail: PropTypes.bool, rooms: PropTypes.array, width: PropTypes.number, - insets: PropTypes.object + insets: PropTypes.object, + queueSize: PropTypes.number, + inquiryEnabled: PropTypes.bool }; constructor(props) { @@ -140,11 +147,12 @@ class RoomsListView extends React.Component { this.gotSubscriptions = false; this.animated = false; + this.count = 0; this.state = { searching: false, search: [], loading: true, - allChats: [], + chatsOrder: [], chats: [], item: {} }; @@ -211,7 +219,7 @@ class RoomsListView extends React.Component { } shouldComponentUpdate(nextProps, nextState) { - const { allChats, searching, item } = this.state; + const { chatsOrder, searching, item } = this.state; // eslint-disable-next-line react/destructuring-assignment const propsUpdated = shouldUpdateProps.some(key => nextProps[key] !== this.props[key]); if (propsUpdated) { @@ -219,7 +227,7 @@ class RoomsListView extends React.Component { } // Compare changes only once - const chatsNotEqual = !isEqual(nextState.allChats, allChats); + const chatsNotEqual = !isEqual(nextState.chatsOrder, chatsOrder); // If they aren't equal, set to update if focused if (chatsNotEqual) { @@ -290,7 +298,7 @@ class RoomsListView extends React.Component { && prevProps.showUnread === showUnread ) ) { - this.getSubscriptions(true); + this.getSubscriptions(); } else if ( appState === 'foreground' && appState !== prevProps.appState @@ -309,9 +317,7 @@ class RoomsListView extends React.Component { } componentWillUnmount() { - if (this.querySubscription && this.querySubscription.unsubscribe) { - this.querySubscription.unsubscribe(); - } + this.unsubscribeQuery(); if (this.unsubscribeFocus) { this.unsubscribeFocus(); } @@ -334,7 +340,7 @@ class RoomsListView extends React.Component { <CustomHeaderButtons left> <Item title='cancel' - iconName='Cross' + iconName='close' onPress={this.cancelSearch} /> </CustomHeaderButtons> @@ -356,15 +362,13 @@ class RoomsListView extends React.Component { <CustomHeaderButtons> <Item title='new' - iconName='new-chat' - onPress={isMasterDetail - ? () => navigation.navigate('ModalStackNavigator', { screen: 'NewMessageView' }) - : () => navigation.navigate('NewMessageStackNavigator')} + iconName='create' + onPress={this.goToNewMessage} testID='rooms-list-view-create-channel' /> <Item title='search' - iconName='magnifier' + iconName='search' onPress={this.initSearching} testID='rooms-list-view-search' /> @@ -396,17 +400,8 @@ class RoomsListView extends React.Component { return allData; } - getSubscriptions = async(force = false) => { - if (this.gotSubscriptions && !force) { - return; - } - this.gotSubscriptions = true; - - if (this.querySubscription && this.querySubscription.unsubscribe) { - this.querySubscription.unsubscribe(); - } - - this.setState({ loading: true }); + getSubscriptions = async() => { + this.unsubscribeQuery(); const { sortBy, @@ -416,41 +411,49 @@ class RoomsListView extends React.Component { } = this.props; const db = database.active; - const observable = await db.collections - .get('subscriptions') - .query( - Q.where('archived', false), - Q.where('open', true) - ) - .observeWithColumns(['room_updated_at', 'unread', 'alert', 'user_mentions', 'f', 't']); + let observable; + + const defaultWhereClause = [ + Q.where('archived', false), + Q.where('open', true) + ]; + + if (sortBy === 'alphabetical') { + defaultWhereClause.push(Q.experimentalSortBy(`${ this.useRealName ? 'fname' : 'name' }`, Q.asc)); + } else { + defaultWhereClause.push(Q.experimentalSortBy('room_updated_at', Q.desc)); + } + + // When we're grouping by something + if (this.isGrouping) { + observable = await db.collections + .get('subscriptions') + .query(...defaultWhereClause) + .observe(); + + // When we're NOT grouping + } else { + this.count += QUERY_SIZE; + observable = await db.collections + .get('subscriptions') + .query( + ...defaultWhereClause, + Q.experimentalSkip(0), + Q.experimentalTake(this.count) + ) + .observe(); + } + this.querySubscription = observable.subscribe((data) => { let tempChats = []; - let chats = []; - if (sortBy === 'alphabetical') { - chats = orderBy(data, [`${ this.useRealName ? 'fname' : 'name' }`], ['asc']); - } else { - chats = orderBy(data, ['roomUpdatedAt'], ['desc']); - } + let chats = data; - // it's better to map and test all subs altogether then testing them individually - const allChats = data.map(item => ({ - alert: item.alert, - unread: item.unread, - userMentions: item.userMentions, - isRead: this.getIsRead(item), - favorite: item.f, - lastMessage: item.lastMessage, - name: this.getRoomTitle(item), - _updatedAt: item.roomUpdatedAt, - key: item._id, - rid: item.rid, - type: item.t, - prid: item.prid, - uids: item.uids, - usernames: item.usernames, - visitor: item.visitor - })); + /** + * We trigger re-render only when chats order changes + * RoomItem handles its own re-render + */ + const chatsOrder = data.map(item => item.rid); // unread if (showUnread) { @@ -484,13 +487,20 @@ class RoomsListView extends React.Component { this.internalSetState({ chats: tempChats, - allChats, + chatsOrder, loading: false }); }); } + unsubscribeQuery = () => { + if (this.querySubscription && this.querySubscription.unsubscribe) { + this.querySubscription.unsubscribe(); + } + } + initSearching = () => { + logEvent(events.RL_SEARCH); const { openSearchHeader } = this.props; this.internalSetState({ searching: true }, () => { openSearchHeader(); @@ -548,10 +558,19 @@ class RoomsListView extends React.Component { getRoomAvatar = item => RocketChat.getRoomAvatar(item) + isGroupChat = item => RocketChat.isGroupChat(item) + + isRead = item => RocketChat.isRead(item) + getUserPresence = uid => RocketChat.getUserPresence(uid) getUidDirectMessage = room => RocketChat.getUidDirectMessage(room); + get isGrouping() { + const { showUnread, showFavorites, groupByType } = this.props; + return showUnread || showFavorites || groupByType; + } + onPressItem = (item = {}) => { const { navigation, isMasterDetail } = this.props; if (!navigation.isFocused()) { @@ -566,9 +585,10 @@ class RoomsListView extends React.Component { if (this.scroll?.scrollToOffset) { this.scroll.scrollToOffset({ offset: 0 }); } - }; + } toggleSort = () => { + logEvent(events.RL_TOGGLE_SORT_DROPDOWN); const { toggleSortDropdown } = this.props; this.scrollToTop(); @@ -578,6 +598,7 @@ class RoomsListView extends React.Component { }; toggleFav = async(rid, favorite) => { + logEvent(favorite ? events.RL_UNFAVORITE_CHANNEL : events.RL_FAVORITE_CHANNEL); try { const db = database.active; const result = await RocketChat.toggleFavorite(rid, !favorite); @@ -595,11 +616,13 @@ class RoomsListView extends React.Component { }); } } catch (e) { + logEvent(events.RL_TOGGLE_FAVORITE_FAIL); log(e); } }; toggleRead = async(rid, isRead) => { + logEvent(isRead ? events.RL_UNREAD_CHANNEL : events.RL_READ_CHANNEL); try { const db = database.active; const result = await RocketChat.toggleRead(isRead, rid); @@ -617,11 +640,13 @@ class RoomsListView extends React.Component { }); } } catch (e) { + logEvent(events.RL_TOGGLE_READ_F); log(e); } }; hideChannel = async(rid, type) => { + logEvent(events.RL_HIDE_CHANNEL); try { const db = database.active; const result = await RocketChat.hideRoom(rid, type); @@ -637,11 +662,13 @@ class RoomsListView extends React.Component { }); } } catch (e) { + logEvent(events.RL_HIDE_CHANNEL_F); log(e); } }; goDirectory = () => { + logEvent(events.RL_GO_DIRECTORY); const { navigation, isMasterDetail } = this.props; if (isMasterDetail) { navigation.navigate('ModalStackNavigator', { screen: 'DirectoryView' }); @@ -650,7 +677,22 @@ class RoomsListView extends React.Component { } }; + goQueue = () => { + logEvent(events.RL_GO_QUEUE); + const { navigation, isMasterDetail, queueSize } = this.props; + // prevent navigation to empty list + if (!queueSize) { + return showErrorAlert(I18n.t('Queue_is_empty'), I18n.t('Oops')); + } + if (isMasterDetail) { + navigation.navigate('ModalStackNavigator', { screen: 'QueueListView' }); + } else { + navigation.navigate('QueueListView'); + } + }; + goRoom = ({ item, isMasterDetail }) => { + logEvent(events.RL_GO_ROOM); const { item: currentItem } = this.state; const { rooms } = this.props; if (currentItem?.rid === item.rid || rooms?.includes(item.rid)) { @@ -710,6 +752,17 @@ class RoomsListView extends React.Component { } } + goToNewMessage = () => { + logEvent(events.RL_GO_NEW_MSG); + const { navigation, isMasterDetail } = this.props; + + if (isMasterDetail) { + navigation.navigate('ModalStackNavigator', { screen: 'NewMessageView' }); + } else { + navigation.navigate('NewMessageStackNavigator'); + } + } + handleCommands = ({ event }) => { const { navigation, server, isMasterDetail } = this.props; const { input } = event; @@ -743,17 +796,27 @@ class RoomsListView extends React.Component { roomsRequest({ allData: true }); } + onEndReached = () => { + // Run only when we're not grouping by anything + if (!this.isGrouping) { + this.getSubscriptions(); + } + } + getScrollRef = ref => (this.scroll = ref); renderListHeader = () => { const { searching } = this.state; - const { sortBy } = this.props; + const { sortBy, queueSize, inquiryEnabled } = this.props; return ( <ListHeader searching={searching} sortBy={sortBy} toggleSort={this.toggleSort} goDirectory={this.goDirectory} + goQueue={this.goQueue} + queueSize={queueSize} + inquiryEnabled={inquiryEnabled} /> ); }; @@ -774,12 +837,6 @@ class RoomsListView extends React.Component { ); } - getIsRead = (item) => { - let isUnread = item.archived !== true && item.open === true; // item is not archived and not opened - isUnread = isUnread && (item.unread > 0 || item.alert === true); // either its unread count > 0 or its alert - return !isUnread; - }; - renderItem = ({ item }) => { if (item.separator) { return this.renderSectionHeader(item.rid); @@ -800,32 +857,19 @@ class RoomsListView extends React.Component { width } = this.props; const id = this.getUidDirectMessage(item); - const isGroupChat = RocketChat.isGroupChat(item); return ( <RoomItem + item={item} theme={theme} - alert={item.alert} - unread={item.unread} - hideUnreadStatus={item.hideUnreadStatus} - userMentions={item.userMentions} - isRead={this.getIsRead(item)} - favorite={item.f} - avatar={this.getRoomAvatar(item)} - lastMessage={item.lastMessage} - name={this.getRoomTitle(item)} - _updatedAt={item.roomUpdatedAt} - key={item._id} id={id} + type={item.t} userId={userId} username={username} token={token} - rid={item.rid} - type={item.t} baseUrl={server} - prid={item.prid} showLastMessage={StoreLastMessage} - onPress={() => this.onPressItem(item)} + onPress={this.onPressItem} testID={`rooms-list-view-item-${ item.name }`} width={isMasterDetail ? MAX_SIDEBAR_WIDTH : width} toggleFav={this.toggleFav} @@ -833,7 +877,10 @@ class RoomsListView extends React.Component { hideChannel={this.hideChannel} useRealName={useRealName} getUserPresence={this.getUserPresence} - isGroupChat={isGroupChat} + getRoomTitle={this.getRoomTitle} + getRoomAvatar={this.getRoomAvatar} + getIsGroupChat={this.isGroupChat} + getIsRead={this.isRead} visitor={item.visitor} isFocused={currentItem?.rid === item.rid} /> @@ -880,6 +927,8 @@ class RoomsListView extends React.Component { /> )} windowSize={9} + onEndReached={this.onEndReached} + onEndReachedThreshold={0.5} /> ); }; @@ -934,7 +983,9 @@ const mapStateToProps = state => ({ useRealName: state.settings.UI_Use_Real_Name, appState: state.app.ready && state.app.foreground ? 'foreground' : 'background', StoreLastMessage: state.settings.Store_Last_Message, - rooms: state.room.rooms + rooms: state.room.rooms, + queueSize: getInquiryQueueSelector(state).length, + inquiryEnabled: state.inquiry.enabled }); const mapDispatchToProps = dispatch => ({ diff --git a/app/views/ScreenLockConfigView.js b/app/views/ScreenLockConfigView.js index f235f6caf..0dfb377f2 100644 --- a/app/views/ScreenLockConfigView.js +++ b/app/views/ScreenLockConfigView.js @@ -16,6 +16,7 @@ import { supportedBiometryLabel, changePasscode, checkHasPasscode } from '../uti import { DisclosureImage } from '../containers/DisclosureIndicator'; import { DEFAULT_AUTO_LOCK } from '../constants/localAuthentication'; import SafeAreaView from '../containers/SafeAreaView'; +import { events, logEvent } from '../utils/log'; const styles = StyleSheet.create({ listPadding: { @@ -29,9 +30,9 @@ const styles = StyleSheet.create({ const DEFAULT_BIOMETRY = false; class ScreenLockConfigView extends React.Component { - static navigationOptions = { + static navigationOptions = () => ({ title: I18n.t('Screen_lock') - }; + }); static propTypes = { theme: PropTypes.string, @@ -113,6 +114,7 @@ class ScreenLockConfigView extends React.Component { } save = async() => { + logEvent(events.SLC_SAVE_SCREEN_LOCK); const { autoLock, autoLockTime, biometry } = this.state; const serversDB = database.servers; await serversDB.action(async() => { @@ -125,10 +127,12 @@ class ScreenLockConfigView extends React.Component { } changePasscode = async({ force }) => { + logEvent(events.SLC_CHANGE_PASSCODE); await changePasscode({ force }); } toggleAutoLock = () => { + logEvent(events.SLC_TOGGLE_AUTOLOCK); this.setState(({ autoLock }) => ({ autoLock: !autoLock, autoLockTime: DEFAULT_AUTO_LOCK }), async() => { const { autoLock } = this.state; if (autoLock) { @@ -143,6 +147,7 @@ class ScreenLockConfigView extends React.Component { } toggleBiometry = () => { + logEvent(events.SLC_TOGGLE_BIOMETRY); this.setState(({ biometry }) => ({ biometry: !biometry }), () => this.save()); } @@ -152,6 +157,7 @@ class ScreenLockConfigView extends React.Component { } changeAutoLockTime = (autoLockTime) => { + logEvent(events.SLC_CHANGE_AUTOLOCK_TIME); this.setState({ autoLockTime }, () => this.save()); } diff --git a/app/views/SelectServerView.js b/app/views/SelectServerView.js index 19131a3e8..46418d395 100644 --- a/app/views/SelectServerView.js +++ b/app/views/SelectServerView.js @@ -29,9 +29,9 @@ const styles = StyleSheet.create({ }); class SelectServerView extends React.Component { - static navigationOptions = { + static navigationOptions = () => ({ title: I18n.t('Select_Server') - } + }) static propTypes = { server: PropTypes.string, diff --git a/app/views/SelectedUsersView.js b/app/views/SelectedUsersView.js index eb8c7bc8e..396728a86 100644 --- a/app/views/SelectedUsersView.js +++ b/app/views/SelectedUsersView.js @@ -11,7 +11,7 @@ import RocketChat from '../lib/rocketchat'; import UserItem from '../presentation/UserItem'; import Loading from '../containers/Loading'; import I18n from '../i18n'; -import log from '../utils/log'; +import log, { logEvent, events } from '../utils/log'; import SearchBox from '../containers/SearchBox'; import sharedStyles from './Styles'; import { Item, CustomHeaderButtons } from '../containers/HeaderButton'; @@ -183,9 +183,10 @@ class SelectedUsersView extends React.Component { if (this.isGroupChat() && users.length === maxUsers) { return showErrorAlert(I18n.t('Max_number_of_users_allowed_is_number', { maxUsers }), I18n.t('Oops')); } - + logEvent(events.SELECTED_USERS_ADD_USER); addUser(user); } else { + logEvent(events.SELECTED_USERS_REMOVE_USER); removeUser(user); } } diff --git a/app/views/SettingsView/index.js b/app/views/SettingsView/index.js index 9cb3c8b05..ee362b772 100644 --- a/app/views/SettingsView/index.js +++ b/app/views/SettingsView/index.js @@ -5,6 +5,7 @@ import { import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import AsyncStorage from '@react-native-community/async-storage'; +import FastImage from '@rocket.chat/react-native-fast-image'; import { logout as logoutAction } from '../../actions/login'; import { selectServerRequest as selectServerRequestAction } from '../../actions/server'; @@ -25,7 +26,9 @@ import openLink from '../../utils/openLink'; import scrollPersistTaps from '../../utils/scrollPersistTaps'; import { showErrorAlert, showConfirmationAlert } from '../../utils/info'; import styles from './styles'; -import { loggerConfig, analytics } from '../../utils/log'; +import { + loggerConfig, analytics, logEvent, events +} from '../../utils/log'; import { PLAY_MARKET_LINK, APP_STORE_LINK, LICENSE_LINK } from '../../constants/links'; import { withTheme } from '../../theme'; import SidebarView from '../SidebarView'; @@ -85,6 +88,7 @@ class SettingsView extends React.Component { } handleLogout = () => { + logEvent(events.SE_LOG_OUT); showConfirmationAlert({ message: I18n.t('You_will_be_logged_out_of_this_application'), callToAction: I18n.t('Logout'), @@ -96,6 +100,7 @@ class SettingsView extends React.Component { } handleClearCache = () => { + logEvent(events.SE_CLEAR_LOCAL_SERVER_CACHE); showConfirmationAlert({ message: I18n.t('This_will_clear_all_your_offline_data'), callToAction: I18n.t('Clear'), @@ -103,20 +108,22 @@ class SettingsView extends React.Component { const { server: { server }, appStart, selectServerRequest } = this.props; - await appStart({ root: ROOT_LOADING, text: I18n.t('Clear_cache_loading') }); + appStart({ root: ROOT_LOADING, text: I18n.t('Clear_cache_loading') }); await RocketChat.clearCache({ server }); - await selectServerRequest(server, null, true); + await FastImage.clearMemoryCache(); + await FastImage.clearDiskCache(); + selectServerRequest(server, null, true); } }); } toggleCrashReport = (value) => { + logEvent(events.SE_TOGGLE_CRASH_REPORT); AsyncStorage.setItem(CRASH_REPORT_KEY, JSON.stringify(value)); const { toggleCrashReport } = this.props; toggleCrashReport(value); loggerConfig.autoNotify = value; analytics().setAnalyticsCollectionEnabled(value); - if (value) { loggerConfig.clearBeforeSendCallbacks(); } else { @@ -133,11 +140,13 @@ class SettingsView extends React.Component { } navigateToScreen = (screen) => { + logEvent(events[`SE_GO_${ screen.replace('View', '').toUpperCase() }`]); const { navigation } = this.props; navigation.navigate(screen); } sendEmail = async() => { + logEvent(events.SE_CONTACT_US); const subject = encodeURI('React Native App Support'); const email = encodeURI('support@rocket.chat'); const description = encodeURI(` @@ -147,20 +156,24 @@ class SettingsView extends React.Component { try { await Linking.openURL(`mailto:${ email }?subject=${ subject }&body=${ description }`); } catch (e) { + logEvent(events.SE_CONTACT_US_F); showErrorAlert(I18n.t('error-email-send-failed', { message: 'support@rocket.chat' })); } } shareApp = () => { + logEvent(events.SE_SHARE_THIS_APP); Share.share({ message: isAndroid ? PLAY_MARKET_LINK : APP_STORE_LINK }); } copyServerVersion = () => { - const { server } = this.props; - this.saveToClipboard(server.version); + const { server: { version } } = this.props; + logEvent(events.SE_COPY_SERVER_VERSION, { serverVersion: version }); + this.saveToClipboard(version); } copyAppVersion = () => { + logEvent(events.SE_COPY_APP_VERSION, { appVersion: getReadableVersion }); this.saveToClipboard(getReadableVersion); } @@ -170,6 +183,7 @@ class SettingsView extends React.Component { } onPressLicense = () => { + logEvent(events.SE_READ_LICENSE); const { theme } = this.props; openLink(LICENSE_LINK, theme); } diff --git a/app/views/ShareListView/index.js b/app/views/ShareListView/index.js index 7e81998cb..c40bd1843 100644 --- a/app/views/ShareListView/index.js +++ b/app/views/ShareListView/index.js @@ -7,7 +7,7 @@ import ShareExtension from 'rn-extensions-share'; import * as FileSystem from 'expo-file-system'; import { connect } from 'react-redux'; import * as mime from 'react-native-mime-types'; -import { isEqual, orderBy } from 'lodash'; +import isEqual from 'react-fast-compare'; import { Q } from '@nozbe/watermelondb'; import database from '../../lib/database'; @@ -32,7 +32,6 @@ const permission = { message: I18n.t('Read_External_Permission_Message') }; -const LIMIT = 50; const getItemLayout = (data, index) => ({ length: ROW_HEIGHT, offset: ROW_HEIGHT * index, index }); const keyExtractor = item => item.rid; @@ -47,7 +46,7 @@ class ShareListView extends React.Component { constructor(props) { super(props); - this.data = []; + this.chats = []; this.state = { searching: false, searchText: '', @@ -155,7 +154,7 @@ class ShareListView extends React.Component { headerLeft: () => (searching ? ( <CustomHeaderButtons left> - <Item title='cancel' iconName='Cross' onPress={this.cancelSearch} /> + <Item title='cancel' iconName='close' onPress={this.cancelSearch} /> </CustomHeaderButtons> ) : ( @@ -186,22 +185,36 @@ class ShareListView extends React.Component { this.setState(...args); } - getSubscriptions = async(server) => { + query = (text) => { const db = database.active; + const defaultWhereClause = [ + Q.where('archived', false), + Q.where('open', true), + Q.experimentalSkip(0), + Q.experimentalTake(50), + Q.experimentalSortBy('room_updated_at', Q.desc) + ]; + if (text) { + return db.collections + .get('subscriptions') + .query( + ...defaultWhereClause, + Q.or( + Q.where('name', Q.like(`%${ Q.sanitizeLikeString(text) }%`)), + Q.where('fname', Q.like(`%${ Q.sanitizeLikeString(text) }%`)) + ) + ).fetch(); + } + return db.collections.get('subscriptions').query(...defaultWhereClause).fetch(); + } + + getSubscriptions = async(server) => { const serversDB = database.servers; if (server) { - this.data = await db.collections - .get('subscriptions') - .query( - Q.where('archived', false), - Q.where('open', true) - ).fetch(); - this.data = orderBy(this.data, ['roomUpdatedAt'], ['desc']); - + this.chats = await this.query(); const serversCollection = serversDB.collections.get('servers'); this.servers = await serversCollection.query().fetch(); - this.chats = this.data.slice(0, LIMIT); let serverInfo = {}; try { serverInfo = await serversCollection.find(server); @@ -210,8 +223,8 @@ class ShareListView extends React.Component { } this.internalSetState({ - chats: this.chats ? this.chats.slice() : [], - servers: this.servers ? this.servers.slice() : [], + chats: this.chats ?? [], + servers: this.servers ?? [], loading: false, serverInfo }); @@ -253,10 +266,10 @@ class ShareListView extends React.Component { }); } - search = (text) => { - const result = this.data.filter(item => item.name.includes(text)) || []; + search = async(text) => { + const result = await this.query(text); this.internalSetState({ - searchResults: result.slice(0, LIMIT), + searchResults: result, searchText: text }); } @@ -297,9 +310,26 @@ class ShareListView extends React.Component { } renderItem = ({ item }) => { + const { serverInfo } = this.state; + const { useRealName } = serverInfo; const { userId, token, server, theme } = this.props; + let description; + switch (item.t) { + case 'c': + description = item.topic || item.description; + break; + case 'p': + description = item.topic || item.description; + break; + case 'd': + description = useRealName ? item.name : item.fname; + break; + default: + description = item.fname; + break; + } return ( <DirectoryItem user={{ @@ -309,11 +339,7 @@ class ShareListView extends React.Component { title={this.getRoomTitle(item)} baseUrl={server} avatar={RocketChat.getRoomAvatar(item)} - description={ - item.t === 'c' - ? (item.topic || item.description) - : item.fname - } + description={description} type={item.prid ? 'discussion' : item.t} onPress={() => this.shareMessage(item)} testID={`share-extension-item-${ item.name }`} diff --git a/app/views/ShareView/Header.js b/app/views/ShareView/Header.js index 7d0312b95..aa1f88c02 100644 --- a/app/views/ShareView/Header.js +++ b/app/views/ShareView/Header.js @@ -45,21 +45,21 @@ const Header = React.memo(({ room, thread, theme }) => { } let icon; if (type === 'discussion') { - icon = 'chat'; + icon = 'discussions'; } else if (type === 'thread') { icon = 'threads'; } else if (type === 'c') { - icon = 'hash'; + icon = 'channel-public'; } else if (type === 'l') { - icon = 'livechat'; + icon = 'omnichannel'; } else if (type === 'd') { if (RocketChat.isGroupChat(room)) { icon = 'team'; } else { - icon = 'at'; + icon = 'mention'; } } else { - icon = 'lock'; + icon = 'channel-private'; } const textColor = themes[theme].previewTintColor; diff --git a/app/views/ShareView/Preview.js b/app/views/ShareView/Preview.js index 2aaff22d8..4b3a9eb81 100644 --- a/app/views/ShareView/Preview.js +++ b/app/views/ShareView/Preview.js @@ -96,7 +96,7 @@ const Preview = React.memo(({ } return ( <IconPreview - iconName={type?.match(/image/) ? 'Camera' : 'clip'} + iconName={type?.match(/image/) ? 'image' : 'attach'} title={item?.filename} description={prettyBytes(item?.size ?? 0)} theme={theme} diff --git a/app/views/ShareView/Thumbs.js b/app/views/ShareView/Thumbs.js index 4b48d7c2d..c9920fad3 100644 --- a/app/views/ShareView/Thumbs.js +++ b/app/views/ShareView/Thumbs.js @@ -80,7 +80,7 @@ const ThumbContent = React.memo(({ item, theme, isShareExtension }) => { return ( <View style={[styles.thumb, { borderColor: themes[theme].borderColor }]}> <CustomIcon - name='Camera' + name='image' size={30} color={themes[theme].tintColor} /> @@ -95,7 +95,7 @@ const ThumbContent = React.memo(({ item, theme, isShareExtension }) => { <> <Image source={{ uri }} style={styles.thumb} /> <CustomIcon - name='video-1' + name='camera-filled' size={20} color={themes[theme].buttonText} style={styles.videoThumbIcon} @@ -127,7 +127,7 @@ const Thumb = ({ > <View style={[styles.removeView, { borderColor: themes[theme].auxiliaryBackground }]}> <CustomIcon - name='Cross' + name='close' color={themes[theme].backgroundColor} size={14} /> diff --git a/app/views/SidebarView/index.js b/app/views/SidebarView/index.js index 2da42c460..6690b3b30 100644 --- a/app/views/SidebarView/index.js +++ b/app/views/SidebarView/index.js @@ -8,7 +8,7 @@ import { Q } from '@nozbe/watermelondb'; import Avatar from '../../containers/Avatar'; import Status from '../../containers/Status/Status'; -import log from '../../utils/log'; +import log, { logEvent, events } from '../../utils/log'; import I18n from '../../i18n'; import scrollPersistTaps from '../../utils/scrollPersistTaps'; import { CustomIcon } from '../../lib/Icons'; @@ -18,7 +18,6 @@ import { themes } from '../../constants/colors'; import database from '../../lib/database'; import { withTheme } from '../../theme'; import { getUserSelector } from '../../selectors/login'; -import Navigation from '../../lib/Navigation'; import SafeAreaView from '../../containers/SafeAreaView'; const Separator = React.memo(({ theme }) => <View style={[styles.separator, { borderColor: themes[theme].separatorColor }]} />); @@ -135,6 +134,7 @@ class Sidebar extends Component { } sidebarNavigate = (route) => { + logEvent(events[`SIDEBAR_GO_${ route.replace('StackNavigator', '').replace('View', '').toUpperCase() }`]); const { navigation } = this.props; navigation.navigate(route); } @@ -164,8 +164,8 @@ class Sidebar extends Component { <Separator theme={theme} /> <SidebarItem text={I18n.t('Admin_Panel')} - left={<CustomIcon name='shield' size={20} color={themes[theme].titleText} />} - onPress={() => Navigation.navigate(routeName)} + left={<CustomIcon name='settings' size={20} color={themes[theme].titleText} />} + onPress={() => this.sidebarNavigate(routeName)} testID='sidebar-settings' current={this.currentItemKey === routeName} /> @@ -193,7 +193,7 @@ class Sidebar extends Component { /> <SidebarItem text={I18n.t('Settings')} - left={<CustomIcon name='cog' size={20} color={themes[theme].titleText} />} + left={<CustomIcon name='administration' size={20} color={themes[theme].titleText} />} onPress={() => this.sidebarNavigate('SettingsStackNavigator')} testID='sidebar-settings' current={this.currentItemKey === 'SettingsStackNavigator'} @@ -210,7 +210,7 @@ class Sidebar extends Component { text={user.statusText || I18n.t('Edit_Status')} left={<Status style={styles.status} size={12} status={user && user.status} />} right={<CustomIcon name='edit' size={20} color={themes[theme].titleText} />} - onPress={() => Navigation.navigate('StatusView')} + onPress={() => this.sidebarNavigate('StatusView')} testID='sidebar-custom-status' /> ); diff --git a/app/views/StatusView.js b/app/views/StatusView.js index 2c91fa294..4cc2fa80d 100644 --- a/app/views/StatusView.js +++ b/app/views/StatusView.js @@ -11,7 +11,7 @@ import TextInput from '../containers/TextInput'; import EventEmitter from '../utils/events'; import Loading from '../containers/Loading'; import RocketChat from '../lib/rocketchat'; -import log from '../utils/log'; +import log, { logEvent, events } from '../utils/log'; import { LISTENER } from '../containers/Toast'; import { themes } from '../constants/colors'; @@ -24,16 +24,16 @@ import SafeAreaView from '../containers/SafeAreaView'; const STATUS = [{ id: 'online', - name: I18n.t('Online') + name: 'Online' }, { id: 'busy', - name: I18n.t('Busy') + name: 'Busy' }, { id: 'away', - name: I18n.t('Away') + name: 'Away' }, { id: 'offline', - name: I18n.t('Invisible') + name: 'Invisible' }]; const styles = StyleSheet.create({ @@ -92,6 +92,7 @@ class StatusView extends React.Component { } submit = async() => { + logEvent(events.STATUS_DONE); const { statusText } = this.state; const { user } = this.props; if (statusText !== user.statusText) { @@ -114,11 +115,14 @@ class StatusView extends React.Component { try { const result = await RocketChat.setUserStatus(user.status, statusText); if (result.success) { + logEvent(events.STATUS_CUSTOM); EventEmitter.emit(LISTENER, { message: I18n.t('Status_saved_successfully') }); } else { + logEvent(events.STATUS_CUSTOM_F); EventEmitter.emit(LISTENER, { message: I18n.t('error-could-not-change-status') }); } } catch { + logEvent(events.STATUS_CUSTOM_F); EventEmitter.emit(LISTENER, { message: I18n.t('error-could-not-change-status') }); } @@ -164,8 +168,9 @@ class StatusView extends React.Component { const { id, name } = item; return ( <ListItem - title={name} + title={I18n.t(name)} onPress={async() => { + logEvent(events[`STATUS_${ item.id.toUpperCase() }`]); if (user.status !== item.id) { try { const result = await RocketChat.setUserStatus(item.id, statusText); @@ -173,6 +178,7 @@ class StatusView extends React.Component { store.dispatch(setUser({ status: item.id })); } } catch (e) { + logEvent(events.SET_STATUS_FAIL); log(e); } } diff --git a/app/views/ThemeView.js b/app/views/ThemeView.js index d8cd96902..e6e07d1f1 100644 --- a/app/views/ThemeView.js +++ b/app/views/ThemeView.js @@ -16,33 +16,34 @@ import { CustomIcon } from '../lib/Icons'; import { THEME_PREFERENCES_KEY } from '../lib/rocketchat'; import { supportSystemTheme } from '../utils/deviceInfo'; import SafeAreaView from '../containers/SafeAreaView'; +import { events, logEvent } from '../utils/log'; const THEME_GROUP = 'THEME_GROUP'; const DARK_GROUP = 'DARK_GROUP'; const SYSTEM_THEME = { - label: I18n.t('Automatic'), + label: 'Automatic', value: 'automatic', group: THEME_GROUP }; const THEMES = [ { - label: I18n.t('Light'), + label: 'Light', value: 'light', group: THEME_GROUP }, { - label: I18n.t('Dark'), + label: 'Dark', value: 'dark', group: THEME_GROUP }, { - label: I18n.t('Dark'), + label: 'Dark', value: 'dark', separator: true, - header: I18n.t('Dark_level'), + header: 'Dark_level', group: DARK_GROUP }, { - label: I18n.t('Black'), + label: 'Black', value: 'black', group: DARK_GROUP } @@ -68,9 +69,9 @@ const styles = StyleSheet.create({ }); class ThemeView extends React.Component { - static navigationOptions = { + static navigationOptions = () => ({ title: I18n.t('Theme') - } + }) static propTypes = { theme: PropTypes.string, @@ -96,9 +97,11 @@ class ThemeView extends React.Component { const { value, group } = item; let changes = {}; if (group === THEME_GROUP && currentTheme !== value) { + logEvent(events.THEME_SET_THEME_GROUP, { theme_group: value }); changes = { currentTheme: value }; } if (group === DARK_GROUP && darkLevel !== value) { + logEvent(events.THEME_SET_DARK_LEVEL, { dark_level: value }); changes = { darkLevel: value }; } this.setTheme(changes); @@ -129,7 +132,7 @@ class ThemeView extends React.Component { <> {item.separator || isFirst ? this.renderSectionHeader(item.header) : null} <ListItem - title={label} + title={I18n.t(label)} onPress={() => this.onClick(item)} testID={`theme-view-${ value }`} right={this.isSelected(item) ? this.renderIcon : null} @@ -139,12 +142,12 @@ class ThemeView extends React.Component { ); } - renderSectionHeader = (header = I18n.t('Theme')) => { + renderSectionHeader = (header = 'Theme') => { const { theme } = this.props; return ( <> <View style={styles.info}> - <Text style={[styles.infoText, { color: themes[theme].infoText }]}>{header}</Text> + <Text style={[styles.infoText, { color: themes[theme].infoText }]}>{I18n.t(header)}</Text> </View> {this.renderSeparator()} </> @@ -169,7 +172,7 @@ class ThemeView extends React.Component { <StatusBar theme={theme} /> <FlatList data={THEMES} - keyExtractor={item => item.value} + keyExtractor={item => item.value + item.group} contentContainerStyle={[ styles.list, { borderColor: themes[theme].separatorColor } diff --git a/app/views/WithoutServersView.js b/app/views/WithoutServersView.js index e5756ea79..136359df1 100644 --- a/app/views/WithoutServersView.js +++ b/app/views/WithoutServersView.js @@ -30,7 +30,7 @@ const styles = StyleSheet.create({ }); class WithoutServerView extends React.Component { - static navigationOptions = { + static navigationOptions = () => ({ title: 'Rocket.Chat', headerLeft: () => ( <CancelModalButton @@ -38,7 +38,7 @@ class WithoutServerView extends React.Component { testID='share-extension-close' /> ) - } + }) static propTypes = { theme: PropTypes.string diff --git a/app/views/WorkspaceView/ServerAvatar.js b/app/views/WorkspaceView/ServerAvatar.js index c7e849028..0a82b30f3 100644 --- a/app/views/WorkspaceView/ServerAvatar.js +++ b/app/views/WorkspaceView/ServerAvatar.js @@ -3,7 +3,7 @@ import { StyleSheet, View, Text } from 'react-native'; import PropTypes from 'prop-types'; import { createImageProgress } from 'react-native-image-progress'; import * as Progress from 'react-native-progress'; -import FastImage from 'react-native-fast-image'; +import FastImage from '@rocket.chat/react-native-fast-image'; import sharedStyles from '../Styles'; import { themes } from '../../constants/colors'; diff --git a/app/views/WorkspaceView/index.js b/app/views/WorkspaceView/index.js index 70531b823..553e7135e 100644 --- a/app/views/WorkspaceView/index.js +++ b/app/views/WorkspaceView/index.js @@ -13,9 +13,9 @@ import ServerAvatar from './ServerAvatar'; import { getShowLoginButton } from '../../selectors/login'; class WorkspaceView extends React.Component { - static navigationOptions = { + static navigationOptions = () => ({ title: I18n.t('Your_workspace') - } + }) static propTypes = { navigation: PropTypes.object, @@ -70,7 +70,7 @@ class WorkspaceView extends React.Component { <FormContainer theme={theme} testID='workspace-view'> <FormContainerInner> <View style={styles.alignItemsCenter}> - <ServerAvatar theme={theme} url={server} image={Assets_favicon_512 && Assets_favicon_512.defaultUrl} /> + <ServerAvatar theme={theme} url={server} image={Assets_favicon_512?.url ?? Assets_favicon_512?.defaultUrl} /> <Text style={[styles.serverName, { color: themes[theme].titleText }]}>{Site_Name}</Text> <Text style={[styles.serverUrl, { color: themes[theme].auxiliaryText }]}>{Site_Url}</Text> </View> diff --git a/e2e/README.md b/e2e/README.md index 597127f2c..995bd3f90 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -1,4 +1,4 @@ -# e2e Testing +# E2E Testing ## Contents diff --git a/e2e/data.js b/e2e/data.js index 4c4c8ca16..d3f4a0df9 100644 --- a/e2e/data.js +++ b/e2e/data.js @@ -9,34 +9,39 @@ const data = { regular: { username: `userone${ value }`, password: '123', - email: `diego.mello+regular${ value }@rocket.chat` + email: `mobile+regular${ value }@rocket.chat` }, alternate: { username: `usertwo${ value }`, password: '123', - email: `diego.mello+alternate${ value }@rocket.chat`, + email: `mobile+alternate${ value }@rocket.chat`, totpSecret: 'NA4GOMZGHBQSK6KEFRVT62DMGJJGSYZJFZIHO3ZOGVXWCYZ6MMZQ' }, profileChanges: { username: `userthree${ value }`, password: '123', - email: `diego.mello+profileChanges${ value }@rocket.chat` + email: `mobile+profileChanges${ value }@rocket.chat` }, existing: { username: `existinguser${ value }`, password: '123', - email: `diego.mello+existing${ value }@rocket.chat` + email: `mobile+existing${ value }@rocket.chat` } }, channels: { - public: { + detoxpublic: { name: 'detox-public' } }, + groups: { + private: { + name: `detox-private-${ value }` + } + }, registeringUser: { username: `newuser${ value }`, password: `password${ value }`, - email: `diego.mello+registering${ value }@rocket.chat` + email: `mobile+registering${ value }@rocket.chat` }, random: value } diff --git a/e2e/data/data.cloud.js b/e2e/data/data.cloud.js index 4c4c8ca16..d3f4a0df9 100644 --- a/e2e/data/data.cloud.js +++ b/e2e/data/data.cloud.js @@ -9,34 +9,39 @@ const data = { regular: { username: `userone${ value }`, password: '123', - email: `diego.mello+regular${ value }@rocket.chat` + email: `mobile+regular${ value }@rocket.chat` }, alternate: { username: `usertwo${ value }`, password: '123', - email: `diego.mello+alternate${ value }@rocket.chat`, + email: `mobile+alternate${ value }@rocket.chat`, totpSecret: 'NA4GOMZGHBQSK6KEFRVT62DMGJJGSYZJFZIHO3ZOGVXWCYZ6MMZQ' }, profileChanges: { username: `userthree${ value }`, password: '123', - email: `diego.mello+profileChanges${ value }@rocket.chat` + email: `mobile+profileChanges${ value }@rocket.chat` }, existing: { username: `existinguser${ value }`, password: '123', - email: `diego.mello+existing${ value }@rocket.chat` + email: `mobile+existing${ value }@rocket.chat` } }, channels: { - public: { + detoxpublic: { name: 'detox-public' } }, + groups: { + private: { + name: `detox-private-${ value }` + } + }, registeringUser: { username: `newuser${ value }`, password: `password${ value }`, - email: `diego.mello+registering${ value }@rocket.chat` + email: `mobile+registering${ value }@rocket.chat` }, random: value } diff --git a/e2e/data/data.docker.js b/e2e/data/data.docker.js index 5a7ed505c..a22423a63 100644 --- a/e2e/data/data.docker.js +++ b/e2e/data/data.docker.js @@ -9,34 +9,39 @@ const data = { regular: { username: `userone${ value }`, password: '123', - email: `diego.mello+regular${ value }@rocket.chat` + email: `mobile+regular${ value }@rocket.chat` }, alternate: { username: `usertwo${ value }`, password: '123', - email: `diego.mello+alternate${ value }@rocket.chat`, + email: `mobile+alternate${ value }@rocket.chat`, totpSecret: 'NA4GOMZGHBQSK6KEFRVT62DMGJJGSYZJFZIHO3ZOGVXWCYZ6MMZQ' }, profileChanges: { username: `userthree${ value }`, password: '123', - email: `diego.mello+profileChanges${ value }@rocket.chat` + email: `mobile+profileChanges${ value }@rocket.chat` }, existing: { username: `existinguser${ value }`, password: '123', - email: `diego.mello+existing${ value }@rocket.chat` + email: `mobile+existing${ value }@rocket.chat` } }, channels: { - public: { + detoxpublic: { name: 'detox-public' } }, + groups: { + private: { + name: `detox-private-${ value }` + } + }, registeringUser: { username: `newuser${ value }`, password: `password${ value }`, - email: `diego.mello+registering${ value }@rocket.chat` + email: `mobile+registering${ value }@rocket.chat` }, random: value } diff --git a/e2e/docker/controlRCDemoEnv.sh b/e2e/docker/controlRCDemoEnv.sh index 16dc49a7a..527d837e3 100755 --- a/e2e/docker/controlRCDemoEnv.sh +++ b/e2e/docker/controlRCDemoEnv.sh @@ -42,7 +42,7 @@ if [ "$COMMAND" == "start" ]; then MAX_ATTEMPTS=60 while [ $ATTEMPT_NUMBER -lt $MAX_ATTEMPTS ]; do # https://stackoverflow.com/a/21189312/399007 ATTEMPT_NUMBER=$((ATTEMPT_NUMBER + 1 )) - echo "Waiting for server to be up ($ATTEMPT_NUMBER of $MAX_ATTEMPTS)" + echo "Checking if servers are ready (attempt $ATTEMPT_NUMBER of $MAX_ATTEMPTS)" LOGS=$(docker logs rc_test_env_rocketchat_1 2> /dev/null) if grep -q 'SERVER RUNNING' <<< $LOGS ; then echo "RocketChat is ready!" diff --git a/e2e/helpers/app.js b/e2e/helpers/app.js index 88ef3d5ad..fcc6dc2ea 100644 --- a/e2e/helpers/app.js +++ b/e2e/helpers/app.js @@ -14,6 +14,7 @@ async function navigateToWorkspace() { } async function navigateToLogin() { + await waitFor(element(by.id('onboarding-view'))).toBeVisible().withTimeout(20000); await navigateToWorkspace(); await element(by.id('workspace-view-login')).tap(); await waitFor(element(by.id('login-view'))).toBeVisible().withTimeout(2000); @@ -21,6 +22,7 @@ async function navigateToLogin() { } async function navigateToRegister() { + await waitFor(element(by.id('onboarding-view'))).toBeVisible().withTimeout(20000); await navigateToWorkspace(); await element(by.id('workspace-view-register')).tap(); await waitFor(element(by.id('register-view'))).toBeVisible().withTimeout(2000); @@ -31,7 +33,6 @@ async function login(username, password) { await waitFor(element(by.id('login-view'))).toBeVisible().withTimeout(2000); await element(by.id('login-view-email')).replaceText(username); await element(by.id('login-view-password')).replaceText(password); - await sleep(300); await element(by.id('login-view-submit')).tap(); await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000); } @@ -61,6 +62,33 @@ async function mockMessage(message) { await element(by.label(`${ data.random }${ message }`)).atIndex(0).tap(); }; +async function starMessage(message){ + const messageLabel = `${ data.random }${ message }` + await waitFor(element(by.label(messageLabel))).toBeVisible().withTimeout(5000); + await element(by.label(messageLabel)).atIndex(0).longPress(); + await expect(element(by.id('action-sheet'))).toExist(); + await expect(element(by.id('action-sheet-handle'))).toBeVisible(); + await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5); + await element(by.label('Star')).tap(); + await waitFor(element(by.id('action-sheet'))).toNotExist().withTimeout(5000); +}; + +async function pinMessage(message){ + const messageLabel = `${ data.random }${ message }` + await waitFor(element(by.label(messageLabel)).atIndex(0)).toExist(); + await element(by.label(messageLabel)).atIndex(0).longPress(); + await expect(element(by.id('action-sheet'))).toExist(); + await expect(element(by.id('action-sheet-handle'))).toBeVisible(); + await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5); + await element(by.label('Pin')).tap(); + await waitFor(element(by.id('action-sheet'))).toNotExist().withTimeout(5000); +} + +async function dismissReviewNag(){ + await waitFor(element(by.text('Are you enjoying this app?'))).toExist().withTimeout(60000); + await element(by.label('No').and(by.type('_UIAlertControllerActionView'))).tap(); // Tap `no` on ask for review alert +} + async function tapBack() { await element(by.id('header-back')).atIndex(0).tap(); } @@ -74,7 +102,22 @@ async function searchRoom(room) { await expect(element(by.id('rooms-list-view-search-input'))).toExist(); await waitFor(element(by.id('rooms-list-view-search-input'))).toExist().withTimeout(5000); await element(by.id('rooms-list-view-search-input')).typeText(room); - await sleep(2000); +} + +async function tryTapping(theElement, timeout, longtap = false){ + try { + if(longtap){ + await theElement.longPress() + } else { + await theElement.tap() + } + } catch(e) { + if(timeout <= 0){ //TODO: Maths. How closely has the timeout been honoured here? + throw e + } + await sleep(100) + await tryTapping(theElement, timeout - 100) + } } module.exports = { @@ -84,7 +127,11 @@ module.exports = { login, logout, mockMessage, + starMessage, + pinMessage, + dismissReviewNag, tapBack, sleep, - searchRoom + searchRoom, + tryTapping }; \ No newline at end of file diff --git a/e2e/helpers/data_setup.js b/e2e/helpers/data_setup.js index 84e5927ea..d16b41a55 100644 --- a/e2e/helpers/data_setup.js +++ b/e2e/helpers/data_setup.js @@ -38,7 +38,7 @@ const createUser = async (username, password, name, email) => { } const createChannelIfNotExists = async (channelname) => { - console.log(`Creating channel ${channelname}`) + console.log(`Creating public channel ${channelname}`) try { await rocketchat.post('channels.create', { "name": channelname @@ -49,7 +49,24 @@ const createChannelIfNotExists = async (channelname) => { } catch (infoError) { console.log(JSON.stringify(createError)) console.log(JSON.stringify(infoError)) - throw "Failed to find or create channel" + throw "Failed to find or create public channel" + } + } +} + +const createGroupIfNotExists = async (groupname) => { + console.log(`Creating private group ${groupname}`) + try { + await rocketchat.post('groups.create', { + "name": groupname + }) + } catch (createError) { + try { //Maybe it exists already? + await rocketchat.get(`group.info?roomName=${groupname}`) + } catch (infoError) { + console.log(JSON.stringify(createError)) + console.log(JSON.stringify(infoError)) + throw "Failed to find or create private group" } } } @@ -71,6 +88,15 @@ const setup = async () => { } } + await login(data.users.regular.username, data.users.regular.password) + + for (var groupKey in data.groups) { + if (data.groups.hasOwnProperty(groupKey)) { + const group = data.groups[groupKey] + await createGroupIfNotExists(group.name) + } + } + return } diff --git a/e2e/tests/assorted/01-changeserver.spec.js b/e2e/tests/assorted/01-changeserver.spec.js index 0664970a7..7210d7060 100644 --- a/e2e/tests/assorted/01-changeserver.spec.js +++ b/e2e/tests/assorted/01-changeserver.spec.js @@ -9,12 +9,12 @@ const checkServer = async(server) => { await element(by.id('rooms-list-view-sidebar')).tap(); await waitFor(element(by.id('sidebar-view'))).toBeVisible().withTimeout(2000); await waitFor(element(by.label(label))).toBeVisible().withTimeout(60000); - await expect(element(by.label(label))).toBeVisible(); await element(by.id('sidebar-close-drawer')).tap(); } describe('Change server', () => { before(async() => { + await device.launchApp({ permissions: { notifications: 'YES' }, delete: true }); await navigateToLogin(); await login(data.users.regular.username, data.users.regular.password); await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000); @@ -28,8 +28,6 @@ describe('Change server', () => { await sleep(5000); await element(by.id('rooms-list-header-server-dropdown-button')).tap(); await waitFor(element(by.id('rooms-list-header-server-dropdown'))).toBeVisible().withTimeout(5000); - await expect(element(by.id('rooms-list-header-server-dropdown'))).toExist(); - await sleep(1000); await element(by.id('rooms-list-header-server-add')).tap(); // TODO: refactor @@ -37,19 +35,16 @@ describe('Change server', () => { await element(by.id('new-server-view-input')).replaceText(data.alternateServer); await element(by.id('new-server-view-button')).tap(); await waitFor(element(by.id('workspace-view'))).toBeVisible().withTimeout(60000); - await expect(element(by.id('workspace-view'))).toBeVisible(); await element(by.id('workspace-view-register')).tap(); await waitFor(element(by.id('register-view'))).toBeVisible().withTimeout(2000); - await expect(element(by.id('register-view'))).toBeVisible(); + // Register new user await element(by.id('register-view-name')).replaceText(data.registeringUser.username); await element(by.id('register-view-username')).replaceText(data.registeringUser.username); await element(by.id('register-view-email')).replaceText(data.registeringUser.email); await element(by.id('register-view-password')).replaceText(data.registeringUser.password); - await sleep(1000); await element(by.id('register-view-submit')).tap(); await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(60000); - await expect(element(by.id('rooms-list-view'))).toBeVisible(); // For a sanity test, to make sure roomslist is showing correct rooms // app CANNOT show public room created on previous tests @@ -59,11 +54,8 @@ describe('Change server', () => { }); it('should change back', async() => { - await sleep(5000); await element(by.id('rooms-list-header-server-dropdown-button')).tap(); await waitFor(element(by.id('rooms-list-header-server-dropdown'))).toBeVisible().withTimeout(5000); - await expect(element(by.id('rooms-list-header-server-dropdown'))).toExist(); - await sleep(1000); await element(by.id(`rooms-list-header-server-${ data.server }`)).tap(); await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000); await checkServer(data.server); diff --git a/e2e/tests/assorted/02-broadcast.spec.js b/e2e/tests/assorted/02-broadcast.spec.js index 1b2fcc1db..9e87c5e14 100644 --- a/e2e/tests/assorted/02-broadcast.spec.js +++ b/e2e/tests/assorted/02-broadcast.spec.js @@ -23,28 +23,16 @@ describe('Broadcast room', () => { await waitFor(element(by.id('select-users-view'))).toBeVisible().withTimeout(2000); await element(by.id('select-users-view-search')).replaceText(otheruser.username); await waitFor(element(by.id(`select-users-view-item-${ otheruser.username }`))).toBeVisible().withTimeout(60000); - await expect(element(by.id(`select-users-view-item-${ otheruser.username }`))).toBeVisible(); await element(by.id(`select-users-view-item-${ otheruser.username }`)).tap(); await waitFor(element(by.id(`selected-user-${ otheruser.username }`))).toBeVisible().withTimeout(5000); - await sleep(1000); await element(by.id('selected-users-view-submit')).tap(); - await sleep(1000); await waitFor(element(by.id('create-channel-view'))).toExist().withTimeout(5000); await element(by.id('create-channel-name')).replaceText(`broadcast${ data.random }`); - await sleep(2000); - await element(by.id('create-channel-broadcast')).tap(); - if (device.getPlatform() === 'ios') { //Because this tap is FLAKY on iOS - await expect(element(by.id('create-channel-broadcast'))).toHaveValue('1') - } - await sleep(500); + await element(by.id('create-channel-broadcast')).longPress(); //https://github.com/facebook/react-native/issues/28032 await element(by.id('create-channel-submit')).tap(); await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(60000); - await expect(element(by.id('room-view'))).toBeVisible(); await waitFor(element(by.id(`room-view-title-broadcast${ data.random }`))).toBeVisible().withTimeout(60000); - await expect(element(by.id(`room-view-title-broadcast${ data.random }`))).toBeVisible(); - await sleep(1000); await element(by.id('room-view-header-actions')).tap(); - await sleep(1000); await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(5000); await element(by.id('room-actions-info')).tap(); await waitFor(element(by.id('room-info-view'))).toBeVisible().withTimeout(2000); @@ -64,25 +52,19 @@ describe('Broadcast room', () => { it('should login as user without write message authorization and enter room', async() => { await device.launchApp({ permissions: { notifications: 'YES' }, delete: true }); await navigateToLogin(); - await element(by.id('login-view-email')).replaceText(otheruser.username); - await element(by.id('login-view-password')).replaceText(otheruser.password); - await sleep(1000); - await element(by.id('login-view-submit')).tap(); + await login(otheruser.username, otheruser.password); + //await waitFor(element(by.id('two-factor'))).toBeVisible().withTimeout(5000); //await expect(element(by.id('two-factor'))).toBeVisible(); //const code = GA.gen(data.alternateUserTOTPSecret); //await element(by.id('two-factor-input')).replaceText(code); - //await sleep(1000); //await element(by.id('two-factor-send')).tap(); - await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000); + await searchRoom(`broadcast${ data.random }`); await waitFor(element(by.id(`rooms-list-view-item-broadcast${ data.random }`))).toExist().withTimeout(60000); - await expect(element(by.id(`rooms-list-view-item-broadcast${ data.random }`))).toExist(); await element(by.id(`rooms-list-view-item-broadcast${ data.random }`)).tap(); await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(5000); await waitFor(element(by.id(`room-view-title-broadcast${ data.random }`))).toBeVisible().withTimeout(60000); - await expect(element(by.id(`room-view-title-broadcast${ data.random }`))).toBeVisible(); - await sleep(1000); }); it('should not have messagebox', async() => { @@ -95,7 +77,6 @@ describe('Broadcast room', () => { it('should have the message created earlier', async() => { await waitFor(element(by.label(`${ data.random }message`)).atIndex(0)).toBeVisible().withTimeout(60000); - await expect(element(by.label(`${ data.random }message`)).atIndex(0)).toBeVisible(); }); it('should have reply button', async() => { @@ -104,9 +85,7 @@ describe('Broadcast room', () => { it('should tap on reply button and navigate to direct room', async() => { await element(by.id('message-broadcast-reply')).tap(); - await sleep(1000); await waitFor(element(by.id(`room-view-title-${ testuser.username }`))).toBeVisible().withTimeout(5000); - await expect(element(by.id(`room-view-title-${ testuser.username }`))).toBeVisible(); }); it('should reply broadcasted message', async() => { diff --git a/e2e/tests/assorted/03-profile.spec.js b/e2e/tests/assorted/03-profile.spec.js index e5c321757..9700da1b2 100644 --- a/e2e/tests/assorted/03-profile.spec.js +++ b/e2e/tests/assorted/03-profile.spec.js @@ -13,7 +13,7 @@ async function waitForToast() { // await expect(element(by.id('toast'))).toBeVisible(); // await waitFor(element(by.id('toast'))).toBeNotVisible().withTimeout(10000); // await expect(element(by.id('toast'))).toBeNotVisible(); - await sleep(5000); + await sleep(1); } describe('Profile screen', () => { @@ -24,7 +24,6 @@ describe('Profile screen', () => { await element(by.id('rooms-list-view-sidebar')).tap(); await waitFor(element(by.id('sidebar-view'))).toBeVisible().withTimeout(2000); await waitFor(element(by.id('sidebar-profile'))).toBeVisible().withTimeout(2000); - await expect(element(by.id('sidebar-profile'))).toBeVisible(); await element(by.id('sidebar-profile')).tap(); await waitFor(element(by.id('profile-view'))).toBeVisible().withTimeout(2000); }); @@ -60,22 +59,18 @@ describe('Profile screen', () => { it('should have reset avatar button', async() => { await waitFor(element(by.id('profile-view-reset-avatar'))).toExist().whileElement(by.id('profile-view-list')).scroll(scrollDown, 'down'); - await expect(element(by.id('profile-view-reset-avatar'))).toExist(); }); it('should have upload avatar button', async() => { await waitFor(element(by.id('profile-view-upload-avatar'))).toExist().whileElement(by.id('profile-view-list')).scroll(scrollDown, 'down'); - await expect(element(by.id('profile-view-upload-avatar'))).toExist(); }); it('should have avatar url button', async() => { await waitFor(element(by.id('profile-view-avatar-url-button'))).toExist().whileElement(by.id('profile-view-list')).scroll(scrollDown, 'down'); - await expect(element(by.id('profile-view-avatar-url-button'))).toExist(); }); it('should have submit button', async() => { await waitFor(element(by.id('profile-view-submit'))).toExist().whileElement(by.id('profile-view-list')).scroll(scrollDown, 'down'); - await expect(element(by.id('profile-view-submit'))).toExist(); }); }); @@ -84,15 +79,13 @@ describe('Profile screen', () => { await element(by.type('UIScrollView')).atIndex(1).swipe('down'); await element(by.id('profile-view-name')).replaceText(`${ profileChangeUser.username }new`); await element(by.id('profile-view-username')).replaceText(`${ profileChangeUser.username }new`); - await sleep(1000); await element(by.type('UIScrollView')).atIndex(1).swipe('up'); - await sleep(1000); await element(by.id('profile-view-submit')).tap(); await waitForToast(); }); it('should change email and password', async() => { - await element(by.id('profile-view-email')).replaceText(`diego.mello+profileChangesNew${ data.random }@rocket.chat`); + await element(by.id('profile-view-email')).replaceText(`mobile+profileChangesNew${ data.random }@rocket.chat`); await element(by.id('profile-view-new-password')).replaceText(`${ profileChangeUser.password }new`); await element(by.id('profile-view-submit')).tap(); await element(by.type('_UIAlertControllerTextField')).replaceText(`${ profileChangeUser.password }`) @@ -103,7 +96,6 @@ describe('Profile screen', () => { it('should reset avatar', async() => { await element(by.type('UIScrollView')).atIndex(1).swipe('up'); - await sleep(1000); await element(by.id('profile-view-reset-avatar')).tap(); await waitForToast(); }); diff --git a/e2e/tests/assorted/04-setting.spec.js b/e2e/tests/assorted/04-setting.spec.js index c2cfae6f1..951ccc70d 100644 --- a/e2e/tests/assorted/04-setting.spec.js +++ b/e2e/tests/assorted/04-setting.spec.js @@ -1,12 +1,18 @@ const { device, expect, element, by, waitFor } = require('detox'); +const { navigateToLogin, login } = require('../../helpers/app'); + +const data = require('../../data'); + +const testuser = data.users.regular describe('Settings screen', () => { before(async() => { - await device.launchApp({ newInstance: true }); + await device.launchApp({ permissions: { notifications: 'YES' }, delete: true }); + await navigateToLogin(); + await login(testuser.username, testuser.password); await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000); - await expect(element(by.id('rooms-list-view'))).toBeVisible(); await element(by.id('rooms-list-view-sidebar')).tap(); await waitFor(element(by.id('sidebar-view'))).toBeVisible().withTimeout(2000); await waitFor(element(by.id('sidebar-settings'))).toBeVisible().withTimeout(2000); diff --git a/e2e/tests/assorted/05-joinpublicroom.spec.js b/e2e/tests/assorted/05-joinpublicroom.spec.js index d68d1a955..1c946f0c2 100644 --- a/e2e/tests/assorted/05-joinpublicroom.spec.js +++ b/e2e/tests/assorted/05-joinpublicroom.spec.js @@ -2,12 +2,12 @@ const { device, expect, element, by, waitFor } = require('detox'); const data = require('../../data'); -const { mockMessage, tapBack, sleep, searchRoom } = require('../../helpers/app'); +const { navigateToLogin, login, mockMessage, tapBack, sleep, searchRoom } = require('../../helpers/app'); -const room = 'detox-public'; +const testuser = data.users.regular +const room = data.channels.detoxpublic.name; async function navigateToRoom() { - await sleep(2000); await searchRoom(room); await waitFor(element(by.id(`rooms-list-view-item-${ room }`)).atIndex(0)).toBeVisible().withTimeout(60000); await element(by.id(`rooms-list-view-item-${ room }`)).atIndex(0).tap(); @@ -15,15 +15,15 @@ async function navigateToRoom() { } async function navigateToRoomActions() { - await sleep(2000); await element(by.id('room-view-header-actions')).tap(); - await sleep(2000); await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(5000); } describe('Join public room', () => { before(async() => { - await device.launchApp({ newInstance: true }); + await device.launchApp({ permissions: { notifications: 'YES' }, delete: true }); + await navigateToLogin(); + await login(testuser.username, testuser.password); await navigateToRoom(); }); @@ -167,9 +167,7 @@ describe('Join public room', () => { await element(by.text('Yes, leave it!')).tap(); await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000); // await element(by.id('rooms-list-view-search')).typeText(''); - await sleep(2000); await waitFor(element(by.id(`rooms-list-view-item-${ room }`))).toBeNotVisible().withTimeout(60000); - await expect(element(by.id(`rooms-list-view-item-${ room }`))).toBeNotVisible(); }); }); }); diff --git a/e2e/tests/assorted/06-status.spec.js b/e2e/tests/assorted/06-status.spec.js index ee592d41f..887dcb1e0 100644 --- a/e2e/tests/assorted/06-status.spec.js +++ b/e2e/tests/assorted/06-status.spec.js @@ -1,14 +1,21 @@ const { expect, element, by, waitFor } = require('detox'); -const { sleep } = require('../../helpers/app'); +const { navigateToLogin, login, sleep } = require('../../helpers/app'); + +const data = require('../../data'); +const testuser = data.users.regular async function waitForToast() { - await sleep(5000); + await sleep(1); } describe('Status screen', () => { - before(async() => { + before(async () => { + await device.launchApp({ permissions: { notifications: 'YES' }, delete: true }); + await navigateToLogin(); + await login(testuser.username, testuser.password); + await element(by.id('rooms-list-view-sidebar')).tap(); await waitFor(element(by.id('sidebar-view'))).toBeVisible().withTimeout(2000); await waitFor(element(by.id('sidebar-custom-status'))).toBeVisible().withTimeout(2000); @@ -17,30 +24,27 @@ describe('Status screen', () => { await waitFor(element(by.id('status-view'))).toBeVisible().withTimeout(2000); }); - describe('Render', async() => { - it('should have status input', async() => { + describe('Render', async () => { + it('should have status input', async () => { await expect(element(by.id('status-view-input'))).toBeVisible(); await expect(element(by.id('status-view-online'))).toExist(); await expect(element(by.id('status-view-busy'))).toExist(); await expect(element(by.id('status-view-away'))).toExist(); await expect(element(by.id('status-view-offline'))).toExist(); - }); - }); - - describe('Usage', async() => { - it('should change status', async() => { - await sleep(1000); - await element(by.id('status-view-busy')).tap(); - await sleep(1000); - await expect(element(by.id('status-view-current-busy'))).toExist(); - }); + }); + }); - it('should change status text', async() => { + describe('Usage', async () => { + it('should change status', async () => { + await element(by.id('status-view-busy')).tap(); + await expect(element(by.id('status-view-current-busy'))).toExist(); + }); + + it('should change status text', async () => { await element(by.id('status-view-input')).replaceText('status-text-new'); - await sleep(1000); await element(by.id('status-view-submit')).tap(); await waitForToast(); await waitFor(element(by.label('status-text-new').withAncestor(by.id('sidebar-custom-status')))).toBeVisible().withTimeout(2000); - }); - }); -}); + }); + }); +}); \ No newline at end of file diff --git a/e2e/tests/init.js b/e2e/tests/init.js index bef12f6d3..9eaa721b6 100644 --- a/e2e/tests/init.js +++ b/e2e/tests/init.js @@ -1,11 +1,21 @@ const detox = require('detox'); const config = require('../../package.json').detox; const dataSetup = require('../helpers/data_setup') +const adapter = require('detox/runners/mocha/adapter'); before(async() => { - await dataSetup() - await detox.init(config, { launchApp: false }); - await device.launchApp({ permissions: { notifications: 'YES' } }); + await Promise.all([dataSetup(), detox.init(config, { launchApp: false })]) + //await dataSetup() + //await detox.init(config, { launchApp: false }); + //await device.launchApp({ permissions: { notifications: 'YES' } }); +}); + +beforeEach(async function() { + await adapter.beforeEach(this); +}); + +afterEach(async function() { + await adapter.afterEach(this); }); after(async() => { diff --git a/e2e/tests/onboarding/01-onboarding.spec.js b/e2e/tests/onboarding/01-onboarding.spec.js index c84928d60..4806dcb57 100644 --- a/e2e/tests/onboarding/01-onboarding.spec.js +++ b/e2e/tests/onboarding/01-onboarding.spec.js @@ -6,7 +6,7 @@ const data = require('../../data'); describe('Onboarding', () => { before(async() => { await device.launchApp({ permissions: { notifications: 'YES' }, delete: true }); - await waitFor(element(by.id('onboarding-view'))).toBeVisible().withTimeout(2000); + await waitFor(element(by.id('onboarding-view'))).toBeVisible().withTimeout(20000); }); describe('Render', () => { @@ -31,7 +31,6 @@ describe('Onboarding', () => { it('should navigate to join a workspace', async() => { await element(by.id('join-workspace')).tap(); await waitFor(element(by.id('new-server-view'))).toBeVisible().withTimeout(60000); - await expect(element(by.id('new-server-view'))).toBeVisible(); }); it('should enter an invalid server and get error', async() => { @@ -39,14 +38,12 @@ describe('Onboarding', () => { await element(by.id('new-server-view-button')).tap(); const errorText = 'Oops!'; await waitFor(element(by.text(errorText))).toBeVisible().withTimeout(60000); - await expect(element(by.text(errorText))).toBeVisible(); await element(by.text('OK')).tap(); }); it('should tap on "Join our open workspace" and navigate', async() => { await element(by.id('new-server-view-open')).tap(); await waitFor(element(by.id('workspace-view'))).toBeVisible().withTimeout(60000); - await expect(element(by.id('workspace-view'))).toBeVisible(); }); it('should enter a valid server without login services and navigate to login', async() => { @@ -57,7 +54,6 @@ describe('Onboarding', () => { await element(by.id('new-server-view-input')).replaceText(data.server); await element(by.id('new-server-view-button')).tap(); await waitFor(element(by.id('workspace-view'))).toBeVisible().withTimeout(60000); - await expect(element(by.id('workspace-view'))).toBeVisible(); }); }); }); diff --git a/e2e/tests/onboarding/02-legal.spec.js b/e2e/tests/onboarding/02-legal.spec.js index e8109ece5..191e0647c 100644 --- a/e2e/tests/onboarding/02-legal.spec.js +++ b/e2e/tests/onboarding/02-legal.spec.js @@ -4,54 +4,62 @@ const { const { navigateToRegister, navigateToLogin } = require('../../helpers/app'); describe('Legal screen', () => { - it('should have legal button on login', async() => { - await device.launchApp({ newInstance: true }); - await navigateToLogin(); - await waitFor(element(by.id('login-view-more'))).toBeVisible().withTimeout(60000); - await expect(element(by.id('login-view-more'))).toBeVisible(); - }); - it('should navigate to legal from login', async() => { - await waitFor(element(by.id('login-view-more'))).toBeVisible().withTimeout(60000); - await element(by.id('login-view-more')).tap(); - }); - - it('should have legal button on register', async() => { - await device.launchApp({ newInstance: true }); - await navigateToRegister(); - await waitFor(element(by.id('register-view-more'))).toBeVisible().withTimeout(60000); - await expect(element(by.id('register-view-more'))).toBeVisible(); - }); - - it('should navigate to legal from register', async() => { - await waitFor(element(by.id('register-view-more'))).toBeVisible().withTimeout(60000); - await element(by.id('register-view-more')).tap(); - }); - - it('should have legal screen', async() => { - await expect(element(by.id('legal-view'))).toBeVisible(); - }); - - it('should have terms of service button', async() => { - await expect(element(by.id('legal-terms-button'))).toBeVisible(); - }); - - it('should have privacy policy button', async() => { - await expect(element(by.id('legal-privacy-button'))).toBeVisible(); - }); + describe('From Login', () => { + before(async() => { + await device.launchApp({ permissions: { notifications: 'YES' }, delete: true }); + await navigateToLogin(); + }); - - // We can't simulate how webview behaves, so I had to disable :( - // it('should navigate to terms', async() => { - // await element(by.id('legal-terms-button')).tap(); - // await waitFor(element(by.id('terms-view'))).toBeVisible().withTimeout(2000); - // await expect(element(by.id('terms-view'))).toBeVisible(); - // }); + it('should have legal button on login', async() => { + await waitFor(element(by.id('login-view-more'))).toBeVisible().withTimeout(60000); + }); - // it('should navigate to privacy', async() => { - // await tapBack(); - // await element(by.id('legal-privacy-button')).tap(); - // await waitFor(element(by.id('privacy-view'))).toBeVisible().withTimeout(2000); - // await expect(element(by.id('privacy-view'))).toBeVisible(); - // }); + it('should navigate to legal from login', async() => { + await expect(element(by.id('login-view-more'))).toBeVisible(); + await element(by.id('login-view-more')).tap(); + await waitFor(element(by.id('legal-view'))).toBeVisible().withTimeout(4000) + }); + }); + + describe('From Register', () => { + before(async() => { + await device.launchApp({ permissions: { notifications: 'YES' }, delete: true }); + await navigateToRegister(); + }); + + it('should have legal button on register', async() => { + await waitFor(element(by.id('register-view-more'))).toBeVisible().withTimeout(60000); + }); + + it('should navigate to legal from register', async() => { + await expect(element(by.id('register-view-more'))).toBeVisible(); + await element(by.id('register-view-more')).tap(); + await waitFor(element(by.id('legal-view'))).toBeVisible().withTimeout(4000); + }); + + it('should have terms of service button', async() => { + await expect(element(by.id('legal-terms-button'))).toBeVisible(); + }); + + it('should have privacy policy button', async() => { + await expect(element(by.id('legal-privacy-button'))).toBeVisible(); + }); + + // We can't simulate how webview behaves, so I had to disable :( + /* + it('should navigate to terms', async() => { + await element(by.id('legal-terms-button')).tap(); + await waitFor(element(by.id('terms-view'))).toBeVisible().withTimeout(2000); + await expect(element(by.id('terms-view'))).toBeVisible(); + }); + + it('should navigate to privacy', async() => { + await tapBack(); + await element(by.id('legal-privacy-button')).tap(); + await waitFor(element(by.id('privacy-view'))).toBeVisible().withTimeout(2000); + await expect(element(by.id('privacy-view'))).toBeVisible(); + }); + */ + }); }); diff --git a/e2e/tests/onboarding/03-forgotpassword.spec.js b/e2e/tests/onboarding/03-forgotpassword.spec.js index 2fa710469..88d4c3e90 100644 --- a/e2e/tests/onboarding/03-forgotpassword.spec.js +++ b/e2e/tests/onboarding/03-forgotpassword.spec.js @@ -32,7 +32,6 @@ describe('Forgot password screen', () => { await element(by.id('forgot-password-view-submit')).tap(); await element(by.text('OK')).tap(); await waitFor(element(by.id('login-view'))).toBeVisible().withTimeout(60000); - await expect(element(by.id('login-view'))).toBeVisible(); }); }); }); diff --git a/e2e/tests/onboarding/04-createuser.spec.js b/e2e/tests/onboarding/04-createuser.spec.js index dbe28a471..aa75807f2 100644 --- a/e2e/tests/onboarding/04-createuser.spec.js +++ b/e2e/tests/onboarding/04-createuser.spec.js @@ -37,6 +37,7 @@ describe('Create user screen', () => { }); describe('Usage', () => { + // FIXME: Detox isn't able to check if it's tappable: https://github.com/wix/Detox/issues/246 // it('should submit invalid email and do nothing', async() => { // const invalidEmail = 'invalidemail'; @@ -52,10 +53,8 @@ describe('Create user screen', () => { await element(by.id('register-view-username')).replaceText(data.registeringUser.username); await element(by.id('register-view-email')).replaceText(data.users.existing.email); await element(by.id('register-view-password')).replaceText(data.registeringUser.password); - await sleep(300); await element(by.id('register-view-submit')).tap(); await waitFor(element(by.text('Email already exists. [403]')).atIndex(0)).toExist().withTimeout(10000); - await expect(element(by.text('Email already exists. [403]')).atIndex(0)).toExist(); await element(by.text('OK')).tap(); }); @@ -64,10 +63,8 @@ describe('Create user screen', () => { await element(by.id('register-view-username')).replaceText(data.users.existing.username); await element(by.id('register-view-email')).replaceText(data.registeringUser.email); await element(by.id('register-view-password')).replaceText(data.registeringUser.password); - await sleep(300); await element(by.id('register-view-submit')).tap(); await waitFor(element(by.text('Username is already in use')).atIndex(0)).toExist().withTimeout(10000); - await expect(element(by.text('Username is already in use')).atIndex(0)).toExist(); await element(by.text('OK')).tap(); }); @@ -76,10 +73,8 @@ describe('Create user screen', () => { await element(by.id('register-view-username')).replaceText(data.registeringUser.username); await element(by.id('register-view-email')).replaceText(data.registeringUser.email); await element(by.id('register-view-password')).replaceText(data.registeringUser.password); - await sleep(300); await element(by.id('register-view-submit')).tap(); await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(60000); - await expect(element(by.id('rooms-list-view'))).toBeVisible(); }); }); }); diff --git a/e2e/tests/onboarding/05-login.spec.js b/e2e/tests/onboarding/05-login.spec.js index 3734b543d..7c6b4853c 100644 --- a/e2e/tests/onboarding/05-login.spec.js +++ b/e2e/tests/onboarding/05-login.spec.js @@ -44,33 +44,27 @@ describe('Login screen', () => { it('should navigate to register', async() => { await element(by.id('login-view-register')).tap(); await waitFor(element(by.id('register-view'))).toBeVisible().withTimeout(2000); - await expect(element(by.id('register-view'))).toBeVisible(); await tapBack(); }); it('should navigate to forgot password', async() => { await element(by.id('login-view-forgot-password')).tap(); await waitFor(element(by.id('forgot-password-view'))).toExist().withTimeout(2000); - await expect(element(by.id('forgot-password-view'))).toExist(); await tapBack(); }); it('should insert wrong password and get error', async() => { await element(by.id('login-view-email')).replaceText(data.users.regular.username); await element(by.id('login-view-password')).replaceText('NotMyActualPassword'); - await sleep(300); await element(by.id('login-view-submit')).tap(); await waitFor(element(by.text('Your credentials were rejected! Please try again.'))).toBeVisible().withTimeout(10000); - await expect(element(by.text('Your credentials were rejected! Please try again.'))).toBeVisible(); await element(by.text('OK')).tap(); }); it('should login with success', async() => { await element(by.id('login-view-password')).replaceText(data.users.regular.password); - await sleep(300); await element(by.id('login-view-submit')).tap(); await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(60000); - await expect(element(by.id('rooms-list-view'))).toBeVisible(); }); }); }); diff --git a/e2e/tests/onboarding/06-roomslist.spec.js b/e2e/tests/onboarding/06-roomslist.spec.js index 5e7e1e8aa..bbe0b886b 100644 --- a/e2e/tests/onboarding/06-roomslist.spec.js +++ b/e2e/tests/onboarding/06-roomslist.spec.js @@ -1,9 +1,17 @@ const { device, expect, element, by, waitFor } = require('detox'); -const { logout, tapBack, sleep, searchRoom } = require('../../helpers/app'); +const { login, navigateToLogin, logout, tapBack, sleep, searchRoom } = require('../../helpers/app'); +const data = require('../../data'); describe('Rooms list screen', () => { + + before(async() => { + await device.launchApp({ permissions: { notifications: 'YES' }, newInstance: true, delete: true }); + await navigateToLogin(); + await login(data.users.regular.username, data.users.regular.password) + }); + describe('Render', () => { it('should have rooms list screen', async() => { await expect(element(by.id('rooms-list-view'))).toBeVisible(); @@ -29,18 +37,12 @@ describe('Rooms list screen', () => { it('should search room and navigate', async() => { await searchRoom('rocket.cat'); await waitFor(element(by.id('rooms-list-view-item-rocket.cat'))).toBeVisible().withTimeout(60000); - await expect(element(by.id('rooms-list-view-item-rocket.cat'))).toBeVisible(); await element(by.id('rooms-list-view-item-rocket.cat')).tap(); await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(10000); - await expect(element(by.id('room-view'))).toBeVisible(); await waitFor(element(by.id('room-view-title-rocket.cat'))).toBeVisible().withTimeout(60000); - await expect(element(by.id('room-view-title-rocket.cat'))).toBeVisible(); await tapBack(); await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000); - await expect(element(by.id('rooms-list-view'))).toBeVisible(); - await sleep(2000); await waitFor(element(by.id('rooms-list-view-item-rocket.cat'))).toExist().withTimeout(60000); - await expect(element(by.id('rooms-list-view-item-rocket.cat'))).toExist(); }); it('should logout', async() => { diff --git a/e2e/tests/room/01-createroom.spec.js b/e2e/tests/room/01-createroom.spec.js index 1cfbf16a7..3fb464458 100644 --- a/e2e/tests/room/01-createroom.spec.js +++ b/e2e/tests/room/01-createroom.spec.js @@ -2,60 +2,59 @@ const { device, expect, element, by, waitFor } = require('detox'); const data = require('../../data'); -const { tapBack, sleep, navigateToLogin, login } = require('../../helpers/app'); +const { tapBack, sleep, navigateToLogin, login, tryTapping } = require('../../helpers/app'); + + describe('Create room screen', () => { before(async() => { + await device.launchApp({ permissions: { notifications: 'YES' }, delete: true }); await navigateToLogin(); await login(data.users.regular.username, data.users.regular.password); - await element(by.id('rooms-list-view-create-channel')).tap(); - await waitFor(element(by.id('new-message-view'))).toExist().withTimeout(2000); }); describe('New Message', async() => { + before(async() => { + await element(by.id('rooms-list-view-create-channel')).tap(); + }); + describe('Render', async() => { it('should have new message screen', async() => { - await expect(element(by.id('new-message-view'))).toExist(); + await waitFor(element(by.id('new-message-view'))).toBeVisible().withTimeout(2000); }); it('should have search input', async() => { - await waitFor(element(by.id('new-message-view-search'))).toExist().withTimeout(2000); - await expect(element(by.id('new-message-view-search'))).toExist(); + await waitFor(element(by.id('new-message-view-search'))).toBeVisible().withTimeout(2000); }); }) describe('Usage', async() => { it('should back to rooms list', async() => { - await sleep(1000); + await waitFor(element(by.id('new-message-view-close'))).toBeVisible().withTimeout(5000); await element(by.id('new-message-view-close')).tap(); - await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(2000); - await expect(element(by.id('rooms-list-view'))).toExist(); - await element(by.id('rooms-list-view-create-channel')).tap(); - await waitFor(element(by.id('new-message-view'))).toExist().withTimeout(2000); - await expect(element(by.id('new-message-view'))).toExist(); + + await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(5000); + + await tryTapping(element(by.id('rooms-list-view-create-channel')), 3000); + //await element(by.id('rooms-list-view-create-channel')).tap(); + await waitFor(element(by.id('new-message-view'))).toExist().withTimeout(5000); }); it('should search user and navigate', async() => { await element(by.id('new-message-view-search')).replaceText('rocket.cat'); await waitFor(element(by.id('new-message-view-item-rocket.cat'))).toExist().withTimeout(60000); - await expect(element(by.id('new-message-view-item-rocket.cat'))).toExist(); await element(by.id('new-message-view-item-rocket.cat')).tap(); await waitFor(element(by.id('room-view'))).toExist().withTimeout(10000); - await expect(element(by.id('room-view'))).toExist(); await waitFor(element(by.id('room-view-title-rocket.cat'))).toExist().withTimeout(60000); - await expect(element(by.id('room-view-title-rocket.cat'))).toExist(); await tapBack(); - await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(2000); + await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(5000); }); it('should navigate to select users', async() => { await element(by.id('rooms-list-view-create-channel')).tap(); - await waitFor(element(by.id('new-message-view'))).toExist().withTimeout(2000); - await expect(element(by.id('new-message-view'))).toExist(); - await sleep(1000); + await waitFor(element(by.id('new-message-view'))).toExist().withTimeout(5000); await element(by.id('new-message-view-create-channel')).tap(); - await waitFor(element(by.id('select-users-view'))).toExist().withTimeout(2000); - await expect(element(by.id('select-users-view'))).toExist(); + await waitFor(element(by.id('select-users-view'))).toExist().withTimeout(5000); }); }) }); @@ -63,35 +62,31 @@ describe('Create room screen', () => { describe('Select Users', async() => { it('should search users', async() => { await element(by.id('select-users-view-search')).replaceText('rocket.cat'); - await waitFor(element(by.id(`select-users-view-item-rocket.cat`))).toExist().withTimeout(10000); - await expect(element(by.id(`select-users-view-item-rocket.cat`))).toExist(); + await waitFor(element(by.id(`select-users-view-item-rocket.cat`))).toBeVisible().withTimeout(10000); }); it('should select/unselect user', async() => { await element(by.id('select-users-view-item-rocket.cat')).tap(); - await waitFor(element(by.id('selected-user-rocket.cat'))).toExist().withTimeout(5000); - await expect(element(by.id('selected-user-rocket.cat'))).toExist(); + await waitFor(element(by.id('selected-user-rocket.cat'))).toBeVisible().withTimeout(10000); await element(by.id('selected-user-rocket.cat')).tap(); - await waitFor(element(by.id('selected-user-rocket.cat'))).toBeNotVisible().withTimeout(5000); - await expect(element(by.id('selected-user-rocket.cat'))).toBeNotVisible(); + await waitFor(element(by.id('selected-user-rocket.cat'))).toBeNotVisible().withTimeout(10000); await element(by.id('select-users-view-item-rocket.cat')).tap(); - await waitFor(element(by.id('selected-user-rocket.cat'))).toExist().withTimeout(5000); + await waitFor(element(by.id('selected-user-rocket.cat'))).toBeVisible().withTimeout(10000); }); it('should navigate to create channel view', async() => { await element(by.id('selected-users-view-submit')).tap(); - await waitFor(element(by.id('create-channel-view'))).toExist().withTimeout(5000); - await expect(element(by.id('create-channel-view'))).toExist(); + await waitFor(element(by.id('create-channel-view'))).toExist().withTimeout(10000); }); }) describe('Create Channel', async() => { describe('Render', async() => { it('should render all fields', async() => { - await expect(element(by.id('create-channel-name'))).toExist(); - await expect(element(by.id('create-channel-type'))).toExist(); - await expect(element(by.id('create-channel-readonly'))).toExist(); - await expect(element(by.id('create-channel-broadcast'))).toExist(); + await expect(element(by.id('create-channel-name'))).toBeVisible(); + await expect(element(by.id('create-channel-type'))).toBeVisible(); + await expect(element(by.id('create-channel-readonly'))).toBeVisible(); + await expect(element(by.id('create-channel-broadcast'))).toBeVisible(); }) }) @@ -108,61 +103,51 @@ describe('Create room screen', () => { const room = `public${ data.random }`; await element(by.id('create-channel-name')).replaceText(room); await element(by.id('create-channel-type')).tap(); - await sleep(1000); await element(by.id('create-channel-submit')).tap(); await waitFor(element(by.id('room-view'))).toExist().withTimeout(60000); await expect(element(by.id('room-view'))).toExist(); await waitFor(element(by.id(`room-view-title-${ room }`))).toExist().withTimeout(60000); await expect(element(by.id(`room-view-title-${ room }`))).toExist(); await tapBack(); - await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(2000); + await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(10000); await waitFor(element(by.id(`rooms-list-view-item-${ room }`))).toExist().withTimeout(60000); await expect(element(by.id(`rooms-list-view-item-${ room }`))).toExist(); }); it('should create private room', async() => { const room = `private${ data.random }`; - await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(2000); - // await device.launchApp({ newInstance: true }); - await sleep(1000); + await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(5000); await element(by.id('rooms-list-view-create-channel')).tap(); - await waitFor(element(by.id('new-message-view'))).toExist().withTimeout(2000); - await sleep(1000); + await waitFor(element(by.id('new-message-view'))).toExist().withTimeout(5000); await element(by.id('new-message-view-create-channel')).tap(); - await waitFor(element(by.id('select-users-view'))).toExist().withTimeout(2000); - await sleep(1000); + await waitFor(element(by.id('select-users-view'))).toExist().withTimeout(5000); await element(by.id('select-users-view-item-rocket.cat')).tap(); await waitFor(element(by.id('selected-user-rocket.cat'))).toExist().withTimeout(5000); await element(by.id('selected-users-view-submit')).tap(); await waitFor(element(by.id('create-channel-view'))).toExist().withTimeout(5000); await element(by.id('create-channel-name')).replaceText(room); - await sleep(1000); await element(by.id('create-channel-submit')).tap(); await waitFor(element(by.id('room-view'))).toExist().withTimeout(60000); await expect(element(by.id('room-view'))).toExist(); await waitFor(element(by.id(`room-view-title-${ room }`))).toExist().withTimeout(60000); await expect(element(by.id(`room-view-title-${ room }`))).toExist(); await tapBack(); - await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(2000); + await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(5000); await waitFor(element(by.id(`rooms-list-view-item-${ room }`))).toExist().withTimeout(60000); await expect(element(by.id(`rooms-list-view-item-${ room }`))).toExist(); }); it('should create empty room', async() => { const room = `empty${ data.random }`; - await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(2000); + await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(10000); // await device.launchApp({ newInstance: true }); - await sleep(1000); await element(by.id('rooms-list-view-create-channel')).tap(); - await waitFor(element(by.id('new-message-view'))).toExist().withTimeout(2000); - await sleep(1000); + await waitFor(element(by.id('new-message-view'))).toExist().withTimeout(5000); await element(by.id('new-message-view-create-channel')).tap(); - await waitFor(element(by.id('select-users-view'))).toExist().withTimeout(2000); - await sleep(1000); + await waitFor(element(by.id('select-users-view'))).toExist().withTimeout(5000); await element(by.id('selected-users-view-submit')).tap(); - await waitFor(element(by.id('create-channel-view'))).toExist().withTimeout(5000); + await waitFor(element(by.id('create-channel-view'))).toExist().withTimeout(10000); await element(by.id('create-channel-name')).replaceText(room); - await sleep(1000); await element(by.id('create-channel-submit')).tap(); await waitFor(element(by.id('room-view'))).toExist().withTimeout(60000); await expect(element(by.id('room-view'))).toExist(); diff --git a/e2e/tests/room/02-room.spec.js b/e2e/tests/room/02-room.spec.js index 86fdfc21f..00d5d434d 100644 --- a/e2e/tests/room/02-room.spec.js +++ b/e2e/tests/room/02-room.spec.js @@ -2,27 +2,29 @@ const { device, expect, element, by, waitFor } = require('detox'); const data = require('../../data'); -const { mockMessage, tapBack, sleep, searchRoom } = require('../../helpers/app'); +const { navigateToLogin, login, mockMessage, tapBack, sleep, searchRoom, starMessage, pinMessage, dismissReviewNag, tryTapping } = require('../../helpers/app'); -async function navigateToRoom() { - await searchRoom(`private${ data.random }`); - await waitFor(element(by.id(`rooms-list-view-item-private${ data.random }`))).toExist().withTimeout(60000); - await element(by.id(`rooms-list-view-item-private${ data.random }`)).tap(); +async function navigateToRoom(roomName) { + await device.launchApp({ permissions: { notifications: 'YES' }, delete: true }); + await navigateToLogin(); + await login(data.users.regular.username, data.users.regular.password); + await searchRoom(`${ roomName }`); + await waitFor(element(by.id(`rooms-list-view-item-${ roomName }`))).toExist().withTimeout(60000); + await element(by.id(`rooms-list-view-item-${ roomName }`)).tap(); await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(5000); } describe('Room screen', () => { - const mainRoom = `private${ data.random }`; + const mainRoom = data.groups.private.name; before(async() => { - await navigateToRoom(); + await navigateToRoom(mainRoom); }); describe('Render', async() => { it('should have room screen', async() => { await expect(element(by.id('room-view'))).toExist(); await waitFor(element(by.id(`room-view-title-${ mainRoom }`))).toExist().withTimeout(5000); - await expect(element(by.id(`room-view-title-${ mainRoom }`))).toExist(); }); // Render - Header @@ -69,22 +71,15 @@ describe('Room screen', () => { await expect(element(by.label(`${ data.random }message`)).atIndex(0)).toExist(); }); - it('should ask for review', async() => { - await waitFor(element(by.text('Are you enjoying this app?'))).toExist().withTimeout(60000); - await expect(element(by.text('Are you enjoying this app?')).atIndex(0)).toExist(); - await element(by.label('No').and(by.type('_UIAlertControllerActionView'))).tap(); // Tap `no` on ask for review alert - }) it('should show/hide emoji keyboard', async () => { if (device.getPlatform() === 'android') { await element(by.id('messagebox-open-emoji')).tap(); await waitFor(element(by.id('messagebox-keyboard-emoji'))).toExist().withTimeout(10000); - await expect(element(by.id('messagebox-keyboard-emoji'))).toExist(); await expect(element(by.id('messagebox-close-emoji'))).toExist(); await expect(element(by.id('messagebox-open-emoji'))).toBeNotVisible(); await element(by.id('messagebox-close-emoji')).tap(); await waitFor(element(by.id('messagebox-keyboard-emoji'))).toBeNotVisible().withTimeout(10000); - await expect(element(by.id('messagebox-keyboard-emoji'))).toBeNotVisible(); await expect(element(by.id('messagebox-close-emoji'))).toBeNotVisible(); await expect(element(by.id('messagebox-open-emoji'))).toExist(); } @@ -94,10 +89,8 @@ describe('Room screen', () => { await element(by.id('messagebox-input')).tap(); await element(by.id('messagebox-input')).typeText(':joy'); await waitFor(element(by.id('messagebox-container'))).toExist().withTimeout(10000); - await expect(element(by.id('messagebox-container'))).toExist(); await element(by.id('messagebox-input')).clearText(); await waitFor(element(by.id('messagebox-container'))).toBeNotVisible().withTimeout(10000); - await expect(element(by.id('messagebox-container'))).toBeNotVisible(); }); it('should show and tap on emoji autocomplete', async() => { @@ -105,8 +98,6 @@ describe('Room screen', () => { await element(by.id('messagebox-input')).replaceText(':'); await element(by.id('messagebox-input')).typeText('joy'); // workaround for number keyboard await waitFor(element(by.id('messagebox-container'))).toExist().withTimeout(10000); - await expect(element(by.id('messagebox-container'))).toExist(); - await sleep(1000); await element(by.id('mention-item-joy')).tap(); await expect(element(by.id('messagebox-input'))).toHaveText(':joy: '); await element(by.id('messagebox-input')).clearText(); @@ -116,25 +107,22 @@ describe('Room screen', () => { const username = data.users.regular.username await element(by.id('messagebox-input')).tap(); await element(by.id('messagebox-input')).typeText(`@${ username }`); - await waitFor(element(by.id('messagebox-container'))).toExist().withTimeout(60000); - await expect(element(by.id('messagebox-container'))).toExist(); - await sleep(1000); - await element(by.id(`mention-item-${ username }`)).tap(); + await waitFor(element(by.id('messagebox-container'))).toExist().withTimeout(4000); + await waitFor(element(by.id(`mention-item-${ username }`))).toBeVisible().withTimeout(4000) + await tryTapping(element(by.id(`mention-item-${ username }`)), 2000, true); await expect(element(by.id('messagebox-input'))).toHaveText(`@${ username } `); - await element(by.id('messagebox-input')).tap(); + await tryTapping(element(by.id('messagebox-input')), 2000) await element(by.id('messagebox-input')).typeText(`${ data.random }mention`); await element(by.id('messagebox-send-message')).tap(); // await waitFor(element(by.label(`@${ data.user } ${ data.random }mention`)).atIndex(0)).toExist().withTimeout(60000); - await sleep(2000); }); it('should show and tap on room autocomplete', async() => { await element(by.id('messagebox-input')).tap(); await element(by.id('messagebox-input')).typeText('#general'); - await waitFor(element(by.id('messagebox-container'))).toExist().withTimeout(60000); - await expect(element(by.id('messagebox-container'))).toExist(); - await sleep(1000); - await element(by.id('mention-item-general')).tap(); + //await waitFor(element(by.id('messagebox-container'))).toExist().withTimeout(4000); + await waitFor(element(by.id('mention-item-general'))).toBeVisible().withTimeout(4000); + await tryTapping(element(by.id('mention-item-general')), 2000, true) await expect(element(by.id('messagebox-input'))).toHaveText('#general '); await element(by.id('messagebox-input')).clearText(); }); @@ -147,7 +135,6 @@ describe('Room screen', () => { await expect(element(by.id('action-sheet-handle'))).toBeVisible(); await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5); await element(by.label('Permalink')).tap(); - await sleep(1000); // TODO: test clipboard }); @@ -158,28 +145,20 @@ describe('Room screen', () => { await expect(element(by.id('action-sheet-handle'))).toBeVisible(); await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5); await element(by.label('Copy')).tap(); - await sleep(1000); // TODO: test clipboard }); it('should star message', async() => { - await element(by.label(`${ data.random }message`)).atIndex(0).longPress(); - await expect(element(by.id('action-sheet'))).toExist(); - await expect(element(by.id('action-sheet-handle'))).toBeVisible(); - await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5); - await element(by.label('Star')).tap(); - await sleep(1000); - await waitFor(element(by.id('action-sheet'))).toNotExist().withTimeout(5000); + await starMessage('message') + await sleep(1000) //https://github.com/RocketChat/Rocket.Chat.ReactNative/issues/2324 await element(by.label(`${ data.random }message`)).atIndex(0).longPress(); await expect(element(by.id('action-sheet'))).toExist(); await expect(element(by.id('action-sheet-handle'))).toBeVisible(); await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5); await waitFor(element(by.label('Unstar'))).toBeVisible().withTimeout(2000); - await expect(element(by.label('Unstar'))).toBeVisible(); await element(by.id('action-sheet-backdrop')).tap(); - await sleep(1000); }); it('should react to message', async() => { @@ -189,14 +168,10 @@ describe('Room screen', () => { await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5); await element(by.id('add-reaction')).tap(); await waitFor(element(by.id('reaction-picker'))).toBeVisible().withTimeout(2000); - await expect(element(by.id('reaction-picker'))).toBeVisible(); await element(by.id('reaction-picker-😃')).tap(); await waitFor(element(by.id('reaction-picker-grinning'))).toExist().withTimeout(2000); - await expect(element(by.id('reaction-picker-grinning'))).toExist(); await element(by.id('reaction-picker-grinning')).tap(); await waitFor(element(by.id('message-reaction-:grinning:'))).toExist().withTimeout(60000); - await expect(element(by.id('message-reaction-:grinning:'))).toExist(); - await sleep(1000); }); it('should react to message with frequently used emoji', async() => { @@ -205,30 +180,27 @@ describe('Room screen', () => { await expect(element(by.id('action-sheet-handle'))).toBeVisible(); await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5); await waitFor(element(by.id('message-actions-emoji-+1'))).toBeVisible().withTimeout(2000); - await expect(element(by.id('message-actions-emoji-+1'))).toBeVisible(); await element(by.id('message-actions-emoji-+1')).tap(); await waitFor(element(by.id('message-reaction-:+1:'))).toBeVisible().withTimeout(60000); - await expect(element(by.id('message-reaction-:+1:'))).toBeVisible(); - await sleep(1000); }); it('should show reaction picker on add reaction button pressed and have frequently used emoji', async() => { await element(by.id('message-add-reaction')).tap(); await waitFor(element(by.id('reaction-picker'))).toExist().withTimeout(2000); - await expect(element(by.id('reaction-picker'))).toExist(); await waitFor(element(by.id('reaction-picker-grinning'))).toExist().withTimeout(2000); - await expect(element(by.id('reaction-picker-grinning'))).toExist(); await element(by.id('reaction-picker-😃')).tap(); await waitFor(element(by.id('reaction-picker-grimacing'))).toExist().withTimeout(2000); await element(by.id('reaction-picker-grimacing')).tap(); await waitFor(element(by.id('message-reaction-:grimacing:'))).toExist().withTimeout(60000); - await sleep(1000); }); + + it('should ask for review', async() => { + await dismissReviewNag() //TODO: Create a proper test for this elsewhere. + }) it('should remove reaction', async() => { await element(by.id('message-reaction-:grinning:')).tap(); await waitFor(element(by.id('message-reaction-:grinning:'))).toBeNotVisible().withTimeout(60000); - await expect(element(by.id('message-reaction-:grinning:'))).toBeNotVisible(); }); it('should edit message', async() => { @@ -241,7 +213,6 @@ describe('Room screen', () => { await element(by.id('messagebox-input')).typeText('ed'); await element(by.id('messagebox-send-message')).tap(); await waitFor(element(by.label(`${ data.random }edited (edited)`)).atIndex(0)).toExist().withTimeout(60000); - await expect(element(by.label(`${ data.random }edited (edited)`)).atIndex(0)).toExist(); }); it('should quote message', async() => { @@ -253,46 +224,39 @@ describe('Room screen', () => { await element(by.label('Quote')).tap(); await element(by.id('messagebox-input')).typeText(`${ data.random }quoted`); await element(by.id('messagebox-send-message')).tap(); - await sleep(1000); // TODO: test if quote was sent }); it('should pin message', async() => { - await waitFor(element(by.label(`${ data.random }edited (edited)`)).atIndex(0)).toExist(); - await element(by.label(`${ data.random }edited (edited)`)).atIndex(0).longPress(); - await expect(element(by.id('action-sheet'))).toExist(); - await expect(element(by.id('action-sheet-handle'))).toBeVisible(); - await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5); - await element(by.label('Pin')).tap(); - await waitFor(element(by.id('action-sheet'))).toNotExist().withTimeout(5000); - await sleep(1500); - - await waitFor(element(by.label(`${ data.random }edited (edited)`)).atIndex(0)).toBeVisible(); - await element(by.label(`${ data.random }edited (edited)`)).atIndex(0).longPress(); - await expect(element(by.id('action-sheet'))).toExist(); + await mockMessage('pin') + await pinMessage('pin') + + await waitFor(element(by.label(`${ data.random }pin`)).atIndex(0)).toBeVisible().withTimeout(2000); + await waitFor(element(by.label('Message pinned')).atIndex(0)).toBeVisible().withTimeout(2000); + await element(by.label(`${ data.random }pin`)).atIndex(0).longPress(); + await waitFor(element(by.id('action-sheet'))).toExist().withTimeout(1000); await expect(element(by.id('action-sheet-handle'))).toBeVisible(); await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5); await waitFor(element(by.label('Unpin'))).toBeVisible().withTimeout(2000); - await expect(element(by.label('Unpin'))).toBeVisible(); await element(by.id('action-sheet-backdrop')).tap(); }); it('should delete message', async() => { - await waitFor(element(by.label(`${ data.random }quoted`)).atIndex(0)).toBeVisible(); - await element(by.label(`${ data.random }quoted`)).atIndex(0).longPress(); + await mockMessage('delete') + + await waitFor(element(by.label(`${ data.random }delete`)).atIndex(0)).toBeVisible(); + await element(by.label(`${ data.random }delete`)).atIndex(0).longPress(); await expect(element(by.id('action-sheet'))).toExist(); await expect(element(by.id('action-sheet-handle'))).toBeVisible(); await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5); await element(by.label('Delete')).tap(); const deleteAlertMessage = 'You will not be able to recover this message!'; - await waitFor(element(by.text(deleteAlertMessage)).atIndex(0)).toExist().withTimeout(10000); - await expect(element(by.text(deleteAlertMessage)).atIndex(0)).toExist(); + await waitFor(element(by.text(deleteAlertMessage)).atIndex(0)).toExist().withTimeout(10000); await element(by.text('Delete')).tap(); - await sleep(1000); - await expect(element(by.label(`${ data.random }quoted`)).atIndex(0)).toNotExist(); + await waitFor(element(by.label(`${ data.random }delete`)).atIndex(0)).toNotExist().withTimeout(2000); }); }); @@ -317,7 +281,6 @@ describe('Room screen', () => { await waitFor(element(by.id(`room-view-title-${ thread }`))).toExist().withTimeout(5000); await expect(element(by.id(`room-view-title-${ thread }`))).toExist(); await tapBack(); - await sleep(1000); }); it('should toggle follow thread', async() => { @@ -332,10 +295,13 @@ describe('Room screen', () => { await waitFor(element(by.id('room-view-header-unfollow'))).toExist().withTimeout(60000); await expect(element(by.id('room-view-header-unfollow'))).toExist(); await tapBack(); - await sleep(1000); }); it('should navigate to thread from thread name', async() => { + await waitFor(element(by.id('room-view-header-actions').and(by.label(` ${ mainRoom }`)))).toBeVisible().withTimeout(2000); + await waitFor(element(by.id('room-view-header-actions').and(by.label(` ${ data.random }thread`)))).toBeNotVisible().withTimeout(2000); + await sleep(500) //TODO: Find a better way to wait for the animation to finish and the messagebox-input to be available and usable :( + await mockMessage('dummymessagebetweenthethread'); await element(by.label(thread)).atIndex(0).longPress(); await expect(element(by.id('action-sheet'))).toExist(); @@ -352,10 +318,10 @@ describe('Room screen', () => { await waitFor(element(by.id(`room-view-title-${ thread }`))).toExist().withTimeout(5000); await expect(element(by.id(`room-view-title-${ thread }`))).toExist(); await tapBack(); - await sleep(1000); }); it('should navigate to thread from threads view', async() => { + await waitFor(element(by.id('room-view-header-threads'))).toExist().withTimeout(1000); await element(by.id('room-view-header-threads')).tap(); await waitFor(element(by.id('thread-messages-view'))).toExist().withTimeout(5000); await expect(element(by.id('thread-messages-view'))).toExist(); diff --git a/e2e/tests/room/03-roomactions.spec.js b/e2e/tests/room/03-roomactions.spec.js index dd5c8defd..43ff025ef 100644 --- a/e2e/tests/room/03-roomactions.spec.js +++ b/e2e/tests/room/03-roomactions.spec.js @@ -2,7 +2,7 @@ const { device, expect, element, by, waitFor } = require('detox'); const data = require('../../data'); -const { tapBack, sleep, searchRoom } = require('../../helpers/app'); +const { navigateToLogin, login, tapBack, sleep, searchRoom, mockMessage, starMessage, pinMessage } = require('../../helpers/app'); const scrollDown = 200; @@ -11,13 +11,12 @@ async function navigateToRoomActions(type) { if (type === 'd') { room = 'rocket.cat'; } else { - room = `private${ data.random }`; + room = data.groups.private.name; } await searchRoom(room); await waitFor(element(by.id(`rooms-list-view-item-${ room }`))).toExist().withTimeout(60000); await element(by.id(`rooms-list-view-item-${ room }`)).tap(); await waitFor(element(by.id('room-view'))).toExist().withTimeout(2000); - await sleep(1000); await element(by.id('room-view-header-actions')).tap(); await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000); } @@ -25,7 +24,6 @@ async function navigateToRoomActions(type) { async function backToActions() { await tapBack(); await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(2000); - await expect(element(by.id('room-actions-view'))).toExist(); } async function backToRoomsList() { @@ -36,10 +34,16 @@ async function backToRoomsList() { } describe('Room actions screen', () => { + + before(async() => { + await device.launchApp({ permissions: { notifications: 'YES' }, delete: true }); + await navigateToLogin(); + await login(data.users.regular.username, data.users.regular.password); + }); + describe('Render', async() => { describe('Direct', async() => { before(async() => { - await device.launchApp({ newInstance: true }); await navigateToRoomActions('d'); }); @@ -197,65 +201,89 @@ describe('Room actions screen', () => { it('should show mentioned messages', async() => { await element(by.id('room-actions-mentioned')).tap(); await waitFor(element(by.id('mentioned-messages-view'))).toExist().withTimeout(2000); - await expect(element(by.id('mentioned-messages-view'))).toExist(); // await waitFor(element(by.text(` ${ data.random }mention`))).toExist().withTimeout(60000); - // await expect(element(by.text(` ${ data.random }mention`))).toExist(); await backToActions(); }); it('should show starred message and unstar it', async() => { + + //Go back to room and send a message + await tapBack(); + await mockMessage('messageToStar'); + + //Star the message + await starMessage('messageToStar') + + //Back into Room Actions + await element(by.id('room-view-header-actions')).tap(); + await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000); + + //Go to starred messages await element(by.id('room-actions-starred')).tap(); await waitFor(element(by.id('starred-messages-view'))).toExist().withTimeout(2000); - await sleep(1000); - await waitFor(element(by.label(`${ data.random }message`).withAncestor(by.id('starred-messages-view')))).toBeVisible().withTimeout(60000); - await expect(element(by.label(`${ data.random }message`).withAncestor(by.id('starred-messages-view')))).toBeVisible(); - await element(by.label(`${ data.random }message`).withAncestor(by.id('starred-messages-view'))).longPress(); - + await waitFor(element(by.label(`${ data.random }messageToStar`).withAncestor(by.id('starred-messages-view')))).toBeVisible().withTimeout(60000); + + //Unstar message + await element(by.label(`${ data.random }messageToStar`).withAncestor(by.id('starred-messages-view'))).longPress(); await expect(element(by.id('action-sheet'))).toExist(); await expect(element(by.id('action-sheet-handle'))).toBeVisible(); await element(by.label('Unstar')).tap(); - await waitFor(element(by.label(`${ data.random }message`).withAncestor(by.id('starred-messages-view')))).toBeNotVisible().withTimeout(60000); - await expect(element(by.label(`${ data.random }message`).withAncestor(by.id('starred-messages-view')))).toBeNotVisible(); + await waitFor(element(by.label(`${ data.random }messageToStar`).withAncestor(by.id('starred-messages-view')))).toBeNotVisible().withTimeout(60000); await backToActions(); }); it('should show pinned message and unpin it', async() => { + + //Go back to room and send a message + await tapBack(); + await mockMessage('messageToPin'); + + //Pin the message + await pinMessage('messageToPin') + + //Back into Room Actions + await element(by.id('room-view-header-actions')).tap(); + await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000); + await waitFor(element(by.id('room-actions-pinned'))).toExist(); await element(by.id('room-actions-pinned')).tap(); await waitFor(element(by.id('pinned-messages-view'))).toExist().withTimeout(2000); - await sleep(1000); - await waitFor(element(by.label(`${ data.random }edited (edited)`).withAncestor(by.id('pinned-messages-view')))).toBeVisible().withTimeout(60000); - await expect(element(by.label(`${ data.random }edited (edited)`).withAncestor(by.id('pinned-messages-view')))).toBeVisible(); - await element(by.label(`${ data.random }edited (edited)`).withAncestor(by.id('pinned-messages-view'))).longPress(); + await waitFor(element(by.label(`${ data.random }messageToPin`).withAncestor(by.id('pinned-messages-view')))).toBeVisible().withTimeout(60000); + await element(by.label(`${ data.random }messageToPin`).withAncestor(by.id('pinned-messages-view'))).longPress(); await expect(element(by.id('action-sheet'))).toExist(); await expect(element(by.id('action-sheet-handle'))).toBeVisible(); await element(by.label('Unpin')).tap(); - await waitFor(element(by.label(`${ data.random }edited (edited)`).withAncestor(by.id('pinned-messages-view')))).toBeNotVisible().withTimeout(60000); - await expect(element(by.label(`${ data.random }edited (edited)`).withAncestor(by.id('pinned-messages-view')))).toBeNotVisible(); + await waitFor(element(by.label(`${ data.random }messageToPin`).withAncestor(by.id('pinned-messages-view')))).toBeNotVisible().withTimeout(60000); await backToActions(); }); it('should search and find a message', async() => { + + //Go back to room and send a message + await tapBack(); + await mockMessage('messageToFind'); + + //Back into Room Actions + await element(by.id('room-view-header-actions')).tap(); + await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000); + await element(by.id('room-actions-search')).tap(); await waitFor(element(by.id('search-messages-view'))).toExist().withTimeout(2000); await expect(element(by.id('search-message-view-input'))).toExist(); - await element(by.id('search-message-view-input')).replaceText(`/${ data.random }message/`); - await waitFor(element(by.label(`${ data.random }message`).withAncestor(by.id('search-messages-view')))).toExist().withTimeout(60000); - await expect(element(by.label(`${ data.random }message`).withAncestor(by.id('search-messages-view')))).toExist(); + await element(by.id('search-message-view-input')).replaceText(`/${ data.random }messageToFind/`); + await waitFor(element(by.label(`${ data.random }messageToFind`).withAncestor(by.id('search-messages-view')))).toExist().withTimeout(60000); await backToActions(); }); }); describe('Notification', async() => { it('should navigate to notification preference view', async() => { - await waitFor(element(by.id('room-actions-notifications'))).toExist(); - await expect(element(by.id('room-actions-notifications'))).toExist(); + await waitFor(element(by.id('room-actions-notifications'))).toExist().withTimeout(2000); await element(by.id('room-actions-notifications')).tap(); await waitFor(element(by.id('notification-preference-view'))).toExist().withTimeout(2000); - await expect(element(by.id('notification-preference-view'))).toExist(); }); it('should have receive notification option', async() => { @@ -271,30 +299,25 @@ describe('Room actions screen', () => { }); it('should have push notification option', async() => { - await waitFor(element(by.id('notification-preference-view-push-notification'))).toExist(); - await expect(element(by.id('notification-preference-view-push-notification'))).toExist(); + await waitFor(element(by.id('notification-preference-view-push-notification'))).toExist().withTimeout(4000); }); it('should have notification audio option', async() => { - await waitFor(element(by.id('notification-preference-view-audio'))).toExist(); - await expect(element(by.id('notification-preference-view-audio'))).toExist(); + await waitFor(element(by.id('notification-preference-view-audio'))).toExist().withTimeout(4000); }); it('should have notification sound option', async() => { // Ugly hack to scroll on detox await element(by.type('UIScrollView')).atIndex(1).scrollTo('bottom'); - await waitFor(element(by.id('notification-preference-view-sound'))).toExist(); - await expect(element(by.id('notification-preference-view-sound'))).toExist(); + await waitFor(element(by.id('notification-preference-view-sound'))).toExist().withTimeout(4000); }); it('should have notification duration option', async() => { - await waitFor(element(by.id('notification-preference-view-notification-duration'))).toExist(); - await expect(element(by.id('notification-preference-view-notification-duration'))).toExist(); + await waitFor(element(by.id('notification-preference-view-notification-duration'))).toExist().withTimeout(4000); }); it('should have email alert option', async() => { - await waitFor(element(by.id('notification-preference-view-email-alert'))).toExist(); - await expect(element(by.id('notification-preference-view-email-alert'))).toExist(); + await waitFor(element(by.id('notification-preference-view-email-alert'))).toExist().withTimeout(4000); }); after(async() => { @@ -309,34 +332,29 @@ describe('Room actions screen', () => { const user = data.users.alternate it('should tap on leave channel and raise alert', async() => { - await waitFor(element(by.id('room-actions-leave-channel'))).toExist(); - await expect(element(by.id('room-actions-leave-channel'))).toExist(); + await waitFor(element(by.id('room-actions-leave-channel'))).toExist().withTimeout(2000); await element(by.id('room-actions-leave-channel')).tap(); await waitFor(element(by.text('Yes, leave it!'))).toExist().withTimeout(2000); - await expect(element(by.text('Yes, leave it!'))).toExist(); await element(by.text('Yes, leave it!')).tap(); - await waitFor(element(by.text('You are the last owner. Please set new owner before leaving the room.'))).toExist().withTimeout(60000); - await expect(element(by.text('You are the last owner. Please set new owner before leaving the room.'))).toExist(); + await waitFor(element(by.text('You are the last owner. Please set new owner before leaving the room.'))).toExist().withTimeout(8000); await element(by.text('OK')).tap(); await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(2000); }); it('should add user to the room', async() => { - await waitFor(element(by.id('room-actions-add-user'))).toExist(); + await waitFor(element(by.id('room-actions-add-user'))).toExist().withTimeout(4000); await element(by.id('room-actions-add-user')).tap(); + await waitFor(element(by.id('select-users-view-search'))).toExist().withTimeout(4000); await element(by.id('select-users-view-search')).tap(); await element(by.id('select-users-view-search')).replaceText(user.username); - await waitFor(element(by.id(`select-users-view-item-${ user.username }`))).toExist().withTimeout(60000); - await expect(element(by.id(`select-users-view-item-${ user.username }`))).toExist(); + await waitFor(element(by.id(`select-users-view-item-${ user.username }`))).toExist().withTimeout(10000); await element(by.id(`select-users-view-item-${ user.username }`)).tap(); await waitFor(element(by.id(`selected-user-${ user.username }`))).toExist().withTimeout(5000); - await expect(element(by.id(`selected-user-${ user.username }`))).toExist(); await element(by.id('selected-users-view-submit')).tap(); await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(2000); await element(by.id('room-actions-members')).tap(); await element(by.id('room-members-view-toggle-status')).tap(); await waitFor(element(by.id(`room-members-view-item-${ user.username }`))).toExist().withTimeout(60000); - await expect(element(by.id(`room-members-view-item-${ user.username }`))).toExist(); await backToActions(1); }); @@ -344,26 +362,20 @@ describe('Room actions screen', () => { before(async() => { await element(by.id('room-actions-members')).tap(); await waitFor(element(by.id('room-members-view'))).toExist().withTimeout(2000); - await expect(element(by.id('room-members-view'))).toExist(); }); it('should show all users', async() => { - await sleep(1000); await element(by.id('room-members-view-toggle-status')).tap(); await waitFor(element(by.id(`room-members-view-item-${ user.username }`))).toExist().withTimeout(60000); - await expect(element(by.id(`room-members-view-item-${ user.username }`))).toExist(); }); it('should filter user', async() => { await waitFor(element(by.id(`room-members-view-item-${ user.username }`))).toExist().withTimeout(60000); - await expect(element(by.id(`room-members-view-item-${ user.username }`))).toExist(); await element(by.id('room-members-view-search')).replaceText('rocket'); await waitFor(element(by.id(`room-members-view-item-${ user.username }`))).toBeNotVisible().withTimeout(60000); - await expect(element(by.id(`room-members-view-item-${ user.username }`))).toBeNotVisible(); await element(by.id('room-members-view-search')).tap(); await element(by.id('room-members-view-search')).clearText(''); await waitFor(element(by.id(`room-members-view-item-${ user.username }`))).toExist().withTimeout(60000); - await expect(element(by.id(`room-members-view-item-${ user.username }`))).toExist(); }); // FIXME: mute/unmute isn't working @@ -391,9 +403,7 @@ describe('Room actions screen', () => { await waitFor(element(by.id(`room-members-view-item-${ user.username }`))).toExist().withTimeout(5000); await element(by.id(`room-members-view-item-${ user.username }`)).tap(); await waitFor(element(by.id('room-view'))).toExist().withTimeout(60000); - await expect(element(by.id('room-view'))).toExist(); await waitFor(element(by.id(`room-view-title-${ user.username }`))).toExist().withTimeout(60000); - await expect(element(by.id(`room-view-title-${ user.username }`))).toExist(); await tapBack(); await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(2000); }); @@ -407,13 +417,10 @@ describe('Room actions screen', () => { it('should block/unblock user', async() => { await waitFor(element(by.id('room-actions-block-user'))).toExist(); - await sleep(1000); await element(by.id('room-actions-block-user')).tap(); await waitFor(element(by.label('Unblock user'))).toExist().withTimeout(60000); - await expect(element(by.label('Unblock user'))).toExist(); await element(by.id('room-actions-block-user')).tap(); await waitFor(element(by.label('Block user'))).toExist().withTimeout(60000); - await expect(element(by.label('Block user'))).toExist(); }); }); }); diff --git a/e2e/tests/room/04-roominfo.spec.js b/e2e/tests/room/04-roominfo.spec.js index 35a45441b..9382f16cf 100644 --- a/e2e/tests/room/04-roominfo.spec.js +++ b/e2e/tests/room/04-roominfo.spec.js @@ -2,23 +2,23 @@ const { device, expect, element, by, waitFor } = require('detox'); const data = require('../../data'); -const { tapBack, sleep, searchRoom } = require('../../helpers/app'); +const { navigateToLogin, login, tapBack, sleep, searchRoom } = require('../../helpers/app'); + +const privateRoomName = data.groups.private.name async function navigateToRoomInfo(type) { let room; if (type === 'd') { room = 'rocket.cat'; } else { - room = `private${ data.random }`; + room = privateRoomName; } await searchRoom(room); await waitFor(element(by.id(`rooms-list-view-item-${ room }`))).toExist().withTimeout(60000); await element(by.id(`rooms-list-view-item-${ room }`)).tap(); await waitFor(element(by.id('room-view'))).toExist().withTimeout(2000); - await sleep(1000); await element(by.id('room-view-header-actions')).tap(); await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000); - await sleep(1000); await element(by.id('room-actions-info')).tap(); await waitFor(element(by.id('room-info-view'))).toExist().withTimeout(2000); } @@ -28,13 +28,19 @@ async function waitForToast() { // await expect(element(by.id('toast'))).toExist(); // await waitFor(element(by.id('toast'))).toBeNotVisible().withTimeout(10000); // await expect(element(by.id('toast'))).toBeNotVisible(); - await sleep(5000); + await sleep(1); } describe('Room info screen', () => { + + before(async() => { + await device.launchApp({ permissions: { notifications: 'YES' }, delete: true }); + await navigateToLogin(); + await login(data.users.regular.username, data.users.regular.password); + }); + describe('Direct', async() => { before(async() => { - await device.launchApp({ newInstance: true }); await navigateToRoomInfo('d'); }); @@ -42,11 +48,16 @@ describe('Room info screen', () => { await expect(element(by.id('room-info-view'))).toExist(); await expect(element(by.id('room-info-view-name'))).toExist(); }); + + after(async() => { + await tapBack() + await tapBack() + await tapBack() + }) }); describe('Channel/Group', async() => { before(async() => { - await device.launchApp({ newInstance: true }); await navigateToRoomInfo('c'); }); @@ -78,7 +89,6 @@ describe('Room info screen', () => { describe('Render Edit', async() => { before(async() => { - await sleep(1000); await waitFor(element(by.id('room-info-view-edit-button'))).toExist().withTimeout(10000); await element(by.id('room-info-view-edit-button')).tap(); await waitFor(element(by.id('room-info-edit-view'))).toExist().withTimeout(2000); @@ -141,7 +151,6 @@ describe('Room info screen', () => { }); describe('Usage', async() => { - const room = `private${ data.random }`; // it('should enter "invalid name" and get error', async() => { // await element(by.type('UIScrollView')).atIndex(1).swipe('down'); // await element(by.id('room-info-edit-view-name')).replaceText('invalid name'); @@ -155,22 +164,17 @@ describe('Room info screen', () => { // }); it('should change room name', async() => { - await element(by.id('room-info-edit-view-name')).replaceText(`${ room }new`); + await element(by.id('room-info-edit-view-name')).replaceText(`${ privateRoomName }new`); await element(by.type('UIScrollView')).atIndex(1).swipe('up'); await element(by.id('room-info-edit-view-submit')).tap(); - await sleep(5000); await tapBack(); await waitFor(element(by.id('room-info-view'))).toExist().withTimeout(2000); - await sleep(1000); - await expect(element(by.id('room-info-view-name'))).toHaveLabel(`${ room }new`); + await expect(element(by.id('room-info-view-name'))).toHaveLabel(`${ privateRoomName }new`); // change name to original await element(by.id('room-info-view-edit-button')).tap(); - await sleep(1000); await waitFor(element(by.id('room-info-edit-view'))).toExist().withTimeout(2000); - await sleep(1000); - await element(by.id('room-info-edit-view-name')).replaceText(`${ room }`); + await element(by.id('room-info-edit-view-name')).replaceText(`${ privateRoomName }`); await element(by.type('UIScrollView')).atIndex(1).swipe('up'); - await sleep(1000); await element(by.id('room-info-edit-view-submit')).tap(); await waitForToast(); await element(by.type('UIScrollView')).atIndex(1).swipe('down'); @@ -184,14 +188,11 @@ describe('Room info screen', () => { await element(by.id('room-info-edit-view-password')).replaceText('abc'); await element(by.type('UIScrollView')).atIndex(1).swipe('up'); await element(by.id('room-info-edit-view-t')).tap(); - await sleep(1000); - await element(by.id('room-info-edit-view-ro')).tap(); - await sleep(1000); + await element(by.id('room-info-edit-view-ro')).longPress(); //https://github.com/facebook/react-native/issues/28032 await element(by.id('room-info-edit-view-react-when-ro')).tap(); - await sleep(1000); await element(by.id('room-info-edit-view-reset')).tap(); // after reset - await expect(element(by.id('room-info-edit-view-name'))).toHaveText(room); + await expect(element(by.id('room-info-edit-view-name'))).toHaveText(privateRoomName); await expect(element(by.id('room-info-edit-view-description'))).toHaveText(''); await expect(element(by.id('room-info-edit-view-topic'))).toHaveText(''); await expect(element(by.id('room-info-edit-view-announcement'))).toHaveText(''); @@ -203,55 +204,45 @@ describe('Room info screen', () => { }); it('should change room description', async() => { - await sleep(1000); await element(by.id('room-info-edit-view-description')).replaceText('new description'); await element(by.type('UIScrollView')).atIndex(1).swipe('up'); await element(by.id('room-info-edit-view-submit')).tap(); await waitForToast(); await tapBack(); await waitFor(element(by.id('room-info-view'))).toExist().withTimeout(2000); - await sleep(1000); await expect(element(by.label('new description').withAncestor(by.id('room-info-view-description')))).toExist(); }); it('should change room topic', async() => { - await sleep(1000); await waitFor(element(by.id('room-info-view-edit-button'))).toExist().withTimeout(10000); await element(by.id('room-info-view-edit-button')).tap(); await waitFor(element(by.id('room-info-edit-view'))).toExist().withTimeout(2000); - await sleep(1000); await element(by.id('room-info-edit-view-topic')).replaceText('new topic'); await element(by.type('UIScrollView')).atIndex(1).swipe('up'); await element(by.id('room-info-edit-view-submit')).tap(); await waitForToast(); await tapBack(); await waitFor(element(by.id('room-info-view'))).toExist().withTimeout(2000); - await sleep(1000); await expect(element(by.label('new topic').withAncestor(by.id('room-info-view-topic')))).toExist(); }); it('should change room announcement', async() => { - await sleep(1000); await waitFor(element(by.id('room-info-view-edit-button'))).toExist().withTimeout(10000); await element(by.id('room-info-view-edit-button')).tap(); await waitFor(element(by.id('room-info-edit-view'))).toExist().withTimeout(2000); - await sleep(1000); await element(by.id('room-info-edit-view-announcement')).replaceText('new announcement'); await element(by.type('UIScrollView')).atIndex(1).swipe('up'); await element(by.id('room-info-edit-view-submit')).tap(); await waitForToast(); await tapBack(); await waitFor(element(by.id('room-info-view'))).toExist().withTimeout(2000); - await sleep(1000); await expect(element(by.label('new announcement').withAncestor(by.id('room-info-view-announcement')))).toExist(); }); it('should change room password', async() => { - await sleep(1000); await waitFor(element(by.id('room-info-view-edit-button'))).toExist().withTimeout(10000); await element(by.id('room-info-view-edit-button')).tap(); await waitFor(element(by.id('room-info-edit-view'))).toExist().withTimeout(2000); - await sleep(1000); await element(by.type('UIScrollView')).atIndex(1).swipe('up'); await element(by.id('room-info-edit-view-password')).replaceText('password'); await element(by.id('room-info-edit-view-submit')).tap(); @@ -259,7 +250,6 @@ describe('Room info screen', () => { }); it('should change room type', async() => { - await sleep(1000); await element(by.type('UIScrollView')).atIndex(1).swipe('up'); await element(by.id('room-info-edit-view-t')).tap(); await element(by.id('room-info-edit-view-submit')).tap(); @@ -282,14 +272,11 @@ describe('Room info screen', () => { // }); it('should archive room', async() => { - await sleep(1000); await element(by.type('UIScrollView')).atIndex(1).swipe('up'); await element(by.id('room-info-edit-view-archive')).tap(); await waitFor(element(by.text('Yes, archive it!'))).toExist().withTimeout(5000); - await expect(element(by.text('Yes, archive it!'))).toExist(); await element(by.text('Yes, archive it!')).tap(); await waitFor(element(by.id('room-info-edit-view-unarchive'))).toExist().withTimeout(60000); - await expect(element(by.id('room-info-edit-view-unarchive'))).toExist(); await expect(element(by.id('room-info-edit-view-archive'))).toBeNotVisible(); // TODO: needs permission to unarchive // await element(by.id('room-info-edit-view-archive')).tap(); @@ -301,16 +288,12 @@ describe('Room info screen', () => { }); it('should delete room', async() => { - await sleep(1000); await element(by.type('UIScrollView')).atIndex(1).swipe('up'); await element(by.id('room-info-edit-view-delete')).tap(); await waitFor(element(by.text('Yes, delete it!'))).toExist().withTimeout(5000); - await expect(element(by.text('Yes, delete it!'))).toExist(); await element(by.text('Yes, delete it!')).tap(); await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(10000); - await sleep(2000); - await waitFor(element(by.id(`rooms-list-view-item-${ room }`))).toBeNotVisible().withTimeout(60000); - await expect(element(by.id(`rooms-list-view-item-${ room }`))).toBeNotVisible(); + await waitFor(element(by.id(`rooms-list-view-item-${ privateRoomName }`))).toBeNotVisible().withTimeout(60000); }); }); }); diff --git a/ios/NotificationService/Info.plist b/ios/NotificationService/Info.plist new file mode 100644 index 000000000..496dfc6ce --- /dev/null +++ b/ios/NotificationService/Info.plist @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>AppGroup</key> + <string>group.ios.chat.rocket</string> + <key>CFBundleDevelopmentRegion</key> + <string>$(DEVELOPMENT_LANGUAGE)</string> + <key>CFBundleDisplayName</key> + <string>NotificationService</string> + <key>CFBundleExecutable</key> + <string>$(EXECUTABLE_NAME)</string> + <key>CFBundleIdentifier</key> + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>$(PRODUCT_NAME)</string> + <key>CFBundlePackageType</key> + <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string> + <key>CFBundleShortVersionString</key> + <string>$(MARKETING_VERSION)</string> + <key>CFBundleVersion</key> + <string>1</string> + <key>NSExtension</key> + <dict> + <key>NSExtensionPointIdentifier</key> + <string>com.apple.usernotifications.service</string> + <key>NSExtensionPrincipalClass</key> + <string>$(PRODUCT_MODULE_NAME).NotificationService</string> + </dict> +</dict> +</plist> diff --git a/ios/NotificationService/NotificationService.entitlements b/ios/NotificationService/NotificationService.entitlements new file mode 100644 index 000000000..f48f06fbc --- /dev/null +++ b/ios/NotificationService/NotificationService.entitlements @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>com.apple.security.application-groups</key> + <array> + <string>group.ios.chat.rocket</string> + </array> +</dict> +</plist> diff --git a/ios/NotificationService/NotificationService.swift b/ios/NotificationService/NotificationService.swift new file mode 100644 index 000000000..bb5352a59 --- /dev/null +++ b/ios/NotificationService/NotificationService.swift @@ -0,0 +1,155 @@ +import CoreLocation +import UserNotifications + +struct PushResponse: Decodable { + let success: Bool + let data: Data + + struct Data: Decodable { + let notification: Notification + + struct Notification: Decodable { + let notId: Int + let title: String + let text: String + let payload: Payload + + struct Payload: Decodable, Encodable { + let host: String + let rid: String? + let type: String? + let sender: Sender? + let messageId: String + let notificationType: String? + let name: String? + let messageType: String? + + struct Sender: Decodable, Encodable { + let _id: String + let username: String + let name: String? + } + } + } + } +} + +class NotificationService: UNNotificationServiceExtension { + + var contentHandler: ((UNNotificationContent) -> Void)? + var bestAttemptContent: UNMutableNotificationContent? + + var retryCount = 0 + var retryTimeout = [1.0, 3.0, 5.0, 10.0] + + override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { + self.contentHandler = contentHandler + bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) + + if let bestAttemptContent = bestAttemptContent { + let ejson = (bestAttemptContent.userInfo["ejson"] as? String ?? "").data(using: .utf8)! + guard let data = try? (JSONDecoder().decode(PushResponse.Data.Notification.Payload.self, from: ejson)) else { + return + } + + let notificationType = data.notificationType ?? "" + + // If the notification have the content at her payload, show it + if notificationType != "message-id-only" { + contentHandler(bestAttemptContent) + return + } + + let suiteName = Bundle.main.object(forInfoDictionaryKey: "AppGroup") as! String + let userDefaults = UserDefaults(suiteName: suiteName) + + var server = data.host + if (server.last == "/") { + server.removeLast() + } + let msgId = data.messageId + + let userId = userDefaults?.string(forKey: "reactnativemeteor_usertoken-\(server)") ?? "" + let token = userDefaults?.string(forKey: "reactnativemeteor_usertoken-\(userId)") ?? "" + + if userId.isEmpty || token.isEmpty { + contentHandler(bestAttemptContent) + return + } + + var urlComponents = URLComponents(string: "\(server)/api/v1/push.get")! + let queryItems = [URLQueryItem(name: "id", value: msgId)] + urlComponents.queryItems = queryItems + + var request = URLRequest(url: urlComponents.url!) + request.httpMethod = "GET" + request.addValue(userId, forHTTPHeaderField: "x-user-id") + request.addValue(token, forHTTPHeaderField: "x-auth-token") + + runRequest(request: request, bestAttemptContent: bestAttemptContent, contentHandler: contentHandler) + } + } + + func runRequest(request: URLRequest, bestAttemptContent: UNMutableNotificationContent, contentHandler: @escaping (UNNotificationContent) -> Void) { + let task = URLSession.shared.dataTask(with: request) {(data, response, error) in + + func retryRequest() { + // if we can try again + if self.retryCount < self.retryTimeout.count { + // Try again after X seconds + DispatchQueue.main.asyncAfter(deadline: .now() + self.retryTimeout[self.retryCount], execute: { + self.runRequest(request: request, bestAttemptContent: bestAttemptContent, contentHandler: contentHandler) + self.retryCount += 1 + }) + } + } + + // If some error happened + if error != nil { + retryRequest() + + // Check if the request did successfully + } else if let response = response as? HTTPURLResponse { + // if it not was successfully + if response.statusCode != 200 { + retryRequest() + + // If the response status is 200 + } else { + // Process data + if let data = data { + // Parse data of response + let push = try? (JSONDecoder().decode(PushResponse.self, from: data)) + if let push = push { + if push.success { + bestAttemptContent.title = push.data.notification.title + bestAttemptContent.body = push.data.notification.text + + let payload = try? (JSONEncoder().encode(push.data.notification.payload)) + if let payload = payload { + bestAttemptContent.userInfo["ejson"] = String(data: payload, encoding: .utf8) ?? "{}" + } + + // Show notification with the content modified + contentHandler(bestAttemptContent) + return + } + } + } + retryRequest() + } + } + } + + task.resume() + } + + override func serviceExtensionTimeWillExpire() { + // Called just before the extension will be terminated by the system. + // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used. + if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent { + contentHandler(bestAttemptContent) + } + } + +} diff --git a/ios/Podfile b/ios/Podfile index 35f65a777..c1eca515e 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -1,143 +1,23 @@ platform :ios, '11.0' +require_relative '../node_modules/react-native/scripts/react_native_pods' require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' require_relative '../node_modules/react-native-unimodules/cocoapods.rb' -def add_flipper_pods!(versions = {}) - versions['Flipper'] ||= '~> 0.33.1' - versions['DoubleConversion'] ||= '1.1.7' - versions['Flipper-Folly'] ||= '~> 2.1' - versions['Flipper-Glog'] ||= '0.3.6' - versions['Flipper-PeerTalk'] ||= '~> 0.0.4' - versions['Flipper-RSocket'] ||= '~> 1.0' - - pod 'FlipperKit', versions['Flipper'], :configuration => 'Debug' - pod 'FlipperKit/FlipperKitLayoutPlugin', versions['Flipper'], :configuration => 'Debug' - pod 'FlipperKit/SKIOSNetworkPlugin', versions['Flipper'], :configuration => 'Debug' - pod 'FlipperKit/FlipperKitUserDefaultsPlugin', versions['Flipper'], :configuration => 'Debug' - pod 'FlipperKit/FlipperKitReactPlugin', versions['Flipper'], :configuration => 'Debug' - - # List all transitive dependencies for FlipperKit pods - # to avoid them being linked in Release builds - pod 'Flipper', versions['Flipper'], :configuration => 'Debug' - pod 'Flipper-DoubleConversion', versions['DoubleConversion'], :configuration => 'Debug' - pod 'Flipper-Folly', versions['Flipper-Folly'], :configuration => 'Debug' - pod 'Flipper-Glog', versions['Flipper-Glog'], :configuration => 'Debug' - pod 'Flipper-PeerTalk', versions['Flipper-PeerTalk'], :configuration => 'Debug' - pod 'Flipper-RSocket', versions['Flipper-RSocket'], :configuration => 'Debug' - pod 'FlipperKit/Core', versions['Flipper'], :configuration => 'Debug' - pod 'FlipperKit/CppBridge', versions['Flipper'], :configuration => 'Debug' - pod 'FlipperKit/FBCxxFollyDynamicConvert', versions['Flipper'], :configuration => 'Debug' - pod 'FlipperKit/FBDefines', versions['Flipper'], :configuration => 'Debug' - pod 'FlipperKit/FKPortForwarding', versions['Flipper'], :configuration => 'Debug' - pod 'FlipperKit/FlipperKitHighlightOverlay', versions['Flipper'], :configuration => 'Debug' - pod 'FlipperKit/FlipperKitLayoutTextSearchable', versions['Flipper'], :configuration => 'Debug' - pod 'FlipperKit/FlipperKitNetworkPlugin', versions['Flipper'], :configuration => 'Debug' -end - -# Post Install processing for Flipper -def flipper_post_install(installer) - installer.pods_project.targets.each do |target| - if target.name == 'YogaKit' - target.build_configurations.each do |config| - config.build_settings['SWIFT_VERSION'] = '4.1' - end - end - end - file_name = Dir.glob("*.xcodeproj")[0] - app_project = Xcodeproj::Project.open(file_name) - app_project.native_targets.each do |target| - target.build_configurations.each do |config| - cflags = config.build_settings['OTHER_CFLAGS'] || '$(inherited) ' - unless cflags.include? '-DFB_SONARKIT_ENABLED=1' - puts 'Adding -DFB_SONARKIT_ENABLED=1 in OTHER_CFLAGS...' - cflags << '-DFB_SONARKIT_ENABLED=1' - end - config.build_settings['OTHER_CFLAGS'] = cflags - end - app_project.save - end - installer.pods_project.save +def all_pods + config = use_native_modules! + use_unimodules! + use_react_native!(:path => config["reactNativePath"]) + use_flipper! end target 'RocketChatRN' do - pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector" - pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec" - pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired" - pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety" - pod 'React', :path => '../node_modules/react-native/' - pod 'React-Core', :path => '../node_modules/react-native/' - pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules' - pod 'React-Core/DevSupport', :path => '../node_modules/react-native/' - pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS' - pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation' - pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob' - pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image' - pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS' - pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network' - pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings' - pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text' - pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration' - pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/' - - pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact' - pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi' - pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor' - pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector' - pod 'ReactCommon/callinvoker', :path => "../node_modules/react-native/ReactCommon" - pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon" - pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga', :modular_headers => true - - pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec' - pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec' - pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec' - - use_native_modules! - use_unimodules! + all_pods end target 'ShareRocketChatRN' do - pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector" - pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec" - pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired" - pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety" - pod 'React', :path => '../node_modules/react-native/' - pod 'React-Core', :path => '../node_modules/react-native/' - pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules' - pod 'React-Core/DevSupport', :path => '../node_modules/react-native/' - pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS' - pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation' - pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob' - pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image' - pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS' - pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network' - pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings' - pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text' - pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration' - pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/' - - pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact' - pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi' - pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor' - pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector' - pod 'ReactCommon/callinvoker', :path => "../node_modules/react-native/ReactCommon" - pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon" - pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga', :modular_headers => true - - pod 'JitsiMeetSDK', :git => 'https://github.com/RocketChat/jitsi-meet-ios-sdk-releases.git' - - pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec' - pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec' - pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec' - - use_native_modules! - use_unimodules! + all_pods end -# Enables Flipper. -# -# Note that if you have use_frameworks! enabled, Flipper will not work and -# you should disable these next few lines. -add_flipper_pods! post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| @@ -145,4 +25,4 @@ post_install do |installer| end end flipper_post_install(installer) -end +end \ No newline at end of file diff --git a/ios/Podfile.lock b/ios/Podfile.lock index fc8055335..c72afcec8 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,89 +1,95 @@ PODS: - boost-for-react-native (1.63.0) - - BugsnagReactNative (2.23.7): - - BugsnagReactNative/Core (= 2.23.7) + - BugsnagReactNative (2.23.10): + - BugsnagReactNative/Core (= 2.23.10) - React - - BugsnagReactNative/Core (2.23.7): + - BugsnagReactNative/Core (2.23.10): - React - CocoaAsyncSocket (7.6.4) - CocoaLibEvent (1.0.0) - - Crashlytics (3.14.0): - - Fabric (~> 1.10.2) - DoubleConversion (1.1.6) - EXAppleAuthentication (2.2.1): - UMCore - - EXAV (8.1.0): + - EXAV (8.2.1): - UMCore - UMFileSystemInterface - UMPermissionsInterface - - EXConstants (9.0.0): + - EXConstants (9.1.1): - UMConstantsInterface - UMCore - - EXFileSystem (8.1.0): + - EXFileSystem (9.0.1): - UMCore - UMFileSystemInterface - - EXHaptics (8.1.0): + - EXHaptics (8.2.1): - UMCore - - EXImageLoader (1.0.1): + - EXImageLoader (1.1.1): - React-Core - UMCore - UMImageLoaderInterface - - EXKeepAwake (8.1.0): + - EXKeepAwake (8.2.1): - UMCore - - EXLocalAuthentication (9.0.0): + - EXLocalAuthentication (9.2.0): - UMConstantsInterface - UMCore - - EXPermissions (8.1.0): + - EXPermissions (9.0.1): - UMCore - UMPermissionsInterface - - EXVideoThumbnails (4.1.1): + - EXVideoThumbnails (4.2.1): - UMCore - UMFileSystemInterface - - EXWebBrowser (8.2.1): + - EXWebBrowser (8.3.1): - UMCore - - Fabric (1.10.2) - - FBLazyVector (0.62.2) - - FBReactNativeSpec (0.62.2): - - Folly (= 2018.10.22.00) - - RCTRequired (= 0.62.2) - - RCTTypeSafety (= 0.62.2) - - React-Core (= 0.62.2) - - React-jsi (= 0.62.2) - - ReactCommon/turbomodule/core (= 0.62.2) - - Firebase/Core (6.24.0): + - FBLazyVector (0.63.1) + - FBReactNativeSpec (0.63.1): + - Folly (= 2020.01.13.00) + - RCTRequired (= 0.63.1) + - RCTTypeSafety (= 0.63.1) + - React-Core (= 0.63.1) + - React-jsi (= 0.63.1) + - ReactCommon/turbomodule/core (= 0.63.1) + - Firebase/Analytics (6.27.1): + - Firebase/Core + - Firebase/Core (6.27.1): - Firebase/CoreOnly - - FirebaseAnalytics (= 6.5.0) - - Firebase/CoreOnly (6.24.0): - - FirebaseCore (= 6.7.0) - - FirebaseAnalytics (6.5.0): - - FirebaseCore (~> 6.7) - - FirebaseInstallations (~> 1.2) - - GoogleAppMeasurement (= 6.5.0) + - FirebaseAnalytics (= 6.6.2) + - Firebase/CoreOnly (6.27.1): + - FirebaseCore (= 6.8.1) + - Firebase/Crashlytics (6.27.1): + - Firebase/CoreOnly + - FirebaseCrashlytics (~> 4.2.0) + - FirebaseAnalytics (6.6.2): + - FirebaseCore (~> 6.8) + - FirebaseInstallations (~> 1.4) + - GoogleAppMeasurement (= 6.6.2) - GoogleUtilities/AppDelegateSwizzler (~> 6.0) - GoogleUtilities/MethodSwizzler (~> 6.0) - GoogleUtilities/Network (~> 6.0) - "GoogleUtilities/NSData+zlib (~> 6.0)" - nanopb (~> 1.30905.0) - - FirebaseCore (6.7.0): + - FirebaseCore (6.8.1): - FirebaseCoreDiagnostics (~> 1.3) - - FirebaseCoreDiagnosticsInterop (~> 1.2) - GoogleUtilities/Environment (~> 6.5) - GoogleUtilities/Logger (~> 6.5) - - FirebaseCoreDiagnostics (1.3.0): - - FirebaseCoreDiagnosticsInterop (~> 1.2) + - FirebaseCoreDiagnostics (1.4.0): - GoogleDataTransportCCTSupport (~> 3.1) - GoogleUtilities/Environment (~> 6.5) - GoogleUtilities/Logger (~> 6.5) - nanopb (~> 1.30905.0) - - FirebaseCoreDiagnosticsInterop (1.2.0) - - FirebaseInstallations (1.2.0): - - FirebaseCore (~> 6.6) - - GoogleUtilities/Environment (~> 6.6) - - GoogleUtilities/UserDefaults (~> 6.6) + - FirebaseCrashlytics (4.2.0): + - FirebaseCore (~> 6.8) + - FirebaseInstallations (~> 1.1) + - GoogleDataTransport (~> 6.1) + - GoogleDataTransportCCTSupport (~> 3.1) + - nanopb (~> 1.30905.0) - PromisesObjC (~> 1.2) - - Flipper (0.33.1): - - Flipper-Folly (~> 2.1) - - Flipper-RSocket (~> 1.0) + - FirebaseInstallations (1.5.0): + - FirebaseCore (~> 6.8) + - GoogleUtilities/Environment (~> 6.7) + - GoogleUtilities/UserDefaults (~> 6.7) + - PromisesObjC (~> 1.2) + - Flipper (0.41.5): + - Flipper-Folly (~> 2.2) + - Flipper-RSocket (~> 1.1) - Flipper-DoubleConversion (1.1.7) - Flipper-Folly (2.2.0): - boost-for-react-native @@ -95,76 +101,76 @@ PODS: - Flipper-PeerTalk (0.0.4) - Flipper-RSocket (1.1.0): - Flipper-Folly (~> 2.2) - - FlipperKit (0.33.1): - - FlipperKit/Core (= 0.33.1) - - FlipperKit/Core (0.33.1): - - Flipper (~> 0.33.1) + - FlipperKit (0.41.5): + - FlipperKit/Core (= 0.41.5) + - FlipperKit/Core (0.41.5): + - Flipper (~> 0.41.5) - FlipperKit/CppBridge - FlipperKit/FBCxxFollyDynamicConvert - FlipperKit/FBDefines - FlipperKit/FKPortForwarding - - FlipperKit/CppBridge (0.33.1): - - Flipper (~> 0.33.1) - - FlipperKit/FBCxxFollyDynamicConvert (0.33.1): - - Flipper-Folly (~> 2.1) - - FlipperKit/FBDefines (0.33.1) - - FlipperKit/FKPortForwarding (0.33.1): + - FlipperKit/CppBridge (0.41.5): + - Flipper (~> 0.41.5) + - FlipperKit/FBCxxFollyDynamicConvert (0.41.5): + - Flipper-Folly (~> 2.2) + - FlipperKit/FBDefines (0.41.5) + - FlipperKit/FKPortForwarding (0.41.5): - CocoaAsyncSocket (~> 7.6) - Flipper-PeerTalk (~> 0.0.4) - - FlipperKit/FlipperKitHighlightOverlay (0.33.1) - - FlipperKit/FlipperKitLayoutPlugin (0.33.1): + - FlipperKit/FlipperKitHighlightOverlay (0.41.5) + - FlipperKit/FlipperKitLayoutPlugin (0.41.5): - FlipperKit/Core - FlipperKit/FlipperKitHighlightOverlay - FlipperKit/FlipperKitLayoutTextSearchable - YogaKit (~> 1.18) - - FlipperKit/FlipperKitLayoutTextSearchable (0.33.1) - - FlipperKit/FlipperKitNetworkPlugin (0.33.1): + - FlipperKit/FlipperKitLayoutTextSearchable (0.41.5) + - FlipperKit/FlipperKitNetworkPlugin (0.41.5): - FlipperKit/Core - - FlipperKit/FlipperKitReactPlugin (0.33.1): + - FlipperKit/FlipperKitReactPlugin (0.41.5): - FlipperKit/Core - - FlipperKit/FlipperKitUserDefaultsPlugin (0.33.1): + - FlipperKit/FlipperKitUserDefaultsPlugin (0.41.5): - FlipperKit/Core - - FlipperKit/SKIOSNetworkPlugin (0.33.1): + - FlipperKit/SKIOSNetworkPlugin (0.41.5): - FlipperKit/Core - FlipperKit/FlipperKitNetworkPlugin - - Folly (2018.10.22.00): + - Folly (2020.01.13.00): - boost-for-react-native - DoubleConversion - - Folly/Default (= 2018.10.22.00) + - Folly/Default (= 2020.01.13.00) - glog - - Folly/Default (2018.10.22.00): + - Folly/Default (2020.01.13.00): - boost-for-react-native - DoubleConversion - glog - glog (0.3.5) - - GoogleAppMeasurement (6.5.0): + - GoogleAppMeasurement (6.6.2): - GoogleUtilities/AppDelegateSwizzler (~> 6.0) - GoogleUtilities/MethodSwizzler (~> 6.0) - GoogleUtilities/Network (~> 6.0) - "GoogleUtilities/NSData+zlib (~> 6.0)" - nanopb (~> 1.30905.0) - - GoogleDataTransport (6.1.0) - - GoogleDataTransportCCTSupport (3.1.0): + - GoogleDataTransport (6.2.1) + - GoogleDataTransportCCTSupport (3.2.0): - GoogleDataTransport (~> 6.1) - nanopb (~> 1.30905.0) - - GoogleUtilities/AppDelegateSwizzler (6.6.0): + - GoogleUtilities/AppDelegateSwizzler (6.7.1): - GoogleUtilities/Environment - GoogleUtilities/Logger - GoogleUtilities/Network - - GoogleUtilities/Environment (6.6.0): + - GoogleUtilities/Environment (6.7.1): - PromisesObjC (~> 1.2) - - GoogleUtilities/Logger (6.6.0): + - GoogleUtilities/Logger (6.7.1): - GoogleUtilities/Environment - - GoogleUtilities/MethodSwizzler (6.6.0): + - GoogleUtilities/MethodSwizzler (6.7.1): - GoogleUtilities/Logger - - GoogleUtilities/Network (6.6.0): + - GoogleUtilities/Network (6.7.1): - GoogleUtilities/Logger - "GoogleUtilities/NSData+zlib" - GoogleUtilities/Reachability - - "GoogleUtilities/NSData+zlib (6.6.0)" - - GoogleUtilities/Reachability (6.6.0): + - "GoogleUtilities/NSData+zlib (6.7.1)" + - GoogleUtilities/Reachability (6.7.1): - GoogleUtilities/Logger - - GoogleUtilities/UserDefaults (6.6.0): + - GoogleUtilities/UserDefaults (6.7.1): - GoogleUtilities/Logger - JitsiMeetSDK (2.8.1) - KeyCommands (2.0.3): @@ -186,177 +192,180 @@ PODS: - OpenSSL-Universal (1.0.2.19): - OpenSSL-Universal/Static (= 1.0.2.19) - OpenSSL-Universal/Static (1.0.2.19) - - PromisesObjC (1.2.8) - - RCTRequired (0.62.2) - - RCTTypeSafety (0.62.2): - - FBLazyVector (= 0.62.2) - - Folly (= 2018.10.22.00) - - RCTRequired (= 0.62.2) - - React-Core (= 0.62.2) - - React (0.62.2): - - React-Core (= 0.62.2) - - React-Core/DevSupport (= 0.62.2) - - React-Core/RCTWebSocket (= 0.62.2) - - React-RCTActionSheet (= 0.62.2) - - React-RCTAnimation (= 0.62.2) - - React-RCTBlob (= 0.62.2) - - React-RCTImage (= 0.62.2) - - React-RCTLinking (= 0.62.2) - - React-RCTNetwork (= 0.62.2) - - React-RCTSettings (= 0.62.2) - - React-RCTText (= 0.62.2) - - React-RCTVibration (= 0.62.2) - - React-Core (0.62.2): - - Folly (= 2018.10.22.00) + - PromisesObjC (1.2.9) + - RCTRequired (0.63.1) + - RCTTypeSafety (0.63.1): + - FBLazyVector (= 0.63.1) + - Folly (= 2020.01.13.00) + - RCTRequired (= 0.63.1) + - React-Core (= 0.63.1) + - React (0.63.1): + - React-Core (= 0.63.1) + - React-Core/DevSupport (= 0.63.1) + - React-Core/RCTWebSocket (= 0.63.1) + - React-RCTActionSheet (= 0.63.1) + - React-RCTAnimation (= 0.63.1) + - React-RCTBlob (= 0.63.1) + - React-RCTImage (= 0.63.1) + - React-RCTLinking (= 0.63.1) + - React-RCTNetwork (= 0.63.1) + - React-RCTSettings (= 0.63.1) + - React-RCTText (= 0.63.1) + - React-RCTVibration (= 0.63.1) + - React-callinvoker (0.63.1) + - React-Core (0.63.1): + - Folly (= 2020.01.13.00) - glog - - React-Core/Default (= 0.62.2) - - React-cxxreact (= 0.62.2) - - React-jsi (= 0.62.2) - - React-jsiexecutor (= 0.62.2) + - React-Core/Default (= 0.63.1) + - React-cxxreact (= 0.63.1) + - React-jsi (= 0.63.1) + - React-jsiexecutor (= 0.63.1) - Yoga - - React-Core/CoreModulesHeaders (0.62.2): - - Folly (= 2018.10.22.00) + - React-Core/CoreModulesHeaders (0.63.1): + - Folly (= 2020.01.13.00) - glog - React-Core/Default - - React-cxxreact (= 0.62.2) - - React-jsi (= 0.62.2) - - React-jsiexecutor (= 0.62.2) + - React-cxxreact (= 0.63.1) + - React-jsi (= 0.63.1) + - React-jsiexecutor (= 0.63.1) - Yoga - - React-Core/Default (0.62.2): - - Folly (= 2018.10.22.00) + - React-Core/Default (0.63.1): + - Folly (= 2020.01.13.00) - glog - - React-cxxreact (= 0.62.2) - - React-jsi (= 0.62.2) - - React-jsiexecutor (= 0.62.2) + - React-cxxreact (= 0.63.1) + - React-jsi (= 0.63.1) + - React-jsiexecutor (= 0.63.1) - Yoga - - React-Core/DevSupport (0.62.2): - - Folly (= 2018.10.22.00) + - React-Core/DevSupport (0.63.1): + - Folly (= 2020.01.13.00) - glog - - React-Core/Default (= 0.62.2) - - React-Core/RCTWebSocket (= 0.62.2) - - React-cxxreact (= 0.62.2) - - React-jsi (= 0.62.2) - - React-jsiexecutor (= 0.62.2) - - React-jsinspector (= 0.62.2) + - React-Core/Default (= 0.63.1) + - React-Core/RCTWebSocket (= 0.63.1) + - React-cxxreact (= 0.63.1) + - React-jsi (= 0.63.1) + - React-jsiexecutor (= 0.63.1) + - React-jsinspector (= 0.63.1) - Yoga - - React-Core/RCTActionSheetHeaders (0.62.2): - - Folly (= 2018.10.22.00) + - React-Core/RCTActionSheetHeaders (0.63.1): + - Folly (= 2020.01.13.00) - glog - React-Core/Default - - React-cxxreact (= 0.62.2) - - React-jsi (= 0.62.2) - - React-jsiexecutor (= 0.62.2) + - React-cxxreact (= 0.63.1) + - React-jsi (= 0.63.1) + - React-jsiexecutor (= 0.63.1) - Yoga - - React-Core/RCTAnimationHeaders (0.62.2): - - Folly (= 2018.10.22.00) + - React-Core/RCTAnimationHeaders (0.63.1): + - Folly (= 2020.01.13.00) - glog - React-Core/Default - - React-cxxreact (= 0.62.2) - - React-jsi (= 0.62.2) - - React-jsiexecutor (= 0.62.2) + - React-cxxreact (= 0.63.1) + - React-jsi (= 0.63.1) + - React-jsiexecutor (= 0.63.1) - Yoga - - React-Core/RCTBlobHeaders (0.62.2): - - Folly (= 2018.10.22.00) + - React-Core/RCTBlobHeaders (0.63.1): + - Folly (= 2020.01.13.00) - glog - React-Core/Default - - React-cxxreact (= 0.62.2) - - React-jsi (= 0.62.2) - - React-jsiexecutor (= 0.62.2) + - React-cxxreact (= 0.63.1) + - React-jsi (= 0.63.1) + - React-jsiexecutor (= 0.63.1) - Yoga - - React-Core/RCTImageHeaders (0.62.2): - - Folly (= 2018.10.22.00) + - React-Core/RCTImageHeaders (0.63.1): + - Folly (= 2020.01.13.00) - glog - React-Core/Default - - React-cxxreact (= 0.62.2) - - React-jsi (= 0.62.2) - - React-jsiexecutor (= 0.62.2) + - React-cxxreact (= 0.63.1) + - React-jsi (= 0.63.1) + - React-jsiexecutor (= 0.63.1) - Yoga - - React-Core/RCTLinkingHeaders (0.62.2): - - Folly (= 2018.10.22.00) + - React-Core/RCTLinkingHeaders (0.63.1): + - Folly (= 2020.01.13.00) - glog - React-Core/Default - - React-cxxreact (= 0.62.2) - - React-jsi (= 0.62.2) - - React-jsiexecutor (= 0.62.2) + - React-cxxreact (= 0.63.1) + - React-jsi (= 0.63.1) + - React-jsiexecutor (= 0.63.1) - Yoga - - React-Core/RCTNetworkHeaders (0.62.2): - - Folly (= 2018.10.22.00) + - React-Core/RCTNetworkHeaders (0.63.1): + - Folly (= 2020.01.13.00) - glog - React-Core/Default - - React-cxxreact (= 0.62.2) - - React-jsi (= 0.62.2) - - React-jsiexecutor (= 0.62.2) + - React-cxxreact (= 0.63.1) + - React-jsi (= 0.63.1) + - React-jsiexecutor (= 0.63.1) - Yoga - - React-Core/RCTSettingsHeaders (0.62.2): - - Folly (= 2018.10.22.00) + - React-Core/RCTSettingsHeaders (0.63.1): + - Folly (= 2020.01.13.00) - glog - React-Core/Default - - React-cxxreact (= 0.62.2) - - React-jsi (= 0.62.2) - - React-jsiexecutor (= 0.62.2) + - React-cxxreact (= 0.63.1) + - React-jsi (= 0.63.1) + - React-jsiexecutor (= 0.63.1) - Yoga - - React-Core/RCTTextHeaders (0.62.2): - - Folly (= 2018.10.22.00) + - React-Core/RCTTextHeaders (0.63.1): + - Folly (= 2020.01.13.00) - glog - React-Core/Default - - React-cxxreact (= 0.62.2) - - React-jsi (= 0.62.2) - - React-jsiexecutor (= 0.62.2) + - React-cxxreact (= 0.63.1) + - React-jsi (= 0.63.1) + - React-jsiexecutor (= 0.63.1) - Yoga - - React-Core/RCTVibrationHeaders (0.62.2): - - Folly (= 2018.10.22.00) + - React-Core/RCTVibrationHeaders (0.63.1): + - Folly (= 2020.01.13.00) - glog - React-Core/Default - - React-cxxreact (= 0.62.2) - - React-jsi (= 0.62.2) - - React-jsiexecutor (= 0.62.2) + - React-cxxreact (= 0.63.1) + - React-jsi (= 0.63.1) + - React-jsiexecutor (= 0.63.1) - Yoga - - React-Core/RCTWebSocket (0.62.2): - - Folly (= 2018.10.22.00) + - React-Core/RCTWebSocket (0.63.1): + - Folly (= 2020.01.13.00) - glog - - React-Core/Default (= 0.62.2) - - React-cxxreact (= 0.62.2) - - React-jsi (= 0.62.2) - - React-jsiexecutor (= 0.62.2) + - React-Core/Default (= 0.63.1) + - React-cxxreact (= 0.63.1) + - React-jsi (= 0.63.1) + - React-jsiexecutor (= 0.63.1) - Yoga - - React-CoreModules (0.62.2): - - FBReactNativeSpec (= 0.62.2) - - Folly (= 2018.10.22.00) - - RCTTypeSafety (= 0.62.2) - - React-Core/CoreModulesHeaders (= 0.62.2) - - React-RCTImage (= 0.62.2) - - ReactCommon/turbomodule/core (= 0.62.2) - - React-cxxreact (0.62.2): + - React-CoreModules (0.63.1): + - FBReactNativeSpec (= 0.63.1) + - Folly (= 2020.01.13.00) + - RCTTypeSafety (= 0.63.1) + - React-Core/CoreModulesHeaders (= 0.63.1) + - React-jsi (= 0.63.1) + - React-RCTImage (= 0.63.1) + - ReactCommon/turbomodule/core (= 0.63.1) + - React-cxxreact (0.63.1): - boost-for-react-native (= 1.63.0) - DoubleConversion - - Folly (= 2018.10.22.00) + - Folly (= 2020.01.13.00) - glog - - React-jsinspector (= 0.62.2) - - React-jsi (0.62.2): + - React-callinvoker (= 0.63.1) + - React-jsinspector (= 0.63.1) + - React-jsi (0.63.1): - boost-for-react-native (= 1.63.0) - DoubleConversion - - Folly (= 2018.10.22.00) + - Folly (= 2020.01.13.00) - glog - - React-jsi/Default (= 0.62.2) - - React-jsi/Default (0.62.2): + - React-jsi/Default (= 0.63.1) + - React-jsi/Default (0.63.1): - boost-for-react-native (= 1.63.0) - DoubleConversion - - Folly (= 2018.10.22.00) + - Folly (= 2020.01.13.00) - glog - - React-jsiexecutor (0.62.2): + - React-jsiexecutor (0.63.1): - DoubleConversion - - Folly (= 2018.10.22.00) + - Folly (= 2020.01.13.00) - glog - - React-cxxreact (= 0.62.2) - - React-jsi (= 0.62.2) - - React-jsinspector (0.62.2) + - React-cxxreact (= 0.63.1) + - React-jsi (= 0.63.1) + - React-jsinspector (0.63.1) - react-native-appearance (0.3.4): - React - react-native-background-timer (2.2.0): - React - - react-native-cameraroll (1.6.0): + - react-native-cameraroll (4.0.0): - React - - react-native-document-picker (3.3.3): + - react-native-document-picker (3.5.3): - React - react-native-jitsi-meet (2.1.1): - JitsiMeetSDK (= 2.8.1) @@ -365,71 +374,72 @@ PODS: - React - react-native-orientation-locker (1.1.8): - React - - react-native-safe-area-context (3.0.2): + - react-native-safe-area-context (3.1.1): - React - - react-native-slider (2.0.9): + - react-native-slider (3.0.2): - React - - react-native-webview (9.4.0): + - react-native-webview (10.3.2): - React - - React-RCTActionSheet (0.62.2): - - React-Core/RCTActionSheetHeaders (= 0.62.2) - - React-RCTAnimation (0.62.2): - - FBReactNativeSpec (= 0.62.2) - - Folly (= 2018.10.22.00) - - RCTTypeSafety (= 0.62.2) - - React-Core/RCTAnimationHeaders (= 0.62.2) - - ReactCommon/turbomodule/core (= 0.62.2) - - React-RCTBlob (0.62.2): - - FBReactNativeSpec (= 0.62.2) - - Folly (= 2018.10.22.00) - - React-Core/RCTBlobHeaders (= 0.62.2) - - React-Core/RCTWebSocket (= 0.62.2) - - React-jsi (= 0.62.2) - - React-RCTNetwork (= 0.62.2) - - ReactCommon/turbomodule/core (= 0.62.2) - - React-RCTImage (0.62.2): - - FBReactNativeSpec (= 0.62.2) - - Folly (= 2018.10.22.00) - - RCTTypeSafety (= 0.62.2) - - React-Core/RCTImageHeaders (= 0.62.2) - - React-RCTNetwork (= 0.62.2) - - ReactCommon/turbomodule/core (= 0.62.2) - - React-RCTLinking (0.62.2): - - FBReactNativeSpec (= 0.62.2) - - React-Core/RCTLinkingHeaders (= 0.62.2) - - ReactCommon/turbomodule/core (= 0.62.2) - - React-RCTNetwork (0.62.2): - - FBReactNativeSpec (= 0.62.2) - - Folly (= 2018.10.22.00) - - RCTTypeSafety (= 0.62.2) - - React-Core/RCTNetworkHeaders (= 0.62.2) - - ReactCommon/turbomodule/core (= 0.62.2) - - React-RCTSettings (0.62.2): - - FBReactNativeSpec (= 0.62.2) - - Folly (= 2018.10.22.00) - - RCTTypeSafety (= 0.62.2) - - React-Core/RCTSettingsHeaders (= 0.62.2) - - ReactCommon/turbomodule/core (= 0.62.2) - - React-RCTText (0.62.2): - - React-Core/RCTTextHeaders (= 0.62.2) - - React-RCTVibration (0.62.2): - - FBReactNativeSpec (= 0.62.2) - - Folly (= 2018.10.22.00) - - React-Core/RCTVibrationHeaders (= 0.62.2) - - ReactCommon/turbomodule/core (= 0.62.2) - - ReactCommon/callinvoker (0.62.2): + - React-RCTActionSheet (0.63.1): + - React-Core/RCTActionSheetHeaders (= 0.63.1) + - React-RCTAnimation (0.63.1): + - FBReactNativeSpec (= 0.63.1) + - Folly (= 2020.01.13.00) + - RCTTypeSafety (= 0.63.1) + - React-Core/RCTAnimationHeaders (= 0.63.1) + - React-jsi (= 0.63.1) + - ReactCommon/turbomodule/core (= 0.63.1) + - React-RCTBlob (0.63.1): + - FBReactNativeSpec (= 0.63.1) + - Folly (= 2020.01.13.00) + - React-Core/RCTBlobHeaders (= 0.63.1) + - React-Core/RCTWebSocket (= 0.63.1) + - React-jsi (= 0.63.1) + - React-RCTNetwork (= 0.63.1) + - ReactCommon/turbomodule/core (= 0.63.1) + - React-RCTImage (0.63.1): + - FBReactNativeSpec (= 0.63.1) + - Folly (= 2020.01.13.00) + - RCTTypeSafety (= 0.63.1) + - React-Core/RCTImageHeaders (= 0.63.1) + - React-jsi (= 0.63.1) + - React-RCTNetwork (= 0.63.1) + - ReactCommon/turbomodule/core (= 0.63.1) + - React-RCTLinking (0.63.1): + - FBReactNativeSpec (= 0.63.1) + - React-Core/RCTLinkingHeaders (= 0.63.1) + - React-jsi (= 0.63.1) + - ReactCommon/turbomodule/core (= 0.63.1) + - React-RCTNetwork (0.63.1): + - FBReactNativeSpec (= 0.63.1) + - Folly (= 2020.01.13.00) + - RCTTypeSafety (= 0.63.1) + - React-Core/RCTNetworkHeaders (= 0.63.1) + - React-jsi (= 0.63.1) + - ReactCommon/turbomodule/core (= 0.63.1) + - React-RCTSettings (0.63.1): + - FBReactNativeSpec (= 0.63.1) + - Folly (= 2020.01.13.00) + - RCTTypeSafety (= 0.63.1) + - React-Core/RCTSettingsHeaders (= 0.63.1) + - React-jsi (= 0.63.1) + - ReactCommon/turbomodule/core (= 0.63.1) + - React-RCTText (0.63.1): + - React-Core/RCTTextHeaders (= 0.63.1) + - React-RCTVibration (0.63.1): + - FBReactNativeSpec (= 0.63.1) + - Folly (= 2020.01.13.00) + - React-Core/RCTVibrationHeaders (= 0.63.1) + - React-jsi (= 0.63.1) + - ReactCommon/turbomodule/core (= 0.63.1) + - ReactCommon/turbomodule/core (0.63.1): - DoubleConversion - - Folly (= 2018.10.22.00) + - Folly (= 2020.01.13.00) - glog - - React-cxxreact (= 0.62.2) - - ReactCommon/turbomodule/core (0.62.2): - - DoubleConversion - - Folly (= 2018.10.22.00) - - glog - - React-Core (= 0.62.2) - - React-cxxreact (= 0.62.2) - - React-jsi (= 0.62.2) - - ReactCommon/callinvoker (= 0.62.2) + - React-callinvoker (= 0.63.1) + - React-Core (= 0.63.1) + - React-cxxreact (= 0.63.1) + - React-jsi (= 0.63.1) - ReactNativeART (1.2.0): - React - ReactNativeKeyboardInput (6.0.0): @@ -442,27 +452,30 @@ PODS: - React-Core - RNBootSplash (2.2.5): - React - - RNCAsyncStorage (1.10.3): + - RNCAsyncStorage (1.11.0): - React - RNCMaskedView (0.1.10): - React - - RNDateTimePicker (2.3.2): + - RNDateTimePicker (2.6.0): - React - - RNDeviceInfo (5.5.7): + - RNDeviceInfo (5.6.2): - React - RNFastImage (8.1.5): - React - SDWebImage (~> 5.0) - SDWebImageWebPCoder (~> 0.4.1) - - RNFirebase (5.6.0): - - Firebase/Core + - RNFBAnalytics (7.3.1): + - Firebase/Analytics (~> 6.27.0) - React - - RNFirebase/Crashlytics (= 5.6.0) - - RNFirebase/Crashlytics (5.6.0): - - Crashlytics - - Fabric - - Firebase/Core + - RNFBApp + - RNFBApp (8.2.0): + - Firebase/CoreOnly (~> 6.27.0) - React + - RNFBCrashlytics (8.1.2): + - Firebase/Core (~> 6.27.0) + - Firebase/Crashlytics (~> 6.27.0) + - React + - RNFBApp - RNGestureHandler (1.6.1): - React - RNImageCropPicker (0.31.1): @@ -476,40 +489,40 @@ PODS: - TOCropViewController - RNLocalize (1.4.0): - React - - RNReanimated (1.8.0): + - RNReanimated (1.9.0): - React - RNRootView (1.0.3): - React - - RNScreens (2.7.0): + - RNScreens (2.9.0): - React - RNUserDefaults (1.8.1): - React - - RNVectorIcons (6.6.0): + - RNVectorIcons (7.0.0): - React - - SDWebImage (5.7.4): - - SDWebImage/Core (= 5.7.4) - - SDWebImage/Core (5.7.4) + - SDWebImage (5.8.4): + - SDWebImage/Core (= 5.8.4) + - SDWebImage/Core (5.8.4) - SDWebImageWebPCoder (0.4.1): - libwebp (~> 1.0) - SDWebImage/Core (~> 5.5) - - TOCropViewController (2.5.2) - - UMAppLoader (1.0.2) - - UMBarCodeScannerInterface (5.1.0) - - UMCameraInterface (5.1.0) - - UMConstantsInterface (5.1.0) - - UMCore (5.1.2) - - UMFaceDetectorInterface (5.1.0) - - UMFileSystemInterface (5.1.0) - - UMFontInterface (5.1.0) - - UMImageLoaderInterface (5.1.0) - - UMPermissionsInterface (5.1.0): + - TOCropViewController (2.5.3) + - UMAppLoader (1.2.0) + - UMBarCodeScannerInterface (5.2.1) + - UMCameraInterface (5.2.1) + - UMConstantsInterface (5.2.1) + - UMCore (5.3.0) + - UMFaceDetectorInterface (5.2.1) + - UMFileSystemInterface (5.2.1) + - UMFontInterface (5.2.1) + - UMImageLoaderInterface (5.2.1) + - UMPermissionsInterface (5.2.1): - UMCore - - UMReactNativeAdapter (5.2.0): + - UMReactNativeAdapter (5.4.0): - React-Core - UMCore - UMFontInterface - - UMSensorsInterface (5.1.0) - - UMTaskManagerInterface (5.1.0) + - UMSensorsInterface (5.2.1) + - UMTaskManagerInterface (5.2.1) - Yoga (1.14.0) - YogaKit (1.18.1): - Yoga (~> 1.14) @@ -530,32 +543,32 @@ DEPENDENCIES: - EXWebBrowser (from `../node_modules/expo-web-browser/ios`) - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) - FBReactNativeSpec (from `../node_modules/react-native/Libraries/FBReactNativeSpec`) - - Flipper (~> 0.33.1) + - Flipper (~> 0.41.1) - Flipper-DoubleConversion (= 1.1.7) - - Flipper-Folly (~> 2.1) + - Flipper-Folly (~> 2.2) - Flipper-Glog (= 0.3.6) - Flipper-PeerTalk (~> 0.0.4) - - Flipper-RSocket (~> 1.0) - - FlipperKit (~> 0.33.1) - - FlipperKit/Core (~> 0.33.1) - - FlipperKit/CppBridge (~> 0.33.1) - - FlipperKit/FBCxxFollyDynamicConvert (~> 0.33.1) - - FlipperKit/FBDefines (~> 0.33.1) - - FlipperKit/FKPortForwarding (~> 0.33.1) - - FlipperKit/FlipperKitHighlightOverlay (~> 0.33.1) - - FlipperKit/FlipperKitLayoutPlugin (~> 0.33.1) - - FlipperKit/FlipperKitLayoutTextSearchable (~> 0.33.1) - - FlipperKit/FlipperKitNetworkPlugin (~> 0.33.1) - - FlipperKit/FlipperKitReactPlugin (~> 0.33.1) - - FlipperKit/FlipperKitUserDefaultsPlugin (~> 0.33.1) - - FlipperKit/SKIOSNetworkPlugin (~> 0.33.1) + - Flipper-RSocket (~> 1.1) + - FlipperKit (~> 0.41.1) + - FlipperKit/Core (~> 0.41.1) + - FlipperKit/CppBridge (~> 0.41.1) + - FlipperKit/FBCxxFollyDynamicConvert (~> 0.41.1) + - FlipperKit/FBDefines (~> 0.41.1) + - FlipperKit/FKPortForwarding (~> 0.41.1) + - FlipperKit/FlipperKitHighlightOverlay (~> 0.41.1) + - FlipperKit/FlipperKitLayoutPlugin (~> 0.41.1) + - FlipperKit/FlipperKitLayoutTextSearchable (~> 0.41.1) + - FlipperKit/FlipperKitNetworkPlugin (~> 0.41.1) + - FlipperKit/FlipperKitReactPlugin (~> 0.41.1) + - FlipperKit/FlipperKitUserDefaultsPlugin (~> 0.41.1) + - FlipperKit/SKIOSNetworkPlugin (~> 0.41.1) - Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`) - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - - JitsiMeetSDK (from `https://github.com/RocketChat/jitsi-meet-ios-sdk-releases.git`) - KeyCommands (from `../node_modules/react-native-keycommands`) - RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`) - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`) - React (from `../node_modules/react-native/`) + - React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`) - React-Core (from `../node_modules/react-native/`) - React-Core/DevSupport (from `../node_modules/react-native/`) - React-Core/RCTWebSocket (from `../node_modules/react-native/`) @@ -583,7 +596,6 @@ DEPENDENCIES: - React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`) - React-RCTText (from `../node_modules/react-native/Libraries/Text`) - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`) - - ReactCommon/callinvoker (from `../node_modules/react-native/ReactCommon`) - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) - "ReactNativeART (from `../node_modules/@react-native-community/art`)" - ReactNativeKeyboardInput (from `../node_modules/react-native-keyboard-input`) @@ -595,8 +607,10 @@ DEPENDENCIES: - "RNCMaskedView (from `../node_modules/@react-native-community/masked-view`)" - "RNDateTimePicker (from `../node_modules/@react-native-community/datetimepicker`)" - RNDeviceInfo (from `../node_modules/react-native-device-info`) - - RNFastImage (from `../node_modules/react-native-fast-image`) - - RNFirebase (from `../node_modules/react-native-firebase/ios`) + - "RNFastImage (from `../node_modules/@rocket.chat/react-native-fast-image`)" + - "RNFBAnalytics (from `../node_modules/@react-native-firebase/analytics`)" + - "RNFBApp (from `../node_modules/@react-native-firebase/app`)" + - "RNFBCrashlytics (from `../node_modules/@react-native-firebase/crashlytics`)" - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) - RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`) - RNLocalize (from `../node_modules/react-native-localize`) @@ -625,13 +639,11 @@ SPEC REPOS: - boost-for-react-native - CocoaAsyncSocket - CocoaLibEvent - - Crashlytics - - Fabric - Firebase - FirebaseAnalytics - FirebaseCore - FirebaseCoreDiagnostics - - FirebaseCoreDiagnosticsInterop + - FirebaseCrashlytics - FirebaseInstallations - Flipper - Flipper-DoubleConversion @@ -644,6 +656,7 @@ SPEC REPOS: - GoogleDataTransport - GoogleDataTransportCCTSupport - GoogleUtilities + - JitsiMeetSDK - libwebp - nanopb - OpenSSL-Universal @@ -688,8 +701,6 @@ EXTERNAL SOURCES: :podspec: "../node_modules/react-native/third-party-podspecs/Folly.podspec" glog: :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec" - JitsiMeetSDK: - :git: https://github.com/RocketChat/jitsi-meet-ios-sdk-releases.git KeyCommands: :path: "../node_modules/react-native-keycommands" RCTRequired: @@ -698,6 +709,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/Libraries/TypeSafety" React: :path: "../node_modules/react-native/" + React-callinvoker: + :path: "../node_modules/react-native/ReactCommon/callinvoker" React-Core: :path: "../node_modules/react-native/" React-CoreModules: @@ -771,9 +784,13 @@ EXTERNAL SOURCES: RNDeviceInfo: :path: "../node_modules/react-native-device-info" RNFastImage: - :path: "../node_modules/react-native-fast-image" - RNFirebase: - :path: "../node_modules/react-native-firebase/ios" + :path: "../node_modules/@rocket.chat/react-native-fast-image" + RNFBAnalytics: + :path: "../node_modules/@react-native-firebase/analytics" + RNFBApp: + :path: "../node_modules/@react-native-firebase/app" + RNFBCrashlytics: + :path: "../node_modules/@react-native-firebase/crashlytics" RNGestureHandler: :path: "../node_modules/react-native-gesture-handler" RNImageCropPicker: @@ -819,125 +836,121 @@ EXTERNAL SOURCES: Yoga: :path: "../node_modules/react-native/ReactCommon/yoga" -CHECKOUT OPTIONS: - JitsiMeetSDK: - :commit: 9177aaa3afb379e17cc687887485e91e5cd24a49 - :git: https://github.com/RocketChat/jitsi-meet-ios-sdk-releases.git - SPEC CHECKSUMS: boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c - BugsnagReactNative: 14c1b59cfbf34fd5591b734bfec65a277b677ef8 + BugsnagReactNative: 98fb350df4bb0c94cce903023531a1a5cc11fa51 CocoaAsyncSocket: 694058e7c0ed05a9e217d1b3c7ded962f4180845 CocoaLibEvent: 2fab71b8bd46dd33ddb959f7928ec5909f838e3f - Crashlytics: 540b7e5f5da5a042647227a5e3ac51d85eed06df - DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2 + DoubleConversion: cde416483dac037923206447da6e1454df403714 EXAppleAuthentication: 5b3da71bada29e2423d8ea27e5538ef0d75aba62 - EXAV: 2edd9cd30fe98d04b55325303c7ff01db02d1d0f - EXConstants: 5304709b1bea70a4828f48ba4c7fc3ec3b2d9b17 - EXFileSystem: cf4232ba7c62dc49b78c2d36005f97b6fddf0b01 - EXHaptics: 013b5065946d4dd7b46ea547b58072d45a206dbd - EXImageLoader: 5ad6896fa1ef2ee814b551873cbf7a7baccc694a - EXKeepAwake: d045bc2cf1ad5a04f0323cc7c894b95b414042e0 - EXLocalAuthentication: bbf1026cc289d729da4f29240dd7a8f6a14e4b20 - EXPermissions: 24b97f734ce9172d245a5be38ad9ccfcb6135964 - EXVideoThumbnails: be6984a3cda1e44c45b5c6278244e99855f99a0a - EXWebBrowser: 5902f99ac5ac551e5c82ff46f13a337b323aa9ea - Fabric: 706c8b8098fff96c33c0db69cbf81f9c551d0d74 - FBLazyVector: 4aab18c93cd9546e4bfed752b4084585eca8b245 - FBReactNativeSpec: 5465d51ccfeecb7faa12f9ae0024f2044ce4044e - Firebase: b28e55c60efd98963cd9011fe2fac5a10c2ba124 - FirebaseAnalytics: 7386fc2176e3f93ad8ef34b5b1f2b33a891e4962 - FirebaseCore: e610482f64097b0e9f056cd97bc6b33dfabcbb6a - FirebaseCoreDiagnostics: 4a773a47bd83bbd5a9b1ccf1ce7caa8b2d535e67 - FirebaseCoreDiagnosticsInterop: 296e2c5f5314500a850ad0b83e9e7c10b011a850 - FirebaseInstallations: 2119fb3e46b0a88bfdbf12562f855ee3252462fa - Flipper: 6c1f484f9a88d30ab3e272800d53688439e50f69 + EXAV: 86344030966e0da7e00556fbb97269d9ad16071d + EXConstants: f907b3b6ce16e20d1750f22af1e095e924574bcb + EXFileSystem: 76875135b61708b9afa7e6a89b72a60ba0fdfa20 + EXHaptics: 5428b344a216ca5d9df6ca8f65720b2a1ad9f109 + EXImageLoader: 02ca02c9cd5cc8a97b423207a73a791e0a86bea5 + EXKeepAwake: 8b0f68242f036b971f9f8976341823cbe6f50812 + EXLocalAuthentication: 985c65e08a6eb84f8f98b51f7435df138b18b9e8 + EXPermissions: 80ac3acbdb145930079810fe5b08c022b3428aa8 + EXVideoThumbnails: f70bdc5511749f3181028f5000bcb7be203c631d + EXWebBrowser: d37a5ffdea1b65947352bc001dd9f732463725d4 + FBLazyVector: a50434c875bd42f2b1c99c712bda892a1dc659c7 + FBReactNativeSpec: 393853a536428e05a9da00b6290042f09809b15b + Firebase: 919186c8e119dd9372a45fd1dd17a8a942bc1892 + FirebaseAnalytics: 5fa308e1b13f838d0f6dc74719ac2a72e8c5afc4 + FirebaseCore: 8cd4f8ea22075e0ee582849b1cf79d8816506085 + FirebaseCoreDiagnostics: 4505e4d4009b1d93f605088ee7d7764d5f0d1c84 + FirebaseCrashlytics: 7d0fa02ea8842cc4b2ab07b0735edafde1ad77d6 + FirebaseInstallations: 3c520c951305cbf9ca54eb891ff9e6d1fd384881 + Flipper: 33585e2d9810fe5528346be33bcf71b37bb7ae13 Flipper-DoubleConversion: 38631e41ef4f9b12861c67d17cb5518d06badc41 Flipper-Folly: c12092ea368353b58e992843a990a3225d4533c3 Flipper-Glog: 1dfd6abf1e922806c52ceb8701a3599a79a200a6 Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9 Flipper-RSocket: 64e7431a55835eb953b0bf984ef3b90ae9fdddd7 - FlipperKit: 6dc9b8f4ef60d9e5ded7f0264db299c91f18832e - Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51 - glog: 1f3da668190260b06b429bb211bfbee5cd790c28 - GoogleAppMeasurement: 4c644d86835d827bab30ab6aabb9ecaf1f500735 - GoogleDataTransport: f6f8eba931df03ebd2232ff4645aa85f8f47b5ab - GoogleDataTransportCCTSupport: d70a561f7d236af529fee598835caad5e25f6d3d - GoogleUtilities: 39530bc0ad980530298e9c4af8549e991fd033b1 + FlipperKit: bc68102cd4952a258a23c9c1b316c7bec1fecf83 + Folly: b73c3869541e86821df3c387eb0af5f65addfab4 + glog: 40a13f7840415b9a77023fbcae0f1e6f43192af3 + GoogleAppMeasurement: 8cd1f289d60e629cf16ab03363b9e89c776b9651 + GoogleDataTransport: 9a8a16f79feffc7f42096743de2a7c4815e84020 + GoogleDataTransportCCTSupport: 489c1265d2c85b68187a83a911913d190012158d + GoogleUtilities: e121a3867449ce16b0e35ddf1797ea7a389ffdf2 JitsiMeetSDK: 2984eac1343690bf1c0c72bde75b48b0148d0f79 KeyCommands: f66c535f698ed14b3d3a4e58859d79a827ea907e libwebp: 946cb3063cea9236285f7e9a8505d806d30e07f3 nanopb: c43f40fadfe79e8b8db116583945847910cbabc9 OpenSSL-Universal: 8b48cc0d10c1b2923617dfe5c178aa9ed2689355 - PromisesObjC: c119f3cd559f50b7ae681fa59dc1acd19173b7e6 - RCTRequired: cec6a34b3ac8a9915c37e7e4ad3aa74726ce4035 - RCTTypeSafety: 93006131180074cffa227a1075802c89a49dd4ce - React: 29a8b1a02bd764fb7644ef04019270849b9a7ac3 - React-Core: b12bffb3f567fdf99510acb716ef1abd426e0e05 - React-CoreModules: 4a9b87bbe669d6c3173c0132c3328e3b000783d0 - React-cxxreact: e65f9c2ba0ac5be946f53548c1aaaee5873a8103 - React-jsi: b6dc94a6a12ff98e8877287a0b7620d365201161 - React-jsiexecutor: 1540d1c01bb493ae3124ed83351b1b6a155db7da - React-jsinspector: 512e560d0e985d0e8c479a54a4e5c147a9c83493 + PromisesObjC: b48e0338dbbac2207e611750777895f7a5811b75 + RCTRequired: d9b1a9e6fa097744ca3ede59f86a35096df7202b + RCTTypeSafety: c227cd061983e9e964115afbc4e8730d6a6f1395 + React: 86e972a20967ee4137aa19dc48319405927c2e94 + React-callinvoker: 87ee376c25277d74e164ff036b27084e343f3e69 + React-Core: f5ec03baf7ed58d9f3ee04a8f84e4c97ee8bf4c9 + React-CoreModules: 958898aa8c069280e866e35a2f29480a81fcf335 + React-cxxreact: 90de76b9b51575668ad7fd4e33a5a8c143beecc2 + React-jsi: b32a31da32e030f30bbf9a8d3a9c8325df9e793f + React-jsiexecutor: 7ab9cdcdd18d57652fb041f8a147fe9658d4e00a + React-jsinspector: 2e28bb487e42dda6c94dbfa0c648d1343767a0fb react-native-appearance: 0f0e5fc2fcef70e03d48c8fe6b00b9158c2ba8aa react-native-background-timer: 1f7d560647b40e6a60b01c452ba29c54bf581fc4 - react-native-cameraroll: 02e60e9af9273a3cc3b641632bf651189830aaf8 - react-native-document-picker: dd96ce05bf1453b110d7a3912097bf6d298d2cb6 + react-native-cameraroll: ae0a7c0cc8462508855707ff623b1e789b692865 + react-native-document-picker: 825552b827012282baf4b7cbf119d3b37a280c90 react-native-jitsi-meet: f89bcb2cfbd5b15403b9c40738036c4f1af45d05 react-native-notifications: ee8fd739853e72694f3af8b374c8ccb106b7b227 react-native-orientation-locker: f0ca1a8e5031dab6b74bfb4ab33a17ed2c2fcb0d - react-native-safe-area-context: b11a34881faac509cad5578726c98161ad4d275c - react-native-slider: e51492f1264d882a8815b71c5870f8978e52887d - react-native-webview: cf5527893252b3b036eea024a1da6996f7344c74 - React-RCTActionSheet: f41ea8a811aac770e0cc6e0ad6b270c644ea8b7c - React-RCTAnimation: 49ab98b1c1ff4445148b72a3d61554138565bad0 - React-RCTBlob: a332773f0ebc413a0ce85942a55b064471587a71 - React-RCTImage: e70be9b9c74fe4e42d0005f42cace7981c994ac3 - React-RCTLinking: c1b9739a88d56ecbec23b7f63650e44672ab2ad2 - React-RCTNetwork: 73138b6f45e5a2768ad93f3d57873c2a18d14b44 - React-RCTSettings: 6e3738a87e21b39a8cb08d627e68c44acf1e325a - React-RCTText: fae545b10cfdb3d247c36c56f61a94cfd6dba41d - React-RCTVibration: 4356114dbcba4ce66991096e51a66e61eda51256 - ReactCommon: ed4e11d27609d571e7eee8b65548efc191116eb3 + react-native-safe-area-context: 344b969c45af3d8464d36e8dea264942992ef033 + react-native-slider: 0221b417686c5957f6e77cd9ac22c1478a165355 + react-native-webview: 679b6f400176e2ea8a785acf7ae16cf282e7d1eb + React-RCTActionSheet: 1702a1a85e550b5c36e2e03cb2bd3adea053de95 + React-RCTAnimation: ddda576010a878865a4eab83a78acd92176ef6a1 + React-RCTBlob: 34334384284c81577409d5205bd2b9ff594d8ab6 + React-RCTImage: e2a661266dca295cffb33909cc64675a2efedb26 + React-RCTLinking: cd39b9b5e9cbb9e827854e30dfa92d7db074cea8 + React-RCTNetwork: 16939b7e4058d6f662b304a1f61689e249a2bfcc + React-RCTSettings: 24726a62de0c326f9ebfc3838898a501b87ce711 + React-RCTText: 4f95d322b7e6da72817284abf8a2cdcec18b9cd8 + React-RCTVibration: f3a9123c244f35c40d3c9f3ec3f0b9e5717bb292 + ReactCommon: 2905859f84a94a381bb0d8dd3921ccb1a0047cb8 ReactNativeART: 78edc68dd4a1e675338cd0cd113319cf3a65f2ab ReactNativeKeyboardInput: c37e26821519869993b3b61844350feb9177ff37 ReactNativeKeyboardTrackingView: 02137fac3b2ebd330d74fa54ead48b14750a2306 rn-extensions-share: 8db79372089567cbc5aefe8444869bbc808578d3 rn-fetch-blob: f065bb7ab7fb48dd002629f8bdcb0336602d3cba RNBootSplash: b3836aa90c5bec690c6cd3c9ab355fcf98d0fe1d - RNCAsyncStorage: cd7234ff15c010723ed7c499ae4eedc605eac1fd + RNCAsyncStorage: d059c3ee71738c39834a627476322a5a8cd5bf36 RNCMaskedView: 5a8ec07677aa885546a0d98da336457e2bea557f - RNDateTimePicker: 4bd49e09f91ca73d69119a9e1173b0d43b82f5e5 - RNDeviceInfo: e2102056bde3ad5d137fd029d8d431510a00486a + RNDateTimePicker: e386ff4ef3300964ed0cad97ce6f206e0effbfdb + RNDeviceInfo: ed8557a8bd6443cbc0ab5d375e6808a38a279744 RNFastImage: 35ae972d6727c84ee3f5c6897e07f84d0a3445e9 - RNFirebase: 37daa9a346d070f9f6ee1f3b4aaf4c8e3b1d5d1c + RNFBAnalytics: dae6d7b280ba61c96e1bbdd34aca3154388f025e + RNFBApp: 6fd8a7e757135d4168bf033a8812c241af7363a0 + RNFBCrashlytics: 88de72c2476b5868a892d9523b89b86c527c540e RNGestureHandler: 8f09cd560f8d533eb36da5a6c5a843af9f056b38 RNImageCropPicker: 38865ab4af1b0b2146ad66061196bc0184946855 RNLocalize: b6df30cc25ae736d37874f9bce13351db2f56796 - RNReanimated: 955cf4068714003d2f1a6e2bae3fb1118f359aff + RNReanimated: b5ccb50650ba06f6e749c7c329a1bc3ae0c88b43 RNRootView: 895a4813dedeaca82db2fa868ca1c333d790e494 - RNScreens: cf198f915f8a2bf163de94ca9f5bfc8d326c3706 + RNScreens: c526239bbe0e957b988dacc8d75ac94ec9cb19da RNUserDefaults: c421fd97ad06b35c16608c5d0fe675db353f632d - RNVectorIcons: 0bb4def82230be1333ddaeee9fcba45f0b288ed4 - SDWebImage: 48b88379b798fd1e4298f95bb25d2cdabbf4deb3 + RNVectorIcons: da6fe858f5a65d7bbc3379540a889b0b12aa5976 + SDWebImage: cf6922231e95550934da2ada0f20f2becf2ceba9 SDWebImageWebPCoder: 36f8f47bd9879a8aea6044765c1351120fd8e3a8 - TOCropViewController: e9da34f484aedd4e5d5a8ab230ba217cfe16c729 - UMAppLoader: ee77a072f9e15128f777ccd6d2d00f52ab4387e6 - UMBarCodeScannerInterface: 9dc692b87e5f20fe277fa57aa47f45d418c3cc6c - UMCameraInterface: 625878bbf2ba188a8548675e1d1d2e438a653e6d - UMConstantsInterface: 64060cf86587bcd90b1dbd804cceb6d377a308c1 - UMCore: eb200e882eadafcd31ead290770835fd648c0945 - UMFaceDetectorInterface: d6677d6ddc9ab95a0ca857aa7f8ba76656cc770f - UMFileSystemInterface: c70ea7147198b9807080f3597f26236be49b0165 - UMFontInterface: d9d3b27af698c5389ae9e20b99ef56a083f491fb - UMImageLoaderInterface: 14dd2c46c67167491effc9e91250e9510f12709e - UMPermissionsInterface: 5e83a9167c177e4a0f0a3539345983cc749efb3e - UMReactNativeAdapter: 126da3486c1a1f11945b649d557d6c2ebb9407b2 - UMSensorsInterface: 48941f70175e2975af1a9386c6d6cb16d8126805 - UMTaskManagerInterface: cb890c79c63885504ddc0efd7a7d01481760aca2 - Yoga: 3ebccbdd559724312790e7742142d062476b698e + TOCropViewController: 20a14b6a7a098308bf369e7c8d700dc983a974e6 + UMAppLoader: 61049c8d55590b74e9ae1d5429bf68d96b4a2528 + UMBarCodeScannerInterface: e5e4c87797d3d01214e25cd1618866caf5d4f17f + UMCameraInterface: 415ac060034edecacdbbaa739c223e3f276e0056 + UMConstantsInterface: 1a52f2d884c95e8829439da13e36b7669a1a8fb4 + UMCore: d98083b522b08c0a8ba3992bc263c624ae5d887c + UMFaceDetectorInterface: 67c6c82451338da01a4bc00ec46365a2a8ea9057 + UMFileSystemInterface: 303d696ede28102a7e11d111808bd2ed2c5eb62f + UMFontInterface: 6edf1ee8bc55d2030766f8cf0a7b20a5d5a913b0 + UMImageLoaderInterface: 9cdbf3bab6a513bddd88505cb2340fe02d6a11c0 + UMPermissionsInterface: 019170ad655f464e3f8d23d2a8bcbda2e645cde4 + UMReactNativeAdapter: 538efe92e781b5d7678cf95b34c46f2d0989a557 + UMSensorsInterface: cb5bf31d52c4349f0ff9e3c049bbe4df0d80d383 + UMTaskManagerInterface: 80653f25c55d9e6d79d6a0a65589fa213feaee11 + Yoga: d5bd05a2b6b94c52323745c2c2b64557c8c66f64 YogaKit: f782866e155069a2cca2517aafea43200b01fd5a -PODFILE CHECKSUM: 35d9478dd32cf502959b8efc14411ecf09c66c95 +PODFILE CHECKSUM: 55c04243097892160d63f79f3a23157165b7ac68 -COCOAPODS: 1.8.4 +COCOAPODS: 1.9.3 diff --git a/ios/Pods/Crashlytics/Crashlytics.framework/README b/ios/Pods/Crashlytics/Crashlytics.framework/README deleted file mode 100644 index 3ebf76719..000000000 --- a/ios/Pods/Crashlytics/Crashlytics.framework/README +++ /dev/null @@ -1 +0,0 @@ -We've now combined all our supported platforms into a single podspec. As a result, we moved our submit script to a new location for Cocoapods projects: ${PODS_ROOT}/Crashlytics/submit. To avoid breaking functionality that references the old location of the submit, we've placed this dummy script that calls to the correct location, while providing a helpful warning if it is invoked. This bridge for backwards compatibility will be removed in a future release, so please heed the warning! diff --git a/ios/Pods/Crashlytics/Crashlytics.framework/submit b/ios/Pods/Crashlytics/Crashlytics.framework/submit deleted file mode 100755 index b7de4e377..000000000 --- a/ios/Pods/Crashlytics/Crashlytics.framework/submit +++ /dev/null @@ -1,6 +0,0 @@ -if [[ -z $PODS_ROOT ]]; then -echo "error: The submit binary delivered by cocoapods is in a new location, under '$"{"PODS_ROOT"}"/Crashlytics/submit'. This script was put in place for backwards compatibility, but it relies on PODS_ROOT, which does not have a value in your current setup. Please update the path to the submit binary to fix this issue." -else -echo "warning: The submit script is now located at '$"{"PODS_ROOT"}"/Crashlytics/submit'. To remove this warning, update your path to point to this new location." -sh "${PODS_ROOT}/Crashlytics/submit" "$@" -fi diff --git a/ios/Pods/Crashlytics/README.md b/ios/Pods/Crashlytics/README.md deleted file mode 100644 index 996af5078..000000000 --- a/ios/Pods/Crashlytics/README.md +++ /dev/null @@ -1,23 +0,0 @@ - -# Crashlytics - -## Overview - -[Crashlytics](https://firebase.google.com/docs/crashlytics/get-started?platform=ios) offers the most powerful, yet lightest weight crash reporting solution for iOS. - - -## Setup - -To start using Crashlytics, there are two options: - -1) The recommended way is to go to the [Firebase Crashlytics Docs](https://firebase.google.com/docs/crashlytics/get-started?platform=ios) and follow the directions there. - -2) If you aren't using Firebase yet, go to [Fabric Kits](https://fabric.io/kits), and follow the directions for Crashlytics. - - -## Resources - -* [API Reference](https://firebase.google.com/docs/reference/ios/crashlytics/api/reference/Classes) -* [Forums](https://stackoverflow.com/questions/tagged/google-fabric) -* [Website](https://firebase.google.com/docs/crashlytics) -* Follow us on Twitter: [@crashlytics](https://twitter.com/crashlytics) diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Crashlytics b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Crashlytics deleted file mode 100755 index 214fb9051..000000000 Binary files a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Crashlytics and /dev/null differ diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/ANSCompatibility.h b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/ANSCompatibility.h deleted file mode 100644 index 6ec011d93..000000000 --- a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/ANSCompatibility.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// ANSCompatibility.h -// AnswersKit -// -// Copyright (c) 2015 Crashlytics, Inc. All rights reserved. -// - -#pragma once - -#if !__has_feature(nullability) -#define nonnull -#define nullable -#define _Nullable -#define _Nonnull -#endif - -#ifndef NS_ASSUME_NONNULL_BEGIN -#define NS_ASSUME_NONNULL_BEGIN -#endif - -#ifndef NS_ASSUME_NONNULL_END -#define NS_ASSUME_NONNULL_END -#endif - -#if __has_feature(objc_generics) -#define ANS_GENERIC_NSARRAY(type) NSArray<type> -#define ANS_GENERIC_NSDICTIONARY(key_type,object_key) NSDictionary<key_type, object_key> -#else -#define ANS_GENERIC_NSARRAY(type) NSArray -#define ANS_GENERIC_NSDICTIONARY(key_type,object_key) NSDictionary -#endif diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/Answers.h b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/Answers.h deleted file mode 100644 index 8deacbee5..000000000 --- a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/Answers.h +++ /dev/null @@ -1,210 +0,0 @@ -// -// Answers.h -// Crashlytics -// -// Copyright (c) 2015 Crashlytics, Inc. All rights reserved. -// - -#import <Foundation/Foundation.h> -#import "ANSCompatibility.h" - -NS_ASSUME_NONNULL_BEGIN - -/** - * This class exposes the Answers Events API, allowing you to track key - * user user actions and metrics in your app. - */ -@interface Answers : NSObject - -/** - * Log a Sign Up event to see users signing up for your app in real-time, understand how - * many users are signing up with different methods and their success rate signing up. - * - * @param signUpMethodOrNil The method by which a user logged in, e.g. Twitter or Digits. - * @param signUpSucceededOrNil The ultimate success or failure of the login - * @param customAttributesOrNil A dictionary of custom attributes to associate with this event. - */ -+ (void)logSignUpWithMethod:(nullable NSString *)signUpMethodOrNil - success:(nullable NSNumber *)signUpSucceededOrNil - customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; - -/** - * Log an Log In event to see users logging into your app in real-time, understand how many - * users are logging in with different methods and their success rate logging into your app. - * - * @param loginMethodOrNil The method by which a user logged in, e.g. email, Twitter or Digits. - * @param loginSucceededOrNil The ultimate success or failure of the login - * @param customAttributesOrNil A dictionary of custom attributes to associate with this event. - */ -+ (void)logLoginWithMethod:(nullable NSString *)loginMethodOrNil - success:(nullable NSNumber *)loginSucceededOrNil - customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; - -/** - * Log a Share event to see users sharing from your app in real-time, letting you - * understand what content they're sharing from the type or genre down to the specific id. - * - * @param shareMethodOrNil The method by which a user shared, e.g. email, Twitter, SMS. - * @param contentNameOrNil The human readable name for this piece of content. - * @param contentTypeOrNil The type of content shared. - * @param contentIdOrNil The unique identifier for this piece of content. Useful for finding the top shared item. - * @param customAttributesOrNil A dictionary of custom attributes to associate with this event. - */ -+ (void)logShareWithMethod:(nullable NSString *)shareMethodOrNil - contentName:(nullable NSString *)contentNameOrNil - contentType:(nullable NSString *)contentTypeOrNil - contentId:(nullable NSString *)contentIdOrNil - customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; - -/** - * Log an Invite Event to track how users are inviting other users into - * your application. - * - * @param inviteMethodOrNil The method of invitation, e.g. GameCenter, Twitter, email. - * @param customAttributesOrNil A dictionary of custom attributes to associate with this event. - */ -+ (void)logInviteWithMethod:(nullable NSString *)inviteMethodOrNil - customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; - -/** - * Log a Purchase event to see your revenue in real-time, understand how many users are making purchases, see which - * items are most popular, and track plenty of other important purchase-related metrics. - * - * @param itemPriceOrNil The purchased item's price. - * @param currencyOrNil The ISO4217 currency code. Example: USD - * @param purchaseSucceededOrNil Was the purchase successful or unsuccessful - * @param itemNameOrNil The human-readable form of the item's name. Example: - * @param itemTypeOrNil The type, or genre of the item. Example: Song - * @param itemIdOrNil The machine-readable, unique item identifier Example: SKU - * @param customAttributesOrNil A dictionary of custom attributes to associate with this purchase. - */ -+ (void)logPurchaseWithPrice:(nullable NSDecimalNumber *)itemPriceOrNil - currency:(nullable NSString *)currencyOrNil - success:(nullable NSNumber *)purchaseSucceededOrNil - itemName:(nullable NSString *)itemNameOrNil - itemType:(nullable NSString *)itemTypeOrNil - itemId:(nullable NSString *)itemIdOrNil - customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; - -/** - * Log a Level Start Event to track where users are in your game. - * - * @param levelNameOrNil The level name - * @param customAttributesOrNil A dictionary of custom attributes to associate with this level start event. - */ -+ (void)logLevelStart:(nullable NSString *)levelNameOrNil - customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; - -/** - * Log a Level End event to track how users are completing levels in your game. - * - * @param levelNameOrNil The name of the level completed, E.G. "1" or "Training" - * @param scoreOrNil The score the user completed the level with. - * @param levelCompletedSuccesfullyOrNil A boolean representing whether or not the level was completed successfully. - * @param customAttributesOrNil A dictionary of custom attributes to associate with this event. - */ -+ (void)logLevelEnd:(nullable NSString *)levelNameOrNil - score:(nullable NSNumber *)scoreOrNil - success:(nullable NSNumber *)levelCompletedSuccesfullyOrNil - customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; - -/** - * Log an Add to Cart event to see users adding items to a shopping cart in real-time, understand how - * many users start the purchase flow, see which items are most popular, and track plenty of other important - * purchase-related metrics. - * - * @param itemPriceOrNil The purchased item's price. - * @param currencyOrNil The ISO4217 currency code. Example: USD - * @param itemNameOrNil The human-readable form of the item's name. Example: - * @param itemTypeOrNil The type, or genre of the item. Example: Song - * @param itemIdOrNil The machine-readable, unique item identifier Example: SKU - * @param customAttributesOrNil A dictionary of custom attributes to associate with this event. - */ -+ (void)logAddToCartWithPrice:(nullable NSDecimalNumber *)itemPriceOrNil - currency:(nullable NSString *)currencyOrNil - itemName:(nullable NSString *)itemNameOrNil - itemType:(nullable NSString *)itemTypeOrNil - itemId:(nullable NSString *)itemIdOrNil - customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; - -/** - * Log a Start Checkout event to see users moving through the purchase funnel in real-time, understand how many - * users are doing this and how much they're spending per checkout, and see how it related to other important - * purchase-related metrics. - * - * @param totalPriceOrNil The total price of the cart. - * @param currencyOrNil The ISO4217 currency code. Example: USD - * @param itemCountOrNil The number of items in the cart. - * @param customAttributesOrNil A dictionary of custom attributes to associate with this event. - */ -+ (void)logStartCheckoutWithPrice:(nullable NSDecimalNumber *)totalPriceOrNil - currency:(nullable NSString *)currencyOrNil - itemCount:(nullable NSNumber *)itemCountOrNil - customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; - -/** - * Log a Rating event to see users rating content within your app in real-time and understand what - * content is most engaging, from the type or genre down to the specific id. - * - * @param ratingOrNil The integer rating given by the user. - * @param contentNameOrNil The human readable name for this piece of content. - * @param contentTypeOrNil The type of content shared. - * @param contentIdOrNil The unique identifier for this piece of content. Useful for finding the top shared item. - * @param customAttributesOrNil A dictionary of custom attributes to associate with this event. - */ -+ (void)logRating:(nullable NSNumber *)ratingOrNil - contentName:(nullable NSString *)contentNameOrNil - contentType:(nullable NSString *)contentTypeOrNil - contentId:(nullable NSString *)contentIdOrNil - customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; - -/** - * Log a Content View event to see users viewing content within your app in real-time and - * understand what content is most engaging, from the type or genre down to the specific id. - * - * @param contentNameOrNil The human readable name for this piece of content. - * @param contentTypeOrNil The type of content shared. - * @param contentIdOrNil The unique identifier for this piece of content. Useful for finding the top shared item. - * @param customAttributesOrNil A dictionary of custom attributes to associate with this event. - */ -+ (void)logContentViewWithName:(nullable NSString *)contentNameOrNil - contentType:(nullable NSString *)contentTypeOrNil - contentId:(nullable NSString *)contentIdOrNil - customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; - -/** - * Log a Search event allows you to see users searching within your app in real-time and understand - * exactly what they're searching for. - * - * @param queryOrNil The user's query. - * @param customAttributesOrNil A dictionary of custom attributes to associate with this event. - */ -+ (void)logSearchWithQuery:(nullable NSString *)queryOrNil - customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; - -/** - * Log a Custom Event to see user actions that are uniquely important for your app in real-time, to see how often - * they're performing these actions with breakdowns by different categories you add. Use a human-readable name for - * the name of the event, since this is how the event will appear in Answers. - * - * @param eventName The human-readable name for the event. - * @param customAttributesOrNil A dictionary of custom attributes to associate with this event. Attribute keys - * must be <code>NSString</code> and values must be <code>NSNumber</code> or <code>NSString</code>. - * @discussion How we treat <code>NSNumbers</code>: - * We will provide information about the distribution of values over time. - * - * How we treat <code>NSStrings</code>: - * NSStrings are used as categorical data, allowing comparison across different category values. - * Strings are limited to a maximum length of 100 characters, attributes over this length will be - * truncated. - * - * When tracking the Tweet views to better understand user engagement, sending the tweet's length - * and the type of media present in the tweet allows you to track how tweet length and the type of media influence - * engagement. - */ -+ (void)logCustomEventWithName:(NSString *)eventName - customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil; - -@end - -NS_ASSUME_NONNULL_END diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSAttributes.h b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSAttributes.h deleted file mode 100644 index 1526b0dca..000000000 --- a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSAttributes.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// CLSAttributes.h -// Crashlytics -// -// Copyright (c) 2015 Crashlytics, Inc. All rights reserved. -// - -#pragma once - -#define CLS_DEPRECATED(x) __attribute__ ((deprecated(x))) - -#if !__has_feature(nullability) - #define nonnull - #define nullable - #define _Nullable - #define _Nonnull -#endif - -#ifndef NS_ASSUME_NONNULL_BEGIN - #define NS_ASSUME_NONNULL_BEGIN -#endif - -#ifndef NS_ASSUME_NONNULL_END - #define NS_ASSUME_NONNULL_END -#endif - -#if __has_feature(objc_generics) - #define CLS_GENERIC_NSARRAY(type) NSArray<type> - #define CLS_GENERIC_NSDICTIONARY(key_type,object_key) NSDictionary<key_type, object_key> -#else - #define CLS_GENERIC_NSARRAY(type) NSArray - #define CLS_GENERIC_NSDICTIONARY(key_type,object_key) NSDictionary -#endif diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSLogging.h b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSLogging.h deleted file mode 100644 index 59590d546..000000000 --- a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSLogging.h +++ /dev/null @@ -1,64 +0,0 @@ -// -// CLSLogging.h -// Crashlytics -// -// Copyright (c) 2015 Crashlytics, Inc. All rights reserved. -// -#ifdef __OBJC__ -#import "CLSAttributes.h" -#import <Foundation/Foundation.h> - -NS_ASSUME_NONNULL_BEGIN -#endif - - - -/** - * - * The CLS_LOG macro provides as easy way to gather more information in your log messages that are - * sent with your crash data. CLS_LOG prepends your custom log message with the function name and - * line number where the macro was used. If your app was built with the DEBUG preprocessor macro - * defined CLS_LOG uses the CLSNSLog function which forwards your log message to NSLog and CLSLog. - * If the DEBUG preprocessor macro is not defined CLS_LOG uses CLSLog only. - * - * Example output: - * -[AppDelegate login:] line 134 $ login start - * - * If you would like to change this macro, create a new header file, unset our define and then define - * your own version. Make sure this new header file is imported after the Crashlytics header file. - * - * #undef CLS_LOG - * #define CLS_LOG(__FORMAT__, ...) CLSNSLog... - * - **/ -#ifdef __OBJC__ -#ifdef DEBUG -#define CLS_LOG(__FORMAT__, ...) CLSNSLog((@"%s line %d $ " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__) -#else -#define CLS_LOG(__FORMAT__, ...) CLSLog((@"%s line %d $ " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__) -#endif -#endif - -/** - * - * Add logging that will be sent with your crash data. This logging will not show up in the system.log - * and will only be visible in your Crashlytics dashboard. - * - **/ - -#ifdef __OBJC__ -OBJC_EXTERN void CLSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2); -OBJC_EXTERN void CLSLogv(NSString *format, va_list ap) NS_FORMAT_FUNCTION(1,0); - -/** - * - * Add logging that will be sent with your crash data. This logging will show up in the system.log - * and your Crashlytics dashboard. It is not recommended for Release builds. - * - **/ -OBJC_EXTERN void CLSNSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2); -OBJC_EXTERN void CLSNSLogv(NSString *format, va_list ap) NS_FORMAT_FUNCTION(1,0); - - -NS_ASSUME_NONNULL_END -#endif diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSReport.h b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSReport.h deleted file mode 100644 index a8ff3b0b9..000000000 --- a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSReport.h +++ /dev/null @@ -1,103 +0,0 @@ -// -// CLSReport.h -// Crashlytics -// -// Copyright (c) 2015 Crashlytics, Inc. All rights reserved. -// - -#import <Foundation/Foundation.h> -#import "CLSAttributes.h" - -NS_ASSUME_NONNULL_BEGIN - -/** - * The CLSCrashReport protocol is deprecated. See the CLSReport class and the CrashyticsDelegate changes for details. - **/ -@protocol CLSCrashReport <NSObject> - -@property (nonatomic, copy, readonly) NSString *identifier; -@property (nonatomic, copy, readonly) NSDictionary *customKeys; -@property (nonatomic, copy, readonly) NSString *bundleVersion; -@property (nonatomic, copy, readonly) NSString *bundleShortVersionString; -@property (nonatomic, readonly, nullable) NSDate *crashedOnDate; -@property (nonatomic, copy, readonly) NSString *OSVersion; -@property (nonatomic, copy, readonly) NSString *OSBuildVersion; - -@end - -/** - * The CLSReport exposes an interface to the phsyical report that Crashlytics has created. You can - * use this class to get information about the event, and can also set some values after the - * event has occurred. - **/ -@interface CLSReport : NSObject <CLSCrashReport> - -- (instancetype)init NS_UNAVAILABLE; -+ (instancetype)new NS_UNAVAILABLE; - -/** - * Returns the session identifier for the report. - **/ -@property (nonatomic, copy, readonly) NSString *identifier; - -/** - * Returns the custom key value data for the report. - **/ -@property (nonatomic, copy, readonly) NSDictionary *customKeys; - -/** - * Returns the CFBundleVersion of the application that generated the report. - **/ -@property (nonatomic, copy, readonly) NSString *bundleVersion; - -/** - * Returns the CFBundleShortVersionString of the application that generated the report. - **/ -@property (nonatomic, copy, readonly) NSString *bundleShortVersionString; - -/** - * Returns the date that the report was created. - **/ -@property (nonatomic, copy, readonly) NSDate *dateCreated; - -/** - * Returns the os version that the application crashed on. - **/ -@property (nonatomic, copy, readonly) NSString *OSVersion; - -/** - * Returns the os build version that the application crashed on. - **/ -@property (nonatomic, copy, readonly) NSString *OSBuildVersion; - -/** - * Returns YES if the report contains any crash information, otherwise returns NO. - **/ -@property (nonatomic, assign, readonly) BOOL isCrash; - -/** - * You can use this method to set, after the event, additional custom keys. The rules - * and semantics for this method are the same as those documented in Crashlytics.h. Be aware - * that the maximum size and count of custom keys is still enforced, and you can overwrite keys - * and/or cause excess keys to be deleted by using this method. - **/ -- (void)setObjectValue:(nullable id)value forKey:(NSString *)key; - -/** - * Record an application-specific user identifier. See Crashlytics.h for details. - **/ -@property (nonatomic, copy, nullable) NSString * userIdentifier; - -/** - * Record a user name. See Crashlytics.h for details. - **/ -@property (nonatomic, copy, nullable) NSString * userName; - -/** - * Record a user email. See Crashlytics.h for details. - **/ -@property (nonatomic, copy, nullable) NSString * userEmail; - -@end - -NS_ASSUME_NONNULL_END diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSStackFrame.h b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSStackFrame.h deleted file mode 100644 index cdb5596cc..000000000 --- a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSStackFrame.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// CLSStackFrame.h -// Crashlytics -// -// Copyright 2015 Crashlytics, Inc. All rights reserved. -// - -#import <Foundation/Foundation.h> -#import "CLSAttributes.h" - -NS_ASSUME_NONNULL_BEGIN - -/** - * - * This class is used in conjunction with -[Crashlytics recordCustomExceptionName:reason:frameArray:] to - * record information about non-ObjC/C++ exceptions. All information included here will be displayed - * in the Crashlytics UI, and can influence crash grouping. Be particularly careful with the use of the - * address property. If set, Crashlytics will attempt symbolication and could overwrite other properities - * in the process. - * - **/ -@interface CLSStackFrame : NSObject - -+ (instancetype)stackFrame; -+ (instancetype)stackFrameWithAddress:(NSUInteger)address; -+ (instancetype)stackFrameWithSymbol:(NSString *)symbol; - -@property (nonatomic, copy, nullable) NSString *symbol; -@property (nonatomic, copy, nullable) NSString *rawSymbol; -@property (nonatomic, copy, nullable) NSString *library; -@property (nonatomic, copy, nullable) NSString *fileName; -@property (nonatomic, assign) uint32_t lineNumber; -@property (nonatomic, assign) uint64_t offset; -@property (nonatomic, assign) uint64_t address; - -@end - -NS_ASSUME_NONNULL_END diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/Crashlytics.h b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/Crashlytics.h deleted file mode 100644 index 7104ca812..000000000 --- a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/Crashlytics.h +++ /dev/null @@ -1,288 +0,0 @@ -// -// Crashlytics.h -// Crashlytics -// -// Copyright (c) 2015 Crashlytics, Inc. All rights reserved. -// - -#import <Foundation/Foundation.h> - -#import "CLSAttributes.h" -#import "CLSLogging.h" -#import "CLSReport.h" -#import "CLSStackFrame.h" -#import "Answers.h" - -NS_ASSUME_NONNULL_BEGIN - -@protocol CrashlyticsDelegate; - -/** - * Crashlytics. Handles configuration and initialization of Crashlytics. - * - * Note: The Crashlytics class cannot be subclassed. If this is causing you pain for - * testing, we suggest using either a wrapper class or a protocol extension. - */ -@interface Crashlytics : NSObject - -@property (nonatomic, readonly, copy) NSString *APIKey; -@property (nonatomic, readonly, copy) NSString *version; -@property (nonatomic, assign) BOOL debugMode; - -/** - * - * The delegate can be used to influence decisions on reporting and behavior, as well as reacting - * to previous crashes. - * - * Make certain that the delegate is setup before starting Crashlytics with startWithAPIKey:... or - * via +[Fabric with:...]. Failure to do will result in missing any delegate callbacks that occur - * synchronously during start. - * - **/ -@property (nonatomic, assign, nullable) id <CrashlyticsDelegate> delegate; - -/** - * The recommended way to install Crashlytics into your application is to place a call to +startWithAPIKey: - * in your -application:didFinishLaunchingWithOptions: or -applicationDidFinishLaunching: - * method. - * - * Note: Starting with 3.0, the submission process has been significantly improved. The delay parameter - * is no longer required to throttle submissions on launch, performance will be great without it. - * - * @param apiKey The Crashlytics API Key for this app - * - * @return The singleton Crashlytics instance - */ -+ (Crashlytics *)startWithAPIKey:(NSString *)apiKey; -+ (Crashlytics *)startWithAPIKey:(NSString *)apiKey afterDelay:(NSTimeInterval)delay CLS_DEPRECATED("Crashlytics no longer needs or uses the delay parameter. Please use +startWithAPIKey: instead."); - -/** - * If you need the functionality provided by the CrashlyticsDelegate protocol, you can use - * these convenience methods to activate the framework and set the delegate in one call. - * - * @param apiKey The Crashlytics API Key for this app - * @param delegate A delegate object which conforms to CrashlyticsDelegate. - * - * @return The singleton Crashlytics instance - */ -+ (Crashlytics *)startWithAPIKey:(NSString *)apiKey delegate:(nullable id<CrashlyticsDelegate>)delegate; -+ (Crashlytics *)startWithAPIKey:(NSString *)apiKey delegate:(nullable id<CrashlyticsDelegate>)delegate afterDelay:(NSTimeInterval)delay CLS_DEPRECATED("Crashlytics no longer needs or uses the delay parameter. Please use +startWithAPIKey:delegate: instead."); - -/** - * Access the singleton Crashlytics instance. - * - * @return The singleton Crashlytics instance - */ -+ (Crashlytics *)sharedInstance; - -/** - * The easiest way to cause a crash - great for testing! - */ -- (void)crash; - -/** - * The easiest way to cause a crash with an exception - great for testing. - */ -- (void)throwException; - -/** - * Specify a user identifier which will be visible in the Crashlytics UI. - * - * Many of our customers have requested the ability to tie crashes to specific end-users of their - * application in order to facilitate responses to support requests or permit the ability to reach - * out for more information. We allow you to specify up to three separate values for display within - * the Crashlytics UI - but please be mindful of your end-user's privacy. - * - * We recommend specifying a user identifier - an arbitrary string that ties an end-user to a record - * in your system. This could be a database id, hash, or other value that is meaningless to a - * third-party observer but can be indexed and queried by you. - * - * Optionally, you may also specify the end-user's name or username, as well as email address if you - * do not have a system that works well with obscured identifiers. - * - * Pursuant to our EULA, this data is transferred securely throughout our system and we will not - * disseminate end-user data unless required to by law. That said, if you choose to provide end-user - * contact information, we strongly recommend that you disclose this in your application's privacy - * policy. Data privacy is of our utmost concern. - * - * @param identifier An arbitrary user identifier string which ties an end-user to a record in your system. - */ -- (void)setUserIdentifier:(nullable NSString *)identifier; - -/** - * Specify a user name which will be visible in the Crashlytics UI. - * Please be mindful of your end-user's privacy and see if setUserIdentifier: can fulfil your needs. - * @see setUserIdentifier: - * - * @param name An end user's name. - */ -- (void)setUserName:(nullable NSString *)name; - -/** - * Specify a user email which will be visible in the Crashlytics UI. - * Please be mindful of your end-user's privacy and see if setUserIdentifier: can fulfil your needs. - * - * @see setUserIdentifier: - * - * @param email An end user's email address. - */ -- (void)setUserEmail:(nullable NSString *)email; - -+ (void)setUserIdentifier:(nullable NSString *)identifier CLS_DEPRECATED("Please access this method via +sharedInstance"); -+ (void)setUserName:(nullable NSString *)name CLS_DEPRECATED("Please access this method via +sharedInstance"); -+ (void)setUserEmail:(nullable NSString *)email CLS_DEPRECATED("Please access this method via +sharedInstance"); - -/** - * Set a value for a for a key to be associated with your crash data which will be visible in the Crashlytics UI. - * When setting an object value, the object is converted to a string. This is typically done by calling - * -[NSObject description]. - * - * @param value The object to be associated with the key - * @param key The key with which to associate the value - */ -- (void)setObjectValue:(nullable id)value forKey:(NSString *)key; - -/** - * Set an int value for a key to be associated with your crash data which will be visible in the Crashlytics UI. - * - * @param value The integer value to be set - * @param key The key with which to associate the value - */ -- (void)setIntValue:(int)value forKey:(NSString *)key; - -/** - * Set an BOOL value for a key to be associated with your crash data which will be visible in the Crashlytics UI. - * - * @param value The BOOL value to be set - * @param key The key with which to associate the value - */ -- (void)setBoolValue:(BOOL)value forKey:(NSString *)key; - -/** - * Set an float value for a key to be associated with your crash data which will be visible in the Crashlytics UI. - * - * @param value The float value to be set - * @param key The key with which to associate the value - */ -- (void)setFloatValue:(float)value forKey:(NSString *)key; - -+ (void)setObjectValue:(nullable id)value forKey:(NSString *)key CLS_DEPRECATED("Please access this method via +sharedInstance"); -+ (void)setIntValue:(int)value forKey:(NSString *)key CLS_DEPRECATED("Please access this method via +sharedInstance"); -+ (void)setBoolValue:(BOOL)value forKey:(NSString *)key CLS_DEPRECATED("Please access this method via +sharedInstance"); -+ (void)setFloatValue:(float)value forKey:(NSString *)key CLS_DEPRECATED("Please access this method via +sharedInstance"); - -/** - * This method can be used to record a single exception structure in a report. This is particularly useful - * when your code interacts with non-native languages like Lua, C#, or Javascript. This call can be - * expensive and should only be used shortly before process termination. This API is not intended be to used - * to log NSException objects. All safely-reportable NSExceptions are automatically captured by - * Crashlytics. - * - * @param name The name of the custom exception - * @param reason The reason this exception occurred - * @param frameArray An array of CLSStackFrame objects - */ -- (void)recordCustomExceptionName:(NSString *)name reason:(nullable NSString *)reason frameArray:(CLS_GENERIC_NSARRAY(CLSStackFrame *) *)frameArray; - -/** - * - * This allows you to record a non-fatal event, described by an NSError object. These events will be grouped and - * displayed similarly to crashes. Keep in mind that this method can be expensive. Also, the total number of - * NSErrors that can be recorded during your app's life-cycle is limited by a fixed-size circular buffer. If the - * buffer is overrun, the oldest data is dropped. Errors are relayed to Crashlytics on a subsequent launch - * of your application. - * - * You can also use the -recordError:withAdditionalUserInfo: to include additional context not represented - * by the NSError instance itself. - * - **/ -- (void)recordError:(NSError *)error; -- (void)recordError:(NSError *)error withAdditionalUserInfo:(nullable CLS_GENERIC_NSDICTIONARY(NSString *, id) *)userInfo; - -- (void)logEvent:(NSString *)eventName CLS_DEPRECATED("Please refer to Answers +logCustomEventWithName:"); -- (void)logEvent:(NSString *)eventName attributes:(nullable NSDictionary *) attributes CLS_DEPRECATED("Please refer to Answers +logCustomEventWithName:"); -+ (void)logEvent:(NSString *)eventName CLS_DEPRECATED("Please refer to Answers +logCustomEventWithName:"); -+ (void)logEvent:(NSString *)eventName attributes:(nullable NSDictionary *) attributes CLS_DEPRECATED("Please refer to Answers +logCustomEventWithName:"); - -@end - -/** - * - * The CrashlyticsDelegate protocol provides a mechanism for your application to take - * action on events that occur in the Crashlytics crash reporting system. You can make - * use of these calls by assigning an object to the Crashlytics' delegate property directly, - * or through the convenience +startWithAPIKey:delegate: method. - * - */ -@protocol CrashlyticsDelegate <NSObject> -@optional - - -- (void)crashlyticsDidDetectCrashDuringPreviousExecution:(Crashlytics *)crashlytics CLS_DEPRECATED("Please refer to -crashlyticsDidDetectReportForLastExecution:"); -- (void)crashlytics:(Crashlytics *)crashlytics didDetectCrashDuringPreviousExecution:(id <CLSCrashReport>)crash CLS_DEPRECATED("Please refer to -crashlyticsDidDetectReportForLastExecution:"); - -/** - * - * Called when a Crashlytics instance has determined that the last execution of the - * application resulted in a saved report. This is called synchronously on Crashlytics - * initialization. Your delegate must invoke the completionHandler, but does not need to do so - * synchronously, or even on the main thread. Invoking completionHandler with NO will cause the - * detected report to be deleted and not submitted to Crashlytics. This is useful for - * implementing permission prompts, or other more-complex forms of logic around submitting crashes. - * - * Instead of using this method, you should try to make use of -crashlyticsDidDetectReportForLastExecution: - * if you can. - * - * @warning Failure to invoke the completionHandler will prevent submissions from being reported. Watch out. - * - * @warning Just implementing this delegate method will disable all forms of synchronous report submission. This can - * impact the reliability of reporting crashes very early in application launch. - * - * @param report The CLSReport object representing the last detected report - * @param completionHandler The completion handler to call when your logic has completed. - * - */ -- (void)crashlyticsDidDetectReportForLastExecution:(CLSReport *)report completionHandler:(void (^)(BOOL submit))completionHandler; - -/** - * - * Called when a Crashlytics instance has determined that the last execution of the - * application resulted in a saved report. This method differs from - * -crashlyticsDidDetectReportForLastExecution:completionHandler: in three important ways: - * - * - it is not called synchronously during initialization - * - it does not give you the ability to prevent the report from being submitted - * - the report object itself is immutable - * - * Thanks to these limitations, making use of this method does not impact reporting - * reliabilty in any way. - * - * @param report The read-only CLSReport object representing the last detected report - * - */ - -- (void)crashlyticsDidDetectReportForLastExecution:(CLSReport *)report; - -/** - * If your app is running on an OS that supports it (OS X 10.9+, iOS 7.0+), Crashlytics will submit - * most reports using out-of-process background networking operations. This results in a significant - * improvement in reliability of reporting, as well as power and performance wins for your users. - * If you don't want this functionality, you can disable by returning NO from this method. - * - * @warning Background submission is not supported for extensions on iOS or OS X. - * - * @param crashlytics The Crashlytics singleton instance - * - * @return Return NO if you don't want out-of-process background network operations. - * - */ -- (BOOL)crashlyticsCanUseBackgroundSessions:(Crashlytics *)crashlytics; - -@end - -/** - * `CrashlyticsKit` can be used as a parameter to `[Fabric with:@[CrashlyticsKit]];` in Objective-C. In Swift, use Crashlytics.sharedInstance() - */ -#define CrashlyticsKit [Crashlytics sharedInstance] - -NS_ASSUME_NONNULL_END diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Info.plist b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Info.plist deleted file mode 100644 index d86059be5..000000000 Binary files a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Info.plist and /dev/null differ diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Modules/module.modulemap b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Modules/module.modulemap deleted file mode 100644 index da0845e39..000000000 --- a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Modules/module.modulemap +++ /dev/null @@ -1,14 +0,0 @@ -framework module Crashlytics { - header "Crashlytics.h" - header "Answers.h" - header "ANSCompatibility.h" - header "CLSLogging.h" - header "CLSReport.h" - header "CLSStackFrame.h" - header "CLSAttributes.h" - - export * - - link "z" - link "c++" -} diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/run b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/run deleted file mode 100755 index 736cd2ff5..000000000 --- a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/run +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/sh - -# run -# -# Copyright (c) 2015 Crashlytics. All rights reserved. -# -# -# This script is meant to be run as a Run Script in the "Build Phases" section -# of your Xcode project. It sends debug symbols to symbolicate stacktraces, -# sends build events to track versions, and onboard apps for Crashlytics. -# -# This script calls upload-symbols twice: -# -# 1) First it calls upload-symbols synchronously in "validation" mode. If the -# script finds issues with the build environment, it will report errors to Xcode. -# In validation mode it exits before doing any time consuming work. -# -# 2) Then it calls upload-symbols in the background to actually send the build -# event and upload symbols. It does this in the background so that it doesn't -# slow down your builds. If an error happens here, you won't see it in Xcode. -# -# You can find the output for the background execution in Console.app, by -# searching for "upload-symbols". -# -# If you want verbose output, you can pass the --debug flag to this script -# - -# Figure out where we're being called from -DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) - -# If the first argument is specified without a dash, treat it as the Fabric API -# Key and add it as an argument -if [ -z "$1" ] || [[ $1 == -* ]]; then - API_KEY_ARG="" -else - API_KEY_ARG="-a $1"; shift -fi - -# If a second argument is specified without a dash, treat it as the Build Secret -# and add it as an argument -if [ -z "$1" ] || [[ $1 == -* ]]; then - BUILD_SECRET_ARG="" -else - BUILD_SECRET_ARG="-bs $1"; shift -fi - -# Build up the arguments list, passing through any flags added after the -# API Key and Build Secret -ARGUMENTS="$API_KEY_ARG $BUILD_SECRET_ARG $@" -VALIDATE_ARGUMENTS="$ARGUMENTS --build-phase --validate" -UPLOAD_ARGUMENTS="$ARGUMENTS --build-phase" - -# Quote the path to handle folders with special characters -COMMAND_PATH="\"$DIR/upload-symbols\" " - -# Ensure params are as expected, run in sync mode to validate, -# and cause a build error if validation fails -eval $COMMAND_PATH$VALIDATE_ARGUMENTS -return_code=$? - -if [[ $return_code != 0 ]]; then - exit $return_code -fi - -# Verification passed, convert and upload cSYMs in the background to prevent -# build delays -# -# Note: Validation is performed again at this step before upload -# -# Note: Output can still be found in Console.app, by searching for -# "upload-symbols" -# -eval $COMMAND_PATH$UPLOAD_ARGUMENTS > /dev/null 2>&1 & diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/submit b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/submit deleted file mode 100755 index 3fda5cff1..000000000 Binary files a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/submit and /dev/null differ diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/upload-symbols b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/upload-symbols deleted file mode 100755 index 5af65decc..000000000 Binary files a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/upload-symbols and /dev/null differ diff --git a/ios/Pods/Crashlytics/submit b/ios/Pods/Crashlytics/submit deleted file mode 100755 index 3fda5cff1..000000000 Binary files a/ios/Pods/Crashlytics/submit and /dev/null differ diff --git a/ios/Pods/Fabric/Fabric.framework/README b/ios/Pods/Fabric/Fabric.framework/README deleted file mode 100644 index 3b1fbe24e..000000000 --- a/ios/Pods/Fabric/Fabric.framework/README +++ /dev/null @@ -1 +0,0 @@ -We've now combined all our supported platforms into a single podspec. As a result, we moved our run script to a new location for Cocoapods projects: ${PODS_ROOT}/Fabric/run. To avoid breaking builds that reference the old location of the run script, we've placed this dummy script that calls to the correct location, while providing a helpful warning in Xcode if it is invoked. This bridge for backwards compatibility will be removed in a future release, so please heed the warning! diff --git a/ios/Pods/Fabric/Fabric.framework/run b/ios/Pods/Fabric/Fabric.framework/run deleted file mode 100755 index b9edd17f9..000000000 --- a/ios/Pods/Fabric/Fabric.framework/run +++ /dev/null @@ -1,6 +0,0 @@ -if [[ -z $PODS_ROOT ]]; then - echo "error: The run binary delivered by cocoapods is in a new location, under '$"{"PODS_ROOT"}"/Fabric/run'. This script was put in place for backwards compatibility, but it relies on PODS_ROOT, which does not have a value in your current setup. Please update the path to the run binary to fix this issue." -else - echo "warning: The run script is now located at '$"{"PODS_ROOT"}"/Fabric/run'. To remove this warning, update your Run Script Build Phase to point to this new location." - sh "${PODS_ROOT}/Fabric/run" "$@" -fi diff --git a/ios/Pods/Fabric/README.md b/ios/Pods/Fabric/README.md deleted file mode 100644 index e99ce8344..000000000 --- a/ios/Pods/Fabric/README.md +++ /dev/null @@ -1,27 +0,0 @@ - -# Fabric - -## Overview - -[Fabric](https://get.fabric.io) provides developers with the tools they need to build the best apps. Developed and maintained by Google and the team that built Crashlytics. - -For a full list of SDKs provided through Fabric visit [https://fabric.io/kits](https://fabric.io/kits). - -To follow the migration to Firebase, check out the [Fabric Roadmap](https://get.fabric.io/roadmap). - - -## Setup - -Fabric is a dependency for the Crashlytics SDK. To start using Crashlytics, there are two options: - -1) The recommended way is to go to the [Firebase Crashlytics Docs](https://firebase.google.com/docs/crashlytics/get-started?platform=ios) and follow the directions there. - -2) If you aren't using Firebase yet, go to [Fabric Kits](https://fabric.io/kits), and follow the directions for Crashlytics. - - -## Resources - -* [Documentation](https://docs.fabric.io/) -* [Forums](https://stackoverflow.com/questions/tagged/google-fabric) -* [Website](https://get.fabric.io) -* Follow us on Twitter: [@fabric](https://twitter.com/fabric) diff --git a/ios/Pods/Fabric/iOS/Fabric.framework/Fabric b/ios/Pods/Fabric/iOS/Fabric.framework/Fabric deleted file mode 100755 index aa394a3de..000000000 Binary files a/ios/Pods/Fabric/iOS/Fabric.framework/Fabric and /dev/null differ diff --git a/ios/Pods/Fabric/iOS/Fabric.framework/Headers/FABAttributes.h b/ios/Pods/Fabric/iOS/Fabric.framework/Headers/FABAttributes.h deleted file mode 100644 index 3a9355a7c..000000000 --- a/ios/Pods/Fabric/iOS/Fabric.framework/Headers/FABAttributes.h +++ /dev/null @@ -1,51 +0,0 @@ -// -// FABAttributes.h -// Fabric -// -// Copyright (C) 2015 Twitter, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -#pragma once - -#define FAB_UNAVAILABLE(x) __attribute__((unavailable(x))) - -#if !__has_feature(nullability) - #define nonnull - #define nullable - #define _Nullable - #define _Nonnull -#endif - -#ifndef NS_ASSUME_NONNULL_BEGIN - #define NS_ASSUME_NONNULL_BEGIN -#endif - -#ifndef NS_ASSUME_NONNULL_END - #define NS_ASSUME_NONNULL_END -#endif - - -/** - * The following macros are defined here to provide - * backwards compatability. If you are still using - * them you should migrate to the native nullability - * macros. - */ -#define fab_nullable nullable -#define fab_nonnull nonnull -#define FAB_NONNULL __fab_nonnull -#define FAB_NULLABLE __fab_nullable -#define FAB_START_NONNULL NS_ASSUME_NONNULL_BEGIN -#define FAB_END_NONNULL NS_ASSUME_NONNULL_END diff --git a/ios/Pods/Fabric/iOS/Fabric.framework/Headers/Fabric.h b/ios/Pods/Fabric/iOS/Fabric.framework/Headers/Fabric.h deleted file mode 100644 index ecbdb53b8..000000000 --- a/ios/Pods/Fabric/iOS/Fabric.framework/Headers/Fabric.h +++ /dev/null @@ -1,82 +0,0 @@ -// -// Fabric.h -// Fabric -// -// Copyright (C) 2015 Twitter, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -#import <Foundation/Foundation.h> -#import "FABAttributes.h" - -NS_ASSUME_NONNULL_BEGIN - -#if TARGET_OS_IPHONE -#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000 - #error "Fabric's minimum iOS version is 6.0" -#endif -#else -#if __MAC_OS_X_VERSION_MIN_REQUIRED < 1070 - #error "Fabric's minimum OS X version is 10.7" -#endif -#endif - -/** - * Fabric Base. Coordinates configuration and starts all provided kits. - */ -@interface Fabric : NSObject - -/** - * Initialize Fabric and all provided kits. Call this method within your App Delegate's `application:didFinishLaunchingWithOptions:` and provide the kits you wish to use. - * - * For example, in Objective-C: - * - * `[Fabric with:@[[Crashlytics class], [Twitter class], [Digits class], [MoPub class]]];` - * - * Swift: - * - * `Fabric.with([Crashlytics.self(), Twitter.self(), Digits.self(), MoPub.self()])` - * - * Only the first call to this method is honored. Subsequent calls are no-ops. - * - * @param kitClasses An array of kit Class objects - * - * @return Returns the shared Fabric instance. In most cases this can be ignored. - */ -+ (instancetype)with:(NSArray *)kitClasses; - -/** - * Returns the Fabric singleton object. - */ -+ (instancetype)sharedSDK; - -/** - * This BOOL enables or disables debug logging, such as kit version information. The default value is NO. - */ -@property (nonatomic, assign) BOOL debug; - -/** - * Unavailable. Use `+sharedSDK` to retrieve the shared Fabric instance. - */ -- (id)init FAB_UNAVAILABLE("Use +sharedSDK to retrieve the shared Fabric instance."); - -/** - * Unavailable. Use `+sharedSDK` to retrieve the shared Fabric instance. - */ -+ (instancetype)new FAB_UNAVAILABLE("Use +sharedSDK to retrieve the shared Fabric instance."); - -@end - -NS_ASSUME_NONNULL_END - diff --git a/ios/Pods/Fabric/iOS/Fabric.framework/Info.plist b/ios/Pods/Fabric/iOS/Fabric.framework/Info.plist deleted file mode 100644 index a617b035f..000000000 Binary files a/ios/Pods/Fabric/iOS/Fabric.framework/Info.plist and /dev/null differ diff --git a/ios/Pods/Fabric/iOS/Fabric.framework/Modules/module.modulemap b/ios/Pods/Fabric/iOS/Fabric.framework/Modules/module.modulemap deleted file mode 100644 index 2a312239d..000000000 --- a/ios/Pods/Fabric/iOS/Fabric.framework/Modules/module.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -framework module Fabric { - umbrella header "Fabric.h" - - export * - module * { export * } -} \ No newline at end of file diff --git a/ios/Pods/Fabric/iOS/Fabric.framework/run b/ios/Pods/Fabric/iOS/Fabric.framework/run deleted file mode 100755 index 736cd2ff5..000000000 --- a/ios/Pods/Fabric/iOS/Fabric.framework/run +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/sh - -# run -# -# Copyright (c) 2015 Crashlytics. All rights reserved. -# -# -# This script is meant to be run as a Run Script in the "Build Phases" section -# of your Xcode project. It sends debug symbols to symbolicate stacktraces, -# sends build events to track versions, and onboard apps for Crashlytics. -# -# This script calls upload-symbols twice: -# -# 1) First it calls upload-symbols synchronously in "validation" mode. If the -# script finds issues with the build environment, it will report errors to Xcode. -# In validation mode it exits before doing any time consuming work. -# -# 2) Then it calls upload-symbols in the background to actually send the build -# event and upload symbols. It does this in the background so that it doesn't -# slow down your builds. If an error happens here, you won't see it in Xcode. -# -# You can find the output for the background execution in Console.app, by -# searching for "upload-symbols". -# -# If you want verbose output, you can pass the --debug flag to this script -# - -# Figure out where we're being called from -DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) - -# If the first argument is specified without a dash, treat it as the Fabric API -# Key and add it as an argument -if [ -z "$1" ] || [[ $1 == -* ]]; then - API_KEY_ARG="" -else - API_KEY_ARG="-a $1"; shift -fi - -# If a second argument is specified without a dash, treat it as the Build Secret -# and add it as an argument -if [ -z "$1" ] || [[ $1 == -* ]]; then - BUILD_SECRET_ARG="" -else - BUILD_SECRET_ARG="-bs $1"; shift -fi - -# Build up the arguments list, passing through any flags added after the -# API Key and Build Secret -ARGUMENTS="$API_KEY_ARG $BUILD_SECRET_ARG $@" -VALIDATE_ARGUMENTS="$ARGUMENTS --build-phase --validate" -UPLOAD_ARGUMENTS="$ARGUMENTS --build-phase" - -# Quote the path to handle folders with special characters -COMMAND_PATH="\"$DIR/upload-symbols\" " - -# Ensure params are as expected, run in sync mode to validate, -# and cause a build error if validation fails -eval $COMMAND_PATH$VALIDATE_ARGUMENTS -return_code=$? - -if [[ $return_code != 0 ]]; then - exit $return_code -fi - -# Verification passed, convert and upload cSYMs in the background to prevent -# build delays -# -# Note: Validation is performed again at this step before upload -# -# Note: Output can still be found in Console.app, by searching for -# "upload-symbols" -# -eval $COMMAND_PATH$UPLOAD_ARGUMENTS > /dev/null 2>&1 & diff --git a/ios/Pods/Fabric/iOS/Fabric.framework/upload-symbols b/ios/Pods/Fabric/iOS/Fabric.framework/upload-symbols deleted file mode 100755 index a18d0b68f..000000000 Binary files a/ios/Pods/Fabric/iOS/Fabric.framework/upload-symbols and /dev/null differ diff --git a/ios/Pods/Fabric/run b/ios/Pods/Fabric/run deleted file mode 100755 index 736cd2ff5..000000000 --- a/ios/Pods/Fabric/run +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/sh - -# run -# -# Copyright (c) 2015 Crashlytics. All rights reserved. -# -# -# This script is meant to be run as a Run Script in the "Build Phases" section -# of your Xcode project. It sends debug symbols to symbolicate stacktraces, -# sends build events to track versions, and onboard apps for Crashlytics. -# -# This script calls upload-symbols twice: -# -# 1) First it calls upload-symbols synchronously in "validation" mode. If the -# script finds issues with the build environment, it will report errors to Xcode. -# In validation mode it exits before doing any time consuming work. -# -# 2) Then it calls upload-symbols in the background to actually send the build -# event and upload symbols. It does this in the background so that it doesn't -# slow down your builds. If an error happens here, you won't see it in Xcode. -# -# You can find the output for the background execution in Console.app, by -# searching for "upload-symbols". -# -# If you want verbose output, you can pass the --debug flag to this script -# - -# Figure out where we're being called from -DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) - -# If the first argument is specified without a dash, treat it as the Fabric API -# Key and add it as an argument -if [ -z "$1" ] || [[ $1 == -* ]]; then - API_KEY_ARG="" -else - API_KEY_ARG="-a $1"; shift -fi - -# If a second argument is specified without a dash, treat it as the Build Secret -# and add it as an argument -if [ -z "$1" ] || [[ $1 == -* ]]; then - BUILD_SECRET_ARG="" -else - BUILD_SECRET_ARG="-bs $1"; shift -fi - -# Build up the arguments list, passing through any flags added after the -# API Key and Build Secret -ARGUMENTS="$API_KEY_ARG $BUILD_SECRET_ARG $@" -VALIDATE_ARGUMENTS="$ARGUMENTS --build-phase --validate" -UPLOAD_ARGUMENTS="$ARGUMENTS --build-phase" - -# Quote the path to handle folders with special characters -COMMAND_PATH="\"$DIR/upload-symbols\" " - -# Ensure params are as expected, run in sync mode to validate, -# and cause a build error if validation fails -eval $COMMAND_PATH$VALIDATE_ARGUMENTS -return_code=$? - -if [[ $return_code != 0 ]]; then - exit $return_code -fi - -# Verification passed, convert and upload cSYMs in the background to prevent -# build delays -# -# Note: Validation is performed again at this step before upload -# -# Note: Output can still be found in Console.app, by searching for -# "upload-symbols" -# -eval $COMMAND_PATH$UPLOAD_ARGUMENTS > /dev/null 2>&1 & diff --git a/ios/Pods/Fabric/upload-symbols b/ios/Pods/Fabric/upload-symbols deleted file mode 100755 index a18d0b68f..000000000 Binary files a/ios/Pods/Fabric/upload-symbols and /dev/null differ diff --git a/ios/Pods/Firebase/README.md b/ios/Pods/Firebase/README.md index 1747cca7a..d778205ff 100644 --- a/ios/Pods/Firebase/README.md +++ b/ios/Pods/Firebase/README.md @@ -2,14 +2,20 @@ [![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) [![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![Actions Status][gh-abtesting-badge]][gh-actions] [![Actions Status][gh-auth-badge]][gh-actions] [![Actions Status][gh-core-badge]][gh-actions] +[![Actions Status][gh-crashlytics-badge]][gh-actions] +[![Actions Status][gh-database-badge]][gh-actions] [![Actions Status][gh-datatransport-badge]][gh-actions] [![Actions Status][gh-dynamiclinks-badge]][gh-actions] [![Actions Status][gh-firebasepod-badge]][gh-actions] [![Actions Status][gh-firestore-badge]][gh-actions] +[![Actions Status][gh-functions-badge]][gh-actions] +[![Actions Status][gh-inappmessaging-badge]][gh-actions] [![Actions Status][gh-interop-badge]][gh-actions] [![Actions Status][gh-messaging-badge]][gh-actions] +[![Actions Status][gh-remoteconfig-badge]][gh-actions] [![Actions Status][gh-storage-badge]][gh-actions] [![Actions Status][gh-symbolcollision-badge]][gh-actions] [![Actions Status][gh-zip-badge]][gh-actions] @@ -92,7 +98,7 @@ Instructions for installing binary frameworks via To develop Firebase software in this repository, ensure that you have at least the following software: - * Xcode 10.1 (or later) + * Xcode 10.3 (or later) * CocoaPods 1.7.2 (or later) * [CocoaPods generate](https://github.com/square/cocoapods-generate) @@ -123,6 +129,10 @@ Firestore has a self contained Xcode project. See See [AddNewPod.md](AddNewPod.md). +### Managing Headers and Imports + +See [HeadersImports.md](HeadersImports.md). + ### Code Formatting To ensure that the code is formatted consistently, run the script @@ -185,8 +195,16 @@ building and running the FirebaseAuth pod along with various samples and tests. ### Firebase Database -To run the Database Integration tests, make your database authentication rules -[public](https://firebase.google.com/docs/database/security/quickstart). +The Firebase Database Integration tests can be run against a locally running Database Emulator +or against a production instance. + +To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before +running the integration test. + +To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to +`Example/Database/App/GoogleService-Info.plist`. Your Security Rule must be set to +[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are +running. ### Firebase Storage @@ -274,14 +292,20 @@ Your use of Firebase is governed by the [Terms of Service for Firebase Services](https://firebase.google.com/terms/). [gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg [gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg [gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg +[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg [gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg [gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg [gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg [gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg +[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg +[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg [gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg [gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg +[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg [gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg [gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg [gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/ios/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector b/ios/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector index bb3a7cae8..8746d38f6 100755 Binary files a/ios/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector and b/ios/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector differ diff --git a/ios/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics b/ios/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics index 46030f0c4..e00c279a8 100755 Binary files a/ios/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics and b/ios/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics differ diff --git a/ios/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h b/ios/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h index be0b1faee..15b693c90 100755 --- a/ios/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h +++ b/ios/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h @@ -90,12 +90,10 @@ NS_SWIFT_NAME(Analytics) /// Must be called on the main thread. /// /// Note that screen reporting is enabled automatically and records the class name of the current -/// UIViewController for you without requiring you to call this method. If you implement -/// viewDidAppear in your UIViewController but do not call [super viewDidAppear:], that screen class -/// will not be automatically tracked. The class name can optionally be overridden by calling this -/// method in the viewDidAppear callback of your UIViewController and specifying the -/// screenClassOverride parameter. setScreenName:screenClass: must be called after -/// [super viewDidAppear:]. +/// UIViewController for you without requiring you to call this method. The class name can +/// optionally be overridden by calling this method in the viewDidAppear callback of your +/// UIViewController and specifying the screenClassOverride parameter. +/// `setScreenName:screenClass:` must be called after `[super viewDidAppear:]`. /// /// If your app does not use a distinct UIViewController for each screen, you should call this /// method and specify a distinct screenName each time a new screen is presented to the user. @@ -103,6 +101,9 @@ NS_SWIFT_NAME(Analytics) /// The screen name and screen class remain in effect until the current UIViewController changes or /// a new call to setScreenName:screenClass: is made. /// +/// @warning If you override `viewDidAppear:` in your UIViewController but do not call +/// `[super viewDidAppear:]`, that screen class will not be tracked. +/// /// @param screenName The name of the current screen. Should contain 1 to 100 characters. Set to nil /// to clear the current screen name. /// @param screenClassOverride The name of the screen class. Should contain 1 to 100 characters. By diff --git a/ios/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h b/ios/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h index 674f8b121..807b6159e 100755 --- a/ios/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h +++ b/ios/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h @@ -366,7 +366,6 @@ static NSString *const kFIREventViewItemList NS_SWIFT_NAME(AnalyticsEventViewIte /// <ul> /// <li>@c kFIRParameterSearchTerm (NSString)</li> /// </ul> -/// <b>This constant has been deprecated.</b> static NSString *const kFIREventViewSearchResults NS_SWIFT_NAME(AnalyticsEventViewSearchResults) = @"view_search_results"; diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.h similarity index 100% rename from ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h rename to ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.h diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m index 3a7d6de0e..07c786cb7 100644 --- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m +++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m @@ -14,7 +14,7 @@ #import <Foundation/Foundation.h> -#import "FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h" +#import "FirebaseCore/Sources/FIRAnalyticsConfiguration.h" #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-implementations" diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRApp.m b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRApp.m index 002f93c51..4dfbfa838 100644 --- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRApp.m +++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRApp.m @@ -22,14 +22,14 @@ #import <AppKit/AppKit.h> #endif -#import <FirebaseCore/FIRApp.h> +#import "FirebaseCore/Sources/Public/FIRApp.h" +#import "FirebaseCore/Sources/FIRAnalyticsConfiguration.h" #import "FirebaseCore/Sources/FIRBundleUtil.h" +#import "FirebaseCore/Sources/FIRComponentContainerInternal.h" +#import "FirebaseCore/Sources/FIRConfigurationInternal.h" #import "FirebaseCore/Sources/FIRVersion.h" -#import "FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h" #import "FirebaseCore/Sources/Private/FIRAppInternal.h" -#import "FirebaseCore/Sources/Private/FIRComponentContainerInternal.h" -#import "FirebaseCore/Sources/Private/FIRConfigurationInternal.h" #import "FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h" #import "FirebaseCore/Sources/Private/FIRLibrary.h" #import "FirebaseCore/Sources/Private/FIRLogger.h" @@ -166,7 +166,7 @@ static dispatch_once_t sFirebaseUserAgentOnceToken; if ([name isEqualToString:kFIRDefaultAppName]) { if (sDefaultApp) { - // The default app already exixts. Handle duplicate `configure` calls and return. + // The default app already exists. Handle duplicate `configure` calls and return. [self appWasConfiguredTwice:sDefaultApp usingOptions:options]; return; } diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppAssociationRegistration.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.h similarity index 100% rename from ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppAssociationRegistration.h rename to ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.h diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.m b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.m index e4125cd25..f3f812c74 100644 --- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.m +++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.m @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#import "FirebaseCore/Sources/Private/FIRAppAssociationRegistration.h" +#import "FirebaseCore/Sources/FIRAppAssociationRegistration.h" #import <objc/runtime.h> diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.m b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.m index b858f14c4..de2c29542 100644 --- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.m +++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.m @@ -49,15 +49,19 @@ + (BOOL)hasBundleIdentifierPrefix:(NSString *)bundleIdentifier inBundles:(NSArray *)bundles { for (NSBundle *bundle in bundles) { - // This allows app extensions that have the app's bundle as their prefix to pass this test. - NSString *applicationBundleIdentifier = - [GULAppEnvironmentUtil isAppExtension] - ? [self bundleIdentifierByRemovingLastPartFrom:bundle.bundleIdentifier] - : bundle.bundleIdentifier; - - if ([applicationBundleIdentifier isEqualToString:bundleIdentifier]) { + if ([bundle.bundleIdentifier isEqualToString:bundleIdentifier]) { return YES; } + + if ([GULAppEnvironmentUtil isAppExtension]) { + // A developer could be using the same `FIROptions` for both their app and extension. Since + // extensions have a suffix added to the bundleID, we consider a matching prefix as valid. + NSString *appBundleIDFromExtension = + [self bundleIdentifierByRemovingLastPartFrom:bundle.bundleIdentifier]; + if ([appBundleIDFromExtension isEqualToString:bundleIdentifier]) { + return YES; + } + } } return NO; } diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainerInternal.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentContainerInternal.h similarity index 93% rename from ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainerInternal.h rename to ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentContainerInternal.h index bf39bc6ce..82356060d 100644 --- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainerInternal.h +++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentContainerInternal.h @@ -15,8 +15,8 @@ */ #import <Foundation/Foundation.h> -#import <FirebaseCore/FIRComponent.h> -#import <FirebaseCore/FIRComponentContainer.h> +#import "FirebaseCore/Sources/Private/FIRComponent.h" +#import "FirebaseCore/Sources/Private/FIRComponentContainer.h" @class FIRApp; diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentType.m b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentType.m index 6410f2ea1..9051336a6 100644 --- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentType.m +++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentType.m @@ -16,7 +16,7 @@ #import "FirebaseCore/Sources/Private/FIRComponentType.h" -#import "FirebaseCore/Sources/Private/FIRComponentContainerInternal.h" +#import "FirebaseCore/Sources/FIRComponentContainerInternal.h" @implementation FIRComponentType diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfiguration.m b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfiguration.m index a1c9f4a2e..83b3248c3 100644 --- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfiguration.m +++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfiguration.m @@ -12,9 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -#import "FirebaseCore/Sources/Private/FIRConfigurationInternal.h" +#import "FirebaseCore/Sources/FIRConfigurationInternal.h" -#import "FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h" +#import "FirebaseCore/Sources/FIRAnalyticsConfiguration.h" extern void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel); diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfigurationInternal.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfigurationInternal.h new file mode 100644 index 000000000..ee1688670 --- /dev/null +++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfigurationInternal.h @@ -0,0 +1,29 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRConfiguration.h" + +@class FIRAnalyticsConfiguration; + +@interface FIRConfiguration () + +/** + * The configuration class for Firebase Analytics. This should be removed once the logic for + * enabling and disabling Analytics is moved to Analytics. + */ +@property(nonatomic, readwrite) FIRAnalyticsConfiguration *analyticsConfiguration; + +@end diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRCoreDiagnosticsConnector.m b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRCoreDiagnosticsConnector.m index 4981ca1b0..730dd6ef9 100644 --- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRCoreDiagnosticsConnector.m +++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRCoreDiagnosticsConnector.m @@ -16,12 +16,12 @@ #import "FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h" -#import <FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsInterop.h> +#import "Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h" -#import <FirebaseCore/FIROptions.h> +#import "FirebaseCore/Sources/Public/FIROptions.h" +#import "FirebaseCore/Sources/FIRDiagnosticsData.h" #import "FirebaseCore/Sources/Private/FIRAppInternal.h" -#import "FirebaseCore/Sources/Private/FIRDiagnosticsData.h" #import "FirebaseCore/Sources/Private/FIROptionsInternal.h" // Define the interop class symbol declared as an extern in FIRCoreDiagnosticsInterop. diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.h new file mode 100644 index 000000000..5b5ff8ad9 --- /dev/null +++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +#import "Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h" + +NS_ASSUME_NONNULL_BEGIN + +/** Implements the FIRCoreDiagnosticsData protocol to log diagnostics data. */ +@interface FIRDiagnosticsData : NSObject <FIRCoreDiagnosticsData> + +/** Inserts values into the diagnosticObjects dictionary if the value isn't nil. + * + * @param value The value to insert if it's not nil. + * @param key The key to associate it with. + */ +- (void)insertValue:(nullable id)value forKey:(NSString *)key; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.m b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.m index bbe0561d9..da9489d99 100644 --- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.m +++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.m @@ -14,9 +14,9 @@ * limitations under the License. */ -#import "FirebaseCore/Sources/Private/FIRDiagnosticsData.h" +#import "FirebaseCore/Sources/FIRDiagnosticsData.h" -#import <FirebaseCore/FIRApp.h> +#import "FirebaseCore/Sources/Public/FIRApp.h" #import "FirebaseCore/Sources/Private/FIRAppInternal.h" #import "FirebaseCore/Sources/Private/FIROptionsInternal.h" diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRLogger.m b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRLogger.m index ba2ee1f58..a749cbd94 100644 --- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRLogger.m +++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRLogger.m @@ -14,9 +14,9 @@ #import "FirebaseCore/Sources/Private/FIRLogger.h" -#import <FirebaseCore/FIRLoggerLevel.h> #import <GoogleUtilities/GULAppEnvironmentUtil.h> #import <GoogleUtilities/GULLogger.h> +#import "FirebaseCore/Sources/Public/FIRLoggerLevel.h" #import "FirebaseCore/Sources/FIRVersion.h" diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppInternal.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppInternal.h index ad1a186b9..9a0c943db 100644 --- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppInternal.h +++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppInternal.h @@ -14,8 +14,19 @@ * limitations under the License. */ +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIRApp.h" +#else #import <FirebaseCore/FIRApp.h> +#endif + +// The has_include is a workaround so the old IID needed for the FIS tests can find FIRErrors.h +#if __has_include("FirebaseCore/Sources/Private/FIRErrors.h") +#import "FirebaseCore/Sources/Private/FIRErrors.h" +#else #import <FirebaseCore/FIRErrors.h> +#endif @class FIRComponentContainer; @protocol FIRLibrary; diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainer.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainer.h index 8dfab9c10..db2bafef8 100644 --- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainer.h +++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainer.h @@ -15,8 +15,14 @@ */ #import <Foundation/Foundation.h> +// The has_include is a workaround so the old IID needed for the FIS tests can find the headers. +#if __has_include("FirebaseCore/Sources/Private/FIRComponentType.h") +#import "FirebaseCore/Sources/Private/FIRComponentType.h" +#import "FirebaseCore/Sources/Private/FIRLibrary.h" +#else #import <FirebaseCore/FIRComponentType.h> #import <FirebaseCore/FIRLibrary.h> +#endif NS_ASSUME_NONNULL_BEGIN diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrorCode.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrorCode.h index f77b3d002..c90d9eecf 100644 --- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrorCode.h +++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrorCode.h @@ -32,7 +32,8 @@ typedef NS_ENUM(NSInteger, FIRErrorCode) { FIRErrorCodeInvalidAppID = -101, /** - * Error code for failing to configure a specific service. + * Error code for failing to configure a specific service. It's deprecated, but + * still used after copybara. */ FIRErrorCodeConfigFailed = -114, }; diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLibrary.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLibrary.h index af9d9685d..e7a9e077c 100644 --- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLibrary.h +++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLibrary.h @@ -19,7 +19,12 @@ #import <Foundation/Foundation.h> +// The has_include is a workaround so the old IID needed for the FIS tests can find the headers. +#if __has_include("FirebaseCore/Sources/Private/FIRComponent.h") +#import "FirebaseCore/Sources/Private/FIRComponent.h" +#else #import <FirebaseCore/FIRComponent.h> +#endif @class FIRApp; diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLogger.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLogger.h index 548e389a4..6fd778441 100644 --- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLogger.h +++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLogger.h @@ -16,7 +16,12 @@ #import <Foundation/Foundation.h> +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIRLoggerLevel.h" +#else #import <FirebaseCore/FIRLoggerLevel.h> +#endif NS_ASSUME_NONNULL_BEGIN diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIROptionsInternal.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIROptionsInternal.h index 0660a3cd8..acaf45868 100644 --- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIROptionsInternal.h +++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIROptionsInternal.h @@ -14,7 +14,12 @@ * limitations under the License. */ +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIROptions.h" +#else #import <FirebaseCore/FIROptions.h> +#endif /** * Keys for the strings in the plist file. diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FirebaseCoreInternal.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FirebaseCoreInternal.h new file mode 100644 index 000000000..93af6cb8d --- /dev/null +++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FirebaseCoreInternal.h @@ -0,0 +1,31 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// An umbrella header, for any other libraries in this repo to access Firebase Public and Private +// headers. Any package manager complexity should be handled here. + +#if SWIFT_PACKAGE +@import FirebaseCore; +#else +#import <FirebaseCore/FirebaseCore.h> +#endif + +#import "FirebaseCore/Sources/Private/FIRAppInternal.h" +#import "FirebaseCore/Sources/Private/FIRComponent.h" +#import "FirebaseCore/Sources/Private/FIRComponentContainer.h" +#import "FirebaseCore/Sources/Private/FIRDependency.h" +#import "FirebaseCore/Sources/Private/FIRHeartbeatInfo.h" +#import "FirebaseCore/Sources/Private/FIRLibrary.h" +#import "FirebaseCore/Sources/Private/FIRLogger.h" +#import "FirebaseCore/Sources/Private/FIROptionsInternal.h" diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRConfiguration.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRConfiguration.h index 8de3b076a..2b8e678ce 100644 --- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRConfiguration.h +++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRConfiguration.h @@ -16,7 +16,7 @@ #import <Foundation/Foundation.h> -#import <FirebaseCore/FIRLoggerLevel.h> +#import "FIRLoggerLevel.h" NS_ASSUME_NONNULL_BEGIN diff --git a/ios/Pods/FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h b/ios/Pods/FirebaseCore/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h similarity index 100% rename from ios/Pods/FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h rename to ios/Pods/FirebaseCore/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h diff --git a/ios/Pods/FirebaseCore/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h b/ios/Pods/FirebaseCore/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h new file mode 100644 index 000000000..2b0eb710c --- /dev/null +++ b/ios/Pods/FirebaseCore/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h @@ -0,0 +1,34 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +#import "FIRCoreDiagnosticsData.h" + +NS_ASSUME_NONNULL_BEGIN + +/** Allows the interoperation of FirebaseCore and FirebaseCoreDiagnostics. */ +@protocol FIRCoreDiagnosticsInterop <NSObject> + +/** Sends the given diagnostics data. + * + * @param diagnosticsData The diagnostics data object to send. + */ ++ (void)sendDiagnosticsData:(id<FIRCoreDiagnosticsData>)diagnosticsData; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCore/README.md b/ios/Pods/FirebaseCore/README.md index 1747cca7a..d778205ff 100644 --- a/ios/Pods/FirebaseCore/README.md +++ b/ios/Pods/FirebaseCore/README.md @@ -2,14 +2,20 @@ [![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) [![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![Actions Status][gh-abtesting-badge]][gh-actions] [![Actions Status][gh-auth-badge]][gh-actions] [![Actions Status][gh-core-badge]][gh-actions] +[![Actions Status][gh-crashlytics-badge]][gh-actions] +[![Actions Status][gh-database-badge]][gh-actions] [![Actions Status][gh-datatransport-badge]][gh-actions] [![Actions Status][gh-dynamiclinks-badge]][gh-actions] [![Actions Status][gh-firebasepod-badge]][gh-actions] [![Actions Status][gh-firestore-badge]][gh-actions] +[![Actions Status][gh-functions-badge]][gh-actions] +[![Actions Status][gh-inappmessaging-badge]][gh-actions] [![Actions Status][gh-interop-badge]][gh-actions] [![Actions Status][gh-messaging-badge]][gh-actions] +[![Actions Status][gh-remoteconfig-badge]][gh-actions] [![Actions Status][gh-storage-badge]][gh-actions] [![Actions Status][gh-symbolcollision-badge]][gh-actions] [![Actions Status][gh-zip-badge]][gh-actions] @@ -92,7 +98,7 @@ Instructions for installing binary frameworks via To develop Firebase software in this repository, ensure that you have at least the following software: - * Xcode 10.1 (or later) + * Xcode 10.3 (or later) * CocoaPods 1.7.2 (or later) * [CocoaPods generate](https://github.com/square/cocoapods-generate) @@ -123,6 +129,10 @@ Firestore has a self contained Xcode project. See See [AddNewPod.md](AddNewPod.md). +### Managing Headers and Imports + +See [HeadersImports.md](HeadersImports.md). + ### Code Formatting To ensure that the code is formatted consistently, run the script @@ -185,8 +195,16 @@ building and running the FirebaseAuth pod along with various samples and tests. ### Firebase Database -To run the Database Integration tests, make your database authentication rules -[public](https://firebase.google.com/docs/database/security/quickstart). +The Firebase Database Integration tests can be run against a locally running Database Emulator +or against a production instance. + +To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before +running the integration test. + +To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to +`Example/Database/App/GoogleService-Info.plist`. Your Security Rule must be set to +[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are +running. ### Firebase Storage @@ -274,14 +292,20 @@ Your use of Firebase is governed by the [Terms of Service for Firebase Services](https://firebase.google.com/terms/). [gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg [gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg [gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg +[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg [gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg [gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg [gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg [gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg +[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg +[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg [gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg [gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg +[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg [gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg [gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg [gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/ios/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m b/ios/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m index 87d57c4e8..2db7db839 100644 --- a/ios/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m +++ b/ios/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m @@ -26,8 +26,8 @@ #import <GoogleUtilities/GULHeartbeatDateStorage.h> #import <GoogleUtilities/GULLogger.h> -#import <FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsData.h> -#import <FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsInterop.h> +#import "Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h" +#import "Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h" #import <nanopb/pb.h> #import <nanopb/pb_decode.h> diff --git a/ios/Pods/FirebaseCoreDiagnostics/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h b/ios/Pods/FirebaseCoreDiagnostics/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h new file mode 100644 index 000000000..69c40721a --- /dev/null +++ b/ios/Pods/FirebaseCoreDiagnostics/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h @@ -0,0 +1,61 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +/** If present, is a BOOL wrapped in an NSNumber. */ +#define kFIRCDIsDataCollectionDefaultEnabledKey @"FIRCDIsDataCollectionDefaultEnabledKey" + +/** If present, is an int32_t wrapped in an NSNumber. */ +#define kFIRCDConfigurationTypeKey @"FIRCDConfigurationTypeKey" + +/** If present, is an NSString. */ +#define kFIRCDSdkNameKey @"FIRCDSdkNameKey" + +/** If present, is an NSString. */ +#define kFIRCDSdkVersionKey @"FIRCDSdkVersionKey" + +/** If present, is an int32_t wrapped in an NSNumber. */ +#define kFIRCDllAppsCountKey @"FIRCDllAppsCountKey" + +/** If present, is an NSString. */ +#define kFIRCDGoogleAppIDKey @"FIRCDGoogleAppIDKey" + +/** If present, is an NSString. */ +#define kFIRCDBundleIDKey @"FIRCDBundleID" + +/** If present, is a BOOL wrapped in an NSNumber. */ +#define kFIRCDUsingOptionsFromDefaultPlistKey @"FIRCDUsingOptionsFromDefaultPlistKey" + +/** If present, is an NSString. */ +#define kFIRCDLibraryVersionIDKey @"FIRCDLibraryVersionIDKey" + +/** If present, is an NSString. */ +#define kFIRCDFirebaseUserAgentKey @"FIRCDFirebaseUserAgentKey" + +/** Defines the interface of a data object needed to log diagnostics data. */ +@protocol FIRCoreDiagnosticsData <NSObject> + +@required + +/** A dictionary containing data (non-exhaustive) to be logged in diagnostics. */ +@property(nonatomic) NSDictionary<NSString *, id> *diagnosticObjects; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCoreDiagnostics/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h b/ios/Pods/FirebaseCoreDiagnostics/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h new file mode 100644 index 000000000..2b0eb710c --- /dev/null +++ b/ios/Pods/FirebaseCoreDiagnostics/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h @@ -0,0 +1,34 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +#import "FIRCoreDiagnosticsData.h" + +NS_ASSUME_NONNULL_BEGIN + +/** Allows the interoperation of FirebaseCore and FirebaseCoreDiagnostics. */ +@protocol FIRCoreDiagnosticsInterop <NSObject> + +/** Sends the given diagnostics data. + * + * @param diagnosticsData The diagnostics data object to send. + */ ++ (void)sendDiagnosticsData:(id<FIRCoreDiagnosticsData>)diagnosticsData; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCoreDiagnostics/README.md b/ios/Pods/FirebaseCoreDiagnostics/README.md index 1747cca7a..d778205ff 100644 --- a/ios/Pods/FirebaseCoreDiagnostics/README.md +++ b/ios/Pods/FirebaseCoreDiagnostics/README.md @@ -2,14 +2,20 @@ [![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) [![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![Actions Status][gh-abtesting-badge]][gh-actions] [![Actions Status][gh-auth-badge]][gh-actions] [![Actions Status][gh-core-badge]][gh-actions] +[![Actions Status][gh-crashlytics-badge]][gh-actions] +[![Actions Status][gh-database-badge]][gh-actions] [![Actions Status][gh-datatransport-badge]][gh-actions] [![Actions Status][gh-dynamiclinks-badge]][gh-actions] [![Actions Status][gh-firebasepod-badge]][gh-actions] [![Actions Status][gh-firestore-badge]][gh-actions] +[![Actions Status][gh-functions-badge]][gh-actions] +[![Actions Status][gh-inappmessaging-badge]][gh-actions] [![Actions Status][gh-interop-badge]][gh-actions] [![Actions Status][gh-messaging-badge]][gh-actions] +[![Actions Status][gh-remoteconfig-badge]][gh-actions] [![Actions Status][gh-storage-badge]][gh-actions] [![Actions Status][gh-symbolcollision-badge]][gh-actions] [![Actions Status][gh-zip-badge]][gh-actions] @@ -92,7 +98,7 @@ Instructions for installing binary frameworks via To develop Firebase software in this repository, ensure that you have at least the following software: - * Xcode 10.1 (or later) + * Xcode 10.3 (or later) * CocoaPods 1.7.2 (or later) * [CocoaPods generate](https://github.com/square/cocoapods-generate) @@ -123,6 +129,10 @@ Firestore has a self contained Xcode project. See See [AddNewPod.md](AddNewPod.md). +### Managing Headers and Imports + +See [HeadersImports.md](HeadersImports.md). + ### Code Formatting To ensure that the code is formatted consistently, run the script @@ -185,8 +195,16 @@ building and running the FirebaseAuth pod along with various samples and tests. ### Firebase Database -To run the Database Integration tests, make your database authentication rules -[public](https://firebase.google.com/docs/database/security/quickstart). +The Firebase Database Integration tests can be run against a locally running Database Emulator +or against a production instance. + +To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before +running the integration test. + +To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to +`Example/Database/App/GoogleService-Info.plist`. Your Security Rule must be set to +[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are +running. ### Firebase Storage @@ -274,14 +292,20 @@ Your use of Firebase is governed by the [Terms of Service for Firebase Services](https://firebase.google.com/terms/). [gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg [gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg [gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg +[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg [gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg [gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg [gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg [gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg +[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg +[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg [gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg [gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg +[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg [gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg [gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg [gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSApplication.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSApplication.h new file mode 100644 index 000000000..75536f7cd --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSApplication.h @@ -0,0 +1,88 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> +#if CLS_TARGET_OS_HAS_UIKIT +#import <UIKit/UIKit.h> +#endif + +__BEGIN_DECLS + +#define FIRCLSApplicationActivityDefault \ + (NSActivitySuddenTerminationDisabled | NSActivityAutomaticTerminationDisabled) + +/** + * Type to indicate application installation source + */ +typedef NS_ENUM(NSInteger, FIRCLSApplicationInstallationSourceType) { + FIRCLSApplicationInstallationSourceTypeDeveloperInstall = 1, + // 2 and 3 are reserved for legacy values. + FIRCLSApplicationInstallationSourceTypeAppStore = 4 +}; + +/** + * Returns the application bundle identifier with occurences of "/" replaced by "_" + */ +NSString* FIRCLSApplicationGetBundleIdentifier(void); + +/** + * Returns the SDK's bundle ID + */ +NSString* FIRCLSApplicationGetSDKBundleID(void); + +/** + * Returns the platform identifier, either: ios, mac, or tvos. + * Catalyst apps are treated as mac. + */ +NSString* FIRCLSApplicationGetPlatform(void); + +/** + * Returns the user-facing app name + */ +NSString* FIRCLSApplicationGetName(void); + +/** + * Returns the build number + */ +NSString* FIRCLSApplicationGetBundleVersion(void); + +/** + * Returns the human-readable build version + */ +NSString* FIRCLSApplicationGetShortBundleVersion(void); + +/** + * Returns a number to indicate how the app has been installed: Developer / App Store + */ +FIRCLSApplicationInstallationSourceType FIRCLSApplicationInstallationSource(void); + +BOOL FIRCLSApplicationIsExtension(void); +NSString* FIRCLSApplicationExtensionPointIdentifier(void); + +#if CLS_TARGET_OS_HAS_UIKIT +UIApplication* FIRCLSApplicationSharedInstance(void); +#else +id FIRCLSApplicationSharedInstance(void); +#endif + +void FIRCLSApplicationOpenURL(NSURL* url, + NSExtensionContext* extensionContext, + void (^completionBlock)(BOOL success)); + +id<NSObject> FIRCLSApplicationBeginActivity(NSActivityOptions options, NSString* reason); +void FIRCLSApplicationEndActivity(id<NSObject> activity); + +void FIRCLSApplicationActivity(NSActivityOptions options, NSString* reason, void (^block)(void)); + +__END_DECLS diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSApplication.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSApplication.m new file mode 100644 index 000000000..219b4bb7a --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSApplication.m @@ -0,0 +1,211 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSApplication.h" + +#import "FIRCLSHost.h" +#import "FIRCLSUtility.h" + +#if CLS_TARGET_OS_OSX +#import <AppKit/AppKit.h> +#endif + +#if CLS_TARGET_OS_HAS_UIKIT +#import <UIKit/UIKit.h> +#endif + +NSString* FIRCLSApplicationGetBundleIdentifier(void) { + return [[[NSBundle mainBundle] bundleIdentifier] stringByReplacingOccurrencesOfString:@"/" + withString:@"_"]; +} + +NSString* FIRCLSApplicationGetSDKBundleID(void) { + return + [@"com.google.firebase.crashlytics." stringByAppendingString:FIRCLSApplicationGetPlatform()]; +} + +NSString* FIRCLSApplicationGetPlatform(void) { +#if defined(TARGET_OS_MACCATALYST) && TARGET_OS_MACCATALYST + return @"mac"; +#elif TARGET_OS_IOS + return @"ios"; +#elif TARGET_OS_OSX + return @"mac"; +#elif TARGET_OS_TV + return @"tvos"; +#endif +} + +// these defaults match the FIRCLSInfoPlist helper in FIRCLSIDEFoundation +NSString* FIRCLSApplicationGetBundleVersion(void) { + return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]; +} + +NSString* FIRCLSApplicationGetShortBundleVersion(void) { + return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; +} + +NSString* FIRCLSApplicationGetName(void) { + NSString* name; + NSBundle* mainBundle; + + mainBundle = [NSBundle mainBundle]; + + name = [mainBundle objectForInfoDictionaryKey:@"CFBundleDisplayName"]; + if (name) { + return name; + } + + name = [mainBundle objectForInfoDictionaryKey:@"CFBundleName"]; + if (name) { + return name; + } + + return FIRCLSApplicationGetBundleVersion(); +} + +BOOL FIRCLSApplicationHasAppStoreReceipt(void) { + NSURL* url = NSBundle.mainBundle.appStoreReceiptURL; + return [NSFileManager.defaultManager fileExistsAtPath:[url path]]; +} + +FIRCLSApplicationInstallationSourceType FIRCLSApplicationInstallationSource(void) { + if (FIRCLSApplicationHasAppStoreReceipt()) { + return FIRCLSApplicationInstallationSourceTypeAppStore; + } + + return FIRCLSApplicationInstallationSourceTypeDeveloperInstall; +} + +BOOL FIRCLSApplicationIsExtension(void) { + return FIRCLSApplicationExtensionPointIdentifier() != nil; +} + +NSString* FIRCLSApplicationExtensionPointIdentifier(void) { + id extensionDict = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"NSExtension"]; + + if (!extensionDict) { + return nil; + } + + if (![extensionDict isKindOfClass:[NSDictionary class]]) { + FIRCLSSDKLog("Error: NSExtension Info.plist entry is mal-formed\n"); + return nil; + } + + id typeValue = [(NSDictionary*)extensionDict objectForKey:@"NSExtensionPointIdentifier"]; + + if (![typeValue isKindOfClass:[NSString class]]) { + FIRCLSSDKLog("Error: NSExtensionPointIdentifier Info.plist entry is mal-formed\n"); + return nil; + } + + return typeValue; +} + +#if CLS_TARGET_OS_HAS_UIKIT +UIApplication* FIRCLSApplicationSharedInstance(void) { + if (FIRCLSApplicationIsExtension()) { + return nil; + } + + return [[UIApplication class] performSelector:@selector(sharedApplication)]; +} +#elif CLS_TARGET_OS_OSX +id FIRCLSApplicationSharedInstance(void) { + return [NSClassFromString(@"NSApplication") sharedApplication]; +} +#else +id FIRCLSApplicationSharedInstance(void) { + return nil; // FIXME: what do we actually return for watch? +} +#endif + +void FIRCLSApplicationOpenURL(NSURL* url, + NSExtensionContext* extensionContext, + void (^completionBlock)(BOOL success)) { + if (extensionContext) { + [extensionContext openURL:url completionHandler:completionBlock]; + return; + } + + BOOL result = NO; + +#if TARGET_OS_IOS + // What's going on here is the value returned is a scalar, but we really need an object to + // call this dynamically. Hoops must be jumped. + NSInvocationOperation* op = + [[NSInvocationOperation alloc] initWithTarget:FIRCLSApplicationSharedInstance() + selector:@selector(openURL:) + object:url]; + [op start]; + [op.result getValue:&result]; +#elif CLS_TARGET_OS_OSX + result = [[NSClassFromString(@"NSWorkspace") sharedWorkspace] openURL:url]; +#endif + + completionBlock(result); +} + +id<NSObject> FIRCLSApplicationBeginActivity(NSActivityOptions options, NSString* reason) { + if ([[NSProcessInfo processInfo] respondsToSelector:@selector(beginActivityWithOptions: + reason:)]) { + return [[NSProcessInfo processInfo] beginActivityWithOptions:options reason:reason]; + } + +#if CLS_TARGET_OS_OSX + if (options & NSActivitySuddenTerminationDisabled) { + [[NSProcessInfo processInfo] disableSuddenTermination]; + } + + if (options & NSActivityAutomaticTerminationDisabled) { + [[NSProcessInfo processInfo] disableAutomaticTermination:reason]; + } +#endif + + // encode the options, so we can undo our work later + return @{@"options" : @(options), @"reason" : reason}; +} + +void FIRCLSApplicationEndActivity(id<NSObject> activity) { + if (!activity) { + return; + } + + if ([[NSProcessInfo processInfo] respondsToSelector:@selector(endActivity:)]) { + [[NSProcessInfo processInfo] endActivity:activity]; + return; + } + +#if CLS_TARGET_OS_OSX + NSInteger options = [[(NSDictionary*)activity objectForKey:@"options"] integerValue]; + + if (options & NSActivitySuddenTerminationDisabled) { + [[NSProcessInfo processInfo] enableSuddenTermination]; + } + + if (options & NSActivityAutomaticTerminationDisabled) { + [[NSProcessInfo processInfo] + enableAutomaticTermination:[(NSDictionary*)activity objectForKey:@"reason"]]; + } +#endif +} + +void FIRCLSApplicationActivity(NSActivityOptions options, NSString* reason, void (^block)(void)) { + id<NSObject> activity = FIRCLSApplicationBeginActivity(options, reason); + + block(); + + FIRCLSApplicationEndActivity(activity); +} diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSBinaryImage.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSBinaryImage.h new file mode 100644 index 000000000..f3c0bd718 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSBinaryImage.h @@ -0,0 +1,81 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include <stdbool.h> +#include <stdint.h> + +#include "FIRCLSFeatures.h" +#include "FIRCLSFile.h" +#include "FIRCLSMachO.h" + +__BEGIN_DECLS + +// Typically, apps seem to have ~300 binary images loaded +#define CLS_BINARY_IMAGE_RUNTIME_NODE_COUNT (512) +#define CLS_BINARY_IMAGE_RUNTIME_NODE_NAME_SIZE (32) +#define CLS_BINARY_IMAGE_RUNTIME_NODE_RECORD_NAME 0 + +#define FIRCLSUUIDStringLength (33) + +typedef struct { + _Atomic(void*) volatile baseAddress; + uint64_t size; +#if CLS_DWARF_UNWINDING_SUPPORTED + const void* ehFrame; +#endif +#if CLS_COMPACT_UNWINDING_SUPPORTED + const void* unwindInfo; +#endif + const void* crashInfo; +#if CLS_BINARY_IMAGE_RUNTIME_NODE_RECORD_NAME + char name[CLS_BINARY_IMAGE_RUNTIME_NODE_NAME_SIZE]; +#endif +} FIRCLSBinaryImageRuntimeNode; + +typedef struct { + char uuidString[FIRCLSUUIDStringLength]; + bool encrypted; + FIRCLSMachOVersion builtSDK; + FIRCLSMachOVersion minSDK; + FIRCLSBinaryImageRuntimeNode node; + struct FIRCLSMachOSlice slice; + intptr_t vmaddr_slide; +} FIRCLSBinaryImageDetails; + +typedef struct { + const char* path; +} FIRCLSBinaryImageReadOnlyContext; + +typedef struct { + FIRCLSFile file; + FIRCLSBinaryImageRuntimeNode nodes[CLS_BINARY_IMAGE_RUNTIME_NODE_COUNT]; +} FIRCLSBinaryImageReadWriteContext; + +void FIRCLSBinaryImageInit(FIRCLSBinaryImageReadOnlyContext* roContext, + FIRCLSBinaryImageReadWriteContext* rwContext); + +#if CLS_COMPACT_UNWINDING_SUPPORTED +bool FIRCLSBinaryImageSafeFindImageForAddress(uintptr_t address, + FIRCLSBinaryImageRuntimeNode* image); +bool FIRCLSBinaryImageSafeHasUnwindInfo(FIRCLSBinaryImageRuntimeNode* image); +#endif + +bool FIRCLSBinaryImageFindImageForUUID(const char* uuidString, + FIRCLSBinaryImageDetails* imageDetails); + +bool FIRCLSBinaryImageRecordMainExecutable(FIRCLSFile* file); + +__END_DECLS diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSBinaryImage.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSBinaryImage.m new file mode 100644 index 000000000..8b707bb44 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSBinaryImage.m @@ -0,0 +1,571 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSBinaryImage.h" + +#include <libkern/OSAtomic.h> +#include <mach-o/dyld.h> + +#include <mach-o/getsect.h> + +#include <stdatomic.h> + +#include "FIRCLSByteUtility.h" +#include "FIRCLSFeatures.h" +#include "FIRCLSFile.h" +#include "FIRCLSGlobals.h" +#include "FIRCLSHost.h" +#include "FIRCLSMachO.h" +#include "FIRCLSUtility.h" + +#include <dispatch/dispatch.h> + +// this is defined only if __OPEN_SOURCE__ is *not* defined in the TVOS SDK's mach-o/loader.h +// also, it has not yet made it back to the OSX SDKs, for example +#ifndef LC_VERSION_MIN_TVOS +#define LC_VERSION_MIN_TVOS 0x2F +#endif + +#pragma mark Prototypes +static bool FIRCLSBinaryImageOpenIfNeeded(bool* needsClosing); + +static void FIRCLSBinaryImageAddedCallback(const struct mach_header* mh, intptr_t vmaddr_slide); +static void FIRCLSBinaryImageRemovedCallback(const struct mach_header* mh, intptr_t vmaddr_slide); +static void FIRCLSBinaryImageChanged(bool added, + const struct mach_header* mh, + intptr_t vmaddr_slide); +static bool FIRCLSBinaryImageFillInImageDetails(FIRCLSBinaryImageDetails* details); + +static void FIRCLSBinaryImageStoreNode(bool added, FIRCLSBinaryImageDetails imageDetails); +static void FIRCLSBinaryImageRecordSlice(bool added, const FIRCLSBinaryImageDetails imageDetails); + +#pragma mark - Core API +void FIRCLSBinaryImageInit(FIRCLSBinaryImageReadOnlyContext* roContext, + FIRCLSBinaryImageReadWriteContext* rwContext) { + // initialize our node array to all zeros + memset(&_firclsContext.writable->binaryImage, 0, sizeof(_firclsContext.writable->binaryImage)); + _firclsContext.writable->binaryImage.file.fd = -1; + + dispatch_async(FIRCLSGetBinaryImageQueue(), ^{ + if (!FIRCLSUnlinkIfExists(_firclsContext.readonly->binaryimage.path)) { + FIRCLSSDKLog("Unable to reset the binary image log file %s\n", strerror(errno)); + } + + bool needsClosing; // unneeded + if (!FIRCLSBinaryImageOpenIfNeeded(&needsClosing)) { + FIRCLSSDKLog("Error: Unable to open the binary image log file during init\n"); + } + }); + + _dyld_register_func_for_add_image(FIRCLSBinaryImageAddedCallback); + _dyld_register_func_for_remove_image(FIRCLSBinaryImageRemovedCallback); + + dispatch_async(FIRCLSGetBinaryImageQueue(), ^{ + FIRCLSFileClose(&_firclsContext.writable->binaryImage.file); + }); +} + +static bool FIRCLSBinaryImageOpenIfNeeded(bool* needsClosing) { + if (!FIRCLSIsValidPointer(_firclsContext.writable)) { + return false; + } + + if (!FIRCLSIsValidPointer(_firclsContext.readonly)) { + return false; + } + + if (!FIRCLSIsValidPointer(needsClosing)) { + return false; + } + + *needsClosing = false; + + if (FIRCLSFileIsOpen(&_firclsContext.writable->binaryImage.file)) { + return true; + } + + if (!FIRCLSFileInitWithPath(&_firclsContext.writable->binaryImage.file, + _firclsContext.readonly->binaryimage.path, false)) { + FIRCLSSDKLog("Error: unable to open binary image log file\n"); + return false; + } + + *needsClosing = true; + + return true; +} + +#if CLS_COMPACT_UNWINDING_SUPPORTED +bool FIRCLSBinaryImageSafeFindImageForAddress(uintptr_t address, + FIRCLSBinaryImageRuntimeNode* image) { + if (!FIRCLSContextIsInitialized()) { + return false; + } + + if (address == 0) { + return false; + } + + if (!FIRCLSIsValidPointer(image)) { + return false; + } + + FIRCLSBinaryImageRuntimeNode* nodes = _firclsContext.writable->binaryImage.nodes; + if (!nodes) { + FIRCLSSDKLogError("The node structure is NULL\n"); + return false; + } + + for (uint32_t i = 0; i < CLS_BINARY_IMAGE_RUNTIME_NODE_COUNT; ++i) { + FIRCLSBinaryImageRuntimeNode* node = &nodes[i]; + if (!FIRCLSIsValidPointer(node)) { + FIRCLSSDKLog( + "Invalid node pointer encountered in context's writable binary image at index %i", i); + continue; + } + + if ((address >= (uintptr_t)node->baseAddress) && + (address < (uintptr_t)node->baseAddress + node->size)) { + *image = *node; // copy the image + return true; + } + } + + return false; +} + +bool FIRCLSBinaryImageSafeHasUnwindInfo(FIRCLSBinaryImageRuntimeNode* image) { + return FIRCLSIsValidPointer(image->unwindInfo); +} +#endif + +bool FIRCLSBinaryImageFindImageForUUID(const char* uuidString, + FIRCLSBinaryImageDetails* imageDetails) { + if (!imageDetails || !uuidString) { + FIRCLSSDKLog("null input\n"); + return false; + } + + uint32_t imageCount = _dyld_image_count(); + + for (uint32_t i = 0; i < imageCount; ++i) { + const struct mach_header* mh = _dyld_get_image_header(i); + + FIRCLSBinaryImageDetails image; + + image.slice = FIRCLSMachOSliceWithHeader((void*)mh); + FIRCLSBinaryImageFillInImageDetails(&image); + + if (strncmp(uuidString, image.uuidString, FIRCLSUUIDStringLength) == 0) { + *imageDetails = image; + return true; + } + } + + return false; +} + +#pragma mark - DYLD callback handlers +static void FIRCLSBinaryImageAddedCallback(const struct mach_header* mh, intptr_t vmaddr_slide) { + FIRCLSBinaryImageChanged(true, mh, vmaddr_slide); +} + +static void FIRCLSBinaryImageRemovedCallback(const struct mach_header* mh, intptr_t vmaddr_slide) { + FIRCLSBinaryImageChanged(false, mh, vmaddr_slide); +} + +#if CLS_BINARY_IMAGE_RUNTIME_NODE_RECORD_NAME +static bool FIRCLSBinaryImagePopulateRuntimeNodeName(FIRCLSBinaryImageDetails* details) { + if (!FIRCLSIsValidPointer(details)) { + return false; + } + + memset(details->node.name, 0, CLS_BINARY_IMAGE_RUNTIME_NODE_NAME_SIZE); + + // We have limited storage space for the name. And, we really want to store + // "CoreFoundation", not "/System/Library/Fram", so we have to play tricks + // to make sure we get the right side of the string. + const char* imageName = FIRCLSMachOSliceGetExecutablePath(&details->slice); + if (!imageName) { + return false; + } + + const size_t imageNameLength = strlen(imageName); + + // Remember to leave one character for null-termination. + if (imageNameLength > CLS_BINARY_IMAGE_RUNTIME_NODE_NAME_SIZE - 1) { + imageName = imageName + (imageNameLength - (CLS_BINARY_IMAGE_RUNTIME_NODE_NAME_SIZE - 1)); + } + + // subtract one to make sure the string is always null-terminated + strncpy(details->node.name, imageName, CLS_BINARY_IMAGE_RUNTIME_NODE_NAME_SIZE - 1); + + return true; +} +#endif + +// There were plans later to replace this with FIRCLSMachO +static FIRCLSMachOSegmentCommand FIRCLSBinaryImageMachOGetSegmentCommand( + const struct load_command* cmd) { + FIRCLSMachOSegmentCommand segmentCommand; + + memset(&segmentCommand, 0, sizeof(FIRCLSMachOSegmentCommand)); + + if (!cmd) { + return segmentCommand; + } + + if (cmd->cmd == LC_SEGMENT) { + struct segment_command* segCmd = (struct segment_command*)cmd; + + memcpy(segmentCommand.segname, segCmd->segname, 16); + segmentCommand.vmaddr = segCmd->vmaddr; + segmentCommand.vmsize = segCmd->vmsize; + } else if (cmd->cmd == LC_SEGMENT_64) { + struct segment_command_64* segCmd = (struct segment_command_64*)cmd; + + memcpy(segmentCommand.segname, segCmd->segname, 16); + segmentCommand.vmaddr = segCmd->vmaddr; + segmentCommand.vmsize = segCmd->vmsize; + } + + return segmentCommand; +} + +static bool FIRCLSBinaryImageMachOSliceInitSectionByName(FIRCLSMachOSliceRef slice, + const char* segName, + const char* sectionName, + FIRCLSMachOSection* section) { + if (!FIRCLSIsValidPointer(slice)) { + return false; + } + + if (!section) { + return false; + } + + memset(section, 0, sizeof(FIRCLSMachOSection)); + + if (FIRCLSMachOSliceIs64Bit(slice)) { + const struct section_64* sect = + getsectbynamefromheader_64(slice->startAddress, segName, sectionName); + if (!sect) { + return false; + } + + section->addr = sect->addr; + section->size = sect->size; + section->offset = sect->offset; + } else { + const struct section* sect = getsectbynamefromheader(slice->startAddress, segName, sectionName); + if (!sect) { + return false; + } + + section->addr = sect->addr; + section->size = sect->size; + section->offset = sect->offset; + } + + return true; +} + +static bool FIRCLSBinaryImageFillInImageDetails(FIRCLSBinaryImageDetails* details) { + if (!FIRCLSIsValidPointer(details)) { + return false; + } + + if (!FIRCLSIsValidPointer(details->slice.startAddress)) { + return false; + } + +#if CLS_BINARY_IMAGE_RUNTIME_NODE_RECORD_NAME + // this is done for debugging purposes, so if it fails, its ok to continue + FIRCLSBinaryImagePopulateRuntimeNodeName(details); +#endif + + // This cast might look a little dubious, but its just because we're using the same + // struct types in a few different places. + details->node.baseAddress = (void* volatile)details->slice.startAddress; + + FIRCLSMachOSliceEnumerateLoadCommands( + &details->slice, ^(uint32_t type, uint32_t size, const struct load_command* cmd) { + switch (type) { + case LC_UUID: { + const uint8_t* uuid = FIRCLSMachOGetUUID(cmd); + FIRCLSSafeHexToString(uuid, 16, details->uuidString); + } break; + case LC_ENCRYPTION_INFO: + details->encrypted = FIRCLSMachOGetEncrypted(cmd); + break; + case LC_SEGMENT: + case LC_SEGMENT_64: { + FIRCLSMachOSegmentCommand segmentCommand = FIRCLSBinaryImageMachOGetSegmentCommand(cmd); + + if (strncmp(segmentCommand.segname, SEG_TEXT, sizeof(SEG_TEXT)) == 0) { + details->node.size = segmentCommand.vmsize; + } + } break; + case LC_VERSION_MIN_MACOSX: + case LC_VERSION_MIN_IPHONEOS: + case LC_VERSION_MIN_TVOS: + case LC_VERSION_MIN_WATCHOS: + details->minSDK = FIRCLSMachOGetMinimumOSVersion(cmd); + details->builtSDK = FIRCLSMachOGetLinkedSDKVersion(cmd); + break; + } + }); + + // We look up the section we want, and we *should* be able to use: + // + // address of data we want = start address + section.offset + // + // However, the offset value is coming back funky in iOS 9. So, instead we look up the address + // the section should be loaded at, and compute the offset by looking up the address of the + // segment itself. + + FIRCLSMachOSection section; + +#if CLS_COMPACT_UNWINDING_SUPPORTED + if (FIRCLSBinaryImageMachOSliceInitSectionByName(&details->slice, SEG_TEXT, "__unwind_info", + §ion)) { + details->node.unwindInfo = (void*)(section.addr + details->vmaddr_slide); + } +#endif + +#if CLS_DWARF_UNWINDING_SUPPORTED + if (FIRCLSBinaryImageMachOSliceInitSectionByName(&details->slice, SEG_TEXT, "__eh_frame", + §ion)) { + details->node.ehFrame = (void*)(section.addr + details->vmaddr_slide); + } +#endif + + if (FIRCLSBinaryImageMachOSliceInitSectionByName(&details->slice, SEG_DATA, "__crash_info", + §ion)) { + details->node.crashInfo = (void*)(section.addr + details->vmaddr_slide); + } + + return true; +} + +static void FIRCLSBinaryImageChanged(bool added, + const struct mach_header* mh, + intptr_t vmaddr_slide) { + // FIRCLSSDKLog("Binary image %s %p\n", added ? "loaded" : "unloaded", mh); + + FIRCLSBinaryImageDetails imageDetails; + + memset(&imageDetails, 0, sizeof(FIRCLSBinaryImageDetails)); + + imageDetails.slice = FIRCLSMachOSliceWithHeader((void*)mh); + imageDetails.vmaddr_slide = vmaddr_slide; + FIRCLSBinaryImageFillInImageDetails(&imageDetails); + + // this is an atomic operation + FIRCLSBinaryImageStoreNode(added, imageDetails); + + // this isn't, so do it on a serial queue + dispatch_async(FIRCLSGetBinaryImageQueue(), ^{ + FIRCLSBinaryImageRecordSlice(added, imageDetails); + }); +} + +#pragma mark - In-Memory Storage +static void FIRCLSBinaryImageStoreNode(bool added, FIRCLSBinaryImageDetails imageDetails) { + // This function is mutating a structure that needs to be accessed at crash time. We + // need to make sure the structure is always in as valid a state as possible. + // FIRCLSSDKLog("Storing %s node %p\n", added ? "loaded" : "unloaded", + // (void*)imageDetails.node.baseAddress); + + if (!_firclsContext.writable) { + FIRCLSSDKLog("Error: Writable context is NULL\n"); + return; + } + + void* searchAddress = NULL; + bool success = false; + FIRCLSBinaryImageRuntimeNode* nodes = _firclsContext.writable->binaryImage.nodes; + + if (!added) { + // capture the search address first + searchAddress = imageDetails.node.baseAddress; + + // If we are removing a node, we need to set its entries to zero. By clearing all of + // these values, we can just copy in imageDetails.node. Using memset here is slightly + // weird, since we have to restore one field. But, this way, if/when the structure changes, + // we still do the right thing. + memset(&imageDetails.node, 0, sizeof(FIRCLSBinaryImageRuntimeNode)); + + // restore the baseAddress, which just got zeroed, and is used for indexing + imageDetails.node.baseAddress = searchAddress; + } + + for (uint32_t i = 0; i < CLS_BINARY_IMAGE_RUNTIME_NODE_COUNT; ++i) { + FIRCLSBinaryImageRuntimeNode* node = &nodes[i]; + + if (!node) { + FIRCLSSDKLog("Error: Binary image storage is NULL\n"); + break; + } + + // navigate through the array, looking for our matching address + if (node->baseAddress != searchAddress) { + continue; + } + + // Attempt to swap the base address with whatever we are searching for. Success means that + // entry has been claims/cleared. Failure means some other thread beat us to it. + if (atomic_compare_exchange_strong(&node->baseAddress, &searchAddress, + imageDetails.node.baseAddress)) { + *node = imageDetails.node; + success = true; + + break; + } + + // If this is an unload, getting here means two threads unloaded at the same time. I think + // that's highly unlikely, and possibly even impossible. So, I'm choosing to abort the process + // at this point. + if (!added) { + FIRCLSSDKLog("Error: Failed to swap during image unload\n"); + break; + } + } + + if (!success) { + FIRCLSSDKLog("Error: Unable to track a %s node %p\n", added ? "loaded" : "unloaded", + (void*)imageDetails.node.baseAddress); + } +} + +#pragma mark - On-Disk Storage +static void FIRCLSBinaryImageRecordDetails(FIRCLSFile* file, + const FIRCLSBinaryImageDetails imageDetails) { + if (!file) { + FIRCLSSDKLog("Error: file is invalid\n"); + return; + } + + FIRCLSFileWriteHashEntryString(file, "uuid", imageDetails.uuidString); + FIRCLSFileWriteHashEntryUint64(file, "base", (uintptr_t)imageDetails.slice.startAddress); + FIRCLSFileWriteHashEntryUint64(file, "size", imageDetails.node.size); +} + +static void FIRCLSBinaryImageRecordLibraryFrameworkInfo(FIRCLSFile* file, const char* path) { + if (!file) { + FIRCLSSDKLog("Error: file is invalid\n"); + return; + } + + if (!path) { + return; + } + + // Because this function is so expensive, we've decided to omit this info for all Apple-supplied + // frameworks. This really isn't that bad, because we can know their info ahead of time (within a + // small margin of error). With this implemenation, we will still record this info for any + // user-built framework, which in the end is the most important thing. + if (strncmp(path, "/System", 7) == 0) { + return; + } + + // check to see if this is a potential framework bundle + if (!strstr(path, ".framework")) { + return; + } + + // My.framework/Versions/A/My for OS X + // My.framework/My for iOS + + NSString* frameworkPath = [NSString stringWithUTF8String:path]; +#if TARGET_OS_IPHONE + frameworkPath = [frameworkPath stringByDeletingLastPathComponent]; +#else + frameworkPath = [frameworkPath stringByDeletingLastPathComponent]; // My.framework/Versions/A + frameworkPath = [frameworkPath stringByDeletingLastPathComponent]; // My.framework/Versions + frameworkPath = [frameworkPath stringByDeletingLastPathComponent]; // My.framework +#endif + + NSBundle* const bundle = [NSBundle bundleWithPath:frameworkPath]; + + if (!bundle) { + return; + } + + FIRCLSFileWriteHashEntryNSStringUnlessNilOrEmpty(file, "bundle_id", [bundle bundleIdentifier]); + FIRCLSFileWriteHashEntryNSStringUnlessNilOrEmpty( + file, "build_version", [bundle objectForInfoDictionaryKey:@"CFBundleVersion"]); + FIRCLSFileWriteHashEntryNSStringUnlessNilOrEmpty( + file, "display_version", [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]); +} + +static void FIRCLSBinaryImageRecordSlice(bool added, const FIRCLSBinaryImageDetails imageDetails) { + bool needsClosing = false; + if (!FIRCLSBinaryImageOpenIfNeeded(&needsClosing)) { + FIRCLSSDKLog("Error: unable to open binary image log file\n"); + return; + } + + FIRCLSFile* file = &_firclsContext.writable->binaryImage.file; + + FIRCLSFileWriteSectionStart(file, added ? "load" : "unload"); + + FIRCLSFileWriteHashStart(file); + + const char* path = FIRCLSMachOSliceGetExecutablePath((FIRCLSMachOSliceRef)&imageDetails.slice); + + FIRCLSFileWriteHashEntryString(file, "path", path); + + if (added) { + // this won't work if the binary has been unloaded + FIRCLSBinaryImageRecordLibraryFrameworkInfo(file, path); + } + + FIRCLSBinaryImageRecordDetails(file, imageDetails); + + FIRCLSFileWriteHashEnd(file); + + FIRCLSFileWriteSectionEnd(file); + + if (needsClosing) { + FIRCLSFileClose(file); + } +} + +bool FIRCLSBinaryImageRecordMainExecutable(FIRCLSFile* file) { + FIRCLSBinaryImageDetails imageDetails; + + memset(&imageDetails, 0, sizeof(FIRCLSBinaryImageDetails)); + + imageDetails.slice = FIRCLSMachOSliceGetCurrent(); + FIRCLSBinaryImageFillInImageDetails(&imageDetails); + + FIRCLSFileWriteSectionStart(file, "executable"); + FIRCLSFileWriteHashStart(file); + + FIRCLSFileWriteHashEntryString(file, "architecture", + FIRCLSMachOSliceGetArchitectureName(&imageDetails.slice)); + + FIRCLSBinaryImageRecordDetails(file, imageDetails); + FIRCLSFileWriteHashEntryBoolean(file, "encrypted", imageDetails.encrypted); + FIRCLSFileWriteHashEntryString(file, "minimum_sdk_version", + [FIRCLSMachOFormatVersion(&imageDetails.minSDK) UTF8String]); + FIRCLSFileWriteHashEntryString(file, "built_sdk_version", + [FIRCLSMachOFormatVersion(&imageDetails.builtSDK) UTF8String]); + + FIRCLSFileWriteHashEnd(file); + FIRCLSFileWriteSectionEnd(file); + + return true; +} diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSContext.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSContext.h new file mode 100644 index 000000000..bdb43418c --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSContext.h @@ -0,0 +1,121 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "FIRCLSAllocate.h" +#include "FIRCLSBinaryImage.h" +#include "FIRCLSException.h" +#include "FIRCLSFeatures.h" +#include "FIRCLSHost.h" +#include "FIRCLSInternalLogging.h" +#include "FIRCLSMachException.h" +#include "FIRCLSSignal.h" +#include "FIRCLSUserLogging.h" + +#include <dispatch/dispatch.h> +#include <stdbool.h> + +// The purpose of the crash context is to hold values that absolutely must be read and/or written at +// crash time. For robustness against memory corruption, they are protected with guard pages. +// Further, the context is seperated into read-only and read-write sections. + +__BEGIN_DECLS + +#ifdef __OBJC__ +@class FIRCLSInternalReport; +@class FIRCLSSettings; +@class FIRCLSInstallIdentifierModel; +@class FIRCLSFileManager; +#endif + +typedef struct { + volatile bool initialized; + volatile bool debuggerAttached; + const char* previouslyCrashedFileFullPath; + const char* logPath; +#if CLS_USE_SIGALTSTACK + void* signalStack; +#endif +#if CLS_MACH_EXCEPTION_SUPPORTED + void* machStack; +#endif + void* delegate; + void* callbackDelegate; + + FIRCLSBinaryImageReadOnlyContext binaryimage; + FIRCLSExceptionReadOnlyContext exception; + FIRCLSHostReadOnlyContext host; + FIRCLSSignalReadContext signal; +#if CLS_MACH_EXCEPTION_SUPPORTED + FIRCLSMachExceptionReadContext machException; +#endif + FIRCLSUserLoggingReadOnlyContext logging; +} FIRCLSReadOnlyContext; + +typedef struct { + FIRCLSInternalLoggingWritableContext internalLogging; + volatile bool crashOccurred; + FIRCLSBinaryImageReadWriteContext binaryImage; + FIRCLSUserLoggingWritableContext logging; + FIRCLSExceptionWritableContext exception; +} FIRCLSReadWriteContext; + +typedef struct { + FIRCLSReadOnlyContext* readonly; + FIRCLSReadWriteContext* writable; + FIRCLSAllocatorRef allocator; +} FIRCLSContext; + +typedef struct { + void* delegate; + const char* customBundleId; + const char* rootPath; + const char* previouslyCrashedFileRootPath; + const char* sessionId; + const char* installId; + const char* betaToken; +#if CLS_MACH_EXCEPTION_SUPPORTED + exception_mask_t machExceptionMask; +#endif + bool errorsEnabled; + bool customExceptionsEnabled; + uint32_t maxCustomExceptions; + uint32_t maxErrorLogSize; + uint32_t maxLogSize; + uint32_t maxKeyValues; +} FIRCLSContextInitData; + +#ifdef __OBJC__ +bool FIRCLSContextInitialize(FIRCLSInternalReport* report, + FIRCLSSettings* settings, + FIRCLSInstallIdentifierModel* installIDModel, + FIRCLSFileManager* fileManager); + +// Re-writes the metadata file on the current thread +void FIRCLSContextUpdateMetadata(FIRCLSInternalReport* report, + FIRCLSSettings* settings, + FIRCLSInstallIdentifierModel* installIDModel, + FIRCLSFileManager* fileManager); +#endif + +void FIRCLSContextBaseInit(void); +void FIRCLSContextBaseDeinit(void); + +bool FIRCLSContextIsInitialized(void); +bool FIRCLSContextHasCrashed(void); +void FIRCLSContextMarkHasCrashed(void); +bool FIRCLSContextMarkAndCheckIfCrashed(void); + +__END_DECLS diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSContext.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSContext.m new file mode 100644 index 000000000..26d46c72e --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSContext.m @@ -0,0 +1,468 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSContext.h" + +#include <stdlib.h> +#include <string.h> + +#import "FIRCLSFileManager.h" +#import "FIRCLSInstallIdentifierModel.h" +#import "FIRCLSInternalReport.h" +#import "FIRCLSSettings.h" + +#include "FIRCLSApplication.h" +#include "FIRCLSCrashedMarkerFile.h" +#include "FIRCLSDefines.h" +#include "FIRCLSFeatures.h" +#include "FIRCLSGlobals.h" +#include "FIRCLSProcess.h" +#include "FIRCLSUtility.h" + +// The writable size is our handler stack plus whatever scratch we need. We have to use this space +// extremely carefully, however, because thread stacks always needs to be page-aligned. Only the +// first allocation is gauranteed to be page-aligned. +// +// CLS_SIGNAL_HANDLER_STACK_SIZE and CLS_MACH_EXCEPTION_HANDLER_STACK_SIZE are platform dependant, +// defined as 0 for tv/watch. +#define CLS_MINIMUM_READWRITE_SIZE \ + (CLS_SIGNAL_HANDLER_STACK_SIZE + CLS_MACH_EXCEPTION_HANDLER_STACK_SIZE + \ + sizeof(FIRCLSReadWriteContext)) + +// We need enough space here for the context, plus storage for strings. +#define CLS_MINIMUM_READABLE_SIZE (sizeof(FIRCLSReadOnlyContext) + 4096 * 4) + +static const int64_t FIRCLSContextInitWaitTime = 5LL * NSEC_PER_SEC; + +static bool FIRCLSContextRecordMetadata(const char* path, const FIRCLSContextInitData* initData); +static const char* FIRCLSContextAppendToRoot(NSString* root, NSString* component); +static void FIRCLSContextAllocate(FIRCLSContext* context); + +FIRCLSContextInitData FIRCLSContextBuildInitData(FIRCLSInternalReport* report, + FIRCLSSettings* settings, + FIRCLSInstallIdentifierModel* installIDModel, + FIRCLSFileManager* fileManager) { + // Because we need to start the crash reporter right away, + // it starts up either with default settings, or cached settings + // from the last time they were fetched + + FIRCLSContextInitData initData; + + memset(&initData, 0, sizeof(FIRCLSContextInitData)); + + initData.customBundleId = nil; + initData.installId = [installIDModel.installID UTF8String]; + initData.sessionId = [[report identifier] UTF8String]; + initData.rootPath = [[report path] UTF8String]; + initData.previouslyCrashedFileRootPath = [[fileManager rootPath] UTF8String]; + initData.errorsEnabled = [settings errorReportingEnabled]; + initData.customExceptionsEnabled = [settings customExceptionsEnabled]; + initData.maxCustomExceptions = [settings maxCustomExceptions]; + initData.maxErrorLogSize = [settings errorLogBufferSize]; + initData.maxLogSize = [settings logBufferSize]; + initData.maxKeyValues = [settings maxCustomKeys]; + + // If this is set, then we could attempt to do a synchronous submission for certain kinds of + // events (exceptions). This is a very cool feature, but adds complexity to the backend. For now, + // we're going to leave this disabled. It does work in the exception case, but will ultimtely + // result in the following crash to be discared. Usually that crash isn't interesting. But, if it + // was, we'd never have a chance to see it. + initData.delegate = nil; + +#if CLS_MACH_EXCEPTION_SUPPORTED + __block exception_mask_t mask = 0; + + // TODO(b/141241224) This if statement was hardcoded to no, so this block was never run + // FIRCLSSignalEnumerateHandledSignals(^(int idx, int signal) { + // if ([self.delegate ensureDeliveryOfUnixSignal:signal]) { + // mask |= FIRCLSMachExceptionMaskForSignal(signal); + // } + // }); + + initData.machExceptionMask = mask; +#endif + + return initData; +} + +bool FIRCLSContextInitialize(FIRCLSInternalReport* report, + FIRCLSSettings* settings, + FIRCLSInstallIdentifierModel* installIDModel, + FIRCLSFileManager* fileManager) { + FIRCLSContextInitData initDataObj = + FIRCLSContextBuildInitData(report, settings, installIDModel, fileManager); + FIRCLSContextInitData* initData = &initDataObj; + + if (!initData) { + return false; + } + + FIRCLSContextBaseInit(); + + dispatch_group_t group = dispatch_group_create(); + dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + + if (!FIRCLSIsValidPointer(initData->rootPath)) { + return false; + } + + NSString* rootPath = [NSString stringWithUTF8String:initData->rootPath]; + + // setup our SDK log file synchronously, because other calls may depend on it + _firclsContext.readonly->logPath = FIRCLSContextAppendToRoot(rootPath, @"sdk.log"); + if (!FIRCLSUnlinkIfExists(_firclsContext.readonly->logPath)) { + FIRCLSErrorLog(@"Unable to write initialize SDK write paths %s", strerror(errno)); + } + + // some values that aren't tied to particular subsystem + _firclsContext.readonly->debuggerAttached = FIRCLSProcessDebuggerAttached(); + _firclsContext.readonly->delegate = initData->delegate; + + dispatch_group_async(group, queue, ^{ + FIRCLSHostInitialize(&_firclsContext.readonly->host); + }); + + dispatch_group_async(group, queue, ^{ + _firclsContext.readonly->logging.errorStorage.maxSize = 0; + _firclsContext.readonly->logging.errorStorage.maxEntries = + initData->errorsEnabled ? initData->maxCustomExceptions : 0; + _firclsContext.readonly->logging.errorStorage.restrictBySize = false; + _firclsContext.readonly->logging.errorStorage.entryCount = + &_firclsContext.writable->logging.errorsCount; + _firclsContext.readonly->logging.errorStorage.aPath = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportErrorAFile); + _firclsContext.readonly->logging.errorStorage.bPath = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportErrorBFile); + + _firclsContext.readonly->logging.logStorage.maxSize = initData->maxLogSize; + _firclsContext.readonly->logging.logStorage.maxEntries = 0; + _firclsContext.readonly->logging.logStorage.restrictBySize = true; + _firclsContext.readonly->logging.logStorage.entryCount = NULL; + _firclsContext.readonly->logging.logStorage.aPath = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportLogAFile); + _firclsContext.readonly->logging.logStorage.bPath = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportLogBFile); + _firclsContext.readonly->logging.customExceptionStorage.aPath = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportCustomExceptionAFile); + _firclsContext.readonly->logging.customExceptionStorage.bPath = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportCustomExceptionBFile); + _firclsContext.readonly->logging.customExceptionStorage.maxSize = 0; + _firclsContext.readonly->logging.customExceptionStorage.restrictBySize = false; + _firclsContext.readonly->logging.customExceptionStorage.maxEntries = + initData->maxCustomExceptions; + _firclsContext.readonly->logging.customExceptionStorage.entryCount = + &_firclsContext.writable->exception.customExceptionCount; + + _firclsContext.readonly->logging.userKVStorage.maxCount = initData->maxKeyValues; + _firclsContext.readonly->logging.userKVStorage.incrementalPath = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportUserIncrementalKVFile); + _firclsContext.readonly->logging.userKVStorage.compactedPath = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportUserCompactedKVFile); + + _firclsContext.readonly->logging.internalKVStorage.maxCount = 32; // Hardcode = bad + _firclsContext.readonly->logging.internalKVStorage.incrementalPath = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportInternalIncrementalKVFile); + _firclsContext.readonly->logging.internalKVStorage.compactedPath = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportInternalCompactedKVFile); + + FIRCLSUserLoggingInit(&_firclsContext.readonly->logging, &_firclsContext.writable->logging); + }); + + dispatch_group_async(group, queue, ^{ + _firclsContext.readonly->binaryimage.path = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportBinaryImageFile); + + FIRCLSBinaryImageInit(&_firclsContext.readonly->binaryimage, + &_firclsContext.writable->binaryImage); + }); + + dispatch_group_async(group, queue, ^{ + NSString* rootPath = [NSString stringWithUTF8String:initData->previouslyCrashedFileRootPath]; + NSString* fileName = [NSString stringWithUTF8String:FIRCLSCrashedMarkerFileName]; + _firclsContext.readonly->previouslyCrashedFileFullPath = + FIRCLSContextAppendToRoot(rootPath, fileName); + }); + + if (!_firclsContext.readonly->debuggerAttached) { + dispatch_group_async(group, queue, ^{ + _firclsContext.readonly->signal.path = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportSignalFile); + + FIRCLSSignalInitialize(&_firclsContext.readonly->signal); + }); + +#if CLS_MACH_EXCEPTION_SUPPORTED + dispatch_group_async(group, queue, ^{ + _firclsContext.readonly->machException.path = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportMachExceptionFile); + + FIRCLSMachExceptionInit(&_firclsContext.readonly->machException, initData->machExceptionMask); + }); +#endif + + dispatch_group_async(group, queue, ^{ + _firclsContext.readonly->exception.path = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportExceptionFile); + _firclsContext.readonly->exception.maxCustomExceptions = + initData->customExceptionsEnabled ? initData->maxCustomExceptions : 0; + + FIRCLSExceptionInitialize(&_firclsContext.readonly->exception, + &_firclsContext.writable->exception, initData->delegate); + }); + } else { + FIRCLSSDKLog("Debugger present - not installing handlers\n"); + } + + dispatch_group_async(group, queue, ^{ + const char* metaDataPath = [[rootPath stringByAppendingPathComponent:FIRCLSReportMetadataFile] + fileSystemRepresentation]; + if (!FIRCLSContextRecordMetadata(metaDataPath, initData)) { + FIRCLSSDKLog("Unable to record context metadata\n"); + } + }); + + // At this point we need to do two things. First, we need to do our memory protection *only* after + // all of these initialization steps are really done. But, we also want to wait as long as + // possible for these to be complete. If we do not, there's a chance that we will not be able to + // correctly report a crash shortly after start. + + // Note at this will retain the group, so its totally fine to release the group here. + dispatch_group_notify(group, queue, ^{ + _firclsContext.readonly->initialized = true; + __sync_synchronize(); + + if (!FIRCLSAllocatorProtect(_firclsContext.allocator)) { + FIRCLSSDKLog("Error: Memory protection failed\n"); + } + }); + + if (dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, FIRCLSContextInitWaitTime)) != + 0) { + FIRCLSSDKLog("Error: Delayed initialization\n"); + } + + return true; +} + +void FIRCLSContextUpdateMetadata(FIRCLSInternalReport* report, + FIRCLSSettings* settings, + FIRCLSInstallIdentifierModel* installIDModel, + FIRCLSFileManager* fileManager) { + FIRCLSContextInitData initDataObj = + FIRCLSContextBuildInitData(report, settings, installIDModel, fileManager); + FIRCLSContextInitData* initData = &initDataObj; + + NSString* rootPath = [NSString stringWithUTF8String:initData->rootPath]; + + const char* metaDataPath = + [[rootPath stringByAppendingPathComponent:FIRCLSReportMetadataFile] fileSystemRepresentation]; + + if (!FIRCLSContextRecordMetadata(metaDataPath, initData)) { + FIRCLSErrorLog(@"Unable to update context metadata"); + } +} + +void FIRCLSContextBaseInit(void) { + NSString* sdkBundleID = FIRCLSApplicationGetSDKBundleID(); + + NSString* loggingQueueName = [sdkBundleID stringByAppendingString:@".logging"]; + NSString* binaryImagesQueueName = [sdkBundleID stringByAppendingString:@".binary-images"]; + NSString* exceptionQueueName = [sdkBundleID stringByAppendingString:@".exception"]; + + _firclsLoggingQueue = dispatch_queue_create([loggingQueueName UTF8String], DISPATCH_QUEUE_SERIAL); + _firclsBinaryImageQueue = + dispatch_queue_create([binaryImagesQueueName UTF8String], DISPATCH_QUEUE_SERIAL); + _firclsExceptionQueue = + dispatch_queue_create([exceptionQueueName UTF8String], DISPATCH_QUEUE_SERIAL); + + FIRCLSContextAllocate(&_firclsContext); + + _firclsContext.writable->internalLogging.logFd = -1; + _firclsContext.writable->internalLogging.logLevel = FIRCLSInternalLogLevelDebug; + _firclsContext.writable->crashOccurred = false; + + _firclsContext.readonly->initialized = false; + + __sync_synchronize(); +} + +static void FIRCLSContextAllocate(FIRCLSContext* context) { + // create the allocator, and the contexts + // The ordering here is really important, because the "stack" variable must be + // page-aligned. There's no mechanism to ask the allocator to do alignment, but we + // do know the very first allocation in a region is aligned to a page boundary. + + context->allocator = FIRCLSAllocatorCreate(CLS_MINIMUM_READWRITE_SIZE, CLS_MINIMUM_READABLE_SIZE); + + context->readonly = + FIRCLSAllocatorSafeAllocate(context->allocator, sizeof(FIRCLSReadOnlyContext), CLS_READONLY); + memset(context->readonly, 0, sizeof(FIRCLSReadOnlyContext)); + +#if CLS_MEMORY_PROTECTION_ENABLED +#if CLS_MACH_EXCEPTION_SUPPORTED + context->readonly->machStack = FIRCLSAllocatorSafeAllocate( + context->allocator, CLS_MACH_EXCEPTION_HANDLER_STACK_SIZE, CLS_READWRITE); +#endif +#if CLS_USE_SIGALTSTACK + context->readonly->signalStack = + FIRCLSAllocatorSafeAllocate(context->allocator, CLS_SIGNAL_HANDLER_STACK_SIZE, CLS_READWRITE); +#endif +#else +#if CLS_MACH_EXCEPTION_SUPPORTED + context->readonly->machStack = valloc(CLS_MACH_EXCEPTION_HANDLER_STACK_SIZE); +#endif +#if CLS_USE_SIGALTSTACK + context->readonly->signalStack = valloc(CLS_SIGNAL_HANDLER_STACK_SIZE); +#endif +#endif + +#if CLS_MACH_EXCEPTION_SUPPORTED + memset(_firclsContext.readonly->machStack, 0, CLS_MACH_EXCEPTION_HANDLER_STACK_SIZE); +#endif +#if CLS_USE_SIGALTSTACK + memset(_firclsContext.readonly->signalStack, 0, CLS_SIGNAL_HANDLER_STACK_SIZE); +#endif + + context->writable = FIRCLSAllocatorSafeAllocate(context->allocator, + sizeof(FIRCLSReadWriteContext), CLS_READWRITE); + memset(context->writable, 0, sizeof(FIRCLSReadWriteContext)); +} + +void FIRCLSContextBaseDeinit(void) { + _firclsContext.readonly->initialized = false; + + FIRCLSAllocatorDestroy(_firclsContext.allocator); +} + +bool FIRCLSContextIsInitialized(void) { + __sync_synchronize(); + if (!FIRCLSIsValidPointer(_firclsContext.readonly)) { + return false; + } + + return _firclsContext.readonly->initialized; +} + +bool FIRCLSContextHasCrashed(void) { + if (!FIRCLSContextIsInitialized()) { + return false; + } + + // we've already run a full barrier above, so this read is ok + return _firclsContext.writable->crashOccurred; +} + +void FIRCLSContextMarkHasCrashed(void) { + if (!FIRCLSContextIsInitialized()) { + return; + } + + _firclsContext.writable->crashOccurred = true; + __sync_synchronize(); +} + +bool FIRCLSContextMarkAndCheckIfCrashed(void) { + if (!FIRCLSContextIsInitialized()) { + return false; + } + + if (_firclsContext.writable->crashOccurred) { + return true; + } + + _firclsContext.writable->crashOccurred = true; + __sync_synchronize(); + + return false; +} + +static const char* FIRCLSContextAppendToRoot(NSString* root, NSString* component) { + return FIRCLSDupString( + [[root stringByAppendingPathComponent:component] fileSystemRepresentation]); +} + +static bool FIRCLSContextRecordIdentity(FIRCLSFile* file, const FIRCLSContextInitData* initData) { + FIRCLSFileWriteSectionStart(file, "identity"); + + FIRCLSFileWriteHashStart(file); + + FIRCLSFileWriteHashEntryString(file, "generator", CLS_SDK_GENERATOR_NAME); + FIRCLSFileWriteHashEntryString(file, "display_version", CLS_SDK_DISPLAY_VERSION); + FIRCLSFileWriteHashEntryString(file, "build_version", CLS_SDK_DISPLAY_VERSION); + FIRCLSFileWriteHashEntryUint64(file, "started_at", time(NULL)); + + FIRCLSFileWriteHashEntryString(file, "session_id", initData->sessionId); + FIRCLSFileWriteHashEntryString(file, "install_id", initData->installId); + FIRCLSFileWriteHashEntryString(file, "beta_token", initData->betaToken); + FIRCLSFileWriteHashEntryBoolean(file, "absolute_log_timestamps", true); + + FIRCLSFileWriteHashEnd(file); + FIRCLSFileWriteSectionEnd(file); + + return true; +} + +static bool FIRCLSContextRecordApplication(FIRCLSFile* file, const char* customBundleId) { + FIRCLSFileWriteSectionStart(file, "application"); + + FIRCLSFileWriteHashStart(file); + + FIRCLSFileWriteHashEntryString(file, "bundle_id", + [FIRCLSApplicationGetBundleIdentifier() UTF8String]); + FIRCLSFileWriteHashEntryString(file, "custom_bundle_id", customBundleId); + FIRCLSFileWriteHashEntryString(file, "build_version", + [FIRCLSApplicationGetBundleVersion() UTF8String]); + FIRCLSFileWriteHashEntryString(file, "display_version", + [FIRCLSApplicationGetShortBundleVersion() UTF8String]); + FIRCLSFileWriteHashEntryString(file, "extension_id", + [FIRCLSApplicationExtensionPointIdentifier() UTF8String]); + + FIRCLSFileWriteHashEnd(file); + FIRCLSFileWriteSectionEnd(file); + + return true; +} + +static bool FIRCLSContextRecordMetadata(const char* path, const FIRCLSContextInitData* initData) { + if (!FIRCLSUnlinkIfExists(path)) { + FIRCLSSDKLog("Unable to unlink existing metadata file %s\n", strerror(errno)); + } + + FIRCLSFile file; + + if (!FIRCLSFileInitWithPath(&file, path, false)) { + FIRCLSSDKLog("Unable to open metadata file %s\n", strerror(errno)); + return false; + } + + if (!FIRCLSContextRecordIdentity(&file, initData)) { + FIRCLSSDKLog("Unable to write out identity metadata\n"); + } + + if (!FIRCLSHostRecord(&file)) { + FIRCLSSDKLog("Unable to write out host metadata\n"); + } + + if (!FIRCLSContextRecordApplication(&file, initData->customBundleId)) { + FIRCLSSDKLog("Unable to write out application metadata\n"); + } + + if (!FIRCLSBinaryImageRecordMainExecutable(&file)) { + FIRCLSSDKLog("Unable to write out executable metadata\n"); + } + + FIRCLSFileClose(&file); + + return true; +} diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSCrashedMarkerFile.c b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSCrashedMarkerFile.c new file mode 100644 index 000000000..5dd67fdec --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSCrashedMarkerFile.c @@ -0,0 +1,31 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSCrashedMarkerFile.h" +#include "FIRCLSFile.h" +#include "FIRCLSUtility.h" + +const char *FIRCLSCrashedMarkerFileName = "previously-crashed"; + +void FIRCLSCreateCrashedMarkerFile() { + FIRCLSFile file; + + if (!FIRCLSFileInitWithPath(&file, _firclsContext.readonly->previouslyCrashedFileFullPath, false)) { + FIRCLSSDKLog("Unable to create the crashed marker file\n"); + return; + } + + FIRCLSFileClose(&file); + FIRCLSSDKLog("Created the crashed marker file\n"); +} diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSCrashedMarkerFile.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSCrashedMarkerFile.h new file mode 100644 index 000000000..ccf427673 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSCrashedMarkerFile.h @@ -0,0 +1,19 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include <stdio.h> + +extern const char *FIRCLSCrashedMarkerFileName; + +void FIRCLSCreateCrashedMarkerFile(void); diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSGlobals.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSGlobals.h new file mode 100644 index 000000000..4f125cf08 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSGlobals.h @@ -0,0 +1,28 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSContext.h" + +__BEGIN_DECLS + +extern FIRCLSContext _firclsContext; +extern dispatch_queue_t _firclsLoggingQueue; +extern dispatch_queue_t _firclsBinaryImageQueue; +extern dispatch_queue_t _firclsExceptionQueue; + +#define FIRCLSGetLoggingQueue() (_firclsLoggingQueue) +#define FIRCLSGetBinaryImageQueue() (_firclsBinaryImageQueue) +#define FIRCLSGetExceptionQueue() (_firclsExceptionQueue) + +__END_DECLS diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSHost.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSHost.h new file mode 100644 index 000000000..24b1acd13 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSHost.h @@ -0,0 +1,37 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include <mach/vm_types.h> +#include <sys/cdefs.h> + +#include "FIRCLSFile.h" + +typedef struct { + const char* documentDirectoryPath; + vm_size_t pageSize; +} FIRCLSHostReadOnlyContext; + +__BEGIN_DECLS + +void FIRCLSHostInitialize(FIRCLSHostReadOnlyContext* roContext); + +vm_size_t FIRCLSHostGetPageSize(void); + +bool FIRCLSHostRecord(FIRCLSFile* file); + +void FIRCLSHostWriteDiskUsage(FIRCLSFile* file); + +__END_DECLS diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSHost.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSHost.m new file mode 100644 index 000000000..87ff0f7ae --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSHost.m @@ -0,0 +1,161 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSHost.h" + +#include <mach/mach.h> +#include <sys/mount.h> +#include <sys/sysctl.h> + +#import "FIRCLSApplication.h" +#include "FIRCLSDefines.h" +#import "FIRCLSFABHost.h" +#include "FIRCLSFile.h" +#include "FIRCLSGlobals.h" +#include "FIRCLSUtility.h" + +#if TARGET_OS_IPHONE +#import <UIKit/UIKit.h> +#else +#import <Cocoa/Cocoa.h> +#endif + +#define CLS_HOST_SYSCTL_BUFFER_SIZE (128) + +#if CLS_CPU_ARM64 +#define CLS_MAX_NATIVE_PAGE_SIZE (1024 * 16) +#else +// return 4K, which is correct for all platforms except arm64, currently +#define CLS_MAX_NATIVE_PAGE_SIZE (1024 * 4) +#endif +#define CLS_MIN_NATIVE_PAGE_SIZE (1024 * 4) + +#pragma mark Prototypes +static void FIRCLSHostWriteSysctlEntry( + FIRCLSFile* file, const char* key, const char* sysctlKey, void* buffer, size_t bufferSize); +static void FIRCLSHostWriteModelInfo(FIRCLSFile* file); +static void FIRCLSHostWriteOSVersionInfo(FIRCLSFile* file); + +#pragma mark - API +void FIRCLSHostInitialize(FIRCLSHostReadOnlyContext* roContext) { + _firclsContext.readonly->host.pageSize = FIRCLSHostGetPageSize(); + _firclsContext.readonly->host.documentDirectoryPath = NULL; + + // determine where the document directory is mounted, so we can get file system statistics later + NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + if ([paths count]) { + _firclsContext.readonly->host.documentDirectoryPath = + FIRCLSDupString([[paths objectAtIndex:0] fileSystemRepresentation]); + } +} + +vm_size_t FIRCLSHostGetPageSize(void) { + size_t size; + int pageSize; + + // hw.pagesize is defined as HW_PAGESIZE, which is an int. It's important to match + // these types. Turns out that sysctl will not init the data to zero, but it appears + // that sysctlbyname does. This API is nicer, but that's important to keep in mind. + + pageSize = 0; + size = sizeof(pageSize); + if (sysctlbyname("hw.pagesize", &pageSize, &size, NULL, 0) != 0) { + FIRCLSSDKLog("sysctlbyname failed while trying to get hw.pagesize\n"); + + return CLS_MAX_NATIVE_PAGE_SIZE; + } + + // if the returned size is not the expected value, abort + if (size != sizeof(pageSize)) { + return CLS_MAX_NATIVE_PAGE_SIZE; + } + + // put in some guards to make sure our size is reasonable + if (pageSize > CLS_MAX_NATIVE_PAGE_SIZE) { + return CLS_MAX_NATIVE_PAGE_SIZE; + } + + if (pageSize < CLS_MIN_NATIVE_PAGE_SIZE) { + return CLS_MIN_NATIVE_PAGE_SIZE; + } + + return pageSize; +} + +static void FIRCLSHostWriteSysctlEntry( + FIRCLSFile* file, const char* key, const char* sysctlKey, void* buffer, size_t bufferSize) { + if (sysctlbyname(sysctlKey, buffer, &bufferSize, NULL, 0) != 0) { + FIRCLSFileWriteHashEntryString(file, key, "(failed)"); + return; + } + + FIRCLSFileWriteHashEntryString(file, key, buffer); +} + +static void FIRCLSHostWriteModelInfo(FIRCLSFile* file) { + FIRCLSFileWriteHashEntryString(file, "model", [FIRCLSHostModelInfo() UTF8String]); + + // allocate a static buffer for the sysctl values, which are typically + // quite short + char buffer[CLS_HOST_SYSCTL_BUFFER_SIZE]; + +#if TARGET_OS_EMBEDDED + FIRCLSHostWriteSysctlEntry(file, "machine", "hw.model", buffer, CLS_HOST_SYSCTL_BUFFER_SIZE); +#else + FIRCLSHostWriteSysctlEntry(file, "machine", "hw.machine", buffer, CLS_HOST_SYSCTL_BUFFER_SIZE); + FIRCLSHostWriteSysctlEntry(file, "cpu", "machdep.cpu.brand_string", buffer, + CLS_HOST_SYSCTL_BUFFER_SIZE); +#endif +} + +static void FIRCLSHostWriteOSVersionInfo(FIRCLSFile* file) { + FIRCLSFileWriteHashEntryString(file, "os_build_version", [FIRCLSHostOSBuildVersion() UTF8String]); + FIRCLSFileWriteHashEntryString(file, "os_display_version", + [FIRCLSHostOSDisplayVersion() UTF8String]); + FIRCLSFileWriteHashEntryString(file, "platform", [FIRCLSApplicationGetPlatform() UTF8String]); +} + +bool FIRCLSHostRecord(FIRCLSFile* file) { + FIRCLSFileWriteSectionStart(file, "host"); + + FIRCLSFileWriteHashStart(file); + + FIRCLSHostWriteModelInfo(file); + FIRCLSHostWriteOSVersionInfo(file); + FIRCLSFileWriteHashEntryString(file, "locale", + [[[NSLocale currentLocale] localeIdentifier] UTF8String]); + + FIRCLSFileWriteHashEnd(file); + + FIRCLSFileWriteSectionEnd(file); + + return true; +} + +void FIRCLSHostWriteDiskUsage(FIRCLSFile* file) { + struct statfs tStats; + + FIRCLSFileWriteSectionStart(file, "storage"); + + FIRCLSFileWriteHashStart(file); + + if (statfs(_firclsContext.readonly->host.documentDirectoryPath, &tStats) == 0) { + FIRCLSFileWriteHashEntryUint64(file, "free", tStats.f_bavail * tStats.f_bsize); + FIRCLSFileWriteHashEntryUint64(file, "total", tStats.f_blocks * tStats.f_bsize); + } + + FIRCLSFileWriteHashEnd(file); + + FIRCLSFileWriteSectionEnd(file); +} diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSProcess.c b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSProcess.c new file mode 100644 index 000000000..415466ec4 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSProcess.c @@ -0,0 +1,824 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSProcess.h" +#include "FIRCLSDefines.h" +#include "FIRCLSFeatures.h" +#include "FIRCLSGlobals.h" +#include "FIRCLSProfiling.h" +#include "FIRCLSThreadState.h" +#include "FIRCLSUnwind.h" +#include "FIRCLSUtility.h" + +#include <dispatch/dispatch.h> +#include <objc/message.h> +#include <pthread.h> +#include <sys/sysctl.h> + +#define THREAD_NAME_BUFFER_SIZE (64) + +#pragma mark Prototypes +static bool FIRCLSProcessGetThreadName(FIRCLSProcess *process, + thread_t thread, + char *buffer, + size_t length); +static const char *FIRCLSProcessGetThreadDispatchQueueName(FIRCLSProcess *process, thread_t thread); + +#pragma mark - API +bool FIRCLSProcessInit(FIRCLSProcess *process, thread_t crashedThread, void *uapVoid) { + if (!process) { + return false; + } + + process->task = mach_task_self(); + process->thisThread = mach_thread_self(); + process->crashedThread = crashedThread; + process->uapVoid = uapVoid; + + if (task_threads(process->task, &process->threads, &process->threadCount) != KERN_SUCCESS) { + // failed to get all threads + process->threadCount = 0; + FIRCLSSDKLog("Error: unable to get task threads\n"); + + return false; + } + + return true; +} + +bool FIRCLSProcessDestroy(FIRCLSProcess *process) { + return false; +} + +// https://developer.apple.com/library/mac/#qa/qa2004/qa1361.html +bool FIRCLSProcessDebuggerAttached(void) { + int junk; + int mib[4]; + struct kinfo_proc info; + size_t size; + + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + info.kp_proc.p_flag = 0; + + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + + // Call sysctl. + size = sizeof(info); + junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0); + if (junk != 0) { + FIRCLSSDKLog("sysctl failed while trying to get kinfo_proc\n"); + return false; + } + + // We're being debugged if the P_TRACED flag is set. + return (info.kp_proc.p_flag & P_TRACED) != 0; +} + +#pragma mark - Thread Support +static bool FIRCLSProcessIsCurrentThread(FIRCLSProcess *process, thread_t thread) { + return MACH_PORT_INDEX(process->thisThread) == MACH_PORT_INDEX(thread); +} + +static bool FIRCLSProcessIsCrashedThread(FIRCLSProcess *process, thread_t thread) { + return MACH_PORT_INDEX(process->crashedThread) == MACH_PORT_INDEX(thread); +} + +static uint32_t FIRCLSProcessGetThreadCount(FIRCLSProcess *process) { + return process->threadCount; +} + +static thread_t FIRCLSProcessGetThread(FIRCLSProcess *process, uint32_t index) { + if (index >= process->threadCount) { + return MACH_PORT_NULL; + } + + return process->threads[index]; +} + +bool FIRCLSProcessSuspendAllOtherThreads(FIRCLSProcess *process) { + mach_msg_type_number_t i; + bool success; + + success = true; + for (i = 0; i < process->threadCount; ++i) { + thread_t thread; + + thread = FIRCLSProcessGetThread(process, i); + + if (FIRCLSProcessIsCurrentThread(process, thread)) { + continue; + } + + // FIXME: workaround to get this building on watch, but we need to suspend/resume threads! +#if CLS_CAN_SUSPEND_THREADS + success = success && (thread_suspend(thread) == KERN_SUCCESS); +#endif + } + + return success; +} + +bool FIRCLSProcessResumeAllOtherThreads(FIRCLSProcess *process) { + mach_msg_type_number_t i; + bool success; + + success = true; + for (i = 0; i < process->threadCount; ++i) { + thread_t thread; + + thread = FIRCLSProcessGetThread(process, i); + + if (FIRCLSProcessIsCurrentThread(process, thread)) { + continue; + } + + // FIXME: workaround to get this building on watch, but we need to suspend/resume threads! +#if CLS_CAN_SUSPEND_THREADS + success = success && (thread_resume(thread) == KERN_SUCCESS); +#endif + } + + return success; +} + +#pragma mark - Thread Properties +void *FIRCLSThreadGetCurrentPC(void) { + return __builtin_return_address(0); +} + +static bool FIRCLSProcessGetThreadState(FIRCLSProcess *process, + thread_t thread, + FIRCLSThreadContext *context) { + if (!FIRCLSIsValidPointer(context)) { + FIRCLSSDKLogError("invalid context supplied"); + return false; + } + + // If the thread context we should use is non-NULL, then just assign it here. Otherwise, + // query the thread state + if (FIRCLSProcessIsCrashedThread(process, thread) && FIRCLSIsValidPointer(process->uapVoid)) { + *context = *((_STRUCT_UCONTEXT *)process->uapVoid)->uc_mcontext; + return true; + } + + // Here's a wild trick: emulate what thread_get_state would do. It apppears that + // we cannot reliably unwind out of thread_get_state. So, instead of trying, setup + // a thread context that resembles what the real thing would look like + if (FIRCLSProcessIsCurrentThread(process, thread)) { + FIRCLSSDKLog("Faking current thread\n"); + memset(context, 0, sizeof(FIRCLSThreadContext)); + + // Compute the frame address, and then base the stack value off of that. A frame pushes + // two pointers onto the stack, so we have to offset. + const uintptr_t frameAddress = (uintptr_t)__builtin_frame_address(0); + const uintptr_t stackAddress = FIRCLSUnwindStackPointerFromFramePointer(frameAddress); + +#if CLS_CPU_X86_64 + context->__ss.__rip = (uintptr_t)FIRCLSThreadGetCurrentPC(); + context->__ss.__rbp = frameAddress; + context->__ss.__rsp = stackAddress; +#elif CLS_CPU_I386 + context->__ss.__eip = (uintptr_t)FIRCLSThreadGetCurrentPC(); + context->__ss.__ebp = frameAddress; + context->__ss.__esp = stackAddress; +#elif CLS_CPU_ARM64 + FIRCLSThreadContextSetPC(context, (uintptr_t)FIRCLSThreadGetCurrentPC()); + FIRCLSThreadContextSetFramePointer(context, frameAddress); + FIRCLSThreadContextSetLinkRegister(context, (uintptr_t)__builtin_return_address(0)); + FIRCLSThreadContextSetStackPointer(context, stackAddress); +#elif CLS_CPU_ARM + context->__ss.__pc = (uintptr_t)FIRCLSThreadGetCurrentPC(); + context->__ss.__r[7] = frameAddress; + context->__ss.__lr = (uintptr_t)__builtin_return_address(0); + context->__ss.__sp = stackAddress; +#endif + + return true; + } + +#if !TARGET_OS_WATCH + // try to get the value by querying the thread state + mach_msg_type_number_t stateCount = FIRCLSThreadStateCount; + if (thread_get_state(thread, FIRCLSThreadState, (thread_state_t)(&(context->__ss)), + &stateCount) != KERN_SUCCESS) { + FIRCLSSDKLogError("failed to get thread state\n"); + return false; + } + + return true; +#else + return false; +#endif +} + +static bool FIRCLSProcessGetThreadName(FIRCLSProcess *process, + thread_t thread, + char *buffer, + size_t length) { + pthread_t pthread; + + if (!buffer || length <= 0) { + return false; + } + + pthread = pthread_from_mach_thread_np(thread); + + return pthread_getname_np(pthread, buffer, length) == 0; +} + +static const char *FIRCLSProcessGetThreadDispatchQueueName(FIRCLSProcess *process, + thread_t thread) { + thread_identifier_info_data_t info; + mach_msg_type_number_t infoCount; + dispatch_queue_t *queueAddress; + dispatch_queue_t queue; + const char *string; + + infoCount = THREAD_IDENTIFIER_INFO_COUNT; + if (thread_info(thread, THREAD_IDENTIFIER_INFO, (thread_info_t)&info, &infoCount) != + KERN_SUCCESS) { + FIRCLSSDKLog("unable to get thread info\n"); + return NULL; + } + + queueAddress = (dispatch_queue_t *)info.dispatch_qaddr; + if (queueAddress == NULL) { + return ""; + } + + // Sometimes a queue address is invalid. I cannot explain why this is, but + // it can cause a crash. + if (!FIRCLSReadMemory((vm_address_t)queueAddress, &queue, sizeof(void *))) { + return ""; + } + + // here, we know it is safe to de-reference this address, so attempt to get the queue name + if (!queue) { + return ""; + } + + string = dispatch_queue_get_label(queue); + + // but, we still don't if the entire string is valid, so check that too + if (!FIRCLSReadString((vm_address_t)string, (char **)&string, 128)) { + return ""; + } + + return string; +} + +#pragma mark - Data Recording +static bool FIRCLSProcessRecordThreadRegisters(FIRCLSThreadContext context, FIRCLSFile *file) { +#if CLS_CPU_ARM + FIRCLSFileWriteHashEntryUint64(file, "r0", context.__ss.__r[0]); + FIRCLSFileWriteHashEntryUint64(file, "r1", context.__ss.__r[1]); + FIRCLSFileWriteHashEntryUint64(file, "r2", context.__ss.__r[2]); + FIRCLSFileWriteHashEntryUint64(file, "r3", context.__ss.__r[3]); + FIRCLSFileWriteHashEntryUint64(file, "r4", context.__ss.__r[4]); + FIRCLSFileWriteHashEntryUint64(file, "r5", context.__ss.__r[5]); + FIRCLSFileWriteHashEntryUint64(file, "r6", context.__ss.__r[6]); + FIRCLSFileWriteHashEntryUint64(file, "r7", context.__ss.__r[7]); + FIRCLSFileWriteHashEntryUint64(file, "r8", context.__ss.__r[8]); + FIRCLSFileWriteHashEntryUint64(file, "r9", context.__ss.__r[9]); + FIRCLSFileWriteHashEntryUint64(file, "r10", context.__ss.__r[10]); + FIRCLSFileWriteHashEntryUint64(file, "r11", context.__ss.__r[11]); + FIRCLSFileWriteHashEntryUint64(file, "ip", context.__ss.__r[12]); + FIRCLSFileWriteHashEntryUint64(file, "sp", context.__ss.__sp); + FIRCLSFileWriteHashEntryUint64(file, "lr", context.__ss.__lr); + FIRCLSFileWriteHashEntryUint64(file, "pc", context.__ss.__pc); + FIRCLSFileWriteHashEntryUint64(file, "cpsr", context.__ss.__cpsr); +#elif CLS_CPU_ARM64 + FIRCLSFileWriteHashEntryUint64(file, "x0", context.__ss.__x[0]); + FIRCLSFileWriteHashEntryUint64(file, "x1", context.__ss.__x[1]); + FIRCLSFileWriteHashEntryUint64(file, "x2", context.__ss.__x[2]); + FIRCLSFileWriteHashEntryUint64(file, "x3", context.__ss.__x[3]); + FIRCLSFileWriteHashEntryUint64(file, "x4", context.__ss.__x[4]); + FIRCLSFileWriteHashEntryUint64(file, "x5", context.__ss.__x[5]); + FIRCLSFileWriteHashEntryUint64(file, "x6", context.__ss.__x[6]); + FIRCLSFileWriteHashEntryUint64(file, "x7", context.__ss.__x[7]); + FIRCLSFileWriteHashEntryUint64(file, "x8", context.__ss.__x[8]); + FIRCLSFileWriteHashEntryUint64(file, "x9", context.__ss.__x[9]); + FIRCLSFileWriteHashEntryUint64(file, "x10", context.__ss.__x[10]); + FIRCLSFileWriteHashEntryUint64(file, "x11", context.__ss.__x[11]); + FIRCLSFileWriteHashEntryUint64(file, "x12", context.__ss.__x[12]); + FIRCLSFileWriteHashEntryUint64(file, "x13", context.__ss.__x[13]); + FIRCLSFileWriteHashEntryUint64(file, "x14", context.__ss.__x[14]); + FIRCLSFileWriteHashEntryUint64(file, "x15", context.__ss.__x[15]); + FIRCLSFileWriteHashEntryUint64(file, "x16", context.__ss.__x[16]); + FIRCLSFileWriteHashEntryUint64(file, "x17", context.__ss.__x[17]); + FIRCLSFileWriteHashEntryUint64(file, "x18", context.__ss.__x[18]); + FIRCLSFileWriteHashEntryUint64(file, "x19", context.__ss.__x[19]); + FIRCLSFileWriteHashEntryUint64(file, "x20", context.__ss.__x[20]); + FIRCLSFileWriteHashEntryUint64(file, "x21", context.__ss.__x[21]); + FIRCLSFileWriteHashEntryUint64(file, "x22", context.__ss.__x[22]); + FIRCLSFileWriteHashEntryUint64(file, "x23", context.__ss.__x[23]); + FIRCLSFileWriteHashEntryUint64(file, "x24", context.__ss.__x[24]); + FIRCLSFileWriteHashEntryUint64(file, "x25", context.__ss.__x[25]); + FIRCLSFileWriteHashEntryUint64(file, "x26", context.__ss.__x[26]); + FIRCLSFileWriteHashEntryUint64(file, "x27", context.__ss.__x[27]); + FIRCLSFileWriteHashEntryUint64(file, "x28", context.__ss.__x[28]); + FIRCLSFileWriteHashEntryUint64(file, "fp", FIRCLSThreadContextGetFramePointer(&context)); + FIRCLSFileWriteHashEntryUint64(file, "sp", FIRCLSThreadContextGetStackPointer(&context)); + FIRCLSFileWriteHashEntryUint64(file, "lr", FIRCLSThreadContextGetLinkRegister(&context)); + FIRCLSFileWriteHashEntryUint64(file, "pc", FIRCLSThreadContextGetPC(&context)); + FIRCLSFileWriteHashEntryUint64(file, "cpsr", context.__ss.__cpsr); +#elif CLS_CPU_I386 + FIRCLSFileWriteHashEntryUint64(file, "eax", context.__ss.__eax); + FIRCLSFileWriteHashEntryUint64(file, "ebx", context.__ss.__ebx); + FIRCLSFileWriteHashEntryUint64(file, "ecx", context.__ss.__ecx); + FIRCLSFileWriteHashEntryUint64(file, "edx", context.__ss.__edx); + FIRCLSFileWriteHashEntryUint64(file, "edi", context.__ss.__edi); + FIRCLSFileWriteHashEntryUint64(file, "esi", context.__ss.__esi); + FIRCLSFileWriteHashEntryUint64(file, "ebp", context.__ss.__ebp); + FIRCLSFileWriteHashEntryUint64(file, "esp", context.__ss.__esp); + FIRCLSFileWriteHashEntryUint64(file, "ss", context.__ss.__ss); + FIRCLSFileWriteHashEntryUint64(file, "eflags", context.__ss.__eflags); + FIRCLSFileWriteHashEntryUint64(file, "eip", context.__ss.__eip); + FIRCLSFileWriteHashEntryUint64(file, "cs", context.__ss.__cs); + FIRCLSFileWriteHashEntryUint64(file, "ds", context.__ss.__ds); + FIRCLSFileWriteHashEntryUint64(file, "es", context.__ss.__es); + FIRCLSFileWriteHashEntryUint64(file, "fs", context.__ss.__fs); + FIRCLSFileWriteHashEntryUint64(file, "gs", context.__ss.__gs); + + // how do we get the cr2 register? +#elif CLS_CPU_X86_64 + FIRCLSFileWriteHashEntryUint64(file, "rax", context.__ss.__rax); + FIRCLSFileWriteHashEntryUint64(file, "rbx", context.__ss.__rbx); + FIRCLSFileWriteHashEntryUint64(file, "rcx", context.__ss.__rcx); + FIRCLSFileWriteHashEntryUint64(file, "rdx", context.__ss.__rdx); + FIRCLSFileWriteHashEntryUint64(file, "rdi", context.__ss.__rdi); + FIRCLSFileWriteHashEntryUint64(file, "rsi", context.__ss.__rsi); + FIRCLSFileWriteHashEntryUint64(file, "rbp", context.__ss.__rbp); + FIRCLSFileWriteHashEntryUint64(file, "rsp", context.__ss.__rsp); + FIRCLSFileWriteHashEntryUint64(file, "r8", context.__ss.__r8); + FIRCLSFileWriteHashEntryUint64(file, "r9", context.__ss.__r9); + FIRCLSFileWriteHashEntryUint64(file, "r10", context.__ss.__r10); + FIRCLSFileWriteHashEntryUint64(file, "r11", context.__ss.__r11); + FIRCLSFileWriteHashEntryUint64(file, "r12", context.__ss.__r12); + FIRCLSFileWriteHashEntryUint64(file, "r13", context.__ss.__r13); + FIRCLSFileWriteHashEntryUint64(file, "r14", context.__ss.__r14); + FIRCLSFileWriteHashEntryUint64(file, "r15", context.__ss.__r15); + FIRCLSFileWriteHashEntryUint64(file, "rip", context.__ss.__rip); + FIRCLSFileWriteHashEntryUint64(file, "rflags", context.__ss.__rflags); + FIRCLSFileWriteHashEntryUint64(file, "cs", context.__ss.__cs); + FIRCLSFileWriteHashEntryUint64(file, "fs", context.__ss.__fs); + FIRCLSFileWriteHashEntryUint64(file, "gs", context.__ss.__gs); +#endif + + return true; +} + +static bool FIRCLSProcessRecordThread(FIRCLSProcess *process, thread_t thread, FIRCLSFile *file) { + FIRCLSUnwindContext unwindContext; + FIRCLSThreadContext context; + + if (!FIRCLSProcessGetThreadState(process, thread, &context)) { + FIRCLSSDKLogError("unable to get thread state"); + return false; + } + + if (!FIRCLSUnwindInit(&unwindContext, context)) { + FIRCLSSDKLog("unable to init unwind context\n"); + + return false; + } + + FIRCLSFileWriteHashStart(file); + + // registers + FIRCLSFileWriteHashKey(file, "registers"); + FIRCLSFileWriteHashStart(file); + + FIRCLSProcessRecordThreadRegisters(context, file); + + FIRCLSFileWriteHashEnd(file); + + // stacktrace + FIRCLSFileWriteHashKey(file, "stacktrace"); + + // stacktrace is an array of integers + FIRCLSFileWriteArrayStart(file); + + uint32_t repeatedPCCount = 0; + uint64_t repeatedPC = 0; + const FIRCLSInternalLogLevel level = _firclsContext.writable->internalLogging.logLevel; + + while (FIRCLSUnwindNextFrame(&unwindContext)) { + const uintptr_t pc = FIRCLSUnwindGetPC(&unwindContext); + const uint32_t frameCount = FIRCLSUnwindGetFrameRepeatCount(&unwindContext); + + if (repeatedPC == pc && repeatedPC != 0) { + // actively counting a recursion + repeatedPCCount = frameCount; + continue; + } + + if (frameCount >= FIRCLSUnwindInfiniteRecursionCountThreshold && repeatedPC == 0) { + repeatedPC = pc; + FIRCLSSDKLogWarn("Possible infinite recursion - suppressing logging\n"); + _firclsContext.writable->internalLogging.logLevel = FIRCLSInternalLogLevelWarn; + continue; + } + + if (repeatedPC != 0) { + // at this point, we've recorded a repeated PC, but it is now no longer + // repeating, so we can restore the logging + _firclsContext.writable->internalLogging.logLevel = level; + } + + FIRCLSFileWriteArrayEntryUint64(file, pc); + } + + FIRCLSFileWriteArrayEnd(file); + + // crashed? + if (FIRCLSProcessIsCrashedThread(process, thread)) { + FIRCLSFileWriteHashEntryBoolean(file, "crashed", true); + } + + if (repeatedPC != 0) { + FIRCLSFileWriteHashEntryUint64(file, "repeated_pc", repeatedPC); + FIRCLSFileWriteHashEntryUint64(file, "repeat_count", repeatedPCCount); + } + + // Just for extra safety, restore the logging level again. The logic + // above is fairly tricky, this is cheap, and no logging is a real pain. + _firclsContext.writable->internalLogging.logLevel = level; + + // end thread info + FIRCLSFileWriteHashEnd(file); + + return true; +} + +bool FIRCLSProcessRecordAllThreads(FIRCLSProcess *process, FIRCLSFile *file) { + uint32_t threadCount; + uint32_t i; + + threadCount = FIRCLSProcessGetThreadCount(process); + + FIRCLSFileWriteSectionStart(file, "threads"); + + FIRCLSFileWriteArrayStart(file); + + for (i = 0; i < threadCount; ++i) { + thread_t thread; + + thread = FIRCLSProcessGetThread(process, i); + + FIRCLSSDKLogInfo("recording thread %d data\n", i); + if (!FIRCLSProcessRecordThread(process, thread, file)) { + return false; + } + } + + FIRCLSFileWriteArrayEnd(file); + + FIRCLSFileWriteSectionEnd(file); + + FIRCLSSDKLogInfo("completed recording all thread data\n"); + + return true; +} + +void FIRCLSProcessRecordThreadNames(FIRCLSProcess *process, FIRCLSFile *file) { + uint32_t threadCount; + uint32_t i; + + FIRCLSFileWriteSectionStart(file, "thread_names"); + + FIRCLSFileWriteArrayStart(file); + + threadCount = FIRCLSProcessGetThreadCount(process); + for (i = 0; i < threadCount; ++i) { + thread_t thread; + char name[THREAD_NAME_BUFFER_SIZE]; + + thread = FIRCLSProcessGetThread(process, i); + + name[0] = 0; // null-terminate, just in case nothing is written + + FIRCLSProcessGetThreadName(process, thread, name, THREAD_NAME_BUFFER_SIZE); + + FIRCLSFileWriteArrayEntryString(file, name); + } + + FIRCLSFileWriteArrayEnd(file); + FIRCLSFileWriteSectionEnd(file); +} + +void FIRCLSProcessRecordDispatchQueueNames(FIRCLSProcess *process, FIRCLSFile *file) { + uint32_t threadCount; + uint32_t i; + + FIRCLSFileWriteSectionStart(file, "dispatch_queue_names"); + + FIRCLSFileWriteArrayStart(file); + + threadCount = FIRCLSProcessGetThreadCount(process); + for (i = 0; i < threadCount; ++i) { + thread_t thread; + const char *name; + + thread = FIRCLSProcessGetThread(process, i); + + name = FIRCLSProcessGetThreadDispatchQueueName(process, thread); + + FIRCLSFileWriteArrayEntryString(file, name); + } + + FIRCLSFileWriteArrayEnd(file); + FIRCLSFileWriteSectionEnd(file); +} + +#pragma mark - Othe Process Info +bool FIRCLSProcessGetMemoryUsage(uint64_t *active, + uint64_t *inactive, + uint64_t *wired, + uint64_t *freeMem) { + mach_port_t hostPort; + mach_msg_type_number_t hostSize; + vm_size_t pageSize; + vm_statistics_data_t vmStat; + + hostPort = mach_host_self(); + + hostSize = sizeof(vm_statistics_data_t) / sizeof(integer_t); + + pageSize = _firclsContext.readonly->host.pageSize; + + if (host_statistics(hostPort, HOST_VM_INFO, (host_info_t)&vmStat, &hostSize) != KERN_SUCCESS) { + FIRCLSSDKLog("Failed to get vm statistics\n"); + return false; + } + + if (!(active && inactive && wired && freeMem)) { + FIRCLSSDKLog("Invalid pointers\n"); + return false; + } + + // compute the sizes in bytes and return the values + *active = vmStat.active_count * pageSize; + *inactive = vmStat.inactive_count * pageSize; + *wired = vmStat.wire_count * pageSize; + *freeMem = vmStat.free_count * pageSize; + + return true; +} + +bool FIRCLSProcessGetInfo(FIRCLSProcess *process, + uint64_t *virtualSize, + uint64_t *residentSize, + time_value_t *userTime, + time_value_t *systemTime) { + struct task_basic_info_64 taskInfo; + mach_msg_type_number_t count; + + count = TASK_BASIC_INFO_64_COUNT; + if (task_info(process->task, TASK_BASIC_INFO_64, (task_info_t)&taskInfo, &count) != + KERN_SUCCESS) { + FIRCLSSDKLog("Failed to get task info\n"); + return false; + } + + if (!(virtualSize && residentSize && userTime && systemTime)) { + FIRCLSSDKLog("Invalid pointers\n"); + return false; + } + + *virtualSize = taskInfo.virtual_size; + *residentSize = taskInfo.resident_size; + *userTime = taskInfo.user_time; + *systemTime = taskInfo.system_time; + + return true; +} + +void FIRCLSProcessRecordStats(FIRCLSProcess *process, FIRCLSFile *file) { + uint64_t active; + uint64_t inactive; + uint64_t virtualSize; + uint64_t residentSize; + uint64_t wired; + uint64_t freeMem; + time_value_t userTime; + time_value_t systemTime; + + if (!FIRCLSProcessGetMemoryUsage(&active, &inactive, &wired, &freeMem)) { + FIRCLSSDKLog("Unable to get process memory usage\n"); + return; + } + + if (!FIRCLSProcessGetInfo(process, &virtualSize, &residentSize, &userTime, &systemTime)) { + FIRCLSSDKLog("Unable to get process stats\n"); + return; + } + + FIRCLSFileWriteSectionStart(file, "process_stats"); + + FIRCLSFileWriteHashStart(file); + + FIRCLSFileWriteHashEntryUint64(file, "active", active); + FIRCLSFileWriteHashEntryUint64(file, "inactive", inactive); + FIRCLSFileWriteHashEntryUint64(file, "wired", wired); + FIRCLSFileWriteHashEntryUint64(file, "freeMem", freeMem); // Intentionally left in, for now. Arg. + FIRCLSFileWriteHashEntryUint64(file, "free_mem", freeMem); + FIRCLSFileWriteHashEntryUint64(file, "virtual", virtualSize); + FIRCLSFileWriteHashEntryUint64(file, "resident", active); + FIRCLSFileWriteHashEntryUint64(file, "user_time", + (userTime.seconds * 1000 * 1000) + userTime.microseconds); + FIRCLSFileWriteHashEntryUint64(file, "sys_time", + (systemTime.seconds * 1000 * 1000) + systemTime.microseconds); + + FIRCLSFileWriteHashEnd(file); + + FIRCLSFileWriteSectionEnd(file); +} + +#pragma mark - Runtime Info +#define OBJC_MSG_SEND_START ((vm_address_t)objc_msgSend) +#define OBJC_MSG_SEND_SUPER_START ((vm_address_t)objc_msgSendSuper) +#define OBJC_MSG_SEND_END (OBJC_MSG_SEND_START + 66) +#define OBJC_MSG_SEND_SUPER_END (OBJC_MSG_SEND_SUPER_START + 66) + +#if !CLS_CPU_ARM64 +#define OBJC_MSG_SEND_STRET_START ((vm_address_t)objc_msgSend_stret) +#define OBJC_MSG_SEND_SUPER_STRET_START ((vm_address_t)objc_msgSendSuper_stret) +#define OBJC_MSG_SEND_STRET_END (OBJC_MSG_SEND_STRET_START + 66) +#define OBJC_MSG_SEND_SUPER_STRET_END (OBJC_MSG_SEND_SUPER_STRET_START + 66) +#endif + +#if CLS_CPU_X86 +#define OBJC_MSG_SEND_FPRET_START ((vm_address_t)objc_msgSend_fpret) +#define OBJC_MSG_SEND_FPRET_END (OBJC_MSG_SEND_FPRET_START + 66) +#endif + +static const char *FIRCLSProcessGetObjCSelectorName(FIRCLSThreadContext registers) { + void *selectorAddress; + void *selRegister; +#if !CLS_CPU_ARM64 + void *stretSelRegister; +#endif + vm_address_t pc; + + // First, did we crash in objc_msgSend? The two ways I can think + // of doing this are to use dladdr, and then comparing the strings to + // objc_msg*, or looking up the symbols, and guessing if we are "close enough". + + selectorAddress = NULL; + +#if CLS_CPU_ARM + pc = registers.__ss.__pc; + selRegister = (void *)registers.__ss.__r[1]; + stretSelRegister = (void *)registers.__ss.__r[2]; +#elif CLS_CPU_ARM64 + pc = FIRCLSThreadContextGetPC(®isters); + selRegister = (void *)registers.__ss.__x[1]; +#elif CLS_CPU_I386 + pc = registers.__ss.__eip; + selRegister = (void *)registers.__ss.__ecx; + stretSelRegister = (void *)registers.__ss.__ecx; +#elif CLS_CPU_X86_64 + pc = registers.__ss.__rip; + selRegister = (void *)registers.__ss.__rsi; + stretSelRegister = (void *)registers.__ss.__rdx; +#endif + + if ((pc >= OBJC_MSG_SEND_START) && (pc <= OBJC_MSG_SEND_END)) { + selectorAddress = selRegister; + } + +#if !CLS_CPU_ARM64 + if ((pc >= OBJC_MSG_SEND_SUPER_START) && (pc <= OBJC_MSG_SEND_SUPER_END)) { + selectorAddress = selRegister; + } + + if ((pc >= OBJC_MSG_SEND_STRET_START) && (pc <= OBJC_MSG_SEND_STRET_END)) { + selectorAddress = stretSelRegister; + } + + if ((pc >= OBJC_MSG_SEND_SUPER_STRET_START) && (pc <= OBJC_MSG_SEND_SUPER_STRET_END)) { + selectorAddress = stretSelRegister; + } + +#if CLS_CPU_X86 + if ((pc >= OBJC_MSG_SEND_FPRET_START) && (pc <= OBJC_MSG_SEND_FPRET_END)) { + selectorAddress = selRegister; + } +#endif +#endif + + if (!selectorAddress) { + return ""; + } + + if (!FIRCLSReadString((vm_address_t)selectorAddress, (char **)&selectorAddress, 128)) { + FIRCLSSDKLog("Unable to read the selector string\n"); + return ""; + } + + return selectorAddress; +} + +#define CRASH_ALIGN __attribute__((aligned(8))) +typedef struct { + unsigned version CRASH_ALIGN; + const char *message CRASH_ALIGN; + const char *signature CRASH_ALIGN; + const char *backtrace CRASH_ALIGN; + const char *message2 CRASH_ALIGN; + void *reserved CRASH_ALIGN; + void *reserved2 CRASH_ALIGN; +} crash_info_t; + +static void FIRCLSProcessRecordCrashInfo(FIRCLSFile *file) { + // TODO: this should be abstracted into binary images, if possible + FIRCLSBinaryImageRuntimeNode *nodes = _firclsContext.writable->binaryImage.nodes; + if (!nodes) { + FIRCLSSDKLogError("The node structure is NULL\n"); + return; + } + + for (uint32_t i = 0; i < CLS_BINARY_IMAGE_RUNTIME_NODE_COUNT; ++i) { + FIRCLSBinaryImageRuntimeNode *node = &nodes[i]; + + if (!node->crashInfo) { + continue; + } + + crash_info_t info; + + if (!FIRCLSReadMemory((vm_address_t)node->crashInfo, &info, sizeof(crash_info_t))) { + continue; + } + + FIRCLSSDKLogDebug("Found crash info with version %d\n", info.version); + + // Currently support versions 0 through 5. + // 4 was in use for a long time, but it appears that with iOS 9 / swift 2.0, the verison has + // been bumped. + if (info.version > 5) { + continue; + } + + if (!info.message) { + continue; + } + +#if CLS_BINARY_IMAGE_RUNTIME_NODE_RECORD_NAME + FIRCLSSDKLogInfo("Found crash info for %s\n", node->name); +#endif + + FIRCLSSDKLogDebug("attempting to read crash info string\n"); + + char *string = NULL; + + if (!FIRCLSReadString((vm_address_t)info.message, &string, 256)) { + FIRCLSSDKLogError("Failed to copy crash info string\n"); + continue; + } + + FIRCLSFileWriteArrayEntryHexEncodedString(file, string); + } +} + +void FIRCLSProcessRecordRuntimeInfo(FIRCLSProcess *process, FIRCLSFile *file) { + FIRCLSThreadContext mcontext; + + if (!FIRCLSProcessGetThreadState(process, process->crashedThread, &mcontext)) { + FIRCLSSDKLogError("unable to get crashed thread state"); + } + + FIRCLSFileWriteSectionStart(file, "runtime"); + + FIRCLSFileWriteHashStart(file); + + FIRCLSFileWriteHashEntryString(file, "objc_selector", FIRCLSProcessGetObjCSelectorName(mcontext)); + + FIRCLSFileWriteHashKey(file, "crash_info_entries"); + + FIRCLSFileWriteArrayStart(file); + FIRCLSProcessRecordCrashInfo(file); + FIRCLSFileWriteArrayEnd(file); + + FIRCLSFileWriteHashEnd(file); + + FIRCLSFileWriteSectionEnd(file); +} diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSProcess.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSProcess.h new file mode 100644 index 000000000..dbe758ffd --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSProcess.h @@ -0,0 +1,45 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include <mach/mach.h> +#include <stdbool.h> + +#include "FIRCLSFile.h" + +typedef struct { + // task info + mach_port_t task; + + // thread stuff + thread_t thisThread; + thread_t crashedThread; + thread_act_array_t threads; + mach_msg_type_number_t threadCount; + void *uapVoid; // current thread state +} FIRCLSProcess; + +bool FIRCLSProcessInit(FIRCLSProcess *process, thread_t crashedThread, void *uapVoid); +bool FIRCLSProcessDestroy(FIRCLSProcess *process); +bool FIRCLSProcessDebuggerAttached(void); + +bool FIRCLSProcessSuspendAllOtherThreads(FIRCLSProcess *process); +bool FIRCLSProcessResumeAllOtherThreads(FIRCLSProcess *process); + +void FIRCLSProcessRecordThreadNames(FIRCLSProcess *process, FIRCLSFile *file); +void FIRCLSProcessRecordDispatchQueueNames(FIRCLSProcess *process, FIRCLSFile *file); +bool FIRCLSProcessRecordAllThreads(FIRCLSProcess *process, FIRCLSFile *file); +void FIRCLSProcessRecordStats(FIRCLSProcess *process, FIRCLSFile *file); +void FIRCLSProcessRecordRuntimeInfo(FIRCLSProcess *process, FIRCLSFile *file); diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.h new file mode 100644 index 000000000..e1ee897d6 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.h @@ -0,0 +1,101 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "FIRCLSFile.h" + +__BEGIN_DECLS + +#ifdef __OBJC__ +extern NSString* const FIRCLSStartTimeKey; +extern NSString* const FIRCLSFirstRunloopTurnTimeKey; +extern NSString* const FIRCLSInBackgroundKey; +#if TARGET_OS_IPHONE +extern NSString* const FIRCLSDeviceOrientationKey; +extern NSString* const FIRCLSUIOrientationKey; +#endif +extern NSString* const FIRCLSUserIdentifierKey; +extern NSString* const FIRCLSUserNameKey; +extern NSString* const FIRCLSUserEmailKey; +extern NSString* const FIRCLSDevelopmentPlatformNameKey; +extern NSString* const FIRCLSDevelopmentPlatformVersionKey; +#endif + +extern const uint32_t FIRCLSUserLoggingMaxKVEntries; + +typedef struct { + const char* incrementalPath; + const char* compactedPath; + + uint32_t maxIncrementalCount; + uint32_t maxCount; +} FIRCLSUserLoggingKVStorage; + +typedef struct { + const char* aPath; + const char* bPath; + uint32_t maxSize; + uint32_t maxEntries; + bool restrictBySize; + uint32_t* entryCount; +} FIRCLSUserLoggingABStorage; + +typedef struct { + FIRCLSUserLoggingKVStorage userKVStorage; + FIRCLSUserLoggingKVStorage internalKVStorage; + + FIRCLSUserLoggingABStorage logStorage; + FIRCLSUserLoggingABStorage errorStorage; + FIRCLSUserLoggingABStorage customExceptionStorage; +} FIRCLSUserLoggingReadOnlyContext; + +typedef struct { + const char* activeUserLogPath; + const char* activeErrorLogPath; + const char* activeCustomExceptionPath; + uint32_t userKVCount; + uint32_t internalKVCount; + uint32_t errorsCount; +} FIRCLSUserLoggingWritableContext; + +void FIRCLSUserLoggingInit(FIRCLSUserLoggingReadOnlyContext* roContext, + FIRCLSUserLoggingWritableContext* rwContext); + +#ifdef __OBJC__ +void FIRCLSUserLoggingRecordUserKeyValue(NSString* key, id value); +void FIRCLSUserLoggingRecordInternalKeyValue(NSString* key, id value); +void FIRCLSUserLoggingWriteInternalKeyValue(NSString* key, NSString* value); + +void FIRCLSUserLoggingRecordError(NSError* error, NSDictionary<NSString*, id>* additionalUserInfo); + +NSDictionary* FIRCLSUserLoggingGetCompactedKVEntries(FIRCLSUserLoggingKVStorage* storage, + bool decodeHex); +void FIRCLSUserLoggingCompactKVEntries(FIRCLSUserLoggingKVStorage* storage); + +void FIRCLSUserLoggingRecordKeyValue(NSString* key, + id value, + FIRCLSUserLoggingKVStorage* storage, + uint32_t* counter); + +void FIRCLSUserLoggingWriteAndCheckABFiles(FIRCLSUserLoggingABStorage* storage, + const char** activePath, + void (^openedFileBlock)(FIRCLSFile* file)); + +NSArray* FIRCLSUserLoggingStoredKeyValues(const char* path); + +OBJC_EXTERN void FIRCLSLog(NSString* format, ...) NS_FORMAT_FUNCTION(1, 2); +#endif + +__END_DECLS diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.m new file mode 100644 index 000000000..0bb768cfe --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.m @@ -0,0 +1,523 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSUserLogging.h" + +#include <sys/time.h> + +#include "FIRCLSGlobals.h" +#include "FIRCLSUtility.h" + +#import "FIRCLSReportManager_Private.h" + +NSString *const FIRCLSStartTimeKey = @"com.crashlytics.kit-start-time"; +NSString *const FIRCLSFirstRunloopTurnTimeKey = @"com.crashlytics.first-run-loop-time"; +NSString *const FIRCLSInBackgroundKey = @"com.crashlytics.in-background"; +#if TARGET_OS_IPHONE +NSString *const FIRCLSDeviceOrientationKey = @"com.crashlytics.device-orientation"; +NSString *const FIRCLSUIOrientationKey = @"com.crashlytics.ui-orientation"; +#endif +NSString *const FIRCLSUserIdentifierKey = @"com.crashlytics.user-id"; +NSString *const FIRCLSDevelopmentPlatformNameKey = @"com.crashlytics.development-platform-name"; +NSString *const FIRCLSDevelopmentPlatformVersionKey = + @"com.crashlytics.development-platform-version"; + +const uint32_t FIRCLSUserLoggingMaxKVEntries = 64; + +#pragma mark - Prototypes +static void FIRCLSUserLoggingWriteKeyValue(NSString *key, + NSString *value, + FIRCLSUserLoggingKVStorage *storage, + uint32_t *counter); +static void FIRCLSUserLoggingCheckAndSwapABFiles(FIRCLSUserLoggingABStorage *storage, + const char **activePath, + off_t fileSize); +void FIRCLSLogInternal(NSString *message); + +#pragma mark - Setup +void FIRCLSUserLoggingInit(FIRCLSUserLoggingReadOnlyContext *roContext, + FIRCLSUserLoggingWritableContext *rwContext) { + rwContext->activeUserLogPath = roContext->logStorage.aPath; + rwContext->activeErrorLogPath = roContext->errorStorage.aPath; + rwContext->activeCustomExceptionPath = roContext->customExceptionStorage.aPath; + + rwContext->userKVCount = 0; + rwContext->internalKVCount = 0; + rwContext->errorsCount = 0; + + roContext->userKVStorage.maxIncrementalCount = FIRCLSUserLoggingMaxKVEntries; + roContext->internalKVStorage.maxIncrementalCount = roContext->userKVStorage.maxIncrementalCount; +} + +#pragma mark - KV Logging +void FIRCLSUserLoggingRecordInternalKeyValue(NSString *key, id value) { + FIRCLSUserLoggingRecordKeyValue(key, value, &_firclsContext.readonly->logging.internalKVStorage, + &_firclsContext.writable->logging.internalKVCount); +} + +void FIRCLSUserLoggingWriteInternalKeyValue(NSString *key, NSString *value) { + // Unsynchronized - must be run on the correct queue + FIRCLSUserLoggingWriteKeyValue(key, value, &_firclsContext.readonly->logging.internalKVStorage, + &_firclsContext.writable->logging.internalKVCount); +} + +void FIRCLSUserLoggingRecordUserKeyValue(NSString *key, id value) { + FIRCLSUserLoggingRecordKeyValue(key, value, &_firclsContext.readonly->logging.userKVStorage, + &_firclsContext.writable->logging.userKVCount); +} + +static id FIRCLSUserLoggingGetComponent(NSDictionary *entry, + NSString *componentName, + bool decodeHex) { + id value = [entry objectForKey:componentName]; + + return (decodeHex && value != [NSNull null]) ? FIRCLSFileHexDecodeString([value UTF8String]) + : value; +} + +static NSString *FIRCLSUserLoggingGetKey(NSDictionary *entry, bool decodeHex) { + return FIRCLSUserLoggingGetComponent(entry, @"key", decodeHex); +} + +static id FIRCLSUserLoggingGetValue(NSDictionary *entry, bool decodeHex) { + return FIRCLSUserLoggingGetComponent(entry, @"value", decodeHex); +} + +NSDictionary *FIRCLSUserLoggingGetCompactedKVEntries(FIRCLSUserLoggingKVStorage *storage, + bool decodeHex) { + if (!FIRCLSIsValidPointer(storage)) { + FIRCLSSDKLogError("storage invalid\n"); + return nil; + } + + NSArray *incrementalKVs = FIRCLSUserLoggingStoredKeyValues(storage->incrementalPath); + NSArray *compactedKVs = FIRCLSUserLoggingStoredKeyValues(storage->compactedPath); + + NSMutableDictionary *finalKVSet = [NSMutableDictionary new]; + + // These should all be unique, so there might be a more efficient way to + // do this + for (NSDictionary *entry in compactedKVs) { + NSString *key = FIRCLSUserLoggingGetKey(entry, decodeHex); + NSString *value = FIRCLSUserLoggingGetValue(entry, decodeHex); + + if (!key || !value) { + FIRCLSSDKLogError("compacted key/value contains a nil and must be dropped\n"); + continue; + } + + [finalKVSet setObject:value forKey:key]; + } + + // Now, assign the incremental values, in file order, so we overwrite any older values. + for (NSDictionary *entry in incrementalKVs) { + NSString *key = FIRCLSUserLoggingGetKey(entry, decodeHex); + NSString *value = FIRCLSUserLoggingGetValue(entry, decodeHex); + + if (!key || !value) { + FIRCLSSDKLogError("incremental key/value contains a nil and must be dropped\n"); + continue; + } + + if ([value isEqual:[NSNull null]]) { + [finalKVSet removeObjectForKey:key]; + } else { + [finalKVSet setObject:value forKey:key]; + } + } + + return finalKVSet; +} + +void FIRCLSUserLoggingCompactKVEntries(FIRCLSUserLoggingKVStorage *storage) { + if (!FIRCLSIsValidPointer(storage)) { + FIRCLSSDKLogError("Error: storage invalid\n"); + return; + } + + NSDictionary *finalKVs = FIRCLSUserLoggingGetCompactedKVEntries(storage, false); + + if (unlink(storage->compactedPath) != 0) { + FIRCLSSDKLog("Error: Unable to remove compacted KV store before compaction %s\n", + strerror(errno)); + } + + FIRCLSFile file; + + if (!FIRCLSFileInitWithPath(&file, storage->compactedPath, true)) { + FIRCLSSDKLog("Error: Unable to open compacted k-v file\n"); + return; + } + + uint32_t maxCount = storage->maxCount; + if ([finalKVs count] > maxCount) { + // We need to remove keys, to avoid going over the max. + // This is just about the worst way to go about doing this. There are lots of smarter ways, + // but it's very uncommon to go down this path. + NSArray *keys = [finalKVs allKeys]; + + FIRCLSSDKLogInfo("Truncating KV set, which is above max %d\n", maxCount); + + finalKVs = + [finalKVs dictionaryWithValuesForKeys:[keys subarrayWithRange:NSMakeRange(0, maxCount)]]; + } + + for (NSString *key in finalKVs) { + NSString *value = [finalKVs objectForKey:key]; + + FIRCLSFileWriteSectionStart(&file, "kv"); + FIRCLSFileWriteHashStart(&file); + // tricky - the values stored incrementally have already been hex-encoded + FIRCLSFileWriteHashEntryString(&file, "key", [key UTF8String]); + FIRCLSFileWriteHashEntryString(&file, "value", [value UTF8String]); + FIRCLSFileWriteHashEnd(&file); + FIRCLSFileWriteSectionEnd(&file); + } + + FIRCLSFileClose(&file); + + if (unlink(storage->incrementalPath) != 0) { + FIRCLSSDKLog("Error: Unable to remove incremental KV store after compaction %s\n", + strerror(errno)); + } +} + +void FIRCLSUserLoggingRecordKeyValue(NSString *key, + id value, + FIRCLSUserLoggingKVStorage *storage, + uint32_t *counter) { + if (!FIRCLSIsValidPointer(key)) { + FIRCLSSDKLogWarn("User provided bad key\n"); + return; + } + + // ensure that any invalid pointer is actually set to nil + if (!FIRCLSIsValidPointer(value) && value != nil) { + FIRCLSSDKLogWarn("Bad value pointer being clamped to nil\n"); + value = nil; + } + + if (!FIRCLSContextIsInitialized()) { + return; + } + + if ([value respondsToSelector:@selector(description)]) { + value = [value description]; + } else { + // passing nil will result in a JSON null being written, which is deserialized as [NSNull null], + // signaling to remove the key during compaction + value = nil; + } + + dispatch_sync(FIRCLSGetLoggingQueue(), ^{ + FIRCLSUserLoggingWriteKeyValue(key, value, storage, counter); + }); +} + +static void FIRCLSUserLoggingWriteKeyValue(NSString *key, + NSString *value, + FIRCLSUserLoggingKVStorage *storage, + uint32_t *counter) { + FIRCLSFile file; + + if (!FIRCLSIsValidPointer(storage) || !FIRCLSIsValidPointer(counter)) { + FIRCLSSDKLogError("Bad parameters\n"); + return; + } + + if (!FIRCLSFileInitWithPath(&file, storage->incrementalPath, true)) { + FIRCLSSDKLogError("Unable to open k-v file\n"); + return; + } + + FIRCLSFileWriteSectionStart(&file, "kv"); + FIRCLSFileWriteHashStart(&file); + FIRCLSFileWriteHashEntryHexEncodedString(&file, "key", [key UTF8String]); + FIRCLSFileWriteHashEntryHexEncodedString(&file, "value", [value UTF8String]); + FIRCLSFileWriteHashEnd(&file); + FIRCLSFileWriteSectionEnd(&file); + + FIRCLSFileClose(&file); + + *counter += 1; + if (*counter >= storage->maxIncrementalCount) { + dispatch_async(FIRCLSGetLoggingQueue(), ^{ + FIRCLSUserLoggingCompactKVEntries(storage); + *counter = 0; + }); + } +} + +NSArray *FIRCLSUserLoggingStoredKeyValues(const char *path) { + if (!FIRCLSContextIsInitialized()) { + return nil; + } + + return FIRCLSFileReadSections(path, true, ^NSObject *(id obj) { + return [obj objectForKey:@"kv"]; + }); +} + +#pragma mark - NSError Logging +static void FIRCLSUserLoggingRecordErrorUserInfo(FIRCLSFile *file, + const char *fileKey, + NSDictionary<NSString *, id> *userInfo) { + if ([userInfo count] == 0) { + return; + } + + FIRCLSFileWriteHashKey(file, fileKey); + FIRCLSFileWriteArrayStart(file); + + for (id key in userInfo) { + id value = [userInfo objectForKey:key]; + if (![value respondsToSelector:@selector(description)]) { + continue; + } + + FIRCLSFileWriteArrayStart(file); + FIRCLSFileWriteArrayEntryHexEncodedString(file, [key UTF8String]); + FIRCLSFileWriteArrayEntryHexEncodedString(file, [[value description] UTF8String]); + FIRCLSFileWriteArrayEnd(file); + } + + FIRCLSFileWriteArrayEnd(file); +} + +static void FIRCLSUserLoggingWriteError(FIRCLSFile *file, + NSError *error, + NSDictionary<NSString *, id> *additionalUserInfo, + NSArray *addresses, + uint64_t timestamp) { + FIRCLSFileWriteSectionStart(file, "error"); + FIRCLSFileWriteHashStart(file); + FIRCLSFileWriteHashEntryHexEncodedString(file, "domain", [[error domain] UTF8String]); + FIRCLSFileWriteHashEntryInt64(file, "code", [error code]); + FIRCLSFileWriteHashEntryUint64(file, "time", timestamp); + + // addresses + FIRCLSFileWriteHashKey(file, "stacktrace"); + FIRCLSFileWriteArrayStart(file); + for (NSNumber *address in addresses) { + FIRCLSFileWriteArrayEntryUint64(file, [address unsignedLongLongValue]); + } + FIRCLSFileWriteArrayEnd(file); + + // user-info + FIRCLSUserLoggingRecordErrorUserInfo(file, "info", [error userInfo]); + FIRCLSUserLoggingRecordErrorUserInfo(file, "extra_info", additionalUserInfo); + + FIRCLSFileWriteHashEnd(file); + FIRCLSFileWriteSectionEnd(file); +} + +void FIRCLSUserLoggingRecordError(NSError *error, + NSDictionary<NSString *, id> *additionalUserInfo) { + if (!error) { + return; + } + + if (!FIRCLSContextIsInitialized()) { + return; + } + + // record the stacktrace and timestamp here, so we + // are as close as possible to the user's log statement + NSArray *addresses = [NSThread callStackReturnAddresses]; + uint64_t timestamp = time(NULL); + + FIRCLSUserLoggingWriteAndCheckABFiles( + &_firclsContext.readonly->logging.errorStorage, + &_firclsContext.writable->logging.activeErrorLogPath, ^(FIRCLSFile *file) { + FIRCLSUserLoggingWriteError(file, error, additionalUserInfo, addresses, timestamp); + }); +} + +#pragma mark - CLSLog Support +void FIRCLSLog(NSString *format, ...) { + // If the format is nil do nothing just like NSLog. + if (!format) { + return; + } + + va_list args; + va_start(args, format); + NSString *msg = [[NSString alloc] initWithFormat:format arguments:args]; + va_end(args); + + FIRCLSLogInternal(msg); +} + +#pragma mark - Properties +uint32_t FIRCLSUserLoggingMaxLogSize(void) { + // don't forget that the message encoding overhead is 2x, and we + // wrap everything in a json structure with time. So, there is + // quite a penalty + + uint32_t size = 1024 * 64; + + return size * 2; +} + +uint32_t FIRCLSUserLoggingMaxErrorSize(void) { + return FIRCLSUserLoggingMaxLogSize(); +} + +#pragma mark - AB Logging +void FIRCLSUserLoggingCheckAndSwapABFiles(FIRCLSUserLoggingABStorage *storage, + const char **activePath, + off_t fileSize) { + if (!activePath || !storage) { + return; + } + + if (!*activePath) { + return; + } + + if (storage->restrictBySize) { + if (fileSize <= storage->maxSize) { + return; + } + } else { + if (!FIRCLSIsValidPointer(storage->entryCount)) { + FIRCLSSDKLogError("Error: storage has invalid pointer, but is restricted by entry count\n"); + return; + } + + if (*storage->entryCount < storage->maxEntries) { + return; + } + + // Here we have rolled over, so we have to reset our counter. + *storage->entryCount = 0; + } + + // if it is too big: + // - reset the other log + // - make it active + const char *otherPath = NULL; + + if (*activePath == storage->aPath) { + otherPath = storage->bPath; + } else { + // take this path if the pointer is invalid as well, to reset + otherPath = storage->aPath; + } + + // guard here against path being nil or empty + NSString *pathString = [NSString stringWithUTF8String:otherPath]; + + if ([pathString length] > 0) { + // ignore the error, because there is nothing we can do to recover here, and its likely + // any failures would be intermittent + + [[NSFileManager defaultManager] removeItemAtPath:pathString error:nil]; + } + + *activePath = otherPath; +} + +void FIRCLSUserLoggingWriteAndCheckABFiles(FIRCLSUserLoggingABStorage *storage, + const char **activePath, + void (^openedFileBlock)(FIRCLSFile *file)) { + if (!storage || !activePath || !openedFileBlock) { + return; + } + + if (!*activePath) { + return; + } + + if (storage->restrictBySize) { + if (storage->maxSize == 0) { + return; + } + } else { + if (storage->maxEntries == 0) { + return; + } + } + + dispatch_sync(FIRCLSGetLoggingQueue(), ^{ + FIRCLSFile file; + + if (!FIRCLSFileInitWithPath(&file, *activePath, true)) { + FIRCLSSDKLog("Unable to open log file\n"); + return; + } + + openedFileBlock(&file); + + off_t fileSize = 0; + FIRCLSFileCloseWithOffset(&file, &fileSize); + + // increment the count before calling FIRCLSUserLoggingCheckAndSwapABFiles, so the value + // reflects the actual amount of stuff written + if (!storage->restrictBySize && FIRCLSIsValidPointer(storage->entryCount)) { + *storage->entryCount += 1; + } + + dispatch_async(FIRCLSGetLoggingQueue(), ^{ + FIRCLSUserLoggingCheckAndSwapABFiles(storage, activePath, fileSize); + }); + }); +} + +void FIRCLSLogInternalWrite(FIRCLSFile *file, NSString *message, uint64_t time) { + FIRCLSFileWriteSectionStart(file, "log"); + FIRCLSFileWriteHashStart(file); + FIRCLSFileWriteHashEntryHexEncodedString(file, "msg", [message UTF8String]); + FIRCLSFileWriteHashEntryUint64(file, "time", time); + FIRCLSFileWriteHashEnd(file); + FIRCLSFileWriteSectionEnd(file); +} + +void FIRCLSLogInternal(NSString *message) { + if (!message) { + return; + } + + if (!FIRCLSContextIsInitialized()) { + FIRCLSWarningLog(@"WARNING: FIRCLSLog has been used before (or concurrently with) " + @"Crashlytics initialization and cannot be recorded. The message was: \n%@", + message); + return; + } + struct timeval te; + + NSUInteger messageLength = [message length]; + int maxLogSize = _firclsContext.readonly->logging.logStorage.maxSize; + + if (messageLength > maxLogSize) { + FIRCLSWarningLog( + @"WARNING: Attempted to write %zd bytes, but %d is the maximum size of the log. " + @"Truncating to %d bytes.\n", + messageLength, maxLogSize, maxLogSize); + message = [message substringToIndex:maxLogSize]; + } + + // unable to get time - abort + if (gettimeofday(&te, NULL) != 0) { + return; + } + + const uint64_t time = te.tv_sec * 1000LL + te.tv_usec / 1000; + + FIRCLSUserLoggingWriteAndCheckABFiles(&_firclsContext.readonly->logging.logStorage, + &_firclsContext.writable->logging.activeUserLogPath, + ^(FIRCLSFile *file) { + FIRCLSLogInternalWrite(file, message, time); + }); +} diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSNetworkClient.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSNetworkClient.h new file mode 100644 index 000000000..2c259c296 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSNetworkClient.h @@ -0,0 +1,61 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +typedef NS_ENUM(NSInteger, FIRCLSNetworkClientErrorType) { + FIRCLSNetworkClientErrorTypeUnknown = -1, + FIRCLSNetworkClientErrorTypeFileUnreadable = -2 +}; + +extern NSString *const FIRCLSNetworkClientErrorDomain; + +@protocol FIRCLSNetworkClientDelegate; +@class FIRCLSDataCollectionToken; +@class FIRCLSFileManager; + +@interface FIRCLSNetworkClient : NSObject + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)initWithQueue:(NSOperationQueue *)queue + fileManager:(FIRCLSFileManager *)fileManager + delegate:(id<FIRCLSNetworkClientDelegate>)delegate; + +@property(nonatomic, weak) id<FIRCLSNetworkClientDelegate> delegate; + +@property(nonatomic, readonly) NSOperationQueue *operationQueue; +@property(nonatomic, readonly) BOOL supportsBackgroundRequests; + +- (void)startUploadRequest:(NSURLRequest *)request + filePath:(NSString *)path + dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken + immediately:(BOOL)immediate; + +- (void)attemptToReconnectBackgroundSessionWithCompletionBlock:(void (^)(void))completionBlock; + +@end + +@class FIRCLSNetworkClient; + +@protocol FIRCLSNetworkClientDelegate <NSObject> +@required +- (BOOL)networkClientCanUseBackgroundSessions:(FIRCLSNetworkClient *)client; + +@optional +- (void)networkClient:(FIRCLSNetworkClient *)client + didFinishUploadWithPath:(NSString *)path + error:(NSError *)error; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSNetworkClient.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSNetworkClient.m new file mode 100644 index 000000000..5fee0ca9f --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSNetworkClient.m @@ -0,0 +1,366 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSNetworkClient.h" + +#import "FIRCLSApplication.h" +#import "FIRCLSByteUtility.h" +#import "FIRCLSDataCollectionToken.h" +#import "FIRCLSDefines.h" +#import "FIRCLSFileManager.h" +#import "FIRCLSNetworkResponseHandler.h" +#import "FIRCLSURLSession.h" +#import "FIRCLSURLSessionConfiguration.h" + +#import "FIRCLSUtility.h" + +NSString *const FIRCLSNetworkClientErrorDomain = @"FIRCLSNetworkError"; + +NSString *const FIRCLSNetworkClientBackgroundIdentifierSuffix = @".crash.background-session"; + +@interface FIRCLSNetworkClient () <NSURLSessionDelegate> { + NSURLSession *_session; +} + +@property(nonatomic, strong) void (^backgroundCompletionHandler)(void); +@property(nonatomic, strong, readonly) NSURLSession *session; +@property(nonatomic, assign) BOOL canUseBackgroundSession; +@property(nonatomic, strong) FIRCLSFileManager *fileManager; + +@end + +@implementation FIRCLSNetworkClient + +- (instancetype)initWithQueue:(NSOperationQueue *)queue + fileManager:(FIRCLSFileManager *)fileManager + delegate:(id<FIRCLSNetworkClientDelegate>)delegate { + self = [super init]; + if (!self) { + return nil; + } + + _operationQueue = queue; + _delegate = delegate; + _fileManager = fileManager; + + self.canUseBackgroundSession = [_delegate networkClientCanUseBackgroundSessions:self]; + + if (!self.supportsBackgroundRequests) { + FIRCLSDeveloperLog( + "Crashlytics:Crash:Client", + @"Background session uploading not supported, asynchronous uploading will be used"); + } + + return self; +} + +#pragma mark - Background Support +- (NSURLSession *)session { + // Creating a NSURLSession takes some time. Doing it lazily saves us time in the normal case. + if (_session) { + return _session; + } + + NSURLSessionConfiguration *config = nil; + + Class urlSessionClass; + Class urlSessionConfigurationClass; +#if FIRCLSURLSESSION_REQUIRED + urlSessionClass = [FIRCLSURLSession class]; + urlSessionConfigurationClass = [FIRCLSURLSessionConfiguration class]; +#else + urlSessionClass = [NSURLSession class]; + urlSessionConfigurationClass = [NSURLSessionConfiguration class]; +#endif + + if (self.supportsBackgroundRequests) { + NSString *sdkBundleID = FIRCLSApplicationGetSDKBundleID(); + NSString *backgroundConfigName = + [sdkBundleID stringByAppendingString:FIRCLSNetworkClientBackgroundIdentifierSuffix]; + + config = [urlSessionConfigurationClass backgroundSessionConfiguration:backgroundConfigName]; +#if TARGET_OS_IPHONE + [config setSessionSendsLaunchEvents:NO]; +#endif + } + + if (!config) { + // take this code path if we don't support background requests OR if we failed to create a + // background configuration + config = [urlSessionConfigurationClass defaultSessionConfiguration]; + } + + _session = [urlSessionClass sessionWithConfiguration:config + delegate:self + delegateQueue:self.operationQueue]; + + if (!_session || !config) { + FIRCLSErrorLog(@"Failed to initialize"); + } + + return _session; +} + +#if FIRCLSURLSESSION_REQUIRED +- (BOOL)NSURLSessionAvailable { + if ([[FIRCLSURLSession class] respondsToSelector:@selector(NSURLSessionShouldBeUsed)]) { + return [FIRCLSURLSession NSURLSessionShouldBeUsed]; + } + + return NSClassFromString(@"NSURLSession") != nil; +} +#endif + +- (BOOL)supportsBackgroundRequests { + return !FIRCLSApplicationIsExtension() +#if FIRCLSURLSESSION_REQUIRED + && [self NSURLSessionAvailable] +#endif + && self.canUseBackgroundSession; +} + +- (void)attemptToReconnectBackgroundSessionWithCompletionBlock:(void (^)(void))completionBlock { + if (!self.supportsBackgroundRequests) { + if (completionBlock) { + completionBlock(); + } + return; + } + + // This is the absolute minimum necessary. Perhaps we can do better? + if (completionBlock) { + [[NSOperationQueue mainQueue] addOperationWithBlock:completionBlock]; + } +} + +#pragma mark - API +- (void)startUploadRequest:(NSURLRequest *)request + filePath:(NSString *)path + dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken + immediately:(BOOL)immediate { + if (![dataCollectionToken isValid]) { + FIRCLSErrorLog(@"An upload was requested with an invalid data collection token."); + return; + } + + if (immediate) { + [self startImmediateUploadRequest:request filePath:path]; + return; + } + + NSString *description = [self relativeTaskPathForAbsolutePath:path]; + [self checkForExistingTaskMatchingDescription:description + completionBlock:^(BOOL found) { + if (found) { + FIRCLSDeveloperLog( + "Crashlytics:Crash:Client", + @"A task currently exists for this upload, skipping"); + return; + } + + [self startNewUploadRequest:request filePath:path]; + }]; +} + +#pragma mark - Support API +- (void)startImmediateUploadRequest:(NSURLRequest *)request filePath:(NSString *)path { + // check the ivar directly, to avoid going back to the delegate + if (self.supportsBackgroundRequests) { + // this can be done here, because the request will be started synchronously. + [self startNewUploadRequest:request filePath:path]; + return; + } + + if (![[NSFileManager defaultManager] isReadableFileAtPath:path]) { + FIRCLSSDKLog("Error: file unreadable\n"); + // Following the same logic as below, do not try to inform the delegate + return; + } + + NSMutableURLRequest *mutableRequest = [request mutableCopy]; + + [mutableRequest setHTTPBodyStream:[NSInputStream inputStreamWithFileAtPath:path]]; + + NSURLResponse *requestResponse = nil; + + [[NSURLSession sharedSession] + dataTaskWithRequest:mutableRequest + completionHandler:^(NSData *_Nullable data, NSURLResponse *_Nullable response, + NSError *_Nullable error) { + [FIRCLSNetworkResponseHandler + clientResponseType:requestResponse + handler:^(FIRCLSNetworkClientResponseType type, NSInteger statusCode) { + if (type != FIRCLSNetworkClientResponseSuccess) { + // don't even inform the delegate of a failure here, because we don't + // want any action to be taken synchronously + return; + } + + [[self delegate] networkClient:self + didFinishUploadWithPath:path + error:error]; + }]; + }]; +} + +- (void)startNewUploadRequest:(NSURLRequest *)request filePath:(NSString *)path { + if (![[NSFileManager defaultManager] isReadableFileAtPath:path]) { + [self.operationQueue addOperationWithBlock:^{ + [self + handleTaskDescription:path + completedWithError:[NSError errorWithDomain:FIRCLSNetworkClientErrorDomain + code:FIRCLSNetworkClientErrorTypeFileUnreadable + userInfo:@{@"path" : path}]]; + }]; + + return; + } + + NSURLSessionUploadTask *task = [self.session uploadTaskWithRequest:request + fromFile:[NSURL fileURLWithPath:path]]; + + // set the description, so we can determine what file was successfully uploaded later on + [task setTaskDescription:[self relativeTaskPathForAbsolutePath:path]]; + + [task resume]; +} + +- (NSString *)rootPath { + return self.fileManager.rootPath; +} + +- (NSString *)absolutePathForRelativeTaskPath:(NSString *)path { + return [self.rootPath stringByAppendingPathComponent:path]; +} + +- (NSString *)relativeTaskPathForAbsolutePath:(NSString *)path { + // make sure this has a tailing slash, so the path looks relative + NSString *root = [self.rootPath stringByAppendingString:@"/"]; + + if (![path hasPrefix:root]) { + FIRCLSSDKLog("Error: path '%s' is not at the root '%s'", [path UTF8String], [root UTF8String]); + return nil; + } + + return [path stringByReplacingOccurrencesOfString:root withString:@""]; +} + +#pragma mark - Task Management +- (BOOL)taskArray:(NSArray *)array hasTaskMatchingDescription:(NSString *)description { + NSUInteger idx = [array indexOfObjectPassingTest:^BOOL(id obj, NSUInteger arrayIdx, BOOL *stop) { + return [[obj taskDescription] isEqualToString:description]; + }]; + + return idx != NSNotFound; +} + +- (void)checkSession:(NSURLSession *)session + forTasksMatchingDescription:(NSString *)description + completionBlock:(void (^)(BOOL found))block { + if (!session) { + block(NO); + return; + } + + [session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, + NSArray *downloadTasks) { + if ([self taskArray:uploadTasks hasTaskMatchingDescription:description]) { + block(YES); + return; + } + + if ([self taskArray:dataTasks hasTaskMatchingDescription:description]) { + block(YES); + return; + } + + if ([self taskArray:downloadTasks hasTaskMatchingDescription:description]) { + block(YES); + return; + } + + block(NO); + }]; +} + +- (void)checkForExistingTaskMatchingDescription:(NSString *)description + completionBlock:(void (^)(BOOL found))block { + // Do not instantiate the normal session, because if it doesn't exist yet, it cannot possibly have + // existing tasks + [_operationQueue addOperationWithBlock:^{ + [self checkSession:self.session + forTasksMatchingDescription:description + completionBlock:^(BOOL found) { + block(found); + }]; + }]; +} + +#pragma mark - Result Handling +// This method is duplicated from FIRCLSFABNetworkClient. Sharing it is a little weird - I didn't +// feel like it fit into FIRCLSNetworkResponseHandler. +- (void)runAfterRetryValueFromResponse:(NSURLResponse *)response block:(void (^)(void))block { + NSTimeInterval delay = [FIRCLSNetworkResponseHandler retryValueForResponse:response]; + + // FIRCLSDeveloperLog("Network", @"Restarting request after %f", delay); + + FIRCLSAddOperationAfter(delay, _operationQueue, block); +} + +- (void)restartTask:(NSURLSessionTask *)task { + NSURLRequest *request = [task originalRequest]; + + [self runAfterRetryValueFromResponse:[task response] + block:^{ + NSString *path = [self + absolutePathForRelativeTaskPath:[task taskDescription]]; + + [self startNewUploadRequest:request filePath:path]; + }]; +} + +- (void)handleTask:(NSURLSessionTask *)task completedWithError:(NSError *)error { + [self handleTaskDescription:[task taskDescription] completedWithError:error]; +} + +- (void)handleTaskDescription:(NSString *)taskDescription completedWithError:(NSError *)error { + NSString *path = [self absolutePathForRelativeTaskPath:taskDescription]; + + [[self delegate] networkClient:self didFinishUploadWithPath:path error:error]; +} + +#pragma mark - NSURLSessionDelegate +- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error { + FIRCLSDeveloperLog("Crashlytics:Crash:Client", @"session became invalid: %@", error); +} + +// Careful! Not implementing this method appears to cause a crash when using a background task +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + didCompleteWithError:(NSError *)error { + [FIRCLSNetworkResponseHandler handleCompletedResponse:task.response + forOriginalRequest:task.originalRequest + error:error + block:^(BOOL restart, NSError *taskError) { + if (restart) { + [self restartTask:task]; + return; + } + + [self handleTask:task + completedWithError:taskError]; + }]; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager.h new file mode 100644 index 000000000..02b7031a5 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager.h @@ -0,0 +1,57 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +#include "FIRCLSApplicationIdentifierModel.h" +#include "FIRCLSProfiling.h" +#include "FIRCrashlytics.h" + +@class FBLPromise<T>; + +NS_ASSUME_NONNULL_BEGIN + +@class FIRCLSDataCollectionArbiter; +@class FIRCLSFileManager; +@class FIRCLSInternalReport; +@class FIRCLSSettings; +@class GDTCORTransport; +@class FIRInstallations; +@protocol FIRAnalyticsInterop; + +@interface FIRCLSReportManager : NSObject + +- (instancetype)initWithFileManager:(FIRCLSFileManager *)fileManager + installations:(FIRInstallations *)installations + analytics:(nullable id<FIRAnalyticsInterop>)analytics + googleAppID:(NSString *)googleAppID + dataArbiter:(FIRCLSDataCollectionArbiter *)dataArbiter + googleTransport:(GDTCORTransport *)googleTransport + appIDModel:(FIRCLSApplicationIdentifierModel *)appIDModel + settings:(FIRCLSSettings *)settings NS_DESIGNATED_INITIALIZER; +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +- (FBLPromise<NSNumber *> *)startWithProfilingMark:(FIRCLSProfileMark)mark; + +- (FBLPromise<NSNumber *> *)checkForUnsentReports; +- (FBLPromise *)sendUnsentReports; +- (FBLPromise *)deleteUnsentReports; + +@end + +extern NSString *const FIRCLSConfigSubmitReportsKey; +extern NSString *const FIRCLSConfigPackageReportsKey; + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager.m new file mode 100644 index 000000000..cf04b3f1f --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager.m @@ -0,0 +1,909 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +// The report manager has the ability to send to two different endpoints. +// +// The old legacy flow for a report goes through the following states/folders: +// 1. active - .clsrecords optimized for crash time persistence +// 2. processing - .clsrecords with attempted symbolication +// 3. prepared-legacy - .multipartmime of compressed .clsrecords +// +// The new flow for a report goes through the following states/folders: +// 1. active - .clsrecords optimized for crash time persistence +// 2. processing - .clsrecords with attempted symbolication +// 3. prepared - .clsrecords moved from processing with no changes +// +// The code was designed so the report processing workflows are not dramatically different from one +// another. The design will help avoid having a lot of conditional code blocks throughout the +// codebase. +// + +#include <stdatomic.h> + +#if __has_include(<FBLPromises/FBLPromises.h>) +#import <FBLPromises/FBLPromises.h> +#else +#import "FBLPromises.h" +#endif + +#import "FIRCLSApplication.h" +#import "FIRCLSDataCollectionArbiter.h" +#import "FIRCLSDataCollectionToken.h" +#import "FIRCLSDefines.h" +#import "FIRCLSFeatures.h" +#import "FIRCLSFileManager.h" +#import "FIRCLSInternalReport.h" +#import "FIRCLSLogger.h" +#import "FIRCLSNetworkClient.h" +#import "FIRCLSPackageReportOperation.h" +#import "FIRCLSProcessReportOperation.h" +#import "FIRCLSReportUploader.h" +#import "FIRCLSSettings.h" +#import "FIRCLSSymbolResolver.h" +#import "FIRCLSUserLogging.h" + +#include "FIRCLSGlobals.h" +#include "FIRCLSUtility.h" + +#import "FIRCLSConstants.h" +#import "FIRCLSExecutionIdentifierModel.h" +#import "FIRCLSInstallIdentifierModel.h" +#import "FIRCLSSettingsOnboardingManager.h" + +#import "FIRCLSReportManager_Private.h" + +#import "Interop/Analytics/Public/FIRAnalyticsInterop.h" +#import "Interop/Analytics/Public/FIRAnalyticsInteropListener.h" + +#include "FIRAEvent+Internal.h" +#include "FIRCLSFCRAnalytics.h" + +#if TARGET_OS_IPHONE +#import <UIKit/UIKit.h> +#else +#import <AppKit/AppKit.h> +#endif + +static NSTimeInterval const CLSReportRetryInterval = 10 * 60; + +static NSString *FIRCLSFirebaseAnalyticsEventLogFormat = @"$A$:%@"; + +@interface FIRCLSAnalyticsInteropListener : NSObject <FIRAnalyticsInteropListener> { +} +@end + +@implementation FIRCLSAnalyticsInteropListener + +- (void)messageTriggered:(NSString *)name parameters:(NSDictionary *)parameters { + NSDictionary *event = @{ + @"name" : name, + @"parameters" : parameters, + }; + NSString *json = FIRCLSFIRAEventDictionaryToJSON(event); + if (json != nil) { + FIRCLSLog(FIRCLSFirebaseAnalyticsEventLogFormat, json); + } +} + +@end + +/** + * A FIRReportAction is used to indicate how to handle unsent reports. + */ +typedef NS_ENUM(NSInteger, FIRCLSReportAction) { + /** Upload the reports to Crashlytics. */ + FIRCLSReportActionSend, + /** Delete the reports without uploading them. */ + FIRCLSReportActionDelete, +}; + +/** + * This is just a helper to make code using FIRReportAction more readable. + */ +typedef NSNumber FIRCLSWrappedReportAction; +@implementation NSNumber (FIRCLSWrappedReportAction) +- (FIRCLSReportAction)reportActionValue { + return [self intValue]; +} +@end + +/** + * This is a helper to make code using NSNumber for bools more readable. + */ +typedef NSNumber FIRCLSWrappedBool; + +@interface FIRCLSReportManager () <FIRCLSNetworkClientDelegate, + FIRCLSReportUploaderDelegate, + FIRCLSReportUploaderDataSource> { + FIRCLSFileManager *_fileManager; + FIRCLSNetworkClient *_networkClient; + FIRCLSReportUploader *_uploader; + dispatch_queue_t _dispatchQueue; + NSOperationQueue *_operationQueue; + id<FIRAnalyticsInterop> _analytics; + + // A promise that will be resolved when unsent reports are found on the device, and + // processReports: can be called to decide how to deal with them. + FBLPromise<FIRCLSWrappedBool *> *_unsentReportsAvailable; + + // A promise that will be resolved when the user has provided an action that they want to perform + // for all the unsent reports. + FBLPromise<FIRCLSWrappedReportAction *> *_reportActionProvided; + + // A promise that will be resolved when all unsent reports have been "handled". They won't + // necessarily have been uploaded, but we will know whether they should be sent or deleted, and + // the initial work to make that happen will have been processed on the work queue. + // + // Currently only used for testing + FBLPromise *_unsentReportsHandled; + + // A token to make sure that checkForUnsentReports only gets called once. + atomic_bool _checkForUnsentReportsCalled; + + BOOL _registeredAnalyticsEventListener; +} + +@property(nonatomic, readonly) NSString *googleAppID; + +@property(nonatomic, strong) FIRCLSDataCollectionArbiter *dataArbiter; + +// Uniquely identifies a build / binary of the app +@property(nonatomic, strong) FIRCLSApplicationIdentifierModel *appIDModel; + +// Uniquely identifies an install of the app +@property(nonatomic, strong) FIRCLSInstallIdentifierModel *installIDModel; + +// Uniquely identifies a run of the app +@property(nonatomic, strong) FIRCLSExecutionIdentifierModel *executionIDModel; + +// Settings fetched from the server +@property(nonatomic, strong) FIRCLSSettings *settings; + +// Runs the operations that fetch settings and call onboarding endpoints +@property(nonatomic, strong) FIRCLSSettingsOnboardingManager *settingsAndOnboardingManager; + +@property(nonatomic, strong) GDTCORTransport *googleTransport; + +@end + +@implementation FIRCLSReportManager + +// Used only for internal data collection E2E testing +static void (^reportSentCallback)(void); + +- (instancetype)initWithFileManager:(FIRCLSFileManager *)fileManager + installations:(FIRInstallations *)installations + analytics:(id<FIRAnalyticsInterop>)analytics + googleAppID:(NSString *)googleAppID + dataArbiter:(FIRCLSDataCollectionArbiter *)dataArbiter + googleTransport:(GDTCORTransport *)googleTransport + appIDModel:(FIRCLSApplicationIdentifierModel *)appIDModel + settings:(FIRCLSSettings *)settings { + self = [super init]; + if (!self) { + return nil; + } + + _fileManager = fileManager; + _analytics = analytics; + _googleAppID = [googleAppID copy]; + _dataArbiter = dataArbiter; + + _googleTransport = googleTransport; + + NSString *sdkBundleID = FIRCLSApplicationGetSDKBundleID(); + + _operationQueue = [NSOperationQueue new]; + [_operationQueue setMaxConcurrentOperationCount:1]; + [_operationQueue setName:[sdkBundleID stringByAppendingString:@".work-queue"]]; + + _dispatchQueue = dispatch_queue_create("com.google.firebase.crashlytics.startup", 0); + _operationQueue.underlyingQueue = _dispatchQueue; + + _networkClient = [self clientWithOperationQueue:_operationQueue]; + + _unsentReportsAvailable = [FBLPromise pendingPromise]; + _reportActionProvided = [FBLPromise pendingPromise]; + _unsentReportsHandled = [FBLPromise pendingPromise]; + + _checkForUnsentReportsCalled = NO; + + _installIDModel = [[FIRCLSInstallIdentifierModel alloc] initWithInstallations:installations]; + _executionIDModel = [[FIRCLSExecutionIdentifierModel alloc] init]; + + _settings = settings; + _appIDModel = appIDModel; + + _settingsAndOnboardingManager = + [[FIRCLSSettingsOnboardingManager alloc] initWithAppIDModel:appIDModel + installIDModel:self.installIDModel + settings:self.settings + fileManager:self.fileManager + googleAppID:self.googleAppID]; + + return self; +} + +- (FIRCLSNetworkClient *)clientWithOperationQueue:(NSOperationQueue *)queue { + return [[FIRCLSNetworkClient alloc] initWithQueue:queue fileManager:_fileManager delegate:self]; +} + +/** + * Returns the number of unsent reports on the device, including the ones passed in. + */ +- (int)unsentReportsCountWithPreexisting:(NSArray<NSString *> *)paths { + int count = [self countSubmittableAndDeleteUnsubmittableReportPaths:paths]; + + count += _fileManager.processingPathContents.count; + + if (self.settings.shouldUseNewReportEndpoint) { + count += _fileManager.preparedPathContents.count; + } else { + count += _fileManager.legacyPreparedPathContents.count; + } + return count; +} + +// This method returns a promise that is resolved with a wrapped FIRReportAction once the user has +// indicated whether they want to upload currently cached reports. +// This method should only be called when we have determined there is at least 1 unsent report. +// This method waits until either: +// 1. Data collection becomes enabled, in which case, the promise will be resolved with Send. +// 2. The developer uses the processCrashReports API to indicate whether the report +// should be sent or deleted, at which point the promise will be resolved with the action. +- (FBLPromise<FIRCLSWrappedReportAction *> *)waitForReportAction { + FIRCLSDebugLog(@"[Crashlytics:Crash] Notifying that unsent reports are available."); + [_unsentReportsAvailable fulfill:@YES]; + + // If data collection gets enabled while we are waiting for an action, go ahead and send the + // reports, and any subsequent explicit response will be ignored. + FBLPromise<FIRCLSWrappedReportAction *> *collectionEnabled = + [[self.dataArbiter waitForCrashlyticsCollectionEnabled] + then:^id _Nullable(NSNumber *_Nullable value) { + return @(FIRCLSReportActionSend); + }]; + + FIRCLSDebugLog(@"[Crashlytics:Crash] Waiting for send/deleteUnsentReports to be called."); + // Wait for either the processReports callback to be called, or data collection to be enabled. + return [FBLPromise race:@[ collectionEnabled, _reportActionProvided ]]; +} + +- (FBLPromise<FIRCLSWrappedBool *> *)checkForUnsentReports { + bool expectedCalled = NO; + if (!atomic_compare_exchange_strong(&_checkForUnsentReportsCalled, &expectedCalled, YES)) { + FIRCLSErrorLog(@"checkForUnsentReports should only be called once per execution."); + return [FBLPromise resolvedWith:@NO]; + } + return _unsentReportsAvailable; +} + +- (FBLPromise *)sendUnsentReports { + [_reportActionProvided fulfill:@(FIRCLSReportActionSend)]; + return _unsentReportsHandled; +} + +- (FBLPromise *)deleteUnsentReports { + [_reportActionProvided fulfill:@(FIRCLSReportActionDelete)]; + return _unsentReportsHandled; +} + +- (FBLPromise<NSNumber *> *)startWithProfilingMark:(FIRCLSProfileMark)mark { + NSString *executionIdentifier = self.executionIDModel.executionID; + + // This needs to be called before any values are read from settings + NSTimeInterval currentTimestamp = [NSDate timeIntervalSinceReferenceDate]; + [self.settings reloadFromCacheWithGoogleAppID:self.googleAppID currentTimestamp:currentTimestamp]; + + if (![self validateAppIdentifiers]) { + return [FBLPromise resolvedWith:@NO]; + } + +#if DEBUG + FIRCLSDebugLog(@"Root: %@", [_fileManager rootPath]); +#endif + + if ([self.dataArbiter isLegacyDataCollectionKeyInPlist]) { + FIRCLSErrorLog(@"Found legacy data collection key in app's Info.plist: " + @"firebase_crashlytics_collection_enabled"); + FIRCLSErrorLog(@"Please update your Info.plist to use the new data collection key: " + @"FirebaseCrashlyticsCollectionEnabled"); + FIRCLSErrorLog(@"The legacy data collection Info.plist value could be overridden by " + @"calling: [Fabric with:...]"); + FIRCLSErrorLog(@"The new value can be overridden by calling: [[FIRCrashlytics " + @"crashlytics] setCrashlyticsCollectionEnabled:<isEnabled>]"); + + return [FBLPromise resolvedWith:@NO]; + } + + if (![_fileManager createReportDirectories]) { + return [FBLPromise resolvedWith:@NO]; + } + + // Grab existing reports + BOOL launchFailure = [self checkForAndCreateLaunchMarker]; + NSArray *preexistingReportPaths = _fileManager.activePathContents; + + FIRCLSInternalReport *report = [self setupCurrentReport:executionIdentifier]; + if (!report) { + FIRCLSErrorLog(@"Unable to setup a new report"); + } + + if (![self startCrashReporterWithProfilingMark:mark report:report]) { + FIRCLSErrorLog(@"Unable to start crash reporter"); + report = nil; + } + + // Regenerate the Install ID on a background thread if it needs to rotate because + // fetching the Firebase Install ID can be slow on some devices. This should happen after we + // create the session on disk so that we can update the Install ID in the written crash report + // metadata. + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ + [self checkAndRotateInstallUUIDIfNeededWithReport:report]; + }); + + FBLPromise<NSNumber *> *promise = [FBLPromise resolvedWith:@(report != nil)]; + + if ([self.dataArbiter isCrashlyticsCollectionEnabled]) { + FIRCLSDebugLog(@"Automatic data collection is enabled."); + FIRCLSDebugLog(@"Unsent reports will be uploaded at startup"); + FIRCLSDataCollectionToken *dataCollectionToken = [FIRCLSDataCollectionToken validToken]; + + [self beginSettingsAndOnboardingWithToken:dataCollectionToken waitForSettingsRequest:NO]; + + [self beginReportUploadsWithToken:dataCollectionToken + preexistingReportPaths:preexistingReportPaths + blockingSend:launchFailure + report:report]; + + // If data collection is enabled, the SDK will not notify the user + // when unsent reports are available, or respect Send / DeleteUnsentReports + [_unsentReportsAvailable fulfill:@NO]; + + } else { + FIRCLSDebugLog(@"Automatic data collection is disabled."); + + // TODO: This counting of the file system happens on the main thread. Now that some of the other + // work below has been made async and moved to the dispatch queue, maybe we can move this code + // to the dispatch queue as well. + int unsentReportsCount = [self unsentReportsCountWithPreexisting:preexistingReportPaths]; + if (unsentReportsCount > 0) { + FIRCLSDebugLog( + @"[Crashlytics:Crash] %d unsent reports are available. Checking for upload permission.", + unsentReportsCount); + // Wait for an action to get sent, either from processReports: or automatic data collection. + promise = [[self waitForReportAction] + onQueue:_dispatchQueue + then:^id _Nullable(FIRCLSWrappedReportAction *_Nullable wrappedAction) { + // Process the actions for the reports on disk. + FIRCLSReportAction action = [wrappedAction reportActionValue]; + if (action == FIRCLSReportActionSend) { + FIRCLSDebugLog(@"Sending unsent reports."); + FIRCLSDataCollectionToken *dataCollectionToken = + [FIRCLSDataCollectionToken validToken]; + + // For the new report endpoint, the orgID is not needed. + // For the legacy report endpoint, wait on settings if orgID is not available. + BOOL waitForSetting = + !self.settings.shouldUseNewReportEndpoint && !self.settings.orgID; + + [self beginSettingsAndOnboardingWithToken:dataCollectionToken + waitForSettingsRequest:waitForSetting]; + + [self beginReportUploadsWithToken:dataCollectionToken + preexistingReportPaths:preexistingReportPaths + blockingSend:NO + report:report]; + + } else if (action == FIRCLSReportActionDelete) { + FIRCLSDebugLog(@"Deleting unsent reports."); + [self deleteUnsentReportsWithPreexisting:preexistingReportPaths]; + } else { + FIRCLSErrorLog(@"Unknown report action: %d", action); + } + return @(report != nil); + }]; + } else { + FIRCLSDebugLog(@"[Crashlytics:Crash] There are no unsent reports."); + [_unsentReportsAvailable fulfill:@NO]; + } + } + + if (report != nil) { + // capture the start-up time here, but record it asynchronously + double endMark = FIRCLSProfileEnd(mark); + + dispatch_async(FIRCLSGetLoggingQueue(), ^{ + FIRCLSUserLoggingWriteInternalKeyValue(FIRCLSStartTimeKey, [@(endMark) description]); + }); + } + + // To make the code more predictable and therefore testable, don't resolve the startup promise + // until the operations that got queued up for processing reports have been processed through the + // work queue. + NSOperationQueue *__weak queue = _operationQueue; + FBLPromise *__weak unsentReportsHandled = _unsentReportsHandled; + promise = [promise then:^id _Nullable(NSNumber *_Nullable value) { + [queue waitUntilAllOperationsAreFinished]; + // Signal that to callers of processReports that everything is finished. + [unsentReportsHandled fulfill:nil]; + return value; + }]; + + return promise; +} + +- (void)checkAndRotateInstallUUIDIfNeededWithReport:(FIRCLSInternalReport *)report { + [self.installIDModel regenerateInstallIDIfNeededWithBlock:^(BOOL didRotate) { + if (!didRotate) { + return; + } + + FIRCLSContextUpdateMetadata(report, self.settings, self.installIDModel, self->_fileManager); + }]; +} + +- (void)beginSettingsAndOnboardingWithToken:(FIRCLSDataCollectionToken *)token + waitForSettingsRequest:(BOOL)waitForSettings { + if (self.settings.isCacheExpired) { + // This method can be called more than once if the user calls + // SendUnsentReports again, so don't repeat the settings fetch + static dispatch_once_t settingsFetchOnceToken; + dispatch_once(&settingsFetchOnceToken, ^{ + [self.settingsAndOnboardingManager beginSettingsAndOnboardingWithGoogleAppId:self.googleAppID + token:token + waitForCompletion:waitForSettings]; + }); + } +} + +- (void)beginReportUploadsWithToken:(FIRCLSDataCollectionToken *)token + preexistingReportPaths:(NSArray *)preexistingReportPaths + blockingSend:(BOOL)blockingSend + report:(FIRCLSInternalReport *)report { + if (self.settings.collectReportsEnabled) { + [self processExistingReportPaths:preexistingReportPaths + dataCollectionToken:token + asUrgent:blockingSend]; + [self handleContentsInOtherReportingDirectoriesWithToken:token]; + + } else { + FIRCLSInfoLog(@"Collect crash reports is disabled"); + [self deleteUnsentReportsWithPreexisting:preexistingReportPaths]; + } +} + +- (BOOL)startCrashReporterWithProfilingMark:(FIRCLSProfileMark)mark + report:(FIRCLSInternalReport *)report { + if (!report) { + return NO; + } + + if (!FIRCLSContextInitialize(report, self.settings, self.installIDModel, _fileManager)) { + return NO; + } + + [self setupStateNotifications]; + + [self registerAnalyticsEventListener]; + + [self crashReportingSetupCompleted:mark]; + + return YES; +} + +- (void)crashReportingSetupCompleted:(FIRCLSProfileMark)mark { + // check our handlers + FIRCLSDispatchAfter(2.0, dispatch_get_main_queue(), ^{ + FIRCLSExceptionCheckHandlers((__bridge void *)(self)); + FIRCLSSignalCheckHandlers(); +#if CLS_MACH_EXCEPTION_SUPPORTED + FIRCLSMachExceptionCheckHandlers(); +#endif + }); + + // remove the launch failure marker and record the startup time + dispatch_async(dispatch_get_main_queue(), ^{ + [self removeLaunchFailureMarker]; + dispatch_async(FIRCLSGetLoggingQueue(), ^{ + FIRCLSUserLoggingWriteInternalKeyValue(FIRCLSFirstRunloopTurnTimeKey, + [@(FIRCLSProfileEnd(mark)) description]); + }); + }); +} + +- (BOOL)validateAppIdentifiers { + // When the ApplicationIdentifierModel fails to initialize, it is usually due to + // failing computeExecutableInfo. This can happen if the user sets the + // Exported Symbols File in Build Settings, and leaves off the one symbol + // that Crashlytics needs, "__mh_execute_header" (wich is defined in mach-o/ldsyms.h as + // _MH_EXECUTE_SYM). From https://github.com/firebase/firebase-ios-sdk/issues/5020 + if (!self.appIDModel) { + FIRCLSErrorLog( + @"Crashlytics could not find the symbol for the app's main function and cannot " + @"start up. This can happen when Exported Symbols File is set in Build Settings. To " + @"resolve this, add \"__mh_execute_header\" as a newline to your Exported Symbols File."); + return NO; + } + + if (self.appIDModel.bundleID.length == 0) { + FIRCLSErrorLog(@"An application must have a valid bundle identifier in its Info.plist"); + return NO; + } + + return YES; +} + +- (FIRCLSReportUploader *)uploader { + if (!_uploader) { + _uploader = [[FIRCLSReportUploader alloc] initWithQueue:self.operationQueue + delegate:self + dataSource:self + client:self.networkClient + fileManager:_fileManager + analytics:_analytics]; + } + + return _uploader; +} + +#pragma mark - Reporting Lifecycle + +- (FIRCLSInternalReport *)setupCurrentReport:(NSString *)executionIdentifier { + [self createLaunchFailureMarker]; + + NSString *reportPath = [_fileManager setupNewPathForExecutionIdentifier:executionIdentifier]; + + return [[FIRCLSInternalReport alloc] initWithPath:reportPath + executionIdentifier:executionIdentifier]; +} + +- (int)countSubmittableAndDeleteUnsubmittableReportPaths:(NSArray *)reportPaths { + int count = 0; + for (NSString *path in reportPaths) { + FIRCLSInternalReport *report = [FIRCLSInternalReport reportWithPath:path]; + if ([report needsToBeSubmitted]) { + count++; + } else { + [self.operationQueue addOperationWithBlock:^{ + [self->_fileManager removeItemAtPath:path]; + }]; + } + } + return count; +} + +- (void)processExistingReportPaths:(NSArray *)reportPaths + dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken + asUrgent:(BOOL)urgent { + for (NSString *path in reportPaths) { + [self processExistingActiveReportPath:path + dataCollectionToken:dataCollectionToken + asUrgent:urgent]; + } +} + +- (void)processExistingActiveReportPath:(NSString *)path + dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken + asUrgent:(BOOL)urgent { + FIRCLSInternalReport *report = [FIRCLSInternalReport reportWithPath:path]; + + // TODO: needsToBeSubmitted should really be called on the background queue. + if (![report needsToBeSubmitted]) { + [self.operationQueue addOperationWithBlock:^{ + [self->_fileManager removeItemAtPath:path]; + }]; + + return; + } + + if (urgent && [dataCollectionToken isValid]) { + // We can proceed without the delegate. + [[self uploader] prepareAndSubmitReport:report + dataCollectionToken:dataCollectionToken + asUrgent:urgent + withProcessing:YES]; + return; + } + + [self submitReport:report dataCollectionToken:dataCollectionToken]; +} + +- (void)submitReport:(FIRCLSInternalReport *)report + dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken { + [self.operationQueue addOperationWithBlock:^{ + [[self uploader] prepareAndSubmitReport:report + dataCollectionToken:dataCollectionToken + asUrgent:NO + withProcessing:YES]; + }]; + + [self didSubmitReport]; +} + +// This is the side-effect of calling deleteUnsentReports, or collect_reports setting +// being false +- (void)deleteUnsentReportsWithPreexisting:(NSArray *)preexistingReportPaths { + [self removeExistingReportPaths:preexistingReportPaths]; + + [self removeExistingReportPaths:self.fileManager.processingPathContents]; + if (self.settings.shouldUseNewReportEndpoint) { + [self removeExistingReportPaths:self.fileManager.preparedPathContents]; + } else { + [self removeExistingReportPaths:self.fileManager.legacyPreparedPathContents]; + } +} + +- (void)removeExistingReportPaths:(NSArray *)reportPaths { + [self.operationQueue addOperationWithBlock:^{ + for (NSString *path in reportPaths) { + [self.fileManager removeItemAtPath:path]; + } + }]; +} + +- (void)handleContentsInOtherReportingDirectoriesWithToken:(FIRCLSDataCollectionToken *)token { + [self handleExistingFilesInProcessingWithToken:token]; + [self handleExistingFilesInPreparedWithToken:token]; +} + +- (void)handleExistingFilesInProcessingWithToken:(FIRCLSDataCollectionToken *)token { + NSArray *processingPaths = _fileManager.processingPathContents; + + // deal with stuff in processing more carefully - do not process again + [self.operationQueue addOperationWithBlock:^{ + for (NSString *path in processingPaths) { + FIRCLSInternalReport *report = [FIRCLSInternalReport reportWithPath:path]; + [[self uploader] prepareAndSubmitReport:report + dataCollectionToken:token + asUrgent:NO + withProcessing:NO]; + } + }]; +} + +- (void)handleExistingFilesInPreparedWithToken:(FIRCLSDataCollectionToken *)token { + NSArray *preparedPaths = self.settings.shouldUseNewReportEndpoint + ? _fileManager.preparedPathContents + : _fileManager.legacyPreparedPathContents; + + // Give our network client a chance to reconnect here, if needed. This attempts to avoid + // trying to re-submit a prepared file that is already in flight. + [self.networkClient attemptToReconnectBackgroundSessionWithCompletionBlock:^{ + [self.operationQueue addOperationWithBlock:^{ + [self uploadPreexistingFiles:preparedPaths withToken:token]; + }]; + }]; +} + +- (void)uploadPreexistingFiles:(NSArray *)files withToken:(FIRCLSDataCollectionToken *)token { + // Because this could happen quite a bit after the inital set of files was + // captured, some could be completed (deleted). So, just double-check to make sure + // the file still exists. + + for (NSString *path in files) { + if (![[_fileManager underlyingFileManager] fileExistsAtPath:path]) { + continue; + } + + [[self uploader] uploadPackagedReportAtPath:path dataCollectionToken:token asUrgent:NO]; + } +} + +- (void)retryUploadForReportAtPath:(NSString *)path + dataCollectionToken:(FIRCLSDataCollectionToken *)token { + FIRCLSAddOperationAfter(CLSReportRetryInterval, self.operationQueue, ^{ + FIRCLSDeveloperLog("Crashlytics:Crash", @"re-attempting report submission"); + [[self uploader] uploadPackagedReportAtPath:path dataCollectionToken:token asUrgent:NO]; + }); +} + +#pragma mark - Launch Failure Detection +- (NSString *)launchFailureMarkerPath { + return [[_fileManager structurePath] stringByAppendingPathComponent:@"launchmarker"]; +} + +- (BOOL)createLaunchFailureMarker { + // It's tempting to use - [NSFileManger createFileAtPath:contents:attributes:] here. But that + // operation, even with empty/nil contents does a ton of work to write out nothing via a + // temporarly file. This is a much faster implemenation. + const char *path = [[self launchFailureMarkerPath] fileSystemRepresentation]; + +#if TARGET_OS_IPHONE + /* + * data-protected non-portable open(2) : + * int open_dprotected_np(user_addr_t path, int flags, int class, int dpflags, int mode) + */ + int fd = open_dprotected_np(path, O_WRONLY | O_CREAT | O_TRUNC, 4, 0, 0644); +#else + int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); +#endif + if (fd == -1) { + return NO; + } + + return close(fd) == 0; +} + +- (BOOL)launchFailureMarkerPresent { + return [[_fileManager underlyingFileManager] fileExistsAtPath:[self launchFailureMarkerPath]]; +} + +- (BOOL)removeLaunchFailureMarker { + return [_fileManager removeItemAtPath:[self launchFailureMarkerPath]]; +} + +- (BOOL)checkForAndCreateLaunchMarker { + BOOL launchFailure = [self launchFailureMarkerPresent]; + if (launchFailure) { + FIRCLSDeveloperLog("Crashlytics:Crash", + @"Last launch failed: this may indicate a crash shortly after app launch."); + } else { + [self createLaunchFailureMarker]; + } + + return launchFailure; +} + +#pragma mark - + +- (void)registerAnalyticsEventListener { + if (_registeredAnalyticsEventListener) { + return; + } + FIRCLSAnalyticsInteropListener *listener = [[FIRCLSAnalyticsInteropListener alloc] init]; + [FIRCLSFCRAnalytics registerEventListener:listener toAnalytics:_analytics]; + _registeredAnalyticsEventListener = YES; +} + +#pragma mark - Notifications +- (void)setupStateNotifications { + [self captureInitialNotificationStates]; + +#if TARGET_OS_IOS + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(willBecomeActive:) + name:UIApplicationWillEnterForegroundNotification + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(didBecomeInactive:) + name:UIApplicationDidEnterBackgroundNotification + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(didChangeOrientation:) + name:UIDeviceOrientationDidChangeNotification + object:nil]; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(didChangeUIOrientation:) + name:UIApplicationDidChangeStatusBarOrientationNotification + object:nil]; +#pragma clang diagnostic pop + +#elif CLS_TARGET_OS_OSX + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(willBecomeActive:) + name:@"NSApplicationWillBecomeActiveNotification" + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(didBecomeInactive:) + name:@"NSApplicationDidResignActiveNotification" + object:nil]; +#endif +} + +- (void)captureInitialNotificationStates { +#if TARGET_OS_IOS + UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; + UIInterfaceOrientation statusBarOrientation = + [FIRCLSApplicationSharedInstance() statusBarOrientation]; +#endif + + // It's nice to do this async, so we don't hold up the main thread while doing three + // consecutive IOs here. + dispatch_async(FIRCLSGetLoggingQueue(), ^{ + FIRCLSUserLoggingWriteInternalKeyValue(FIRCLSInBackgroundKey, @"0"); +#if TARGET_OS_IOS + FIRCLSUserLoggingWriteInternalKeyValue(FIRCLSDeviceOrientationKey, + [@(orientation) description]); + FIRCLSUserLoggingWriteInternalKeyValue(FIRCLSUIOrientationKey, + [@(statusBarOrientation) description]); +#endif + }); +} + +- (void)willBecomeActive:(NSNotification *)notification { + FIRCLSUserLoggingRecordInternalKeyValue(FIRCLSInBackgroundKey, @NO); +} + +- (void)didBecomeInactive:(NSNotification *)notification { + FIRCLSUserLoggingRecordInternalKeyValue(FIRCLSInBackgroundKey, @YES); +} + +#if TARGET_OS_IOS +- (void)didChangeOrientation:(NSNotification *)notification { + UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; + + FIRCLSUserLoggingRecordInternalKeyValue(FIRCLSDeviceOrientationKey, @(orientation)); +} + +- (void)didChangeUIOrientation:(NSNotification *)notification { + UIInterfaceOrientation statusBarOrientation = + [FIRCLSApplicationSharedInstance() statusBarOrientation]; + + FIRCLSUserLoggingRecordInternalKeyValue(FIRCLSUIOrientationKey, @(statusBarOrientation)); +} +#endif + +#pragma mark - FIRCLSNetworkClientDelegate +- (BOOL)networkClientCanUseBackgroundSessions:(FIRCLSNetworkClient *)client { + return !FIRCLSApplicationIsExtension(); +} + +- (void)networkClient:(FIRCLSNetworkClient *)client + didFinishUploadWithPath:(NSString *)path + error:(NSError *)error { + // Route this through to the reports uploader. + // Since this callback happens after an upload finished, then we can assume that the original data + // collection was authorized. This isn't ideal, but it's better than trying to plumb the data + // collection token through all the system networking callbacks. + FIRCLSDataCollectionToken *token = [FIRCLSDataCollectionToken validToken]; + [[self uploader] reportUploadAtPath:path dataCollectionToken:token completedWithError:error]; +} + +#pragma mark - FIRCLSReportUploaderDelegate + +- (void)didCompletePackageSubmission:(NSString *)path + dataCollectionToken:(FIRCLSDataCollectionToken *)token + error:(NSError *)error { + if (!error) { + FIRCLSDeveloperLog("Crashlytics:Crash", @"report submission successful"); + return; + } + + FIRCLSDeveloperLog("Crashlytics:Crash", @"report submission failed with error %@", error); + FIRCLSSDKLog("Error: failed to submit report '%s'\n", error.description.UTF8String); + + [self retryUploadForReportAtPath:path dataCollectionToken:token]; +} + +- (void)didCompleteAllSubmissions { + [self.operationQueue addOperationWithBlock:^{ + // Dealloc the reports uploader. If we need it again (if we re-enqueued submissions from + // didCompletePackageSubmission:, we can just create it again + self->_uploader = nil; + + FIRCLSDeveloperLog("Crashlytics:Crash", @"report submission complete"); + }]; +} + +#pragma mark - UITest Helpers + +// Used only for internal data collection E2E testing +- (void)didSubmitReport { + if (reportSentCallback) { + dispatch_async(dispatch_get_main_queue(), ^{ + reportSentCallback(); + }); + } +} + ++ (void)setReportSentCallback:(void (^)(void))callback { + reportSentCallback = callback; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager_Private.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager_Private.h new file mode 100644 index 000000000..f7f139740 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager_Private.h @@ -0,0 +1,36 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSReportManager.h" +#import "FIRCLSReportUploader.h" + +@class FIRCLSInstallIdentifierModel; + +@interface FIRCLSReportManager () <FIRCLSReportUploaderDelegate, FIRCLSReportUploaderDataSource> + +@property(nonatomic, strong) NSOperationQueue *operationQueue; +@property(nonatomic, strong) FIRCLSNetworkClient *networkClient; +@property(nonatomic, readonly) FIRCLSReportUploader *uploader; +@property(nonatomic, strong) FIRCLSFileManager *fileManager; + +@end + +@interface FIRCLSReportManager (PrivateMethods) + +- (BOOL)createLaunchFailureMarker; +- (BOOL)launchFailureMarkerPresent; + +- (BOOL)potentiallySubmittableCrashOccurred; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.h new file mode 100644 index 000000000..c1cf8b4a1 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.h @@ -0,0 +1,80 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +#import <GoogleDataTransport/GDTCORTransport.h> + +@class FIRCLSDataCollectionToken; +@class FIRCLSInternalReport; +@class FIRCLSSettings; +@class FIRCLSFileManager; +@class FIRCLSNetworkClient; +@class FIRCLSReportUploader; + +@protocol FIRCLSReportUploaderDelegate; +@protocol FIRCLSReportUploaderDataSource; +@protocol FIRAnalyticsInterop; + +@interface FIRCLSReportUploader : NSObject + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)initWithQueue:(NSOperationQueue *)queue + delegate:(id<FIRCLSReportUploaderDelegate>)delegate + dataSource:(id<FIRCLSReportUploaderDataSource>)dataSource + client:(FIRCLSNetworkClient *)client + fileManager:(FIRCLSFileManager *)fileManager + analytics:(id<FIRAnalyticsInterop>)analytics NS_DESIGNATED_INITIALIZER; + +@property(nonatomic, weak) id<FIRCLSReportUploaderDelegate> delegate; +@property(nonatomic, weak) id<FIRCLSReportUploaderDataSource> dataSource; + +@property(nonatomic, readonly) NSOperationQueue *operationQueue; +@property(nonatomic, readonly) FIRCLSNetworkClient *networkClient; +@property(nonatomic, readonly) FIRCLSFileManager *fileManager; + +- (BOOL)prepareAndSubmitReport:(FIRCLSInternalReport *)report + dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken + asUrgent:(BOOL)urgent + withProcessing:(BOOL)shouldProcess; + +- (BOOL)uploadPackagedReportAtPath:(NSString *)path + dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken + asUrgent:(BOOL)urgent; + +- (void)reportUploadAtPath:(NSString *)path + dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken + completedWithError:(NSError *)error; + +@end + +@protocol FIRCLSReportUploaderDelegate <NSObject> +@required + +- (void)didCompletePackageSubmission:(NSString *)path + dataCollectionToken:(FIRCLSDataCollectionToken *)token + error:(NSError *)error; +- (void)didCompleteAllSubmissions; + +@end + +@protocol FIRCLSReportUploaderDataSource <NSObject> +@required + +- (NSString *)googleAppID; +- (FIRCLSSettings *)settings; +- (GDTCORTransport *)googleTransport; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.m new file mode 100644 index 000000000..6b8263534 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.m @@ -0,0 +1,356 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Interop/Analytics/Public/FIRAnalyticsInterop.h" + +#import "FIRCLSApplication.h" +#import "FIRCLSDataCollectionArbiter.h" +#import "FIRCLSDataCollectionToken.h" +#import "FIRCLSDefines.h" +#import "FIRCLSFCRAnalytics.h" +#import "FIRCLSFileManager.h" +#import "FIRCLSInstallIdentifierModel.h" +#import "FIRCLSInternalReport.h" +#import "FIRCLSNetworkClient.h" +#import "FIRCLSPackageReportOperation.h" +#import "FIRCLSProcessReportOperation.h" +#import "FIRCLSReportAdapter.h" +#import "FIRCLSReportUploader_Private.h" +#import "FIRCLSSettings.h" +#import "FIRCLSSymbolResolver.h" + +#include "FIRCLSUtility.h" + +#import "FIRCLSConstants.h" +#import "FIRCLSMultipartMimeStreamEncoder.h" +#import "FIRCLSURLBuilder.h" + +#import <GoogleDataTransport/GDTCOREvent.h> +#import <GoogleDataTransport/GDTCORTransport.h> + +@interface FIRCLSReportUploader () { + id<FIRAnalyticsInterop> _analytics; +} +@end + +@implementation FIRCLSReportUploader + +- (instancetype)initWithQueue:(NSOperationQueue *)queue + delegate:(id<FIRCLSReportUploaderDelegate>)delegate + dataSource:(id<FIRCLSReportUploaderDataSource>)dataSource + client:(FIRCLSNetworkClient *)client + fileManager:(FIRCLSFileManager *)fileManager + analytics:(id<FIRAnalyticsInterop>)analytics { + self = [super init]; + if (!self) { + return nil; + } + + _operationQueue = queue; + _delegate = delegate; + _dataSource = dataSource; + _networkClient = client; + _fileManager = fileManager; + _analytics = analytics; + + return self; +} + +#pragma mark - Packaging and Submission +- (BOOL)prepareAndSubmitReport:(FIRCLSInternalReport *)report + dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken + asUrgent:(BOOL)urgent + withProcessing:(BOOL)shouldProcess { + __block BOOL success = NO; + + if (![dataCollectionToken isValid]) { + FIRCLSErrorLog(@"Data collection disabled and report will not be submitted"); + return NO; + } + + if (!self.dataSource.settings.orgID && !self.dataSource.settings.shouldUseNewReportEndpoint) { + FIRCLSDebugLog( + @"Skipping report with id '%@' this run of the app because Organization ID was " + @"nil. Report via the legacy endpoint will upload once settings are download successfully", + report.identifier); + return YES; + } + + FIRCLSApplicationActivity( + FIRCLSApplicationActivityDefault, @"Crashlytics Crash Report Processing", ^{ + if (shouldProcess) { + if (![self.fileManager moveItemAtPath:report.path + toDirectory:self.fileManager.processingPath]) { + FIRCLSErrorLog(@"Unable to move report for processing"); + return; + } + + // adjust the report's path, and process it + [report setPath:[self.fileManager.processingPath + stringByAppendingPathComponent:report.directoryName]]; + + FIRCLSSymbolResolver *resolver = [[FIRCLSSymbolResolver alloc] init]; + + FIRCLSProcessReportOperation *processOperation = + [[FIRCLSProcessReportOperation alloc] initWithReport:report resolver:resolver]; + + [processOperation start]; + } + + NSString *packagedPath; + + FIRCLSDebugLog(@"Preparing the report for the new endpoint: %d", + self.dataSource.settings.shouldUseNewReportEndpoint); + + // With the new report endpoint, the report is deleted once it is written to GDT + // Check if the report has a crash file before the report is moved or deleted + BOOL isCrash = report.isCrash; + + if (self.dataSource.settings.shouldUseNewReportEndpoint) { + // For the new endpoint, just move the .clsrecords from "processing" -> "prepared" + if (![self.fileManager moveItemAtPath:report.path + toDirectory:self.fileManager.preparedPath]) { + FIRCLSErrorLog(@"Unable to move report to prepared"); + return; + } + + packagedPath = [self.fileManager.preparedPath + stringByAppendingPathComponent:report.path.lastPathComponent]; + } else { + // For the legacy endpoint, continue generate the multipartmime file in "prepared-legacy" + FIRCLSPackageReportOperation *packageOperation = + [[FIRCLSPackageReportOperation alloc] initWithReport:report + fileManager:self.fileManager + settings:self.dataSource.settings]; + + [packageOperation start]; + packagedPath = packageOperation.finalPath; + if (!packagedPath) { + FIRCLSErrorLog(@"Unable to package report"); + return; + } + + if (![self.fileManager removeItemAtPath:report.path]) { + FIRCLSErrorLog(@"Unable to remove a processing item"); + } + } + + NSLog(@"[Firebase/Crashlytics] Packaged report with id '%@' for submission", + report.identifier); + + success = [self uploadPackagedReportAtPath:packagedPath + dataCollectionToken:dataCollectionToken + asUrgent:urgent]; + + // If the upload was successful and the report contained a crash forward it to Google + // Analytics. + if (success && isCrash) { + [FIRCLSFCRAnalytics logCrashWithTimeStamp:report.crashedOnDate.timeIntervalSince1970 + toAnalytics:self->_analytics]; + } + }); + + return success; +} + +- (BOOL)submitPackageMultipartMimeAtPath:(NSString *)multipartmimePath + dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken + synchronously:(BOOL)synchronous { + FIRCLSDeveloperLog(@"Crashlytics:Crash:Reports", "Submitting %@ %@", + synchronous ? @"sync" : @"async", multipartmimePath); + + if ([[[self fileManager] fileSizeAtPath:multipartmimePath] unsignedIntegerValue] == 0) { + FIRCLSDeveloperLog("Crashlytics:Crash:Reports", @"Already-submitted report being ignored"); + return NO; + } + + NSTimeInterval timeout = 10.0; + + // If we are submitting synchronously, be more aggressive with the timeout. However, + // we only need this if the client does not support background requests. + if (synchronous && ![[self networkClient] supportsBackgroundRequests]) { + timeout = 2.0; + } + + NSMutableURLRequest *request = [self mutableRequestWithURL:[self reportURL] timeout:timeout]; + + [request setHTTPMethod:@"POST"]; + + if (![self fillInRequest:request forMultipartMimeDataAtPath:multipartmimePath]) { + return NO; + } + + [[self networkClient] startUploadRequest:request + filePath:multipartmimePath + dataCollectionToken:dataCollectionToken + immediately:synchronous]; + + return YES; +} + +- (BOOL)uploadPackagedReportAtPath:(NSString *)path + dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken + asUrgent:(BOOL)urgent { + FIRCLSDeveloperLog("Crashlytics:Crash:Reports", @"Submitting report%@", + urgent ? @" as urgent" : @""); + + // Check with the legacy path as the new path will always be contained in the legacy path + BOOL isNewPreparedPath = ![path containsString:self.fileManager.legacyPreparedPath]; + + if (isNewPreparedPath && self.dataSource.settings.shouldUseNewReportEndpoint) { + if (![dataCollectionToken isValid]) { + FIRCLSErrorLog(@"A report upload was requested with an invalid data collection token."); + return NO; + } + + FIRCLSReportAdapter *adapter = + [[FIRCLSReportAdapter alloc] initWithPath:path googleAppId:self.dataSource.googleAppID]; + + GDTCOREvent *event = [self.dataSource.googleTransport eventForTransport]; + event.dataObject = adapter; + event.qosTier = GDTCOREventQoSFast; // Bypass batching, send immediately + + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + + __block BOOL success = YES; + + [self.dataSource.googleTransport + sendDataEvent:event + onComplete:^(BOOL wasWritten, NSError *error) { + if (!wasWritten) { + FIRCLSDeveloperLog("Crashlytics:Crash:Reports", + @"Failed to send crash report due to gdt write failure."); + success = NO; + return; + } + + if (error) { + FIRCLSDeveloperLog("Crashlytics:Crash:Reports", + @"Failed to send crash report due to gdt error: %@", + error.localizedDescription); + success = NO; + return; + } + + FIRCLSDeveloperLog("Crashlytics:Crash:Reports", + @"Completed report submission with id: %@", path.lastPathComponent); + + if (urgent) { + dispatch_semaphore_signal(semaphore); + } + + [self cleanUpSubmittedReportAtPath:path]; + }]; + + if (urgent) { + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + } + + return success; + + } else if (!isNewPreparedPath && !self.dataSource.settings.shouldUseNewReportEndpoint) { + return [self submitPackageMultipartMimeAtPath:path + dataCollectionToken:dataCollectionToken + synchronously:urgent]; + } + + // Unsupported state + return NO; +} + +- (BOOL)cleanUpSubmittedReportAtPath:(NSString *)path { + if (![[self fileManager] removeItemAtPath:path]) { + FIRCLSErrorLog(@"Unable to remove packaged submission"); + return NO; + } + + return YES; +} + +- (void)reportUploadAtPath:(NSString *)path + dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken + completedWithError:(NSError *)error { + FIRCLSDeveloperLog("Crashlytics:Crash:Reports", @"completed submission of %@", path); + + if (!error) { + [self cleanUpSubmittedReportAtPath:path]; + } + + [[self delegate] didCompletePackageSubmission:path + dataCollectionToken:dataCollectionToken + error:error]; +} + +#pragma mark - Properties (TODO: Can delete once the experiment is over) + +- (NSURL *)reportURL { + FIRCLSURLBuilder *url = [FIRCLSURLBuilder URLWithBase:FIRCLSReportsEndpoint]; + + [url appendComponent:@"/sdk-api/v1/platforms/"]; + [url appendComponent:FIRCLSApplicationGetPlatform()]; + [url appendComponent:@"/apps/"]; + [url appendComponent:self.dataSource.settings.fetchedBundleID]; + [url appendComponent:@"/reports"]; + + return [url URL]; +} + +- (NSString *)localeIdentifier { + return [[NSLocale currentLocale] localeIdentifier]; +} + +#pragma mark - URL Requests +- (NSMutableURLRequest *)mutableRequestWithURL:(NSURL *)url timeout:(NSTimeInterval)timeout { + NSMutableURLRequest *request = + [NSMutableURLRequest requestWithURL:url + cachePolicy:NSURLRequestReloadIgnoringLocalCacheData + timeoutInterval:timeout]; + + NSString *localeId = [self localeIdentifier]; + + [request setValue:@CLS_SDK_GENERATOR_NAME forHTTPHeaderField:FIRCLSNetworkUserAgent]; + [request setValue:FIRCLSNetworkApplicationJson forHTTPHeaderField:FIRCLSNetworkAccept]; + [request setValue:FIRCLSNetworkUTF8 forHTTPHeaderField:FIRCLSNetworkAcceptCharset]; + [request setValue:localeId forHTTPHeaderField:FIRCLSNetworkAcceptLanguage]; + [request setValue:localeId forHTTPHeaderField:FIRCLSNetworkContentLanguage]; + [request setValue:FIRCLSDeveloperToken forHTTPHeaderField:FIRCLSNetworkCrashlyticsDeveloperToken]; + [request setValue:FIRCLSApplicationGetSDKBundleID() + forHTTPHeaderField:FIRCLSNetworkCrashlyticsAPIClientId]; + [request setValue:@CLS_SDK_DISPLAY_VERSION + forHTTPHeaderField:FIRCLSNetworkCrashlyticsAPIClientDisplayVersion]; + [request setValue:[[self dataSource] googleAppID] + forHTTPHeaderField:FIRCLSNetworkCrashlyticsGoogleAppId]; + + return request; +} + +- (BOOL)fillInRequest:(NSMutableURLRequest *)request forMultipartMimeDataAtPath:(NSString *)path { + NSString *boundary = [[path lastPathComponent] stringByDeletingPathExtension]; + + [request setValue:[FIRCLSMultipartMimeStreamEncoder + contentTypeHTTPHeaderValueWithBoundary:boundary] + forHTTPHeaderField:@"Content-Type"]; + + NSNumber *fileSize = [[self fileManager] fileSizeAtPath:path]; + if (fileSize == nil) { + FIRCLSErrorLog(@"Could not determine size of multipart mime file"); + return NO; + } + + [request setValue:[fileSize stringValue] forHTTPHeaderField:@"Content-Length"]; + + return YES; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader_Private.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader_Private.h new file mode 100644 index 000000000..f54dc1673 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader_Private.h @@ -0,0 +1,23 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSReportUploader.h" + +@interface FIRCLSReportUploader (PrivateMethods) + +@property(nonatomic, readonly) NSURL *reportURL; + +- (NSMutableURLRequest *)mutableRequestWithURL:(NSURL *)url timeout:(NSTimeInterval)timeout; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionArbiter.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionArbiter.h new file mode 100644 index 000000000..147bc7bbc --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionArbiter.h @@ -0,0 +1,39 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +@class FIRApp; +@class FBLPromise<T>; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRCLSDataCollectionArbiter : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +- (instancetype)initWithApp:(FIRApp *)app withAppInfo:(NSDictionary *)dict; + +- (BOOL)isLegacyDataCollectionKeyInPlist; + +- (BOOL)isCrashlyticsCollectionEnabled; + +- (void)setCrashlyticsCollectionEnabled:(BOOL)enabled; + +// Returns a promise that is fulfilled once data collection is enabled. +- (FBLPromise<NSNumber *> *)waitForCrashlyticsCollectionEnabled; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionArbiter.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionArbiter.m new file mode 100644 index 000000000..e7d5996cf --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionArbiter.m @@ -0,0 +1,148 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSDataCollectionArbiter.h" + +#if __has_include(<FBLPromises/FBLPromises.h>) +#import <FBLPromises/FBLPromises.h> +#else +#import "FBLPromises.h" +#endif + +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +#import "FIRCLSUserDefaults.h" + +// The legacy data collection setting allows Fabric customers to turn off auto- +// initialization, but can be overridden by calling [Fabric with:]. +// +// While we support Fabric, we must have two different versions, because +// they require these slightly different semantics. +NSString *const FIRCLSLegacyCrashlyticsCollectionKey = @"firebase_crashlytics_collection_enabled"; + +// The new data collection setting can be set by an API that is stored in FIRCLSUserDefaults +NSString *const FIRCLSDataCollectionEnabledKey = @"com.crashlytics.data_collection"; + +// The new data collection setting also allows Firebase customers to turn off data +// collection in their Info.plist, and can be overridden by setting it to true using +// the setCrashlyticsCollectionEnabled API. +NSString *const FIRCLSCrashlyticsCollectionKey = @"FirebaseCrashlyticsCollectionEnabled"; + +typedef NS_ENUM(NSInteger, FIRCLSDataCollectionSetting) { + FIRCLSDataCollectionSettingNotSet = 0, + FIRCLSDataCollectionSettingEnabled = 1, + FIRCLSDataCollectionSettingDisabled = 2, +}; + +@interface FIRCLSDataCollectionArbiter () { + NSLock *_mutex; + FBLPromise *_dataCollectionEnabled; + BOOL _promiseResolved; + FIRApp *_app; + NSDictionary *_appInfo; +} +@end + +@implementation FIRCLSDataCollectionArbiter + +- (instancetype)initWithApp:(FIRApp *)app withAppInfo:(NSDictionary *)dict { + self = [super init]; + if (self) { + _mutex = [[NSLock alloc] init]; + _appInfo = dict; + _app = app; + if ([FIRCLSDataCollectionArbiter isCrashlyticsCollectionEnabledWithApp:app withAppInfo:dict]) { + _dataCollectionEnabled = [FBLPromise resolvedWith:nil]; + _promiseResolved = YES; + } else { + _dataCollectionEnabled = [FBLPromise pendingPromise]; + _promiseResolved = NO; + } + } + + return self; +} + +/* + * Legacy collection key that we provide for customers to disable Crash reporting. + * Customers can later turn on Crashlytics using Fabric.with if they choose to do so. + * + * This flag is unsupported for the "New SDK" + */ +- (BOOL)isLegacyDataCollectionKeyInPlist { + if ([_appInfo objectForKey:FIRCLSLegacyCrashlyticsCollectionKey]) { + return true; + } + + return false; +} + +// This functionality is called in the initializer before self is fully initialized, +// so a class method is used. The instance method below allows for a consistent clean API. ++ (BOOL)isCrashlyticsCollectionEnabledWithApp:(FIRApp *)app withAppInfo:(NSDictionary *)dict { + FIRCLSDataCollectionSetting stickySetting = [FIRCLSDataCollectionArbiter stickySetting]; + if (stickySetting != FIRCLSDataCollectionSettingNotSet) { + return stickySetting == FIRCLSDataCollectionSettingEnabled; + } + + id firebaseCrashlyticsCollectionEnabled = [dict objectForKey:FIRCLSCrashlyticsCollectionKey]; + if ([firebaseCrashlyticsCollectionEnabled isKindOfClass:[NSString class]] || + [firebaseCrashlyticsCollectionEnabled isKindOfClass:[NSNumber class]]) { + return [firebaseCrashlyticsCollectionEnabled boolValue]; + } + + return [app isDataCollectionDefaultEnabled]; +} + +- (BOOL)isCrashlyticsCollectionEnabled { + return [FIRCLSDataCollectionArbiter isCrashlyticsCollectionEnabledWithApp:_app + withAppInfo:_appInfo]; +} + +- (void)setCrashlyticsCollectionEnabled:(BOOL)enabled { + FIRCLSUserDefaults *userDefaults = [FIRCLSUserDefaults standardUserDefaults]; + FIRCLSDataCollectionSetting setting = + enabled ? FIRCLSDataCollectionSettingEnabled : FIRCLSDataCollectionSettingDisabled; + [userDefaults setInteger:setting forKey:FIRCLSDataCollectionEnabledKey]; + [userDefaults synchronize]; + + [_mutex lock]; + if (enabled) { + if (!_promiseResolved) { + [_dataCollectionEnabled fulfill:nil]; + _promiseResolved = YES; + } + } else { + if (_promiseResolved) { + _dataCollectionEnabled = [FBLPromise pendingPromise]; + _promiseResolved = NO; + } + } + [_mutex unlock]; +} + ++ (FIRCLSDataCollectionSetting)stickySetting { + FIRCLSUserDefaults *userDefaults = [FIRCLSUserDefaults standardUserDefaults]; + return [userDefaults integerForKey:FIRCLSDataCollectionEnabledKey]; +} + +- (FBLPromise *)waitForCrashlyticsCollectionEnabled { + FBLPromise *result = nil; + [_mutex lock]; + result = _dataCollectionEnabled; + [_mutex unlock]; + return result; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.h new file mode 100644 index 000000000..4ab2bb661 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.h @@ -0,0 +1,45 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +/** + * A FIRCLSDataCollectionToken represents having permission to upload data. A data collection token + * is either valid or nil. Every function that directly initiates a network operation that will + * result in data collection must check to make sure it has been passed a valid token. Tokens should + * only be created when either (1) automatic data collection is enabled, or (2) the user has + * explicitly given permission to collect data for a particular purpose, using the API. For all the + * functions in between, the data collection token getting passed as an argument helps to document + * and enforce the flow of data collection permission through the SDK. + */ +@interface FIRCLSDataCollectionToken : NSObject + +/** + * Creates a valid token. Only call this method when either (1) automatic data collection is + * enabled, or (2) the user has explicitly given permission to collect data for a particular + * purpose, using the API. + */ ++ (instancetype)validToken; + +/** + * Use this to verify that a token is valid. If this is called on a nil instance, it will return NO. + * @return YES. + */ +- (BOOL)isValid; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.m new file mode 100644 index 000000000..1a41ee1df --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.m @@ -0,0 +1,27 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSDataCollectionToken.h" + +@implementation FIRCLSDataCollectionToken + ++ (instancetype)validToken { + return [[FIRCLSDataCollectionToken alloc] init]; +} + +- (BOOL)isValid { + return YES; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession.h new file mode 100644 index 000000000..fa53468c1 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession.h @@ -0,0 +1,84 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED + +#import "FIRCLSURLSessionConfiguration.h" + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRCLSURLSession : NSObject { + id<NSURLSessionDelegate> _delegate; + NSOperationQueue *_delegateQueue; + NSURLSessionConfiguration *_configuration; + NSMutableSet *_taskSet; + dispatch_queue_t _queue; + + NSString *_sessionDescription; +} + ++ (BOOL)NSURLSessionShouldBeUsed; + ++ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration; ++ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration + delegate:(nullable id<NSURLSessionDelegate>)delegate + delegateQueue:(nullable NSOperationQueue *)queue; + +@property(nonatomic, readonly, retain) NSOperationQueue *delegateQueue; +@property(nonatomic, readonly, retain) id<NSURLSessionDelegate> delegate; +@property(nonatomic, readonly, copy) NSURLSessionConfiguration *configuration; + +@property(nonatomic, copy) NSString *sessionDescription; + +- (void)getTasksWithCompletionHandler: + (void (^)(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks))completionHandler; + +// task creation - suitable for background operations +- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL; + +- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request; +- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url; + +// convenience methods (that are not available for background sessions +- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request + completionHandler:(nullable void (^)(NSData *data, + NSURLResponse *response, + NSError *error))completionHandler; +- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request; + +- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request + completionHandler: + (nullable void (^)(NSURL *targetPath, + NSURLResponse *response, + NSError *error))completionHandler; + +- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request + fromFile:(NSURL *)fileURL + completionHandler: + (nullable void (^)(NSData *data, + NSURLResponse *response, + NSError *error))completionHandler; + +- (void)invalidateAndCancel; +- (void)finishTasksAndInvalidate; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession.m new file mode 100644 index 000000000..981542368 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession.m @@ -0,0 +1,346 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED +#import "FIRCLSURLSession.h" + +#import "FIRCLSURLSessionDataTask.h" +#import "FIRCLSURLSessionDataTask_PrivateMethods.h" +#import "FIRCLSURLSessionDownloadTask.h" +#import "FIRCLSURLSessionDownloadTask_PrivateMethods.h" +#import "FIRCLSURLSessionTask_PrivateMethods.h" +#import "FIRCLSURLSessionUploadTask.h" + +#define DELEGATE ((id<NSURLSessionDataDelegate, NSURLSessionDownloadDelegate>)self->_delegate) + +@interface FIRCLSURLSession () <FIRCLSURLSessionDownloadDelegate> + +@property(nonatomic, retain) NSOperationQueue *delegateQueue; +@property(nonatomic, retain) id<NSURLSessionDelegate> delegate; +@property(nonatomic, copy) NSURLSessionConfiguration *configuration; + +@end + +@implementation FIRCLSURLSession + +@synthesize delegate = _delegate; +@synthesize delegateQueue = _delegateQueue; +@synthesize configuration = _configuration; +@synthesize sessionDescription = _sessionDescription; + ++ (BOOL)NSURLSessionShouldBeUsed { + if (!NSClassFromString(@"NSURLSession")) { + return NO; + } + + // We use this as a proxy to verify that we are on at least iOS 8 or 10.10. The first OSes that + // has NSURLSession were fairly unstable. + return [[NSURLSessionConfiguration class] + respondsToSelector:@selector(backgroundSessionConfigurationWithIdentifier:)]; +} + ++ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration { + return [self sessionWithConfiguration:configuration delegate:nil delegateQueue:nil]; +} + ++ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration + delegate:(nullable id<NSURLSessionDelegate>)delegate + delegateQueue:(nullable NSOperationQueue *)queue { + if ([self NSURLSessionShouldBeUsed]) { + return [NSURLSession sessionWithConfiguration:configuration + delegate:delegate + delegateQueue:queue]; + } + + if (!configuration) { + return nil; + } + +#if __has_feature(objc_arc) + FIRCLSURLSession *session = [self new]; +#else + FIRCLSURLSession *session = [[self new] autorelease]; +#endif + [session setDelegate:delegate]; + // When delegate exists, but delegateQueue is nil, create a serial queue like NSURLSession + // documents. + if (delegate && !queue) { + queue = [self newDefaultDelegateQueue]; + } + session.delegateQueue = queue; + session.configuration = configuration; + return (NSURLSession *)session; +} + ++ (NSOperationQueue *)newDefaultDelegateQueue { + NSOperationQueue *delegateQueue = [[NSOperationQueue alloc] init]; + delegateQueue.name = [NSString stringWithFormat:@"%@ %p", NSStringFromClass(self), self]; + delegateQueue.maxConcurrentOperationCount = 1; + return delegateQueue; +} + +- (instancetype)init { + self = [super init]; + if (!self) { + return nil; + } + + _queue = dispatch_queue_create("com.crashlytics.URLSession", 0); + + return self; +} + +#if !__has_feature(objc_arc) +- (void)dealloc { + [_taskSet release]; + [_delegate release]; + [_delegateQueue release]; + [_configuration release]; + +#if !OS_OBJECT_USE_OBJC + dispatch_release(_queue); +#endif + + [super dealloc]; +} +#endif + +#pragma mark - Managing the Session + +- (void)invalidateAndCancel { + dispatch_sync(_queue, ^{ + for (FIRCLSURLSessionTask *task in self->_taskSet) { + [task cancel]; + } + }); + + self.delegate = nil; +} + +- (void)finishTasksAndInvalidate { + self.delegate = nil; +} + +#pragma mark - + +- (void)getTasksWithCompletionHandler: + (void (^)(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks))completionHandler { + [[self delegateQueue] addOperationWithBlock:^{ + // TODO - this is totally wrong, but better than not calling back at all + completionHandler(@[], @[], @[]); + }]; +} + +- (void)removeTaskFromSet:(FIRCLSURLSessionTask *)task { + dispatch_async(_queue, ^{ + [self->_taskSet removeObject:task]; + }); +} + +- (void)configureTask:(FIRCLSURLSessionTask *)task + withRequest:(NSURLRequest *)request + block:(void (^)(NSMutableURLRequest *mutableRequest))block { + NSMutableURLRequest *modifiedRequest = [request mutableCopy]; + + dispatch_sync(_queue, ^{ + [self->_taskSet addObject:task]; + + // TODO: this isn't allowed to overwrite existing headers + for (NSString *key in [self->_configuration HTTPAdditionalHeaders]) { + [modifiedRequest addValue:[[self->_configuration HTTPAdditionalHeaders] objectForKey:key] + forHTTPHeaderField:key]; + } + }); + + if (block) { + block(modifiedRequest); + } + + [task setOriginalRequest:modifiedRequest]; + [task setDelegate:self]; + +#if !__has_feature(objc_arc) + [modifiedRequest release]; +#endif +} + +- (BOOL)shouldInvokeDelegateSelector:(SEL)selector forTask:(FIRCLSURLSessionTask *)task { + return [task invokesDelegate] && [_delegate respondsToSelector:selector]; +} + +#pragma mark Task Creation +- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request + fromFile:(NSURL *)fileURL { + return [self uploadTaskWithRequest:request fromFile:fileURL completionHandler:nil]; +} + +- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request { + return [self downloadTaskWithRequest:request completionHandler:nil]; +} + +- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url { + return [self downloadTaskWithRequest:[NSURLRequest requestWithURL:url]]; +} + +#pragma mark Async Convenience Methods +- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request + completionHandler:(nullable void (^)(NSData *data, + NSURLResponse *response, + NSError *error))completionHandler { + FIRCLSURLSessionDataTask *task = [FIRCLSURLSessionDataTask task]; + + if (completionHandler) { + [task setCompletionHandler:completionHandler]; + [task setInvokesDelegate:NO]; + } + + [self configureTask:task withRequest:request block:nil]; + + return (NSURLSessionDataTask *)task; +} + +- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request { + return [self dataTaskWithRequest:request completionHandler:nil]; +} + +- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request + fromFile:(NSURL *)fileURL + completionHandler: + (nullable void (^)(NSData *data, + NSURLResponse *response, + NSError *error))completionHandler { + FIRCLSURLSessionUploadTask *task = [FIRCLSURLSessionUploadTask task]; + + if (completionHandler) { + [task setCompletionHandler:completionHandler]; + [task setInvokesDelegate:NO]; + } + + [self configureTask:task + withRequest:request + block:^(NSMutableURLRequest *mutableRequest) { + // you cannot set up both of these, and we'll be using the stream here + [mutableRequest setHTTPBody:nil]; + [mutableRequest setHTTPBodyStream:[NSInputStream inputStreamWithURL:fileURL]]; + }]; + + return (NSURLSessionUploadTask *)task; +} + +- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request + completionHandler: + (nullable void (^)(NSURL *targetPath, + NSURLResponse *response, + NSError *error))completionHandler { + FIRCLSURLSessionDownloadTask *task = [FIRCLSURLSessionDownloadTask task]; + + if (completionHandler) { + [task setDownloadCompletionHandler:completionHandler]; + [task setInvokesDelegate:NO]; + } + + [self configureTask:task withRequest:request block:nil]; + + return (NSURLSessionDownloadTask *)task; +} + +#pragma mark FIRCLSURLSessionTaskDelegate +- (NSURLRequest *)task:(FIRCLSURLSessionTask *)task + willPerformHTTPRedirection:(NSHTTPURLResponse *)response + newRequest:(NSURLRequest *)request { + // just accept the proposed redirection + return request; +} + +- (void)task:(FIRCLSURLSessionTask *)task didCompleteWithError:(NSError *)error { + if (![self shouldInvokeDelegateSelector:@selector(URLSession:task:didCompleteWithError:) + forTask:task]) { + [self removeTaskFromSet:task]; + return; + } + + [_delegateQueue addOperationWithBlock:^{ + [DELEGATE URLSession:(NSURLSession *)self + task:(NSURLSessionTask *)task + didCompleteWithError:error]; + + // Note that you *cannot* clean up here, because this method could be run asynchronously with + // the delegate methods that care about the state of the task + [self removeTaskFromSet:task]; + }]; +} + +#pragma mark FIRCLSURLSessionDataTask +- (void)task:(FIRCLSURLSessionDataTask *)task didReceiveResponse:(NSURLResponse *)response { + if (![self shouldInvokeDelegateSelector:@selector + (URLSession:dataTask:didReceiveResponse:completionHandler:) + forTask:task]) { + return; + } + + [_delegateQueue addOperationWithBlock:^{ + [DELEGATE URLSession:(NSURLSession *)self + dataTask:(NSURLSessionDataTask *)task + didReceiveResponse:response + completionHandler:^(NSURLSessionResponseDisposition disposition){ + // nothing to do here + }]; + }]; +} + +- (void)task:(FIRCLSURLSessionDataTask *)task didReceiveData:(NSData *)data { + if (![self shouldInvokeDelegateSelector:@selector(URLSession:dataTask:didReceiveData:) + forTask:task]) { + return; + } + + [_delegateQueue addOperationWithBlock:^{ + [DELEGATE URLSession:(NSURLSession *)self + dataTask:(NSURLSessionDataTask *)task + didReceiveData:data]; + }]; +} + +#pragma mark FIRCLSURLSessionDownloadDelegate +- (void)downloadTask:(FIRCLSURLSessionDownloadTask *)task didFinishDownloadingToURL:(NSURL *)url { + if (![self shouldInvokeDelegateSelector:@selector(URLSession: + downloadTask:didFinishDownloadingToURL:) + forTask:task]) { + // We have to be certain that we cleanup only once the delegate no longer cares about the state + // of the task being changed. In the case of download, this is either after the delegate method + // has been invoked, or here, if the delegate doesn't care. + [task cleanup]; + return; + } + + [_delegateQueue addOperationWithBlock:^{ + [DELEGATE URLSession:(NSURLSession *)self + downloadTask:(NSURLSessionDownloadTask *)task + didFinishDownloadingToURL:url]; + + // Cleanup for the download tasks is a little complex. As long as we do it only after + // the delegate has been informed of the completed download, we are ok. + [task cleanup]; + }]; +} + +@end + +#else + +INJECT_STRIP_SYMBOL(clsurlsession) + +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h new file mode 100644 index 000000000..9f3ead01b --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h @@ -0,0 +1,28 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include <Foundation/Foundation.h> + +#define FIRCLSURLSESSION_REQUIRED (!TARGET_OS_WATCH && !TARGET_OS_TV) + +// These macros generate a function to force a symbol for the containing .o, to work around an issue +// where strip will not strip debug information without a symbol to strip. +#define CONCAT_EXPANDED(a, b) a##b +#define CONCAT(a, b) CONCAT_EXPANDED(a, b) +#define DUMMY_FUNCTION_NAME(x) CONCAT(fircls_strip_this_, x) +#define INJECT_STRIP_SYMBOL(x) \ + void DUMMY_FUNCTION_NAME(x)(void) { \ + } diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionConfiguration.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionConfiguration.h new file mode 100644 index 000000000..bda0f7083 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionConfiguration.h @@ -0,0 +1,42 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED + +#import <Foundation/Foundation.h> + +@interface FIRCLSURLSessionConfiguration : NSObject <NSCopying> { + NSDictionary *_additionalHeaders; + NSURLCache *_URLCache; + NSHTTPCookieAcceptPolicy _cookiePolicy; +} + ++ (NSURLSessionConfiguration *)defaultSessionConfiguration; ++ (NSURLSessionConfiguration *)ephemeralSessionConfiguration; ++ (NSURLSessionConfiguration *)backgroundSessionConfiguration:(NSString *)identifier; ++ (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier; + +@property(nonatomic, copy) NSDictionary *HTTPAdditionalHeaders; +@property(nonatomic, retain) NSURLCache *URLCache; +@property(nonatomic, assign) NSHTTPCookieAcceptPolicy HTTPCookieAcceptPolicy; +@property(nonatomic, assign) BOOL sessionSendsLaunchEvents; +@property(nonatomic, assign) NSTimeInterval timeoutIntervalForRequest; +@property(nonatomic, assign) NSTimeInterval timeoutIntervalForResource; +@property(nonatomic, assign) BOOL allowsCellularAccess; + +@end + +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionConfiguration.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionConfiguration.m new file mode 100644 index 000000000..177e7a6bf --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionConfiguration.m @@ -0,0 +1,92 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSURLSessionAvailability.h" + +#import "FIRCLSURLSession.h" + +#if FIRCLSURLSESSION_REQUIRED +#import "FIRCLSURLSessionConfiguration.h" + +@implementation FIRCLSURLSessionConfiguration + +@synthesize URLCache = _URLCache; +@synthesize HTTPAdditionalHeaders = _additionalHeaders; +@synthesize HTTPCookieAcceptPolicy = _cookiePolicy; + ++ (NSURLSessionConfiguration *)defaultSessionConfiguration { + if ([FIRCLSURLSession NSURLSessionShouldBeUsed]) { + return [NSURLSessionConfiguration defaultSessionConfiguration]; + } + +#if __has_feature(objc_arc) + return [self new]; +#else + return [[self new] autorelease]; +#endif +} + ++ (NSURLSessionConfiguration *)ephemeralSessionConfiguration { + if ([FIRCLSURLSession NSURLSessionShouldBeUsed]) { + return [NSURLSessionConfiguration ephemeralSessionConfiguration]; + } + +#if __has_feature(objc_arc) + return [self new]; +#else + return [[self new] autorelease]; +#endif +} + ++ (NSURLSessionConfiguration *)backgroundSessionConfiguration:(NSString *)identifier { + return [self backgroundSessionConfigurationWithIdentifier:identifier]; +} + ++ (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier { + if (![FIRCLSURLSession NSURLSessionShouldBeUsed]) { + return nil; + } + + if ([[NSURLSessionConfiguration class] + respondsToSelector:@selector(backgroundSessionConfigurationWithIdentifier:)]) { + return [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:identifier]; + } + + return [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:identifier]; +} + +- (id)copyWithZone:(NSZone *)zone { + FIRCLSURLSessionConfiguration *configuration; + + configuration = [FIRCLSURLSessionConfiguration new]; + [configuration setHTTPAdditionalHeaders:[self HTTPAdditionalHeaders]]; + + return configuration; +} + +// This functionality is not supported by the wrapper, so we just stub it out +- (BOOL)sessionSendsLaunchEvents { + return NO; +} + +- (void)setSessionSendsLaunchEvents:(BOOL)sessionSendsLaunchEvents { +} + +@end + +#else + +INJECT_STRIP_SYMBOL(clsurlsessionconfiguration) + +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession_PrivateMethods.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession_PrivateMethods.h new file mode 100644 index 000000000..84885e1d6 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession_PrivateMethods.h @@ -0,0 +1,27 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED + +#import <Foundation/Foundation.h> + +@interface FIRCLSURLSession (PrivateMethods) + +- (void)runOnDelegateQueue:(void (^)(void))block; + +@end + +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask.h new file mode 100644 index 000000000..22099584e --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask.h @@ -0,0 +1,32 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED + +#import "FIRCLSURLSessionTask.h" + +@interface FIRCLSURLSessionDataTask : FIRCLSURLSessionTask { + void (^_completionHandler)(NSData *data, NSURLResponse *response, NSError *error); + NSURLConnection *_connection; + NSMutableData *_data; + NSString *_taskDescription; +} + +@property(nonatomic, copy) NSString *taskDescription; + +@end + +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask.m new file mode 100644 index 000000000..be40ab753 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask.m @@ -0,0 +1,124 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED +#import "FIRCLSURLSessionDataTask.h" + +#import "FIRCLSURLSessionDataTask_PrivateMethods.h" + +#define DELEGATE ((id<FIRCLSURLSessionDataDelegate>)[self delegate]) + +@interface FIRCLSURLSessionDataTask () <NSURLConnectionDelegate> +@end + +@implementation FIRCLSURLSessionDataTask + +@synthesize connection = _connection; +@synthesize completionHandler = _completionHandler; +@synthesize taskDescription = _taskDescription; + +#if !__has_feature(objc_arc) +- (void)dealloc { + [_connection release]; + [_completionHandler release]; + [_taskDescription release]; + [_data release]; + + [super dealloc]; +} +#endif + +- (void)resume { + dispatch_async([self queue], ^{ + NSURLConnection *connection; + + if ([self connection]) { + return; + } + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + connection = [[NSURLConnection alloc] initWithRequest:[self originalRequest] + delegate:self + startImmediately:NO]; +#pragma clang diagnostic pop + + [self setConnection:connection]; + + // bummer we have to do this on a runloop, but other mechanisms require iOS 5 or 10.7 + [connection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; +#if !__has_feature(objc_arc) + [connection release]; +#endif + [connection start]; + }); +} + +- (void)complete { + // call completion handler first + if (_completionHandler) { + // this should go to another queue + _completionHandler(_data, [self response], [self error]); + } + + // and then finally, call the session delegate completion + [DELEGATE task:self didCompleteWithError:[self error]]; +} + +- (void)cancel { + [self.connection cancel]; +} + +#pragma mark NSURLConnectionDelegate +- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { + dispatch_async([self queue], ^{ + [DELEGATE task:self didReceiveResponse:response]; + + [self setResponse:response]; + }); +} + +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { + dispatch_async([self queue], ^{ + if (!self->_data) { + self->_data = [NSMutableData new]; + } + + [self->_data appendData:data]; + [DELEGATE task:self didReceiveData:data]; + }); +} + +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { + dispatch_async([self queue], ^{ + [self setError:error]; + [self complete]; + }); +} + +- (void)connectionDidFinishLoading:(NSURLConnection *)connection { + dispatch_async([self queue], ^{ + [self complete]; + }); +} + +@end + +#else + +INJECT_STRIP_SYMBOL(clsurlsessiondatatask) + +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask_PrivateMethods.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask_PrivateMethods.h new file mode 100644 index 000000000..f85a3776f --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask_PrivateMethods.h @@ -0,0 +1,43 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED + +#import <Foundation/Foundation.h> + +#import "FIRCLSURLSessionTask_PrivateMethods.h" + +@protocol FIRCLSURLSessionDataDelegate; + +@interface FIRCLSURLSessionDataTask () + +@property(nonatomic, retain) NSURLConnection *connection; +@property(nonatomic, copy) void (^completionHandler) + (NSData *data, NSURLResponse *response, NSError *error); + +- (void)complete; + +@end + +@protocol FIRCLSURLSessionDataDelegate <FIRCLSURLSessionTaskDelegate> +@required + +- (void)task:(FIRCLSURLSessionDataTask *)task didReceiveResponse:(NSURLResponse *)response; +- (void)task:(FIRCLSURLSessionDataTask *)task didReceiveData:(NSData *)data; + +@end + +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask.h new file mode 100644 index 000000000..314180f7d --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask.h @@ -0,0 +1,31 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED + +#import "FIRCLSURLSessionDataTask.h" + +@protocol FIRCLSURLSessionDownloadDelegate; + +@interface FIRCLSURLSessionDownloadTask : FIRCLSURLSessionDataTask { + void (^_downloadCompletionHandler)(NSURL *targetPath, NSURLResponse *response, NSError *error); + NSOutputStream *_outputStream; + NSURL *_targetURL; +} + +@end + +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask.m new file mode 100644 index 000000000..a0c9b2a84 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask.m @@ -0,0 +1,157 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED +#import "FIRCLSURLSessionDownloadTask.h" + +#import "FIRCLSURLSessionDownloadTask_PrivateMethods.h" + +#define DELEGATE ((id<FIRCLSURLSessionDownloadDelegate>)[self delegate]) + +@interface FIRCLSURLSessionDownloadTask () <NSStreamDelegate> +@end + +@implementation FIRCLSURLSessionDownloadTask + +@synthesize downloadCompletionHandler = _downloadCompletionHandler; + +- (id)init { + self = [super init]; + if (!self) { + return nil; + } + +#if __has_feature(objc_arc) + _targetURL = [self temporaryFileURL]; + _outputStream = [NSOutputStream outputStreamWithURL:_targetURL append:NO]; +#else + _targetURL = [[self temporaryFileURL] retain]; + _outputStream = [[NSOutputStream outputStreamWithURL:_targetURL append:NO] retain]; +#endif + + [_outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; + [_outputStream setDelegate:self]; + + return self; +} + +#if !__has_feature(objc_arc) +- (void)dealloc { + [_downloadCompletionHandler release]; + [_targetURL release]; + [_outputStream release]; + + [super dealloc]; +} +#else +- (void)dealloc { + [_outputStream close]; + _outputStream.delegate = nil; +} +#endif + +- (NSURL *)temporaryFileURL { + NSString *tmpPath; + + tmpPath = [NSTemporaryDirectory() + stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]]; + + // TODO: make this actually unique + return [NSURL fileURLWithPath:tmpPath isDirectory:NO]; +} + +- (void)cleanup { + // now, remove the temporary file + [[NSFileManager defaultManager] removeItemAtURL:_targetURL error:nil]; +} + +- (void)complete { + // This is an override of FIRCLSURLSessionDataTask's cleanup method + + // call completion handler first + if (_downloadCompletionHandler) { + _downloadCompletionHandler(_targetURL, [self response], [self error]); + } + + // followed by the session delegate, if there was no error + if (![self error]) { + [DELEGATE downloadTask:self didFinishDownloadingToURL:_targetURL]; + } + + // and then finally, call the session delegate completion + [DELEGATE task:self didCompleteWithError:[self error]]; +} + +- (void)writeDataToStream:(NSData *)data { + // open the stream first + if ([_outputStream streamStatus] == NSStreamStatusNotOpen) { + [_outputStream open]; + } + + if ([data respondsToSelector:@selector(enumerateByteRangesUsingBlock:)]) { + [data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) { + [self->_outputStream write:bytes maxLength:byteRange.length]; + }]; + + return; + } + + // fall back to the less-efficient mechanism for older OSes + [_outputStream write:[data bytes] maxLength:[data length]]; +} + +#pragma mark NSURLConnectionDelegate +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { + dispatch_async([self queue], ^{ + [self writeDataToStream:data]; + }); +} + +- (void)completeForError { + dispatch_async([self queue], ^{ + [self->_outputStream close]; + [self->_connection cancel]; + if (![self error]) { + [self setError:[NSError errorWithDomain:@"FIRCLSURLSessionDownloadTaskError" + code:-1 + userInfo:nil]]; + } + [self complete]; + }); +} + +#pragma mark NSStreamDelegate +- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { + switch (eventCode) { + case NSStreamEventHasSpaceAvailable: + break; + case NSStreamEventErrorOccurred: + [self completeForError]; + break; + case NSStreamEventEndEncountered: + break; + default: + break; + } +} + +@end + +#else + +INJECT_STRIP_SYMBOL(clsurlsessiondownloadtask) + +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask_PrivateMethods.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask_PrivateMethods.h new file mode 100644 index 000000000..7e8ee9d9f --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask_PrivateMethods.h @@ -0,0 +1,39 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED + +#import <Foundation/Foundation.h> + +#import "FIRCLSURLSessionDataTask_PrivateMethods.h" + +@protocol FIRCLSURLSessionDownloadDelegate; + +@interface FIRCLSURLSessionDownloadTask () + +@property(nonatomic, copy) void (^downloadCompletionHandler) + (NSURL *targetPath, NSURLResponse *response, NSError *error); + +@end + +@protocol FIRCLSURLSessionDownloadDelegate <FIRCLSURLSessionDataDelegate> +@required + +- (void)downloadTask:(FIRCLSURLSessionDownloadTask *)task didFinishDownloadingToURL:(NSURL *)url; + +@end + +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask.h new file mode 100644 index 000000000..92316464d --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask.h @@ -0,0 +1,38 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +@protocol FIRCLSURLSessionTaskDelegate; + +@interface FIRCLSURLSessionTask : NSObject { + __unsafe_unretained id<FIRCLSURLSessionTaskDelegate> _delegate; + + NSURLRequest* _originalRequest; + NSURLRequest* _currentRequest; + NSURLResponse* _response; + NSError* _error; + dispatch_queue_t _queue; + BOOL _invokesDelegate; +} + +@property(nonatomic, readonly, copy) NSURLRequest* originalRequest; +@property(nonatomic, readonly, copy) NSURLRequest* currentRequest; +@property(nonatomic, readonly, copy) NSURLResponse* response; + +@property(nonatomic, readonly, copy) NSError* error; + +- (void)resume; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask.m new file mode 100644 index 000000000..8eba2c185 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask.m @@ -0,0 +1,95 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED +#import "FIRCLSURLSession.h" + +#import "FIRCLSURLSessionTask.h" + +#import "FIRCLSURLSessionTask_PrivateMethods.h" +#import "FIRCLSURLSession_PrivateMethods.h" + +@implementation FIRCLSURLSessionTask + ++ (instancetype)task { +#if __has_feature(objc_arc) + return [[self class] new]; + +#else + return [[[self class] new] autorelease]; +#endif +} + +@synthesize currentRequest = _currentRequest; +@synthesize originalRequest = _originalRequest; +@synthesize response = _response; +@synthesize error = _error; +@synthesize queue = _queue; +@synthesize invokesDelegate = _invokesDelegate; + +- (instancetype)init { + self = [super init]; + if (!self) { + return self; + } + + _queue = dispatch_queue_create("com.crashlytics.URLSessionTask", 0); + + _invokesDelegate = YES; + + return self; +} + +#if !__has_feature(objc_arc) +- (void)dealloc { + [_originalRequest release]; + [_currentRequest release]; + [_response release]; + [_error release]; + +#if !OS_OBJECT_USE_OBJC + dispatch_release(_queue); +#endif + + [super dealloc]; +} +#endif + +- (void)start { +#if DEBUG + assert(0 && "Must be implemented by FIRCLSURLSessionTask subclasses"); +#endif +} + +- (void)cancel { +#if DEBUG + assert(0 && "Must be implemented by FIRCLSURLSessionTask subclasses"); +#endif +} + +- (void)resume { +} + +- (void)cleanup { +} + +@end + +#else + +INJECT_STRIP_SYMBOL(clsurlsessiontask) + +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask_PrivateMethods.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask_PrivateMethods.h new file mode 100644 index 000000000..784b3a3ce --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask_PrivateMethods.h @@ -0,0 +1,55 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED + +#import <Foundation/Foundation.h> + +@protocol FIRCLSURLSessionTaskDelegate; + +@interface FIRCLSURLSessionTask () + ++ (instancetype)task; + +@property(nonatomic, assign) id<FIRCLSURLSessionTaskDelegate> delegate; + +@property(nonatomic, copy) NSURLRequest *originalRequest; +@property(nonatomic, copy) NSURLRequest *currentRequest; +@property(nonatomic, copy) NSURLResponse *response; + +@property(nonatomic, readonly) dispatch_queue_t queue; +@property(nonatomic, assign) BOOL invokesDelegate; + +- (void)cancel; + +@property(nonatomic, copy) NSError *error; + +- (void)cleanup; + +@end + +@protocol FIRCLSURLSessionTaskDelegate <NSObject> +@required + +- (NSURLRequest *)task:(FIRCLSURLSessionTask *)task + willPerformHTTPRedirection:(NSHTTPURLResponse *)response + newRequest:(NSURLRequest *)request; + +- (void)task:(FIRCLSURLSessionTask *)task didCompleteWithError:(NSError *)error; + +@end + +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionUploadTask.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionUploadTask.h new file mode 100644 index 000000000..6c5ed8b4b --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionUploadTask.h @@ -0,0 +1,25 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED + +#import "FIRCLSURLSessionDataTask.h" + +@interface FIRCLSURLSessionUploadTask : FIRCLSURLSessionDataTask + +@end + +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionUploadTask.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionUploadTask.m new file mode 100644 index 000000000..df3df8382 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionUploadTask.m @@ -0,0 +1,28 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED +#import "FIRCLSURLSessionUploadTask.h" + +@implementation FIRCLSURLSessionUploadTask + +@end + +#else + +INJECT_STRIP_SYMBOL(clsurlsessionuploadtask) + +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults.h new file mode 100644 index 000000000..6df153268 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults.h @@ -0,0 +1,42 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +extern NSString *const FIRCLSUserDefaultsPathComponent; + +@interface FIRCLSUserDefaults : NSObject + ++ (instancetype)standardUserDefaults; + +- (id)objectForKey:(NSString *)key; +- (NSString *)stringForKey:(NSString *)key; +- (BOOL)boolForKey:(NSString *)key; +- (NSInteger)integerForKey:(NSString *)key; + +- (void)setObject:(id)object forKey:(NSString *)key; +- (void)setString:(NSString *)string forKey:(NSString *)key; +- (void)setBool:(BOOL)boolean forKey:(NSString *)key; +- (void)setInteger:(NSInteger)integer forKey:(NSString *)key; + +- (void)removeObjectForKey:(NSString *)key; +- (void)removeAllObjects; + +- (NSDictionary *)dictionaryRepresentation; + +- (void)migrateFromNSUserDefaults:(NSArray *)keysToMigrate; +- (id)objectForKeyByMigratingFromNSUserDefaults:(NSString *)keyToMigrateOrNil; +- (void)synchronize; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults.m new file mode 100644 index 000000000..244dbe169 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults.m @@ -0,0 +1,372 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSUserDefaults.h" + +#import "FIRCLSApplication.h" +#import "FIRCLSLogger.h" + +#define CLS_USER_DEFAULTS_SERIAL_DISPATCH_QUEUE "com.crashlytics.CLSUserDefaults.access" +#define CLS_USER_DEFAULTS_SYNC_QUEUE "com.crashlytics.CLSUserDefaults.io" + +#define CLS_TARGET_CAN_WRITE_TO_DISK !TARGET_OS_TV + +// These values are required to stay the same between versions of the SDK so +// that when end users upgrade, their crashlytics data is still saved on disk. +#if !CLS_TARGET_CAN_WRITE_TO_DISK +static NSString *const FIRCLSNSUserDefaultsDataDictionaryKey = + @"com.crashlytics.CLSUserDefaults.user-default-key.data-dictionary"; +#endif + +NSString *const FIRCLSUserDefaultsPathComponent = @"CLSUserDefaults"; + +/** + * This class is an isolated re-implementation of NSUserDefaults which isolates our storage + * from that of our customers. This solves a number of issues we have seen in production, firstly + * that customers often delete or clear NSUserDefaults, unintentionally deleting our data. + * Further, we have seen thread safety issues in production with NSUserDefaults, as well as a number + * of bugs related to accessing NSUserDefaults before the device has been unlocked due to the + * NSFileProtection of NSUserDefaults. + */ +@interface FIRCLSUserDefaults () +@property(nonatomic, readwrite) BOOL synchronizeWroteToDisk; +#if CLS_TARGET_CAN_WRITE_TO_DISK +@property(nonatomic, copy, readonly) NSURL *directoryURL; +@property(nonatomic, copy, readonly) NSURL *fileURL; +#endif +@property(nonatomic, copy, readonly) + NSDictionary *persistedDataDictionary; // May only be safely accessed on the DictionaryQueue +@property(nonatomic, copy, readonly) + NSMutableDictionary *dataDictionary; // May only be safely accessed on the DictionaryQueue +@property(nonatomic, readonly) dispatch_queue_t + serialDictionaryQueue; // The queue on which all access to the dataDictionary occurs. +@property(nonatomic, readonly) + dispatch_queue_t synchronizationQueue; // The queue on which all disk access occurs. + +@end + +@implementation FIRCLSUserDefaults + +#pragma mark - singleton + ++ (instancetype)standardUserDefaults { + static FIRCLSUserDefaults *standardUserDefaults = nil; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + standardUserDefaults = [[super allocWithZone:NULL] init]; + }); + + return standardUserDefaults; +} + +- (id)copyWithZone:(NSZone *)zone { + return self; +} + +- (id)init { + if (self = [super init]) { + _serialDictionaryQueue = + dispatch_queue_create(CLS_USER_DEFAULTS_SERIAL_DISPATCH_QUEUE, DISPATCH_QUEUE_SERIAL); + _synchronizationQueue = + dispatch_queue_create(CLS_USER_DEFAULTS_SYNC_QUEUE, DISPATCH_QUEUE_SERIAL); + + dispatch_sync(self.serialDictionaryQueue, ^{ +#if CLS_TARGET_CAN_WRITE_TO_DISK + self->_directoryURL = [self generateDirectoryURL]; + self->_fileURL = [[self->_directoryURL + URLByAppendingPathComponent:FIRCLSUserDefaultsPathComponent + isDirectory:NO] URLByAppendingPathExtension:@"plist"]; +#endif + self->_persistedDataDictionary = [self loadDefaults]; + if (!self->_persistedDataDictionary) { + self->_persistedDataDictionary = [NSDictionary dictionary]; + } + self->_dataDictionary = [self->_persistedDataDictionary mutableCopy]; + }); + } + return self; +} + +- (NSURL *)generateDirectoryURL { + NSURL *directoryBaseURL = + [[[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory + inDomains:NSUserDomainMask] lastObject]; + NSString *hostAppBundleIdentifier = [self getEscapedAppBundleIdentifier]; + return [self generateDirectoryURLForBaseURL:directoryBaseURL + hostAppBundleIdentifier:hostAppBundleIdentifier]; +} + +- (NSURL *)generateDirectoryURLForBaseURL:(NSURL *)directoryBaseURL + hostAppBundleIdentifier:(NSString *)hostAppBundleIdentifier { + NSURL *directoryURL = directoryBaseURL; + // On iOS NSApplicationSupportDirectory is contained in the app's bundle. On OSX, it is not (it is + // ~/Library/Application Support/). On OSX we create a directory + // ~/Library/Application Support/<app-identifier>/com.crashlytics/ for storing files. + // Mac App Store review process requires files to be written to + // ~/Library/Application Support/<app-identifier>/, + // so ~/Library/Application Support/com.crashlytics/<app-identifier>/ cannot be used. +#if !TARGET_OS_SIMULATOR && !TARGET_OS_EMBEDDED + if (hostAppBundleIdentifier) { + directoryURL = [directoryURL URLByAppendingPathComponent:hostAppBundleIdentifier]; + } +#endif + directoryURL = [directoryURL URLByAppendingPathComponent:@"com.crashlytics"]; + return directoryURL; +} + +- (NSString *)getEscapedAppBundleIdentifier { + return FIRCLSApplicationGetBundleIdentifier(); +} + +#pragma mark - fetch object + +- (id)objectForKey:(NSString *)key { + __block id result; + + dispatch_sync(self.serialDictionaryQueue, ^{ + result = [self->_dataDictionary objectForKey:key]; + }); + + return result; +} + +- (NSString *)stringForKey:(NSString *)key { + id result = [self objectForKey:key]; + + if (result != nil && [result isKindOfClass:[NSString class]]) { + return (NSString *)result; + } else { + return nil; + } +} + +- (BOOL)boolForKey:(NSString *)key { + id result = [self objectForKey:key]; + if (result != nil && [result isKindOfClass:[NSNumber class]]) { + return [(NSNumber *)result boolValue]; + } else { + return NO; + } +} + +// Defaults to 0 +- (NSInteger)integerForKey:(NSString *)key { + id result = [self objectForKey:key]; + if (result && [result isKindOfClass:[NSNumber class]]) { + return [(NSNumber *)result integerValue]; + } else { + return 0; + } +} + +#pragma mark - set object + +- (void)setObject:(id)object forKey:(NSString *)key { + dispatch_sync(self.serialDictionaryQueue, ^{ + [self->_dataDictionary setValue:object forKey:key]; + }); +} + +- (void)setString:(NSString *)string forKey:(NSString *)key { + [self setObject:string forKey:key]; +} + +- (void)setBool:(BOOL)boolean forKey:(NSString *)key { + [self setObject:[NSNumber numberWithBool:boolean] forKey:key]; +} + +- (void)setInteger:(NSInteger)integer forKey:(NSString *)key { + [self setObject:[NSNumber numberWithInteger:integer] forKey:key]; +} + +#pragma mark - removing objects + +- (void)removeObjectForKey:(NSString *)key { + dispatch_sync(self.serialDictionaryQueue, ^{ + [self->_dataDictionary removeObjectForKey:key]; + }); +} + +- (void)removeAllObjects { + dispatch_sync(self.serialDictionaryQueue, ^{ + [self->_dataDictionary removeAllObjects]; + }); +} + +#pragma mark - dictionary representation + +- (NSDictionary *)dictionaryRepresentation { + __block NSDictionary *result; + + dispatch_sync(self.serialDictionaryQueue, ^{ + result = [self->_dataDictionary copy]; + }); + + return result; +} + +#pragma mark - synchronization + +- (void)synchronize { + __block BOOL dirty = NO; + + // only write to the disk if the dictionaries have changed + dispatch_sync(self.serialDictionaryQueue, ^{ + dirty = ![self->_persistedDataDictionary isEqualToDictionary:self->_dataDictionary]; + }); + + _synchronizeWroteToDisk = dirty; + if (!dirty) { + return; + } + + NSDictionary *state = [self dictionaryRepresentation]; + dispatch_sync(self.synchronizationQueue, ^{ +#if CLS_TARGET_CAN_WRITE_TO_DISK + BOOL isDirectory = NO; + BOOL pathExists = [[NSFileManager defaultManager] fileExistsAtPath:[self->_directoryURL path] + isDirectory:&isDirectory]; + + if (!pathExists) { + NSError *error; + if (![[NSFileManager defaultManager] createDirectoryAtURL:self->_directoryURL + withIntermediateDirectories:YES + attributes:nil + error:&error]) { + FIRCLSErrorLog(@"Failed to create directory with error: %@", error); + } + } + + if (![state writeToURL:self->_fileURL atomically:YES]) { + FIRCLSErrorLog(@"Unable to open file for writing at path %@", [self->_fileURL path]); + } else { +#if TARGET_OS_IOS + // We disable NSFileProtection on our file in order to allow us to access it even if the + // device is locked. + NSError *error; + if (![[NSFileManager defaultManager] + setAttributes:@{NSFileProtectionKey : NSFileProtectionNone} + ofItemAtPath:[self->_fileURL path] + error:&error]) { + FIRCLSErrorLog(@"Error setting NSFileProtection: %@", error); + } +#endif + } +#else + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + [defaults setObject:state forKey:FIRCLSNSUserDefaultsDataDictionaryKey]; + [defaults synchronize]; +#endif + }); + + dispatch_sync(self.serialDictionaryQueue, ^{ + self->_persistedDataDictionary = [self->_dataDictionary copy]; + }); +} + +- (NSDictionary *)loadDefaults { + __block NSDictionary *state = nil; + dispatch_sync(self.synchronizationQueue, ^{ +#if CLS_TARGET_CAN_WRITE_TO_DISK + BOOL isDirectory = NO; + BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:[self->_fileURL path] + isDirectory:&isDirectory]; + + if (fileExists && !isDirectory) { + state = [NSDictionary dictionaryWithContentsOfURL:self->_fileURL]; + if (nil == state) { + FIRCLSErrorLog(@"Failed to read existing UserDefaults file"); + } + } else if (!fileExists) { + // No file found. This is expected on first launch. + } else if (fileExists && isDirectory) { + FIRCLSErrorLog(@"Found directory where file expected. Removing conflicting directory"); + + NSError *error; + if (![[NSFileManager defaultManager] removeItemAtURL:self->_fileURL error:&error]) { + FIRCLSErrorLog(@"Error removing conflicting directory: %@", error); + } + } +#else + state = [[NSUserDefaults standardUserDefaults] dictionaryForKey:FIRCLSNSUserDefaultsDataDictionaryKey]; +#endif + }); + return state; +} + +#pragma mark - migration + +// This method migrates all keys specified from NSUserDefaults to FIRCLSUserDefaults +// To do so, we copy all known key-value pairs into FIRCLSUserDefaults, synchronize it, then +// remove the keys from NSUserDefaults and synchronize it. +- (void)migrateFromNSUserDefaults:(NSArray *)keysToMigrate { + BOOL didFindKeys = NO; + + // First, copy all of the keysToMigrate which are stored NSUserDefaults + for (NSString *key in keysToMigrate) { + id oldValue = [[NSUserDefaults standardUserDefaults] objectForKey:(NSString *)key]; + if (nil != oldValue) { + didFindKeys = YES; + [self setObject:oldValue forKey:key]; + } + } + + if (didFindKeys) { + // First synchronize FIRCLSUserDefaults such that all keysToMigrate in NSUserDefaults are stored + // in FIRCLSUserDefaults. At this point, data is duplicated. + [[FIRCLSUserDefaults standardUserDefaults] synchronize]; + + for (NSString *key in keysToMigrate) { + [[NSUserDefaults standardUserDefaults] removeObjectForKey:(NSString *)key]; + } + + // This should be our last interaction with NSUserDefaults. All data is migrated into + // FIRCLSUserDefaults + [[NSUserDefaults standardUserDefaults] synchronize]; + } +} + +// This method first queries FIRCLSUserDefaults to see if the key exist, and upon failure, +// searches for the key in NSUserDefaults, and migrates it if found. +- (id)objectForKeyByMigratingFromNSUserDefaults:(NSString *)keyToMigrateOrNil { + if (!keyToMigrateOrNil) { + return nil; + } + + id clsUserDefaultsValue = [self objectForKey:keyToMigrateOrNil]; + if (clsUserDefaultsValue != nil) { + return clsUserDefaultsValue; // if the value exists in FIRCLSUserDefaults, return it. + } + + id oldNSUserDefaultsValue = + [[NSUserDefaults standardUserDefaults] objectForKey:keyToMigrateOrNil]; + if (!oldNSUserDefaultsValue) { + return nil; // if the value also does not exist in NSUserDefaults, return nil. + } + + // Otherwise, the key exists in NSUserDefaults. Migrate it to FIRCLSUserDefaults + // and then return the associated value. + + // First store it in FIRCLSUserDefaults so in the event of a crash, data is not lost. + [self setObject:oldNSUserDefaultsValue forKey:keyToMigrateOrNil]; + [[FIRCLSUserDefaults standardUserDefaults] synchronize]; + + [[NSUserDefaults standardUserDefaults] removeObjectForKey:keyToMigrateOrNil]; + [[NSUserDefaults standardUserDefaults] synchronize]; + + return oldNSUserDefaultsValue; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults_private.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults_private.h new file mode 100644 index 000000000..775bca24a --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults_private.h @@ -0,0 +1,23 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> +#import "FIRCLSUserDefaults.h" + +@interface FIRCLSUserDefaults (Private) +- (BOOL)synchronizeWroteToDisk; +- (NSDictionary *)loadDefaults; +- (NSURL *)generateDirectoryURLForBaseURL:(NSURL *)directoryBaseURL + hostAppBundleIdentifier:(NSString *)hostAppBundleIdentifer; +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCrashlytics.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCrashlytics.m new file mode 100644 index 000000000..16e7a2f44 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCrashlytics.m @@ -0,0 +1,318 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include <stdatomic.h> + +#if __has_include(<FBLPromises/FBLPromises.h>) +#import <FBLPromises/FBLPromises.h> +#else +#import "FBLPromises.h" +#endif + +#import "FIRCLSApplicationIdentifierModel.h" +#include "FIRCLSCrashedMarkerFile.h" +#import "FIRCLSDataCollectionArbiter.h" +#import "FIRCLSDefines.h" +#include "FIRCLSException.h" +#import "FIRCLSFileManager.h" +#include "FIRCLSGlobals.h" +#import "FIRCLSHost.h" +#include "FIRCLSProfiling.h" +#import "FIRCLSReport_Private.h" +#import "FIRCLSSettings.h" +#import "FIRCLSUserDefaults.h" +#include "FIRCLSUserLogging.h" +#include "FIRCLSUtility.h" + +#import "FIRCLSByteUtility.h" +#import "FIRCLSFABHost.h" +#import "FIRCLSLogger.h" + +#import "FIRCLSReportManager.h" + +#import <FirebaseInstallations/FirebaseInstallations.h> +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" +#import "Interop/Analytics/Public/FIRAnalyticsInterop.h" + +#import <GoogleDataTransport/GDTCORTargets.h> +#import <GoogleDataTransport/GDTCORTransport.h> + +#if TARGET_OS_IPHONE +#import <UIKit/UIKit.h> +#endif + +FIRCLSContext _firclsContext; +dispatch_queue_t _firclsLoggingQueue; +dispatch_queue_t _firclsBinaryImageQueue; +dispatch_queue_t _firclsExceptionQueue; + +static atomic_bool _hasInitializedInstance; + +NSString *const FIRCLSGoogleTransportMappingID = @"1206"; + +/// Empty protocol to register with FirebaseCore's component system. +@protocol FIRCrashlyticsInstanceProvider <NSObject> +@end + +@interface FIRCrashlytics () <FIRLibrary, FIRCrashlyticsInstanceProvider> + +@property(nonatomic) BOOL didPreviouslyCrash; +@property(nonatomic, copy) NSString *googleAppID; +@property(nonatomic) FIRCLSDataCollectionArbiter *dataArbiter; +@property(nonatomic) FIRCLSFileManager *fileManager; +@property(nonatomic) FIRCLSReportManager *reportManager; +@property(nonatomic) GDTCORTransport *googleTransport; + +@end + +@implementation FIRCrashlytics + +#pragma mark - Singleton Support + +- (instancetype)initWithApp:(FIRApp *)app + appInfo:(NSDictionary *)appInfo + installations:(FIRInstallations *)installations + analytics:(id<FIRAnalyticsInterop>)analytics { + self = [super init]; + + if (self) { + bool expectedCalled = NO; + if (!atomic_compare_exchange_strong(&_hasInitializedInstance, &expectedCalled, YES)) { + FIRCLSErrorLog(@"Cannot instantiate more than one instance of Crashlytics."); + return nil; + } + + FIRCLSProfileMark mark = FIRCLSProfilingStart(); + + NSLog(@"[Firebase/Crashlytics] Version %@", @CLS_SDK_DISPLAY_VERSION); + + FIRCLSDeveloperLog("Crashlytics", @"Running on %@, %@ (%@)", FIRCLSHostModelInfo(), + FIRCLSHostOSDisplayVersion(), FIRCLSHostOSBuildVersion()); + + _googleTransport = [[GDTCORTransport alloc] initWithMappingID:FIRCLSGoogleTransportMappingID + transformers:nil + target:kGDTCORTargetCSH]; + + _fileManager = [[FIRCLSFileManager alloc] init]; + _googleAppID = app.options.googleAppID; + _dataArbiter = [[FIRCLSDataCollectionArbiter alloc] initWithApp:app withAppInfo:appInfo]; + + FIRCLSApplicationIdentifierModel *appModel = [[FIRCLSApplicationIdentifierModel alloc] init]; + FIRCLSSettings *settings = [[FIRCLSSettings alloc] initWithFileManager:_fileManager + appIDModel:appModel]; + + _reportManager = [[FIRCLSReportManager alloc] initWithFileManager:_fileManager + installations:installations + analytics:analytics + googleAppID:_googleAppID + dataArbiter:_dataArbiter + googleTransport:_googleTransport + appIDModel:appModel + settings:settings]; + + // Process did crash during previous execution + NSString *crashedMarkerFileName = [NSString stringWithUTF8String:FIRCLSCrashedMarkerFileName]; + NSString *crashedMarkerFileFullPath = + [[_fileManager rootPath] stringByAppendingPathComponent:crashedMarkerFileName]; + _didPreviouslyCrash = [_fileManager fileExistsAtPath:crashedMarkerFileFullPath]; + + if (_didPreviouslyCrash) { + // Delete the crash file marker in the background ensure start up is as fast as possible + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ + [self.fileManager removeItemAtPath:crashedMarkerFileFullPath]; + }); + } + + [[[_reportManager startWithProfilingMark:mark] then:^id _Nullable(NSNumber *_Nullable value) { + if (![value boolValue]) { + FIRCLSErrorLog(@"Crash reporting could not be initialized"); + } + return value; + }] catch:^void(NSError *error) { + FIRCLSErrorLog(@"Crash reporting failed to initialize with error: %@", error); + }]; + } + + return self; +} + ++ (void)load { + [FIRApp registerInternalLibrary:(Class<FIRLibrary>)self + withName:@"firebase-crashlytics" + withVersion:@CLS_SDK_DISPLAY_VERSION]; +} + ++ (NSArray<FIRComponent *> *)componentsToRegister { + FIRDependency *analyticsDep = + [FIRDependency dependencyWithProtocol:@protocol(FIRAnalyticsInterop)]; + + FIRComponentCreationBlock creationBlock = + ^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) { + if (!container.app.isDefaultApp) { + FIRCLSErrorLog(@"Crashlytics must be used with the default Firebase app."); + return nil; + } + + id<FIRAnalyticsInterop> analytics = FIR_COMPONENT(FIRAnalyticsInterop, container); + + FIRInstallations *installations = [FIRInstallations installationsWithApp:container.app]; + + *isCacheable = YES; + + return [[FIRCrashlytics alloc] initWithApp:container.app + appInfo:NSBundle.mainBundle.infoDictionary + installations:installations + analytics:analytics]; + }; + + FIRComponent *component = + [FIRComponent componentWithProtocol:@protocol(FIRCrashlyticsInstanceProvider) + instantiationTiming:FIRInstantiationTimingEagerInDefaultApp + dependencies:@[ analyticsDep ] + creationBlock:creationBlock]; + return @[ component ]; +} + ++ (instancetype)crashlytics { + // The container will return the same instance since isCacheable is set + + FIRApp *defaultApp = [FIRApp defaultApp]; // Missing configure will be logged here. + + // Get the instance from the `FIRApp`'s container. This will create a new instance the + // first time it is called, and since `isCacheable` is set in the component creation + // block, it will return the existing instance on subsequent calls. + id<FIRCrashlyticsInstanceProvider> instance = + FIR_COMPONENT(FIRCrashlyticsInstanceProvider, defaultApp.container); + + // In the component creation block, we return an instance of `FIRCrashlytics`. Cast it and + // return it. + return (FIRCrashlytics *)instance; +} + +- (void)setCrashlyticsCollectionEnabled:(BOOL)enabled { + [self.dataArbiter setCrashlyticsCollectionEnabled:enabled]; +} + +- (BOOL)isCrashlyticsCollectionEnabled { + return [self.dataArbiter isCrashlyticsCollectionEnabled]; +} + +#pragma mark - API: didCrashDuringPreviousExecution + +- (BOOL)didCrashDuringPreviousExecution { + return self.didPreviouslyCrash; +} + +- (void)processDidCrashDuringPreviousExecution { + NSString *crashedMarkerFileName = [NSString stringWithUTF8String:FIRCLSCrashedMarkerFileName]; + NSString *crashedMarkerFileFullPath = + [[self.fileManager rootPath] stringByAppendingPathComponent:crashedMarkerFileName]; + self.didPreviouslyCrash = [self.fileManager fileExistsAtPath:crashedMarkerFileFullPath]; + + if (self.didPreviouslyCrash) { + // Delete the crash file marker in the background ensure start up is as fast as possible + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ + [self.fileManager removeItemAtPath:crashedMarkerFileFullPath]; + }); + } +} + +#pragma mark - API: Logging +- (void)log:(NSString *)msg { + FIRCLSLog(@"%@", msg); +} + +- (void)logWithFormat:(NSString *)format, ... { + va_list args; + va_start(args, format); + [self logWithFormat:format arguments:args]; + va_end(args); +} + +- (void)logWithFormat:(NSString *)format arguments:(va_list)args { + [self log:[[NSString alloc] initWithFormat:format arguments:args]]; +} + +#pragma mark - API: Accessors + +- (void)checkForUnsentReportsWithCompletion:(void (^)(BOOL))completion { + [[self.reportManager checkForUnsentReports] then:^id _Nullable(NSNumber *_Nullable value) { + completion([value boolValue]); + return nil; + }]; +} + +- (void)sendUnsentReports { + [self.reportManager sendUnsentReports]; +} + +- (void)deleteUnsentReports { + [self.reportManager deleteUnsentReports]; +} + +#pragma mark - API: setUserID +- (void)setUserID:(NSString *)userID { + FIRCLSUserLoggingRecordInternalKeyValue(FIRCLSUserIdentifierKey, userID); +} + +#pragma mark - API: setCustomValue + +- (void)setCustomValue:(id)value forKey:(NSString *)key { + FIRCLSUserLoggingRecordUserKeyValue(key, value); +} + +#pragma mark - API: Development Platform +// These two methods are depercated by our own API, so +// its ok to implement them +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" ++ (void)setDevelopmentPlatformName:(NSString *)name { + [[self crashlytics] setDevelopmentPlatformName:name]; +} + ++ (void)setDevelopmentPlatformVersion:(NSString *)version { + [[self crashlytics] setDevelopmentPlatformVersion:version]; +} +#pragma clang diagnostic pop + +- (NSString *)developmentPlatformName { + FIRCLSErrorLog(@"developmentPlatformName is write-only"); + return nil; +} + +- (void)setDevelopmentPlatformName:(NSString *)developmentPlatformName { + FIRCLSUserLoggingRecordInternalKeyValue(FIRCLSDevelopmentPlatformNameKey, + developmentPlatformName); +} + +- (NSString *)developmentPlatformVersion { + FIRCLSErrorLog(@"developmentPlatformVersion is write-only"); + return nil; +} + +- (void)setDevelopmentPlatformVersion:(NSString *)developmentPlatformVersion { + FIRCLSUserLoggingRecordInternalKeyValue(FIRCLSDevelopmentPlatformVersionKey, + developmentPlatformVersion); +} + +#pragma mark - API: Errors and Exceptions +- (void)recordError:(NSError *)error { + FIRCLSUserLoggingRecordError(error, nil); +} + +- (void)recordExceptionModel:(FIRExceptionModel *)exceptionModel { + FIRCLSExceptionRecordModel(exceptionModel); +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRExceptionModel.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRExceptionModel.m new file mode 100644 index 000000000..f0c4697a8 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRExceptionModel.m @@ -0,0 +1,42 @@ +// Copyright 2020 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRExceptionModel.h" + +@interface FIRExceptionModel () + +@property(nonatomic, copy) NSString *name; +@property(nonatomic, copy) NSString *reason; + +@end + +@implementation FIRExceptionModel + +- (instancetype)initWithName:(NSString *)name reason:(NSString *)reason { + self = [super init]; + if (!self) { + return nil; + } + + _name = [name copy]; + _reason = [reason copy]; + + return self; +} + ++ (instancetype)exceptionModelWithName:(NSString *)name reason:(NSString *)reason { + return [[FIRExceptionModel alloc] initWithName:name reason:reason]; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRStackFrame.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRStackFrame.m new file mode 100644 index 000000000..304491465 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRStackFrame.m @@ -0,0 +1,94 @@ +// Copyright 2020 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRStackFrame_Private.h" + +@interface FIRStackFrame () + +@property(nonatomic, copy, nullable) NSString *symbol; +@property(nonatomic, copy, nullable) NSString *rawSymbol; +@property(nonatomic, copy, nullable) NSString *library; +@property(nonatomic, copy, nullable) NSString *fileName; +@property(nonatomic, assign) uint32_t lineNumber; +@property(nonatomic, assign) uint64_t offset; +@property(nonatomic, assign) uint64_t address; + +@property(nonatomic, assign) BOOL isSymbolicated; + +@end + +@implementation FIRStackFrame + +#pragma mark - Public Methods + +- (instancetype)initWithSymbol:(NSString *)symbol file:(NSString *)file line:(NSInteger)line { + self = [super init]; + if (!self) { + return nil; + } + + _symbol = [symbol copy]; + _fileName = [file copy]; + _lineNumber = (uint32_t)line; + + _isSymbolicated = true; + + return self; +} + ++ (instancetype)stackFrameWithSymbol:(NSString *)symbol file:(NSString *)file line:(NSInteger)line { + return [[FIRStackFrame alloc] initWithSymbol:symbol file:file line:line]; +} + +#pragma mark - Internal Methods + ++ (instancetype)stackFrame { + return [[self alloc] init]; +} + ++ (instancetype)stackFrameWithAddress:(NSUInteger)address { + FIRStackFrame *frame = [self stackFrame]; + + [frame setAddress:address]; + + return frame; +} + ++ (instancetype)stackFrameWithSymbol:(NSString *)symbol { + FIRStackFrame *frame = [self stackFrame]; + + frame.symbol = symbol; + frame.rawSymbol = symbol; + + return frame; +} + +#pragma mark - Overrides + +- (NSString *)description { + if (self.isSymbolicated) { + return [NSString + stringWithFormat:@"{%@ - %@:%u}", [self fileName], [self symbol], [self lineNumber]]; + } + + if (self.fileName) { + return [NSString stringWithFormat:@"{[0x%llx] %@ - %@:%u}", [self address], [self fileName], + [self symbol], [self lineNumber]]; + } + + return [NSString + stringWithFormat:@"{[0x%llx + %u] %@}", [self address], [self lineNumber], [self symbol]]; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSException.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSException.h new file mode 100644 index 000000000..61dac77c3 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSException.h @@ -0,0 +1,73 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include <stdint.h> +#include <sys/cdefs.h> + +#ifdef __OBJC__ +#import <Foundation/Foundation.h> +@class FIRStackFrame; +@class FIRExceptionModel; +#endif + +#define CLS_EXCEPTION_STRING_LENGTH_MAX (1024 * 16) + +typedef enum { + FIRCLSExceptionTypeUnknown = 0, + FIRCLSExceptionTypeObjectiveC = 1, + FIRCLSExceptionTypeCpp = 2, + // 3 was FIRCLSExceptionTypeJavascript + // Keeping these numbers the same just to be safe + FIRCLSExceptionTypeCustom = 4 +} FIRCLSExceptionType; + +typedef struct { + const char* path; + + void (*originalTerminateHandler)(void); + +#if !TARGET_OS_IPHONE + void* originalNSApplicationReportException; +#endif + + uint32_t maxCustomExceptions; +} FIRCLSExceptionReadOnlyContext; + +typedef struct { + uint32_t customExceptionCount; +} FIRCLSExceptionWritableContext; + +__BEGIN_DECLS + +void FIRCLSExceptionInitialize(FIRCLSExceptionReadOnlyContext* roContext, + FIRCLSExceptionWritableContext* rwContext, + void* delegate); +void FIRCLSExceptionCheckHandlers(void* delegate); + +void FIRCLSExceptionRaiseTestObjCException(void) __attribute((noreturn)); +void FIRCLSExceptionRaiseTestCppException(void) __attribute((noreturn)); + +#ifdef __OBJC__ +void FIRCLSExceptionRecordModel(FIRExceptionModel* exceptionModel); +void FIRCLSExceptionRecordNSException(NSException* exception); +void FIRCLSExceptionRecord(FIRCLSExceptionType type, + const char* name, + const char* reason, + NSArray<FIRStackFrame*>* frames, + BOOL attemptDelivery); +#endif + +__END_DECLS diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSException.mm b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSException.mm new file mode 100644 index 000000000..6f2099045 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSException.mm @@ -0,0 +1,410 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +#include "FIRCLSException.h" + +#import "FIRExceptionModel_Private.h" +#import "FIRStackFrame_Private.h" + +#include "FIRCLSApplication.h" +#include "FIRCLSFile.h" +#include "FIRCLSGlobals.h" +#include "FIRCLSHandler.h" +#import "FIRCLSLogger.h" +#include "FIRCLSProcess.h" +#import "FIRCLSUserLogging.h" +#import "FIRCLSUtility.h" + +#include "FIRCLSDemangleOperation.h" +#import "FIRCLSReportManager_Private.h" + +// C++/Objective-C exception handling +#include <cxxabi.h> +#include <exception> +#include <string> +#include <typeinfo> + +#if !TARGET_OS_IPHONE +#import <AppKit/NSApplication.h> +#import <objc/runtime.h> +#endif + +#pragma mark Prototypes +static void FIRCLSTerminateHandler(void); +#if !TARGET_OS_IPHONE +void FIRCLSNSApplicationReportException(id self, SEL cmd, NSException *exception); + +typedef void (*NSApplicationReportExceptionFunction)(id, SEL, NSException *); + +static BOOL FIRCLSIsNSApplicationCrashOnExceptionsEnabled(void); +static NSApplicationReportExceptionFunction FIRCLSOriginalNSExceptionReportExceptionFunction(void); +static Method FIRCLSGetNSApplicationReportExceptionMethod(void); + +#endif + +#pragma mark - API +void FIRCLSExceptionInitialize(FIRCLSExceptionReadOnlyContext *roContext, + FIRCLSExceptionWritableContext *rwContext, + void *delegate) { + if (!FIRCLSUnlinkIfExists(roContext->path)) { + FIRCLSSDKLog("Unable to reset the exception file %s\n", strerror(errno)); + } + + roContext->originalTerminateHandler = std::set_terminate(FIRCLSTerminateHandler); + +#if !TARGET_OS_IPHONE + // If FIRCLSApplicationSharedInstance is null, we don't need this + if (FIRCLSIsNSApplicationCrashOnExceptionsEnabled() && FIRCLSApplicationSharedInstance()) { + Method m = FIRCLSGetNSApplicationReportExceptionMethod(); + + roContext->originalNSApplicationReportException = + (void *)method_setImplementation(m, (IMP)FIRCLSNSApplicationReportException); + } +#endif + + rwContext->customExceptionCount = 0; +} + +void FIRCLSExceptionRecordModel(FIRExceptionModel *exceptionModel) { + const char *name = [[exceptionModel.name copy] UTF8String]; + const char *reason = [[exceptionModel.reason copy] UTF8String]; + + FIRCLSExceptionRecord(FIRCLSExceptionTypeCustom, name, reason, [exceptionModel.stackTrace copy], + NO); +} + +void FIRCLSExceptionRecordNSException(NSException *exception) { + FIRCLSSDKLog("Recording an NSException\n"); + + NSArray *returnAddresses = [exception callStackReturnAddresses]; + + NSString *name = [exception name]; + NSString *reason = [exception reason]; + + // It's tempting to try to make use of callStackSymbols here. But, the output + // of that function is not intended to be machine-readible. We could parse it, + // but that isn't really worthwhile, considering that address-based symbolication + // needs to work anyways. + + // package our frames up into the appropriate format + NSMutableArray *frames = [NSMutableArray new]; + + for (NSNumber *address in returnAddresses) { + [frames addObject:[FIRStackFrame stackFrameWithAddress:[address unsignedIntegerValue]]]; + } + + FIRCLSExceptionRecord(FIRCLSExceptionTypeObjectiveC, [name UTF8String], [reason UTF8String], + frames, YES); +} + +static void FIRCLSExceptionRecordFrame(FIRCLSFile *file, FIRStackFrame *frame) { + FIRCLSFileWriteHashStart(file); + + FIRCLSFileWriteHashEntryUint64(file, "pc", [frame address]); + + NSString *string = [frame symbol]; + if (string) { + FIRCLSFileWriteHashEntryHexEncodedString(file, "symbol", [string UTF8String]); + } + + FIRCLSFileWriteHashEntryUint64(file, "offset", [frame offset]); + + string = [frame library]; + if (string) { + FIRCLSFileWriteHashEntryHexEncodedString(file, "library", [string UTF8String]); + } + + string = [frame fileName]; + if (string) { + FIRCLSFileWriteHashEntryHexEncodedString(file, "file", [string UTF8String]); + } + + FIRCLSFileWriteHashEntryUint64(file, "line", [frame lineNumber]); + + FIRCLSFileWriteHashEnd(file); +} + +static bool FIRCLSExceptionIsNative(FIRCLSExceptionType type) { + return type == FIRCLSExceptionTypeObjectiveC || type == FIRCLSExceptionTypeCpp; +} + +static const char *FIRCLSExceptionNameForType(FIRCLSExceptionType type) { + switch (type) { + case FIRCLSExceptionTypeObjectiveC: + return "objective-c"; + case FIRCLSExceptionTypeCpp: + return "c++"; + case FIRCLSExceptionTypeCustom: + return "custom"; + default: + break; + } + + return "unknown"; +} + +void FIRCLSExceptionWrite(FIRCLSFile *file, + FIRCLSExceptionType type, + const char *name, + const char *reason, + NSArray<FIRStackFrame *> *frames) { + FIRCLSFileWriteSectionStart(file, "exception"); + + FIRCLSFileWriteHashStart(file); + + FIRCLSFileWriteHashEntryString(file, "type", FIRCLSExceptionNameForType(type)); + FIRCLSFileWriteHashEntryHexEncodedString(file, "name", name); + FIRCLSFileWriteHashEntryHexEncodedString(file, "reason", reason); + FIRCLSFileWriteHashEntryUint64(file, "time", time(NULL)); + + if ([frames count]) { + FIRCLSFileWriteHashKey(file, "frames"); + FIRCLSFileWriteArrayStart(file); + + for (FIRStackFrame *frame in frames) { + FIRCLSExceptionRecordFrame(file, frame); + } + + FIRCLSFileWriteArrayEnd(file); + } + + FIRCLSFileWriteHashEnd(file); + + FIRCLSFileWriteSectionEnd(file); +} + +void FIRCLSExceptionRecord(FIRCLSExceptionType type, + const char *name, + const char *reason, + NSArray<FIRStackFrame *> *frames, + BOOL attemptDelivery) { + if (!FIRCLSContextIsInitialized()) { + return; + } + + bool native = FIRCLSExceptionIsNative(type); + + FIRCLSSDKLog("Recording an exception structure (%d, %d)\n", attemptDelivery, native); + + // exceptions can happen on multiple threads at the same time + if (native) { + dispatch_sync(_firclsExceptionQueue, ^{ + const char *path = _firclsContext.readonly->exception.path; + FIRCLSFile file; + + if (!FIRCLSFileInitWithPath(&file, path, false)) { + FIRCLSSDKLog("Unable to open exception file\n"); + return; + } + + FIRCLSExceptionWrite(&file, type, name, reason, frames); + + // We only want to do this work if we have the expectation that we'll actually crash + FIRCLSHandler(&file, mach_thread_self(), NULL); + + FIRCLSFileClose(&file); + + // disallow immediate delivery for non-native exceptions + if (attemptDelivery) { + FIRCLSHandlerAttemptImmediateDelivery(); + } + }); + } else { + FIRCLSUserLoggingWriteAndCheckABFiles( + &_firclsContext.readonly->logging.customExceptionStorage, + &_firclsContext.writable->logging.activeCustomExceptionPath, ^(FIRCLSFile *file) { + FIRCLSExceptionWrite(file, type, name, reason, frames); + }); + } + + FIRCLSSDKLog("Finished recording an exception structure\n"); +} + +// Ignore this message here, because we know that this call will not leak. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Winvalid-noreturn" +void FIRCLSExceptionRaiseTestObjCException(void) { + [NSException raise:@"CrashlyticsTestException" + format:@"This is an Objective-C exception using for testing."]; +} + +void FIRCLSExceptionRaiseTestCppException(void) { + throw "Crashlytics C++ Test Exception"; +} +#pragma clang diagnostic pop + +static const char *FIRCLSExceptionDemangle(const char *symbol) { + return [[FIRCLSDemangleOperation demangleCppSymbol:symbol] UTF8String]; +} + +static void FIRCLSCatchAndRecordActiveException(std::type_info *typeInfo) { + if (!FIRCLSIsValidPointer(typeInfo)) { + FIRCLSSDKLog("Error: invalid parameter\n"); + return; + } + + const char *name = typeInfo->name(); + FIRCLSSDKLog("Recording exception of type '%s'\n", name); + + // This is a funny technique to get the exception object. The inner @try + // has the ability to capture NSException-derived objects. It seems that + // c++ trys can do that in some cases, but I was warned by the WWDC labs + // that there are cases where that will not work (like for NSException subclasses). + try { + @try { + // This could potentially cause a call to std::terminate() if there is actually no active + // exception. + throw; + } @catch (NSException *exception) { +#if TARGET_OS_IPHONE + FIRCLSExceptionRecordNSException(exception); +#else + // There's no need to record this here, because we're going to get + // the value forward to us by AppKit + FIRCLSSDKLog("Skipping ObjC exception at this point\n"); +#endif + } + } catch (const char *exc) { + FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, "const char *", exc, nil, YES); + } catch (const std::string &exc) { + FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, "std::string", exc.c_str(), nil, YES); + } catch (const std::exception &exc) { + FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, FIRCLSExceptionDemangle(name), exc.what(), nil, + YES); + } catch (const std::exception *exc) { + FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, FIRCLSExceptionDemangle(name), exc->what(), nil, + YES); + } catch (const std::bad_alloc &exc) { + // it is especially important to avoid demangling in this case, because the expetation at this + // point is that all allocations could fail + FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, "std::bad_alloc", exc.what(), nil, YES); + } catch (...) { + FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, FIRCLSExceptionDemangle(name), "", nil, YES); + } +} + +#pragma mark - Handlers +static void FIRCLSTerminateHandler(void) { + FIRCLSSDKLog("C++ terminate handler invoked\n"); + + void (*handler)(void) = _firclsContext.readonly->exception.originalTerminateHandler; + if (handler == FIRCLSTerminateHandler) { + FIRCLSSDKLog("Error: original handler was set recursively\n"); + handler = NULL; + } + + // Restore pre-existing handler, if any. Do this early, so that + // if std::terminate is called while we are executing here, we do not recurse. + if (handler) { + FIRCLSSDKLog("restoring pre-existing handler\n"); + + // To prevent infinite recursion in this function, check that we aren't resetting the terminate + // handler to the same function again, which would be this function in the event that we can't + // actually change the handler during a terminate. + if (std::set_terminate(handler) == handler) { + FIRCLSSDKLog("handler has already been restored, aborting\n"); + abort(); + } + } + + // we can use typeInfo to record the type of the exception, + // but we must use a catch to get the value + std::type_info *typeInfo = __cxxabiv1::__cxa_current_exception_type(); + if (typeInfo) { + FIRCLSCatchAndRecordActiveException(typeInfo); + } else { + FIRCLSSDKLog("no active exception\n"); + } + + // only do this if there was a pre-existing handler + if (handler) { + FIRCLSSDKLog("invoking pre-existing handler\n"); + handler(); + } + + FIRCLSSDKLog("aborting\n"); + abort(); +} + +void FIRCLSExceptionCheckHandlers(void *delegate) { +#if !TARGET_OS_IPHONE + // Check this on OS X all the time, even if the debugger is attached. This is a common + // source of errors, so we want to be extra verbose in this case. + if (FIRCLSApplicationSharedInstance()) { + if (!FIRCLSIsNSApplicationCrashOnExceptionsEnabled()) { + FIRCLSWarningLog(@"Warning: NSApplicationCrashOnExceptions is not set. This will " + @"result in poor top-level uncaught exception reporting."); + } + } +#endif + + if (_firclsContext.readonly->debuggerAttached) { + return; + } + + void *ptr = NULL; + + ptr = (void *)std::get_terminate(); + if (ptr != FIRCLSTerminateHandler) { + FIRCLSLookupFunctionPointer(ptr, ^(const char *name, const char *lib) { + FIRCLSWarningLog(@"Warning: std::get_terminate is '%s' in '%s'", name, lib); + }); + } + +#if TARGET_OS_IPHONE + ptr = (void *)NSGetUncaughtExceptionHandler(); + if (ptr) { + FIRCLSLookupFunctionPointer(ptr, ^(const char *name, const char *lib) { + FIRCLSWarningLog(@"Warning: NSUncaughtExceptionHandler is '%s' in '%s'", name, lib); + }); + } +#else + if (FIRCLSApplicationSharedInstance() && FIRCLSIsNSApplicationCrashOnExceptionsEnabled()) { + // In this case, we *might* be able to intercept exceptions. But, verify we've still + // swizzled the method. + Method m = FIRCLSGetNSApplicationReportExceptionMethod(); + + if (method_getImplementation(m) != (IMP)FIRCLSNSApplicationReportException) { + FIRCLSWarningLog( + @"Warning: top-level NSApplication-reported exceptions cannot be intercepted"); + } + } +#endif +} + +#pragma mark - AppKit Handling +#if !TARGET_OS_IPHONE +static BOOL FIRCLSIsNSApplicationCrashOnExceptionsEnabled(void) { + return [[NSUserDefaults standardUserDefaults] boolForKey:@"NSApplicationCrashOnExceptions"]; +} + +static Method FIRCLSGetNSApplicationReportExceptionMethod(void) { + return class_getInstanceMethod(NSClassFromString(@"NSApplication"), @selector(reportException:)); +} + +static NSApplicationReportExceptionFunction FIRCLSOriginalNSExceptionReportExceptionFunction(void) { + return (NSApplicationReportExceptionFunction) + _firclsContext.readonly->exception.originalNSApplicationReportException; +} + +void FIRCLSNSApplicationReportException(id self, SEL cmd, NSException *exception) { + FIRCLSExceptionRecordNSException(exception); + + // Call the original implementation + FIRCLSOriginalNSExceptionReportExceptionFunction()(self, cmd, exception); +} + +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSHandler.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSHandler.h new file mode 100644 index 000000000..7ce03e416 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSHandler.h @@ -0,0 +1,26 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include <mach/mach.h> + +#include "FIRCLSFile.h" + +__BEGIN_DECLS + +void FIRCLSHandler(FIRCLSFile* file, thread_t crashedThread, void* uapVoid); +void FIRCLSHandlerAttemptImmediateDelivery(void); + +__END_DECLS diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSHandler.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSHandler.m new file mode 100644 index 000000000..918e4265e --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSHandler.m @@ -0,0 +1,61 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSHandler.h" + +#include "FIRCLSCrashedMarkerFile.h" +#include "FIRCLSGlobals.h" +#include "FIRCLSHost.h" +#include "FIRCLSProcess.h" +#include "FIRCLSUtility.h" + +#import "FIRCLSReportManager_Private.h" + +void FIRCLSHandler(FIRCLSFile* file, thread_t crashedThread, void* uapVoid) { + FIRCLSProcess process; + + FIRCLSProcessInit(&process, crashedThread, uapVoid); + + FIRCLSProcessSuspendAllOtherThreads(&process); + + FIRCLSProcessRecordAllThreads(&process, file); + + FIRCLSProcessRecordRuntimeInfo(&process, file); + // Get dispatch queue and thread names. Note that getting the thread names + // can hang, so let's do that last + FIRCLSProcessRecordDispatchQueueNames(&process, file); + FIRCLSProcessRecordThreadNames(&process, file); + + // this stuff isn't super important, but we can try + FIRCLSProcessRecordStats(&process, file); + FIRCLSHostWriteDiskUsage(file); + + // This is the first common point where various crash handlers call into + // Store a crash file marker to indicate that a crash has occured + FIRCLSCreateCrashedMarkerFile(); + + FIRCLSProcessResumeAllOtherThreads(&process); + + // clean up after ourselves + FIRCLSProcessDestroy(&process); +} + +void FIRCLSHandlerAttemptImmediateDelivery(void) { + // now, attempt to relay the event to the delegate + FIRCLSReportManager* manager = (__bridge id)_firclsContext.readonly->delegate; + + if ([manager respondsToSelector:@selector(potentiallySubmittableCrashOccurred)]) { + [manager potentiallySubmittableCrashOccurred]; + } +} diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSMachException.c b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSMachException.c new file mode 100644 index 000000000..3ec4e9790 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSMachException.c @@ -0,0 +1,533 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSDefines.h" +#include "FIRCLSFeatures.h" + +#if CLS_MACH_EXCEPTION_SUPPORTED + +#include "FIRCLSGlobals.h" +#include "FIRCLSHandler.h" +#include "FIRCLSMachException.h" +#include "FIRCLSProcess.h" +#include "FIRCLSSignal.h" +#include "FIRCLSUtility.h" + +#include <errno.h> +#include <mach/mach.h> +#include <pthread.h> +#include <unistd.h> + +#pragma mark Prototypes +static exception_mask_t FIRCLSMachExceptionMask(void); +static void* FIRCLSMachExceptionServer(void* argument); +static bool FIRCLSMachExceptionThreadStart(FIRCLSMachExceptionReadContext* context); +static bool FIRCLSMachExceptionReadMessage(FIRCLSMachExceptionReadContext* context, + MachExceptionMessage* message); +static kern_return_t FIRCLSMachExceptionDispatchMessage(FIRCLSMachExceptionReadContext* context, + MachExceptionMessage* message); +static bool FIRCLSMachExceptionReply(FIRCLSMachExceptionReadContext* context, + MachExceptionMessage* message, + kern_return_t result); +static bool FIRCLSMachExceptionRegister(FIRCLSMachExceptionReadContext* context, + exception_mask_t ignoreMask); +static bool FIRCLSMachExceptionUnregister(FIRCLSMachExceptionOriginalPorts* originalPorts, + exception_mask_t mask); +static bool FIRCLSMachExceptionRecord(FIRCLSMachExceptionReadContext* context, + MachExceptionMessage* message); + +#pragma mark - Initialization +void FIRCLSMachExceptionInit(FIRCLSMachExceptionReadContext* context, exception_mask_t ignoreMask) { + if (!FIRCLSUnlinkIfExists(context->path)) { + FIRCLSSDKLog("Unable to reset the mach exception file %s\n", strerror(errno)); + } + + if (!FIRCLSMachExceptionRegister(context, ignoreMask)) { + FIRCLSSDKLog("Unable to register mach exception handler\n"); + return; + } + + if (!FIRCLSMachExceptionThreadStart(context)) { + FIRCLSSDKLog("Unable to start thread\n"); + FIRCLSMachExceptionUnregister(&context->originalPorts, context->mask); + } +} + +void FIRCLSMachExceptionCheckHandlers(void) { + if (_firclsContext.readonly->debuggerAttached) { + return; + } + + // It isn't really critical that this be done, as its extremely uncommon to run into + // preexisting handlers. + // Can use task_get_exception_ports for this. +} + +static exception_mask_t FIRCLSMachExceptionMask(void) { + exception_mask_t mask; + + // EXC_BAD_ACCESS + // EXC_BAD_INSTRUCTION + // EXC_ARITHMETIC + // EXC_EMULATION - non-failure + // EXC_SOFTWARE - non-failure + // EXC_BREAKPOINT - trap instructions, from the debugger and code. Needs special treatment. + // EXC_SYSCALL - non-failure + // EXC_MACH_SYSCALL - non-failure + // EXC_RPC_ALERT - non-failure + // EXC_CRASH - see below + // EXC_RESOURCE - non-failure, happens when a process exceeds a resource limit + // EXC_GUARD - see below + // + // EXC_CRASH is a special kind of exception. It is handled by launchd, and treated special by + // the kernel. Seems that we cannot safely catch it - our handler will never be called. This + // is a confirmed kernel bug. Lacking access to EXC_CRASH means we must use signal handlers to + // cover all types of crashes. + // EXC_GUARD is relatively new, and isn't available on all OS versions. You have to be careful, + // becuase you cannot succesfully register hanlders if there are any unrecognized masks. We've + // dropped support for old OS versions that didn't have EXC_GUARD (iOS 5 and below, macOS 10.6 and + // below) so we always add it now + + mask = EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC | + EXC_MASK_BREAKPOINT | EXC_MASK_GUARD; + + return mask; +} + +static bool FIRCLSMachExceptionThreadStart(FIRCLSMachExceptionReadContext* context) { + pthread_attr_t attr; + + if (pthread_attr_init(&attr) != 0) { + FIRCLSSDKLog("pthread_attr_init %s\n", strerror(errno)); + return false; + } + + if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0) { + FIRCLSSDKLog("pthread_attr_setdetachstate %s\n", strerror(errno)); + return false; + } + + // Use to pre-allocate a stack for this thread + // The stack must be page-aligned + if (pthread_attr_setstack(&attr, _firclsContext.readonly->machStack, + CLS_MACH_EXCEPTION_HANDLER_STACK_SIZE) != 0) { + FIRCLSSDKLog("pthread_attr_setstack %s\n", strerror(errno)); + return false; + } + + if (pthread_create(&context->thread, &attr, FIRCLSMachExceptionServer, context) != 0) { + FIRCLSSDKLog("pthread_create %s\n", strerror(errno)); + return false; + } + + pthread_attr_destroy(&attr); + + return true; +} + +exception_mask_t FIRCLSMachExceptionMaskForSignal(int signal) { + switch (signal) { + case SIGTRAP: + return EXC_MASK_BREAKPOINT; + case SIGSEGV: + return EXC_MASK_BAD_ACCESS; + case SIGBUS: + return EXC_MASK_BAD_ACCESS; + case SIGILL: + return EXC_MASK_BAD_INSTRUCTION; + case SIGABRT: + return EXC_MASK_CRASH; + case SIGSYS: + return EXC_MASK_CRASH; + case SIGFPE: + return EXC_MASK_ARITHMETIC; + } + + return 0; +} + +#pragma mark - Message Handling +static void* FIRCLSMachExceptionServer(void* argument) { + FIRCLSMachExceptionReadContext* context = argument; + + pthread_setname_np("com.google.firebase.crashlytics.MachExceptionServer"); + + while (1) { + MachExceptionMessage message; + + // read the exception message + if (!FIRCLSMachExceptionReadMessage(context, &message)) { + break; + } + + // handle it, and possibly forward + kern_return_t result = FIRCLSMachExceptionDispatchMessage(context, &message); + + // and now, reply + if (!FIRCLSMachExceptionReply(context, &message, result)) { + break; + } + } + + FIRCLSSDKLog("Mach exception server thread exiting\n"); + + return NULL; +} + +static bool FIRCLSMachExceptionReadMessage(FIRCLSMachExceptionReadContext* context, + MachExceptionMessage* message) { + mach_msg_return_t r; + + memset(message, 0, sizeof(MachExceptionMessage)); + + r = mach_msg(&message->head, MACH_RCV_MSG | MACH_RCV_LARGE, 0, sizeof(MachExceptionMessage), + context->port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + if (r != MACH_MSG_SUCCESS) { + FIRCLSSDKLog("Error receving mach_msg (%d)\n", r); + return false; + } + + FIRCLSSDKLog("Accepted mach exception message\n"); + + return true; +} + +static kern_return_t FIRCLSMachExceptionDispatchMessage(FIRCLSMachExceptionReadContext* context, + MachExceptionMessage* message) { + FIRCLSSDKLog("Mach exception: 0x%x, count: %d, code: 0x%llx 0x%llx\n", message->exception, + message->codeCnt, message->codeCnt > 0 ? message->code[0] : -1, + message->codeCnt > 1 ? message->code[1] : -1); + + // This will happen if a child process raises an exception, as the exception ports are + // inherited. + if (message->task.name != mach_task_self()) { + FIRCLSSDKLog("Mach exception task mis-match, returning failure\n"); + return KERN_FAILURE; + } + + FIRCLSSDKLog("Unregistering handler\n"); + if (!FIRCLSMachExceptionUnregister(&context->originalPorts, context->mask)) { + FIRCLSSDKLog("Failed to unregister\n"); + return KERN_FAILURE; + } + + FIRCLSSDKLog("Restoring original signal handlers\n"); + if (!FIRCLSSignalSafeInstallPreexistingHandlers(&_firclsContext.readonly->signal)) { + FIRCLSSDKLog("Failed to restore signal handlers\n"); + return KERN_FAILURE; + } + + FIRCLSSDKLog("Recording mach exception\n"); + if (!FIRCLSMachExceptionRecord(context, message)) { + FIRCLSSDKLog("Failed to record mach exception\n"); + return KERN_FAILURE; + } + + return KERN_SUCCESS; +} + +static bool FIRCLSMachExceptionReply(FIRCLSMachExceptionReadContext* context, + MachExceptionMessage* message, + kern_return_t result) { + MachExceptionReply reply; + mach_msg_return_t r; + + // prepare the reply + reply.head.msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(message->head.msgh_bits), 0); + reply.head.msgh_remote_port = message->head.msgh_remote_port; + reply.head.msgh_size = (mach_msg_size_t)sizeof(MachExceptionReply); + reply.head.msgh_local_port = MACH_PORT_NULL; + reply.head.msgh_id = message->head.msgh_id + 100; + + reply.NDR = NDR_record; + + reply.retCode = result; + + FIRCLSSDKLog("Sending exception reply\n"); + + // send it + r = mach_msg(&reply.head, MACH_SEND_MSG, reply.head.msgh_size, 0, MACH_PORT_NULL, + MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + if (r != MACH_MSG_SUCCESS) { + FIRCLSSDKLog("mach_msg reply failed (%d)\n", r); + return false; + } + + FIRCLSSDKLog("Exception reply delivered\n"); + + return true; +} + +#pragma mark - Registration +static bool FIRCLSMachExceptionRegister(FIRCLSMachExceptionReadContext* context, + exception_mask_t ignoreMask) { + mach_port_t task = mach_task_self(); + + kern_return_t kr = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &context->port); + if (kr != KERN_SUCCESS) { + FIRCLSSDKLog("Error: mach_port_allocate failed %d\n", kr); + return false; + } + + kr = mach_port_insert_right(task, context->port, context->port, MACH_MSG_TYPE_MAKE_SEND); + if (kr != KERN_SUCCESS) { + FIRCLSSDKLog("Error: mach_port_insert_right failed %d\n", kr); + mach_port_deallocate(task, context->port); + return false; + } + + // Get the desired mask, which covers all the mach exceptions we are capable of handling, + // but clear out any that are in our ignore list. We do this by ANDing with the bitwise + // negation. Because we are only clearing bits, there's no way to set an incorrect mask + // using ignoreMask. + context->mask = FIRCLSMachExceptionMask() & ~ignoreMask; + + // ORing with MACH_EXCEPTION_CODES will produce 64-bit exception data + kr = task_swap_exception_ports(task, context->mask, context->port, + EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE, + context->originalPorts.masks, &context->originalPorts.count, + context->originalPorts.ports, context->originalPorts.behaviors, + context->originalPorts.flavors); + if (kr != KERN_SUCCESS) { + FIRCLSSDKLog("Error: task_swap_exception_ports %d\n", kr); + return false; + } + + for (int i = 0; i < context->originalPorts.count; ++i) { + FIRCLSSDKLog("original 0x%x 0x%x 0x%x 0x%x\n", context->originalPorts.ports[i], + context->originalPorts.masks[i], context->originalPorts.behaviors[i], + context->originalPorts.flavors[i]); + } + + return true; +} + +static bool FIRCLSMachExceptionUnregister(FIRCLSMachExceptionOriginalPorts* originalPorts, + exception_mask_t mask) { + kern_return_t kr; + + // Re-register all the old ports. + for (mach_msg_type_number_t i = 0; i < originalPorts->count; ++i) { + // clear the bits from this original mask + mask &= ~originalPorts->masks[i]; + + kr = + task_set_exception_ports(mach_task_self(), originalPorts->masks[i], originalPorts->ports[i], + originalPorts->behaviors[i], originalPorts->flavors[i]); + if (kr != KERN_SUCCESS) { + FIRCLSSDKLog("unable to restore original port: %d", originalPorts->ports[i]); + } + } + + // Finally, mark any masks we registered for that do not have an original port as unused. + kr = task_set_exception_ports(mach_task_self(), mask, MACH_PORT_NULL, + EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE); + if (kr != KERN_SUCCESS) { + FIRCLSSDKLog("unable to unset unregistered mask: 0x%x", mask); + return false; + } + + return true; +} + +#pragma mark - Recording +static void FIRCLSMachExceptionNameLookup(exception_type_t number, + mach_exception_data_type_t code, + const char** name, + const char** codeName) { + if (!name || !codeName) { + return; + } + + *name = NULL; + *codeName = NULL; + + switch (number) { + case EXC_BAD_ACCESS: + *name = "EXC_BAD_ACCESS"; + switch (code) { + case KERN_INVALID_ADDRESS: + *codeName = "KERN_INVALID_ADDRESS"; + break; + case KERN_PROTECTION_FAILURE: + *codeName = "KERN_PROTECTION_FAILURE"; + break; + } + + break; + case EXC_BAD_INSTRUCTION: + *name = "EXC_BAD_INSTRUCTION"; +#if CLS_CPU_X86 + *codeName = "EXC_I386_INVOP"; +#endif + break; + case EXC_ARITHMETIC: + *name = "EXC_ARITHMETIC"; +#if CLS_CPU_X86 + switch (code) { + case EXC_I386_DIV: + *codeName = "EXC_I386_DIV"; + break; + case EXC_I386_INTO: + *codeName = "EXC_I386_INTO"; + break; + case EXC_I386_NOEXT: + *codeName = "EXC_I386_NOEXT"; + break; + case EXC_I386_EXTOVR: + *codeName = "EXC_I386_EXTOVR"; + break; + case EXC_I386_EXTERR: + *codeName = "EXC_I386_EXTERR"; + break; + case EXC_I386_EMERR: + *codeName = "EXC_I386_EMERR"; + break; + case EXC_I386_BOUND: + *codeName = "EXC_I386_BOUND"; + break; + case EXC_I386_SSEEXTERR: + *codeName = "EXC_I386_SSEEXTERR"; + break; + } +#endif + break; + case EXC_BREAKPOINT: + *name = "EXC_BREAKPOINT"; +#if CLS_CPU_X86 + switch (code) { + case EXC_I386_DIVERR: + *codeName = "EXC_I386_DIVERR"; + break; + case EXC_I386_SGLSTP: + *codeName = "EXC_I386_SGLSTP"; + break; + case EXC_I386_NMIFLT: + *codeName = "EXC_I386_NMIFLT"; + break; + case EXC_I386_BPTFLT: + *codeName = "EXC_I386_BPTFLT"; + break; + case EXC_I386_INTOFLT: + *codeName = "EXC_I386_INTOFLT"; + break; + case EXC_I386_BOUNDFLT: + *codeName = "EXC_I386_BOUNDFLT"; + break; + case EXC_I386_INVOPFLT: + *codeName = "EXC_I386_INVOPFLT"; + break; + case EXC_I386_NOEXTFLT: + *codeName = "EXC_I386_NOEXTFLT"; + break; + case EXC_I386_EXTOVRFLT: + *codeName = "EXC_I386_EXTOVRFLT"; + break; + case EXC_I386_INVTSSFLT: + *codeName = "EXC_I386_INVTSSFLT"; + break; + case EXC_I386_SEGNPFLT: + *codeName = "EXC_I386_SEGNPFLT"; + break; + case EXC_I386_STKFLT: + *codeName = "EXC_I386_STKFLT"; + break; + case EXC_I386_GPFLT: + *codeName = "EXC_I386_GPFLT"; + break; + case EXC_I386_PGFLT: + *codeName = "EXC_I386_PGFLT"; + break; + case EXC_I386_EXTERRFLT: + *codeName = "EXC_I386_EXTERRFLT"; + break; + case EXC_I386_ALIGNFLT: + *codeName = "EXC_I386_ALIGNFLT"; + break; + case EXC_I386_ENDPERR: + *codeName = "EXC_I386_ENDPERR"; + break; + case EXC_I386_ENOEXTFLT: + *codeName = "EXC_I386_ENOEXTFLT"; + break; + } +#endif + break; + case EXC_GUARD: + *name = "EXC_GUARD"; + break; + } +} + +static bool FIRCLSMachExceptionRecord(FIRCLSMachExceptionReadContext* context, + MachExceptionMessage* message) { + if (!context || !message) { + return false; + } + + if (FIRCLSContextMarkAndCheckIfCrashed()) { + FIRCLSSDKLog("Error: aborting mach exception handler because crash has already occurred\n"); + exit(1); + return false; + } + + FIRCLSFile file; + + if (!FIRCLSFileInitWithPath(&file, context->path, false)) { + FIRCLSSDKLog("Unable to open mach exception file\n"); + return false; + } + + FIRCLSFileWriteSectionStart(&file, "mach_exception"); + + FIRCLSFileWriteHashStart(&file); + + FIRCLSFileWriteHashEntryUint64(&file, "exception", message->exception); + + // record the codes + FIRCLSFileWriteHashKey(&file, "codes"); + FIRCLSFileWriteArrayStart(&file); + for (mach_msg_type_number_t i = 0; i < message->codeCnt; ++i) { + FIRCLSFileWriteArrayEntryUint64(&file, message->code[i]); + } + FIRCLSFileWriteArrayEnd(&file); + + const char* name = NULL; + const char* codeName = NULL; + + FIRCLSMachExceptionNameLookup(message->exception, message->codeCnt > 0 ? message->code[0] : 0, + &name, &codeName); + + FIRCLSFileWriteHashEntryString(&file, "name", name); + FIRCLSFileWriteHashEntryString(&file, "code_name", codeName); + + FIRCLSFileWriteHashEntryUint64(&file, "original_ports", context->originalPorts.count); + FIRCLSFileWriteHashEntryUint64(&file, "time", time(NULL)); + + FIRCLSFileWriteHashEnd(&file); + + FIRCLSFileWriteSectionEnd(&file); + + FIRCLSHandler(&file, message->thread.name, NULL); + + FIRCLSFileClose(&file); + + return true; +} + +#else + +INJECT_STRIP_SYMBOL(cls_mach_exception) + +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSMachException.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSMachException.h new file mode 100644 index 000000000..b19881a7a --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSMachException.h @@ -0,0 +1,78 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSFeatures.h" + +#pragma once + +#if CLS_MACH_EXCEPTION_SUPPORTED + +#include <mach/mach.h> +#include <pthread.h> +#include <stdbool.h> + +// must be at least PTHREAD_STACK_MIN size +#define CLS_MACH_EXCEPTION_HANDLER_STACK_SIZE (256 * 1024) + +#pragma mark Structures +#pragma pack(push, 4) +typedef struct { + mach_msg_header_t head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + mach_exception_data_type_t code[EXCEPTION_CODE_MAX]; + mach_msg_trailer_t trailer; +} MachExceptionMessage; + +typedef struct { + mach_msg_header_t head; + NDR_record_t NDR; + kern_return_t retCode; +} MachExceptionReply; +#pragma pack(pop) + +typedef struct { + mach_msg_type_number_t count; + exception_mask_t masks[EXC_TYPES_COUNT]; + exception_handler_t ports[EXC_TYPES_COUNT]; + exception_behavior_t behaviors[EXC_TYPES_COUNT]; + thread_state_flavor_t flavors[EXC_TYPES_COUNT]; +} FIRCLSMachExceptionOriginalPorts; + +typedef struct { + mach_port_t port; + pthread_t thread; + const char* path; + + exception_mask_t mask; + FIRCLSMachExceptionOriginalPorts originalPorts; +} FIRCLSMachExceptionReadContext; + +#pragma mark - API +void FIRCLSMachExceptionInit(FIRCLSMachExceptionReadContext* context, exception_mask_t ignoreMask); +exception_mask_t FIRCLSMachExceptionMaskForSignal(int signal); + +void FIRCLSMachExceptionCheckHandlers(void); + +#else + +#define CLS_MACH_EXCEPTION_HANDLER_STACK_SIZE 0 + +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSSignal.c b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSSignal.c new file mode 100644 index 000000000..5fa302d7c --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSSignal.c @@ -0,0 +1,318 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSSignal.h" +#include "FIRCLSGlobals.h" +#include "FIRCLSHandler.h" +#include "FIRCLSUtility.h" + +#include <dlfcn.h> +#include <stdlib.h> + +static const int FIRCLSFatalSignals[FIRCLSSignalCount] = {SIGABRT, SIGBUS, SIGFPE, SIGILL, + SIGSEGV, SIGSYS, SIGTRAP}; + +#if CLS_USE_SIGALTSTACK +static void FIRCLSSignalInstallAltStack(FIRCLSSignalReadContext *roContext); +#endif +static void FIRCLSSignalInstallHandlers(FIRCLSSignalReadContext *roContext); +static void FIRCLSSignalHandler(int signal, siginfo_t *info, void *uapVoid); + +void FIRCLSSignalInitialize(FIRCLSSignalReadContext *roContext) { + if (!FIRCLSUnlinkIfExists(roContext->path)) { + FIRCLSSDKLog("Unable to reset the signal log file %s\n", strerror(errno)); + } + +#if CLS_USE_SIGALTSTACK + FIRCLSSignalInstallAltStack(roContext); +#endif + FIRCLSSignalInstallHandlers(roContext); +#if TARGET_IPHONE_SIMULATOR + // prevent the OpenGL stack (by way of OpenGLES.framework/libLLVMContainer.dylib) from installing + // signal handlers that do not chain back + // TODO: I don't believe this is necessary as of recent iOS releases + bool *ptr = dlsym(RTLD_DEFAULT, "_ZN4llvm23DisablePrettyStackTraceE"); + if (ptr) { + *ptr = true; + } +#endif +} + +void FIRCLSSignalEnumerateHandledSignals(void (^block)(int idx, int signal)) { + for (int i = 0; i < FIRCLSSignalCount; ++i) { + block(i, FIRCLSFatalSignals[i]); + } +} + +#if CLS_USE_SIGALTSTACK + +static void FIRCLSSignalInstallAltStack(FIRCLSSignalReadContext *roContext) { + stack_t signalStack; + stack_t originalStack; + + signalStack.ss_sp = _firclsContext.readonly->signalStack; + signalStack.ss_size = CLS_SIGNAL_HANDLER_STACK_SIZE; + signalStack.ss_flags = 0; + + if (sigaltstack(&signalStack, &originalStack) != 0) { + FIRCLSSDKLog("Unable to setup stack %s\n", strerror(errno)); + + return; + } + + roContext->originalStack.ss_sp = NULL; + roContext->originalStack = originalStack; +} + +#endif + +static void FIRCLSSignalInstallHandlers(FIRCLSSignalReadContext *roContext) { + FIRCLSSignalEnumerateHandledSignals(^(int idx, int signal) { + struct sigaction action; + struct sigaction previousAction; + + action.sa_sigaction = FIRCLSSignalHandler; + // SA_RESETHAND seems like it would be great, but it doesn't appear to + // work correctly. After taking a signal, causing another identical signal in + // the handler will *not* cause the default handler to be invokved (which should + // terminate the process). I've found some evidence that others have seen this + // behavior on MAC OS X. + action.sa_flags = SA_SIGINFO | SA_ONSTACK; + + sigemptyset(&action.sa_mask); + + previousAction.sa_sigaction = NULL; + if (sigaction(signal, &action, &previousAction) != 0) { + FIRCLSSDKLog("Unable to install handler for %d (%s)\n", signal, strerror(errno)); + } + + // store the last action, so it can be recalled + roContext->originalActions[idx].sa_sigaction = NULL; + + if (previousAction.sa_sigaction) { + roContext->originalActions[idx] = previousAction; + } + }); +} + +void FIRCLSSignalCheckHandlers(void) { + if (_firclsContext.readonly->debuggerAttached) { + return; + } + + FIRCLSSignalEnumerateHandledSignals(^(int idx, int signal) { + struct sigaction previousAction; + Dl_info info; + void *ptr; + + if (sigaction(signal, 0, &previousAction) != 0) { + fprintf(stderr, "Unable to read signal handler\n"); + return; + } + + ptr = previousAction.__sigaction_u.__sa_handler; + const char *signalName = NULL; + const char *codeName = NULL; + + FIRCLSSignalNameLookup(signal, 0, &signalName, &codeName); + + if (ptr == FIRCLSSignalHandler) { + return; + } + + const char *name = NULL; + if (dladdr(ptr, &info) != 0) { + name = info.dli_sname; + } + + fprintf(stderr, + "[Crashlytics] The signal %s has a non-Crashlytics handler (%s). This will interfere " + "with reporting.\n", + signalName, name); + }); +} + +void FIRCLSSignalSafeRemoveHandlers(bool includingAbort) { + for (int i = 0; i < FIRCLSSignalCount; ++i) { + struct sigaction sa; + + if (!includingAbort && (FIRCLSFatalSignals[i] == SIGABRT)) { + continue; + } + + sa.sa_handler = SIG_DFL; + sigemptyset(&sa.sa_mask); + + if (sigaction(FIRCLSFatalSignals[i], &sa, NULL) != 0) + FIRCLSSDKLog("Unable to set default handler for %d (%s)\n", i, strerror(errno)); + } +} + +bool FIRCLSSignalSafeInstallPreexistingHandlers(FIRCLSSignalReadContext *roContext) { + bool success; + + FIRCLSSignalSafeRemoveHandlers(true); + +#if CLS_USE_SIGALTSTACK + + // re-install the original stack, if needed + if (roContext->originalStack.ss_sp) { + if (sigaltstack(&roContext->originalStack, 0) != 0) { + FIRCLSSDKLog("Unable to setup stack %s\n", strerror(errno)); + + return false; + } + } + +#endif + + // re-install the original handlers, if any + success = true; + for (int i = 0; i < FIRCLSSignalCount; ++i) { + if (roContext->originalActions[i].sa_sigaction == NULL) { + continue; + } + + if (sigaction(FIRCLSFatalSignals[i], &roContext->originalActions[i], 0) != 0) { + FIRCLSSDKLog("Unable to install handler for %d (%s)\n", i, strerror(errno)); + success = false; + } + } + + return success; +} + +void FIRCLSSignalNameLookup(int number, int code, const char **name, const char **codeName) { + if (!name || !codeName) { + return; + } + + *codeName = NULL; + + switch (number) { + case SIGABRT: + *name = "SIGABRT"; + *codeName = "ABORT"; + break; + case SIGBUS: + *name = "SIGBUS"; + break; + case SIGFPE: + *name = "SIGFPE"; + break; + case SIGILL: + *name = "SIGILL"; + break; + case SIGSEGV: + *name = "SIGSEGV"; + break; + case SIGSYS: + *name = "SIGSYS"; + break; + case SIGTRAP: + *name = "SIGTRAP"; + break; + default: + *name = "UNKNOWN"; + break; + } +} + +static void FIRCLSSignalRecordSignal(int savedErrno, siginfo_t *info, void *uapVoid) { + if (!_firclsContext.readonly) { + return; + } + + if (FIRCLSContextMarkAndCheckIfCrashed()) { + FIRCLSSDKLog("Error: aborting signal handler because crash has already occurred"); + exit(1); + return; + } + + FIRCLSFile file; + + if (!FIRCLSFileInitWithPath(&file, _firclsContext.readonly->signal.path, false)) { + FIRCLSSDKLog("Unable to open signal file\n"); + return; + } + + FIRCLSFileWriteSectionStart(&file, "signal"); + + FIRCLSFileWriteHashStart(&file); + + if (FIRCLSIsValidPointer(info)) { + FIRCLSFileWriteHashEntryUint64(&file, "number", info->si_signo); + FIRCLSFileWriteHashEntryUint64(&file, "code", info->si_code); + FIRCLSFileWriteHashEntryUint64(&file, "address", (uint64_t)info->si_addr); + + const char *name = NULL; + const char *codeName = NULL; + + FIRCLSSignalNameLookup(info->si_signo, info->si_code, &name, &codeName); + + FIRCLSFileWriteHashEntryString(&file, "name", name); + FIRCLSFileWriteHashEntryString(&file, "code_name", codeName); + } + + FIRCLSFileWriteHashEntryUint64(&file, "errno", savedErrno); + FIRCLSFileWriteHashEntryUint64(&file, "time", time(NULL)); + + FIRCLSFileWriteHashEnd(&file); + + FIRCLSFileWriteSectionEnd(&file); + + FIRCLSHandler(&file, mach_thread_self(), uapVoid); + + FIRCLSFileClose(&file); +} + +static void FIRCLSSignalHandler(int signal, siginfo_t *info, void *uapVoid) { + int savedErrno; + sigset_t set; + + // save errno, both because it is interesting, and so we can restore it afterwards + savedErrno = errno; + errno = 0; + + FIRCLSSDKLog("Signal: %d\n", signal); + + // it is important to do this before unmasking signals, otherwise we can get + // called in a loop + FIRCLSSignalSafeRemoveHandlers(true); + + sigfillset(&set); + if (sigprocmask(SIG_UNBLOCK, &set, NULL) != 0) { + FIRCLSSDKLog("Unable to unmask signals - we risk infinite recursion here\n"); + } + + // check info and uapVoid, and set them to appropriate values if invalid. This can happen + // if we have been called without the SA_SIGINFO flag set + if (!FIRCLSIsValidPointer(info)) { + info = NULL; + } + + if (!FIRCLSIsValidPointer(uapVoid)) { + uapVoid = NULL; + } + + FIRCLSSignalRecordSignal(savedErrno, info, uapVoid); + + // re-install original handlers + if (_firclsContext.readonly) { + FIRCLSSignalSafeInstallPreexistingHandlers(&_firclsContext.readonly->signal); + } + + // restore errno + errno = savedErrno; +} diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSSignal.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSSignal.h new file mode 100644 index 000000000..3b6b1b4e2 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSSignal.h @@ -0,0 +1,51 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "FIRCLSFeatures.h" +#include "FIRCLSFile.h" + +#include <signal.h> +#include <stdbool.h> + +#define FIRCLSSignalCount (7) + +// per man sigaltstack, MINSIGSTKSZ is the minimum *overhead* needed to support +// a signal stack. The actual stack size must be larger. Let's pick the recommended +// size. +#if CLS_USE_SIGALTSTACK +#define CLS_SIGNAL_HANDLER_STACK_SIZE (SIGSTKSZ * 2) +#else +#define CLS_SIGNAL_HANDLER_STACK_SIZE 0 +#endif + +typedef struct { + const char* path; + struct sigaction originalActions[FIRCLSSignalCount]; + +#if CLS_USE_SIGALTSTACK + stack_t originalStack; +#endif +} FIRCLSSignalReadContext; + +void FIRCLSSignalInitialize(FIRCLSSignalReadContext* roContext); +void FIRCLSSignalCheckHandlers(void); + +void FIRCLSSignalSafeRemoveHandlers(bool includingAbort); +bool FIRCLSSignalSafeInstallPreexistingHandlers(FIRCLSSignalReadContext* roContext); + +void FIRCLSSignalNameLookup(int number, int code, const char** name, const char** codeName); + +void FIRCLSSignalEnumerateHandledSignals(void (^block)(int idx, int signal)); diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent+Internal.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent+Internal.h new file mode 100644 index 000000000..f0de9fed9 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent+Internal.h @@ -0,0 +1,23 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef FIRAEvent_Internal_h +#define FIRAEvent_Internal_h + +#import "FIRAEvent.h" +#import "FIRAValue.h" + +NSString* FIRCLSFIRAEventDictionaryToJSON(NSDictionary* eventAsDictionary); + +#endif /* FIRAEvent_Internal_h */ diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent+Internal.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent+Internal.m new file mode 100644 index 000000000..4591e29f1 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent+Internal.m @@ -0,0 +1,42 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRAEvent+Internal.h" + +#import "FIRCLSUtility.h" + +NSString* FIRCLSFIRAEventDictionaryToJSON(NSDictionary* eventAsDictionary) { + NSError* error = nil; + + if (eventAsDictionary == nil) { + return nil; + } + + if (![NSJSONSerialization isValidJSONObject:eventAsDictionary]) { + FIRCLSSDKLog("Firebase Analytics event is not valid JSON"); + return nil; + } + + NSData* jsonData = [NSJSONSerialization dataWithJSONObject:eventAsDictionary + options:0 + error:&error]; + + if (error == nil) { + NSString* json = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + return json; + } else { + FIRCLSSDKLog("Unable to convert Firebase Analytics event to json"); + return nil; + } +} diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent.h new file mode 100644 index 000000000..9fcbd6602 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent.h @@ -0,0 +1,79 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +@class FIRAPBEvent; + +/// An application event. +@interface FIRAEvent : NSObject <NSCopying> + +/// Origin of this event (eg "app" or "auto"). +@property(nonatomic, readonly) NSString *origin; + +/// Name of this event. +@property(nonatomic, readonly) NSString *name; + +/// Timestamp of when this event was fired. +@property(nonatomic, readonly) NSTimeInterval timestamp; + +/// Timestamp of the previous time an event with this name was fired, if any. +@property(nonatomic, readonly) NSTimeInterval previousTimestamp; + +/// The event's parameters as {NSString : NSString} or {NSString : NSNumber}. +@property(nonatomic, readonly) NSDictionary *parameters; + +/// Indicates whether the event has the conversion parameter. Setting to YES adds the conversion +/// parameter if not already present. Setting to NO removes the conversion parameter and adds an +/// error. +@property(nonatomic, getter=isConversion) BOOL conversion; + +/// Indicates whether the event has the real-time parameter. Setting to YES adds the real-time +/// parameter if not already present. Setting to NO removes the real-time parameter. +@property(nonatomic, getter=isRealtime) BOOL realtime; + +/// Indicates whether the event has debug parameter. Setting to YES adds the debug parameter if +/// not already present. Setting to NO removes the debug parameter. +@property(nonatomic, getter=isDebug) BOOL debug; + +/// The populated FIRAPBEvent for proto. +@property(nonatomic, readonly) FIRAPBEvent *protoEvent; + +/// Creates an event with the given parameters. Parameters will be copied and normalized. Returns +/// nil if the name does not meet length requirements. +/// If |parameters| contains the "_o" parameter, its value will be overwritten with the value of +/// |origin|. +- (instancetype)initWithOrigin:(NSString *)origin + isPublic:(BOOL)isPublic + name:(NSString *)name + timestamp:(NSTimeInterval)timestamp + previousTimestamp:(NSTimeInterval)previousTimestamp + parameters:(NSDictionary *)parameters NS_DESIGNATED_INITIALIZER; + +- (instancetype)init NS_UNAVAILABLE; + +/// Returns a new event object with the given previousTimestamp. +- (instancetype)copyWithPreviousTimestamp:(NSTimeInterval)previousTimestamp; + +/// Returns a new event object with the new parameters. +- (instancetype)copyWithParameters:(NSDictionary *)parameters; + +/// Returns YES if all parameters in screenParameters were added to the event object. Returns NO if +/// screenParameters is nil/empty or the event already contains any of the screen parameter keys. +/// Performs internal validation on the screen parameter values and converts them to FIRAValue +/// objects if they aren't already. screenParameters should be a dictionary of +/// { NSString : NSString | NSNumber } or { NSString : FIRAValue }. +- (BOOL)addScreenParameters:(NSDictionary *)screenParameters; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAValue.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAValue.h new file mode 100644 index 000000000..7d10ec308 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAValue.h @@ -0,0 +1,69 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +typedef NS_ENUM(NSInteger, FIRAValueType) { + kFIRAValueTypeDouble = 0, + kFIRAValueTypeInteger, + kFIRAValueTypeString, +}; + +@interface FIRAValue : NSObject <NSCopying> + +/// The type of the value. +@property(nonatomic, readonly) FIRAValueType valueType; + +#pragma mark - Double type. + +/// Indicates whether the FIRAValue instance is a floating point. +@property(nonatomic, readonly) BOOL isDouble; + +/// Float value. Check valueType to see if this attribute has float value. +@property(nonatomic, readonly) double doubleValue; + +#pragma mark - Integer type. + +/// Indicates whether the FIRAValue instance is an integer. +@property(nonatomic, readonly) BOOL isInt64; + +/// Int64 value. Check valueType to see if this attribute has int64 value. +@property(nonatomic, readonly) int64_t int64Value; + +#pragma mark - String type. + +/// Indicates whether the FIRAValue instance is a string. +@property(nonatomic, readonly) BOOL isString; + +/// String value. Check valueType to see if this attribute has string value. +@property(nonatomic, readonly) NSString *stringValue; + +#pragma mark - Initializers. + +/// Creates a @c FIRAValue if |object| is of type NSString or NSNumber. Returns |object| if it's +/// already a FIRAValue. Returns nil otherwise. ++ (instancetype)valueFromObject:(id)object; + +/// Creates a @c FIRAValue with double value. +- (instancetype)initWithDouble:(double)value; + +/// Creates a @c FIRAValue with int64 value. +- (instancetype)initWithInt64:(int64_t)value; + +/// Creates a @c FIRAValue with string value. +- (instancetype)initWithString:(NSString *)stringValue; + +- (instancetype)init NS_UNAVAILABLE; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSAllocate.c b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSAllocate.c new file mode 100644 index 000000000..febafd2ab --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSAllocate.c @@ -0,0 +1,238 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include <stdatomic.h> + +#include "FIRCLSAllocate.h" +#include "FIRCLSHost.h" +#include "FIRCLSUtility.h" + +#include <errno.h> +#include <libkern/OSAtomic.h> +#include <mach/vm_map.h> +#include <mach/vm_param.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/mman.h> + +void* FIRCLSAllocatorSafeAllocateFromRegion(FIRCLSAllocationRegion* region, size_t size); + +FIRCLSAllocatorRef FIRCLSAllocatorCreate(size_t writableSpace, size_t readableSpace) { + FIRCLSAllocatorRef allocator; + FIRCLSAllocationRegion writableRegion; + FIRCLSAllocationRegion readableRegion; + size_t allocationSize; + vm_size_t pageSize; + void* buffer; + + // | GUARD | WRITABLE_REGION | GUARD | READABLE_REGION | GUARD | + + pageSize = FIRCLSHostGetPageSize(); + + readableSpace += sizeof(FIRCLSAllocator); // add the space for our allocator itself + + // we can only protect at the page level, so we need all of our regions to be + // exact multples of pages. But, we don't need anything in the special-case of zero. + + writableRegion.size = 0; + if (writableSpace > 0) { + writableRegion.size = ((writableSpace / pageSize) + 1) * pageSize; + } + + readableRegion.size = 0; + if (readableSpace > 0) { + readableRegion.size = ((readableSpace / pageSize) + 1) * pageSize; + } + + // Make one big, continous allocation, adding additional pages for our guards. Note + // that we cannot use malloc (or valloc) in this case, because we need to assert full + // ownership over these allocations. mmap is a much better choice. We also mark these + // pages as MAP_NOCACHE. + allocationSize = writableRegion.size + readableRegion.size + pageSize * 3; + buffer = + mmap(0, allocationSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_NOCACHE, -1, 0); + if (buffer == MAP_FAILED) { + FIRCLSSDKLogError("Mapping failed %s\n", strerror(errno)); + return NULL; + } + + // move our cursors into position + writableRegion.cursor = (void*)((uintptr_t)buffer + pageSize); + readableRegion.cursor = (void*)((uintptr_t)buffer + pageSize + writableRegion.size + pageSize); + writableRegion.start = writableRegion.cursor; + readableRegion.start = readableRegion.cursor; + + FIRCLSSDKLogInfo("Mapping: %p %p %p, total: %zu K\n", buffer, writableRegion.start, + readableRegion.start, allocationSize / 1024); + + // protect first guard page + if (mprotect(buffer, pageSize, PROT_NONE) != 0) { + FIRCLSSDKLogError("First guard protection failed %s\n", strerror(errno)); + return NULL; + } + + // middle guard + if (mprotect((void*)((uintptr_t)buffer + pageSize + writableRegion.size), pageSize, PROT_NONE) != + 0) { + FIRCLSSDKLogError("Middle guard protection failed %s\n", strerror(errno)); + return NULL; + } + + // end guard + if (mprotect((void*)((uintptr_t)buffer + pageSize + writableRegion.size + pageSize + + readableRegion.size), + pageSize, PROT_NONE) != 0) { + FIRCLSSDKLogError("Last guard protection failed %s\n", strerror(errno)); + return NULL; + } + + // now, perform our first "allocation", which is to place our allocator into the read-only region + allocator = FIRCLSAllocatorSafeAllocateFromRegion(&readableRegion, sizeof(FIRCLSAllocator)); + + // set up its data structure + allocator->buffer = buffer; + allocator->protectionEnabled = false; + allocator->readableRegion = readableRegion; + allocator->writeableRegion = writableRegion; + + FIRCLSSDKLogDebug("Allocator successfully created %p", allocator); + + return allocator; +} + +void FIRCLSAllocatorDestroy(FIRCLSAllocatorRef allocator) { + if (allocator) { + } +} + +bool FIRCLSAllocatorProtect(FIRCLSAllocatorRef allocator) { + void* address; + + if (!FIRCLSIsValidPointer(allocator)) { + FIRCLSSDKLogError("Invalid allocator"); + return false; + } + + if (allocator->protectionEnabled) { + FIRCLSSDKLogWarn("Write protection already enabled"); + return true; + } + + // This has to be done first + allocator->protectionEnabled = true; + + vm_size_t pageSize = FIRCLSHostGetPageSize(); + + // readable region + address = + (void*)((uintptr_t)allocator->buffer + pageSize + allocator->writeableRegion.size + pageSize); + + return mprotect(address, allocator->readableRegion.size, PROT_READ) == 0; +} + +bool FIRCLSAllocatorUnprotect(FIRCLSAllocatorRef allocator) { + size_t bufferSize; + + if (!allocator) { + return false; + } + + vm_size_t pageSize = FIRCLSHostGetPageSize(); + + bufferSize = (uintptr_t)allocator->buffer + pageSize + allocator->writeableRegion.size + + pageSize + allocator->readableRegion.size + pageSize; + + allocator->protectionEnabled = + !(mprotect(allocator->buffer, bufferSize, PROT_READ | PROT_WRITE) == 0); + + return allocator->protectionEnabled; +} + +void* FIRCLSAllocatorSafeAllocateFromRegion(FIRCLSAllocationRegion* region, size_t size) { + void* newCursor; + void* originalCursor; + + // Here's the idea + // - read the current cursor + // - compute what our new cursor should be + // - attempt a swap + // if the swap fails, some other thread has modified stuff, and we have to start again + // if the swap works, everything has been updated correctly and we are done + do { + originalCursor = region->cursor; + + // this shouldn't happen unless we make a mistake with our size pre-computations + if ((uintptr_t)originalCursor - (uintptr_t)region->start + size > region->size) { + FIRCLSSDKLog("Unable to allocate sufficient memory, falling back to malloc\n"); + void* ptr = malloc(size); + if (!ptr) { + FIRCLSSDKLog("Unable to malloc in FIRCLSAllocatorSafeAllocateFromRegion\n"); + return NULL; + } + return ptr; + } + + newCursor = (void*)((uintptr_t)originalCursor + size); + } while (!atomic_compare_exchange_strong(®ion->cursor, &originalCursor, newCursor)); + + return originalCursor; +} + +void* FIRCLSAllocatorSafeAllocate(FIRCLSAllocatorRef allocator, + size_t size, + FIRCLSAllocationType type) { + FIRCLSAllocationRegion* region; + + if (!allocator) { + // fall back to malloc in this case + FIRCLSSDKLog("Allocator invalid, falling back to malloc\n"); + void* ptr = malloc(size); + if (!ptr) { + FIRCLSSDKLog("Unable to malloc in FIRCLSAllocatorSafeAllocate\n"); + return NULL; + } + return ptr; + } + + if (allocator->protectionEnabled) { + FIRCLSSDKLog("Allocator already protected, falling back to malloc\n"); + void* ptr = malloc(size); + if (!ptr) { + FIRCLSSDKLog("Unable to malloc in FIRCLSAllocatorSafeAllocate\n"); + return NULL; + } + return ptr; + } + + switch (type) { + case CLS_READONLY: + region = &allocator->readableRegion; + break; + case CLS_READWRITE: + region = &allocator->writeableRegion; + break; + default: + return NULL; + } + + return FIRCLSAllocatorSafeAllocateFromRegion(region, size); +} + +void FIRCLSAllocatorFree(FIRCLSAllocatorRef allocator, void* ptr) { + if (!allocator) { + free(ptr); + } + + // how do we do deallocations? +} diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSAllocate.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSAllocate.h new file mode 100644 index 000000000..02b526a87 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSAllocate.h @@ -0,0 +1,48 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSFeatures.h" + +#pragma once + +#include <stdbool.h> +#include <sys/types.h> + +typedef enum { CLS_READONLY = 0, CLS_READWRITE = 1 } FIRCLSAllocationType; + +typedef struct { + size_t size; + void* start; + _Atomic(void*) volatile cursor; +} FIRCLSAllocationRegion; + +typedef struct { + void* buffer; + bool protectionEnabled; + FIRCLSAllocationRegion writeableRegion; + FIRCLSAllocationRegion readableRegion; +} FIRCLSAllocator; +typedef FIRCLSAllocator* FIRCLSAllocatorRef; + +FIRCLSAllocatorRef FIRCLSAllocatorCreate(size_t writableSpace, size_t readableSpace); +void FIRCLSAllocatorDestroy(FIRCLSAllocatorRef allocator); + +bool FIRCLSAllocatorProtect(FIRCLSAllocatorRef allocator); +bool FIRCLSAllocatorUnprotect(FIRCLSAllocatorRef allocator); + +void* FIRCLSAllocatorSafeAllocate(FIRCLSAllocatorRef allocator, + size_t size, + FIRCLSAllocationType type); +const char* FIRCLSAllocatorSafeStrdup(FIRCLSAllocatorRef allocator, const char* string); +void FIRCLSAllocatorFree(FIRCLSAllocatorRef allocator, void* ptr); diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h new file mode 100644 index 000000000..f309ae07a --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h @@ -0,0 +1,81 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "TargetConditionals.h" + +// macro trickiness +#define STR_HELPER(x) #x +#define STR(x) STR_HELPER(x) +#define CONCAT_EXPANDED(a, b) a##b +#define CONCAT(a, b) CONCAT_EXPANDED(a, b) + +// These macros generate a function to force a symbol for the containing .o, to work around an issue +// where strip will not strip debug information without a symbol to strip. +#define DUMMY_FUNCTION_NAME(x) CONCAT(fircls_strip_this_, x) +#define INJECT_STRIP_SYMBOL(x) \ + void DUMMY_FUNCTION_NAME(x)(void) { \ + } + +// These make some target os types available to previous versions of xcode that do not yet have them +// in their SDKs +#ifndef TARGET_OS_IOS +#define TARGET_OS_IOS TARGET_OS_IPHONE +#endif + +#ifndef TARGET_OS_WATCH +#define TARGET_OS_WATCH 0 +#endif + +#ifndef TARGET_OS_TV +#define TARGET_OS_TV 0 +#endif + +// These help compile based on availability of technologies/frameworks. +#define CLS_TARGET_OS_OSX (TARGET_OS_MAC && !TARGET_OS_IPHONE) +#define CLS_TARGET_OS_HAS_UIKIT (TARGET_OS_IOS || TARGET_OS_TV) + +#define CLS_SDK_DISPLAY_VERSION STR(DISPLAY_VERSION) + +#define CLS_SDK_GENERATOR_NAME (STR(CLS_SDK_NAME) "/" CLS_SDK_DISPLAY_VERSION) + +// arch definitions +#if defined(__arm__) || defined(__arm64__) || defined(__arm64e__) +#include <arm/arch.h> +#endif + +#if defined(__arm__) +#define CLS_CPU_ARM 1 +#endif +#if defined(__arm64__) || defined(__arm64e__) +#define CLS_CPU_ARM64 1 +#endif +#if defined(__ARM_ARCH_7S__) +#define CLS_CPU_ARMV7S 1 +#endif +#if defined(_ARM_ARCH_7) +#define CLS_CPU_ARMV7 1 +#endif +#if defined(_ARM_ARCH_6) +#define CLS_CPU_ARMV6 1 +#endif +#if defined(__i386__) +#define CLS_CPU_I386 1 +#endif +#if defined(__x86_64__) +#define CLS_CPU_X86_64 1 +#endif +#define CLS_CPU_X86 (CLS_CPU_I386 || CLS_CPU_X86_64) +#define CLS_CPU_64BIT (CLS_CPU_X86_64 || CLS_CPU_ARM64) diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFCRAnalytics.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFCRAnalytics.h new file mode 100644 index 000000000..098833f61 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFCRAnalytics.h @@ -0,0 +1,32 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +@class FIRCLSSettings; +@protocol FIRAnalyticsInterop; +@protocol FIRAnalyticsInteropListener; + +@interface FIRCLSFCRAnalytics : NSObject + +/** Logs a Crashlytics crash session in Firebase Analytics. + * @param crashTimeStamp The time stamp of the crash to be logged. + */ ++ (void)logCrashWithTimeStamp:(NSTimeInterval)crashTimeStamp + toAnalytics:(id<FIRAnalyticsInterop>)analytics; + ++ (void)registerEventListener:(id<FIRAnalyticsInteropListener>)eventListener + toAnalytics:(id<FIRAnalyticsInterop>)analytics; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFCRAnalytics.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFCRAnalytics.m new file mode 100644 index 000000000..56dd33b98 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFCRAnalytics.m @@ -0,0 +1,78 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSFCRAnalytics.h" + +#import "FIRCLSInternalLogging.h" +#import "FIRCLSSettings.h" + +#import "Interop/Analytics/Public/FIRAnalyticsInterop.h" + +// Origin for events and user properties generated by Crashlytics. +static NSString *const kFIREventOriginCrash = @"clx"; + +// App exception event name. +static NSString *const kFIREventAppException = @"_ae"; + +// Timestamp key for the event payload. +static NSString *const kFIRParameterTimestamp = @"timestamp"; + +// Fatal key for the event payload. +static NSString *const kFIRParameterFatal = @"fatal"; + +FOUNDATION_STATIC_INLINE NSNumber *timeIntervalInMillis(NSTimeInterval timeInterval) { + return @(llrint(timeInterval * 1000.0)); +} + +@implementation FIRCLSFCRAnalytics + ++ (void)logCrashWithTimeStamp:(NSTimeInterval)crashTimeStamp + toAnalytics:(id<FIRAnalyticsInterop>)analytics { + if (analytics == nil) { + return; + } + + FIRCLSDeveloperLog(@"Crashlytics:Crash:Reports:Event", "Sending event."); + NSDictionary *params = [self buildLogParamsFromCrash:crashTimeStamp]; + [analytics logEventWithOrigin:kFIREventOriginCrash name:kFIREventAppException parameters:params]; +} + ++ (void)registerEventListener:(id<FIRAnalyticsInteropListener>)eventListener + toAnalytics:(id<FIRAnalyticsInterop>)analytics { + if (analytics == nil) { + return; + } + + [analytics registerAnalyticsListener:eventListener withOrigin:kFIREventOriginCrash]; + + FIRCLSDeveloperLog(@"Crashlytics:Crash:Reports:Event", + "Registered Firebase Analytics event listener"); +} + +/** + * Builds a dictionary of params to be sent to Analytics using the crash object. + * + * @param crashTimeStamp The time stamp of the crash to be logged. + * + * @return An NSDictionary containing the time the crash occured and the fatal + * flag to be fed into Firebase Analytics. + */ ++ (NSDictionary *)buildLogParamsFromCrash:(NSTimeInterval)crashTimeStamp { + return @{ + kFIRParameterTimestamp : timeIntervalInMillis(crashTimeStamp), + kFIRParameterFatal : @(INT64_C(1)) + }; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h new file mode 100644 index 000000000..4810a5d9b --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h @@ -0,0 +1,31 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "FIRCLSDefines.h" + +#define CLS_MEMORY_PROTECTION_ENABLED 1 +#define CLS_COMPACT_UNWINDED_ENABLED 1 +#define CLS_DWARF_UNWINDING_ENABLED 1 + +#define CLS_USE_SIGALTSTACK (!TARGET_OS_WATCH && !TARGET_OS_TV) +#define CLS_CAN_SUSPEND_THREADS !TARGET_OS_WATCH +#define CLS_MACH_EXCEPTION_SUPPORTED (!TARGET_OS_WATCH && !TARGET_OS_TV) + +#define CLS_COMPACT_UNWINDING_SUPPORTED \ + ((CLS_CPU_I386 || CLS_CPU_X86_64 || CLS_CPU_ARM64) && CLS_COMPACT_UNWINDED_ENABLED) + +#define CLS_DWARF_UNWINDING_SUPPORTED \ + (CLS_COMPACT_UNWINDING_SUPPORTED && CLS_DWARF_UNWINDING_ENABLED) diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFile.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFile.h new file mode 100644 index 000000000..1714ac12e --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFile.h @@ -0,0 +1,109 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include <stdbool.h> +#include <stdint.h> +#include <sys/cdefs.h> + +// Required for 1P builds +#include <stddef.h> +#include <sys/types.h> +#include <unistd.h> + +#if defined(__OBJC__) +#import <Foundation/Foundation.h> +#endif + +__BEGIN_DECLS + +typedef struct { + int fd; + int collectionDepth; + bool needComma; + + bool bufferWrites; + char* writeBuffer; + size_t writeBufferLength; + + off_t writtenLength; +} FIRCLSFile; +typedef FIRCLSFile* FIRCLSFileRef; + +#define CLS_FILE_MAX_STRING_LENGTH (10240) +#define CLS_FILE_HEX_BUFFER \ + (32) // must be at least 2, and should be even (to account for 2 chars per hex value) +#define CLS_FILE_MAX_WRITE_ATTEMPTS (50) + +extern const size_t FIRCLSWriteBufferLength; + +// make sure to stop work if either FIRCLSFileInit... method returns false, because the FIRCLSFile +// struct will contain garbage data! +bool FIRCLSFileInitWithPath(FIRCLSFile* file, const char* path, bool bufferWrites); +bool FIRCLSFileInitWithPathMode(FIRCLSFile* file, + const char* path, + bool appendMode, + bool bufferWrites); + +void FIRCLSFileFlushWriteBuffer(FIRCLSFile* file); +bool FIRCLSFileClose(FIRCLSFile* file); +bool FIRCLSFileCloseWithOffset(FIRCLSFile* file, off_t* finalSize); +bool FIRCLSFileIsOpen(FIRCLSFile* file); + +bool FIRCLSFileLoopWithWriteBlock(const void* buffer, + size_t length, + ssize_t (^writeBlock)(const void* partialBuffer, + size_t partialLength)); +bool FIRCLSFileWriteWithRetries(int fd, const void* buffer, size_t length); + +// writing +void FIRCLSFileWriteSectionStart(FIRCLSFile* file, const char* name); +void FIRCLSFileWriteSectionEnd(FIRCLSFile* file); + +void FIRCLSFileWriteHashStart(FIRCLSFile* file); +void FIRCLSFileWriteHashEnd(FIRCLSFile* file); +void FIRCLSFileWriteHashKey(FIRCLSFile* file, const char* key); +void FIRCLSFileWriteHashEntryUint64(FIRCLSFile* file, const char* key, uint64_t value); +void FIRCLSFileWriteHashEntryInt64(FIRCLSFile* file, const char* key, int64_t value); +void FIRCLSFileWriteHashEntryString(FIRCLSFile* file, const char* key, const char* value); +#if defined(__OBJC__) +void FIRCLSFileWriteHashEntryNSString(FIRCLSFile* file, const char* key, NSString* string); +void FIRCLSFileWriteHashEntryNSStringUnlessNilOrEmpty(FIRCLSFile* file, + const char* key, + NSString* string); +#endif +void FIRCLSFileWriteHashEntryHexEncodedString(FIRCLSFile* file, const char* key, const char* value); +void FIRCLSFileWriteHashEntryBoolean(FIRCLSFile* file, const char* key, bool value); + +void FIRCLSFileWriteArrayStart(FIRCLSFile* file); +void FIRCLSFileWriteArrayEnd(FIRCLSFile* file); +void FIRCLSFileWriteArrayEntryUint64(FIRCLSFile* file, uint64_t value); +void FIRCLSFileWriteArrayEntryString(FIRCLSFile* file, const char* value); +void FIRCLSFileWriteArrayEntryHexEncodedString(FIRCLSFile* file, const char* value); + +void FIRCLSFileFDWriteUInt64(int fd, uint64_t number, bool hex); +void FIRCLSFileFDWriteInt64(int fd, int64_t number); +void FIRCLSFileWriteUInt64(FIRCLSFile* file, uint64_t number, bool hex); +void FIRCLSFileWriteInt64(FIRCLSFile* file, int64_t number); + +#if defined(__OBJC__) && TARGET_OS_MAC +NSArray* FIRCLSFileReadSections(const char* path, + bool deleteOnFailure, + NSObject* (^transformer)(id obj)); +NSString* FIRCLSFileHexEncodeString(const char* string); +NSString* FIRCLSFileHexDecodeString(const char* string); +#endif + +__END_DECLS diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFile.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFile.m new file mode 100644 index 000000000..10b96d339 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFile.m @@ -0,0 +1,702 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSFile.h" + +#include "FIRCLSByteUtility.h" +#include "FIRCLSUtility.h" + +#if TARGET_OS_MAC +#include <Foundation/Foundation.h> +#endif + +#include <sys/stat.h> + +#include <stdio.h> +#include <string.h> + +#include <unistd.h> + +// uint64_t should only have max 19 chars in base 10, and less in base 16 +static const size_t FIRCLSUInt64StringBufferLength = 21; +static const size_t FIRCLSStringBufferLength = 16; +const size_t FIRCLSWriteBufferLength = 1000; + +static bool FIRCLSFileInit(FIRCLSFile* file, int fdm, bool appendMode, bool bufferWrites); + +static void FIRCLSFileWriteToFileDescriptorOrBuffer(FIRCLSFile* file, + const char* string, + size_t length); +static void FIRCLSFileWriteToBuffer(FIRCLSFile* file, const char* string, size_t length); +static void FIRCLSFileWriteToFileDescriptor(FIRCLSFile* file, const char* string, size_t length); + +short FIRCLSFilePrepareUInt64(char* buffer, uint64_t number, bool hex); + +static void FIRCLSFileWriteString(FIRCLSFile* file, const char* string); +static void FIRCLSFileWriteHexEncodedString(FIRCLSFile* file, const char* string); +static void FIRCLSFileWriteBool(FIRCLSFile* file, bool value); + +static void FIRCLSFileWriteCollectionStart(FIRCLSFile* file, const char openingChar); +static void FIRCLSFileWriteCollectionEnd(FIRCLSFile* file, const char closingChar); +static void FIRCLSFileWriteColletionEntryProlog(FIRCLSFile* file); +static void FIRCLSFileWriteColletionEntryEpilog(FIRCLSFile* file); + +#define CLS_FILE_DEBUG_LOGGING 0 + +#pragma mark - File Structure +static bool FIRCLSFileInit(FIRCLSFile* file, int fd, bool appendMode, bool bufferWrites) { + if (!file) { + FIRCLSSDKLog("Error: file is null\n"); + return false; + } + + if (fd < 0) { + FIRCLSSDKLog("Error: file descriptor invalid\n"); + return false; + } + + memset(file, 0, sizeof(FIRCLSFile)); + + file->fd = fd; + + file->bufferWrites = bufferWrites; + if (bufferWrites) { + file->writeBuffer = malloc(FIRCLSWriteBufferLength * sizeof(char)); + if (!file->writeBuffer) { + FIRCLSErrorLog(@"Unable to malloc in FIRCLSFileInit"); + return false; + } + + file->writeBufferLength = 0; + } + + file->writtenLength = 0; + if (appendMode) { + struct stat fileStats; + fstat(fd, &fileStats); + off_t currentFileSize = fileStats.st_size; + if (currentFileSize > 0) { + file->writtenLength += currentFileSize; + } + } + + return true; +} + +bool FIRCLSFileInitWithPath(FIRCLSFile* file, const char* path, bool bufferWrites) { + return FIRCLSFileInitWithPathMode(file, path, true, bufferWrites); +} + +bool FIRCLSFileInitWithPathMode(FIRCLSFile* file, + const char* path, + bool appendMode, + bool bufferWrites) { + if (!file) { + FIRCLSSDKLog("Error: file is null\n"); + return false; + } + + int mask = O_WRONLY | O_CREAT; + + if (appendMode) { + mask |= O_APPEND; + } else { + mask |= O_TRUNC; + } + + // make sure to call FIRCLSFileInit no matter what + int fd = -1; + if (path) { +#if TARGET_OS_IPHONE + /* + * data-protected non-portable open(2) : + * int open_dprotected_np(user_addr_t path, int flags, int class, int dpflags, int mode) + */ + fd = open_dprotected_np(path, mask, 4, 0, 0644); +#else + fd = open(path, mask, 0644); +#endif + + if (fd < 0) { + FIRCLSSDKLog("Error: Unable to open file %s\n", strerror(errno)); + } + } + + return FIRCLSFileInit(file, fd, appendMode, bufferWrites); +} + +bool FIRCLSFileClose(FIRCLSFile* file) { + return FIRCLSFileCloseWithOffset(file, NULL); +} + +bool FIRCLSFileCloseWithOffset(FIRCLSFile* file, off_t* finalSize) { + if (!FIRCLSIsValidPointer(file)) { + return false; + } + + if (file->bufferWrites && FIRCLSIsValidPointer(file->writeBuffer)) { + if (file->writeBufferLength > 0) { + FIRCLSFileFlushWriteBuffer(file); + } + free(file->writeBuffer); + } + + if (FIRCLSIsValidPointer(finalSize)) { + *finalSize = file->writtenLength; + } + + if (close(file->fd) != 0) { + FIRCLSSDKLog("Error: Unable to close file %s\n", strerror(errno)); + return false; + } + + memset(file, 0, sizeof(FIRCLSFile)); + file->fd = -1; + + return true; +} + +bool FIRCLSFileIsOpen(FIRCLSFile* file) { + if (!FIRCLSIsValidPointer(file)) { + return false; + } + + return file->fd > -1; +} + +#pragma mark - Core Writing API +void FIRCLSFileFlushWriteBuffer(FIRCLSFile* file) { + if (!FIRCLSIsValidPointer(file)) { + return; + } + + if (!file->bufferWrites) { + return; + } + + FIRCLSFileWriteToFileDescriptor(file, file->writeBuffer, file->writeBufferLength); + file->writeBufferLength = 0; +} + +static void FIRCLSFileWriteToFileDescriptorOrBuffer(FIRCLSFile* file, + const char* string, + size_t length) { + if (file->bufferWrites) { + if (file->writeBufferLength + length > FIRCLSWriteBufferLength - 1) { + // fill remaining space in buffer + size_t remainingSpace = FIRCLSWriteBufferLength - file->writeBufferLength - 1; + FIRCLSFileWriteToBuffer(file, string, remainingSpace); + FIRCLSFileFlushWriteBuffer(file); + + // write remainder of string to newly-emptied buffer + size_t remainingLength = length - remainingSpace; + FIRCLSFileWriteToFileDescriptorOrBuffer(file, string + remainingSpace, remainingLength); + } else { + FIRCLSFileWriteToBuffer(file, string, length); + } + } else { + FIRCLSFileWriteToFileDescriptor(file, string, length); + } +} + +static void FIRCLSFileWriteToFileDescriptor(FIRCLSFile* file, const char* string, size_t length) { + if (!FIRCLSFileWriteWithRetries(file->fd, string, length)) { + return; + } + + file->writtenLength += length; +} + +// Beware calling this method directly: it will truncate the input string if it's longer +// than the remaining space in the buffer. It's safer to call through +// FIRCLSFileWriteToFileDescriptorOrBuffer. +static void FIRCLSFileWriteToBuffer(FIRCLSFile* file, const char* string, size_t length) { + size_t writeLength = length; + if (file->writeBufferLength + writeLength > FIRCLSWriteBufferLength - 1) { + writeLength = FIRCLSWriteBufferLength - file->writeBufferLength - 1; + } + strncpy(file->writeBuffer + file->writeBufferLength, string, writeLength); + file->writeBufferLength += writeLength; + file->writeBuffer[file->writeBufferLength] = '\0'; +} + +bool FIRCLSFileLoopWithWriteBlock(const void* buffer, + size_t length, + ssize_t (^writeBlock)(const void* buf, size_t len)) { + for (size_t count = 0; length > 0 && count < CLS_FILE_MAX_WRITE_ATTEMPTS; ++count) { + // try to write all that is left + ssize_t ret = writeBlock(buffer, length); + if (ret >= 0 && ret == length) { + return true; + } + + // Write was unsuccessful (out of space, etc) + if (ret < 0) { + return false; + } + + // We wrote more bytes than we expected, abort + if (ret > length) { + return false; + } + + // wrote a portion of the data, adjust and keep trying + if (ret > 0) { + length -= ret; + buffer += ret; + continue; + } + + // return value is <= 0, which is an error + break; + } + + return false; +} + +bool FIRCLSFileWriteWithRetries(int fd, const void* buffer, size_t length) { + return FIRCLSFileLoopWithWriteBlock(buffer, length, + ^ssize_t(const void* partialBuffer, size_t partialLength) { + return write(fd, partialBuffer, partialLength); + }); +} + +#pragma mark - Strings + +static void FIRCLSFileWriteUnbufferedStringWithSuffix(FIRCLSFile* file, + const char* string, + size_t length, + char suffix) { + char suffixBuffer[2]; + + // collaspe the quote + suffix into one single write call, for a small performance win + suffixBuffer[0] = '"'; + suffixBuffer[1] = suffix; + + FIRCLSFileWriteToFileDescriptorOrBuffer(file, "\"", 1); + FIRCLSFileWriteToFileDescriptorOrBuffer(file, string, length); + FIRCLSFileWriteToFileDescriptorOrBuffer(file, suffixBuffer, suffix == 0 ? 1 : 2); +} + +static void FIRCLSFileWriteStringWithSuffix(FIRCLSFile* file, + const char* string, + size_t length, + char suffix) { + // 2 for quotes, 1 for suffix (if present) and 1 more for null character + const size_t maxStringSize = FIRCLSStringBufferLength - (suffix == 0 ? 3 : 4); + + if (length >= maxStringSize) { + FIRCLSFileWriteUnbufferedStringWithSuffix(file, string, length, suffix); + return; + } + + // we are trying to achieve this in one write call + // <"><string contents><"><suffix> + + char buffer[FIRCLSStringBufferLength]; + + buffer[0] = '"'; + + strncpy(buffer + 1, string, length); + + buffer[length + 1] = '"'; + length += 2; + + if (suffix) { + buffer[length] = suffix; + length += 1; + } + + // Always add the terminator. strncpy above would copy the terminator, if we supplied length + 1, + // but since we do this suffix adjustment here, it's easier to just fix it up in both cases. + buffer[length + 1] = 0; + + FIRCLSFileWriteToFileDescriptorOrBuffer(file, buffer, length); +} + +void FIRCLSFileWriteString(FIRCLSFile* file, const char* string) { + if (!string) { + FIRCLSFileWriteToFileDescriptorOrBuffer(file, "null", 4); + return; + } + + FIRCLSFileWriteStringWithSuffix(file, string, strlen(string), 0); +} + +void FIRCLSFileWriteHexEncodedString(FIRCLSFile* file, const char* string) { + if (!file) { + return; + } + + if (!string) { + FIRCLSFileWriteToFileDescriptorOrBuffer(file, "null", 4); + return; + } + + char buffer[CLS_FILE_HEX_BUFFER]; + + memset(buffer, 0, sizeof(buffer)); + + size_t length = strlen(string); + + FIRCLSFileWriteToFileDescriptorOrBuffer(file, "\"", 1); + + int bufferIndex = 0; + for (int i = 0; i < length; ++i) { + FIRCLSHexFromByte(string[i], &buffer[bufferIndex]); + + bufferIndex += 2; // 1 char => 2 hex values at a time + + // we can continue only if we have enough space for two more hex + // characters *and* a terminator. So, we need three total chars + // of space + if (bufferIndex >= CLS_FILE_HEX_BUFFER) { + FIRCLSFileWriteToFileDescriptorOrBuffer(file, buffer, CLS_FILE_HEX_BUFFER); + bufferIndex = 0; + } + } + + // Copy the remainder, which could even be the entire string, if it + // fit into the buffer completely. Be careful with bounds checking here. + // The string needs to be non-empty, and we have to have copied at least + // one pair of hex characters in. + if (bufferIndex > 0 && length > 0) { + FIRCLSFileWriteToFileDescriptorOrBuffer(file, buffer, bufferIndex); + } + + FIRCLSFileWriteToFileDescriptorOrBuffer(file, "\"", 1); +} + +#pragma mark - Integers +void FIRCLSFileWriteUInt64(FIRCLSFile* file, uint64_t number, bool hex) { + char buffer[FIRCLSUInt64StringBufferLength]; + short i = FIRCLSFilePrepareUInt64(buffer, number, hex); + char* beginning = &buffer[i]; // Write from a pointer to the begining of the string. + FIRCLSFileWriteToFileDescriptorOrBuffer(file, beginning, strlen(beginning)); +} + +void FIRCLSFileFDWriteUInt64(int fd, uint64_t number, bool hex) { + char buffer[FIRCLSUInt64StringBufferLength]; + short i = FIRCLSFilePrepareUInt64(buffer, number, hex); + char* beginning = &buffer[i]; // Write from a pointer to the begining of the string. + FIRCLSFileWriteWithRetries(fd, beginning, strlen(beginning)); +} + +void FIRCLSFileWriteInt64(FIRCLSFile* file, int64_t number) { + if (number < 0) { + FIRCLSFileWriteToFileDescriptorOrBuffer(file, "-", 1); + number *= -1; // make it positive + } + + FIRCLSFileWriteUInt64(file, number, false); +} + +void FIRCLSFileFDWriteInt64(int fd, int64_t number) { + if (number < 0) { + FIRCLSFileWriteWithRetries(fd, "-", 1); + number *= -1; // make it positive + } + + FIRCLSFileFDWriteUInt64(fd, number, false); +} + +short FIRCLSFilePrepareUInt64(char* buffer, uint64_t number, bool hex) { + uint32_t base = hex ? 16 : 10; + + // zero it out, which will add a terminator + memset(buffer, 0, FIRCLSUInt64StringBufferLength); + + // TODO: look at this closer + // I'm pretty sure there is a bug in this code that + // can result in numbers with leading zeros. Technically, + // those are not valid json. + + // Set current index. + short i = FIRCLSUInt64StringBufferLength - 1; + + // Loop through filling in the chars from the end. + do { + char value = number % base + '0'; + if (value > '9') { + value += 'a' - '9' - 1; + } + + buffer[--i] = value; + } while ((number /= base) > 0 && i > 0); + + // returns index pointing to the beginning of the string. + return i; +} + +void FIRCLSFileWriteBool(FIRCLSFile* file, bool value) { + if (value) { + FIRCLSFileWriteToFileDescriptorOrBuffer(file, "true", 4); + } else { + FIRCLSFileWriteToFileDescriptorOrBuffer(file, "false", 5); + } +} + +void FIRCLSFileWriteSectionStart(FIRCLSFile* file, const char* name) { + FIRCLSFileWriteHashStart(file); + FIRCLSFileWriteHashKey(file, name); +} + +void FIRCLSFileWriteSectionEnd(FIRCLSFile* file) { + FIRCLSFileWriteHashEnd(file); + FIRCLSFileWriteToFileDescriptorOrBuffer(file, "\n", 1); +} + +void FIRCLSFileWriteCollectionStart(FIRCLSFile* file, const char openingChar) { + char string[2]; + + string[0] = ','; + string[1] = openingChar; + + if (file->needComma) { + FIRCLSFileWriteToFileDescriptorOrBuffer(file, string, 2); // write the seperator + opening char + } else { + FIRCLSFileWriteToFileDescriptorOrBuffer(file, &string[1], 1); // write only the opening char + } + + file->collectionDepth++; + + file->needComma = false; +} + +void FIRCLSFileWriteCollectionEnd(FIRCLSFile* file, const char closingChar) { + FIRCLSFileWriteToFileDescriptorOrBuffer(file, &closingChar, 1); + + if (file->collectionDepth <= 0) { + // FIRCLSSafeLog("Collection depth invariant violated\n"); + return; + } + + file->collectionDepth--; + + file->needComma = file->collectionDepth > 0; +} + +void FIRCLSFileWriteColletionEntryProlog(FIRCLSFile* file) { + if (file->needComma) { + FIRCLSFileWriteToFileDescriptorOrBuffer(file, ",", 1); + } +} + +void FIRCLSFileWriteColletionEntryEpilog(FIRCLSFile* file) { + file->needComma = true; +} + +void FIRCLSFileWriteHashStart(FIRCLSFile* file) { + FIRCLSFileWriteCollectionStart(file, '{'); +} + +void FIRCLSFileWriteHashEnd(FIRCLSFile* file) { + FIRCLSFileWriteCollectionEnd(file, '}'); +} + +void FIRCLSFileWriteHashKey(FIRCLSFile* file, const char* key) { + FIRCLSFileWriteColletionEntryProlog(file); + + FIRCLSFileWriteStringWithSuffix(file, key, strlen(key), ':'); + + file->needComma = false; +} + +void FIRCLSFileWriteHashEntryUint64(FIRCLSFile* file, const char* key, uint64_t value) { + // no prolog needed because it comes from the key + + FIRCLSFileWriteHashKey(file, key); + FIRCLSFileWriteUInt64(file, value, false); + + FIRCLSFileWriteColletionEntryEpilog(file); +} + +void FIRCLSFileWriteHashEntryInt64(FIRCLSFile* file, const char* key, int64_t value) { + // prolog from key + FIRCLSFileWriteHashKey(file, key); + FIRCLSFileWriteInt64(file, value); + + FIRCLSFileWriteColletionEntryEpilog(file); +} + +void FIRCLSFileWriteHashEntryString(FIRCLSFile* file, const char* key, const char* value) { + FIRCLSFileWriteHashKey(file, key); + FIRCLSFileWriteString(file, value); + + FIRCLSFileWriteColletionEntryEpilog(file); +} + +void FIRCLSFileWriteHashEntryNSString(FIRCLSFile* file, const char* key, NSString* string) { + FIRCLSFileWriteHashEntryString(file, key, [string UTF8String]); +} + +void FIRCLSFileWriteHashEntryNSStringUnlessNilOrEmpty(FIRCLSFile* file, + const char* key, + NSString* string) { + if ([string length] > 0) { + FIRCLSFileWriteHashEntryString(file, key, [string UTF8String]); + } +} + +void FIRCLSFileWriteHashEntryHexEncodedString(FIRCLSFile* file, + const char* key, + const char* value) { + FIRCLSFileWriteHashKey(file, key); + FIRCLSFileWriteHexEncodedString(file, value); + + FIRCLSFileWriteColletionEntryEpilog(file); +} + +void FIRCLSFileWriteHashEntryBoolean(FIRCLSFile* file, const char* key, bool value) { + FIRCLSFileWriteHashKey(file, key); + FIRCLSFileWriteBool(file, value); + + FIRCLSFileWriteColletionEntryEpilog(file); +} + +void FIRCLSFileWriteArrayStart(FIRCLSFile* file) { + FIRCLSFileWriteCollectionStart(file, '['); +} + +void FIRCLSFileWriteArrayEnd(FIRCLSFile* file) { + FIRCLSFileWriteCollectionEnd(file, ']'); +} + +void FIRCLSFileWriteArrayEntryUint64(FIRCLSFile* file, uint64_t value) { + FIRCLSFileWriteColletionEntryProlog(file); + + FIRCLSFileWriteUInt64(file, value, false); + + FIRCLSFileWriteColletionEntryEpilog(file); +} + +void FIRCLSFileWriteArrayEntryString(FIRCLSFile* file, const char* value) { + FIRCLSFileWriteColletionEntryProlog(file); + + FIRCLSFileWriteString(file, value); + + FIRCLSFileWriteColletionEntryEpilog(file); +} + +void FIRCLSFileWriteArrayEntryHexEncodedString(FIRCLSFile* file, const char* value) { + FIRCLSFileWriteColletionEntryProlog(file); + + FIRCLSFileWriteHexEncodedString(file, value); + + FIRCLSFileWriteColletionEntryEpilog(file); +} + +NSArray* FIRCLSFileReadSections(const char* path, + bool deleteOnFailure, + NSObject* (^transformer)(id obj)) { + if (!FIRCLSIsValidPointer(path)) { + FIRCLSSDKLogError("Error: input path is invalid\n"); + return nil; + } + + NSString* pathString = [NSString stringWithUTF8String:path]; + NSString* contents = [NSString stringWithContentsOfFile:pathString + encoding:NSUTF8StringEncoding + error:nil]; + NSArray* components = [contents componentsSeparatedByString:@"\n"]; + + if (!components) { + if (deleteOnFailure) { + unlink(path); + } + + FIRCLSSDKLog("Unable to read file %s\n", path); + return nil; + } + + NSMutableArray* array = [NSMutableArray array]; + + // loop through all the entires, and + for (NSString* component in components) { + NSData* data = [component dataUsingEncoding:NSUTF8StringEncoding]; + + id obj = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; + if (!obj) { + continue; + } + + if (transformer) { + obj = transformer(obj); + } + + if (!obj) { + continue; + } + + [array addObject:obj]; + } + + return array; +} + +NSString* FIRCLSFileHexEncodeString(const char* string) { + size_t length = strlen(string); + char* encodedBuffer = malloc(length * 2 + 1); + + if (!encodedBuffer) { + FIRCLSErrorLog(@"Unable to malloc in FIRCLSFileHexEncodeString"); + return nil; + } + + memset(encodedBuffer, 0, length * 2 + 1); + + int bufferIndex = 0; + for (int i = 0; i < length; ++i) { + FIRCLSHexFromByte(string[i], &encodedBuffer[bufferIndex]); + + bufferIndex += 2; // 1 char => 2 hex values at a time + } + + NSString* stringObject = [NSString stringWithUTF8String:encodedBuffer]; + + free(encodedBuffer); + + return stringObject; +} + +NSString* FIRCLSFileHexDecodeString(const char* string) { + size_t length = strlen(string); + char* decodedBuffer = malloc(length); // too long, but safe + if (!decodedBuffer) { + FIRCLSErrorLog(@"Unable to malloc in FIRCLSFileHexDecodeString"); + return nil; + } + + memset(decodedBuffer, 0, length); + + for (int i = 0; i < length / 2; ++i) { + size_t index = i * 2; + + uint8_t hiNybble = FIRCLSNybbleFromChar(string[index]); + uint8_t lowNybble = FIRCLSNybbleFromChar(string[index + 1]); + + if (hiNybble == FIRCLSInvalidCharNybble || lowNybble == FIRCLSInvalidCharNybble) { + // char is invalid, abort loop + break; + } + + decodedBuffer[i] = (hiNybble << 4) | lowNybble; + } + + NSString* strObject = [NSString stringWithUTF8String:decodedBuffer]; + + free(decodedBuffer); + + return strObject; +} diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSInternalLogging.c b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSInternalLogging.c new file mode 100644 index 000000000..d9e3daa09 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSInternalLogging.c @@ -0,0 +1,96 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSInternalLogging.h" +#include "FIRCLSContext.h" +#include "FIRCLSGlobals.h" +#include "FIRCLSUtility.h" + +void FIRCLSSDKFileLog(FIRCLSInternalLogLevel level, const char* format, ...) { + if (!_firclsContext.readonly || !_firclsContext.writable) { + return; + } + + const char* path = _firclsContext.readonly->logPath; + if (!FIRCLSIsValidPointer(path)) { + return; + } + + if (_firclsContext.writable->internalLogging.logLevel > level) { + return; + } + + if (_firclsContext.writable->internalLogging.logFd == -1) { + _firclsContext.writable->internalLogging.logFd = open(path, O_WRONLY | O_CREAT | O_APPEND, 0644); + } + + const int fd = _firclsContext.writable->internalLogging.logFd; + if (fd < 0) { + return; + } + + va_list args; + va_start(args, format); + +#if DEBUG && 0 + // It's nice to use printf here, so all the formatting works. However, its possible to hit a + // deadlock if you call vfprintf in a crash handler. So, this code is handy to keep, just in case, + // if there's a really tough thing to debug. + FILE* file = fopen(path, "a+"); + vfprintf(file, format, args); + fclose(file); +#else + size_t formatLength = strlen(format); + for (size_t idx = 0; idx < formatLength; ++idx) { + if (format[idx] != '%') { + write(fd, &format[idx], 1); + continue; + } + + idx++; // move to the format char + switch (format[idx]) { + case 'd': { + int value = va_arg(args, int); + FIRCLSFileFDWriteInt64(fd, value); + } break; + case 'u': { + uint32_t value = va_arg(args, uint32_t); + FIRCLSFileFDWriteUInt64(fd, value, false); + } break; + case 'p': { + uintptr_t value = va_arg(args, uintptr_t); + write(fd, "0x", 2); + FIRCLSFileFDWriteUInt64(fd, value, true); + } break; + case 's': { + const char* string = va_arg(args, const char*); + if (!string) { + string = "(null)"; + } + + write(fd, string, strlen(string)); + } break; + case 'x': { + unsigned int value = va_arg(args, unsigned int); + FIRCLSFileFDWriteUInt64(fd, value, true); + } break; + default: + // unhandled, back up to write out the percent + the format char + write(fd, &format[idx - 1], 2); + break; + } + } +#endif + va_end(args); +} diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSInternalLogging.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSInternalLogging.h new file mode 100644 index 000000000..4ff164453 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSInternalLogging.h @@ -0,0 +1,57 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include <stdio.h> + +#if __OBJC__ +#import "FIRCLSLogger.h" +#define FIRCLSDeveloperLog(label, __FORMAT__, ...) \ + FIRCLSDebugLog(@"[" label "] " __FORMAT__, ##__VA_ARGS__); +#endif + +typedef enum { + FIRCLSInternalLogLevelUnknown = 0, + FIRCLSInternalLogLevelDebug = 1, + FIRCLSInternalLogLevelInfo = 2, + FIRCLSInternalLogLevelWarn = 3, + FIRCLSInternalLogLevelError = 4 +} FIRCLSInternalLogLevel; + +typedef struct { + int logFd; + FIRCLSInternalLogLevel logLevel; +} FIRCLSInternalLoggingWritableContext; + +#define FIRCLSSDKLogDebug(__FORMAT__, ...) \ + FIRCLSSDKFileLog(FIRCLSInternalLogLevelDebug, "DEBUG [%s:%d] " __FORMAT__, __FUNCTION__, \ + __LINE__, ##__VA_ARGS__) +#define FIRCLSSDKLogInfo(__FORMAT__, ...) \ + FIRCLSSDKFileLog(FIRCLSInternalLogLevelInfo, "INFO [%s:%d] " __FORMAT__, __FUNCTION__, \ + __LINE__, ##__VA_ARGS__) +#define FIRCLSSDKLogWarn(__FORMAT__, ...) \ + FIRCLSSDKFileLog(FIRCLSInternalLogLevelWarn, "WARN [%s:%d] " __FORMAT__, __FUNCTION__, \ + __LINE__, ##__VA_ARGS__) +#define FIRCLSSDKLogError(__FORMAT__, ...) \ + FIRCLSSDKFileLog(FIRCLSInternalLogLevelError, "ERROR [%s:%d] " __FORMAT__, __FUNCTION__, \ + __LINE__, ##__VA_ARGS__) + +#define FIRCLSSDKLog FIRCLSSDKLogWarn + +__BEGIN_DECLS + +void FIRCLSSDKFileLog(FIRCLSInternalLogLevel level, const char* format, ...) __printflike(2, 3); + +__END_DECLS diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h new file mode 100644 index 000000000..e03d99a9e --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h @@ -0,0 +1,24 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +__BEGIN_DECLS + +void FIRCLSDebugLog(NSString *message, ...); +void FIRCLSInfoLog(NSString *message, ...); +void FIRCLSWarningLog(NSString *message, ...); +void FIRCLSErrorLog(NSString *message, ...); + +__END_DECLS diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSLogger.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSLogger.m new file mode 100644 index 000000000..50bd1922f --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSLogger.m @@ -0,0 +1,52 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSLogger.h" + +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +FIRLoggerService kFIRLoggerCrashlytics = @"[Firebase/Crashlytics]"; + +NSString *const CrashlyticsMessageCode = @"I-CLS000000"; + +void FIRCLSDebugLog(NSString *message, ...) { + va_list args_ptr; + va_start(args_ptr, message); + FIRLogBasic(FIRLoggerLevelDebug, kFIRLoggerCrashlytics, CrashlyticsMessageCode, message, + args_ptr); + va_end(args_ptr); +} + +void FIRCLSInfoLog(NSString *message, ...) { + va_list args_ptr; + va_start(args_ptr, message); + FIRLogBasic(FIRLoggerLevelInfo, kFIRLoggerCrashlytics, CrashlyticsMessageCode, message, args_ptr); + va_end(args_ptr); +} + +void FIRCLSWarningLog(NSString *message, ...) { + va_list args_ptr; + va_start(args_ptr, message); + FIRLogBasic(FIRLoggerLevelWarning, kFIRLoggerCrashlytics, CrashlyticsMessageCode, message, + args_ptr); + va_end(args_ptr); +} + +void FIRCLSErrorLog(NSString *message, ...) { + va_list args_ptr; + va_start(args_ptr, message); + FIRLogBasic(FIRLoggerLevelError, kFIRLoggerCrashlytics, CrashlyticsMessageCode, message, + args_ptr); + va_end(args_ptr); +} diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSProfiling.c b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSProfiling.c new file mode 100644 index 000000000..df5008023 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSProfiling.c @@ -0,0 +1,47 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSProfiling.h" + +#include <mach/mach_time.h> +#include <stdio.h> + +FIRCLSProfileMark FIRCLSProfilingStart(void) { + return mach_absolute_time(); +} + +double FIRCLSProfileEnd(FIRCLSProfileMark mark) { + uint64_t duration = mach_absolute_time() - mark; + + mach_timebase_info_data_t info; + mach_timebase_info(&info); + + if (info.denom == 0) { + return 0.0; + } + + // Convert to nanoseconds + duration *= info.numer; + duration /= info.denom; + + return (double)duration / (double)NSEC_PER_MSEC; // return time in milliseconds +} + +void FIRCLSProfileBlock(const char* label, void (^block)(void)) { + FIRCLSProfileMark mark = FIRCLSProfilingStart(); + + block(); + + fprintf(stderr, "[Profile] %s: %f ms\n", label, FIRCLSProfileEnd(mark)); +} diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSProfiling.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSProfiling.h new file mode 100644 index 000000000..5cc312f4e --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSProfiling.h @@ -0,0 +1,29 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include <stdint.h> + +typedef uint64_t FIRCLSProfileMark; + +__BEGIN_DECLS + +// high-resolution timing, returning the results in seconds +FIRCLSProfileMark FIRCLSProfilingStart(void); +double FIRCLSProfileEnd(FIRCLSProfileMark mark); + +void FIRCLSProfileBlock(const char* label, void (^block)(void)); + +__END_DECLS diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSThreadState.c b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSThreadState.c new file mode 100644 index 000000000..44a300282 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSThreadState.c @@ -0,0 +1,147 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSThreadState.h" +#include "FIRCLSDefines.h" +#include "FIRCLSUtility.h" + +#if defined(__arm__) || defined(__arm64__) +#include <mach/arm/thread_status.h> +#include <ptrauth.h> +#endif + +#if CLS_CPU_X86_64 +#define GET_IP_REGISTER(r) (r->__ss.__rip) +#define GET_FP_REGISTER(r) (r->__ss.__rbp) +#define GET_SP_REGISTER(r) (r->__ss.__rsp) +#define GET_LR_REGISTER(r) 0 +#define SET_IP_REGISTER(r, v) (r->__ss.__rip = v) +#define SET_FP_REGISTER(r, v) (r->__ss.__rbp = v) +#define SET_SP_REGISTER(r, v) (r->__ss.__rsp = v) +#define SET_LR_REGISTER(r, v) +#elif CLS_CPU_I386 +#define GET_IP_REGISTER(r) (r->__ss.__eip) +#define GET_FP_REGISTER(r) (r->__ss.__ebp) +#define GET_SP_REGISTER(r) (r->__ss.__esp) +#define GET_LR_REGISTER(r) 0 +#define SET_IP_REGISTER(r, v) (r->__ss.__eip = v) +#define SET_FP_REGISTER(r, v) (r->__ss.__ebp = v) +#define SET_SP_REGISTER(r, v) (r->__ss.__esp = v) +#define SET_LR_REGISTER(r, v) +#elif CLS_CPU_ARM64 +// The arm_thread_state64_get_* macros translate down to the AUTIA and AUTIB instructions which +// authenticate the address, but don't clear the upper bits. From the docs: +// "If the authentication passes, the upper bits of the address are restored to enable +// subsequent use of the address. the authentication fails, the upper bits are corrupted and +// any subsequent use of the address results in a Translation fault." +// Since we only want the address (with the metadata in the upper bits masked out), we used the +// ptrauth_strip macro to clear the upper bits. +// +// We found later that ptrauth_strip doesn't seem to do anything. In many cases, the upper bits were +// already stripped, so for most non-system-library code, Crashlytics would still symbolicate. But +// for system libraries, the upper bits were being left in even when we called ptrauth_strip. +// Instead, we're bit masking and only allowing the latter 36 bits. +#define CLS_PTRAUTH_STRIP(pointer) ((uintptr_t)pointer & 0x0000000FFFFFFFFF) +#define GET_IP_REGISTER(r) (CLS_PTRAUTH_STRIP(arm_thread_state64_get_pc(r->__ss))) +#define GET_FP_REGISTER(r) (CLS_PTRAUTH_STRIP(arm_thread_state64_get_fp(r->__ss))) +#define GET_SP_REGISTER(r) (CLS_PTRAUTH_STRIP(arm_thread_state64_get_sp(r->__ss))) +#define GET_LR_REGISTER(r) (CLS_PTRAUTH_STRIP(arm_thread_state64_get_lr(r->__ss))) +#define SET_IP_REGISTER(r, v) arm_thread_state64_set_pc_fptr(r->__ss, (void*)v) +#define SET_FP_REGISTER(r, v) arm_thread_state64_set_fp(r->__ss, v) +#define SET_SP_REGISTER(r, v) arm_thread_state64_set_sp(r->__ss, v) +#define SET_LR_REGISTER(r, v) arm_thread_state64_set_lr_fptr(r->__ss, (void*)v) +#elif CLS_CPU_ARM +#define GET_IP_REGISTER(r) (r->__ss.__pc) +#define GET_FP_REGISTER(r) (r->__ss.__r[7]) +#define GET_SP_REGISTER(r) (r->__ss.__sp) +#define GET_LR_REGISTER(r) (r->__ss.__lr) +#define SET_IP_REGISTER(r, v) (r->__ss.__pc = v) +#define SET_FP_REGISTER(r, v) (r->__ss.__r[7] = v) +#define SET_SP_REGISTER(r, v) (r->__ss.__sp = v) +#define SET_LR_REGISTER(r, v) (r->__ss.__lr = v) +#else +#error "Architecture Unsupported" +#endif + +uintptr_t FIRCLSThreadContextGetPC(FIRCLSThreadContext* registers) { + if (!registers) { + return 0; + } + + return GET_IP_REGISTER(registers); +} + +uintptr_t FIRCLSThreadContextGetStackPointer(const FIRCLSThreadContext* registers) { + if (!registers) { + return 0; + } + + return GET_SP_REGISTER(registers); +} + +bool FIRCLSThreadContextSetStackPointer(FIRCLSThreadContext* registers, uintptr_t value) { + if (!FIRCLSIsValidPointer(registers)) { + return false; + } + + SET_SP_REGISTER(registers, value); + + return true; +} + +uintptr_t FIRCLSThreadContextGetLinkRegister(const FIRCLSThreadContext* registers) { + if (!FIRCLSIsValidPointer(registers)) { + return 0; + } + + return GET_LR_REGISTER(registers); +} + +bool FIRCLSThreadContextSetLinkRegister(FIRCLSThreadContext* registers, uintptr_t value) { + if (!FIRCLSIsValidPointer(registers)) { + return false; + } + + SET_LR_REGISTER(registers, value); + + return true; +} + +bool FIRCLSThreadContextSetPC(FIRCLSThreadContext* registers, uintptr_t value) { + if (!registers) { + return false; + } + + SET_IP_REGISTER(registers, value); + + return true; +} + +uintptr_t FIRCLSThreadContextGetFramePointer(const FIRCLSThreadContext* registers) { + if (!FIRCLSIsValidPointer(registers)) { + return 0; + } + + return GET_FP_REGISTER(registers); +} + +bool FIRCLSThreadContextSetFramePointer(FIRCLSThreadContext* registers, uintptr_t value) { + if (!FIRCLSIsValidPointer(registers)) { + return false; + } + + SET_FP_REGISTER(registers, value); + + return true; +} diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSThreadState.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSThreadState.h new file mode 100644 index 000000000..f281f665c --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSThreadState.h @@ -0,0 +1,57 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include <stdbool.h> +#include <sys/ucontext.h> + +#if CLS_CPU_ARM +#define FIRCLSThreadStateCount ARM_THREAD_STATE_COUNT +#define FIRCLSThreadState ARM_THREAD_STATE +#elif CLS_CPU_ARM64 +#define FIRCLSThreadStateCount ARM_THREAD_STATE64_COUNT +#define FIRCLSThreadState ARM_THREAD_STATE64 +#elif CLS_CPU_I386 +#define FIRCLSThreadStateCount x86_THREAD_STATE32_COUNT +#define FIRCLSThreadState x86_THREAD_STATE32 +#elif CLS_CPU_X86_64 +#define FIRCLSThreadStateCount x86_THREAD_STATE64_COUNT +#define FIRCLSThreadState x86_THREAD_STATE64 +#endif + +// _STRUCT_MCONTEXT was fixed to point to the right thing on ARM in the iOS 7.1 SDK +typedef _STRUCT_MCONTEXT FIRCLSThreadContext; + +// I'm not entirely sure what happened when, but this appears to have disappeared from +// the SDKs... +#if !defined(_STRUCT_UCONTEXT64) +typedef _STRUCT_UCONTEXT _STRUCT_UCONTEXT64; +#endif + +#pragma mark Register Access + +uintptr_t FIRCLSThreadContextGetPC(FIRCLSThreadContext* registers); +uintptr_t FIRCLSThreadContextGetStackPointer(const FIRCLSThreadContext* registers); +uintptr_t FIRCLSThreadContextGetFramePointer(const FIRCLSThreadContext* registers); + +bool FIRCLSThreadContextSetPC(FIRCLSThreadContext* registers, uintptr_t value); +bool FIRCLSThreadContextSetStackPointer(FIRCLSThreadContext* registers, uintptr_t value); +bool FIRCLSThreadContextSetFramePointer(FIRCLSThreadContext* registers, uintptr_t value); + +// The link register only exists on ARM platforms. +#if CLS_CPU_ARM || CLS_CPU_ARM64 +uintptr_t FIRCLSThreadContextGetLinkRegister(const FIRCLSThreadContext* registers); +bool FIRCLSThreadContextSetLinkRegister(FIRCLSThreadContext* registers, uintptr_t value); +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h new file mode 100644 index 000000000..5a50f0fd3 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h @@ -0,0 +1,54 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include <mach/vm_types.h> +#include <stdbool.h> +#include <stdio.h> +#include "FIRCLSGlobals.h" + +#define FIRCLSIsValidPointer(x) ((uintptr_t)x >= 4096) +#define FIRCLSInvalidCharNybble (255) + +__BEGIN_DECLS + +void FIRCLSLookupFunctionPointer(void* ptr, void (^block)(const char* name, const char* lib)); + +void FIRCLSHexFromByte(uint8_t c, char output[]); +uint8_t FIRCLSNybbleFromChar(char c); + +bool FIRCLSReadMemory(vm_address_t src, void* dest, size_t len); +bool FIRCLSReadString(vm_address_t src, char** dest, size_t maxlen); + +const char* FIRCLSDupString(const char* string); + +bool FIRCLSUnlinkIfExists(const char* path); + +#if __OBJC__ +void FIRCLSDispatchAfter(float timeInSeconds, dispatch_queue_t queue, dispatch_block_t block); + +NSString* FIRCLSNormalizeUUID(NSString* value); +NSString* FIRCLSGenerateNormalizedUUID(void); + +NSString* FIRCLSNSDataToNSString(NSData* data); + +void FIRCLSAddOperationAfter(float timeInSeconds, NSOperationQueue* queue, void (^block)(void)); +#endif + +#if DEBUG +void FIRCLSPrintAUUID(const uint8_t* value); +#endif + +__END_DECLS diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSUtility.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSUtility.m new file mode 100644 index 000000000..520640f3c --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSUtility.m @@ -0,0 +1,218 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSUtility.h" + +#include <mach/mach.h> + +#include <dlfcn.h> + +#include "FIRCLSFeatures.h" +#include "FIRCLSFile.h" +#include "FIRCLSGlobals.h" + +#import "FIRCLSByteUtility.h" +#import "FIRCLSUUID.h" + +#import <CommonCrypto/CommonHMAC.h> + +void FIRCLSLookupFunctionPointer(void* ptr, void (^block)(const char* name, const char* lib)) { + Dl_info info; + + if (dladdr(ptr, &info) == 0) { + block(NULL, NULL); + return; + } + + const char* name = "unknown"; + const char* lib = "unknown"; + + if (info.dli_sname) { + name = info.dli_sname; + } + + if (info.dli_fname) { + lib = info.dli_fname; + } + + block(name, lib); +} + +uint8_t FIRCLSNybbleFromChar(char c) { + if (c >= '0' && c <= '9') { + return c - '0'; + } + + if (c >= 'a' && c <= 'f') { + return c - 'a' + 10; + } + + if (c >= 'A' && c <= 'F') { + return c - 'A' + 10; + } + + return FIRCLSInvalidCharNybble; +} + +bool FIRCLSReadMemory(vm_address_t src, void* dest, size_t len) { + if (!FIRCLSIsValidPointer(src)) { + return false; + } + + vm_size_t readSize = len; + + return vm_read_overwrite(mach_task_self(), src, len, (pointer_t)dest, &readSize) == KERN_SUCCESS; +} + +bool FIRCLSReadString(vm_address_t src, char** dest, size_t maxlen) { + char c; + vm_address_t address; + + if (!dest) { + return false; + } + + // Walk the entire string. Not certain this is perfect... + for (address = src; address < src + maxlen; ++address) { + if (!FIRCLSReadMemory(address, &c, 1)) { + return false; + } + + if (c == 0) { + break; + } + } + + *dest = (char*)src; + + return true; +} + +const char* FIRCLSDupString(const char* string) { +#if CLS_MEMORY_PROTECTION_ENABLED + char* buffer; + size_t length; + + if (!string) { + return NULL; + } + + length = strlen(string); + buffer = FIRCLSAllocatorSafeAllocate(_firclsContext.allocator, length + 1, CLS_READONLY); + + memcpy(buffer, string, length); + + buffer[length] = 0; // null-terminate + + return buffer; +#else + return strdup(string); +#endif +} + +void FIRCLSDispatchAfter(float timeInSeconds, dispatch_queue_t queue, dispatch_block_t block) { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeInSeconds * NSEC_PER_SEC)), queue, + block); +} + +bool FIRCLSUnlinkIfExists(const char* path) { + if (unlink(path) != 0) { + if (errno != ENOENT) { + return false; + } + } + + return true; +} + +/* +NSString* FIRCLSGenerateUUID(void) { + NSString* string; + + CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault); + string = CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, uuid)); + CFRelease(uuid); + + return string; +} +*/ + +NSString* FIRCLSNormalizeUUID(NSString* value) { + return [[value stringByReplacingOccurrencesOfString:@"-" withString:@""] lowercaseString]; +} + +NSString* FIRCLSGenerateNormalizedUUID(void) { + return FIRCLSNormalizeUUID(FIRCLSGenerateUUID()); +} + +NSString* FIRCLSNSDataToNSString(NSData* data) { + NSString* string; + char* buffer; + size_t size; + NSUInteger length; + + // we need 2 hex char for every byte of data, plus one more spot for a + // null terminator + length = [data length]; + size = (length * 2) + 1; + buffer = malloc(sizeof(char) * size); + + if (!buffer) { + FIRCLSErrorLog(@"Unable to malloc in FIRCLSNSDataToNSString"); + return nil; + } + + FIRCLSSafeHexToString([data bytes], length, buffer); + + string = [NSString stringWithUTF8String:buffer]; + + free(buffer); + + return string; +} + +/* +NSString* FIRCLSHashBytes(const void* bytes, size_t length) { + uint8_t digest[CC_SHA1_DIGEST_LENGTH] = {0}; + CC_SHA1(bytes, (CC_LONG)length, digest); + + NSData* result = [NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH]; + + return FIRCLSNSDataToNSString(result); +} + +NSString* FIRCLSHashNSData(NSData* data) { + return FIRCLSHashBytes([data bytes], [data length]); +} +*/ + +void FIRCLSAddOperationAfter(float timeInSeconds, NSOperationQueue* queue, void (^block)(void)) { + dispatch_queue_t afterQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + FIRCLSDispatchAfter(timeInSeconds, afterQueue, ^{ + [queue addOperationWithBlock:block]; + }); +} + +#if DEBUG +void FIRCLSPrintAUUID(const uint8_t* value) { + CFUUIDRef uuid = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, *(CFUUIDBytes*)value); + + NSString* string = CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, uuid)); + + CFRelease(uuid); + + FIRCLSDebugLog(@"%@", [[string stringByReplacingOccurrencesOfString:@"-" + withString:@""] lowercaseString]); +} +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSExecutionIdentifierModel.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSExecutionIdentifierModel.h new file mode 100644 index 000000000..41a489672 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSExecutionIdentifierModel.h @@ -0,0 +1,33 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +/** + * This class is a model to identify a single execution of the app + */ +@interface FIRCLSExecutionIdentifierModel : NSObject + +/** + * Returns the launch identifier. This is a unique id that will remain constant until this process + * is relaunched. This value is useful for correlating events across kits and/or across reports at + * the process-lifecycle level. + */ +@property(nonatomic, readonly) NSString *executionID; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSExecutionIdentifierModel.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSExecutionIdentifierModel.m new file mode 100644 index 000000000..e312d46f8 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSExecutionIdentifierModel.m @@ -0,0 +1,33 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSExecutionIdentifierModel.h" + +#import "FIRCLSUUID.h" + +@implementation FIRCLSExecutionIdentifierModel + +- (instancetype)init { + self = [super init]; + if (!self) { + return nil; + } + + _executionID = [[FIRCLSGenerateUUID() stringByReplacingOccurrencesOfString:@"-" + withString:@""] lowercaseString]; + + return self; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSFileManager.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSFileManager.h new file mode 100644 index 000000000..dd988a950 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSFileManager.h @@ -0,0 +1,73 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +@class FIRCLSInternalReport; + +@interface FIRCLSFileManager : NSObject + +- (instancetype)init NS_DESIGNATED_INITIALIZER; + +@property(nonatomic, readonly) NSFileManager *underlyingFileManager; + +/** + * Returns the folder containing the settings file + */ +@property(nonatomic, readonly) NSString *settingsDirectoryPath; + +/** + * Returns the path to the settings file + */ +@property(nonatomic, readonly) NSString *settingsFilePath; + +/** + * Path to the file that holds the ttl and keys that invalidate settings + */ +@property(nonatomic, readonly) NSString *settingsCacheKeyPath; + +@property(nonatomic, readonly) NSString *rootPath; +@property(nonatomic, readonly) NSString *structurePath; +@property(nonatomic, readonly) NSString *activePath; +@property(nonatomic, readonly) NSString *processingPath; +@property(nonatomic, readonly) NSString *pendingPath; +@property(nonatomic, readonly) NSString *preparedPath; +@property(nonatomic, readonly) NSString *legacyPreparedPath; +@property(nonatomic, readonly) NSArray *activePathContents; +@property(nonatomic, readonly) NSArray *legacyPreparedPathContents; +@property(nonatomic, readonly) NSArray *preparedPathContents; +@property(nonatomic, readonly) NSArray *processingPathContents; + +- (BOOL)fileExistsAtPath:(NSString *)path; +- (BOOL)createFileAtPath:(NSString *)path + contents:(NSData *)data + attributes:(NSDictionary<NSFileAttributeKey, id> *)attr; +- (BOOL)createDirectoryAtPath:(NSString *)path; +- (BOOL)removeItemAtPath:(NSString *)path; +- (BOOL)removeContentsOfDirectoryAtPath:(NSString *)path; +- (BOOL)moveItemAtPath:(NSString *)path toDirectory:(NSString *)destDir; +- (void)enumerateFilesInDirectory:(NSString *)directory + usingBlock:(void (^)(NSString *filePath, NSString *extension))block; +- (NSNumber *)fileSizeAtPath:(NSString *)path; +- (NSArray *)contentsOfDirectory:(NSString *)path; + +// logic of managing files/directories +- (BOOL)createReportDirectories; +- (NSString *)setupNewPathForExecutionIdentifier:(NSString *)identifier; + +- (BOOL)moveItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error; + +- (NSData *)dataWithContentsOfFile:(NSString *)path; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSFileManager.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSFileManager.m new file mode 100644 index 000000000..040dcf5b8 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSFileManager.m @@ -0,0 +1,279 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSFileManager.h" + +#import "FIRCLSApplication.h" +#import "FIRCLSInternalReport.h" +#import "FIRCLSLogger.h" + +NSString *const FIRCLSCacheDirectoryName = @"com.crashlytics.data"; +NSString *const FIRCLSCacheVersion = @"v5"; + +@interface FIRCLSFileManager () { + NSString *_rootPath; +} + +@end + +@implementation FIRCLSFileManager + +- (instancetype)init { + self = [super init]; + if (!self) { + return nil; + } + + _underlyingFileManager = [NSFileManager defaultManager]; + + NSString *path = + [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; + path = [path stringByAppendingPathComponent:FIRCLSCacheDirectoryName]; + path = [path stringByAppendingPathComponent:[self pathNamespace]]; + _rootPath = [path copy]; + + return self; +} + +#pragma mark - Core API + +- (BOOL)fileExistsAtPath:(NSString *)path { + return [_underlyingFileManager fileExistsAtPath:path]; +} + +- (BOOL)createFileAtPath:(NSString *)path + contents:(nullable NSData *)data + attributes:(nullable NSDictionary<NSFileAttributeKey, id> *)attr { + return [_underlyingFileManager createFileAtPath:path contents:data attributes:attr]; +} + +- (BOOL)createDirectoryAtPath:(NSString *)path { + NSDictionary *attributes; + NSError *error; + + attributes = @{NSFilePosixPermissions : [NSNumber numberWithShort:0755]}; + error = nil; + + if (![[self underlyingFileManager] createDirectoryAtPath:path + withIntermediateDirectories:YES + attributes:attributes + error:&error]) { + FIRCLSErrorLog(@"Unable to create directory %@", error); + return NO; + } + + return YES; +} + +- (BOOL)removeItemAtPath:(NSString *)path { + NSError *error; + + error = nil; + if (![[self underlyingFileManager] removeItemAtPath:path error:&error] || !path) { + FIRCLSErrorLog(@"Failed to remove file %@: %@", path, error); + + return NO; + } + + return YES; +} + +- (BOOL)removeContentsOfDirectoryAtPath:(NSString *)path { + __block BOOL success = YES; + + // only return true if we were able to remove every item in the directory (or it was empty) + + [self enumerateFilesInDirectory:path + usingBlock:^(NSString *filePath, NSString *extension) { + success = [self removeItemAtPath:filePath] && success; + }]; + + return success; +} + +- (BOOL)moveItemAtPath:(NSString *)path toDirectory:(NSString *)destDir { + NSString *destPath; + NSError *error; + + destPath = [destDir stringByAppendingPathComponent:[path lastPathComponent]]; + error = nil; + + if (!path || !destPath) { + FIRCLSErrorLog(@"Failed to move file, inputs invalid"); + + return NO; + } + + if (![[self underlyingFileManager] moveItemAtPath:path toPath:destPath error:&error]) { + FIRCLSErrorLog(@"Failed to move file: %@", error); + + return NO; + } + + return YES; +} + +- (void)enumerateFilesInDirectory:(NSString *)directory + usingBlock:(void (^)(NSString *filePath, NSString *extension))block { + for (NSString *path in [[self underlyingFileManager] contentsOfDirectoryAtPath:directory + error:nil]) { + NSString *extension; + NSString *fullPath; + + // Skip files that start with a dot. This is important, because if you try to move a .DS_Store + // file, it will fail if the target directory also has a .DS_Store file in it. Plus, its + // wasteful, because we don't care about dot files. + if ([path hasPrefix:@"."]) { + continue; + } + + extension = [path pathExtension]; + fullPath = [directory stringByAppendingPathComponent:path]; + if (block) { + block(fullPath, extension); + } + } +} + +- (NSNumber *)fileSizeAtPath:(NSString *)path { + NSError *error = nil; + NSDictionary *attrs = [[self underlyingFileManager] attributesOfItemAtPath:path error:&error]; + + if (!attrs) { + FIRCLSErrorLog(@"Unable to read file size: %@", error); + return nil; + } + + return [attrs objectForKey:NSFileSize]; +} + +- (NSArray *)contentsOfDirectory:(NSString *)path { + NSMutableArray *array = [NSMutableArray array]; + + [self enumerateFilesInDirectory:path + usingBlock:^(NSString *filePath, NSString *extension) { + [array addObject:filePath]; + }]; + + return [array copy]; +} + +#pragma - Properties +- (NSString *)pathNamespace { + return FIRCLSApplicationGetBundleIdentifier(); +} + +- (NSString *)versionedPath { + return [[self rootPath] stringByAppendingPathComponent:FIRCLSCacheVersion]; +} + +#pragma - Settings Paths + +// This path should be different than the structurePath because the +// settings download operations will delete the settings directory, +// which would delete crash reports if these were the same +- (NSString *)settingsDirectoryPath { + return [[self versionedPath] stringByAppendingPathComponent:@"settings"]; +} + +- (NSString *)settingsFilePath { + return [[self settingsDirectoryPath] stringByAppendingPathComponent:@"settings.json"]; +} + +- (NSString *)settingsCacheKeyPath { + return [[self settingsDirectoryPath] stringByAppendingPathComponent:@"cache-key.json"]; +} + +#pragma - Report Paths +- (NSString *)structurePath { + return [[self versionedPath] stringByAppendingPathComponent:@"reports"]; +} + +- (NSString *)activePath { + return [[self structurePath] stringByAppendingPathComponent:@"active"]; +} + +- (NSString *)pendingPath { + return [[self structurePath] stringByAppendingPathComponent:@"pending"]; +} + +- (NSString *)processingPath { + return [[self structurePath] stringByAppendingPathComponent:@"processing"]; +} + +- (NSString *)legacyPreparedPath { + return [[self structurePath] stringByAppendingPathComponent:@"prepared-legacy"]; +} + +- (NSString *)preparedPath { + return [[self structurePath] stringByAppendingPathComponent:@"prepared"]; +} + +- (NSArray *)activePathContents { + return [self contentsOfDirectory:[self activePath]]; +} + +- (NSArray *)legacyPreparedPathContents { + return [self contentsOfDirectory:[self legacyPreparedPath]]; +} + +- (NSArray *)preparedPathContents { + return [self contentsOfDirectory:[self preparedPath]]; +} + +- (NSArray *)processingPathContents { + return [self contentsOfDirectory:[self processingPath]]; +} + +#pragma mark - Logic +- (BOOL)createReportDirectories { + if (![self createDirectoryAtPath:[self activePath]]) { + return NO; + } + + if (![self createDirectoryAtPath:[self processingPath]]) { + return NO; + } + + if (![self createDirectoryAtPath:[self legacyPreparedPath]]) { + return NO; + } + + if (![self createDirectoryAtPath:[self preparedPath]]) { + return NO; + } + + return YES; +} + +- (NSString *)setupNewPathForExecutionIdentifier:(NSString *)identifier { + NSString *path = [[self activePath] stringByAppendingPathComponent:identifier]; + + if (![self createDirectoryAtPath:path]) { + return nil; + } + + return path; +} + +- (BOOL)moveItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error { + return [self.underlyingFileManager moveItemAtPath:srcPath toPath:dstPath error:error]; +} + +// Wrapper over NSData so the method can be mocked for unit tests +- (NSData *)dataWithContentsOfFile:(NSString *)path { + return [NSData dataWithContentsOfFile:path]; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInstallIdentifierModel.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInstallIdentifierModel.h new file mode 100644 index 000000000..6100c8a97 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInstallIdentifierModel.h @@ -0,0 +1,46 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +@class FIRInstallations; + +NS_ASSUME_NONNULL_BEGIN + +/** + * This class is a model for identifying an installation of an app + */ +@interface FIRCLSInstallIdentifierModel : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +- (instancetype)initWithInstallations:(FIRInstallations *)instanceID NS_DESIGNATED_INITIALIZER; + +/** + * Returns the backwards compatible Crashlytics Installation UUID + */ +@property(nonatomic, readonly) NSString *installID; + +/** + * To support end-users rotating Install IDs, this will check and rotate the Install ID, + * which is a costly operation performance-wise. To keep the startup time impact down, call this in + * a background thread. + * + * The block will be called on a background thread. + */ +- (void)regenerateInstallIDIfNeededWithBlock:(void (^)(BOOL didRotate))callback; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInstallIdentifierModel.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInstallIdentifierModel.m new file mode 100644 index 000000000..2af2d7dbc --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInstallIdentifierModel.m @@ -0,0 +1,161 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSInstallIdentifierModel.h" + +#import <FirebaseInstallations/FirebaseInstallations.h> + +#import "FIRCLSByteUtility.h" +#import "FIRCLSLogger.h" +#import "FIRCLSUUID.h" +#import "FIRCLSUserDefaults.h" + +static NSString *const FIRCLSInstallationUUIDKey = @"com.crashlytics.iuuid"; +static NSString *const FIRCLSInstallationIIDHashKey = @"com.crashlytics.install.iid"; + +// Legacy key that is automatically removed +static NSString *const FIRCLSInstallationADIDKey = @"com.crashlytics.install.adid"; + +@interface FIRCLSInstallIdentifierModel () + +@property(nonatomic, copy) NSString *installID; + +@property(nonatomic, readonly) FIRInstallations *installations; + +@end + +@implementation FIRCLSInstallIdentifierModel + +// This needs to be synthesized so we can set without using the setter in the constructor and +// overridden setters and getters +@synthesize installID = _installID; + +- (instancetype)initWithInstallations:(FIRInstallations *)installations { + self = [super init]; + if (!self) { + return nil; + } + + // capture the install ID information + _installID = [self readInstallationUUID].copy; + _installations = installations; + + if (!_installID) { + FIRCLSDebugLog(@"Generating Install ID"); + _installID = [self generateInstallationUUID].copy; + + FIRCLSUserDefaults *defaults = [FIRCLSUserDefaults standardUserDefaults]; + [defaults synchronize]; + } + + return self; +} + +- (NSString *)installID { + @synchronized(self) { + return _installID; + } +} + +- (void)setInstallID:(NSString *)installID { + @synchronized(self) { + _installID = installID; + } +} + +/** + * Reads installation UUID stored in persistent storage. + * If the installation UUID is stored in legacy key, migrates it over to the new key. + */ +- (NSString *)readInstallationUUID { + return [[FIRCLSUserDefaults standardUserDefaults] objectForKey:FIRCLSInstallationUUIDKey]; +} + +/** + * Generates a new UUID and saves it in persistent storage. + * Does not sychronize the user defaults (to allow optimized + * batching of user default synchronizing) + */ +- (NSString *)generateInstallationUUID { + NSString *UUID = FIRCLSGenerateUUID(); + FIRCLSUserDefaults *userDefaults = [FIRCLSUserDefaults standardUserDefaults]; + [userDefaults setObject:UUID forKey:FIRCLSInstallationUUIDKey]; + return UUID; +} + +#pragma mark Privacy Shield + +/** + * To support privacy shield we need to regenerate the install id when the IID changes. + * + * This is a blocking, slow call that must be called on a background thread. + */ +- (void)regenerateInstallIDIfNeededWithBlock:(void (^)(BOOL didRotate))callback { + // This callback is on the main thread + [self.installations + installationIDWithCompletion:^(NSString *_Nullable currentIID, NSError *_Nullable error) { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ + BOOL didRotate = [self rotateCrashlyticsInstallUUIDWithIID:currentIID error:error]; + callback(didRotate); + }); + }]; +} + +- (BOOL)rotateCrashlyticsInstallUUIDWithIID:(NSString *_Nullable)currentIID + error:(NSError *_Nullable)error { + BOOL didRotate = NO; + + FIRCLSUserDefaults *defaults = [FIRCLSUserDefaults standardUserDefaults]; + + // Remove the legacy ID + NSString *adID = [defaults objectForKey:FIRCLSInstallationADIDKey]; + if (adID.length != 0) { + [defaults removeObjectForKey:FIRCLSInstallationADIDKey]; + [defaults synchronize]; + } + + if (error != nil) { + FIRCLSErrorLog(@"Failed to get Firebase Instance ID: %@", error); + return didRotate; + } + + if (currentIID.length == 0) { + FIRCLSErrorLog(@"Firebase Instance ID was empty when checked for changes"); + return didRotate; + } + + NSString *currentIIDHash = + FIRCLS256HashNSData([currentIID dataUsingEncoding:NSUTF8StringEncoding]); + NSString *lastIIDHash = [defaults objectForKey:FIRCLSInstallationIIDHashKey]; + + // If the IDs are the same, we never regenerate + if ([lastIIDHash isEqualToString:currentIIDHash]) { + return didRotate; + } + + // If we had an FIID saved, we know it's not an upgrade scenario, so we can regenerate + if (lastIIDHash.length != 0) { + FIRCLSDebugLog(@"Regenerating Install ID"); + self.installID = [self generateInstallationUUID].copy; + didRotate = YES; + } + + // Write the new FIID to UserDefaults + [defaults setObject:currentIIDHash forKey:FIRCLSInstallationIIDHashKey]; + [defaults synchronize]; + + return didRotate; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h new file mode 100644 index 000000000..a02123ffd --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h @@ -0,0 +1,117 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +#include "FIRCLSFeatures.h" + +extern NSString *const FIRCLSReportBinaryImageFile; +extern NSString *const FIRCLSReportExceptionFile; +extern NSString *const FIRCLSReportCustomExceptionAFile; +extern NSString *const FIRCLSReportCustomExceptionBFile; +extern NSString *const FIRCLSReportSignalFile; +#if CLS_MACH_EXCEPTION_SUPPORTED +extern NSString *const FIRCLSReportMachExceptionFile; +#endif +extern NSString *const FIRCLSReportErrorAFile; +extern NSString *const FIRCLSReportErrorBFile; +extern NSString *const FIRCLSReportLogAFile; +extern NSString *const FIRCLSReportLogBFile; +extern NSString *const FIRCLSReportMetadataFile; +extern NSString *const FIRCLSReportInternalIncrementalKVFile; +extern NSString *const FIRCLSReportInternalCompactedKVFile; +extern NSString *const FIRCLSReportUserIncrementalKVFile; +extern NSString *const FIRCLSReportUserCompactedKVFile; + +@class FIRCLSFileManager; + +@interface FIRCLSInternalReport : NSObject + ++ (instancetype)reportWithPath:(NSString *)path; +- (instancetype)initWithPath:(NSString *)path + executionIdentifier:(NSString *)identifier NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithPath:(NSString *)path; +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + ++ (NSArray *)crashFileNames; + +@property(nonatomic, copy, readonly) NSString *directoryName; +@property(nonatomic, copy) NSString *path; +@property(nonatomic, assign, readonly) BOOL needsToBeSubmitted; + +// content paths +@property(nonatomic, copy, readonly) NSString *binaryImagePath; +@property(nonatomic, copy, readonly) NSString *metadataPath; + +- (void)enumerateSymbolicatableFilesInContent:(void (^)(NSString *path))block; + +- (NSString *)pathForContentFile:(NSString *)name; + +// Metadata Helpers + +/** + * Returns the org id for the report. + **/ +@property(nonatomic, copy, readonly) NSString *orgID; + +/** + * Returns the Install UUID for the report. + **/ +@property(nonatomic, copy, readonly) NSString *installID; + +/** + * Returns YES if report contains a signal, mach exception or unhandled exception record, NO + * otherwise. + **/ +@property(nonatomic, assign, readonly) BOOL isCrash; + +/** + * Returns the session identifier for the report. + **/ +@property(nonatomic, copy, readonly) NSString *identifier; + +/** + * Returns the custom key value data for the report. + **/ +@property(nonatomic, copy, readonly) NSDictionary *customKeys; + +/** + * Returns the CFBundleVersion of the application that generated the report. + **/ +@property(nonatomic, copy, readonly) NSString *bundleVersion; + +/** + * Returns the CFBundleShortVersionString of the application that generated the report. + **/ +@property(nonatomic, copy, readonly) NSString *bundleShortVersionString; + +/** + * Returns the date that the report was created. + **/ +@property(nonatomic, copy, readonly) NSDate *dateCreated; + +@property(nonatomic, copy, readonly) NSDate *crashedOnDate; + +/** + * Returns the os version that the application crashed on. + **/ +@property(nonatomic, copy, readonly) NSString *OSVersion; + +/** + * Returns the os build version that the application crashed on. + **/ +@property(nonatomic, copy, readonly) NSString *OSBuildVersion; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInternalReport.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInternalReport.m new file mode 100644 index 000000000..74ac9975b --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInternalReport.m @@ -0,0 +1,253 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// TODO: Remove this class after the uploading of reports via GoogleDataTransport is no longer an +// experiment + +#import "FIRCLSInternalReport.h" + +#import "FIRCLSFile.h" +#import "FIRCLSFileManager.h" +#import "FIRCLSLogger.h" + +NSString *const FIRCLSReportBinaryImageFile = @"binary_images.clsrecord"; +NSString *const FIRCLSReportExceptionFile = @"exception.clsrecord"; +NSString *const FIRCLSReportCustomExceptionAFile = @"custom_exception_a.clsrecord"; +NSString *const FIRCLSReportCustomExceptionBFile = @"custom_exception_b.clsrecord"; +NSString *const FIRCLSReportSignalFile = @"signal.clsrecord"; +#if CLS_MACH_EXCEPTION_SUPPORTED +NSString *const FIRCLSReportMachExceptionFile = @"mach_exception.clsrecord"; +#endif +NSString *const FIRCLSReportMetadataFile = @"metadata.clsrecord"; +NSString *const FIRCLSReportErrorAFile = @"errors_a.clsrecord"; +NSString *const FIRCLSReportErrorBFile = @"errors_b.clsrecord"; +NSString *const FIRCLSReportLogAFile = @"log_a.clsrecord"; +NSString *const FIRCLSReportLogBFile = @"log_b.clsrecord"; +NSString *const FIRCLSReportInternalIncrementalKVFile = @"internal_incremental_kv.clsrecord"; +NSString *const FIRCLSReportInternalCompactedKVFile = @"internal_compacted_kv.clsrecord"; +NSString *const FIRCLSReportUserIncrementalKVFile = @"user_incremental_kv.clsrecord"; +NSString *const FIRCLSReportUserCompactedKVFile = @"user_compacted_kv.clsrecord"; + +@interface FIRCLSInternalReport () { + NSString *_identifier; + NSString *_path; + NSArray *_metadataSections; +} + +@end + +@implementation FIRCLSInternalReport + ++ (instancetype)reportWithPath:(NSString *)path { + return [[self alloc] initWithPath:path]; +} + +#pragma mark - Initialization +/** + * Initializes a new report, i.e. one without metadata on the file system yet. + */ +- (instancetype)initWithPath:(NSString *)path executionIdentifier:(NSString *)identifier { + self = [super init]; + if (!self) { + return self; + } + + if (!path || !identifier) { + return nil; + } + + [self setPath:path]; + + _identifier = [identifier copy]; + + return self; +} + +/** + * Initializes a pre-existing report, i.e. one with metadata on the file system. + */ +- (instancetype)initWithPath:(NSString *)path { + NSString *metadataPath = [path stringByAppendingPathComponent:FIRCLSReportMetadataFile]; + NSString *identifier = [[[[self.class readFIRCLSFileAtPath:metadataPath] objectAtIndex:0] + objectForKey:@"identity"] objectForKey:@"session_id"]; + if (!identifier) { + FIRCLSErrorLog(@"Unable to read identifier at path %@", path); + } + return [self initWithPath:path executionIdentifier:identifier]; +} + +#pragma mark - Path Helpers +- (NSString *)directoryName { + return self.path.lastPathComponent; +} + +- (NSString *)pathForContentFile:(NSString *)name { + return [[self path] stringByAppendingPathComponent:name]; +} + +- (NSString *)metadataPath { + return [[self path] stringByAppendingPathComponent:FIRCLSReportMetadataFile]; +} + +- (NSString *)binaryImagePath { + return [self pathForContentFile:FIRCLSReportBinaryImageFile]; +} + +#pragma mark - Processing Methods +- (BOOL)needsToBeSubmitted { + NSArray *reportFiles = @[ + FIRCLSReportExceptionFile, FIRCLSReportSignalFile, FIRCLSReportCustomExceptionAFile, + FIRCLSReportCustomExceptionBFile, +#if CLS_MACH_EXCEPTION_SUPPORTED + FIRCLSReportMachExceptionFile, +#endif + FIRCLSReportErrorAFile, FIRCLSReportErrorBFile + ]; + return [self checkExistenceOfAtLeastOnceFileInArray:reportFiles]; +} + +// These are purposefully in order of precedence. If duplicate data exists +// in any crash file, the exception file's contents take precedence over the +// rest, for example +// +// Do not change the order of this. +// ++ (NSArray *)crashFileNames { + static NSArray *files; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + files = @[ + FIRCLSReportExceptionFile, +#if CLS_MACH_EXCEPTION_SUPPORTED + FIRCLSReportMachExceptionFile, +#endif + FIRCLSReportSignalFile + ]; + }); + return files; +} + +- (BOOL)isCrash { + NSArray *crashFiles = [FIRCLSInternalReport crashFileNames]; + return [self checkExistenceOfAtLeastOnceFileInArray:crashFiles]; +} + +- (BOOL)checkExistenceOfAtLeastOnceFileInArray:(NSArray *)files { + NSFileManager *manager = [NSFileManager defaultManager]; + + for (NSString *fileName in files) { + NSString *path = [self pathForContentFile:fileName]; + + if ([manager fileExistsAtPath:path]) { + return YES; + } + } + + return NO; +} + +- (void)enumerateSymbolicatableFilesInContent:(void (^)(NSString *path))block { + for (NSString *fileName in [FIRCLSInternalReport crashFileNames]) { + NSString *path = [self pathForContentFile:fileName]; + + block(path); + } +} + +#pragma mark - Metadata helpers ++ (NSArray *)readFIRCLSFileAtPath:(NSString *)path { + NSArray *sections = FIRCLSFileReadSections([path fileSystemRepresentation], false, nil); + + if ([sections count] == 0) { + return nil; + } + + return sections; +} + +- (NSArray *)metadataSections { + if (!_metadataSections) { + _metadataSections = [self.class readFIRCLSFileAtPath:self.metadataPath]; + } + return _metadataSections; +} + +- (NSString *)orgID { + return + [[[self.metadataSections objectAtIndex:0] objectForKey:@"identity"] objectForKey:@"org_id"]; +} + +- (NSDictionary *)customKeys { + return nil; +} + +- (NSString *)bundleVersion { + return [[[self.metadataSections objectAtIndex:2] objectForKey:@"application"] + objectForKey:@"build_version"]; +} + +- (NSString *)bundleShortVersionString { + return [[[self.metadataSections objectAtIndex:2] objectForKey:@"application"] + objectForKey:@"display_version"]; +} + +- (NSDate *)dateCreated { + NSUInteger unixtime = [[[[self.metadataSections objectAtIndex:0] objectForKey:@"identity"] + objectForKey:@"started_at"] unsignedIntegerValue]; + + return [NSDate dateWithTimeIntervalSince1970:unixtime]; +} + +- (NSDate *)crashedOnDate { + if (!self.isCrash) { + return nil; + } + +#if CLS_MACH_EXCEPTION_SUPPORTED + // try the mach exception first, because it is more common + NSDate *date = [self timeFromCrashContentFile:FIRCLSReportMachExceptionFile + sectionName:@"mach_exception"]; + if (date) { + return date; + } +#endif + + return [self timeFromCrashContentFile:FIRCLSReportSignalFile sectionName:@"signal"]; +} + +- (NSDate *)timeFromCrashContentFile:(NSString *)fileName sectionName:(NSString *)sectionName { + // This works because both signal and mach exception files have the same structure to extract + // the "time" component + NSString *path = [self pathForContentFile:fileName]; + + NSNumber *timeValue = [[[[self.class readFIRCLSFileAtPath:path] objectAtIndex:0] + objectForKey:sectionName] objectForKey:@"time"]; + if (timeValue == nil) { + return nil; + } + + return [NSDate dateWithTimeIntervalSince1970:[timeValue unsignedIntegerValue]]; +} + +- (NSString *)OSVersion { + return [[[self.metadataSections objectAtIndex:1] objectForKey:@"host"] + objectForKey:@"os_display_version"]; +} + +- (NSString *)OSBuildVersion { + return [[[self.metadataSections objectAtIndex:1] objectForKey:@"host"] + objectForKey:@"os_build_version"]; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSReport.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSReport.h new file mode 100644 index 000000000..464dff736 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSReport.h @@ -0,0 +1,110 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +/** + * The CLSCrashReport protocol is deprecated. See the CLSReport class and the CrashyticsDelegate + * changes for details. + **/ +@protocol FIRCLSCrashReport <NSObject> + +@property(nonatomic, copy, readonly) NSString *identifier; +@property(nonatomic, copy, readonly) NSDictionary *customKeys; +@property(nonatomic, copy, readonly) NSString *bundleVersion; +@property(nonatomic, copy, readonly) NSString *bundleShortVersionString; +@property(nonatomic, readonly, nullable) NSDate *crashedOnDate; +@property(nonatomic, copy, readonly) NSString *OSVersion; +@property(nonatomic, copy, readonly) NSString *OSBuildVersion; + +@end + +/** + * The CLSReport exposes an interface to the phsyical report that Crashlytics has created. You can + * use this class to get information about the event, and can also set some values after the + * event has occurred. + **/ +@interface FIRCLSReport : NSObject <FIRCLSCrashReport> + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +/** + * Returns the session identifier for the report. + **/ +@property(nonatomic, copy, readonly) NSString *identifier; + +/** + * Returns the custom key value data for the report. + **/ +@property(nonatomic, copy, readonly) NSDictionary *customKeys; + +/** + * Returns the CFBundleVersion of the application that generated the report. + **/ +@property(nonatomic, copy, readonly) NSString *bundleVersion; + +/** + * Returns the CFBundleShortVersionString of the application that generated the report. + **/ +@property(nonatomic, copy, readonly) NSString *bundleShortVersionString; + +/** + * Returns the date that the report was created. + **/ +@property(nonatomic, copy, readonly) NSDate *dateCreated; + +/** + * Returns the os version that the application crashed on. + **/ +@property(nonatomic, copy, readonly) NSString *OSVersion; + +/** + * Returns the os build version that the application crashed on. + **/ +@property(nonatomic, copy, readonly) NSString *OSBuildVersion; + +/** + * Returns YES if the report contains any crash information, otherwise returns NO. + **/ +@property(nonatomic, assign, readonly) BOOL isCrash; + +/** + * You can use this method to set, after the event, additional custom keys. The rules + * and semantics for this method are the same as those documented in FIRCrashlytics.h. Be aware + * that the maximum size and count of custom keys is still enforced, and you can overwrite keys + * and/or cause excess keys to be deleted by using this method. + **/ +- (void)setObjectValue:(nullable id)value forKey:(NSString *)key; + +/** + * Record an application-specific user identifier. See FIRCrashlytics.h for details. + **/ +@property(nonatomic, copy, nullable) NSString *userIdentifier; + +/** + * Record a user name. See FIRCrashlytics.h for details. + **/ +@property(nonatomic, copy, nullable) NSString *userName; + +/** + * Record a user email. See FIRCrashlytics.h for details. + **/ +@property(nonatomic, copy, nullable) NSString *userEmail; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSReport.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSReport.m new file mode 100644 index 000000000..1b4bade64 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSReport.m @@ -0,0 +1,241 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSContext.h" +#import "FIRCLSFile.h" +#import "FIRCLSGlobals.h" +#import "FIRCLSInternalReport.h" +#import "FIRCLSReport_Private.h" +#import "FIRCLSUserLogging.h" + +@interface FIRCLSReport () { + FIRCLSInternalReport *_internalReport; + uint32_t _internalKVCounter; + uint32_t _userKVCounter; + + NSString *_internalCompactedKVFile; + NSString *_internalIncrementalKVFile; + NSString *_userCompactedKVFile; + NSString *_userIncrementalKVFile; + + BOOL _readOnly; + + // cached values, to ensure that their contents remain valid + // even if the report is deleted + NSString *_identifer; + NSString *_bundleVersion; + NSString *_bundleShortVersionString; + NSDate *_dateCreated; + NSDate *_crashedOnDate; + NSString *_OSVersion; + NSString *_OSBuildVersion; + NSNumber *_isCrash; + NSDictionary *_customKeys; +} + +@end + +@implementation FIRCLSReport + +- (instancetype)initWithInternalReport:(FIRCLSInternalReport *)report + prefetchData:(BOOL)shouldPrefetch { + self = [super init]; + if (!self) { + return nil; + } + + _internalReport = report; + + // TODO: correct kv accounting + // The internal report will have non-zero compacted and incremental keys. The right thing to do + // is count them, so we can kick off compactions/pruning at the right times. By + // setting this value to zero, we're allowing more entries to be made than there really + // should be. Not the end of the world, but we should do better eventually. + _internalKVCounter = 0; + _userKVCounter = 0; + + _internalCompactedKVFile = + [self.internalReport pathForContentFile:FIRCLSReportInternalCompactedKVFile]; + _internalIncrementalKVFile = + [self.internalReport pathForContentFile:FIRCLSReportInternalIncrementalKVFile]; + _userCompactedKVFile = [self.internalReport pathForContentFile:FIRCLSReportUserCompactedKVFile]; + _userIncrementalKVFile = + [self.internalReport pathForContentFile:FIRCLSReportUserIncrementalKVFile]; + + _readOnly = shouldPrefetch; + + if (shouldPrefetch) { + _identifer = report.identifier; + _bundleVersion = report.bundleVersion; + _bundleShortVersionString = report.bundleShortVersionString; + _dateCreated = report.dateCreated; + _crashedOnDate = report.crashedOnDate; + _OSVersion = report.OSVersion; + _OSBuildVersion = report.OSBuildVersion; + _isCrash = [NSNumber numberWithBool:report.isCrash]; + + _customKeys = [self readCustomKeys]; + } + + return self; +} + +- (instancetype)initWithInternalReport:(FIRCLSInternalReport *)report { + return [self initWithInternalReport:report prefetchData:NO]; +} + +#pragma mark - Helpers +- (FIRCLSUserLoggingKVStorage)internalKVStorage { + FIRCLSUserLoggingKVStorage storage; + + storage.maxCount = _firclsContext.readonly->logging.internalKVStorage.maxCount; + storage.maxIncrementalCount = + _firclsContext.readonly->logging.internalKVStorage.maxIncrementalCount; + storage.compactedPath = [_internalCompactedKVFile fileSystemRepresentation]; + storage.incrementalPath = [_internalIncrementalKVFile fileSystemRepresentation]; + + return storage; +} + +- (FIRCLSUserLoggingKVStorage)userKVStorage { + FIRCLSUserLoggingKVStorage storage; + + storage.maxCount = _firclsContext.readonly->logging.userKVStorage.maxCount; + storage.maxIncrementalCount = _firclsContext.readonly->logging.userKVStorage.maxIncrementalCount; + storage.compactedPath = [_userCompactedKVFile fileSystemRepresentation]; + storage.incrementalPath = [_userIncrementalKVFile fileSystemRepresentation]; + + return storage; +} + +- (BOOL)canRecordNewValues { + return !_readOnly && FIRCLSContextIsInitialized(); +} + +- (void)recordValue:(id)value forInternalKey:(NSString *)key { + if (!self.canRecordNewValues) { + return; + } + + FIRCLSUserLoggingKVStorage storage = [self internalKVStorage]; + + FIRCLSUserLoggingRecordKeyValue(key, value, &storage, &_internalKVCounter); +} + +- (void)recordValue:(id)value forUserKey:(NSString *)key { + if (!self.canRecordNewValues) { + return; + } + + FIRCLSUserLoggingKVStorage storage = [self userKVStorage]; + + FIRCLSUserLoggingRecordKeyValue(key, value, &storage, &_userKVCounter); +} + +- (NSDictionary *)readCustomKeys { + FIRCLSUserLoggingKVStorage storage = [self userKVStorage]; + + // return decoded entries + return FIRCLSUserLoggingGetCompactedKVEntries(&storage, true); +} + +#pragma mark - Metadata helpers + +- (NSString *)identifier { + if (!_identifer) { + _identifer = self.internalReport.identifier; + } + + return _identifer; +} + +- (NSDictionary *)customKeys { + if (!_customKeys) { + _customKeys = [self readCustomKeys]; + } + + return _customKeys; +} + +- (NSString *)bundleVersion { + if (!_bundleVersion) { + _bundleVersion = self.internalReport.bundleVersion; + } + + return _bundleVersion; +} + +- (NSString *)bundleShortVersionString { + if (!_bundleShortVersionString) { + _bundleShortVersionString = self.internalReport.bundleShortVersionString; + } + + return _bundleShortVersionString; +} + +- (NSDate *)dateCreated { + if (!_dateCreated) { + _dateCreated = self.internalReport.dateCreated; + } + + return _dateCreated; +} + +// for compatibility with the CLSCrashReport Protocol +- (NSDate *)crashedOnDate { + if (!_crashedOnDate) { + _crashedOnDate = self.internalReport.crashedOnDate; + } + + return _crashedOnDate; +} + +- (NSString *)OSVersion { + if (!_OSVersion) { + _OSVersion = self.internalReport.OSVersion; + } + + return _OSVersion; +} + +- (NSString *)OSBuildVersion { + if (!_OSBuildVersion) { + _OSBuildVersion = self.internalReport.OSBuildVersion; + } + + return _OSBuildVersion; +} + +- (BOOL)isCrash { + if (_isCrash == nil) { + _isCrash = [NSNumber numberWithBool:self.internalReport.isCrash]; + } + + return [_isCrash boolValue]; +} + +#pragma mark - Public Read/Write Methods +- (void)setObjectValue:(id)value forKey:(NSString *)key { + [self recordValue:value forUserKey:key]; +} + +- (NSString *)userIdentifier { + return nil; +} + +- (void)setUserIdentifier:(NSString *)userIdentifier { + [self recordValue:userIdentifier forInternalKey:FIRCLSUserIdentifierKey]; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSReport_Private.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSReport_Private.h new file mode 100644 index 000000000..0d8b67c6b --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSReport_Private.h @@ -0,0 +1,27 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSReport.h" + +@class FIRCLSInternalReport; + +@interface FIRCLSReport () + +- (instancetype)initWithInternalReport:(FIRCLSInternalReport *)report + prefetchData:(BOOL)shouldPrefetch NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithInternalReport:(FIRCLSInternalReport *)report; + +@property(nonatomic, strong, readonly) FIRCLSInternalReport *internalReport; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSettings.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSettings.h new file mode 100644 index 000000000..f45b45fd0 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSettings.h @@ -0,0 +1,134 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +#if __has_include(<FBLPromises/FBLPromises.h>) +#import <FBLPromises/FBLPromises.h> +#else +#import "FBLPromises.h" +#endif + +@class FIRCLSApplicationIdentifierModel; +@class FIRCLSFileManager; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRCLSSettings : NSObject + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)initWithFileManager:(FIRCLSFileManager *)fileManager + appIDModel:(FIRCLSApplicationIdentifierModel *)appIDModel + NS_DESIGNATED_INITIALIZER; + +/** + * Recreates the settings dictionary by re-reading the settings file from persistent storage. This + * should be called before any settings values are read, as it will populate the underlying + * settingsDictionary. If the Google App ID has changed or there is an error, delete the cache file + * and settingsDictionary. If the cache has expired, set `isCacheExpired` to true so that settings + * are re-fetched, but do not delete any values. + */ +- (void)reloadFromCacheWithGoogleAppID:(NSString *)googleAppID + currentTimestamp:(NSTimeInterval)currentTimestamp; + +/** + * Stores a separate file with the settings expiration and Google App ID it was saved with + * so that we can later determine that the settings have expired. + * + * This should be called in a background thread right after the settings.json file has been + * downloaded. + */ +- (void)cacheSettingsWithGoogleAppID:(NSString *)googleAppID + currentTimestamp:(NSTimeInterval)currentTimestamp; + +/** + * Returns true when Settings should be fetched from the server again + */ +@property(nonatomic, readonly) BOOL isCacheExpired; + +/** + * Determines how long these Settings should be respected until the SDK should fetch again + */ +@property(nonatomic, readonly) uint32_t cacheDurationSeconds; + +/** + * The Crashlytics Organization identifier of the app. Allows data continuity between + * old and new Crashlytics SDKs. + */ +@property(nonatomic, nullable, readonly) NSString *orgID; + +/** + * The backend bundle identifier of the app. Crashlytics can in some cases have + * a different bundle identifier than the app itself (eg. Crashlytics will always downcase + * the bundle ID). + */ +@property(nonatomic, nullable, readonly) NSString *fetchedBundleID; + +/** + * Indicates whether the app needs onboarding + */ +@property(nonatomic, readonly) BOOL appNeedsOnboarding; + +/** + * Indicates whether the app needs an update + */ +@property(nonatomic, readonly) BOOL appUpdateRequired; + +/** + * When this is false, Crashlytics will not start up + */ +@property(nonatomic, readonly) BOOL collectReportsEnabled; + +/** + * When this is false, Crashlytics will not collect non-fatal errors and errors + * from the custom exception / record error APIs + */ +@property(nonatomic, readonly) BOOL errorReportingEnabled; + +/** + * When this is false, Crashlytics will not collect custom exceptions from the API + */ +@property(nonatomic, readonly) BOOL customExceptionsEnabled; + +/** + * Determine if the SDK should use the new endpoint for uploading reports + */ +@property(nonatomic, readonly) BOOL shouldUseNewReportEndpoint; + +/** + * Returns the maximum number of custom exception events that will be + * recorded in a session. + */ +@property(nonatomic, readonly) uint32_t errorLogBufferSize; + +/** + * Returns the maximum size of the log buffer in bytes + */ +@property(nonatomic, readonly) uint32_t logBufferSize; + +/** + * Returns the maximum number of custom exceptions that will be collected + * in a session. + */ +@property(nonatomic, readonly) uint32_t maxCustomExceptions; + +/** + * Returns the maximum number of custom key-value pair keys (not bytes). + */ +@property(nonatomic, readonly) uint32_t maxCustomKeys; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSettings.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSettings.m new file mode 100644 index 000000000..7d1347f4e --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSettings.m @@ -0,0 +1,357 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSSettings.h" + +#if __has_include(<FBLPromises/FBLPromises.h>) +#import <FBLPromises/FBLPromises.h> +#else +#import "FBLPromises.h" +#endif + +#import "FIRCLSApplicationIdentifierModel.h" +#import "FIRCLSConstants.h" +#import "FIRCLSFileManager.h" +#import "FIRCLSLogger.h" +#import "FIRCLSURLBuilder.h" + +NSString *const CreatedAtKey = @"created_at"; +NSString *const GoogleAppIDKey = @"google_app_id"; +NSString *const BuildInstanceID = @"build_instance_id"; +NSString *const AppVersion = @"app_version"; + +@interface FIRCLSSettings () + +@property(nonatomic, strong) FIRCLSFileManager *fileManager; +@property(nonatomic, strong) FIRCLSApplicationIdentifierModel *appIDModel; + +@property(nonatomic, strong) NSDictionary<NSString *, id> *settingsDictionary; + +@property(nonatomic) BOOL isCacheKeyExpired; + +@end + +@implementation FIRCLSSettings + +- (instancetype)initWithFileManager:(FIRCLSFileManager *)fileManager + appIDModel:(FIRCLSApplicationIdentifierModel *)appIDModel { + self = [super init]; + if (!self) { + return nil; + } + + _fileManager = fileManager; + _appIDModel = appIDModel; + + _settingsDictionary = nil; + _isCacheKeyExpired = NO; + + return self; +} + +#pragma mark - Public Methods + +- (void)reloadFromCacheWithGoogleAppID:(NSString *)googleAppID + currentTimestamp:(NSTimeInterval)currentTimestamp { + NSString *settingsFilePath = self.fileManager.settingsFilePath; + + NSData *data = [self.fileManager dataWithContentsOfFile:settingsFilePath]; + + if (!data) { + FIRCLSDebugLog(@"[Crashlytics:Settings] No settings were cached"); + + return; + } + + NSError *error = nil; + @synchronized(self) { + _settingsDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; + } + + if (!_settingsDictionary) { + FIRCLSErrorLog(@"Could not load settings file data with error: %@", error.localizedDescription); + + // Attempt to remove it, in case it's messed up + [self deleteCachedSettings]; + return; + } + + NSDictionary<NSString *, id> *cacheKey = [self loadCacheKey]; + if (!cacheKey) { + FIRCLSErrorLog(@"Could not load settings cache key"); + + [self deleteCachedSettings]; + return; + } + + NSString *cachedGoogleAppID = cacheKey[GoogleAppIDKey]; + if (![cachedGoogleAppID isEqualToString:googleAppID]) { + FIRCLSDebugLog( + @"[Crashlytics:Settings] Invalidating settings cache because Google App ID changed"); + + [self deleteCachedSettings]; + return; + } + + NSTimeInterval cacheCreatedAt = [cacheKey[CreatedAtKey] unsignedIntValue]; + NSTimeInterval cacheDurationSeconds = self.cacheDurationSeconds; + if (currentTimestamp > (cacheCreatedAt + cacheDurationSeconds)) { + FIRCLSDebugLog(@"[Crashlytics:Settings] Settings TTL expired"); + + @synchronized(self) { + self.isCacheKeyExpired = YES; + } + } + + NSString *cacheBuildInstanceID = cacheKey[BuildInstanceID]; + if (![cacheBuildInstanceID isEqualToString:self.appIDModel.buildInstanceID]) { + FIRCLSDebugLog(@"[Crashlytics:Settings] Settings expired because build instance changed"); + + @synchronized(self) { + self.isCacheKeyExpired = YES; + } + } + + NSString *cacheAppVersion = cacheKey[AppVersion]; + if (![cacheAppVersion isEqualToString:self.appIDModel.synthesizedVersion]) { + FIRCLSDebugLog(@"[Crashlytics:Settings] Settings expired because app version changed"); + + @synchronized(self) { + self.isCacheKeyExpired = YES; + } + } +} + +- (void)cacheSettingsWithGoogleAppID:(NSString *)googleAppID + currentTimestamp:(NSTimeInterval)currentTimestamp { + NSNumber *createdAtTimestamp = [NSNumber numberWithDouble:currentTimestamp]; + NSDictionary *cacheKey = @{ + CreatedAtKey : createdAtTimestamp, + GoogleAppIDKey : googleAppID, + BuildInstanceID : self.appIDModel.buildInstanceID, + AppVersion : self.appIDModel.synthesizedVersion, + }; + + NSError *error = nil; + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:cacheKey + options:kNilOptions + error:&error]; + + if (!jsonData) { + FIRCLSErrorLog(@"Could not create settings cache key with error: %@", + error.localizedDescription); + + return; + } + + if ([self.fileManager fileExistsAtPath:self.fileManager.settingsCacheKeyPath]) { + [self.fileManager removeItemAtPath:self.fileManager.settingsCacheKeyPath]; + } + [self.fileManager createFileAtPath:self.fileManager.settingsCacheKeyPath + contents:jsonData + attributes:nil]; + + // If Settings were expired before, they should no longer be expired after this. + // This may be set back to YES if reloading from the cache fails + @synchronized(self) { + self.isCacheKeyExpired = NO; + } + + [self reloadFromCacheWithGoogleAppID:googleAppID currentTimestamp:currentTimestamp]; +} + +#pragma mark - Convenience Methods + +- (NSDictionary *)loadCacheKey { + NSData *cacheKeyData = + [self.fileManager dataWithContentsOfFile:self.fileManager.settingsCacheKeyPath]; + + if (!cacheKeyData) { + return nil; + } + + NSError *error = nil; + NSDictionary *cacheKey = [NSJSONSerialization JSONObjectWithData:cacheKeyData + options:NSJSONReadingAllowFragments + error:&error]; + return cacheKey; +} + +- (void)deleteCachedSettings { + __weak FIRCLSSettings *weakSelf = self; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ + __strong FIRCLSSettings *strongSelf = weakSelf; + if ([strongSelf.fileManager fileExistsAtPath:strongSelf.fileManager.settingsFilePath]) { + [strongSelf.fileManager removeItemAtPath:strongSelf.fileManager.settingsFilePath]; + } + if ([strongSelf.fileManager fileExistsAtPath:strongSelf.fileManager.settingsCacheKeyPath]) { + [strongSelf.fileManager removeItemAtPath:strongSelf.fileManager.settingsCacheKeyPath]; + } + }); + + @synchronized(self) { + self.isCacheKeyExpired = YES; + _settingsDictionary = nil; + } +} + +- (NSDictionary<NSString *, id> *)settingsDictionary { + @synchronized(self) { + return _settingsDictionary; + } +} + +#pragma mark - Settings Groups + +- (NSDictionary<NSString *, id> *)appSettings { + return self.settingsDictionary[@"app"]; +} + +- (NSDictionary<NSString *, id> *)sessionSettings { + return self.settingsDictionary[@"session"]; +} + +- (NSDictionary<NSString *, id> *)featuresSettings { + return self.settingsDictionary[@"features"]; +} + +- (NSDictionary<NSString *, id> *)fabricSettings { + return self.settingsDictionary[@"fabric"]; +} + +#pragma mark - Caching + +- (BOOL)isCacheExpired { + if (!self.settingsDictionary) { + return YES; + } + + @synchronized(self) { + return self.isCacheKeyExpired; + } +} + +- (uint32_t)cacheDurationSeconds { + id fetchedCacheDuration = self.settingsDictionary[@"cache_duration"]; + if (fetchedCacheDuration) { + return [fetchedCacheDuration unsignedIntValue]; + } + + return 60 * 60; +} + +#pragma mark - Identifiers + +- (nullable NSString *)orgID { + return self.fabricSettings[@"org_id"]; +} + +- (nullable NSString *)fetchedBundleID { + return self.fabricSettings[@"bundle_id"]; +} + +#pragma mark - Onboarding / Update + +- (NSString *)appStatus { + return self.appSettings[@"status"]; +} + +- (BOOL)appNeedsOnboarding { + return [self.appStatus isEqualToString:@"new"]; +} + +- (BOOL)appUpdateRequired { + return [[self.appSettings objectForKey:@"update_required"] boolValue]; +} + +#pragma mark - On / Off Switches + +- (BOOL)errorReportingEnabled { + NSNumber *value = [self featuresSettings][@"collect_logged_exceptions"]; + + if (value != nil) { + return [value boolValue]; + } + + return YES; +} + +- (BOOL)customExceptionsEnabled { + // Right now, recording custom exceptions from the API and + // automatically capturing non-fatal errors go hand in hand + return [self errorReportingEnabled]; +} + +- (BOOL)collectReportsEnabled { + NSNumber *value = [self featuresSettings][@"collect_reports"]; + + if (value != nil) { + return value.boolValue; + } + + return YES; +} + +- (BOOL)shouldUseNewReportEndpoint { + NSNumber *value = [self appSettings][@"report_upload_variant"]; + + // Default to use the new endpoint when settings were not successfully fetched + // or there's an unexpected issue + if (value == nil) { + return YES; + } + + // 0 - Unknown + // 1 - Legacy + // 2 - New + return value.intValue == 2; +} + +#pragma mark - Optional Limit Overrides + +- (uint32_t)errorLogBufferSize { + return [self logBufferSize]; +} + +- (uint32_t)logBufferSize { + NSNumber *value = [self sessionSettings][@"log_buffer_size"]; + + if (value != nil) { + return value.unsignedIntValue; + } + + return 64 * 1000; +} + +- (uint32_t)maxCustomExceptions { + NSNumber *value = [self sessionSettings][@"max_custom_exception_events"]; + + if (value != nil) { + return value.unsignedIntValue; + } + + return 8; +} + +- (uint32_t)maxCustomKeys { + NSNumber *value = [self sessionSettings][@"max_custom_key_value_pairs"]; + + if (value != nil) { + return value.unsignedIntValue; + } + + return 64; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSymbolResolver.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSymbolResolver.h new file mode 100644 index 000000000..a18e60467 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSymbolResolver.h @@ -0,0 +1,26 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +@class FIRStackFrame; + +@interface FIRCLSSymbolResolver : NSObject + +- (BOOL)loadBinaryImagesFromFile:(NSString *)path; + +- (FIRStackFrame *)frameForAddress:(uint64_t)address; +- (BOOL)updateStackFrame:(FIRStackFrame *)frame; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSymbolResolver.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSymbolResolver.m new file mode 100644 index 000000000..522a14ec5 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSymbolResolver.m @@ -0,0 +1,175 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSSymbolResolver.h" + +#include <dlfcn.h> + +#include "FIRCLSBinaryImage.h" +#include "FIRCLSFile.h" +#import "FIRCLSLogger.h" +#import "FIRStackFrame_Private.h" + +@interface FIRCLSSymbolResolver () { + NSMutableArray* _binaryImages; +} + +@end + +@implementation FIRCLSSymbolResolver + +- (instancetype)init { + self = [super init]; + if (!self) { + return nil; + } + + _binaryImages = [NSMutableArray array]; + + return self; +} + +- (BOOL)loadBinaryImagesFromFile:(NSString*)path { + if ([path length] == 0) { + return NO; + } + + NSArray* sections = FIRCLSFileReadSections([path fileSystemRepresentation], false, nil); + + if ([sections count] == 0) { + FIRCLSErrorLog(@"Failed to read binary image file %@", path); + return NO; + } + + // filter out unloads, as well as loads with invalid entries + for (NSDictionary* entry in sections) { + NSDictionary* details = [entry objectForKey:@"load"]; + if (!details) { + continue; + } + + // This does happen occationally and causes a crash. I'm really not sure there + // is anything sane we can do in this case. + if (![details objectForKey:@"base"] || ![details objectForKey:@"size"]) { + continue; + } + + if ([details objectForKey:@"base"] == (id)[NSNull null] || + [details objectForKey:@"size"] == (id)[NSNull null]) { + continue; + } + + [_binaryImages addObject:details]; + } + + [_binaryImages sortUsingComparator:^NSComparisonResult(id obj1, id obj2) { + NSNumber* base1 = [obj1 objectForKey:@"base"]; + NSNumber* base2 = [obj2 objectForKey:@"base"]; + + return [base1 compare:base2]; + }]; + + return YES; +} + +- (NSDictionary*)loadedBinaryImageForPC:(uintptr_t)pc { + NSUInteger index = + [_binaryImages indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL* stop) { + uintptr_t base = [[obj objectForKey:@"base"] unsignedIntegerValue]; + uintptr_t size = [[obj objectForKey:@"size"] unsignedIntegerValue]; + + return pc >= base && pc < (base + size); + }]; + + if (index == NSNotFound) { + return nil; + } + + return [_binaryImages objectAtIndex:index]; +} + +- (BOOL)fillInImageDetails:(FIRCLSBinaryImageDetails*)details forUUID:(NSString*)uuid { + if (!details || !uuid) { + return NO; + } + + return FIRCLSBinaryImageFindImageForUUID([uuid UTF8String], details); +} + +- (FIRStackFrame*)frameForAddress:(uint64_t)address { + FIRStackFrame* frame = [FIRStackFrame stackFrameWithAddress:(NSUInteger)address]; + + if (![self updateStackFrame:frame]) { + return nil; + } + + return frame; +} + +- (BOOL)updateStackFrame:(FIRStackFrame*)frame { + uint64_t address = [frame address]; + if (address == 0) { + return NO; + } + + NSDictionary* binaryImage = [self loadedBinaryImageForPC:(uintptr_t)address]; + + FIRCLSBinaryImageDetails imageDetails; + + if (![self fillInImageDetails:&imageDetails forUUID:[binaryImage objectForKey:@"uuid"]]) { +#if DEBUG + FIRCLSDebugLog(@"Image not found"); +#endif + return NO; + } + + uintptr_t addr = (uintptr_t)address - + (uintptr_t)[[binaryImage objectForKey:@"base"] unsignedIntegerValue] + + (uintptr_t)imageDetails.node.baseAddress; + Dl_info dlInfo; + + if (dladdr((void*)addr, &dlInfo) == 0) { +#if DEBUG + FIRCLSDebugLog(@"Could not look up address"); +#endif + return NO; + } + + if (addr - (uintptr_t)dlInfo.dli_saddr == 0) { + addr -= 2; + if (dladdr((void*)addr, &dlInfo) == 0) { +#if DEBUG + FIRCLSDebugLog(@"Could not look up address"); +#endif + return NO; + } + } + + if (dlInfo.dli_sname) { + NSString* symbol = [NSString stringWithUTF8String:dlInfo.dli_sname]; + + frame.symbol = symbol; + frame.rawSymbol = symbol; + } + + if (addr > (uintptr_t)dlInfo.dli_saddr) { + [frame setOffset:addr - (uintptr_t)dlInfo.dli_saddr]; + } + + [frame setLibrary:[[binaryImage objectForKey:@"path"] lastPathComponent]]; + + return YES; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordApplication.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordApplication.h new file mode 100644 index 000000000..d17bdce72 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordApplication.h @@ -0,0 +1,24 @@ +/* + * Copyright 2020 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRCLSRecordBase.h" + +@interface FIRCLSRecordApplication : FIRCLSRecordBase + +@property(nonatomic, copy) NSString *build_version; +@property(nonatomic, copy) NSString *display_version; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordApplication.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordApplication.m new file mode 100644 index 000000000..f587e1014 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordApplication.m @@ -0,0 +1,30 @@ +/* + * Copyright 2020 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRCLSRecordApplication.h" + +@implementation FIRCLSRecordApplication + +- (instancetype)initWithDict:(NSDictionary *)dict { + self = [super initWithDict:dict]; + if (self) { + _display_version = dict[@"display_version"]; + _build_version = dict[@"build_version"]; + } + return self; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordBase.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordBase.h new file mode 100644 index 000000000..a3cb6e2f8 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordBase.h @@ -0,0 +1,37 @@ +/* + * Copyright 2020 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +/** + * This is the base class to represent the data in the persisted crash (.clsrecord) files. + * The properties these subclasses are nullable on purpose. If there is an issue reading values + * from the crash files, continue as if those fields are optional so a report can still be uploaded. + * That way the issue can potentially be monitored through the backend. + **/ +@interface FIRCLSRecordBase : NSObject + +/** + * Mark the default initializer as unavailable so the subclasses do not have to add the same line + **/ +- (instancetype)init NS_UNAVAILABLE; + +/** + * All subclasses should define an initializer taking in a dictionary + **/ +- (instancetype)initWithDict:(NSDictionary *)dict; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordBase.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordBase.m new file mode 100644 index 000000000..7d591f539 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordBase.m @@ -0,0 +1,25 @@ +/* + * Copyright 2020 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRCLSRecordBase.h" + +@implementation FIRCLSRecordBase + +- (instancetype)initWithDict:(NSDictionary *)dict { + return [super init]; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordHost.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordHost.h new file mode 100644 index 000000000..652d283c1 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordHost.h @@ -0,0 +1,23 @@ +/* + * Copyright 2020 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRCLSRecordBase.h" + +@interface FIRCLSRecordHost : FIRCLSRecordBase + +@property(nonatomic, copy) NSString *platform; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordHost.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordHost.m new file mode 100644 index 000000000..67184ae68 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordHost.m @@ -0,0 +1,29 @@ +/* + * Copyright 2020 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRCLSRecordHost.h" + +@implementation FIRCLSRecordHost + +- (instancetype)initWithDict:(NSDictionary *)dict { + self = [super initWithDict:dict]; + if (self) { + _platform = dict[@"platform"]; + } + return self; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordIdentity.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordIdentity.h new file mode 100644 index 000000000..9f13fdd16 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordIdentity.h @@ -0,0 +1,24 @@ +/* + * Copyright 2020 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRCLSRecordBase.h" + +@interface FIRCLSRecordIdentity : FIRCLSRecordBase + +@property(nonatomic, copy) NSString *build_version; +@property(nonatomic, copy) NSString *install_id; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordIdentity.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordIdentity.m new file mode 100644 index 000000000..b4b547e63 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordIdentity.m @@ -0,0 +1,30 @@ +/* + * Copyright 2020 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRCLSRecordIdentity.h" + +@implementation FIRCLSRecordIdentity + +- (instancetype)initWithDict:(NSDictionary *)dict { + self = [super initWithDict:dict]; + if (self) { + _build_version = dict[@"build_version"]; + _install_id = dict[@"install_id"]; + } + return self; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter.h new file mode 100644 index 000000000..eea894814 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter.h @@ -0,0 +1,33 @@ +/* + * Copyright 2020 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +#include "crashlytics.nanopb.h" + +#import <GoogleDataTransport/GDTCOREventDataObject.h> + +/// This class is responsible for reading the persisted crash reports from disk and converting them +/// the information into the nanopb model to be used with GoogleDataTransport +@interface FIRCLSReportAdapter : NSObject <GDTCOREventDataObject> + +- (instancetype)init NS_UNAVAILABLE; + +/// Initializer +/// @param folderPath Path where the persisted crash files reside +- (instancetype)initWithPath:(NSString *)folderPath googleAppId:(NSString *)googleAppID; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter.m new file mode 100644 index 000000000..3c74691b8 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter.m @@ -0,0 +1,250 @@ +/* + * Copyright 2020 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRCLSReportAdapter.h" +#import "FIRCLSReportAdapter_Private.h" + +#import "FIRCLSInternalReport.h" +#import "FIRCLSLogger.h" + +#import "FIRCLSUserLogging.h" + +#import <nanopb/pb.h> +#import <nanopb/pb_decode.h> +#import <nanopb/pb_encode.h> + +@implementation FIRCLSReportAdapter + +- (instancetype)initWithPath:(NSString *)folderPath googleAppId:(NSString *)googleAppID { + self = [super init]; + if (self) { + _folderPath = folderPath; + _googleAppID = googleAppID; + + [self loadMetaDataFile]; + + _report = [self protoReport]; + } + return self; +} + +- (void)dealloc { + pb_release(google_crashlytics_Report_fields, &_report); +} + +// +// MARK: Load from persisted crash files +// + +/// Reads from metadata.clsrecord +- (void)loadMetaDataFile { + NSString *path = [self.folderPath stringByAppendingPathComponent:FIRCLSReportMetadataFile]; + NSDictionary *dict = [FIRCLSReportAdapter combinedDictionariesFromFilePath:path]; + + self.identity = [[FIRCLSRecordIdentity alloc] initWithDict:dict[@"identity"]]; + self.host = [[FIRCLSRecordHost alloc] initWithDict:dict[@"host"]]; + self.application = [[FIRCLSRecordApplication alloc] initWithDict:dict[@"application"]]; +} + +/// Return the persisted crash file as a combined dictionary that way lookups can occur with a key +/// (to avoid ordering dependency) +/// @param filePath Persisted crash file path ++ (NSDictionary *)combinedDictionariesFromFilePath:(NSString *)filePath { + NSMutableDictionary *joinedDict = [[NSMutableDictionary alloc] init]; + for (NSDictionary *dict in [self dictionariesFromEachLineOfFile:filePath]) { + [joinedDict addEntriesFromDictionary:dict]; + } + return joinedDict; +} + +/// The persisted crash files contains JSON on separate lines. Read each line and return the JSON +/// data as a dictionary. +/// @param filePath Persisted crash file path ++ (NSArray<NSDictionary *> *)dictionariesFromEachLineOfFile:(NSString *)filePath { + NSString *content = [[NSString alloc] initWithContentsOfFile:filePath + encoding:NSUTF8StringEncoding + error:nil]; + NSArray *lines = + [content componentsSeparatedByCharactersInSet:NSCharacterSet.newlineCharacterSet]; + + NSMutableArray<NSDictionary *> *array = [[NSMutableArray<NSDictionary *> alloc] init]; + + int lineNum = 0; + for (NSString *line in lines) { + lineNum++; + + if (line.length == 0) { + // Likely newline at the end of the file + continue; + } + + NSError *error; + NSDictionary *dict = + [NSJSONSerialization JSONObjectWithData:[line dataUsingEncoding:NSUTF8StringEncoding] + options:0 + error:&error]; + + if (error) { + FIRCLSErrorLog(@"Failed to read JSON from file (%@) line (%d) with error: %@", filePath, + lineNum, error); + } else { + [array addObject:dict]; + } + } + + return array; +} + +// +// MARK: GDTCOREventDataObject +// + +- (NSData *)transportBytes { + pb_ostream_t sizestream = PB_OSTREAM_SIZING; + + // Encode 1 time to determine the size. + if (!pb_encode(&sizestream, google_crashlytics_Report_fields, &_report)) { + FIRCLSErrorLog(@"Error in nanopb encoding for size: %s", PB_GET_ERROR(&sizestream)); + } + + // Encode a 2nd time to actually get the bytes from it. + size_t bufferSize = sizestream.bytes_written; + CFMutableDataRef dataRef = CFDataCreateMutable(CFAllocatorGetDefault(), bufferSize); + CFDataSetLength(dataRef, bufferSize); + pb_ostream_t ostream = pb_ostream_from_buffer((void *)CFDataGetBytePtr(dataRef), bufferSize); + if (!pb_encode(&ostream, google_crashlytics_Report_fields, &_report)) { + FIRCLSErrorLog(@"Error in nanopb encoding for bytes: %s", PB_GET_ERROR(&ostream)); + } + + return CFBridgingRelease(dataRef); +} + +// +// MARK: NanoPB conversions +// + +- (google_crashlytics_Report)protoReport { + google_crashlytics_Report report = google_crashlytics_Report_init_default; + report.sdk_version = FIRCLSEncodeString(self.identity.build_version); + report.gmp_app_id = FIRCLSEncodeString(self.googleAppID); + report.platform = [self protoPlatformFromString:self.host.platform]; + report.installation_uuid = FIRCLSEncodeString(self.identity.install_id); + report.build_version = FIRCLSEncodeString(self.application.build_version); + report.display_version = FIRCLSEncodeString(self.application.display_version); + report.apple_payload = [self protoFilesPayload]; + return report; +} + +- (google_crashlytics_FilesPayload)protoFilesPayload { + google_crashlytics_FilesPayload apple_payload = google_crashlytics_FilesPayload_init_default; + + NSArray<NSString *> *clsRecords = [self clsRecordFilePaths]; + google_crashlytics_FilesPayload_File *files = + malloc(sizeof(google_crashlytics_FilesPayload_File) * clsRecords.count); + + if (files == NULL) { + // files and files_count are initialized to NULL and 0 by default. + return apple_payload; + } + for (NSUInteger i = 0; i < clsRecords.count; i++) { + google_crashlytics_FilesPayload_File file = google_crashlytics_FilesPayload_File_init_default; + file.filename = FIRCLSEncodeString(clsRecords[i].lastPathComponent); + + NSError *error; + file.contents = FIRCLSEncodeData([NSData dataWithContentsOfFile:clsRecords[i] + options:0 + error:&error]); + if (error) { + FIRCLSErrorLog(@"Failed to read from %@ with error: %@", clsRecords[i], error); + } + + files[i] = file; + } + + apple_payload.files = files; + apple_payload.files_count = (pb_size_t)clsRecords.count; + + return apple_payload; +} + +- (NSArray<NSString *> *)clsRecordFilePaths { + NSMutableArray<NSString *> *clsRecords = [[NSMutableArray<NSString *> alloc] init]; + + NSError *error; + NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:self.folderPath + error:&error]; + + if (error) { + FIRCLSErrorLog(@"Failed to find .clsrecords from %@ with error: %@", self.folderPath, error); + return clsRecords; + } + + [files enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + NSString *filename = (NSString *)obj; + NSString *lowerExtension = filename.pathExtension.lowercaseString; + if ([lowerExtension isEqualToString:@"clsrecord"] || + [lowerExtension isEqualToString:@"symbolicated"]) { + [clsRecords addObject:[self.folderPath stringByAppendingPathComponent:filename]]; + } + }]; + + return [clsRecords sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; +} + +- (google_crashlytics_Platforms)protoPlatformFromString:(NSString *)str { + NSString *platform = str.lowercaseString; + + if ([platform isEqualToString:@"ios"]) { + return google_crashlytics_Platforms_IOS; + } else if ([platform isEqualToString:@"mac"]) { + return google_crashlytics_Platforms_MAC_OS_X; + } else if ([platform isEqualToString:@"tvos"]) { + return google_crashlytics_Platforms_TVOS; + } else { + return google_crashlytics_Platforms_UNKNOWN_PLATFORM; + } +} + +/** Mallocs a pb_bytes_array and copies the given NSString's bytes into the bytes array. + * @note Memory needs to be freed manually, through pb_free or pb_release. + * @param string The string to encode as pb_bytes. + */ +pb_bytes_array_t *FIRCLSEncodeString(NSString *string) { + if ([string isMemberOfClass:[NSNull class]]) { + FIRCLSErrorLog(@"Expected encodable string, but found NSNull instead. " + @"Set a symbolic breakpoint at FIRCLSEncodeString to debug."); + string = nil; + } + NSString *stringToEncode = string ? string : @""; + NSData *stringBytes = [stringToEncode dataUsingEncoding:NSUTF8StringEncoding]; + return FIRCLSEncodeData(stringBytes); +} + +/** Mallocs a pb_bytes_array and copies the given NSData bytes into the bytes array. + * @note Memory needs to be free manually, through pb_free or pb_release. + * @param data The data to copy into the new bytes array. + */ +pb_bytes_array_t *FIRCLSEncodeData(NSData *data) { + pb_bytes_array_t *pbBytes = malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(data.length)); + if (pbBytes == NULL) { + return NULL; + } + memcpy(pbBytes->bytes, [data bytes], data.length); + pbBytes->size = (pb_size_t)data.length; + return pbBytes; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter_Private.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter_Private.h new file mode 100644 index 000000000..e9f2c1606 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter_Private.h @@ -0,0 +1,43 @@ +/* + * Copyright 2020 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRCLSReportAdapter.h" + +#import "FIRCLSRecordApplication.h" +#import "FIRCLSRecordHost.h" +#import "FIRCLSRecordIdentity.h" + +pb_bytes_array_t *FIRCLSEncodeString(NSString *string); +pb_bytes_array_t *FIRCLSEncodeData(NSData *data); + +@interface FIRCLSReportAdapter () + +@property(nonatomic, readonly) BOOL hasCrashed; + +@property(nonatomic, strong) NSString *folderPath; +@property(nonatomic, strong) NSString *googleAppID; + +// From metadata.clsrecord +@property(nonatomic, strong) FIRCLSRecordIdentity *identity; +@property(nonatomic, strong) FIRCLSRecordHost *host; +@property(nonatomic, strong) FIRCLSRecordApplication *application; + +@property(nonatomic) google_crashlytics_Report report; + +- (google_crashlytics_Report)protoReport; +- (NSArray<NSString *> *)clsRecordFilePaths; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/FIRCLSAsyncOperation.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/FIRCLSAsyncOperation.h new file mode 100644 index 000000000..5636d3d09 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/FIRCLSAsyncOperation.h @@ -0,0 +1,23 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +typedef void (^FIRCLSAsyncOperationCompletionBlock)(NSError* error); + +@interface FIRCLSAsyncOperation : NSOperation + +@property(copy, nonatomic) FIRCLSAsyncOperationCompletionBlock asyncCompletion; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/FIRCLSAsyncOperation.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/FIRCLSAsyncOperation.m new file mode 100644 index 000000000..94415f14e --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/FIRCLSAsyncOperation.m @@ -0,0 +1,135 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSAsyncOperation.h" + +@interface FIRCLSAsyncOperation () { + BOOL _internalExecuting; + BOOL _internalFinished; +} + +@property(nonatomic, strong) NSRecursiveLock *lock; + +@end + +@implementation FIRCLSAsyncOperation + +- (instancetype)init { + self = [super init]; + if (!self) { + return nil; + } + + _internalExecuting = NO; + _internalFinished = NO; + + self.lock = [[NSRecursiveLock alloc] init]; + self.lock.name = @"com.crashlytics.async-operation-lock"; + + return self; +} + +#pragma mark - NSOperation Overrides +- (BOOL)isConcurrent { + return YES; +} + +- (BOOL)isAsynchronous { + return YES; +} + +- (BOOL)isExecuting { + [self.lock lock]; + BOOL result = _internalExecuting; + [self.lock unlock]; + + return result; +} + +- (BOOL)isFinished { + [self.lock lock]; + BOOL result = _internalFinished; + [self.lock unlock]; + + return result; +} + +- (void)start { + if ([self checkForCancellation]) { + return; + } + + [self markStarted]; + + [self main]; +} + +#pragma mark - Utilities +- (void)changeValueForKey:(NSString *)key inBlock:(void (^)(void))block { + [self willChangeValueForKey:key]; + block(); + [self didChangeValueForKey:key]; +} + +- (void)lock:(void (^)(void))block { + [self.lock lock]; + block(); + [self.lock unlock]; +} + +- (BOOL)checkForCancellation { + if ([self isCancelled]) { + [self markDone]; + return YES; + } + + return NO; +} + +#pragma mark - State Management +- (void)unlockedMarkFinished { + [self changeValueForKey:@"isFinished" + inBlock:^{ + self->_internalFinished = YES; + }]; +} + +- (void)unlockedMarkStarted { + [self changeValueForKey:@"isExecuting" + inBlock:^{ + self->_internalExecuting = YES; + }]; +} + +- (void)unlockedMarkComplete { + [self changeValueForKey:@"isExecuting" + inBlock:^{ + self->_internalExecuting = NO; + }]; +} + +- (void)markStarted { + [self lock:^{ + [self unlockedMarkStarted]; + }]; +} + +- (void)markDone { + [self lock:^{ + [self unlockedMarkComplete]; + [self unlockedMarkFinished]; + }]; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/FIRCLSAsyncOperation_Private.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/FIRCLSAsyncOperation_Private.h new file mode 100644 index 000000000..1135ed75b --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/FIRCLSAsyncOperation_Private.h @@ -0,0 +1,24 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSAsyncOperation.h" + +@interface FIRCLSAsyncOperation (Private) + +- (void)markStarted; +- (void)markDone; + +- (BOOL)checkForCancellation; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSPackageReportOperation.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSPackageReportOperation.h new file mode 100644 index 000000000..5822e7527 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSPackageReportOperation.h @@ -0,0 +1,35 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +@class FIRCLSInternalReport; +@class FIRCLSFileManager; +@class FIRCLSSettings; + +@interface FIRCLSPackageReportOperation : NSOperation + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)initWithReport:(FIRCLSInternalReport *)report + fileManager:(FIRCLSFileManager *)fileManager + settings:(FIRCLSSettings *)settings NS_DESIGNATED_INITIALIZER; + +@property(nonatomic, readonly) FIRCLSInternalReport *report; +@property(nonatomic, readonly) FIRCLSFileManager *fileManager; +@property(nonatomic, readonly) FIRCLSSettings *settings; + +@property(nonatomic, copy, readonly) NSString *finalPath; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSPackageReportOperation.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSPackageReportOperation.m new file mode 100644 index 000000000..aaf4c2a16 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSPackageReportOperation.m @@ -0,0 +1,210 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSPackageReportOperation.h" + +#include <errno.h> +#include <zlib.h> + +#import "FIRCLSFileManager.h" +#import "FIRCLSInternalReport.h" + +#import "FIRCLSUtility.h" + +#import "FIRCLSByteUtility.h" +#import "FIRCLSMultipartMimeStreamEncoder.h" + +#import "FIRCLSSettings.h" + +@interface FIRCLSPackageReportOperation () + +@property(nonatomic, copy) NSString *finalPath; + +@end + +@implementation FIRCLSPackageReportOperation + +- (instancetype)initWithReport:(FIRCLSInternalReport *)report + fileManager:(FIRCLSFileManager *)fileManager + settings:(FIRCLSSettings *)settings { + self = [super init]; + if (!self) { + return nil; + } + + _report = report; + _fileManager = fileManager; + _settings = settings; + + return self; +} + +- (BOOL)compressData:(NSData *)data toPath:(NSString *)path { + gzFile file = gzopen([path fileSystemRepresentation], "w"); + if (file == Z_NULL) { + FIRCLSSDKLogError("Error: unable to open file for compression %s\n", strerror(errno)); + return NO; + } + + __block BOOL success = [data length] > 0; + + FIRCLSEnumerateByteRangesOfNSDataUsingBlock( + data, ^(const void *bytes, NSRange byteRange, BOOL *stop) { + size_t length = byteRange.length; + + if (![self writeBytes:bytes length:length toGZFile:file]) { + *stop = YES; + success = NO; + } + }); + + gzclose(file); + + return success; +} + +- (BOOL)writeBytes:(const void *)buffer length:(size_t)length toGZFile:(gzFile)file { + return FIRCLSFileLoopWithWriteBlock( + buffer, length, ^ssize_t(const void *partialBuffer, size_t partialLength) { + errno = 0; + int ret = gzwrite(file, buffer, (unsigned int)length); + + if (ret == 0) { + int zerror = 0; + const char *errorString = gzerror(file, &zerror); + + FIRCLSSDKLogError("Error: failed to write compressed bytes %d, %s, %s \n", zerror, + errorString, strerror(errno)); + } + + return ret; + }); +} + +- (NSString *)reportPath { + return [self.report path]; +} + +- (NSString *)destinationDirectory { + return [self.fileManager legacyPreparedPath]; +} + +- (NSString *)packagedPathWithName:(NSString *)name { + // the output file will use the boundary as the filename, and "multipartmime" as the extension + return [[self.destinationDirectory stringByAppendingPathComponent:name] + stringByAppendingPathExtension:@"multipartmime"]; +} + +- (void)main { + NSString *reportOrgID = self.settings.orgID; + if (!reportOrgID) { + FIRCLSDebugLog( + @"[Crashlytics:PackageReport] Skipping packaging of report with id '%@' this run of the " + @"app because Organization ID was nil. Report will upload once settings are download " + @"successfully", + self.report.identifier); + + return; + } + + self.finalPath = nil; + + NSString *boundary = [FIRCLSMultipartMimeStreamEncoder generateBoundary]; + NSString *destPath = [self packagedPathWithName:boundary]; + + // try to read the metadata file, which could always fail + NSString *reportSessionId = self.report.identifier; + + NSOutputStream *stream = [NSOutputStream outputStreamToFileAtPath:destPath append:NO]; + + FIRCLSMultipartMimeStreamEncoder *encoder = + [FIRCLSMultipartMimeStreamEncoder encoderWithStream:stream andBoundary:boundary]; + if (!encoder) { + return; + } + + [encoder encode:^{ + [encoder addValue:reportOrgID fieldName:@"org_id"]; + + if (reportSessionId) { + [encoder addValue:reportSessionId fieldName:@"report_id"]; + } + + [self.fileManager + enumerateFilesInDirectory:self.reportPath + usingBlock:^(NSString *filePath, NSString *extension) { + if (self.cancelled) { + return; + } + + // Do not package or include already gz'ed files. These can get left over + // from previously-submitted reports. There's an opportinity here to avoid + // compressed certain types of files that cannot be changed. + if ([extension isEqualToString:@"gz"]) { + return; + } + + NSData *data = [NSData dataWithContentsOfFile:filePath + options:0 + error:nil]; + if ([data length] == 0) { + const char *filename = [[filePath lastPathComponent] UTF8String]; + + FIRCLSSDKLogError("Error: unable to read data for compression: %s\n", + filename); + return; + } + + [self encode:encoder data:data fromPath:filePath]; + }]; + }]; + + if (self.cancelled) { + [self.fileManager removeItemAtPath:destPath]; + return; + } + + self.finalPath = destPath; +} + +- (void)encode:(FIRCLSMultipartMimeStreamEncoder *)encoder + data:(NSData *)data + fromPath:(NSString *)path { + // must be non-nil and > 0 length + if ([path length] == 0) { + FIRCLSSDKLogError("Error: path is invalid\n"); + return; + } + + NSString *uploadPath = [path stringByAppendingPathExtension:@"gz"]; + NSString *fieldname = [path lastPathComponent]; + NSString *filename = [uploadPath lastPathComponent]; + NSString *mimeType = @"application/x-gzip"; + + // first, attempt to compress + if (![self compressData:data toPath:uploadPath]) { + FIRCLSSDKLogError("Error: compression failed for %s\n", [filename UTF8String]); + + // attempt the upload without compression + mimeType = @"text/plain"; + uploadPath = path; + } + + [encoder addFile:[NSURL fileURLWithPath:uploadPath] + fileName:filename + mimeType:mimeType + fieldName:fieldname]; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSProcessReportOperation.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSProcessReportOperation.h new file mode 100644 index 000000000..1e9028636 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSProcessReportOperation.h @@ -0,0 +1,30 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +@class FIRCLSInternalReport; +@class FIRCLSSymbolResolver; + +@interface FIRCLSProcessReportOperation : NSOperation + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)initWithReport:(FIRCLSInternalReport *)report + resolver:(FIRCLSSymbolResolver *)resolver NS_DESIGNATED_INITIALIZER; + +@property(nonatomic, readonly) FIRCLSSymbolResolver *symbolResolver; +@property(nonatomic, readonly) FIRCLSInternalReport *report; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSProcessReportOperation.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSProcessReportOperation.m new file mode 100644 index 000000000..12ce601d6 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSProcessReportOperation.m @@ -0,0 +1,113 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSProcessReportOperation.h" + +#import "FIRCLSDemangleOperation.h" +#import "FIRCLSFile.h" +#import "FIRCLSInternalReport.h" +#import "FIRCLSSerializeSymbolicatedFramesOperation.h" +#import "FIRCLSSymbolResolver.h" +#import "FIRCLSSymbolicationOperation.h" +#import "FIRStackFrame_Private.h" + +@implementation FIRCLSProcessReportOperation + +- (instancetype)initWithReport:(FIRCLSInternalReport *)report + resolver:(FIRCLSSymbolResolver *)resolver { + self = [super init]; + if (!self) { + return nil; + } + + _report = report; + _symbolResolver = resolver; + + return self; +} + +- (NSString *)binaryImagePath { + return self.report.binaryImagePath; +} + +- (NSArray *)threadArrayFromFile:(NSString *)path { + NSArray *threads = + FIRCLSFileReadSections([path fileSystemRepresentation], false, ^NSObject *(id obj) { + // use this to select out the one entry that has a "threads" top-level entry + return [obj objectForKey:@"threads"]; + }); + + if ([threads count] == 0) { + return nil; + } + + // threads is actually an array of arrays + threads = [threads objectAtIndex:0]; + if (!threads) { + return nil; + } + + NSMutableArray *threadArray = [NSMutableArray array]; + + for (NSDictionary *threadDetails in threads) { + NSMutableArray *frameArray = [NSMutableArray array]; + + for (NSNumber *pc in [threadDetails objectForKey:@"stacktrace"]) { + FIRStackFrame *frame = [FIRStackFrame stackFrameWithAddress:[pc unsignedIntegerValue]]; + + [frameArray addObject:frame]; + } + + [threadArray addObject:frameArray]; + } + + return threadArray; +} + +- (BOOL)symbolicateFile:(NSString *)path withResolver:(FIRCLSSymbolResolver *)resolver { + NSArray *threadArray = [self threadArrayFromFile:path]; + if (!threadArray) { + return NO; + } + + FIRCLSSymbolicationOperation *symbolicationOp = [[FIRCLSSymbolicationOperation alloc] init]; + [symbolicationOp setThreadArray:threadArray]; + [symbolicationOp setSymbolResolver:resolver]; + + FIRCLSDemangleOperation *demangleOp = [[FIRCLSDemangleOperation alloc] init]; + [demangleOp setThreadArray:threadArray]; + + FIRCLSSerializeSymbolicatedFramesOperation *serializeOp = + [[FIRCLSSerializeSymbolicatedFramesOperation alloc] init]; + [serializeOp setThreadArray:threadArray]; + [serializeOp setOutputPath:[path stringByAppendingPathExtension:@"symbolicated"]]; + + [symbolicationOp start]; + [demangleOp start]; + [serializeOp start]; + + return YES; +} + +- (void)main { + if (![self.symbolResolver loadBinaryImagesFromFile:self.binaryImagePath]) { + return; + } + + [self.report enumerateSymbolicatableFilesInContent:^(NSString *path) { + [self symbolicateFile:path withResolver:self.symbolResolver]; + }]; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSDemangleOperation.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSDemangleOperation.h new file mode 100644 index 000000000..b26b87cd7 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSDemangleOperation.h @@ -0,0 +1,24 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSThreadArrayOperation.h" + +@interface FIRCLSDemangleOperation : FIRCLSThreadArrayOperation + ++ (NSString *)demangleSymbol:(const char *)symbol; ++ (NSString *)demangleCppSymbol:(const char *)symbol; + +- (NSString *)demangleSymbol:(const char *)symbol; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSDemangleOperation.mm b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSDemangleOperation.mm new file mode 100644 index 000000000..364a6ed6d --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSDemangleOperation.mm @@ -0,0 +1,96 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSDemangleOperation.h" +#include "FIRStackFrame_Private.h" + +#import <cxxabi.h> + +@implementation FIRCLSDemangleOperation + ++ (NSString *)demangleSymbol:(const char *)symbol { + if (!symbol) { + return nil; + } + + if (strncmp(symbol, "_Z", 2) == 0) { + return [self demangleCppSymbol:symbol]; + } else if (strncmp(symbol, "__Z", 3) == 0) { + return [self demangleBlockInvokeCppSymbol:symbol]; + } + + return nil; +} + ++ (NSString *)demangleBlockInvokeCppSymbol:(const char *)symbol { + NSString *string = [NSString stringWithUTF8String:symbol]; + + // search backwards, because this string should be at the end + NSRange range = [string rangeOfString:@"_block_invoke" options:NSBackwardsSearch]; + + if (range.location == NSNotFound) { + return nil; + } + + // we need at least a "_Z..." for a valid C++ symbol, so make sure of that + if (range.location < 5) { + return nil; + } + + // extract the mangled C++ symbol from the string + NSString *cppSymbol = [string substringWithRange:NSMakeRange(1, range.location - 1)]; + cppSymbol = [self demangleSymbol:[cppSymbol UTF8String]]; + if (!cppSymbol) { + return nil; + } + + // extract out just the "_block_invoke..." part + string = + [string substringWithRange:NSMakeRange(range.location, [string length] - range.location)]; + + // and glue that onto the end + return [cppSymbol stringByAppendingString:string]; +} + ++ (NSString *)demangleCppSymbol:(const char *)symbol { + int status; + char *buffer = NULL; + + buffer = __cxxabiv1::__cxa_demangle(symbol, buffer, NULL, &status); + if (!buffer) { + return nil; + } + + NSString *result = [NSString stringWithUTF8String:buffer]; + + free(buffer); + + return result; +} + +- (NSString *)demangleSymbol:(const char *)symbol { + return [[self class] demangleSymbol:symbol]; +} + +- (void)main { + [self enumerateFramesWithBlock:^(FIRStackFrame *frame) { + NSString *demangedSymbol = [self demangleSymbol:[[frame rawSymbol] UTF8String]]; + + if (demangedSymbol) { + [frame setSymbol:demangedSymbol]; + } + }]; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSerializeSymbolicatedFramesOperation.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSerializeSymbolicatedFramesOperation.h new file mode 100644 index 000000000..b73c67cdc --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSerializeSymbolicatedFramesOperation.h @@ -0,0 +1,21 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSThreadArrayOperation.h" + +@interface FIRCLSSerializeSymbolicatedFramesOperation : FIRCLSThreadArrayOperation + +@property(nonatomic, copy) NSString *outputPath; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSerializeSymbolicatedFramesOperation.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSerializeSymbolicatedFramesOperation.m new file mode 100644 index 000000000..b8701d261 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSerializeSymbolicatedFramesOperation.m @@ -0,0 +1,63 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSSerializeSymbolicatedFramesOperation.h" + +#import "FIRCLSFile.h" +#import "FIRCLSLogger.h" +#import "FIRStackFrame_Private.h" + +@implementation FIRCLSSerializeSymbolicatedFramesOperation + +- (void)main { + FIRCLSFile file; + + // Make sure not to open in append mode, so we can overwrite any pre-existing symbolication + // files. + if (!FIRCLSFileInitWithPathMode(&file, [self.outputPath fileSystemRepresentation], false, + false)) { + FIRCLSErrorLog(@"Failed to create output file"); + return; + } + + FIRCLSFileWriteSectionStart(&file, "threads"); + FIRCLSFileWriteArrayStart(&file); + + for (NSArray *frameArray in self.threadArray) { + FIRCLSFileWriteArrayStart(&file); + + for (FIRStackFrame *frame in frameArray) { + FIRCLSFileWriteHashStart(&file); + FIRCLSFileWriteHashEntryString(&file, "symbol", [[frame symbol] UTF8String]); + + // only include this field if it is present and different + if (![[frame rawSymbol] isEqualToString:[frame symbol]]) { + FIRCLSFileWriteHashEntryString(&file, "raw_symbol", [[frame rawSymbol] UTF8String]); + } + + FIRCLSFileWriteHashEntryUint64(&file, "offset", [frame offset]); + FIRCLSFileWriteHashEntryString(&file, "library", [[frame library] UTF8String]); + + FIRCLSFileWriteHashEnd(&file); + } + + FIRCLSFileWriteArrayEnd(&file); + } + + FIRCLSFileWriteArrayEnd(&file); + FIRCLSFileWriteSectionEnd(&file); + FIRCLSFileClose(&file); +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSymbolicationOperation.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSymbolicationOperation.h new file mode 100644 index 000000000..7c63e20e9 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSymbolicationOperation.h @@ -0,0 +1,23 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSThreadArrayOperation.h" + +@class FIRCLSSymbolResolver; + +@interface FIRCLSSymbolicationOperation : FIRCLSThreadArrayOperation + +@property(nonatomic, strong) FIRCLSSymbolResolver *symbolResolver; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSymbolicationOperation.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSymbolicationOperation.m new file mode 100644 index 000000000..d15005bbe --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSymbolicationOperation.m @@ -0,0 +1,27 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSSymbolicationOperation.h" + +#import "FIRCLSSymbolResolver.h" + +@implementation FIRCLSSymbolicationOperation + +- (void)main { + [self enumerateFramesWithBlock:^(FIRStackFrame *frame) { + [self.symbolResolver updateStackFrame:frame]; + }]; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSThreadArrayOperation.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSThreadArrayOperation.h new file mode 100644 index 000000000..0c2a1df54 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSThreadArrayOperation.h @@ -0,0 +1,25 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +@class FIRStackFrame; + +@interface FIRCLSThreadArrayOperation : NSOperation + +@property(nonatomic, strong) NSArray *threadArray; + +- (void)enumerateFramesWithBlock:(void (^)(FIRStackFrame *frame))block; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSThreadArrayOperation.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSThreadArrayOperation.m new file mode 100644 index 000000000..3f7509e7e --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSThreadArrayOperation.m @@ -0,0 +1,31 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSThreadArrayOperation.h" + +@implementation FIRCLSThreadArrayOperation + +- (void)enumerateFramesWithBlock:(void (^)(FIRStackFrame *frame))block { + for (NSArray *frameArray in self.threadArray) { + for (FIRStackFrame *frame in frameArray) { + block(frame); + + if ([self isCancelled]) { + break; + } + } + } +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Private/FIRExceptionModel_Private.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Private/FIRExceptionModel_Private.h new file mode 100644 index 000000000..7cd161a95 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Private/FIRExceptionModel_Private.h @@ -0,0 +1,33 @@ +// Copyright 2020 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef FIRExceptionModel_Private_h +#define FIRExceptionModel_Private_h + +#import <Foundation/Foundation.h> + +#import "FIRExceptionModel.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRExceptionModel (Private) + +@property(nonatomic, copy) NSString *name; +@property(nonatomic, copy) NSString *reason; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* FIRExceptionModel_Private_h */ diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Private/FIRStackFrame_Private.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Private/FIRStackFrame_Private.h new file mode 100644 index 000000000..d4c0a44c9 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Private/FIRStackFrame_Private.h @@ -0,0 +1,44 @@ +// Copyright 2020 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +#import "FIRStackFrame.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * This class is used in conjunction with recordExceptionModel to record information about + * non-ObjC/C++ exceptions. All information included here will be displayed in the Crashlytics UI, + * and can influence crash grouping. Be particularly careful with the use of the address property. + *If set, Crashlytics will attempt symbolication and could overwrite other properities in the + *process. + **/ +@interface FIRStackFrame (Private) + ++ (instancetype)stackFrame; ++ (instancetype)stackFrameWithAddress:(NSUInteger)address; ++ (instancetype)stackFrameWithSymbol:(NSString *)symbol; + +@property(nonatomic, copy, nullable) NSString *symbol; +@property(nonatomic, copy, nullable) NSString *rawSymbol; +@property(nonatomic, copy, nullable) NSString *library; +@property(nonatomic, copy, nullable) NSString *fileName; +@property(nonatomic, assign) uint32_t lineNumber; +@property(nonatomic, assign) uint64_t offset; +@property(nonatomic, assign) uint64_t address; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FIRCrashlytics.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FIRCrashlytics.h new file mode 100644 index 000000000..9f651537b --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FIRCrashlytics.h @@ -0,0 +1,192 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +#import "FIRExceptionModel.h" + +#if __has_include(<Crashlytics/Crashlytics.h>) +#warning "FirebaseCrashlytics and Crashlytics are not compatible \ +in the same app because including multiple crash reporters can \ +cause problems when registering exception handlers." +#endif + +NS_ASSUME_NONNULL_BEGIN + +/** + * The Firebase Crashlytics API provides methods to annotate and manage fatal and + * non-fatal reports captured and reported to Firebase Crashlytics. + * + * By default, Firebase Crashlytics is initialized with `[FIRApp configure]`. + * + * Note: The Crashlytics class cannot be subclassed. If this makes testing difficult, + * we suggest using a wrapper class or a protocol extension. + */ +NS_SWIFT_NAME(Crashlytics) +@interface FIRCrashlytics : NSObject + +/** :nodoc: */ +- (instancetype)init NS_UNAVAILABLE; + +/** + * Accesses the singleton Crashlytics instance. + * + * @return The singleton Crashlytics instance. + */ ++ (instancetype)crashlytics NS_SWIFT_NAME(crashlytics()); + +/** + * Adds logging that is sent with your crash data. The logging does not appear in the + * system.log and is only visible in the Crashlytics dashboard. + * + * @param msg Message to log + */ +- (void)log:(NSString *)msg; + +/** + * Adds logging that is sent with your crash data. The logging does not appear in the + * system.log and is only visible in the Crashlytics dashboard. + * + * @param format Format of string + * @param ... A comma-separated list of arguments to substitute into format + */ +- (void)logWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1, 2); + +/** + * Adds logging that is sent with your crash data. The logging does not appear in the + * system.log and is only visible in the Crashlytics dashboard. + * + * @param format Format of string + * @param args Arguments to substitute into format + */ +- (void)logWithFormat:(NSString *)format + arguments:(va_list)args NS_SWIFT_NAME(log(format:arguments:)); + +/** + * Sets a custom key and value to be associated with subsequent fatal and non-fatal reports. + * When setting an object value, the object is converted to a string. This is + * typically done by calling "-[NSObject description]". + * + * @param value The value to be associated with the key + * @param key A unique key + */ +- (void)setCustomValue:(id)value forKey:(NSString *)key; + +/** + * Records a user ID (identifier) that's associated with subsequent fatal and non-fatal reports. + * + * If you want to associate a crash with a specific user, we recommend specifying an arbitrary + * string (e.g., a database, ID, hash, or other value that you can index and query, but is + * meaningless to a third-party observer). This allows you to facilitate responses for support + * requests and reach out to users for more information. + * + * @param userID An arbitrary user identifier string that associates a user to a record in your + * system. + */ +- (void)setUserID:(NSString *)userID; + +/** + * Records a non-fatal event described by an NSError object. The events are + * grouped and displayed similarly to crashes. Keep in mind that this method can be expensive. + * The total number of NSErrors that can be recorded during your app's life-cycle is limited by a + * fixed-size circular buffer. If the buffer is overrun, the oldest data is dropped. Errors are + * relayed to Crashlytics on a subsequent launch of your application. + * + * @param error Non-fatal error to be recorded + */ +- (void)recordError:(NSError *)error NS_SWIFT_NAME(record(error:)); + +/** + * Records an Exception Model described by an FIRExceptionModel object. The events are + * grouped and displayed similarly to crashes. Keep in mind that this method can be expensive. + * The total number of FIRExceptionModels that can be recorded during your app's life-cycle is + * limited by a fixed-size circular buffer. If the buffer is overrun, the oldest data is dropped. + * Exception Models are relayed to Crashlytics on a subsequent launch of your application. + * + * @param exceptionModel Instance of the FIRExceptionModel to be recorded + */ +- (void)recordExceptionModel:(FIRExceptionModel *)exceptionModel + NS_SWIFT_NAME(record(exceptionModel:)); + +/** + * Returns whether the app crashed during the previous execution. + */ +- (BOOL)didCrashDuringPreviousExecution; + +/** + * Enables/disables automatic data collection. + * + * Calling this method overrides both the FirebaseCrashlyticsCollectionEnabled flag in your + * App's Info.plist and FIRApp's isDataCollectionDefaultEnabled flag. + * + * When you set a value for this method, it persists across runs of the app. + * + * The value does not apply until the next run of the app. If you want to disable data + * collection without rebooting, add the FirebaseCrashlyticsCollectionEnabled flag to your app's + * Info.plist. + * * + * @param enabled Determines whether automatic data collection is enabled + */ +- (void)setCrashlyticsCollectionEnabled:(BOOL)enabled; + +/** + * Indicates whether or not automatic data collection is enabled + * + * This method uses three ways to decide whether automatic data collection is enabled, + * in order of priority: + * - If setCrashlyticsCollectionEnabled iscalled with a value, use it + * - If the FirebaseCrashlyticsCollectionEnabled key is in your app's Info.plist, use it + * - Otherwise, use the default isDataCollectionDefaultEnabled in FIRApp + */ +- (BOOL)isCrashlyticsCollectionEnabled; + +/** + * Determines whether there are any unsent crash reports cached on the device, then calls the given + * callback. + * + * The callback only executes if automatic data collection is disabled. You can use + * the callback to get one-time consent from a user upon a crash, and then call + * sendUnsentReports or deleteUnsentReports, depending on whether or not the user gives consent. + * + * Disable automatic collection by: + * - Adding the FirebaseCrashlyticsCollectionEnabled: NO key to your App's Info.plist + * - Calling [[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:NO] in your app + * - Setting FIRApp's isDataCollectionDefaultEnabled to NO + * + * @param completion The callback that's executed once Crashlytics finishes checking for unsent + * reports. The callback is set to YES if there are unsent reports on disk. + */ +- (void)checkForUnsentReportsWithCompletion:(void (^)(BOOL))completion + NS_SWIFT_NAME(checkForUnsentReports(completion:)); + +/** + * Enqueues any unsent reports on the device to upload to Crashlytics. + * + * This method only applies if automatic data collection is disabled. + * + * When automatic data collection is enabled, Crashlytics automatically uploads and deletes reports + * at startup, so this method is ignored. + */ +- (void)sendUnsentReports; + +/** + * Deletes any unsent reports on the device. + * + * This method only applies if automatic data collection is disabled. + */ +- (void)deleteUnsentReports; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FIRExceptionModel.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FIRExceptionModel.h new file mode 100644 index 000000000..a0ee1579e --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FIRExceptionModel.h @@ -0,0 +1,57 @@ +// Copyright 2020 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +#import "FIRStackFrame.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * The Firebase Crashlytics Exception Model provides a way to report custom exceptions + * to Crashlytics that came from a runtime environment outside of the native + * platform Crashlytics is running in. + */ +NS_SWIFT_NAME(ExceptionModel) +@interface FIRExceptionModel : NSObject + +/** :nodoc: */ +- (instancetype)init NS_UNAVAILABLE; + +/** + * Initializes an Exception Model model with the given required fields. + * + * @param name - typically the type of the Exception class + * @param reason - the human-readable reason the issue occurred + */ +- (instancetype)initWithName:(NSString *)name reason:(NSString *)reason; + +/** + * Creates an Exception Model model with the given required fields. + * + * @param name - typically the type of the Exception class + * @param reason - the human-readable reason the issue occurred + */ ++ (instancetype)exceptionModelWithName:(NSString *)name + reason:(NSString *)reason NS_SWIFT_UNAVAILABLE(""); + +/** + * A list of Stack Frames that make up the stack trace. The order of the stack trace is top-first, + * so typically the "main" function is the last element in this list. + */ +@property(nonatomic, copy) NSArray<FIRStackFrame *> *stackTrace; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FIRStackFrame.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FIRStackFrame.h new file mode 100644 index 000000000..ef9746fbb --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FIRStackFrame.h @@ -0,0 +1,53 @@ +// Copyright 2020 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +/** + * The Firebase Crashlytics Stack Frame provides a way to construct the lines of + * a stack trace for reporting along with a recorded Exception Model. + */ +NS_SWIFT_NAME(StackFrame) +@interface FIRStackFrame : NSObject + +/** :nodoc: */ +- (instancetype)init NS_UNAVAILABLE; + +/** + * Initializes a symbolicated Stack Frame with the given required fields. Symbolicated + * Stack Frames will appear in the Crashlytics dashboard as reported in these fields. + * + * @param symbol - The function or method name + * @param file - the file where the exception occurred + * @param line - the line number + */ +- (instancetype)initWithSymbol:(NSString *)symbol file:(NSString *)file line:(NSInteger)line; + +/** + * Creates a symbolicated Stack Frame with the given required fields. Symbolicated + * Stack Frames will appear in the Crashlytics dashboard as reported in these fields. * + * + * @param symbol - The function or method name + * @param file - the file where the exception occurred + * @param line - the line number + */ ++ (instancetype)stackFrameWithSymbol:(NSString *)symbol + file:(NSString *)file + line:(NSInteger)line NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/Folly/folly/lang/ColdClass.cpp b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FirebaseCrashlytics.h similarity index 74% rename from ios/Pods/Folly/folly/lang/ColdClass.cpp rename to ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FirebaseCrashlytics.h index 47bf67c21..9022811ba 100644 --- a/ios/Pods/Folly/folly/lang/ColdClass.cpp +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FirebaseCrashlytics.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright 2019 Google * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include <folly/lang/ColdClass.h> -folly::cold_detail::ColdClass::ColdClass() noexcept {} +#import "FIRCrashlytics.h" +#import "FIRExceptionModel.h" +#import "FIRStackFrame.h" diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/FIRCLSSettingsOnboardingManager.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/FIRCLSSettingsOnboardingManager.h new file mode 100644 index 000000000..2708d0952 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/FIRCLSSettingsOnboardingManager.h @@ -0,0 +1,59 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +#if __has_include(<FBLPromises/FBLPromises.h>) +#import <FBLPromises/FBLPromises.h> +#else +#import "FBLPromises.h" +#endif + +@class FIRCLSApplicationIdentifierModel; +@class FIRCLSDataCollectionToken; +@class FIRCLSFileManager; +@class FIRCLSInstallIdentifierModel; +@class FIRCLSSettings; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Use this class to retrieve remote settings for the application from crashlytics backend, and + * onboard the application on the server. + */ +@interface FIRCLSSettingsOnboardingManager : NSObject + +/** + * Designated Initializer. + */ +- (instancetype)initWithAppIDModel:(FIRCLSApplicationIdentifierModel *)appIDModel + installIDModel:(FIRCLSInstallIdentifierModel *)installIDModel + settings:(FIRCLSSettings *)settings + fileManager:(FIRCLSFileManager *)fileManager + googleAppID:(NSString *)googleAppID NS_DESIGNATED_INITIALIZER; +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +/** + * This method kicks off downloading settings and onboarding for the app. + * @param googleAppID (required) GMP id for the app. + * @param token (required) Data collection token signifying we can make network calls + */ +- (void)beginSettingsAndOnboardingWithGoogleAppId:(NSString *)googleAppID + token:(FIRCLSDataCollectionToken *)token + waitForCompletion:(BOOL)waitForCompletion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/FIRCLSSettingsOnboardingManager.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/FIRCLSSettingsOnboardingManager.m new file mode 100644 index 000000000..c820d2dcb --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/FIRCLSSettingsOnboardingManager.m @@ -0,0 +1,243 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSSettingsOnboardingManager.h" + +#import "FIRCLSApplicationIdentifierModel.h" +#import "FIRCLSConstants.h" +#import "FIRCLSDataCollectionToken.h" +#import "FIRCLSDefines.h" +#import "FIRCLSDownloadAndSaveSettingsOperation.h" +#import "FIRCLSFABNetworkClient.h" +#import "FIRCLSFileManager.h" +#import "FIRCLSInstallIdentifierModel.h" +#import "FIRCLSLogger.h" +#import "FIRCLSOnboardingOperation.h" +#import "FIRCLSSettings.h" +#import "FIRCLSURLBuilder.h" + +@interface FIRCLSSettingsOnboardingManager () <FIRCLSDownloadAndSaveSettingsOperationDelegate, + FIRCLSOnboardingOperationDelegate> + +@property(nonatomic, strong) FIRCLSApplicationIdentifierModel *appIDModel; +@property(nonatomic, strong) FIRCLSInstallIdentifierModel *installIDModel; + +@property(nonatomic, strong) FIRCLSSettings *settings; + +@property(nonatomic, nullable, strong) FIRCLSOnboardingOperation *onboardingOperation; +@property(nonatomic, strong) FIRCLSFileManager *fileManager; + +// set to YES once onboarding call has been made. +@property(nonatomic) BOOL hasAttemptedAppConfigure; + +@property(nonatomic) NSDictionary *configuration; +@property(nonatomic) NSDictionary *defaultConfiguration; +@property(nonatomic, copy) NSString *googleAppID; +@property(nonatomic, copy) NSDictionary *kitVersionsByKitBundleIdentifier; +@property(nonatomic, readonly) FIRCLSFABNetworkClient *networkClient; + +@end + +@implementation FIRCLSSettingsOnboardingManager + +- (instancetype)initWithAppIDModel:(FIRCLSApplicationIdentifierModel *)appIDModel + installIDModel:(FIRCLSInstallIdentifierModel *)installIDModel + settings:(FIRCLSSettings *)settings + fileManager:(FIRCLSFileManager *)fileManager + googleAppID:(NSString *)googleAppID { + self = [super init]; + if (!self) { + return nil; + } + + _appIDModel = appIDModel; + _installIDModel = installIDModel; + _settings = settings; + _fileManager = fileManager; + _googleAppID = googleAppID; + + _networkClient = [[FIRCLSFABNetworkClient alloc] initWithQueue:nil]; + + return self; +} + +- (void)beginSettingsAndOnboardingWithGoogleAppId:(NSString *)googleAppID + token:(FIRCLSDataCollectionToken *)token + waitForCompletion:(BOOL)waitForCompletion { + NSParameterAssert(googleAppID); + + self.googleAppID = googleAppID; + + // This map helps us determine what versions of the SDK + // are out there. We're keeping the Fabric value in there for + // backwards compatibility + // TODO(b/141747635) + self.kitVersionsByKitBundleIdentifier = @{ + FIRCLSApplicationGetSDKBundleID() : @CLS_SDK_DISPLAY_VERSION, + }; + + [self beginSettingsDownload:token waitForCompletion:waitForCompletion]; +} + +#pragma mark Helper methods + +/** + * Makes a settings download request. If the request fails, the error is handled silently(with a log + * statement). If the server response indicates onboarding is needed, an onboarding request is sent + * to the server. If the onboarding request fails, the error is handled silently(with a log + * statement). + */ +- (void)beginSettingsDownload:(FIRCLSDataCollectionToken *)token + waitForCompletion:(BOOL)waitForCompletion { + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + + FIRCLSDownloadAndSaveSettingsOperation *operation = nil; + operation = [[FIRCLSDownloadAndSaveSettingsOperation alloc] + initWithGoogleAppID:self.googleAppID + delegate:self + settingsURL:self.settingsURL + settingsDirectoryPath:self.fileManager.settingsDirectoryPath + settingsFilePath:self.fileManager.settingsFilePath + installIDModel:self.installIDModel + networkClient:self.networkClient + token:token]; + + if (waitForCompletion) { + operation.asyncCompletion = ^(NSError *error) { + dispatch_semaphore_signal(semaphore); + }; + } + + [operation startWithToken:token]; + + if (waitForCompletion) { + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + } +} + +- (void)beginOnboarding:(BOOL)appCreate + endpointString:(NSString *)endpoint + token:(FIRCLSDataCollectionToken *)token { + [self.onboardingOperation cancel]; + + self.onboardingOperation = + [[FIRCLSOnboardingOperation alloc] initWithDelegate:self + shouldCreate:appCreate + googleAppID:self.googleAppID + kitVersionsByKitBundleIdentifier:self.kitVersionsByKitBundleIdentifier + appIdentifierModel:self.appIDModel + endpointString:endpoint + networkClient:self.networkClient + token:token + settings:self.settings]; + + [self.onboardingOperation startWithToken:token]; +} + +- (void)finishNetworkingSession { + [self.networkClient invalidateAndCancel]; +} + +#pragma mark FIRCLSOnboardingOperationDelegate methods + +- (void)onboardingOperation:(FIRCLSOnboardingOperation *)operation + didCompleteAppCreationWithError:(nullable NSError *)error { + if (error) { + FIRCLSErrorLog(@"Unable to complete application configure: %@", error); + [self finishNetworkingSession]; + return; + } + self.onboardingOperation = nil; + FIRCLSDebugLog(@"Completed configure"); + + // now, go get settings, as they can change (and it completes the onboarding process) + [self beginSettingsDownload:operation.token waitForCompletion:NO]; +} + +- (void)onboardingOperation:(FIRCLSOnboardingOperation *)operation + didCompleteAppUpdateWithError:(nullable NSError *)error { + [self finishNetworkingSession]; + if (error) { + FIRCLSErrorLog(@"Unable to complete application update: %@", error); + return; + } + self.onboardingOperation = nil; + FIRCLSDebugLog(@"Completed application update"); +} + +#pragma mark FIRCLSDownloadAndSaveSettingsOperationDelegate methods + +- (void)operation:(FIRCLSDownloadAndSaveSettingsOperation *)operation + didDownloadAndSaveSettingsWithError:(nullable NSError *)error { + if (error) { + FIRCLSErrorLog(@"Failed to download settings %@", error); + [self finishNetworkingSession]; + return; + } + + FIRCLSDebugLog(@"Settings downloaded successfully"); + + NSTimeInterval currentTimestamp = [NSDate timeIntervalSinceReferenceDate]; + [self.settings cacheSettingsWithGoogleAppID:self.googleAppID currentTimestamp:currentTimestamp]; + + // only try this once + if (self.hasAttemptedAppConfigure) { + FIRCLSDebugLog(@"App already onboarded in this run of the app"); + [self finishNetworkingSession]; + return; + } + + // Onboarding is still needed in Firebase, here are the backend app states - + // 1. When the app is created in the Firebase console, app state: built (client settings call + // returns app status: new) + // 2. After onboarding call is made, app state: build_configured + // 3. Another settings call is triggered after onboarding, app state: activated + if ([self.settings appNeedsOnboarding]) { + FIRCLSDebugLog(@"Starting onboarding with app create"); + self.hasAttemptedAppConfigure = YES; + [self beginOnboarding:YES endpointString:FIRCLSConfigureEndpoint token:operation.token]; + return; + } + + if ([self.settings appUpdateRequired]) { + FIRCLSDebugLog(@"Starting onboarding with app update"); + self.hasAttemptedAppConfigure = YES; + [self beginOnboarding:NO endpointString:FIRCLSConfigureEndpoint token:operation.token]; + return; + } + + // we're all set! + [self finishNetworkingSession]; +} + +- (NSURL *)settingsURL { + // GET + // /spi/v2/platforms/:platform/apps/:identifier/settings?build_version=1234&display_version=abc&instance=xyz&source=1 + FIRCLSURLBuilder *url = [FIRCLSURLBuilder URLWithBase:FIRCLSSettingsEndpoint]; + + [url appendComponent:@"/spi/v2/platforms/"]; + [url escapeAndAppendComponent:self.appIDModel.platform]; + [url appendComponent:@"/gmp/"]; + [url escapeAndAppendComponent:self.googleAppID]; + [url appendComponent:@"/settings"]; + + [url appendValue:self.appIDModel.buildVersion forQueryParam:@"build_version"]; + [url appendValue:self.appIDModel.displayVersion forQueryParam:@"display_version"]; + [url appendValue:self.appIDModel.buildInstanceID forQueryParam:@"instance"]; + [url appendValue:@(self.appIDModel.installSource) forQueryParam:@"source"]; + // TODO: find the right param name for KitVersions and add them here + return url.URL; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Models/FIRCLSApplicationIdentifierModel.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Models/FIRCLSApplicationIdentifierModel.h new file mode 100644 index 000000000..3bc75630b --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Models/FIRCLSApplicationIdentifierModel.h @@ -0,0 +1,71 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +#import "FIRCLSApplication.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * This class is a model for identifiers related to the application binary. + * It is thread-safe. + */ +@interface FIRCLSApplicationIdentifierModel : NSObject + +@property(nonatomic, readonly, nullable) NSString* bundleID; + +/** + * Returns the user-facing app name + */ +@property(nonatomic, readonly, nullable) NSString* displayName; + +@property(nonatomic, readonly, nullable) NSString* platform; +@property(nonatomic, readonly, nullable) NSString* buildVersion; +@property(nonatomic, readonly, nullable) NSString* displayVersion; + +/** + * Returns the synthesized app version, similar to how the backend does it + * <displayVersion> (<buildVersion>) + */ +@property(nonatomic, readonly, nullable) NSString* synthesizedVersion; + +@property(nonatomic, readonly) FIRCLSApplicationInstallationSourceType installSource; + +/** + * A mapping between all supported architectures and their UUIDs + */ +@property(nonatomic, readonly) NSDictionary* architectureUUIDMap; + +/** + * Returns the linked OS SDK + */ +@property(nonatomic, readonly) NSString* builtSDKString; + +/** + * Returns the min supported OS + */ +@property(nonatomic, readonly) NSString* minimumSDKString; + +/** + * The unique identifier for this instance of the version of app running Crashlytics. This is + * computed by hashing the app itself. + * + * On Android, this is called the Build ID + */ +@property(nonatomic, readonly) NSString* buildInstanceID; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Models/FIRCLSApplicationIdentifierModel.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Models/FIRCLSApplicationIdentifierModel.m new file mode 100644 index 000000000..3429df4d8 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Models/FIRCLSApplicationIdentifierModel.m @@ -0,0 +1,138 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSApplicationIdentifierModel.h" + +#import "FIRCLSApplication.h" +#import "FIRCLSByteUtility.h" +#import "FIRCLSDefines.h" +#import "FIRCLSMachO.h" +#import "FIRCLSUUID.h" + +@interface FIRCLSApplicationIdentifierModel () + +@property(nonatomic, copy, readwrite) NSDictionary *architectureUUIDMap; +@property(nonatomic, copy, readwrite) NSString *buildInstanceID; +@property(nonatomic, readonly) FIRCLSMachOVersion builtSDK; +@property(nonatomic, readonly) FIRCLSMachOVersion minimumSDK; + +@end + +@implementation FIRCLSApplicationIdentifierModel + +- (nullable instancetype)init { + self = [super init]; + if (!self) { + return nil; + } + + if (![self computeExecutableInfo]) { + return nil; + } + + [self computeInstanceIdentifier]; + + return self; +} + +- (NSString *)bundleID { + return FIRCLSApplicationGetBundleIdentifier(); +} + +- (NSString *)displayName { + return FIRCLSApplicationGetName(); +} + +- (NSString *)platform { + return FIRCLSApplicationGetPlatform(); +} + +- (NSString *)buildVersion { + return FIRCLSApplicationGetBundleVersion(); +} + +- (NSString *)displayVersion { + return FIRCLSApplicationGetShortBundleVersion(); +} + +- (NSString *)synthesizedVersion { + return [NSString stringWithFormat:@"%@ (%@)", self.displayVersion, self.buildVersion]; +} + +- (FIRCLSApplicationInstallationSourceType)installSource { + return FIRCLSApplicationInstallationSource(); +} + +- (NSString *)builtSDKString { + return FIRCLSMachOFormatVersion(&_builtSDK); +} + +- (NSString *)minimumSDKString { + return FIRCLSMachOFormatVersion(&_minimumSDK); +} + +- (BOOL)computeExecutableInfo { + struct FIRCLSMachOFile file; + + if (!FIRCLSMachOFileInitWithCurrent(&file)) { + return NO; + } + + NSMutableDictionary *executables = [NSMutableDictionary dictionary]; + + FIRCLSMachOFileEnumerateSlices(&file, ^(FIRCLSMachOSliceRef fileSlice) { + NSString *arch; + + arch = [NSString stringWithUTF8String:FIRCLSMachOSliceGetArchitectureName(fileSlice)]; + + FIRCLSMachOSliceEnumerateLoadCommands( + fileSlice, ^(uint32_t type, uint32_t size, const struct load_command *cmd) { + if (type == LC_UUID) { + const uint8_t *uuid; + + uuid = FIRCLSMachOGetUUID(cmd); + + [executables setObject:FIRCLSUUIDToNSString(uuid) forKey:arch]; + } else if (type == LC_VERSION_MIN_MACOSX || type == LC_VERSION_MIN_IPHONEOS) { + self->_minimumSDK = FIRCLSMachOGetMinimumOSVersion(cmd); + self->_builtSDK = FIRCLSMachOGetLinkedSDKVersion(cmd); + } + }); + }); + + FIRCLSMachOFileDestroy(&file); + + _architectureUUIDMap = executables; + + return YES; +} + +- (void)computeInstanceIdentifier { + // build up the components of the instance identifier + NSMutableString *string = [NSMutableString string]; + + // first, the uuids, sorted by architecture name + for (NSString *key in + [[_architectureUUIDMap allKeys] sortedArrayUsingSelector:@selector(compare:)]) { + [string appendString:[self.architectureUUIDMap objectForKey:key]]; + } + + // TODO: the instance identifier calculation needs to match Beta's expectation. So, we have to + // continue generating a less-correct value for now. One day, we should encorporate a hash of the + // Info.plist and icon data. + + _buildInstanceID = FIRCLSHashNSData([string dataUsingEncoding:NSUTF8StringEncoding]); +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSDownloadAndSaveSettingsOperation.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSDownloadAndSaveSettingsOperation.h new file mode 100644 index 000000000..318089ff9 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSDownloadAndSaveSettingsOperation.h @@ -0,0 +1,80 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> +#import "FIRCLSNetworkOperation.h" + +@class FIRCLSDownloadAndSaveSettingsOperation; +@class FIRCLSFABNetworkClient; +@class FIRCLSInstallIdentifierModel; + +NS_ASSUME_NONNULL_BEGIN + +/** + * This is the protocol that a delegate of FIRCLSDownloadAndSaveSettingsOperation needs to follow. + */ +@protocol FIRCLSDownloadAndSaveSettingsOperationDelegate <NSObject> + +@required + +/** + * Method that is called when settings have been downloaded and saved, or an error has occurred + * during the operation. This method may be called on an arbitrary background thread. + */ +- (void)operation:(FIRCLSDownloadAndSaveSettingsOperation *)operation + didDownloadAndSaveSettingsWithError:(nullable NSError *)error; + +@end + +/** + * This operation downloads settings from the backend servers, and saves them in file on disk. + */ +@interface FIRCLSDownloadAndSaveSettingsOperation : FIRCLSNetworkOperation + +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID + token:(FIRCLSDataCollectionToken *)token NS_UNAVAILABLE; + +/** + * @param googleAppID must NOT be nil + * @param delegate gets a callback after settings have been downloaded or an error occurs. + * @param settingsURL must NOT be nil. This is the URL to which a download request is made. + * @param settingsDirectoryPath must NOT be nil. This is the directory on disk where the settings + * are persisted. + * @param settingsFilePath must NOT be nil. It is the full file path(including file name) in which + * settings will be persisted on disk. + * @param installIDModel must NOT be nil. This value is sent back to the backend to uniquely + * identify the app install. + */ +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID + delegate:(id<FIRCLSDownloadAndSaveSettingsOperationDelegate>)delegate + settingsURL:(NSURL *)settingsURL + settingsDirectoryPath:(NSString *)settingsDirectoryPath + settingsFilePath:(NSString *)settingsFilePath + installIDModel:(FIRCLSInstallIdentifierModel *)installIDModel + networkClient:(FIRCLSFABNetworkClient *)networkClient + token:(FIRCLSDataCollectionToken *)token NS_DESIGNATED_INITIALIZER; + +/** + * Delegate of this operation. + */ +@property(nonatomic, readonly, weak) id<FIRCLSDownloadAndSaveSettingsOperationDelegate> delegate; + +/** + * When an error occurs during this operation, it is made available in this property. + */ +@property(nonatomic, readonly) NSError *error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSDownloadAndSaveSettingsOperation.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSDownloadAndSaveSettingsOperation.m new file mode 100644 index 000000000..9d32f9150 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSDownloadAndSaveSettingsOperation.m @@ -0,0 +1,132 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSDownloadAndSaveSettingsOperation.h" + +#import "FIRCLSConstants.h" +#import "FIRCLSFABHost.h" +#import "FIRCLSFABNetworkClient.h" +#import "FIRCLSInstallIdentifierModel.h" +#import "FIRCLSLogger.h" + +@interface FIRCLSDownloadAndSaveSettingsOperation () + +/** + * Method called to fetch the URL from where settings have to be downloaded. + */ +@property(readonly, nonatomic) NSURL *settingsURL; +/** + * File manager which will be used to save settings on disk. + */ +@property(readonly, nonatomic) NSFileManager *fileManager; + +/** + * Directory path on which settings file will be saved + */ +@property(readonly, nonatomic) NSString *settingsDirectoryPath; +/** + * Complete file path on which settings file will be saved + */ +@property(readonly, nonatomic) NSString *settingsFilePath; +/** + * App install identifier. + */ +@property(strong, readonly, nonatomic) FIRCLSInstallIdentifierModel *installIDModel; + +@property(weak, readonly, nonatomic) FIRCLSFABNetworkClient *networkClient; + +@end + +@implementation FIRCLSDownloadAndSaveSettingsOperation + +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID + delegate:(id<FIRCLSDownloadAndSaveSettingsOperationDelegate>)delegate + settingsURL:(NSURL *)settingsURL + settingsDirectoryPath:(NSString *)settingsDirectoryPath + settingsFilePath:(NSString *)settingsFilePath + installIDModel:(FIRCLSInstallIdentifierModel *)installIDModel + networkClient:(FIRCLSFABNetworkClient *)networkClient + token:(FIRCLSDataCollectionToken *)token { + NSParameterAssert(settingsURL); + NSParameterAssert(settingsDirectoryPath); + NSParameterAssert(settingsFilePath); + NSParameterAssert(installIDModel); + + self = [super initWithGoogleAppID:googleAppID token:token]; + if (self) { + _delegate = delegate; + _settingsURL = settingsURL.copy; + _settingsDirectoryPath = settingsDirectoryPath.copy; + _settingsFilePath = settingsFilePath.copy; + _fileManager = [[NSFileManager alloc] init]; + _installIDModel = installIDModel; + _networkClient = networkClient; + } + return self; +} + +- (NSMutableURLRequest *)mutableRequestWithDefaultHTTPHeaderFieldsAndTimeoutForURL:(NSURL *)url { + NSMutableURLRequest *request = + [super mutableRequestWithDefaultHTTPHeaderFieldsAndTimeoutForURL:url]; + request.HTTPMethod = @"GET"; + [request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; + [request setValue:self.installIDModel.installID + forHTTPHeaderField:@"X-Crashlytics-Installation-ID"]; + [request setValue:FIRCLSHostModelInfo() forHTTPHeaderField:@"X-Crashlytics-Device-Model"]; + [request setValue:FIRCLSHostOSBuildVersion() + forHTTPHeaderField:@"X-Crashlytics-OS-Build-Version"]; + [request setValue:FIRCLSHostOSDisplayVersion() + forHTTPHeaderField:@"X-Crashlytics-OS-Display-Version"]; + [request setValue:FIRCLSVersion forHTTPHeaderField:@"X-Crashlytics-API-Client-Version"]; + + return request; +} + +- (void)main { + NSMutableURLRequest *request = + [self mutableRequestWithDefaultHTTPHeaderFieldsAndTimeoutForURL:self.settingsURL]; + + [self.networkClient + startDownloadTaskWithRequest:request + retryLimit:1 + completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) { + if (error) { + self->_error = error; + [self.delegate operation:self didDownloadAndSaveSettingsWithError:self.error]; + [self finishWithError:error]; + return; + } + // This move needs to happen synchronously, because after this method completes, + // the file will not be available. + NSError *moveError = nil; + + // this removal will frequently fail, and we don't want the warning + [self.fileManager removeItemAtPath:self.settingsDirectoryPath error:nil]; + + [self.fileManager createDirectoryAtPath:self.settingsDirectoryPath + withIntermediateDirectories:YES + attributes:nil + error:nil]; + if (![self.fileManager moveItemAtPath:location.path + toPath:self.settingsFilePath + error:&moveError]) { + FIRCLSErrorLog(@"Unable to complete settings download %@", moveError); + self->_error = moveError; + } + [self.delegate operation:self didDownloadAndSaveSettingsWithError:self.error]; + [self finishWithError:self.error]; + }]; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSNetworkOperation.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSNetworkOperation.h new file mode 100644 index 000000000..a449903f7 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSNetworkOperation.h @@ -0,0 +1,55 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> +#import "FIRCLSOperation.h" + +NS_ASSUME_NONNULL_BEGIN + +@class FIRCLSDataCollectionToken; +@class FIRCLSSettings; + +/** + * This is a base class for network based operations. + */ +@interface FIRCLSNetworkOperation : FIRCLSFABAsyncOperation + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +/** + * Designated initializer. All parameters are mandatory and must not be nil. + */ +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID + token:(FIRCLSDataCollectionToken *)token NS_DESIGNATED_INITIALIZER; + +- (void)start NS_UNAVAILABLE; +- (void)startWithToken:(FIRCLSDataCollectionToken *)token; + +/** + * Creates a mutable request for posting to Crashlytics backend with a default timeout. + */ +- (NSMutableURLRequest *)mutableRequestWithDefaultHTTPHeaderFieldsAndTimeoutForURL:(NSURL *)url; + +/** + * Creates a mutable request for posting to Crashlytics backend with given timeout. + */ +- (NSMutableURLRequest *)mutableRequestWithDefaultHTTPHeadersForURL:(NSURL *)url + timeout:(NSTimeInterval)timeout; + +@property(nonatomic, strong, readonly) FIRCLSDataCollectionToken *token; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSNetworkOperation.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSNetworkOperation.m new file mode 100644 index 000000000..52b77c19c --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSNetworkOperation.m @@ -0,0 +1,92 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSNetworkOperation.h" + +#import "FIRCLSApplication.h" +#import "FIRCLSConstants.h" +#import "FIRCLSDataCollectionToken.h" +#import "FIRCLSDefines.h" +#import "FIRCLSLogger.h" + +@interface FIRCLSNetworkOperation () + +@property(nonatomic, strong, readonly) NSString *googleAppID; + +@end + +@implementation FIRCLSNetworkOperation + +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID + token:(FIRCLSDataCollectionToken *)token { + NSParameterAssert(googleAppID); + if (!googleAppID) { + return nil; + } + + self = [super init]; + if (self) { + _googleAppID = googleAppID; + _token = token; + } + return self; +} + +- (void)startWithToken:(FIRCLSDataCollectionToken *)token { + // Settings and Onboarding are considered data collection, so we must only + // call this with a valid token + if (![token isValid]) { + FIRCLSErrorLog(@"Skipping network operation with invalid data collection token"); + return; + } + + [super start]; +} + +- (NSMutableURLRequest *)mutableRequestWithDefaultHTTPHeaderFieldsAndTimeoutForURL:(NSURL *)url { + return [self mutableRequestWithDefaultHTTPHeadersForURL:url timeout:10.0]; +} + +- (NSMutableURLRequest *)mutableRequestWithDefaultHTTPHeadersForURL:(NSURL *)url + timeout:(NSTimeInterval)timeout { + NSMutableURLRequest *request = + [NSMutableURLRequest requestWithURL:url + cachePolicy:NSURLRequestReloadIgnoringLocalCacheData + timeoutInterval:timeout]; + + NSString *localeId = self.localeIdentifier; + + [request setValue:self.userAgentString forHTTPHeaderField:FIRCLSNetworkUserAgent]; + [request setValue:FIRCLSNetworkUTF8 forHTTPHeaderField:FIRCLSNetworkAcceptCharset]; + [request setValue:localeId forHTTPHeaderField:FIRCLSNetworkAcceptLanguage]; + [request setValue:localeId forHTTPHeaderField:FIRCLSNetworkContentLanguage]; + [request setValue:FIRCLSDeveloperToken forHTTPHeaderField:FIRCLSNetworkCrashlyticsDeveloperToken]; + [request setValue:FIRCLSApplicationGetSDKBundleID() + forHTTPHeaderField:FIRCLSNetworkCrashlyticsAPIClientId]; + [request setValue:FIRCLSVersion + forHTTPHeaderField:FIRCLSNetworkCrashlyticsAPIClientDisplayVersion]; + [request setValue:self.googleAppID forHTTPHeaderField:FIRCLSNetworkCrashlyticsGoogleAppId]; + + return request; +} + +- (NSString *)userAgentString { + return [NSString stringWithFormat:@"%@/%@", FIRCLSApplicationGetSDKBundleID(), FIRCLSVersion]; +} + +- (NSString *)localeIdentifier { + return NSLocale.currentLocale.localeIdentifier; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSOnboardingOperation.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSOnboardingOperation.h new file mode 100644 index 000000000..14d56ed64 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSOnboardingOperation.h @@ -0,0 +1,84 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> +#import "FIRCLSApplicationIdentifierModel.h" +#import "FIRCLSDataCollectionToken.h" +#import "FIRCLSNetworkOperation.h" + +NS_ASSUME_NONNULL_BEGIN + +extern NSString *const FIRCLSOnboardingErrorDomain; + +@class FIRCLSOnboardingOperation; +@class FIRCLSFABNetworkClient; +@class FIRCLSSettings; + +/** + * This is the protocol that a delegate of FIRCLSOnboardingOperation should follow. + */ +@protocol FIRCLSOnboardingOperationDelegate <NSObject> +@required + +/** + * This callback is for the delegate to know that app update has completed with/without an error. + */ +- (void)onboardingOperation:(FIRCLSOnboardingOperation *)operation + didCompleteAppUpdateWithError:(nullable NSError *)error; +/** + * This callback is for the delegate to know that app creation has completed with/without an error. + */ +- (void)onboardingOperation:(FIRCLSOnboardingOperation *)operation + didCompleteAppCreationWithError:(nullable NSError *)error; + +@end + +/** + * This class onboards the app, by making request to the backend servers. + */ +@interface FIRCLSOnboardingOperation : FIRCLSNetworkOperation + +/** + * When an error occurs during this operation, it is made available in this property. + */ +@property(nonatomic, readonly) NSError *error; + +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID + token:(FIRCLSDataCollectionToken *)token NS_UNAVAILABLE; + +/** + * Designated initializer. + * @param delegate may be nil. Gets callbacks when app creation or updation succeeds or gets errored + * out. + * @param googleAppID must NOT be nil. + * @param kitVersionsByKitBundleIdentifier may be nil. Maps Kit bundle identifier to kit version + * being used in the app. + * @param appIdentifierModel must NOT be nil. Used to get information required in the onboarding + * network call. + * @param appEndPoint must NOT be nil. Endpoint which needs to be hit with the onboarding request. + * @param settings which are used to fetch the organization identifier. + */ +- (instancetype)initWithDelegate:(id<FIRCLSOnboardingOperationDelegate>)delegate + shouldCreate:(BOOL)shouldCreate + googleAppID:(NSString *)googleAppID + kitVersionsByKitBundleIdentifier:(NSDictionary *)kitVersionsByKitBundleIdentifier + appIdentifierModel:(FIRCLSApplicationIdentifierModel *)appIdentifierModel + endpointString:(NSString *)appEndPoint + networkClient:(FIRCLSFABNetworkClient *)networkClient + token:(FIRCLSDataCollectionToken *)token + settings:(FIRCLSSettings *)settings NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSOnboardingOperation.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSOnboardingOperation.m new file mode 100644 index 000000000..ce2e58b5c --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSOnboardingOperation.m @@ -0,0 +1,208 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSOnboardingOperation.h" + +#import "FIRCLSByteUtility.h" +#import "FIRCLSConstants.h" +#import "FIRCLSFABNetworkClient.h" +#import "FIRCLSLogger.h" +#import "FIRCLSMachO.h" +#import "FIRCLSMultipartMimeStreamEncoder.h" +#import "FIRCLSSettings.h" +#import "FIRCLSURLBuilder.h" + +// The SPIv1/v2 onboarding flow looks something like this: +// - get settings +// - settings says we're good, nothing to do +// - settings says update +// - do an update +// - settings says new +// - do a create +// - get settings again (and do *not* take action after that) + +NSString *const FIRCLSOnboardingErrorDomain = @"FIRCLSOnboardingErrorDomain"; + +typedef NS_ENUM(NSInteger, FIRCLSOnboardingError) { + FIRCLSOnboardingErrorMultipartMimeConfiguration +}; + +@interface FIRCLSOnboardingOperation () + +@property(nonatomic) BOOL shouldCreate; +@property(nonatomic, readonly) FIRCLSApplicationIdentifierModel *appIdentifierModel; +@property(nonatomic, readonly) NSString *appEndpoint; +@property(nonatomic, readonly, unsafe_unretained) id<FIRCLSOnboardingOperationDelegate> delegate; +@property(nonatomic, weak, readonly) FIRCLSFABNetworkClient *networkClient; +@property(nonatomic, readonly) NSDictionary *kitVersionsByKitBundleIdentifier; +@property(nonatomic, readonly) FIRCLSSettings *settings; +@end + +@implementation FIRCLSOnboardingOperation + +#pragma mark lifecycle methods + +- (instancetype)initWithDelegate:(id<FIRCLSOnboardingOperationDelegate>)delegate + shouldCreate:(BOOL)shouldCreate + googleAppID:(NSString *)googleAppID + kitVersionsByKitBundleIdentifier:(NSDictionary *)kitVersionsByKitBundleIdentifier + appIdentifierModel:(FIRCLSApplicationIdentifierModel *)appIdentifierModel + endpointString:(NSString *)appEndPoint + networkClient:(FIRCLSFABNetworkClient *)networkClient + token:(FIRCLSDataCollectionToken *)token + settings:(FIRCLSSettings *)settings { + NSParameterAssert(appIdentifierModel); + NSParameterAssert(appEndPoint); + + self = [super initWithGoogleAppID:googleAppID token:token]; + if (self) { + _shouldCreate = shouldCreate; + _delegate = delegate; + _appIdentifierModel = appIdentifierModel; + _appEndpoint = appEndPoint; + _networkClient = networkClient; + _kitVersionsByKitBundleIdentifier = kitVersionsByKitBundleIdentifier.copy; + _settings = settings; + } + return self; +} + +- (void)main { + [self beginAppConfigure]; +} + +- (void)beginAppConfigure { + NSOutputStream *stream = [[NSOutputStream alloc] initToMemory]; + NSString *boundary = [FIRCLSMultipartMimeStreamEncoder generateBoundary]; + + FIRCLSMultipartMimeStreamEncoder *encoder = + [FIRCLSMultipartMimeStreamEncoder encoderWithStream:stream andBoundary:boundary]; + if (!encoder) { + FIRCLSErrorLog(@"Configure failed during onboarding"); + [self finishWithError:[self errorForCode:FIRCLSOnboardingErrorMultipartMimeConfiguration + userInfo:@{ + NSLocalizedDescriptionKey : @"Multipart mime encoder was nil" + }]]; + return; + } + + NSString *orgID = [self.settings orgID]; + if (!orgID) { + FIRCLSErrorLog(@"Could not onboard app with missing Organization ID"); + [self finishWithError:[self errorForCode:FIRCLSOnboardingErrorMultipartMimeConfiguration + userInfo:@{ + NSLocalizedDescriptionKey : @"Organization ID was nil" + }]]; + return; + } + + [encoder encode:^{ + [encoder addValue:orgID fieldName:@"org_id"]; + + [encoder addValue:self.settings.fetchedBundleID fieldName:@"app[identifier]"]; + [encoder addValue:self.appIdentifierModel.buildInstanceID + fieldName:@"app[instance_identifier]"]; + [encoder addValue:self.appIdentifierModel.displayName fieldName:@"app[name]"]; + [encoder addValue:self.appIdentifierModel.buildVersion fieldName:@"app[build_version]"]; + [encoder addValue:self.appIdentifierModel.displayVersion fieldName:@"app[display_version]"]; + [encoder addValue:@(self.appIdentifierModel.installSource) fieldName:@"app[source]"]; + [encoder addValue:self.appIdentifierModel.minimumSDKString + fieldName:@"app[minimum_sdk_version]"]; + [encoder addValue:self.appIdentifierModel.builtSDKString fieldName:@"app[built_sdk_version]"]; + [self.kitVersionsByKitBundleIdentifier + enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + NSString *formKey = [NSString stringWithFormat:@"%@[%@]", @"app[build][libraries]", key]; + [encoder addValue:obj fieldName:formKey]; + }]; + + [self.appIdentifierModel.architectureUUIDMap + enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + [encoder addValue:key fieldName:@"app[slices][][arch]"]; + [encoder addValue:obj fieldName:@"app[slices][][uuid]"]; + }]; + }]; + + NSMutableURLRequest *request = [self onboardingRequestForAppCreate:self.shouldCreate]; + [request setValue:orgID forHTTPHeaderField:FIRCLSNetworkCrashlyticsOrgId]; + + [request setValue:encoder.contentTypeHTTPHeaderValue forHTTPHeaderField:@"Content-Type"]; + [request setValue:encoder.contentLengthHTTPHeaderValue forHTTPHeaderField:@"Content-Length"]; + [request setHTTPBody:[stream propertyForKey:NSStreamDataWrittenToMemoryStreamKey]]; + + // Retry only when onboarding an app for the first time, otherwise it'll overwhelm our servers + NSUInteger retryLimit = self.shouldCreate ? 10 : 1; + + [self.networkClient + startDataTaskWithRequest:request + retryLimit:retryLimit + completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { + self->_error = error; + if (!self.shouldCreate) { + [self.delegate onboardingOperation:self didCompleteAppUpdateWithError:error]; + } else { + [self.delegate onboardingOperation:self didCompleteAppCreationWithError:error]; + } + [self finishWithError:error]; + }]; +} + +#pragma mark private methods + +- (NSError *)errorForCode:(NSUInteger)code userInfo:(NSDictionary *)userInfo { + return [NSError errorWithDomain:FIRCLSOnboardingErrorDomain code:code userInfo:userInfo]; +} + +- (NSURL *)appCreateURL { + // https://update.crashlytics.com/spi/v1/platforms/mac/apps/com.crashlytics.mac + + FIRCLSURLBuilder *url = [FIRCLSURLBuilder URLWithBase:self.appEndpoint]; + + [url appendComponent:@"/spi/v1/platforms/"]; + [url escapeAndAppendComponent:self.appIdentifierModel.platform]; + [url appendComponent:@"/apps"]; + + return url.URL; +} + +- (NSURL *)appUpdateURL { + // https://update.crashlytics.com/spi/v1/platforms/mac/apps/com.crashlytics.mac + + FIRCLSURLBuilder *url = [FIRCLSURLBuilder URLWithBase:[self appEndpoint]]; + + [url appendComponent:@"/spi/v1/platforms/"]; + [url escapeAndAppendComponent:self.appIdentifierModel.platform]; + [url appendComponent:@"/apps/"]; + [url escapeAndAppendComponent:self.settings.fetchedBundleID]; + + return url.URL; +} + +- (NSMutableURLRequest *)onboardingRequestForAppCreate:(BOOL)shouldCreate { + const NSTimeInterval timeout = 10.0; + NSURL *url = nil; + NSString *httpVerb = nil; + if (shouldCreate) { + httpVerb = @"POST"; + url = self.appCreateURL; + } else { + httpVerb = @"PUT"; + url = self.appUpdateURL; + } + NSMutableURLRequest *request = [self mutableRequestWithDefaultHTTPHeadersForURL:url + timeout:timeout]; + request.HTTPMethod = httpVerb; + return request; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind.c b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind.c new file mode 100644 index 000000000..1875f9812 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind.c @@ -0,0 +1,404 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSCompactUnwind_Private.h" +#include "FIRCLSDataParsing.h" +#include "FIRCLSDefines.h" +#include "FIRCLSDwarfUnwind.h" +#include "FIRCLSFeatures.h" +#include "FIRCLSUnwind.h" +#include "FIRCLSUtility.h" + +#include <string.h> + +#if CLS_COMPACT_UNWINDING_SUPPORTED + +#pragma mark Parsing +bool FIRCLSCompactUnwindInit(FIRCLSCompactUnwindContext* context, + const void* unwindInfo, + const void* ehFrame, + uintptr_t loadAddress) { + if (!FIRCLSIsValidPointer(context)) { + FIRCLSSDKLog("Error: invalid context passed to compact unwind init"); + return false; + } + if (!FIRCLSIsValidPointer(unwindInfo)) { + FIRCLSSDKLog("Error: invalid unwind info passed to compact unwind init"); + return false; + } + if (!FIRCLSIsValidPointer(loadAddress)) { + FIRCLSSDKLog("Error: invalid load address passed to compact unwind init"); + return false; + } + + memset(context, 0, sizeof(FIRCLSCompactUnwindContext)); + + if (!FIRCLSReadMemory((vm_address_t)unwindInfo, &context->unwindHeader, + sizeof(struct unwind_info_section_header))) { + FIRCLSSDKLog("Error: could not read memory contents of unwindInfo\n"); + return false; + } + + if (context->unwindHeader.version != UNWIND_SECTION_VERSION) { + FIRCLSSDKLog("Error: bad unwind_info structure version (%d != %d)\n", + context->unwindHeader.version, UNWIND_SECTION_VERSION); + return false; + } + + // copy in the values + context->unwindInfo = unwindInfo; + context->ehFrame = ehFrame; + context->loadAddress = loadAddress; + + return true; +} + +void* FIRCLSCompactUnwindGetIndexData(FIRCLSCompactUnwindContext* context) { + return (void*)((uintptr_t)context->unwindInfo + + (uintptr_t)context->unwindHeader.indexSectionOffset); +} + +compact_unwind_encoding_t* FIRCLSCompactUnwindGetCommonEncodings( + FIRCLSCompactUnwindContext* context) { + return (compact_unwind_encoding_t*)((uintptr_t)context->unwindInfo + + (uintptr_t) + context->unwindHeader.commonEncodingsArraySectionOffset); +} + +void* FIRCLSCompactUnwindGetSecondLevelData(FIRCLSCompactUnwindContext* context) { + return (void*)((uintptr_t)context->unwindInfo + + context->indexHeader.secondLevelPagesSectionOffset); +} + +uintptr_t FIRCLSCompactUnwindGetIndexFunctionOffset(FIRCLSCompactUnwindContext* context) { + return context->loadAddress + context->indexHeader.functionOffset; +} +uintptr_t FIRCLSCompactUnwindGetTargetAddress(FIRCLSCompactUnwindContext* context, uintptr_t pc) { + uintptr_t offset = FIRCLSCompactUnwindGetIndexFunctionOffset(context); + + if (pc <= offset) { + FIRCLSSDKLog("Error: PC is invalid\n"); + return 0; + } + + return pc - offset; +} + +#pragma mark - Parsing and Lookup +bool FIRCLSCompactUnwindLookupFirstLevel(FIRCLSCompactUnwindContext* context, uintptr_t address) { + if (!context) { + return false; + } + + // In practice, it appears that there always one more first level entry + // than required. This actually makes sense, since we have to use this + // info to check if we are in range. This implies there must be + // at least 2 indices at a minimum. + + uint32_t indexCount = context->unwindHeader.indexCount; + if (indexCount < 2) { + return false; + } + + // make sure our address is valid + if (address < context->loadAddress) { + return false; + } + + struct unwind_info_section_header_index_entry* indexEntries = + FIRCLSCompactUnwindGetIndexData(context); + if (!indexEntries) { + return false; + } + + address -= context->loadAddress; // search relative to zero + + // minus one because of the extra entry - see comment above + for (uint32_t index = 0; index < indexCount - 1; ++index) { + uint32_t value = indexEntries[index].functionOffset; + uint32_t nextValue = indexEntries[index + 1].functionOffset; + + if (address >= value && address < nextValue) { + context->firstLevelNextFunctionOffset = nextValue; + context->indexHeader = indexEntries[index]; + return true; + } + } + + return false; +} + +uint32_t FIRCLSCompactUnwindGetSecondLevelPageKind(FIRCLSCompactUnwindContext* context) { + if (!context) { + return 0; + } + + return *(uint32_t*)FIRCLSCompactUnwindGetSecondLevelData(context); +} + +bool FIRCLSCompactUnwindLookupSecondLevelRegular(FIRCLSCompactUnwindContext* context, + uintptr_t pc, + FIRCLSCompactUnwindResult* result) { + FIRCLSSDKLog("Encountered a regular second-level page\n"); + return false; +} + +// this only works for compressed entries right now +bool FIRCLSCompactUnwindBinarySearchSecondLevel(uintptr_t address, + uint32_t* index, + uint16_t entryCount, + uint32_t* entryArray) { + if (!index || !entryArray) { + return false; + } + + if (entryCount == 0) { + return false; + } + + if (address == 0) { + return false; + } + + uint32_t highIndex = entryCount; + *index = 0; + + while (*index < highIndex) { + uint32_t midIndex = (*index + highIndex) / 2; + + // FIRCLSSDKLog("%u %u %u\n", *index, midIndex, highIndex); + + uintptr_t value = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entryArray[midIndex]); + + if (value > address) { + if (highIndex == midIndex) { + return false; + } + + highIndex = midIndex; + continue; + } + + *index = midIndex; + + // are we at the end of the array? + if (midIndex == entryCount - 1) { + return false; + } + + uintptr_t nextValue = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entryArray[midIndex + 1]); + if (nextValue > address) { + // we've found it + break; + } + + *index += 1; + } + + // check to make sure we're still within bounds + return *index < entryCount; +} + +bool FIRCLSCompactUnwindLookupSecondLevelCompressed(FIRCLSCompactUnwindContext* context, + uintptr_t pc, + FIRCLSCompactUnwindResult* result) { + if (!context || !result) { + return false; + } + + void* ptr = FIRCLSCompactUnwindGetSecondLevelData(context); + + if (!ptr) { + return false; + } + + memset(result, 0, sizeof(FIRCLSCompactUnwindResult)); + + struct unwind_info_compressed_second_level_page_header* header = + (struct unwind_info_compressed_second_level_page_header*)ptr; + + // adjust address + uintptr_t targetAddress = FIRCLSCompactUnwindGetTargetAddress(context, pc); + + uint32_t* entryArray = ptr + header->entryPageOffset; + + uint32_t index = 0; + + if (!FIRCLSCompactUnwindBinarySearchSecondLevel(targetAddress, &index, header->entryCount, + entryArray)) { + FIRCLSSDKLogInfo("Unable to find PC in second level\n"); + return false; + } + + uint32_t entry = entryArray[index]; + + // Computing the fuction start address is easy + result->functionStart = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry) + + FIRCLSCompactUnwindGetIndexFunctionOffset(context); + + // Computing the end is more complex, because we could be on the last entry. In that case, we + // cannot use the next value as the end. + result->functionEnd = context->loadAddress; + if (index < header->entryCount - 1) { + result->functionEnd += UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entryArray[index + 1]) + + context->indexHeader.functionOffset; + } else { + result->functionEnd += context->firstLevelNextFunctionOffset; + } + + // FIRCLSSDKLog("Located %lx => %lx %lx\n", pc, result->functionStart, result->functionEnd); + + if ((pc < result->functionStart) || (pc >= result->functionEnd)) { + FIRCLSSDKLog("PC does not match computed function range\n"); + return false; + } + + uint32_t encodingIndex = UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry); + + // encoding could be in the common array + if (encodingIndex < context->unwindHeader.commonEncodingsArrayCount) { + result->encoding = FIRCLSCompactUnwindGetCommonEncodings(context)[encodingIndex]; + + // FIRCLSSDKLog("Entry has common encoding: 0x%x\n", result->encoding); + } else { + encodingIndex = encodingIndex - context->unwindHeader.commonEncodingsArrayCount; + + compact_unwind_encoding_t* encodings = ptr + header->encodingsPageOffset; + + result->encoding = encodings[encodingIndex]; + + // FIRCLSSDKLog("Entry has compressed encoding: 0x%x\n", result->encoding); + } + + if (result->encoding == 0) { + FIRCLSSDKLogInfo("Entry has has no unwind info\n"); + return false; + } + + return true; +} + +bool FIRCLSCompactUnwindLookupSecondLevel(FIRCLSCompactUnwindContext* context, + uintptr_t pc, + FIRCLSCompactUnwindResult* result) { + switch (FIRCLSCompactUnwindGetSecondLevelPageKind(context)) { + case UNWIND_SECOND_LEVEL_REGULAR: + FIRCLSSDKLogInfo("Found a second level regular header\n"); + if (FIRCLSCompactUnwindLookupSecondLevelRegular(context, pc, result)) { + return true; + } + break; + case UNWIND_SECOND_LEVEL_COMPRESSED: + FIRCLSSDKLogInfo("Found a second level compressed header\n"); + if (FIRCLSCompactUnwindLookupSecondLevelCompressed(context, pc, result)) { + return true; + } + break; + default: + FIRCLSSDKLogError("Unrecognized header kind - unable to continue\n"); + break; + } + + return false; +} + +bool FIRCLSCompactUnwindLookup(FIRCLSCompactUnwindContext* context, + uintptr_t pc, + FIRCLSCompactUnwindResult* result) { + if (!context || !result) { + return false; + } + + // step 1 - find the pc in the first-level index + if (!FIRCLSCompactUnwindLookupFirstLevel(context, pc)) { + FIRCLSSDKLogWarn("Unable to find pc in first level\n"); + return false; + } + + FIRCLSSDKLogDebug("Found first level (second => %u)\n", + context->indexHeader.secondLevelPagesSectionOffset); + + // step 2 - use that info to find the second-level information + // that second actually has the encoding info we're looking for. + if (!FIRCLSCompactUnwindLookupSecondLevel(context, pc, result)) { + FIRCLSSDKLogInfo("Second-level PC lookup failed\n"); + return false; + } + + return true; +} + +#pragma mark - Unwinding +bool FIRCLSCompactUnwindLookupAndCompute(FIRCLSCompactUnwindContext* context, + FIRCLSThreadContext* registers) { + if (!context || !registers) { + return false; + } + + uintptr_t pc = FIRCLSThreadContextGetPC(registers); + + // little sanity check + if (pc < context->loadAddress) { + return false; + } + + FIRCLSCompactUnwindResult result; + + memset(&result, 0, sizeof(result)); + + if (!FIRCLSCompactUnwindLookup(context, pc, &result)) { + FIRCLSSDKLogInfo("Unable to lookup compact unwind for pc %p\n", (void*)pc); + return false; + } + + // Ok, armed with the encoding, we can actually attempt to modify the registers. Because + // the encoding is arch-specific, this function has to be defined per-arch. + if (!FIRCLSCompactUnwindComputeRegisters(context, &result, registers)) { + FIRCLSSDKLogError("Failed to compute registers\n"); + return false; + } + + return true; +} + +#if CLS_DWARF_UNWINDING_SUPPORTED +bool FIRCLSCompactUnwindDwarfFrame(FIRCLSCompactUnwindContext* context, + uintptr_t dwarfOffset, + FIRCLSThreadContext* registers) { + if (!context || !registers) { + return false; + } + + // Everyone's favorite! Dwarf unwinding! + FIRCLSSDKLogInfo("Trying to read dwarf data with offset %lx\n", dwarfOffset); + + FIRCLSDwarfCFIRecord record; + + if (!FIRCLSDwarfParseCFIFromFDERecordOffset(&record, context->ehFrame, dwarfOffset)) { + FIRCLSSDKLogError("Unable to init FDE\n"); + return false; + } + + if (!FIRCLSDwarfUnwindComputeRegisters(&record, registers)) { + FIRCLSSDKLogError("Failed to compute DWARF registers\n"); + return false; + } + + return true; +} +#endif + +#else +INJECT_STRIP_SYMBOL(compact_unwind) +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind.h new file mode 100644 index 000000000..1698e7585 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind.h @@ -0,0 +1,68 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include <stdbool.h> +#include <stdint.h> + +#include "FIRCLSFeatures.h" +#include "FIRCLSThreadState.h" + +// We have to pack the arrays defined in this header, so +// we can reason about pointer math. +#pragma pack(push) +#pragma pack(1) +#include <mach-o/compact_unwind_encoding.h> +#pragma pack(pop) + +// First masks out the value, and then shifts the value by the number +// of zeros in the mask. __builtin_ctz returns the number of trailing zeros. +// Its output is undefined if the input is zero. +#define GET_BITS_WITH_MASK(value, mask) ((value & mask) >> (mask == 0 ? 0 : __builtin_ctz(mask))) + +typedef struct { + const void* unwindInfo; + const void* ehFrame; + uintptr_t loadAddress; + + struct unwind_info_section_header unwindHeader; + struct unwind_info_section_header_index_entry indexHeader; + uint32_t firstLevelNextFunctionOffset; +} FIRCLSCompactUnwindContext; + +typedef struct { + compact_unwind_encoding_t encoding; + uintptr_t functionStart; + uintptr_t functionEnd; + uintptr_t lsda; + uintptr_t personality; + +} FIRCLSCompactUnwindResult; + +bool FIRCLSCompactUnwindInit(FIRCLSCompactUnwindContext* context, + const void* unwindInfo, + const void* ehFrame, + uintptr_t loadAddress); +void* FIRCLSCompactUnwindGetIndexData(FIRCLSCompactUnwindContext* context); +void* FIRCLSCompactUnwindGetSecondLevelData(FIRCLSCompactUnwindContext* context); +bool FIRCLSCompactUnwindFindFirstLevelIndex(FIRCLSCompactUnwindContext* context, + uintptr_t pc, + uint32_t* index); + +bool FIRCLSCompactUnwindDwarfFrame(FIRCLSCompactUnwindContext* context, + uintptr_t dwarfOffset, + FIRCLSThreadContext* registers); +bool FIRCLSCompactUnwindLookupAndCompute(FIRCLSCompactUnwindContext* context, + FIRCLSThreadContext* registers); diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind_Private.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind_Private.h new file mode 100644 index 000000000..1dd01562f --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind_Private.h @@ -0,0 +1,28 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "FIRCLSCompactUnwind.h" +#pragma pack(push, 1) +#include <mach-o/compact_unwind_encoding.h> +#pragma pack(pop) + +bool FIRCLSCompactUnwindLookup(FIRCLSCompactUnwindContext* context, + uintptr_t pc, + FIRCLSCompactUnwindResult* result); + +bool FIRCLSCompactUnwindComputeRegisters(FIRCLSCompactUnwindContext* context, + FIRCLSCompactUnwindResult* result, + FIRCLSThreadContext* registers); diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDataParsing.c b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDataParsing.c new file mode 100644 index 000000000..871fd3007 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDataParsing.c @@ -0,0 +1,238 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSDataParsing.h" +#include "FIRCLSDefines.h" +#include "FIRCLSUtility.h" +#include "dwarf.h" + +#include <string.h> + +#if CLS_DWARF_UNWINDING_SUPPORTED + +uint8_t FIRCLSParseUint8AndAdvance(const void** cursor) { + uint8_t tmp = **(uint8_t**)cursor; + + *cursor += sizeof(uint8_t); + + return tmp; +} + +uint16_t FIRCLSParseUint16AndAdvance(const void** cursor) { + uint16_t tmp = **(uint16_t**)cursor; + + *cursor += sizeof(uint16_t); + + return tmp; +} + +int16_t FIRCLSParseInt16AndAdvance(const void** cursor) { + int16_t tmp = **(int16_t**)cursor; + + *cursor += sizeof(int16_t); + + return tmp; +} + +uint32_t FIRCLSParseUint32AndAdvance(const void** cursor) { + uint32_t tmp = **(uint32_t**)cursor; + + *cursor += sizeof(uint32_t); + + return tmp; +} + +int32_t FIRCLSParseInt32AndAdvance(const void** cursor) { + int32_t tmp = **(int32_t**)cursor; + + *cursor += sizeof(int32_t); + + return tmp; +} + +uint64_t FIRCLSParseUint64AndAdvance(const void** cursor) { + uint64_t tmp = **(uint64_t**)cursor; + + *cursor += sizeof(uint64_t); + + return tmp; +} + +int64_t FIRCLSParseInt64AndAdvance(const void** cursor) { + int64_t tmp = **(int64_t**)cursor; + + *cursor += sizeof(int64_t); + + return tmp; +} + +uintptr_t FIRCLSParsePointerAndAdvance(const void** cursor) { + uintptr_t tmp = **(uintptr_t**)cursor; + + *cursor += sizeof(uintptr_t); + + return tmp; +} + +// Signed and Unsigned LEB128 decoding algorithms taken from Wikipedia - +// http://en.wikipedia.org/wiki/LEB128 +uint64_t FIRCLSParseULEB128AndAdvance(const void** cursor) { + uint64_t result = 0; + char shift = 0; + + for (int i = 0; i < sizeof(uint64_t); ++i) { + char byte; + + byte = **(uint8_t**)cursor; + + *cursor += 1; + + result |= ((0x7F & byte) << shift); + if ((0x80 & byte) == 0) { + break; + } + + shift += 7; + } + + return result; +} + +int64_t FIRCLSParseLEB128AndAdvance(const void** cursor) { + uint64_t result = 0; + char shift = 0; + char size = sizeof(int64_t) * 8; + char byte = 0; + + for (int i = 0; i < sizeof(uint64_t); ++i) { + byte = **(uint8_t**)cursor; + + *cursor += 1; + + result |= ((0x7F & byte) << shift); + shift += 7; + + /* sign bit of byte is second high order bit (0x40) */ + if ((0x80 & byte) == 0) { + break; + } + } + + if ((shift < size) && (0x40 & byte)) { + // sign extend + result |= -(1 << shift); + } + + return result; +} + +const char* FIRCLSParseStringAndAdvance(const void** cursor) { + const char* string; + + string = (const char*)(*cursor); + + // strlen doesn't include the null character, which we need to advance past + *cursor += strlen(string) + 1; + + return string; +} + +uint64_t FIRCLSParseRecordLengthAndAdvance(const void** cursor) { + uint64_t length; + + length = FIRCLSParseUint32AndAdvance(cursor); + if (length == DWARF_EXTENDED_LENGTH_FLAG) { + length = FIRCLSParseUint64AndAdvance(cursor); + } + + return length; +} + +uintptr_t FIRCLSParseAddressWithEncodingAndAdvance(const void** cursor, uint8_t encoding) { + if (encoding == DW_EH_PE_omit) { + return 0; + } + + if (!cursor) { + return CLS_INVALID_ADDRESS; + } + + if (!*cursor) { + return CLS_INVALID_ADDRESS; + } + + intptr_t inputAddr = (intptr_t)*cursor; + intptr_t addr; + + switch (encoding & DW_EH_PE_VALUE_MASK) { + case DW_EH_PE_ptr: + // 32 or 64 bits + addr = FIRCLSParsePointerAndAdvance(cursor); + break; + case DW_EH_PE_uleb128: + addr = (intptr_t)FIRCLSParseULEB128AndAdvance(cursor); + break; + case DW_EH_PE_udata2: + addr = FIRCLSParseUint16AndAdvance(cursor); + break; + case DW_EH_PE_udata4: + addr = FIRCLSParseUint32AndAdvance(cursor); + break; + case DW_EH_PE_udata8: + addr = (intptr_t)FIRCLSParseUint64AndAdvance(cursor); + break; + case DW_EH_PE_sleb128: + addr = (intptr_t)FIRCLSParseLEB128AndAdvance(cursor); + break; + case DW_EH_PE_sdata2: + addr = FIRCLSParseInt16AndAdvance(cursor); + break; + case DW_EH_PE_sdata4: + addr = FIRCLSParseInt32AndAdvance(cursor); + break; + case DW_EH_PE_sdata8: + addr = (intptr_t)FIRCLSParseInt64AndAdvance(cursor); + break; + default: + FIRCLSSDKLog("Unhandled: encoding 0x%02x\n", encoding); + return CLS_INVALID_ADDRESS; + } + + // and now apply the relative offset + switch (encoding & DW_EH_PE_RELATIVE_OFFSET_MASK) { + case DW_EH_PE_absptr: + break; + case DW_EH_PE_pcrel: + addr += inputAddr; + break; + default: + FIRCLSSDKLog("Unhandled: relative encoding 0x%02x\n", encoding); + return CLS_INVALID_ADDRESS; + } + + // Here's a crazy one. It seems this encoding means you actually look up + // the value of the address using the result address itself + if (encoding & DW_EH_PE_indirect) { + if (!addr) { + return CLS_INVALID_ADDRESS; + } + + addr = *(uintptr_t*)addr; + } + + return addr; +} +#else +INJECT_STRIP_SYMBOL(data_parsing) +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDataParsing.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDataParsing.h new file mode 100644 index 000000000..8a6e96617 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDataParsing.h @@ -0,0 +1,46 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include <stdint.h> + +#include "FIRCLSFeatures.h" + +#if CLS_DWARF_UNWINDING_SUPPORTED + +#if CLS_CPU_64BIT +#define CLS_INVALID_ADDRESS (0xffffffffffffffff) +#else +#define CLS_INVALID_ADDRESS (0xffffffff) +#endif + +// basic data types +uint8_t FIRCLSParseUint8AndAdvance(const void** cursor); +uint16_t FIRCLSParseUint16AndAdvance(const void** cursor); +int16_t FIRCLSParseInt16AndAdvance(const void** cursor); +uint32_t FIRCLSParseUint32AndAdvance(const void** cursor); +int32_t FIRCLSParseInt32AndAdvance(const void** cursor); +uint64_t FIRCLSParseUint64AndAdvance(const void** cursor); +int64_t FIRCLSParseInt64AndAdvance(const void** cursor); +uintptr_t FIRCLSParsePointerAndAdvance(const void** cursor); +uint64_t FIRCLSParseULEB128AndAdvance(const void** cursor); +int64_t FIRCLSParseLEB128AndAdvance(const void** cursor); +const char* FIRCLSParseStringAndAdvance(const void** cursor); + +// FDE/CIE-specifc structures +uint64_t FIRCLSParseRecordLengthAndAdvance(const void** cursor); +uintptr_t FIRCLSParseAddressWithEncodingAndAdvance(const void** cursor, uint8_t encoding); + +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfExpressionMachine.c b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfExpressionMachine.c new file mode 100644 index 000000000..ea308f13a --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfExpressionMachine.c @@ -0,0 +1,453 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSDwarfExpressionMachine.h" +#include "FIRCLSDataParsing.h" +#include "FIRCLSDefines.h" +#include "FIRCLSDwarfUnwindRegisters.h" +#include "FIRCLSUnwind_arch.h" +#include "FIRCLSUtility.h" +#include "dwarf.h" + +#if CLS_DWARF_UNWINDING_SUPPORTED + +static bool FIRCLSDwarfExpressionMachineExecute_bregN(FIRCLSDwarfExpressionMachine *machine, + uint8_t opcode); +static bool FIRCLSDwarfExpressionMachineExecute_deref(FIRCLSDwarfExpressionMachine *machine); +static bool FIRCLSDwarfExpressionMachineExecute_plus_uconst(FIRCLSDwarfExpressionMachine *machine); +static bool FIRCLSDwarfExpressionMachineExecute_and(FIRCLSDwarfExpressionMachine *machine); +static bool FIRCLSDwarfExpressionMachineExecute_plus(FIRCLSDwarfExpressionMachine *machine); +static bool FIRCLSDwarfExpressionMachineExecute_dup(FIRCLSDwarfExpressionMachine *machine); +static bool FIRCLSDwarfExpressionMachineExecute_swap(FIRCLSDwarfExpressionMachine *machine); +static bool FIRCLSDwarfExpressionMachineExecute_deref_size(FIRCLSDwarfExpressionMachine *machine); +static bool FIRCLSDwarfExpressionMachineExecute_ne(FIRCLSDwarfExpressionMachine *machine); +static bool FIRCLSDwarfExpressionMachineExecute_litN(FIRCLSDwarfExpressionMachine *machine, + uint8_t opcode); + +#pragma mark - +#pragma mark Stack Implementation +void FIRCLSDwarfExpressionStackInit(FIRCLSDwarfExpressionStack *stack) { + if (!FIRCLSIsValidPointer(stack)) { + return; + } + + memset(stack, 0, sizeof(FIRCLSDwarfExpressionStack)); + + stack->pointer = stack->buffer; +} + +bool FIRCLSDwarfExpressionStackIsValid(FIRCLSDwarfExpressionStack *stack) { + if (!FIRCLSIsValidPointer(stack)) { + return false; + } + + // check for valid stack pointer + if (stack->pointer < stack->buffer) { + return false; + } + + if (stack->pointer > stack->buffer + CLS_DWARF_EXPRESSION_STACK_SIZE) { + return false; + } + + return true; +} + +bool FIRCLSDwarfExpressionStackPush(FIRCLSDwarfExpressionStack *stack, intptr_t value) { + if (!FIRCLSDwarfExpressionStackIsValid(stack)) { + return false; + } + + if (stack->pointer == stack->buffer + CLS_DWARF_EXPRESSION_STACK_SIZE) { + // overflow + stack->pointer = NULL; + return false; + } + + *(stack->pointer) = value; + stack->pointer += 1; + + return true; +} + +intptr_t FIRCLSDwarfExpressionStackPeek(FIRCLSDwarfExpressionStack *stack) { + if (!FIRCLSDwarfExpressionStackIsValid(stack)) { + return 0; + } + + if (stack->pointer == stack->buffer) { + // underflow + stack->pointer = NULL; + return 0; + } + + return *(stack->pointer - 1); +} + +intptr_t FIRCLSDwarfExpressionStackPop(FIRCLSDwarfExpressionStack *stack) { + if (!FIRCLSDwarfExpressionStackIsValid(stack)) { + return 0; + } + + if (stack->pointer == stack->buffer) { + // underflow + stack->pointer = NULL; + return 0; + } + + stack->pointer -= 1; + + return *(stack->pointer); +} + +#pragma mark - +#pragma mark Machine API +bool FIRCLSDwarfExpressionMachineInit(FIRCLSDwarfExpressionMachine *machine, + const void *cursor, + const FIRCLSThreadContext *registers, + intptr_t stackValue) { + if (!FIRCLSIsValidPointer(machine)) { + return false; + } + + memset(machine, 0, sizeof(FIRCLSDwarfExpressionMachine)); + + if (!FIRCLSIsValidPointer(cursor)) { + return false; + } + + machine->dataCursor = cursor; + machine->registers = registers; + + FIRCLSDwarfExpressionStackInit(&machine->stack); + + return FIRCLSDwarfExpressionStackPush(&machine->stack, stackValue); +} + +bool FIRCLSDwarfExpressionMachinePrepareForExecution(FIRCLSDwarfExpressionMachine *machine) { + if (!FIRCLSIsValidPointer(machine)) { + FIRCLSSDKLog("Error: invalid inputs\n"); + return false; + } + + uint64_t expressionLength = FIRCLSParseULEB128AndAdvance(&machine->dataCursor); + + if (expressionLength == 0) { + FIRCLSSDKLog("Error: DWARF expression length is zero\n"); + return false; + } + + machine->endAddress = machine->dataCursor + expressionLength; + + return true; +} + +bool FIRCLSDwarfExpressionMachineIsFinished(FIRCLSDwarfExpressionMachine *machine) { + if (!FIRCLSIsValidPointer(machine)) { + FIRCLSSDKLog("Error: invalid inputs\n"); + return true; + } + + if (!FIRCLSIsValidPointer(machine->endAddress) || !FIRCLSIsValidPointer(machine->dataCursor)) { + FIRCLSSDKLog("Error: DWARF machine pointers invalid\n"); + return true; + } + + if (!FIRCLSDwarfExpressionStackIsValid(&machine->stack)) { + FIRCLSSDKLog("Error: DWARF machine stack invalid\n"); + return true; + } + + return machine->dataCursor >= machine->endAddress; +} + +bool FIRCLSDwarfExpressionMachineGetResult(FIRCLSDwarfExpressionMachine *machine, + intptr_t *result) { + if (!FIRCLSIsValidPointer(machine) || !FIRCLSIsValidPointer(result)) { + return false; + } + + if (machine->dataCursor != machine->endAddress) { + FIRCLSSDKLog("Error: DWARF expression hasn't completed execution\n"); + return false; + } + + *result = FIRCLSDwarfExpressionStackPeek(&machine->stack); + + return FIRCLSDwarfExpressionStackIsValid(&machine->stack); +} + +bool FIRCLSDwarfExpressionMachineExecuteNextOpcode(FIRCLSDwarfExpressionMachine *machine) { + if (!FIRCLSIsValidPointer(machine)) { + return false; + } + + const uint8_t opcode = FIRCLSParseUint8AndAdvance(&machine->dataCursor); + + bool success = false; + + switch (opcode) { + case DW_OP_deref: + success = FIRCLSDwarfExpressionMachineExecute_deref(machine); + break; + case DW_OP_dup: + success = FIRCLSDwarfExpressionMachineExecute_dup(machine); + break; + case DW_OP_and: + success = FIRCLSDwarfExpressionMachineExecute_and(machine); + break; + case DW_OP_plus: + success = FIRCLSDwarfExpressionMachineExecute_plus(machine); + break; + case DW_OP_swap: + success = FIRCLSDwarfExpressionMachineExecute_swap(machine); + break; + case DW_OP_plus_uconst: + success = FIRCLSDwarfExpressionMachineExecute_plus_uconst(machine); + break; + case DW_OP_ne: + success = FIRCLSDwarfExpressionMachineExecute_ne(machine); + break; + case DW_OP_lit0: + case DW_OP_lit1: + case DW_OP_lit2: + case DW_OP_lit3: + case DW_OP_lit4: + case DW_OP_lit5: + case DW_OP_lit6: + case DW_OP_lit7: + case DW_OP_lit8: + case DW_OP_lit9: + case DW_OP_lit10: + case DW_OP_lit11: + case DW_OP_lit12: + case DW_OP_lit13: + case DW_OP_lit14: + case DW_OP_lit15: + case DW_OP_lit16: + case DW_OP_lit17: + case DW_OP_lit18: + case DW_OP_lit19: + case DW_OP_lit20: + case DW_OP_lit21: + case DW_OP_lit22: + case DW_OP_lit23: + case DW_OP_lit24: + case DW_OP_lit25: + case DW_OP_lit26: + case DW_OP_lit27: + case DW_OP_lit28: + case DW_OP_lit29: + case DW_OP_lit30: + case DW_OP_lit31: + success = FIRCLSDwarfExpressionMachineExecute_litN(machine, opcode); + break; + case DW_OP_breg0: + case DW_OP_breg1: + case DW_OP_breg2: + case DW_OP_breg3: + case DW_OP_breg4: + case DW_OP_breg5: + case DW_OP_breg6: + case DW_OP_breg7: + case DW_OP_breg8: + case DW_OP_breg9: + case DW_OP_breg10: + case DW_OP_breg11: + case DW_OP_breg12: + case DW_OP_breg13: + case DW_OP_breg14: + case DW_OP_breg15: + case DW_OP_breg16: + case DW_OP_breg17: + case DW_OP_breg18: + case DW_OP_breg19: + case DW_OP_breg20: + case DW_OP_breg21: + case DW_OP_breg22: + case DW_OP_breg23: + case DW_OP_breg24: + case DW_OP_breg25: + case DW_OP_breg26: + case DW_OP_breg27: + case DW_OP_breg28: + case DW_OP_breg29: + case DW_OP_breg30: + case DW_OP_breg31: + success = FIRCLSDwarfExpressionMachineExecute_bregN(machine, opcode); + break; + case DW_OP_deref_size: + success = FIRCLSDwarfExpressionMachineExecute_deref_size(machine); + break; + default: + FIRCLSSDKLog("Error: Unrecognized DWARF expression opcode 0x%x\n", opcode); + return false; + } + + return success; +} + +#pragma mark - +#pragma mark Helpers +static intptr_t FIRCLSDwarfExpressionMachineStackPop(FIRCLSDwarfExpressionMachine *machine) { + return FIRCLSDwarfExpressionStackPop(&machine->stack); +} + +static bool FIRCLSDwarfExpressionMachineStackPush(FIRCLSDwarfExpressionMachine *machine, + intptr_t value) { + return FIRCLSDwarfExpressionStackPush(&machine->stack, value); +} + +#pragma mark - +#pragma mark Opcode Implementations +static bool FIRCLSDwarfExpressionMachineExecute_bregN(FIRCLSDwarfExpressionMachine *machine, + uint8_t opcode) { + // find the register number, compute offset value, push + const uint8_t regNum = opcode - DW_OP_breg0; + + if (regNum > CLS_DWARF_MAX_REGISTER_NUM) { + FIRCLSSDKLog("Error: DW_OP_breg invalid register number\n"); + return false; + } + + int64_t offset = FIRCLSParseLEB128AndAdvance(&machine->dataCursor); + + FIRCLSSDKLog("DW_OP_breg %d value %d\n", regNum, (int)offset); + + const intptr_t value = + FIRCLSDwarfUnwindGetRegisterValue(machine->registers, regNum) + (intptr_t)offset; + + return FIRCLSDwarfExpressionMachineStackPush(machine, value); +} + +static bool FIRCLSDwarfExpressionMachineExecute_deref(FIRCLSDwarfExpressionMachine *machine) { + // pop stack, dereference, push result + intptr_t value = FIRCLSDwarfExpressionMachineStackPop(machine); + + FIRCLSSDKLog("DW_OP_deref value %p\n", (void *)value); + + if (!FIRCLSReadMemory(value, &value, sizeof(value))) { + FIRCLSSDKLog("Error: DW_OP_deref failed to read memory\n"); + return false; + } + + return FIRCLSDwarfExpressionMachineStackPush(machine, value); +} + +static bool FIRCLSDwarfExpressionMachineExecute_plus_uconst(FIRCLSDwarfExpressionMachine *machine) { + // pop stack, add constant, push result + intptr_t value = FIRCLSDwarfExpressionMachineStackPop(machine); + + value += FIRCLSParseULEB128AndAdvance(&machine->dataCursor); + + FIRCLSSDKLog("DW_OP_plus_uconst value %lu\n", value); + + return FIRCLSDwarfExpressionMachineStackPush(machine, value); +} + +static bool FIRCLSDwarfExpressionMachineExecute_and(FIRCLSDwarfExpressionMachine *machine) { + FIRCLSSDKLog("DW_OP_plus_and\n"); + + intptr_t value = FIRCLSDwarfExpressionMachineStackPop(machine); + + value = value & FIRCLSDwarfExpressionMachineStackPop(machine); + + return FIRCLSDwarfExpressionMachineStackPush(machine, value); +} + +static bool FIRCLSDwarfExpressionMachineExecute_plus(FIRCLSDwarfExpressionMachine *machine) { + FIRCLSSDKLog("DW_OP_plus\n"); + + intptr_t value = FIRCLSDwarfExpressionMachineStackPop(machine); + + value = value + FIRCLSDwarfExpressionMachineStackPop(machine); + + return FIRCLSDwarfExpressionMachineStackPush(machine, value); +} + +static bool FIRCLSDwarfExpressionMachineExecute_dup(FIRCLSDwarfExpressionMachine *machine) { + // duplicate top of stack + intptr_t value = FIRCLSDwarfExpressionStackPeek(&machine->stack); + + FIRCLSSDKLog("DW_OP_dup value %lu\n", value); + + return FIRCLSDwarfExpressionMachineStackPush(machine, value); +} + +static bool FIRCLSDwarfExpressionMachineExecute_swap(FIRCLSDwarfExpressionMachine *machine) { + // swap top two values on the stack + intptr_t valueA = FIRCLSDwarfExpressionMachineStackPop(machine); + intptr_t valueB = FIRCLSDwarfExpressionMachineStackPop(machine); + + FIRCLSSDKLog("DW_OP_swap\n"); + + if (!FIRCLSDwarfExpressionMachineStackPush(machine, valueA)) { + return false; + } + + return FIRCLSDwarfExpressionMachineStackPush(machine, valueB); +} + +static bool FIRCLSDwarfExpressionMachineExecute_deref_size(FIRCLSDwarfExpressionMachine *machine) { + // pop stack, dereference variable sized value, push result + const void *address = (const void *)FIRCLSDwarfExpressionMachineStackPop(machine); + const uint8_t readSize = FIRCLSParseUint8AndAdvance(&machine->dataCursor); + intptr_t value = 0; + + FIRCLSSDKLog("DW_OP_deref_size %p size %u\n", address, readSize); + + switch (readSize) { + case 1: + value = FIRCLSParseUint8AndAdvance(&address); + break; + case 2: + value = FIRCLSParseUint16AndAdvance(&address); + break; + case 4: + value = FIRCLSParseUint32AndAdvance(&address); + break; + case 8: + // this is a little funky, as an 8 here really doesn't make sense for 32-bit platforms + value = (intptr_t)FIRCLSParseUint64AndAdvance(&address); + break; + default: + FIRCLSSDKLog("Error: unrecognized DW_OP_deref_size argument %x\n", readSize); + return false; + } + + return FIRCLSDwarfExpressionMachineStackPush(machine, value); +} + +static bool FIRCLSDwarfExpressionMachineExecute_ne(FIRCLSDwarfExpressionMachine *machine) { + FIRCLSSDKLog("DW_OP_ne\n"); + + intptr_t value = FIRCLSDwarfExpressionMachineStackPop(machine); + + value = value != FIRCLSDwarfExpressionMachineStackPop(machine); + + return FIRCLSDwarfExpressionMachineStackPush(machine, value); +} + +static bool FIRCLSDwarfExpressionMachineExecute_litN(FIRCLSDwarfExpressionMachine *machine, + uint8_t opcode) { + const uint8_t value = opcode - DW_OP_lit0; + + FIRCLSSDKLog("DW_OP_lit %u\n", value); + + return FIRCLSDwarfExpressionMachineStackPush(machine, value); +} + +#else +INJECT_STRIP_SYMBOL(dwarf_expression_machine) +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfExpressionMachine.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfExpressionMachine.h new file mode 100644 index 000000000..7dd70f847 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfExpressionMachine.h @@ -0,0 +1,55 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include <stdbool.h> +#include <stdint.h> + +#include "FIRCLSFeatures.h" +#include "FIRCLSThreadState.h" + +#define CLS_DWARF_EXPRESSION_STACK_SIZE (100) + +#if CLS_DWARF_UNWINDING_SUPPORTED + +typedef struct { + intptr_t buffer[CLS_DWARF_EXPRESSION_STACK_SIZE]; + intptr_t *pointer; +} FIRCLSDwarfExpressionStack; + +typedef struct { + FIRCLSDwarfExpressionStack stack; + const void *dataCursor; + const void *endAddress; + const FIRCLSThreadContext *registers; +} FIRCLSDwarfExpressionMachine; + +void FIRCLSDwarfExpressionStackInit(FIRCLSDwarfExpressionStack *stack); +bool FIRCLSDwarfExpressionStackIsValid(FIRCLSDwarfExpressionStack *stack); +bool FIRCLSDwarfExpressionStackPush(FIRCLSDwarfExpressionStack *stack, intptr_t value); +intptr_t FIRCLSDwarfExpressionStackPeek(FIRCLSDwarfExpressionStack *stack); +intptr_t FIRCLSDwarfExpressionStackPop(FIRCLSDwarfExpressionStack *stack); + +bool FIRCLSDwarfExpressionMachineInit(FIRCLSDwarfExpressionMachine *machine, + const void *cursor, + const FIRCLSThreadContext *registers, + intptr_t stackValue); +bool FIRCLSDwarfExpressionMachinePrepareForExecution(FIRCLSDwarfExpressionMachine *machine); +bool FIRCLSDwarfExpressionMachineIsFinished(FIRCLSDwarfExpressionMachine *machine); +bool FIRCLSDwarfExpressionMachineGetResult(FIRCLSDwarfExpressionMachine *machine, intptr_t *result); + +bool FIRCLSDwarfExpressionMachineExecuteNextOpcode(FIRCLSDwarfExpressionMachine *machine); + +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwind.c b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwind.c new file mode 100644 index 000000000..665e8aaa9 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwind.c @@ -0,0 +1,1002 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSDwarfUnwind.h" +#include "FIRCLSDataParsing.h" +#include "FIRCLSDefines.h" +#include "FIRCLSDwarfExpressionMachine.h" +#include "FIRCLSFeatures.h" +#include "FIRCLSUnwind_arch.h" +#include "FIRCLSUtility.h" +#include "dwarf.h" + +#include <string.h> + +#if CLS_DWARF_UNWINDING_SUPPORTED + +#define FIRCLSDwarfLog(__FORMAT__, ...) FIRCLSSDKLog(__FORMAT__, ##__VA_ARGS__) + +#define CLS_DWARF_EXPRESSION_STACK_SIZE (100) + +#pragma mark Prototypes +static bool FIRCLSDwarfParseAndProcessAugmentation(DWARFCIERecord* record, const void** ptr); + +#pragma mark - Record Parsing +bool FIRCLSDwarfParseCIERecord(DWARFCIERecord* cie, const void* ptr) { + if (!cie || !ptr) { + return false; + } + + memset(cie, 0, sizeof(DWARFCIERecord)); + + cie->length = FIRCLSParseRecordLengthAndAdvance(&ptr); + if (cie->length == 0) { + FIRCLSSDKLog("Error: CIE length invalid\n"); + return false; + } + + // the length does not include the length field(s) themselves + const void* endAddress = ptr + cie->length; + + if (FIRCLSParseUint32AndAdvance(&ptr) != DWARF_CIE_ID_CIE_FLAG) { + FIRCLSSDKLog("Error: CIE flag not found\n"); + } + + cie->version = FIRCLSParseUint8AndAdvance(&ptr); + if (cie->version != 1 && cie->version != 3) { + FIRCLSSDKLog("Error: CIE version %u unsupported\n", cie->version); + } + + cie->pointerEncoding = DW_EH_PE_absptr; + cie->lsdaEncoding = DW_EH_PE_absptr; + + cie->augmentation = FIRCLSParseStringAndAdvance(&ptr); + cie->codeAlignFactor = FIRCLSParseULEB128AndAdvance(&ptr); + cie->dataAlignFactor = FIRCLSParseLEB128AndAdvance(&ptr); + + switch (cie->version) { + case 1: + cie->returnAddressRegister = FIRCLSParseUint8AndAdvance(&ptr); + break; + case 3: + cie->returnAddressRegister = FIRCLSParseULEB128AndAdvance(&ptr); + break; + default: + FIRCLSSDKLog("Error: CIE version %u unsupported\n", cie->version); + return false; + } + + if (!FIRCLSDwarfParseAndProcessAugmentation(cie, &ptr)) { + return false; + } + + cie->instructions.data = ptr; + cie->instructions.length = (uint32_t)(endAddress - ptr); + + return true; +} + +static bool FIRCLSDwarfParseAndProcessAugmentation(DWARFCIERecord* record, const void** ptr) { + if (!record || !ptr) { + return false; + } + + if (!record->augmentation) { + return false; + } + + if (record->augmentation[0] == 0) { + return true; + } + + if (record->augmentation[0] != 'z') { + FIRCLSSDKLog("Error: Unimplemented: augmentation string %s\n", record->augmentation); + return false; + } + + size_t stringLength = strlen(record->augmentation); + + uint64_t dataLength = FIRCLSParseULEB128AndAdvance(ptr); + const void* ending = *ptr + dataLength; + + // start at 1 because we know the first character is a 'z' + for (size_t i = 1; i < stringLength; ++i) { + switch (record->augmentation[i]) { + case 'L': + // There is an LSDA pointer encoding present. The actual address of the LSDA + // is in the FDE + record->lsdaEncoding = FIRCLSParseUint8AndAdvance(ptr); + break; + case 'R': + // There is a pointer encoding present, used for all addresses in an FDE. + record->pointerEncoding = FIRCLSParseUint8AndAdvance(ptr); + break; + case 'P': + // Two arguments. A pointer encoding, and a pointer to a personality function encoded + // with that value. + record->personalityEncoding = FIRCLSParseUint8AndAdvance(ptr); + record->personalityFunction = + FIRCLSParseAddressWithEncodingAndAdvance(ptr, record->personalityEncoding); + if (record->personalityFunction == CLS_INVALID_ADDRESS) { + FIRCLSSDKLog("Error: Found an invalid start address\n"); + return false; + } + break; + case 'S': + record->signalFrame = true; + break; + default: + FIRCLSSDKLog("Error: Unhandled augmentation string entry %c\n", record->augmentation[i]); + return false; + } + + // small sanity check + if (*ptr > ending) { + return false; + } + } + + return true; +} + +bool FIRCLSDwarfParseFDERecord(DWARFFDERecord* fdeRecord, + bool parseCIE, + DWARFCIERecord* cieRecord, + const void* ptr) { + if (!fdeRecord || !cieRecord || !ptr) { + return false; + } + + fdeRecord->length = FIRCLSParseRecordLengthAndAdvance(&ptr); + if (fdeRecord->length == 0) { + FIRCLSSDKLog("Error: FDE has zero length\n"); + return false; + } + + // length does not include length field + const void* endAddress = ptr + fdeRecord->length; + + // According to the spec, this is 32/64 bit value, but libunwind always + // parses this as a 32bit value. + fdeRecord->cieOffset = FIRCLSParseUint32AndAdvance(&ptr); + if (fdeRecord->cieOffset == 0) { + FIRCLSSDKLog("Error: CIE offset invalid\n"); + return false; + } + + if (parseCIE) { + // The CIE offset is really weird. It appears to be an offset from the + // beginning of its field. This isn't what the documentation says, but it is + // a little ambigious. This is what DwarfParser.hpp does. + // Note that we have to back up one sizeof(uint32_t), because we've advanced + // by parsing the offset + const void* ciePointer = ptr - fdeRecord->cieOffset - sizeof(uint32_t); + if (!FIRCLSDwarfParseCIERecord(cieRecord, ciePointer)) { + FIRCLSSDKLog("Error: Unable to parse CIE record\n"); + return false; + } + } + + if (!FIRCLSDwarfCIEIsValid(cieRecord)) { + FIRCLSSDKLog("Error: CIE invalid\n"); + return false; + } + + // the next field depends on the pointer encoding style used + fdeRecord->startAddress = + FIRCLSParseAddressWithEncodingAndAdvance(&ptr, cieRecord->pointerEncoding); + if (fdeRecord->startAddress == CLS_INVALID_ADDRESS) { + FIRCLSSDKLog("Error: Found an invalid start address\n"); + return false; + } + + // Here's something weird too. The range is encoded as a "special" address, where only the value + // is used, regardless of other pointer-encoding schemes. + fdeRecord->rangeSize = FIRCLSParseAddressWithEncodingAndAdvance( + &ptr, cieRecord->pointerEncoding & DW_EH_PE_VALUE_MASK); + if (fdeRecord->rangeSize == CLS_INVALID_ADDRESS) { + FIRCLSSDKLog("Error: Found an invalid address range\n"); + return false; + } + + // Just skip over the section for now. The data here is only needed for personality functions, + // which we don't need + if (FIRCLSDwarfCIEHasAugmentationData(cieRecord)) { + uintptr_t augmentationLength = (uintptr_t)FIRCLSParseULEB128AndAdvance(&ptr); + + ptr += augmentationLength; + } + + fdeRecord->instructions.data = ptr; + fdeRecord->instructions.length = (uint32_t)(endAddress - ptr); + + return true; +} + +bool FIRCLSDwarfParseCFIFromFDERecord(FIRCLSDwarfCFIRecord* record, const void* ptr) { + if (!record || !ptr) { + return false; + } + + return FIRCLSDwarfParseFDERecord(&record->fde, true, &record->cie, ptr); +} + +bool FIRCLSDwarfParseCFIFromFDERecordOffset(FIRCLSDwarfCFIRecord* record, + const void* ehFrame, + uintptr_t fdeOffset) { + if (!record || !ehFrame || (fdeOffset == 0)) { + return false; + } + + const void* ptr = ehFrame + fdeOffset; + + return FIRCLSDwarfParseCFIFromFDERecord(record, ptr); +} + +#pragma mark - Properties +bool FIRCLSDwarfCIEIsValid(DWARFCIERecord* cie) { + if (!cie) { + return false; + } + + if (cie->length == 0) { + return false; + } + + if (cie->version != 1 && cie->version != 3) { + return false; + } + + return true; +} + +bool FIRCLSDwarfCIEHasAugmentationData(DWARFCIERecord* cie) { + if (!cie) { + return false; + } + + if (!cie->augmentation) { + return false; + } + + return cie->augmentation[0] == 'z'; +} + +#pragma mark - Instructions + +static bool FIRCLSDwarfParseAndExecute_set_loc(const void** cursor, + DWARFCIERecord* cieRecord, + intptr_t* codeOffset) { + uintptr_t operand = FIRCLSParseAddressWithEncodingAndAdvance(cursor, cieRecord->pointerEncoding); + + *codeOffset = operand; + + FIRCLSDwarfLog("DW_CFA_set_loc %lu\n", operand); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_advance_loc1(const void** cursor, + DWARFCIERecord* cieRecord, + intptr_t* codeOffset) { + int64_t offset = FIRCLSParseUint8AndAdvance(cursor) * cieRecord->codeAlignFactor; + + *codeOffset += offset; + + FIRCLSDwarfLog("DW_CFA_advance_loc1 %lld\n", offset); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_advance_loc2(const void** cursor, + DWARFCIERecord* cieRecord, + intptr_t* codeOffset) { + int64_t offset = FIRCLSParseUint16AndAdvance(cursor) * cieRecord->codeAlignFactor; + + *codeOffset += offset; + + FIRCLSDwarfLog("DW_CFA_advance_loc2 %lld\n", offset); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_advance_loc4(const void** cursor, + DWARFCIERecord* cieRecord, + intptr_t* codeOffset) { + int64_t offset = FIRCLSParseUint32AndAdvance(cursor) * cieRecord->codeAlignFactor; + + *codeOffset += offset; + + FIRCLSDwarfLog("DW_CFA_advance_loc4 %lld\n", offset); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_def_cfa(const void** cursor, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state) { + uint64_t regNum = FIRCLSParseULEB128AndAdvance(cursor); + + if (regNum > CLS_DWARF_MAX_REGISTER_NUM) { + FIRCLSSDKLog("Error: Found an invalid DW_CFA_def_cfa register number\n"); + return false; + } + + int64_t offset = FIRCLSParseULEB128AndAdvance(cursor); + + state->cfaRegister = regNum; + state->cfaRegisterOffset = offset; + + FIRCLSDwarfLog("DW_CFA_def_cfa %llu, %lld\n", regNum, offset); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_def_cfa_register(const void** cursor, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state) { + uint64_t regNum = FIRCLSParseULEB128AndAdvance(cursor); + + if (regNum > CLS_DWARF_MAX_REGISTER_NUM) { + FIRCLSSDKLog("Error: Found an invalid DW_CFA_def_cfa_register register number\n"); + return false; + } + + state->cfaRegister = regNum; + + FIRCLSDwarfLog("DW_CFA_def_cfa_register %llu\n", regNum); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_def_cfa_offset(const void** cursor, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state) { + uint64_t offset = FIRCLSParseULEB128AndAdvance(cursor); + + state->cfaRegisterOffset = offset; + + FIRCLSDwarfLog("DW_CFA_def_cfa_offset %lld\n", offset); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_same_value(const void** cursor, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state) { + uint64_t regNum = FIRCLSParseULEB128AndAdvance(cursor); + + if (regNum > CLS_DWARF_MAX_REGISTER_NUM) { + FIRCLSSDKLog("Error: Found an invalid DW_CFA_same_value register number\n"); + return false; + } + + state->registers[regNum].location = FIRCLSDwarfRegisterUnused; + + FIRCLSDwarfLog("DW_CFA_same_value %llu\n", regNum); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_register(const void** cursor, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state) { + uint64_t regNum = FIRCLSParseULEB128AndAdvance(cursor); + + if (regNum > CLS_DWARF_MAX_REGISTER_NUM) { + FIRCLSSDKLog("Error: Found an invalid DW_CFA_register number\n"); + return false; + } + + uint64_t regValue = FIRCLSParseULEB128AndAdvance(cursor); + + if (regValue > CLS_DWARF_MAX_REGISTER_NUM) { + FIRCLSSDKLog("Error: Found an invalid DW_CFA_register value\n"); + return false; + } + + state->registers[regNum].location = FIRCLSDwarfRegisterInRegister; + state->registers[regNum].value = regValue; + + FIRCLSDwarfLog("DW_CFA_register %llu %llu\n", regNum, regValue); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_expression(const void** cursor, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state) { + uint64_t regNum = FIRCLSParseULEB128AndAdvance(cursor); + + if (regNum > CLS_DWARF_MAX_REGISTER_NUM) { + FIRCLSSDKLog("Error: Found an invalid DW_CFA_expression register number\n"); + return false; + } + + state->registers[regNum].location = FIRCLSDwarfRegisterAtExpression; + state->registers[regNum].value = (uintptr_t)*cursor; + + // read the length of the expression, and advance past it + uint64_t length = FIRCLSParseULEB128AndAdvance(cursor); + *cursor += length; + + FIRCLSDwarfLog("DW_CFA_expression %llu %llu\n", regNum, length); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_val_expression(const void** cursor, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state) { + uint64_t regNum = FIRCLSParseULEB128AndAdvance(cursor); + + if (regNum > CLS_DWARF_MAX_REGISTER_NUM) { + FIRCLSSDKLog("Error: Found an invalid DW_CFA_val_expression register number\n"); + return false; + } + + state->registers[regNum].location = FIRCLSDwarfRegisterIsExpression; + state->registers[regNum].value = (uintptr_t)*cursor; + + // read the length of the expression, and advance past it + uint64_t length = FIRCLSParseULEB128AndAdvance(cursor); + *cursor += length; + + FIRCLSDwarfLog("DW_CFA_val_expression %llu %llu\n", regNum, length); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_def_cfa_expression(const void** cursor, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state) { + state->cfaRegister = CLS_DWARF_INVALID_REGISTER_NUM; + state->cfaExpression = *cursor; + + // read the length of the expression, and advance past it + uint64_t length = FIRCLSParseULEB128AndAdvance(cursor); + *cursor += length; + + FIRCLSDwarfLog("DW_CFA_def_cfa_expression %llu\n", length); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_offset(const void** cursor, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state, + uint8_t regNum) { + if (regNum > CLS_DWARF_MAX_REGISTER_NUM) { + FIRCLSSDKLog("Error: Found an invalid DW_CFA_offset register number\n"); + return false; + } + + int64_t offset = FIRCLSParseULEB128AndAdvance(cursor) * cieRecord->dataAlignFactor; + + state->registers[regNum].location = FIRCLSDwarfRegisterInCFA; + state->registers[regNum].value = offset; + + FIRCLSDwarfLog("DW_CFA_offset %u, %lld\n", regNum, offset); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_advance_loc(const void** cursor, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state, + uint8_t delta, + intptr_t* codeOffset) { + if (!FIRCLSIsValidPointer(codeOffset) || !FIRCLSIsValidPointer(cieRecord)) { + FIRCLSSDKLog("Error: invalid inputs\n"); + return false; + } + + *codeOffset = delta * (intptr_t)cieRecord->codeAlignFactor; + + FIRCLSDwarfLog("DW_CFA_advance_loc %u\n", delta); + + return true; +} + +static bool FIRCLSDwarfParseAndExecuteInstructionWithOperand(const void** cursor, + uint8_t instruction, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state, + intptr_t* codeOffset) { + uint8_t operand = instruction & DW_CFA_OPERAND_MASK; + bool success = false; + + switch (instruction & DW_CFA_OPCODE_MASK) { + case DW_CFA_offset: + success = FIRCLSDwarfParseAndExecute_offset(cursor, cieRecord, state, operand); + break; + case DW_CFA_advance_loc: + success = + FIRCLSDwarfParseAndExecute_advance_loc(cursor, cieRecord, state, operand, codeOffset); + break; + case DW_CFA_restore: + FIRCLSSDKLog("Error: Unimplemented DWARF instruction with operand 0x%x\n", instruction); + break; + default: + FIRCLSSDKLog("Error: Unrecognized DWARF instruction 0x%x\n", instruction); + break; + } + + return success; +} + +#pragma mark - Expressions +static bool FIRCLSDwarfEvalulateExpression(const void* cursor, + const FIRCLSThreadContext* registers, + intptr_t stackValue, + intptr_t* result) { + FIRCLSDwarfLog("starting at %p with initial value %lx\n", cursor, stackValue); + + if (!FIRCLSIsValidPointer(cursor) || !FIRCLSIsValidPointer(result)) { + FIRCLSSDKLog("Error: inputs invalid\n"); + return false; + } + + FIRCLSDwarfExpressionMachine machine; + + if (!FIRCLSDwarfExpressionMachineInit(&machine, cursor, registers, stackValue)) { + FIRCLSSDKLog("Error: unable to init DWARF expression machine\n"); + return false; + } + + if (!FIRCLSDwarfExpressionMachinePrepareForExecution(&machine)) { + FIRCLSSDKLog("Error: unable to prepare for execution\n"); + return false; + } + + while (!FIRCLSDwarfExpressionMachineIsFinished(&machine)) { + if (!FIRCLSDwarfExpressionMachineExecuteNextOpcode(&machine)) { + FIRCLSSDKLog("Error: failed to execute DWARF machine opcode\n"); + return false; + } + } + + if (!FIRCLSDwarfExpressionMachineGetResult(&machine, result)) { + FIRCLSSDKLog("Error: failed to get DWARF expression result\n"); + return false; + } + + FIRCLSDwarfLog("successfully computed expression result\n"); + + return true; +} + +#pragma mark - Execution +bool FIRCLSDwarfInstructionsEnumerate(DWARFInstructions* instructions, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state, + intptr_t pcOffset) { + if (!instructions || !cieRecord || !state) { + FIRCLSSDKLog("Error: inputs invalid\n"); + return false; + } + + // This is a little bit of state that can't be put into the state structure, because + // it is possible for instructions to push/pop state that does not affect this value. + intptr_t codeOffset = 0; + + const void* cursor = instructions->data; + const void* endAddress = cursor + instructions->length; + + FIRCLSDwarfLog("Running instructions from %p to %p\n", cursor, endAddress); + + // parse the instructions, as long as: + // - our data pointer is still in range + // - the pc offset is within the range of instructions that apply + + while ((cursor < endAddress) && (codeOffset < pcOffset)) { + uint8_t instruction = FIRCLSParseUint8AndAdvance(&cursor); + bool success = false; + + switch (instruction) { + case DW_CFA_nop: + FIRCLSDwarfLog("DW_CFA_nop\n"); + continue; + case DW_CFA_set_loc: + success = FIRCLSDwarfParseAndExecute_set_loc(&cursor, cieRecord, &codeOffset); + break; + case DW_CFA_advance_loc1: + success = FIRCLSDwarfParseAndExecute_advance_loc1(&cursor, cieRecord, &codeOffset); + break; + case DW_CFA_advance_loc2: + success = FIRCLSDwarfParseAndExecute_advance_loc2(&cursor, cieRecord, &codeOffset); + break; + case DW_CFA_advance_loc4: + success = FIRCLSDwarfParseAndExecute_advance_loc4(&cursor, cieRecord, &codeOffset); + break; + case DW_CFA_def_cfa: + success = FIRCLSDwarfParseAndExecute_def_cfa(&cursor, cieRecord, state); + break; + case DW_CFA_def_cfa_register: + success = FIRCLSDwarfParseAndExecute_def_cfa_register(&cursor, cieRecord, state); + break; + case DW_CFA_def_cfa_offset: + success = FIRCLSDwarfParseAndExecute_def_cfa_offset(&cursor, cieRecord, state); + break; + case DW_CFA_same_value: + success = FIRCLSDwarfParseAndExecute_same_value(&cursor, cieRecord, state); + break; + case DW_CFA_register: + success = FIRCLSDwarfParseAndExecute_register(&cursor, cieRecord, state); + break; + case DW_CFA_def_cfa_expression: + success = FIRCLSDwarfParseAndExecute_def_cfa_expression(&cursor, cieRecord, state); + break; + case DW_CFA_expression: + success = FIRCLSDwarfParseAndExecute_expression(&cursor, cieRecord, state); + break; + case DW_CFA_val_expression: + success = FIRCLSDwarfParseAndExecute_val_expression(&cursor, cieRecord, state); + break; + case DW_CFA_offset_extended: + case DW_CFA_restore_extended: + case DW_CFA_undefined: + case DW_CFA_remember_state: + case DW_CFA_restore_state: + case DW_CFA_offset_extended_sf: + case DW_CFA_def_cfa_sf: + case DW_CFA_def_cfa_offset_sf: + case DW_CFA_val_offset: + case DW_CFA_val_offset_sf: + case DW_CFA_GNU_window_save: + case DW_CFA_GNU_args_size: + case DW_CFA_GNU_negative_offset_extended: + FIRCLSSDKLog("Error: Unimplemented DWARF instruction 0x%x\n", instruction); + return false; + default: + success = FIRCLSDwarfParseAndExecuteInstructionWithOperand(&cursor, instruction, cieRecord, + state, &codeOffset); + break; + } + + if (!success) { + FIRCLSSDKLog("Error: Failed to execute dwarf instruction 0x%x\n", instruction); + return false; + } + } + + return true; +} + +bool FIRCLSDwarfUnwindComputeRegisters(FIRCLSDwarfCFIRecord* record, + FIRCLSThreadContext* registers) { + if (!record || !registers) { + return false; + } + + // We need to run the dwarf instructions to compute our register values. + // - initialize state + // - run the CIE instructions + // - run the FDE instructions + // - grab the values + + FIRCLSDwarfState state; + + memset(&state, 0, sizeof(FIRCLSDwarfState)); + + // We need to run all the instructions in the CIE record. So, pass in a large value for the pc + // offset so we don't stop early. + if (!FIRCLSDwarfInstructionsEnumerate(&record->cie.instructions, &record->cie, &state, + INTPTR_MAX)) { + FIRCLSSDKLog("Error: Unable to run CIE instructions\n"); + return false; + } + + intptr_t pcOffset = FIRCLSThreadContextGetPC(registers) - record->fde.startAddress; + if (pcOffset < 0) { + FIRCLSSDKLog("Error: The FDE pcOffset value cannot be negative\n"); + return false; + } + + if (!FIRCLSDwarfInstructionsEnumerate(&record->fde.instructions, &record->cie, &state, + pcOffset)) { + FIRCLSSDKLog("Error: Unable to run FDE instructions\n"); + return false; + } + + uintptr_t cfaRegister = 0; + + if (!FIRCLSDwarfGetCFA(&state, registers, &cfaRegister)) { + FIRCLSSDKLog("Error: failed to get CFA\n"); + return false; + } + + if (!FIRCLSDwarfUnwindAssignRegisters(&state, registers, cfaRegister, registers)) { + FIRCLSSDKLogError("Error: Unable to assign DWARF registers\n"); + return false; + } + + return true; +} + +bool FIRCLSDwarfUnwindAssignRegisters(const FIRCLSDwarfState* state, + const FIRCLSThreadContext* registers, + uintptr_t cfaRegister, + FIRCLSThreadContext* outputRegisters) { + if (!FIRCLSIsValidPointer(state) || !FIRCLSIsValidPointer(registers)) { + FIRCLSSDKLogError("Error: input invalid\n"); + return false; + } + + // make a copy, which we'll be changing + FIRCLSThreadContext newThreadState = *registers; + + // loop through all the registers, so we can set their values + for (size_t i = 0; i <= CLS_DWARF_MAX_REGISTER_NUM; ++i) { + if (state->registers[i].location == FIRCLSDwarfRegisterUnused) { + continue; + } + + const uintptr_t value = + FIRCLSDwarfGetSavedRegister(registers, cfaRegister, state->registers[i]); + + if (!FIRCLSDwarfUnwindSetRegisterValue(&newThreadState, i, value)) { + FIRCLSSDKLog("Error: Unable to restore register value\n"); + return false; + } + } + + if (!FIRCLSDwarfUnwindSetRegisterValue(&newThreadState, CLS_DWARF_REG_SP, cfaRegister)) { + FIRCLSSDKLog("Error: Unable to restore SP value\n"); + return false; + } + + // sanity-check that things have changed + if (FIRCLSDwarfCompareRegisters(registers, &newThreadState, CLS_DWARF_REG_SP)) { + FIRCLSSDKLog("Error: Stack pointer hasn't changed\n"); + return false; + } + + if (FIRCLSDwarfCompareRegisters(registers, &newThreadState, CLS_DWARF_REG_RETURN)) { + FIRCLSSDKLog("Error: PC hasn't changed\n"); + return false; + } + + // set our new value + *outputRegisters = newThreadState; + + return true; +} + +#pragma mark - Register Operations +bool FIRCLSDwarfCompareRegisters(const FIRCLSThreadContext* a, + const FIRCLSThreadContext* b, + uint64_t registerNum) { + return FIRCLSDwarfUnwindGetRegisterValue(a, registerNum) == + FIRCLSDwarfUnwindGetRegisterValue(b, registerNum); +} + +bool FIRCLSDwarfGetCFA(FIRCLSDwarfState* state, + const FIRCLSThreadContext* registers, + uintptr_t* cfa) { + if (!FIRCLSIsValidPointer(state) || !FIRCLSIsValidPointer(registers) || + !FIRCLSIsValidPointer(cfa)) { + FIRCLSSDKLog("Error: invalid input\n"); + return false; + } + + if (state->cfaExpression) { + if (!FIRCLSDwarfEvalulateExpression(state->cfaExpression, registers, 0, (intptr_t*)cfa)) { + FIRCLSSDKLog("Error: failed to compute CFA expression\n"); + return false; + } + + return true; + } + + // libunwind checks that cfaRegister is not zero. This seems like a potential bug - why couldn't + // it be zero? + + *cfa = FIRCLSDwarfUnwindGetRegisterValue(registers, state->cfaRegister) + + (uintptr_t)state->cfaRegisterOffset; + + return true; +} + +uintptr_t FIRCLSDwarfGetSavedRegister(const FIRCLSThreadContext* registers, + uintptr_t cfaRegister, + FIRCLSDwarfRegister dRegister) { + intptr_t result = 0; + + FIRCLSDwarfLog("Getting register %x\n", dRegister.location); + + switch (dRegister.location) { + case FIRCLSDwarfRegisterInCFA: { + const uintptr_t address = cfaRegister + (uintptr_t)dRegister.value; + + if (!FIRCLSReadMemory(address, &result, sizeof(result))) { + FIRCLSSDKLog("Error: Unable to read CFA value\n"); + return 0; + } + } + return result; + case FIRCLSDwarfRegisterInRegister: + return FIRCLSDwarfUnwindGetRegisterValue(registers, dRegister.value); + case FIRCLSDwarfRegisterOffsetFromCFA: + FIRCLSSDKLog("Error: OffsetFromCFA unhandled\n"); + break; + case FIRCLSDwarfRegisterAtExpression: + if (!FIRCLSDwarfEvalulateExpression((void*)dRegister.value, registers, cfaRegister, + &result)) { + FIRCLSSDKLog("Error: unable to evaluate expression\n"); + return 0; + } + + if (!FIRCLSReadMemory(result, &result, sizeof(result))) { + FIRCLSSDKLog("Error: Unable to read memory computed from expression\n"); + return 0; + } + + return result; + case FIRCLSDwarfRegisterIsExpression: + if (!FIRCLSDwarfEvalulateExpression((void*)dRegister.value, registers, cfaRegister, + &result)) { + FIRCLSSDKLog("Error: unable to evaluate expression\n"); + return 0; + } + + return result; + default: + FIRCLSSDKLog("Error: Unrecognized register save location 0x%x\n", dRegister.location); + break; + } + + return 0; +} + +#if DEBUG +#pragma mark - Debugging +void FIRCLSCFIRecordShow(FIRCLSDwarfCFIRecord* record) { + if (!record) { + FIRCLSSDKLog("Error: CFI record: null\n"); + return; + } + + FIRCLSCIERecordShow(&record->cie); + FIRCLSFDERecordShow(&record->fde, &record->cie); +} + +void FIRCLSCIERecordShow(DWARFCIERecord* record) { + if (!record) { + FIRCLSSDKLog("Error: CIE: null\n"); + return; + } + + FIRCLSSDKLog("CIE:\n"); + FIRCLSSDKLog(" length: %llu\n", record->length); + FIRCLSSDKLog(" version: %u\n", record->version); + FIRCLSSDKLog(" augmentation: %s\n", record->augmentation); + FIRCLSSDKLog(" EH Data: 0x%04lx\n", record->ehData); + FIRCLSSDKLog("LSDA encoding: 0x%02x\n", record->lsdaEncoding); + FIRCLSSDKLog(" personality: 0x%lx\n", record->personalityFunction); + + FIRCLSDwarfPointerEncodingShow(" encoding", record->pointerEncoding); + FIRCLSDwarfPointerEncodingShow(" P encoding", record->personalityEncoding); + + FIRCLSSDKLog(" code align: %llu\n", record->codeAlignFactor); + FIRCLSSDKLog(" data align: %lld\n", record->dataAlignFactor); + FIRCLSSDKLog(" RA register: %llu\n", record->returnAddressRegister); + + FIRCLSDwarfInstructionsShow(&record->instructions, record); +} + +void FIRCLSFDERecordShow(DWARFFDERecord* record, DWARFCIERecord* cie) { + if (!record) { + FIRCLSSDKLog("FDE: null\n"); + return; + } + + FIRCLSSDKLog("FDE:\n"); + FIRCLSSDKLog(" length: %llu\n", record->length); + FIRCLSSDKLog(" CIE offset: %llu\n", record->cieOffset); + FIRCLSSDKLog(" start addr: 0x%lx\n", record->startAddress); + FIRCLSSDKLog(" range: %lu\n", record->rangeSize); + + FIRCLSDwarfInstructionsShow(&record->instructions, cie); +} + +void FIRCLSDwarfPointerEncodingShow(const char* leadString, uint8_t encoding) { + if (encoding == DW_EH_PE_omit) { + FIRCLSSDKLog("%s: 0x%02x (omit)\n", leadString, encoding); + } else { + const char* peValue = ""; + const char* peOffset = ""; + + switch (encoding & DW_EH_PE_VALUE_MASK) { + case DW_EH_PE_absptr: + peValue = "DW_EH_PE_absptr"; + break; + case DW_EH_PE_uleb128: + peValue = "DW_EH_PE_uleb128"; + break; + case DW_EH_PE_udata2: + peValue = "DW_EH_PE_udata2"; + break; + case DW_EH_PE_udata4: + peValue = "DW_EH_PE_udata4"; + break; + case DW_EH_PE_udata8: + peValue = "DW_EH_PE_udata8"; + break; + case DW_EH_PE_signed: + peValue = "DW_EH_PE_signed"; + break; + case DW_EH_PE_sleb128: + peValue = "DW_EH_PE_sleb128"; + break; + case DW_EH_PE_sdata2: + peValue = "DW_EH_PE_sdata2"; + break; + case DW_EH_PE_sdata4: + peValue = "DW_EH_PE_sdata4"; + break; + case DW_EH_PE_sdata8: + peValue = "DW_EH_PE_sdata8"; + break; + default: + peValue = "unknown"; + break; + } + + switch (encoding & DW_EH_PE_RELATIVE_OFFSET_MASK) { + case DW_EH_PE_absptr: + break; + case DW_EH_PE_pcrel: + peOffset = " + DW_EH_PE_pcrel"; + break; + case DW_EH_PE_textrel: + peOffset = " + DW_EH_PE_textrel"; + break; + case DW_EH_PE_datarel: + peOffset = " + DW_EH_PE_datarel"; + break; + case DW_EH_PE_funcrel: + peOffset = " + DW_EH_PE_funcrel"; + break; + case DW_EH_PE_aligned: + peOffset = " + DW_EH_PE_aligned"; + break; + case DW_EH_PE_indirect: + peOffset = " + DW_EH_PE_indirect"; + break; + default: + break; + } + + FIRCLSSDKLog("%s: 0x%02x (%s%s)\n", leadString, encoding, peValue, peOffset); + } +} + +void FIRCLSDwarfInstructionsShow(DWARFInstructions* instructions, DWARFCIERecord* cie) { + if (!instructions) { + FIRCLSSDKLog("Error: Instructions null\n"); + } + + FIRCLSDwarfState state; + + memset(&state, 0, sizeof(FIRCLSDwarfState)); + + FIRCLSDwarfInstructionsEnumerate(instructions, cie, &state, -1); +} + +#endif + +#else +INJECT_STRIP_SYMBOL(dwarf_unwind) +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwind.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwind.h new file mode 100644 index 000000000..bbb28805b --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwind.h @@ -0,0 +1,138 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include <stdbool.h> +#include <stdint.h> +#include <sys/types.h> + +#include "FIRCLSDwarfUnwindRegisters.h" +#include "FIRCLSThreadState.h" + +#if CLS_DWARF_UNWINDING_SUPPORTED + +#pragma mark Structures +typedef struct { + uint32_t length; + const void* data; +} DWARFInstructions; + +typedef struct { + uint64_t length; + uint8_t version; + uintptr_t ehData; // 8 bytes for 64-bit architectures, 4 bytes for 32 + const char* augmentation; + uint8_t pointerEncoding; + uint8_t lsdaEncoding; + uint8_t personalityEncoding; + uintptr_t personalityFunction; + uint64_t codeAlignFactor; + int64_t dataAlignFactor; + uint64_t returnAddressRegister; // is 64 bits enough for this value? + bool signalFrame; + + DWARFInstructions instructions; +} DWARFCIERecord; + +typedef struct { + uint64_t length; + uint64_t cieOffset; // also an arch-specific size + uintptr_t startAddress; + uintptr_t rangeSize; + + DWARFInstructions instructions; +} DWARFFDERecord; + +typedef struct { + DWARFCIERecord cie; + DWARFFDERecord fde; +} FIRCLSDwarfCFIRecord; + +typedef enum { + FIRCLSDwarfRegisterUnused = 0, + FIRCLSDwarfRegisterInCFA, + FIRCLSDwarfRegisterOffsetFromCFA, + FIRCLSDwarfRegisterInRegister, + FIRCLSDwarfRegisterAtExpression, + FIRCLSDwarfRegisterIsExpression +} FIRCLSDwarfRegisterLocation; + +typedef struct { + FIRCLSDwarfRegisterLocation location; + uint64_t value; +} FIRCLSDwarfRegister; + +typedef struct { + uint64_t cfaRegister; + int64_t cfaRegisterOffset; + const void* cfaExpression; + uint32_t spArgSize; + + FIRCLSDwarfRegister registers[CLS_DWARF_MAX_REGISTER_NUM + 1]; +} FIRCLSDwarfState; + +__BEGIN_DECLS + +#pragma mark - Parsing +bool FIRCLSDwarfParseCIERecord(DWARFCIERecord* cie, const void* ptr); +bool FIRCLSDwarfParseFDERecord(DWARFFDERecord* fdeRecord, + bool parseCIE, + DWARFCIERecord* cieRecord, + const void* ptr); +bool FIRCLSDwarfParseCFIFromFDERecord(FIRCLSDwarfCFIRecord* record, const void* ptr); +bool FIRCLSDwarfParseCFIFromFDERecordOffset(FIRCLSDwarfCFIRecord* record, + const void* ehFrame, + uintptr_t fdeOffset); + +#pragma mark - Properties +bool FIRCLSDwarfCIEIsValid(DWARFCIERecord* cie); +bool FIRCLSDwarfCIEHasAugmentationData(DWARFCIERecord* cie); + +#pragma mark - Execution +bool FIRCLSDwarfInstructionsEnumerate(DWARFInstructions* instructions, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state, + intptr_t pcOffset); +bool FIRCLSDwarfUnwindComputeRegisters(FIRCLSDwarfCFIRecord* record, + FIRCLSThreadContext* registers); +bool FIRCLSDwarfUnwindAssignRegisters(const FIRCLSDwarfState* state, + const FIRCLSThreadContext* registers, + uintptr_t cfaRegister, + FIRCLSThreadContext* outputRegisters); + +#pragma mark - Register Operations +bool FIRCLSDwarfCompareRegisters(const FIRCLSThreadContext* a, + const FIRCLSThreadContext* b, + uint64_t registerNum); + +bool FIRCLSDwarfGetCFA(FIRCLSDwarfState* state, + const FIRCLSThreadContext* registers, + uintptr_t* cfa); +uintptr_t FIRCLSDwarfGetSavedRegister(const FIRCLSThreadContext* registers, + uintptr_t cfaRegister, + FIRCLSDwarfRegister dRegister); + +#if DEBUG +#pragma mark - Debugging +void FIRCLSCFIRecordShow(FIRCLSDwarfCFIRecord* record); +void FIRCLSCIERecordShow(DWARFCIERecord* record); +void FIRCLSFDERecordShow(DWARFFDERecord* record, DWARFCIERecord* cie); +void FIRCLSDwarfPointerEncodingShow(const char* leadString, uint8_t encoding); +void FIRCLSDwarfInstructionsShow(DWARFInstructions* instructions, DWARFCIERecord* cie); +#endif + +__END_DECLS + +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwindRegisters.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwindRegisters.h new file mode 100644 index 000000000..1e3739692 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwindRegisters.h @@ -0,0 +1,152 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include <stdint.h> + +#include "FIRCLSFeatures.h" + +#if CLS_CPU_X86_64 +enum { + CLS_DWARF_X86_64_RAX = 0, + CLS_DWARF_X86_64_RDX = 1, + CLS_DWARF_X86_64_RCX = 2, + CLS_DWARF_X86_64_RBX = 3, + CLS_DWARF_X86_64_RSI = 4, + CLS_DWARF_X86_64_RDI = 5, + CLS_DWARF_X86_64_RBP = 6, + CLS_DWARF_X86_64_RSP = 7, + CLS_DWARF_X86_64_R8 = 8, + CLS_DWARF_X86_64_R9 = 9, + CLS_DWARF_X86_64_R10 = 10, + CLS_DWARF_X86_64_R11 = 11, + CLS_DWARF_X86_64_R12 = 12, + CLS_DWARF_X86_64_R13 = 13, + CLS_DWARF_X86_64_R14 = 14, + CLS_DWARF_X86_64_R15 = 15, + + CLS_DWARF_X86_64_RET_ADDR = 16 +}; + +#define CLS_DWARF_REG_RETURN CLS_DWARF_X86_64_RET_ADDR +#define CLS_DWARF_REG_SP CLS_DWARF_X86_64_RSP +#define CLS_DWARF_REG_FP CLS_DWARF_X86_64_RBP + +#define CLS_DWARF_MAX_REGISTER_NUM (CLS_DWARF_X86_64_RET_ADDR) + +#elif CLS_CPU_I386 + +enum { + CLS_DWARF_X86_EAX = 0, + CLS_DWARF_X86_ECX = 1, + CLS_DWARF_X86_EDX = 2, + CLS_DWARF_X86_EBX = 3, + CLS_DWARF_X86_EBP = 4, + CLS_DWARF_X86_ESP = 5, + CLS_DWARF_X86_ESI = 6, + CLS_DWARF_X86_EDI = 7, + + CLS_DWARF_X86_RET_ADDR = 8 +}; + +#define CLS_DWARF_REG_RETURN CLS_DWARF_X86_RET_ADDR +#define CLS_DWARF_REG_SP CLS_DWARF_X86_ESP +#define CLS_DWARF_REG_FP CLS_DWARF_X86_EBP + +#define CLS_DWARF_MAX_REGISTER_NUM (CLS_DWARF_X86_RET_ADDR) + +#elif CLS_CPU_ARM64 + +// 64-bit ARM64 registers +enum { + CLS_DWARF_ARM64_X0 = 0, + CLS_DWARF_ARM64_X1 = 1, + CLS_DWARF_ARM64_X2 = 2, + CLS_DWARF_ARM64_X3 = 3, + CLS_DWARF_ARM64_X4 = 4, + CLS_DWARF_ARM64_X5 = 5, + CLS_DWARF_ARM64_X6 = 6, + CLS_DWARF_ARM64_X7 = 7, + CLS_DWARF_ARM64_X8 = 8, + CLS_DWARF_ARM64_X9 = 9, + CLS_DWARF_ARM64_X10 = 10, + CLS_DWARF_ARM64_X11 = 11, + CLS_DWARF_ARM64_X12 = 12, + CLS_DWARF_ARM64_X13 = 13, + CLS_DWARF_ARM64_X14 = 14, + CLS_DWARF_ARM64_X15 = 15, + CLS_DWARF_ARM64_X16 = 16, + CLS_DWARF_ARM64_X17 = 17, + CLS_DWARF_ARM64_X18 = 18, + CLS_DWARF_ARM64_X19 = 19, + CLS_DWARF_ARM64_X20 = 20, + CLS_DWARF_ARM64_X21 = 21, + CLS_DWARF_ARM64_X22 = 22, + CLS_DWARF_ARM64_X23 = 23, + CLS_DWARF_ARM64_X24 = 24, + CLS_DWARF_ARM64_X25 = 25, + CLS_DWARF_ARM64_X26 = 26, + CLS_DWARF_ARM64_X27 = 27, + CLS_DWARF_ARM64_X28 = 28, + CLS_DWARF_ARM64_X29 = 29, + CLS_DWARF_ARM64_FP = 29, + CLS_DWARF_ARM64_X30 = 30, + CLS_DWARF_ARM64_LR = 30, + CLS_DWARF_ARM64_X31 = 31, + CLS_DWARF_ARM64_SP = 31, + // reserved block + CLS_DWARF_ARM64_D0 = 64, + CLS_DWARF_ARM64_D1 = 65, + CLS_DWARF_ARM64_D2 = 66, + CLS_DWARF_ARM64_D3 = 67, + CLS_DWARF_ARM64_D4 = 68, + CLS_DWARF_ARM64_D5 = 69, + CLS_DWARF_ARM64_D6 = 70, + CLS_DWARF_ARM64_D7 = 71, + CLS_DWARF_ARM64_D8 = 72, + CLS_DWARF_ARM64_D9 = 73, + CLS_DWARF_ARM64_D10 = 74, + CLS_DWARF_ARM64_D11 = 75, + CLS_DWARF_ARM64_D12 = 76, + CLS_DWARF_ARM64_D13 = 77, + CLS_DWARF_ARM64_D14 = 78, + CLS_DWARF_ARM64_D15 = 79, + CLS_DWARF_ARM64_D16 = 80, + CLS_DWARF_ARM64_D17 = 81, + CLS_DWARF_ARM64_D18 = 82, + CLS_DWARF_ARM64_D19 = 83, + CLS_DWARF_ARM64_D20 = 84, + CLS_DWARF_ARM64_D21 = 85, + CLS_DWARF_ARM64_D22 = 86, + CLS_DWARF_ARM64_D23 = 87, + CLS_DWARF_ARM64_D24 = 88, + CLS_DWARF_ARM64_D25 = 89, + CLS_DWARF_ARM64_D26 = 90, + CLS_DWARF_ARM64_D27 = 91, + CLS_DWARF_ARM64_D28 = 92, + CLS_DWARF_ARM64_D29 = 93, + CLS_DWARF_ARM64_D30 = 94, + CLS_DWARF_ARM64_D31 = 95 +}; + +#define CLS_DWARF_MAX_REGISTER_NUM (CLS_DWARF_ARM64_SP) + +#define CLS_DWARF_REG_RETURN CLS_DWARF_ARM64_LR +#define CLS_DWARF_REG_SP CLS_DWARF_ARM64_SP +#define CLS_DWARF_REG_FP CLS_DWARF_ARM64_FP + +#endif + +#define CLS_DWARF_INVALID_REGISTER_NUM (CLS_DWARF_MAX_REGISTER_NUM + 1) diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind.c b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind.c new file mode 100644 index 000000000..7961071d2 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind.c @@ -0,0 +1,319 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSUnwind.h" +#include "FIRCLSBinaryImage.h" +#include "FIRCLSCompactUnwind.h" +#include "FIRCLSFeatures.h" +#include "FIRCLSGlobals.h" +#include "FIRCLSUtility.h" + +#include <mach/mach.h> +#include <signal.h> +#include <stdio.h> + +// Without a limit on the number of frames we unwind, there's a real possibility +// we'll get stuck in an infinite loop. But, we still need pretty big limits, +// because stacks can get quite big. Also, the stacks are different on the platforms. +// These values were empirically determined (~525000 on OS X, ~65000 on iOS). +#if TARGET_OS_EMBEDDED +const uint32_t FIRCLSUnwindMaxFrames = 100000; +#else +const uint32_t FIRCLSUnwindMaxFrames = 600000; +#endif + +const uint32_t FIRCLSUnwindInfiniteRecursionCountThreshold = 10; + +#pragma mark Prototypes +static bool FIRCLSUnwindNextFrameUsingAllStrategies(FIRCLSUnwindContext* context); +#if CLS_COMPACT_UNWINDING_SUPPORTED +static bool FIRCLSUnwindWithCompactUnwindInfo(FIRCLSUnwindContext* context); +#endif +bool FIRCLSUnwindContextHasValidPCAndSP(FIRCLSUnwindContext* context); + +#pragma mark - API +bool FIRCLSUnwindInit(FIRCLSUnwindContext* context, FIRCLSThreadContext threadContext) { + if (!context) { + return false; + } + + memset(context, 0, sizeof(FIRCLSUnwindContext)); + + context->registers = threadContext; + + return true; +} + +bool FIRCLSUnwindNextFrame(FIRCLSUnwindContext* context) { + if (!FIRCLSIsValidPointer(context)) { + FIRCLSSDKLog("Error: invalid inputs\n"); + return false; + } + + if (!FIRCLSUnwindContextHasValidPCAndSP(context)) { + // This is a special-case. It is possible to try to unwind a thread that has no stack (ie, is + // executing zero functions. I believe this happens when a thread has exited, but before the + // kernel has actually cleaned it up. This situation can only apply to the first frame. So, in + // that case, we don't count it as an error. But, if it happens mid-unwind, it's a problem. + + if (context->frameCount == 0) { + FIRCLSSDKLog("Cancelling unwind for thread with invalid PC/SP\n"); + } else { + FIRCLSSDKLog("Error: thread PC/SP invalid before unwind\n"); + } + + return false; + } + + if (!FIRCLSUnwindNextFrameUsingAllStrategies(context)) { + FIRCLSSDKLogError("Failed to advance to the next frame\n"); + return false; + } + + uintptr_t pc = FIRCLSUnwindGetPC(context); + uintptr_t sp = FIRCLSUnwindGetStackPointer(context); + + // Unwinding will complete when this is no longer a valid value + if (!FIRCLSIsValidPointer(pc)) { + return false; + } + + // after unwinding, validate that we have a sane register value + if (!FIRCLSIsValidPointer(sp)) { + FIRCLSSDKLog("Error: SP (%p) isn't a valid pointer\n", (void*)sp); + return false; + } + + // track repeating frames + if (context->lastFramePC == pc) { + context->repeatCount += 1; + } else { + context->repeatCount = 0; + } + + context->frameCount += 1; + context->lastFramePC = pc; + + return true; +} + +#pragma mark - Register Accessors +uintptr_t FIRCLSUnwindGetPC(FIRCLSUnwindContext* context) { + if (!FIRCLSIsValidPointer(context)) { + return 0; + } + + return FIRCLSThreadContextGetPC(&context->registers); +} + +uintptr_t FIRCLSUnwindGetStackPointer(FIRCLSUnwindContext* context) { + if (!FIRCLSIsValidPointer(context)) { + return 0; + } + + return FIRCLSThreadContextGetStackPointer(&context->registers); +} + +static uintptr_t FIRCLSUnwindGetFramePointer(FIRCLSUnwindContext* context) { + if (!FIRCLSIsValidPointer(context)) { + return 0; + } + + return FIRCLSThreadContextGetFramePointer(&context->registers); +} + +uint32_t FIRCLSUnwindGetFrameRepeatCount(FIRCLSUnwindContext* context) { + if (!FIRCLSIsValidPointer(context)) { + return 0; + } + + return context->repeatCount; +} + +#pragma mark - Unwind Strategies +static bool FIRCLSUnwindNextFrameUsingAllStrategies(FIRCLSUnwindContext* context) { + if (!FIRCLSIsValidPointer(context)) { + FIRCLSSDKLogError("Arguments invalid\n"); + return false; + } + + if (context->frameCount >= FIRCLSUnwindMaxFrames) { + FIRCLSSDKLogWarn("Exceeded maximum number of frames\n"); + return false; + } + + uintptr_t pc = FIRCLSUnwindGetPC(context); + + // Ok, what's going on here? libunwind's UnwindCursor<A,R>::setInfoBasedOnIPRegister has a + // parameter that, if true, does this subtraction. Despite the comments in the code + // (of 35.1), I found that the parameter was almost always set to true. + // + // I then ran into a problem when unwinding from _pthread_start -> thread_start. This + // is a common transition, which happens in pretty much every report. An extra frame + // was being generated, because the PC we get for _pthread_start was mapping to exactly + // one greater than the function's last byte, according to the compact unwind info. This + // resulted in using the wrong compact encoding, and picking the next function, which + // turned out to be dwarf instead of a frame pointer. + + // So, the moral is - do the subtraction for all frames except the first. I haven't found + // a case where it produces an incorrect result. Also note that at first, I thought this would + // subtract one from the final addresses too. But, the end of this function will *compute* PC, + // so this value is used only to look up unwinding data. + + if (context->frameCount > 0) { + --pc; + if (!FIRCLSThreadContextSetPC(&context->registers, pc)) { + FIRCLSSDKLogError("Unable to set PC\n"); + return false; + } + } + + if (!FIRCLSIsValidPointer(pc)) { + FIRCLSSDKLogError("PC is invalid\n"); + return false; + } + + // the first frame is special - as the registers we need + // are already loaded by definition + if (context->frameCount == 0) { + return true; + } + +#if CLS_COMPACT_UNWINDING_SUPPORTED + // attempt to advance to the next frame using compact unwinding, and + // only fall back to the frame pointer if that fails + if (FIRCLSUnwindWithCompactUnwindInfo(context)) { + return true; + } +#endif + + // If the frame pointer is zero, we cannot use an FP-based unwind and we can reasonably + // assume that we've just gotten to the end of the stack. + if (FIRCLSUnwindGetFramePointer(context) == 0) { + FIRCLSSDKLogWarn("FP is zero, aborting unwind\n"); + // make sure to set the PC to zero, to indicate the unwind is complete + return FIRCLSThreadContextSetPC(&context->registers, 0); + } + + // Only allow stack scanning (as a last resort) if we're on the first frame. All others + // are too likely to screw up. + if (FIRCLSUnwindWithFramePointer(&context->registers, context->frameCount == 1)) { + return true; + } + + FIRCLSSDKLogError("Unable to use frame pointer\n"); + + return false; +} + +#if CLS_COMPACT_UNWINDING_SUPPORTED +static bool FIRCLSUnwindWithCompactUnwindInfo(FIRCLSUnwindContext* context) { + if (!context) { + return false; + } + + // step one - find the image the current pc is within + FIRCLSBinaryImageRuntimeNode image; + + uintptr_t pc = FIRCLSUnwindGetPC(context); + + if (!FIRCLSBinaryImageSafeFindImageForAddress(pc, &image)) { + FIRCLSSDKLogWarn("Unable to find binary for %p\n", (void*)pc); + return false; + } + +#if CLS_BINARY_IMAGE_RUNTIME_NODE_RECORD_NAME + FIRCLSSDKLogDebug("Binary image for %p at %p => %s\n", (void*)pc, image.baseAddress, image.name); +#else + FIRCLSSDKLogDebug("Binary image for %p at %p\n", (void*)pc, image.baseAddress); +#endif + + if (!FIRCLSBinaryImageSafeHasUnwindInfo(&image)) { + FIRCLSSDKLogInfo("Binary image at %p has no unwind info\n", image.baseAddress); + return false; + } + + if (!FIRCLSCompactUnwindInit(&context->compactUnwindState, image.unwindInfo, image.ehFrame, + (uintptr_t)image.baseAddress)) { + FIRCLSSDKLogError("Unable to read unwind info\n"); + return false; + } + + // this function will actually attempt to find compact unwind info for the current PC, + // and use it to mutate the context register state + return FIRCLSCompactUnwindLookupAndCompute(&context->compactUnwindState, &context->registers); +} +#endif + +#pragma mark - Utility Functions +bool FIRCLSUnwindContextHasValidPCAndSP(FIRCLSUnwindContext* context) { + return FIRCLSIsValidPointer(FIRCLSUnwindGetPC(context)) && + FIRCLSIsValidPointer(FIRCLSUnwindGetStackPointer(context)); +} + +#if CLS_CPU_64BIT +#define BASIC_INFO_TYPE vm_region_basic_info_64_t +#define BASIC_INFO VM_REGION_BASIC_INFO_64 +#define BASIC_INFO_COUNT VM_REGION_BASIC_INFO_COUNT_64 +#define vm_region_query_fn vm_region_64 +#else +#define BASIC_INFO_TYPE vm_region_basic_info_t +#define BASIC_INFO VM_REGION_BASIC_INFO +#define BASIC_INFO_COUNT VM_REGION_BASIC_INFO_COUNT +#define vm_region_query_fn vm_region +#endif +bool FIRCLSUnwindIsAddressExecutable(vm_address_t address) { +#if CLS_COMPACT_UNWINDING_SUPPORTED + FIRCLSBinaryImageRuntimeNode unusedNode; + + return FIRCLSBinaryImageSafeFindImageForAddress(address, &unusedNode); +#else + return true; +#endif +} + +bool FIRCLSUnwindFirstExecutableAddress(vm_address_t start, + vm_address_t end, + vm_address_t* foundAddress) { + // This function walks up the data on the stack, looking for the first value that is an address on + // an exectuable page. This is a heurestic, and can hit false positives. + + *foundAddress = 0; // write in a 0 + + do { + vm_address_t address; + + FIRCLSSDKLogDebug("Checking address %p => %p\n", (void*)start, (void*)*(uintptr_t*)start); + + // if start isn't a valid pointer, don't even bother trying + if (FIRCLSIsValidPointer(start)) { + if (!FIRCLSReadMemory(start, &address, sizeof(void*))) { + // if we fail to read from the stack, we're done + return false; + } + + FIRCLSSDKLogDebug("Checking for executable %p\n", (void*)address); + // when we find an exectuable address, we're finished + if (FIRCLSUnwindIsAddressExecutable(address)) { + *foundAddress = address; + return true; + } + } + + start += sizeof(void*); // move back up the stack + + } while (start < end); + + return false; +} diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind.h new file mode 100644 index 000000000..a92a2871d --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind.h @@ -0,0 +1,53 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "FIRCLSThreadState.h" +#include "FIRCLSUtility.h" +#if CLS_COMPACT_UNWINDING_SUPPORTED +#include "FIRCLSCompactUnwind.h" +#endif +#include <mach/vm_types.h> +#include <stdbool.h> + +#include "FIRCLSUnwind_arch.h" + +extern const uint32_t FIRCLSUnwindMaxFrames; + +extern const uint32_t FIRCLSUnwindInfiniteRecursionCountThreshold; + +typedef struct { + FIRCLSThreadContext registers; + uint32_t frameCount; +#if CLS_COMPACT_UNWINDING_SUPPORTED + FIRCLSCompactUnwindContext compactUnwindState; +#endif + uintptr_t lastFramePC; + uint32_t repeatCount; +} FIRCLSUnwindContext; + +// API +bool FIRCLSUnwindInit(FIRCLSUnwindContext* context, FIRCLSThreadContext threadContext); + +bool FIRCLSUnwindNextFrame(FIRCLSUnwindContext* context); +uintptr_t FIRCLSUnwindGetPC(FIRCLSUnwindContext* context); +uintptr_t FIRCLSUnwindGetStackPointer(FIRCLSUnwindContext* context); +uint32_t FIRCLSUnwindGetFrameRepeatCount(FIRCLSUnwindContext* context); + +// utility functions +bool FIRCLSUnwindIsAddressExecutable(vm_address_t address); +bool FIRCLSUnwindFirstExecutableAddress(vm_address_t start, + vm_address_t end, + vm_address_t* foundAddress); diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_arch.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_arch.h new file mode 100644 index 000000000..3accd40ea --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_arch.h @@ -0,0 +1,32 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "FIRCLSFeatures.h" +#include "FIRCLSThreadState.h" +#if CLS_COMPACT_UNWINDING_SUPPORTED +#include "FIRCLSCompactUnwind.h" +#endif + +bool FIRCLSUnwindWithFramePointer(FIRCLSThreadContext *registers, bool allowScanning); +uintptr_t FIRCLSUnwindStackPointerFromFramePointer(uintptr_t framePtr); + +#if CLS_DWARF_UNWINDING_SUPPORTED +uintptr_t FIRCLSCompactUnwindDwarfOffset(compact_unwind_encoding_t encoding); +bool FIRCLSDwarfUnwindSetRegisterValue(FIRCLSThreadContext *registers, + uint64_t num, + uintptr_t value); +uintptr_t FIRCLSDwarfUnwindGetRegisterValue(const FIRCLSThreadContext *registers, uint64_t num); +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_arm.c b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_arm.c new file mode 100644 index 000000000..ead1a29f4 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_arm.c @@ -0,0 +1,313 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSCompactUnwind.h" +#include "FIRCLSCompactUnwind_Private.h" +#include "FIRCLSDefines.h" +#include "FIRCLSDwarfUnwind.h" +#include "FIRCLSFeatures.h" +#include "FIRCLSUnwind.h" +#include "FIRCLSUnwind_arch.h" +#include "FIRCLSUtility.h" + +#if CLS_CPU_ARM || CLS_CPU_ARM64 + +static bool FIRCLSUnwindWithLRRegister(FIRCLSThreadContext* registers) { + if (!FIRCLSIsValidPointer(registers)) { + return false; + } + + // Return address is in LR, SP is pointing to the next frame. + uintptr_t value = FIRCLSThreadContextGetLinkRegister(registers); + + if (!FIRCLSIsValidPointer(value)) { + FIRCLSSDKLog("Error: LR value is invalid\n"); + return false; + } + + return FIRCLSThreadContextSetPC(registers, value); +} + +bool FIRCLSUnwindWithFramePointer(FIRCLSThreadContext* registers, bool allowScanning) { + if (allowScanning) { + // The LR register does have the return address here, but there are situations where + // this can produce false matches. Better backend rules can fix this up in many cases. + if (FIRCLSUnwindWithLRRegister(registers)) { + return true; + } else { + // In this case, we're unable to use the LR. We don't want to just stop unwinding, so + // proceed with the normal, non-scanning path + FIRCLSSDKLog("Unable to use LR, skipping\n"); + } + } + + // read the values from the stack + const uintptr_t framePointer = FIRCLSThreadContextGetFramePointer(registers); + uintptr_t stack[2]; + + if (!FIRCLSReadMemory((vm_address_t)framePointer, stack, sizeof(stack))) { + // unable to read the first stack frame + FIRCLSSDKLog("Error: failed to read memory at address %p\n", (void*)framePointer); + return false; + } + + if (!FIRCLSThreadContextSetPC(registers, stack[1])) { + return false; + } + + if (!FIRCLSThreadContextSetFramePointer(registers, stack[0])) { + return false; + } + + if (!FIRCLSThreadContextSetStackPointer(registers, + FIRCLSUnwindStackPointerFromFramePointer(framePointer))) { + return false; + } + + return true; +} + +uintptr_t FIRCLSUnwindStackPointerFromFramePointer(uintptr_t framePtr) { + // the stack pointer is the frame pointer plus the two saved pointers for the frame + return framePtr + 2 * sizeof(void*); +} + +#if CLS_COMPACT_UNWINDING_SUPPORTED +bool FIRCLSCompactUnwindComputeRegisters(FIRCLSCompactUnwindContext* context, + FIRCLSCompactUnwindResult* result, + FIRCLSThreadContext* registers) { + if (!context || !result || !registers) { + return false; + } + + // Note that compact_uwnind_encoding.h has a few bugs in it prior to iOS 8.0. + // Only refer to the >= 8.0 header. + switch (result->encoding & UNWIND_ARM64_MODE_MASK) { + case UNWIND_ARM64_MODE_FRAMELESS: + // Interestingly, we also know the size of the stack frame, by + // using UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK. Is that useful? + return FIRCLSUnwindWithLRRegister(registers); + break; + case UNWIND_ARM64_MODE_DWARF: + return FIRCLSCompactUnwindDwarfFrame( + context, result->encoding & UNWIND_ARM64_DWARF_SECTION_OFFSET, registers); + break; + case UNWIND_ARM64_MODE_FRAME: + return FIRCLSUnwindWithFramePointer(registers, false); + default: + FIRCLSSDKLog("Invalid encoding 0x%x\n", result->encoding); + break; + } + + return false; +} +#endif + +#if CLS_DWARF_UNWINDING_SUPPORTED +uintptr_t FIRCLSDwarfUnwindGetRegisterValue(const FIRCLSThreadContext* registers, uint64_t num) { + switch (num) { + case CLS_DWARF_ARM64_X0: + return registers->__ss.__x[0]; + case CLS_DWARF_ARM64_X1: + return registers->__ss.__x[1]; + case CLS_DWARF_ARM64_X2: + return registers->__ss.__x[2]; + case CLS_DWARF_ARM64_X3: + return registers->__ss.__x[3]; + case CLS_DWARF_ARM64_X4: + return registers->__ss.__x[4]; + case CLS_DWARF_ARM64_X5: + return registers->__ss.__x[5]; + case CLS_DWARF_ARM64_X6: + return registers->__ss.__x[6]; + case CLS_DWARF_ARM64_X7: + return registers->__ss.__x[7]; + case CLS_DWARF_ARM64_X8: + return registers->__ss.__x[8]; + case CLS_DWARF_ARM64_X9: + return registers->__ss.__x[9]; + case CLS_DWARF_ARM64_X10: + return registers->__ss.__x[10]; + case CLS_DWARF_ARM64_X11: + return registers->__ss.__x[11]; + case CLS_DWARF_ARM64_X12: + return registers->__ss.__x[12]; + case CLS_DWARF_ARM64_X13: + return registers->__ss.__x[13]; + case CLS_DWARF_ARM64_X14: + return registers->__ss.__x[14]; + case CLS_DWARF_ARM64_X15: + return registers->__ss.__x[15]; + case CLS_DWARF_ARM64_X16: + return registers->__ss.__x[16]; + case CLS_DWARF_ARM64_X17: + return registers->__ss.__x[17]; + case CLS_DWARF_ARM64_X18: + return registers->__ss.__x[18]; + case CLS_DWARF_ARM64_X19: + return registers->__ss.__x[19]; + case CLS_DWARF_ARM64_X20: + return registers->__ss.__x[20]; + case CLS_DWARF_ARM64_X21: + return registers->__ss.__x[21]; + case CLS_DWARF_ARM64_X22: + return registers->__ss.__x[22]; + case CLS_DWARF_ARM64_X23: + return registers->__ss.__x[23]; + case CLS_DWARF_ARM64_X24: + return registers->__ss.__x[24]; + case CLS_DWARF_ARM64_X25: + return registers->__ss.__x[25]; + case CLS_DWARF_ARM64_X26: + return registers->__ss.__x[26]; + case CLS_DWARF_ARM64_X27: + return registers->__ss.__x[27]; + case CLS_DWARF_ARM64_X28: + return registers->__ss.__x[28]; + case CLS_DWARF_ARM64_FP: + return FIRCLSThreadContextGetFramePointer(registers); + case CLS_DWARF_ARM64_LR: + return FIRCLSThreadContextGetLinkRegister(registers); + case CLS_DWARF_ARM64_SP: + return FIRCLSThreadContextGetStackPointer(registers); + default: + break; + } + + FIRCLSSDKLog("Error: Unrecognized get register number %llu\n", num); + + return 0; +} + +bool FIRCLSDwarfUnwindSetRegisterValue(FIRCLSThreadContext* registers, + uint64_t num, + uintptr_t value) { + switch (num) { + case CLS_DWARF_ARM64_X0: + registers->__ss.__x[0] = value; + return true; + case CLS_DWARF_ARM64_X1: + registers->__ss.__x[1] = value; + return true; + case CLS_DWARF_ARM64_X2: + registers->__ss.__x[2] = value; + return true; + case CLS_DWARF_ARM64_X3: + registers->__ss.__x[3] = value; + return true; + case CLS_DWARF_ARM64_X4: + registers->__ss.__x[4] = value; + return true; + case CLS_DWARF_ARM64_X5: + registers->__ss.__x[5] = value; + return true; + case CLS_DWARF_ARM64_X6: + registers->__ss.__x[6] = value; + return true; + case CLS_DWARF_ARM64_X7: + registers->__ss.__x[7] = value; + return true; + case CLS_DWARF_ARM64_X8: + registers->__ss.__x[8] = value; + return true; + case CLS_DWARF_ARM64_X9: + registers->__ss.__x[9] = value; + return true; + case CLS_DWARF_ARM64_X10: + registers->__ss.__x[10] = value; + return true; + case CLS_DWARF_ARM64_X11: + registers->__ss.__x[11] = value; + return true; + case CLS_DWARF_ARM64_X12: + registers->__ss.__x[12] = value; + return true; + case CLS_DWARF_ARM64_X13: + registers->__ss.__x[13] = value; + return true; + case CLS_DWARF_ARM64_X14: + registers->__ss.__x[14] = value; + return true; + case CLS_DWARF_ARM64_X15: + registers->__ss.__x[15] = value; + return true; + case CLS_DWARF_ARM64_X16: + registers->__ss.__x[16] = value; + return true; + case CLS_DWARF_ARM64_X17: + registers->__ss.__x[17] = value; + return true; + case CLS_DWARF_ARM64_X18: + registers->__ss.__x[18] = value; + return true; + case CLS_DWARF_ARM64_X19: + registers->__ss.__x[19] = value; + return true; + case CLS_DWARF_ARM64_X20: + registers->__ss.__x[20] = value; + return true; + case CLS_DWARF_ARM64_X21: + registers->__ss.__x[21] = value; + return true; + case CLS_DWARF_ARM64_X22: + registers->__ss.__x[22] = value; + return true; + case CLS_DWARF_ARM64_X23: + registers->__ss.__x[23] = value; + return true; + case CLS_DWARF_ARM64_X24: + registers->__ss.__x[24] = value; + return true; + case CLS_DWARF_ARM64_X25: + registers->__ss.__x[25] = value; + return true; + case CLS_DWARF_ARM64_X26: + registers->__ss.__x[26] = value; + return true; + case CLS_DWARF_ARM64_X27: + registers->__ss.__x[27] = value; + return true; + case CLS_DWARF_ARM64_X28: + registers->__ss.__x[28] = value; + return true; + case CLS_DWARF_ARM64_FP: + FIRCLSThreadContextSetFramePointer(registers, value); + return true; + case CLS_DWARF_ARM64_SP: + FIRCLSThreadContextSetStackPointer(registers, value); + return true; + case CLS_DWARF_ARM64_LR: + // Here's what's going on. For x86, the "return register" is virtual. The architecture + // doesn't actually have one, but DWARF does have the concept. So, when the system + // tries to set the return register, we set the PC. You can see this behavior + // in the FIRCLSDwarfUnwindSetRegisterValue implemenation for that architecture. In the + // case of ARM64, the register is real. So, we have to be extra careful to make sure + // we update the PC here. Otherwise, when a DWARF unwind completes, it won't have + // changed the PC to the right value. + FIRCLSThreadContextSetLinkRegister(registers, value); + FIRCLSThreadContextSetPC(registers, value); + return true; + default: + break; + } + + FIRCLSSDKLog("Unrecognized set register number %llu\n", num); + + return false; +} +#endif + +#else +INJECT_STRIP_SYMBOL(unwind_arm) +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_x86.c b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_x86.c new file mode 100644 index 000000000..cc0655a92 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_x86.c @@ -0,0 +1,537 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSUnwind_x86.h" +#include "FIRCLSCompactUnwind_Private.h" +#include "FIRCLSDefines.h" +#include "FIRCLSDwarfUnwind.h" +#include "FIRCLSFeatures.h" +#include "FIRCLSUnwind.h" +#include "FIRCLSUnwind_arch.h" +#include "FIRCLSUtility.h" + +#if CLS_CPU_X86 + +static bool FIRCLSCompactUnwindBPFrame(compact_unwind_encoding_t encoding, + FIRCLSThreadContext* registers); +static bool FIRCLSCompactUnwindFrameless(compact_unwind_encoding_t encoding, + FIRCLSThreadContext* registers, + uintptr_t functionStart, + bool indirect); + +#if CLS_COMPACT_UNWINDING_SUPPORTED +bool FIRCLSCompactUnwindComputeRegisters(FIRCLSCompactUnwindContext* context, + FIRCLSCompactUnwindResult* result, + FIRCLSThreadContext* registers) { + if (!FIRCLSIsValidPointer(context) || !FIRCLSIsValidPointer(result) || + !FIRCLSIsValidPointer(registers)) { + FIRCLSSDKLogError("invalid inputs\n"); + return false; + } + + FIRCLSSDKLogDebug("Computing registers for encoding %x\n", result->encoding); + + switch (result->encoding & CLS_X86_MODE_MASK) { + case CLS_X86_MODE_BP_FRAME: + return FIRCLSCompactUnwindBPFrame(result->encoding, registers); + case CLS_X86_MODE_STACK_IMMD: + return FIRCLSCompactUnwindFrameless(result->encoding, registers, result->functionStart, + false); + case CLS_X86_MODE_STACK_IND: + return FIRCLSCompactUnwindFrameless(result->encoding, registers, result->functionStart, true); + case CLS_X86_MODE_DWARF: + return FIRCLSCompactUnwindDwarfFrame(context, result->encoding & CLS_X86_DWARF_SECTION_OFFSET, + registers); + default: + FIRCLSSDKLogError("Invalid encoding %x\n", result->encoding); + break; + } + + return false; +} +#endif + +static bool FIRCLSCompactUnwindBPFrame(compact_unwind_encoding_t encoding, + FIRCLSThreadContext* registers) { + // this is the plain-vanilla frame pointer process + + // uint32_t offset = GET_BITS_WITH_MASK(encoding, UNWIND_X86_EBP_FRAME_OFFSET); + // uint32_t locations = GET_BITS_WITH_MASK(encoding, UNWIND_X86_64_RBP_FRAME_REGISTERS); + + // TODO: pretty sure we do need to restore registers here, so that if a subsequent frame needs + // these results, they will be correct + + // Checkout CompactUnwinder.hpp in libunwind for how to do this. Since we don't make use of any of + // those registers for a stacktrace only, there's nothing we need do with them. + + // read the values from the stack + const uintptr_t framePointer = FIRCLSThreadContextGetFramePointer(registers); + uintptr_t stack[2]; + + if (!FIRCLSReadMemory((vm_address_t)framePointer, stack, sizeof(stack))) { + // unable to read the first stack frame + FIRCLSSDKLog("Error: failed to read memory at address %p\n", (void*)framePointer); + return false; + } + + if (!FIRCLSThreadContextSetPC(registers, stack[1])) { + return false; + } + + if (!FIRCLSThreadContextSetFramePointer(registers, stack[0])) { + return false; + } + + if (!FIRCLSThreadContextSetStackPointer(registers, + FIRCLSUnwindStackPointerFromFramePointer(framePointer))) { + return false; + } + + return true; +} + +bool FIRCLSUnwindWithStackScanning(FIRCLSThreadContext* registers) { + vm_address_t start = (vm_address_t)FIRCLSThreadContextGetStackPointer(registers); + vm_address_t end = (vm_address_t)FIRCLSThreadContextGetFramePointer(registers); + + uintptr_t newPC = 0; + + if (!FIRCLSUnwindFirstExecutableAddress(start, end, (vm_address_t*)&newPC)) { + return false; + } + + return FIRCLSThreadContextSetPC(registers, newPC); +} + +bool FIRCLSUnwindWithFramePointer(FIRCLSThreadContext* registers, bool allowScanning) { + // Here's an interesting case. We've just processed the first frame, and it did + // not have any unwind info. If that first function did not allocate + // a stack frame, we'll "skip" the caller. This might sound unlikely, but it actually + // happens a lot in practice. + + // Sooo, one thing we can do is try to stack the stack for things that look like return + // addresses. Normally, this technique will hit many false positives. But, if we do it + // only for the second frame, and only when we don't have other unwind info available. + + if (allowScanning) { + FIRCLSSDKLogInfo("Attempting stack scan\n"); + if (FIRCLSUnwindWithStackScanning(registers)) { + FIRCLSSDKLogInfo("Stack scan successful\n"); + return true; + } + } + + // If we ever do anything else with the encoding, we need to be sure + // to set it up right. + return FIRCLSCompactUnwindBPFrame(CLS_X86_MODE_BP_FRAME, registers); +} + +uintptr_t FIRCLSUnwindStackPointerFromFramePointer(uintptr_t framePtr) { + // the stack pointer is the frame pointer plus the two saved pointers for the frame + return framePtr + 2 * sizeof(void*); +} + +#if CLS_COMPACT_UNWINDING_SUPPORTED || CLS_DWARF_UNWINDING_SUPPORTED +uintptr_t FIRCLSDwarfUnwindGetRegisterValue(const FIRCLSThreadContext* registers, uint64_t num) { + switch (num) { +#if CLS_CPU_X86_64 + case CLS_DWARF_X86_64_RAX: + return registers->__ss.__rax; + case CLS_DWARF_X86_64_RDX: + return registers->__ss.__rdx; + case CLS_DWARF_X86_64_RCX: + return registers->__ss.__rcx; + case CLS_DWARF_X86_64_RBX: + return registers->__ss.__rbx; + case CLS_DWARF_X86_64_RSI: + return registers->__ss.__rsi; + case CLS_DWARF_X86_64_RDI: + return registers->__ss.__rdi; + case CLS_DWARF_X86_64_RBP: + return registers->__ss.__rbp; + case CLS_DWARF_X86_64_RSP: + return registers->__ss.__rsp; + case CLS_DWARF_X86_64_R8: + return registers->__ss.__r8; + case CLS_DWARF_X86_64_R9: + return registers->__ss.__r9; + case CLS_DWARF_X86_64_R10: + return registers->__ss.__r10; + case CLS_DWARF_X86_64_R11: + return registers->__ss.__r11; + case CLS_DWARF_X86_64_R12: + return registers->__ss.__r12; + case CLS_DWARF_X86_64_R13: + return registers->__ss.__r13; + case CLS_DWARF_X86_64_R14: + return registers->__ss.__r14; + case CLS_DWARF_X86_64_R15: + return registers->__ss.__r15; + case CLS_DWARF_X86_64_RET_ADDR: + return registers->__ss.__rip; +#elif CLS_CPU_I386 + case CLS_DWARF_X86_EAX: + return registers->__ss.__eax; + case CLS_DWARF_X86_ECX: + return registers->__ss.__ecx; + case CLS_DWARF_X86_EDX: + return registers->__ss.__edx; + case CLS_DWARF_X86_EBX: + return registers->__ss.__ebx; + case CLS_DWARF_X86_EBP: + return registers->__ss.__ebp; + case CLS_DWARF_X86_ESP: + return registers->__ss.__esp; + case CLS_DWARF_X86_ESI: + return registers->__ss.__esi; + case CLS_DWARF_X86_EDI: + return registers->__ss.__edi; + case CLS_DWARF_X86_RET_ADDR: + return registers->__ss.__eip; +#endif + default: + break; + } + + FIRCLSSDKLog("Error: Unrecognized get register number %llu\n", num); + + return 0; +} + +bool FIRCLSDwarfUnwindSetRegisterValue(FIRCLSThreadContext* registers, + uint64_t num, + uintptr_t value) { + switch (num) { +#if CLS_CPU_X86_64 + case CLS_DWARF_X86_64_RAX: + registers->__ss.__rax = value; + return true; + case CLS_DWARF_X86_64_RDX: + registers->__ss.__rdx = value; + return true; + case CLS_DWARF_X86_64_RCX: + registers->__ss.__rcx = value; + return true; + case CLS_DWARF_X86_64_RBX: + registers->__ss.__rbx = value; + return true; + case CLS_DWARF_X86_64_RSI: + registers->__ss.__rsi = value; + return true; + case CLS_DWARF_X86_64_RDI: + registers->__ss.__rdi = value; + return true; + case CLS_DWARF_X86_64_RBP: + registers->__ss.__rbp = value; + return true; + case CLS_DWARF_X86_64_RSP: + registers->__ss.__rsp = value; + return true; + case CLS_DWARF_X86_64_R8: + registers->__ss.__r8 = value; + return true; + case CLS_DWARF_X86_64_R9: + registers->__ss.__r9 = value; + return true; + case CLS_DWARF_X86_64_R10: + registers->__ss.__r10 = value; + return true; + case CLS_DWARF_X86_64_R11: + registers->__ss.__r11 = value; + return true; + case CLS_DWARF_X86_64_R12: + registers->__ss.__r12 = value; + return true; + case CLS_DWARF_X86_64_R13: + registers->__ss.__r13 = value; + return true; + case CLS_DWARF_X86_64_R14: + registers->__ss.__r14 = value; + return true; + case CLS_DWARF_X86_64_R15: + registers->__ss.__r15 = value; + return true; + case CLS_DWARF_X86_64_RET_ADDR: + registers->__ss.__rip = value; + return true; +#elif CLS_CPU_I386 + case CLS_DWARF_X86_EAX: + registers->__ss.__eax = value; + return true; + case CLS_DWARF_X86_ECX: + registers->__ss.__ecx = value; + return true; + case CLS_DWARF_X86_EDX: + registers->__ss.__edx = value; + return true; + case CLS_DWARF_X86_EBX: + registers->__ss.__ebx = value; + return true; + case CLS_DWARF_X86_EBP: + registers->__ss.__ebp = value; + return true; + case CLS_DWARF_X86_ESP: + registers->__ss.__esp = value; + return true; + case CLS_DWARF_X86_ESI: + registers->__ss.__esi = value; + return true; + case CLS_DWARF_X86_EDI: + registers->__ss.__edi = value; + return true; + case CLS_DWARF_X86_RET_ADDR: + registers->__ss.__eip = value; + return true; +#endif + default: + break; + } + + FIRCLSSDKLog("Unrecognized set register number %llu\n", num); + + return false; +} +#endif + +#if CLS_COMPACT_UNWINDING_SUPPORTED +bool FIRCLSCompactUnwindComputeStackSize(const compact_unwind_encoding_t encoding, + const uintptr_t functionStart, + const bool indirect, + uint32_t* const stackSize) { + if (!FIRCLSIsValidPointer(stackSize)) { + FIRCLSSDKLog("Error: invalid inputs\n"); + return false; + } + + const uint32_t stackSizeEncoded = GET_BITS_WITH_MASK(encoding, CLS_X86_FRAMELESS_STACK_SIZE); + + if (!indirect) { + *stackSize = stackSizeEncoded * sizeof(void*); + return true; + } + + const vm_address_t sublAddress = functionStart + stackSizeEncoded; + uint32_t sublValue = 0; + + if (!FIRCLSReadMemory(sublAddress, &sublValue, sizeof(uint32_t))) { + FIRCLSSDKLog("Error: unable to read subl value\n"); + return false; + } + + const uint32_t stackAdjust = GET_BITS_WITH_MASK(encoding, CLS_X86_FRAMELESS_STACK_ADJUST); + + *stackSize = sublValue + stackAdjust * sizeof(void*); + + return true; +} + +bool FIRCLSCompactUnwindDecompressPermutation(const compact_unwind_encoding_t encoding, + uintptr_t permutatedRegisters[const static 6]) { + const uint32_t regCount = GET_BITS_WITH_MASK(encoding, CLS_X86_FRAMELESS_STACK_REG_COUNT); + uint32_t permutation = GET_BITS_WITH_MASK(encoding, CLS_X86_FRAMELESS_STACK_REG_PERMUTATION); + + switch (regCount) { + case 6: + permutatedRegisters[0] = permutation / 120; + permutation -= (permutatedRegisters[0] * 120); + permutatedRegisters[1] = permutation / 24; + permutation -= (permutatedRegisters[1] * 24); + permutatedRegisters[2] = permutation / 6; + permutation -= (permutatedRegisters[2] * 6); + permutatedRegisters[3] = permutation / 2; + permutation -= (permutatedRegisters[3] * 2); + permutatedRegisters[4] = permutation; + permutatedRegisters[5] = 0; + break; + case 5: + permutatedRegisters[0] = permutation / 120; + permutation -= (permutatedRegisters[0] * 120); + permutatedRegisters[1] = permutation / 24; + permutation -= (permutatedRegisters[1] * 24); + permutatedRegisters[2] = permutation / 6; + permutation -= (permutatedRegisters[2] * 6); + permutatedRegisters[3] = permutation / 2; + permutation -= (permutatedRegisters[3] * 2); + permutatedRegisters[4] = permutation; + break; + case 4: + permutatedRegisters[0] = permutation / 60; + permutation -= (permutatedRegisters[0] * 60); + permutatedRegisters[1] = permutation / 12; + permutation -= (permutatedRegisters[1] * 12); + permutatedRegisters[2] = permutation / 3; + permutation -= (permutatedRegisters[2] * 3); + permutatedRegisters[3] = permutation; + break; + case 3: + permutatedRegisters[0] = permutation / 20; + permutation -= (permutatedRegisters[0] * 20); + permutatedRegisters[1] = permutation / 4; + permutation -= (permutatedRegisters[1] * 4); + permutatedRegisters[2] = permutation; + break; + case 2: + permutatedRegisters[0] = permutation / 5; + permutation -= (permutatedRegisters[0] * 5); + permutatedRegisters[1] = permutation; + break; + case 1: + permutatedRegisters[0] = permutation; + break; + case 0: + break; + default: + FIRCLSSDKLog("Error: unhandled number of register permutations for encoding %x\n", encoding); + return false; + } + + return true; +} + +bool FIRCLSCompactUnwindRemapRegisters(const compact_unwind_encoding_t encoding, + uintptr_t permutatedRegisters[const static 6], + uintptr_t savedRegisters[const static 6]) { + const uint32_t regCount = GET_BITS_WITH_MASK(encoding, CLS_X86_FRAMELESS_STACK_REG_COUNT); + + if (regCount > 6) { + FIRCLSSDKLog("Error: invalid register number count %d\n", regCount); + return false; + } + + // Re-number the registers + + // You are probably wondering, what the hell is this algorithm even doing? It is + // taken from libunwind's implemenation that does the same thing. + bool used[7] = {false, false, false, false, false, false, false}; + for (uint32_t i = 0; i < regCount; ++i) { + int renum = 0; + for (int u = 1; u < 7; ++u) { + if (!used[u]) { + if (renum == permutatedRegisters[i]) { + savedRegisters[i] = u; + used[u] = true; + break; + } + ++renum; + } + } + } + + return true; +} + +bool FIRCLSCompactUnwindRestoreRegisters(compact_unwind_encoding_t encoding, + FIRCLSThreadContext* registers, + uint32_t stackSize, + const uintptr_t savedRegisters[const static 6], + uintptr_t* address) { + if (!FIRCLSIsValidPointer(registers) || !FIRCLSIsValidPointer(address)) { + FIRCLSSDKLog("Error: invalid inputs\n"); + return false; + } + + const uint32_t regCount = GET_BITS_WITH_MASK(encoding, CLS_X86_FRAMELESS_STACK_REG_COUNT); + + // compute initial address of saved registers + *address = FIRCLSThreadContextGetStackPointer(registers) + stackSize - sizeof(void*) - + sizeof(void*) * regCount; + uintptr_t value = 0; + + for (uint32_t i = 0; i < regCount; ++i) { + value = 0; + + switch (savedRegisters[i]) { + case CLS_X86_REG_RBP: + if (!FIRCLSReadMemory((vm_address_t)*address, (void*)&value, sizeof(uintptr_t))) { + FIRCLSSDKLog("Error: unable to read memory to set register\n"); + return false; + } + + if (!FIRCLSThreadContextSetFramePointer(registers, value)) { + FIRCLSSDKLog("Error: unable to set FP\n"); + return false; + } + break; + default: + // here, we are restoring a register we don't need for unwinding + FIRCLSSDKLog("Error: skipping a restore of register %d at %p\n", (int)savedRegisters[i], + (void*)*address); + break; + } + + *address += sizeof(void*); + } + + return true; +} + +static bool FIRCLSCompactUnwindFrameless(compact_unwind_encoding_t encoding, + FIRCLSThreadContext* registers, + uintptr_t functionStart, + bool indirect) { + FIRCLSSDKLog("Frameless unwind encountered with encoding %x\n", encoding); + + uint32_t stackSize = 0; + if (!FIRCLSCompactUnwindComputeStackSize(encoding, functionStart, indirect, &stackSize)) { + FIRCLSSDKLog("Error: unable to compute stack size for encoding %x\n", encoding); + return false; + } + + uintptr_t permutatedRegisters[6]; + + memset(permutatedRegisters, 0, sizeof(permutatedRegisters)); + if (!FIRCLSCompactUnwindDecompressPermutation(encoding, permutatedRegisters)) { + FIRCLSSDKLog("Error: unable to decompress registers %x\n", encoding); + return false; + } + + uintptr_t savedRegisters[6]; + + memset(savedRegisters, 0, sizeof(savedRegisters)); + if (!FIRCLSCompactUnwindRemapRegisters(encoding, permutatedRegisters, savedRegisters)) { + FIRCLSSDKLog("Error: unable to remap registers %x\n", encoding); + return false; + } + + uintptr_t address = 0; + + if (!FIRCLSCompactUnwindRestoreRegisters(encoding, registers, stackSize, savedRegisters, + &address)) { + FIRCLSSDKLog("Error: unable to restore registers\n"); + return false; + } + + FIRCLSSDKLog("SP is %p and we are reading %p\n", + (void*)FIRCLSThreadContextGetStackPointer(registers), (void*)address); + // read the value from the stack, now that we know the address to read + uintptr_t value = 0; + if (!FIRCLSReadMemory((vm_address_t)address, (void*)&value, sizeof(uintptr_t))) { + FIRCLSSDKLog("Error: unable to read memory to set register\n"); + return false; + } + + FIRCLSSDKLog("Read PC to be %p\n", (void*)value); + if (!FIRCLSIsValidPointer(value)) { + FIRCLSSDKLog("Error: computed PC is invalid\n"); + return false; + } + + return FIRCLSThreadContextSetPC(registers, value) && + FIRCLSThreadContextSetStackPointer(registers, address + sizeof(void*)); +} +#endif + +#else +INJECT_STRIP_SYMBOL(unwind_x86) +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_x86.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_x86.h new file mode 100644 index 000000000..7c8010ec0 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_x86.h @@ -0,0 +1,76 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "FIRCLSCompactUnwind.h" +#include "FIRCLSFeatures.h" + +// Add some abstraction to compact unwinding, because compact +// unwinding is nearly identical between 32 and 64 bit +#if CLS_CPU_X86_64 + +#define CLS_X86_MODE_MASK UNWIND_X86_64_MODE_MASK +#define CLS_X86_MODE_BP_FRAME UNWIND_X86_64_MODE_RBP_FRAME +#define CLS_X86_MODE_STACK_IMMD UNWIND_X86_64_MODE_STACK_IMMD +#define CLS_X86_MODE_STACK_IND UNWIND_X86_64_MODE_STACK_IND +#define CLS_X86_MODE_DWARF UNWIND_X86_64_MODE_DWARF + +#define CLS_X86_BP_FRAME_REGISTERS UNWIND_X86_64_RBP_FRAME_REGISTERS +#define CLS_X86_BP_FRAME_OFFSET UNWIND_X86_64_RBP_FRAME_OFFSET + +#define CLS_X86_FRAMELESS_STACK_SIZE UNWIND_X86_64_FRAMELESS_STACK_SIZE +#define CLS_X86_FRAMELESS_STACK_ADJUST UNWIND_X86_64_FRAMELESS_STACK_ADJUST +#define CLS_X86_FRAMELESS_STACK_REG_COUNT UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT +#define CLS_X86_FRAMELESS_STACK_REG_PERMUTATION UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION + +#define CLS_X86_DWARF_SECTION_OFFSET UNWIND_X86_64_DWARF_SECTION_OFFSET + +#define CLS_X86_REG_RBP UNWIND_X86_64_REG_RBP + +#else + +#define CLS_X86_MODE_MASK UNWIND_X86_MODE_MASK +#define CLS_X86_MODE_BP_FRAME UNWIND_X86_MODE_EBP_FRAME +#define CLS_X86_MODE_STACK_IMMD UNWIND_X86_MODE_STACK_IMMD +#define CLS_X86_MODE_STACK_IND UNWIND_X86_MODE_STACK_IND +#define CLS_X86_MODE_DWARF UNWIND_X86_MODE_DWARF + +#define CLS_X86_BP_FRAME_REGISTERS UNWIND_X86_RBP_FRAME_REGISTERS +#define CLS_X86_BP_FRAME_OFFSET UNWIND_X86_RBP_FRAME_OFFSET + +#define CLS_X86_FRAMELESS_STACK_SIZE UNWIND_X86_FRAMELESS_STACK_SIZE +#define CLS_X86_FRAMELESS_STACK_ADJUST UNWIND_X86_FRAMELESS_STACK_ADJUST +#define CLS_X86_FRAMELESS_STACK_REG_COUNT UNWIND_X86_FRAMELESS_STACK_REG_COUNT +#define CLS_X86_FRAMELESS_STACK_REG_PERMUTATION UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION + +#define CLS_X86_DWARF_SECTION_OFFSET UNWIND_X86_DWARF_SECTION_OFFSET + +#define CLS_X86_REG_RBP UNWIND_X86_REG_EBP + +#endif + +#if CLS_COMPACT_UNWINDING_SUPPORTED +bool FIRCLSCompactUnwindComputeStackSize(const compact_unwind_encoding_t encoding, + const uintptr_t functionStart, + const bool indirect, + uint32_t* const stackSize); +bool FIRCLSCompactUnwindDecompressPermutation(const compact_unwind_encoding_t encoding, + uintptr_t permutatedRegisters[const static 6]); +bool FIRCLSCompactUnwindRestoreRegisters(compact_unwind_encoding_t encoding, + FIRCLSThreadContext* registers, + uint32_t stackSize, + const uintptr_t savedRegisters[const static 6], + uintptr_t* address); +#endif diff --git a/ios/Pods/FirebaseCoreDiagnosticsInterop/LICENSE b/ios/Pods/FirebaseCrashlytics/Crashlytics/LICENSE similarity index 88% rename from ios/Pods/FirebaseCoreDiagnosticsInterop/LICENSE rename to ios/Pods/FirebaseCrashlytics/Crashlytics/LICENSE index d64569567..925bc57fc 100644 --- a/ios/Pods/FirebaseCoreDiagnosticsInterop/LICENSE +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/LICENSE @@ -200,3 +200,31 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + +================================================================================ + +The following copyright from Hewlett-Packard Development Company, L.P. +applies to the dwarf.h file in third_party/libunwind + + libunwind - a platform-independent unwind library + Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang <davidm@hpl.hp.com> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Protogen/nanopb/crashlytics.nanopb.c b/ios/Pods/FirebaseCrashlytics/Crashlytics/Protogen/nanopb/crashlytics.nanopb.c new file mode 100644 index 000000000..d2e9d0455 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Protogen/nanopb/crashlytics.nanopb.c @@ -0,0 +1,75 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.3.9.5 */ + +#include "crashlytics.nanopb.h" + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + + + +const pb_field_t google_crashlytics_Report_fields[8] = { + PB_FIELD( 1, BYTES , SINGULAR, POINTER , FIRST, google_crashlytics_Report, sdk_version, sdk_version, 0), + PB_FIELD( 3, BYTES , SINGULAR, POINTER , OTHER, google_crashlytics_Report, gmp_app_id, sdk_version, 0), + PB_FIELD( 4, UENUM , SINGULAR, STATIC , OTHER, google_crashlytics_Report, platform, gmp_app_id, 0), + PB_FIELD( 5, BYTES , SINGULAR, POINTER , OTHER, google_crashlytics_Report, installation_uuid, platform, 0), + PB_FIELD( 6, BYTES , SINGULAR, POINTER , OTHER, google_crashlytics_Report, build_version, installation_uuid, 0), + PB_FIELD( 7, BYTES , SINGULAR, POINTER , OTHER, google_crashlytics_Report, display_version, build_version, 0), + PB_FIELD( 10, MESSAGE , SINGULAR, STATIC , OTHER, google_crashlytics_Report, apple_payload, display_version, &google_crashlytics_FilesPayload_fields), + PB_LAST_FIELD +}; + +const pb_field_t google_crashlytics_FilesPayload_fields[2] = { + PB_FIELD( 1, MESSAGE , REPEATED, POINTER , FIRST, google_crashlytics_FilesPayload, files, files, &google_crashlytics_FilesPayload_File_fields), + PB_LAST_FIELD +}; + +const pb_field_t google_crashlytics_FilesPayload_File_fields[3] = { + PB_FIELD( 1, BYTES , SINGULAR, POINTER , FIRST, google_crashlytics_FilesPayload_File, filename, filename, 0), + PB_FIELD( 2, BYTES , SINGULAR, POINTER , OTHER, google_crashlytics_FilesPayload_File, contents, filename, 0), + PB_LAST_FIELD +}; + + + +/* Check that field information fits in pb_field_t */ +#if !defined(PB_FIELD_32BIT) +/* If you get an error here, it means that you need to define PB_FIELD_32BIT + * compile-time option. You can do that in pb.h or on compiler command line. + * The reason you need to do this is that some of your messages contain tag + * numbers or field sizes that are larger than what can fit in 8 or 16 bit + * field descriptors. + */ +PB_STATIC_ASSERT((pb_membersize(google_crashlytics_Report, apple_payload) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_google_crashlytics_Report_google_crashlytics_FilesPayload_google_crashlytics_FilesPayload_File) +#endif + +#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) +/* If you get an error here, it means that you need to define PB_FIELD_16BIT + * compile-time option. You can do that in pb.h or on compiler command line. + * The reason you need to do this is that some of your messages contain tag + * numbers or field sizes that are larger than what can fit in the default + * 8 bit descriptors. + */ +PB_STATIC_ASSERT((pb_membersize(google_crashlytics_Report, apple_payload) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_google_crashlytics_Report_google_crashlytics_FilesPayload_google_crashlytics_FilesPayload_File) +#endif + + +/* @@protoc_insertion_point(eof) */ diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Protogen/nanopb/crashlytics.nanopb.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Protogen/nanopb/crashlytics.nanopb.h new file mode 100644 index 000000000..c873fbcd8 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Protogen/nanopb/crashlytics.nanopb.h @@ -0,0 +1,107 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.3.9.5 */ + +#ifndef PB_GOOGLE_CRASHLYTICS_CRASHLYTICS_NANOPB_H_INCLUDED +#define PB_GOOGLE_CRASHLYTICS_CRASHLYTICS_NANOPB_H_INCLUDED +#include <nanopb/pb.h> + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + + +/* Enum definitions */ +typedef enum _google_crashlytics_Platforms { + google_crashlytics_Platforms_UNKNOWN_PLATFORM = 0, + google_crashlytics_Platforms_IOS = 1, + google_crashlytics_Platforms_TVOS = 2, + google_crashlytics_Platforms_MAC_OS_X = 5 +} google_crashlytics_Platforms; +#define _google_crashlytics_Platforms_MIN google_crashlytics_Platforms_UNKNOWN_PLATFORM +#define _google_crashlytics_Platforms_MAX google_crashlytics_Platforms_MAC_OS_X +#define _google_crashlytics_Platforms_ARRAYSIZE ((google_crashlytics_Platforms)(google_crashlytics_Platforms_MAC_OS_X+1)) + +/* Struct definitions */ +typedef struct _google_crashlytics_FilesPayload { + pb_size_t files_count; + struct _google_crashlytics_FilesPayload_File *files; +/* @@protoc_insertion_point(struct:google_crashlytics_FilesPayload) */ +} google_crashlytics_FilesPayload; + +typedef struct _google_crashlytics_FilesPayload_File { + pb_bytes_array_t *filename; + pb_bytes_array_t *contents; +/* @@protoc_insertion_point(struct:google_crashlytics_FilesPayload_File) */ +} google_crashlytics_FilesPayload_File; + +typedef struct _google_crashlytics_Report { + pb_bytes_array_t *sdk_version; + pb_bytes_array_t *gmp_app_id; + google_crashlytics_Platforms platform; + pb_bytes_array_t *installation_uuid; + pb_bytes_array_t *build_version; + pb_bytes_array_t *display_version; + google_crashlytics_FilesPayload apple_payload; +/* @@protoc_insertion_point(struct:google_crashlytics_Report) */ +} google_crashlytics_Report; + +/* Default values for struct fields */ + +/* Initializer values for message structs */ +#define google_crashlytics_Report_init_default {NULL, NULL, _google_crashlytics_Platforms_MIN, NULL, NULL, NULL, google_crashlytics_FilesPayload_init_default} +#define google_crashlytics_FilesPayload_init_default {0, NULL} +#define google_crashlytics_FilesPayload_File_init_default {NULL, NULL} +#define google_crashlytics_Report_init_zero {NULL, NULL, _google_crashlytics_Platforms_MIN, NULL, NULL, NULL, google_crashlytics_FilesPayload_init_zero} +#define google_crashlytics_FilesPayload_init_zero {0, NULL} +#define google_crashlytics_FilesPayload_File_init_zero {NULL, NULL} + +/* Field tags (for use in manual encoding/decoding) */ +#define google_crashlytics_FilesPayload_files_tag 1 +#define google_crashlytics_FilesPayload_File_filename_tag 1 +#define google_crashlytics_FilesPayload_File_contents_tag 2 +#define google_crashlytics_Report_sdk_version_tag 1 +#define google_crashlytics_Report_gmp_app_id_tag 3 +#define google_crashlytics_Report_platform_tag 4 +#define google_crashlytics_Report_installation_uuid_tag 5 +#define google_crashlytics_Report_build_version_tag 6 +#define google_crashlytics_Report_display_version_tag 7 +#define google_crashlytics_Report_apple_payload_tag 10 + +/* Struct field encoding specification for nanopb */ +extern const pb_field_t google_crashlytics_Report_fields[8]; +extern const pb_field_t google_crashlytics_FilesPayload_fields[2]; +extern const pb_field_t google_crashlytics_FilesPayload_File_fields[3]; + +/* Maximum encoded size of messages (where known) */ +/* google_crashlytics_Report_size depends on runtime parameters */ +/* google_crashlytics_FilesPayload_size depends on runtime parameters */ +/* google_crashlytics_FilesPayload_File_size depends on runtime parameters */ + +/* Message IDs (where set with "msgid" option) */ +#ifdef PB_MSGID + +#define CRASHLYTICS_MESSAGES \ + + +#endif + +/* @@protoc_insertion_point(eof) */ + +#endif diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/README.md b/ios/Pods/FirebaseCrashlytics/Crashlytics/README.md new file mode 100644 index 000000000..55d36e659 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/README.md @@ -0,0 +1,39 @@ +# Firebase Crashlytics SDK + +## Development + +Follow the subsequent instructions to develop, debug, unit test, and +integration test FirebaseCrashlytics: + +### Prereqs + +- At least CocoaPods 1.6.0 +- Install [cocoapods-generate](https://github.com/square/cocoapods-generate) +- For nanopb and GDT: + - `brew install protobuf nanopb-generator` + - `easy_install protobuf python` + +### To Develop + +- Run `Crashlytics/generate_project.sh` +- `open gen/FirebaseCrashlytics/FirebaseCrashlytics.xcworkspace` + +You're now in an Xcode workspace generate for building, debugging and +testing the FirebaseCrashlytics CocoaPod. + +### Running Unit Tests + +Open the generated workspace, choose the FirebaseCrashlytics-Unit-unit scheme and press Command-u. + +### Changing crash report uploads (using GDT) + +#### Update report proto + +If the crash report proto needs to be updated, follow these instructions: + +- Update `ProtoSupport/Protos/crashlytics.proto` with the new changes +- Depending on the type of fields added/removed, also update `ProtoSupport/Protos/crashlytics.options`. + `CALLBACK` type fields in crashlytics.nanopb.c needs to be changed to `POINTER` + (through the options file). Known field types that require an entry in crashlytics.options are + `strings`, `repeated` and `bytes`. +- Run `generate_project.sh` to update the nanopb .c/.h files. \ No newline at end of file diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSByteUtility.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSByteUtility.h new file mode 100644 index 000000000..ca2abb81d --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSByteUtility.h @@ -0,0 +1,41 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +/** + * Returns a SHA1 Hash of the input NSData + */ +NSString *FIRCLSHashNSData(NSData *data); +/** + * Returns a SHA256 Hash of the input NSData + */ +NSString *FIRCLS256HashNSData(NSData *data); +/** + * Returns a SHA1 Hash of the input bytes + */ +NSString *FIRCLSHashBytes(const void *bytes, size_t length); +/** + * Populates a Hex value conversion of value into outputBuffer. + * If value is nil, then outputBuffer is not modified. + */ +void FIRCLSSafeHexToString(const uint8_t *value, size_t length, char *outputBuffer); + +/** + * Iterates through the raw bytes of NSData in a way that is similar to + * -[NSData enumerateByteRangesUsingBlock:], but is safe to call from older + * OSes that do not support it. + */ +void FIRCLSEnumerateByteRangesOfNSDataUsingBlock( + NSData *data, void (^block)(const void *bytes, NSRange byteRange, BOOL *stop)); diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSByteUtility.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSByteUtility.m new file mode 100644 index 000000000..79f46f3f7 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSByteUtility.m @@ -0,0 +1,120 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSByteUtility.h" + +#import <CommonCrypto/CommonDigest.h> +#import <CommonCrypto/CommonHMAC.h> + +#pragma mark Private functions + +static const char FIRCLSHexMap[] = "0123456789abcdef"; + +void FIRCLSHexFromByte(uint8_t c, char output[]) { + if (!output) { + return; + } + + output[0] = FIRCLSHexMap[c >> 4]; + output[1] = FIRCLSHexMap[c & 0x0f]; +} + +void FIRCLSSafeHexToString(const uint8_t *value, size_t length, char *outputBuffer) { + if (!outputBuffer) { + return; + } + + memset(outputBuffer, 0, (length * 2) + 1); + + if (!value) { + return; + } + + for (size_t i = 0; i < length; ++i) { + uint8_t c = value[i]; + + FIRCLSHexFromByte(c, &outputBuffer[i * 2]); + } +} + +NSString *FIRCLSNSDataPrettyDescription(NSData *data) { + NSString *string; + char *buffer; + size_t size; + NSUInteger length; + + // we need 2 hex char for every byte of data, plus one more spot for a + // null terminator + length = data.length; + size = (length * 2) + 1; + buffer = malloc(sizeof(char) * size); + + if (!buffer) { + return nil; + } + + FIRCLSSafeHexToString(data.bytes, length, buffer); + + string = [NSString stringWithUTF8String:buffer]; + + free(buffer); + + return string; +} + +#pragma mark Public functions + +NSString *FIRCLSHashBytes(const void *bytes, size_t length) { + uint8_t digest[CC_SHA1_DIGEST_LENGTH] = {0}; + CC_SHA1(bytes, (CC_LONG)length, digest); + + NSData *result = [NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH]; + + return FIRCLSNSDataPrettyDescription(result); +} + +NSString *FIRCLSHashNSData(NSData *data) { + return FIRCLSHashBytes(data.bytes, data.length); +} + +NSString *FIRCLS256HashBytes(const void *bytes, size_t length) { + uint8_t digest[CC_SHA256_DIGEST_LENGTH] = {0}; + CC_SHA256(bytes, (CC_LONG)length, digest); + + NSData *result = [NSData dataWithBytes:digest length:CC_SHA256_DIGEST_LENGTH]; + + return FIRCLSNSDataPrettyDescription(result); +} + +NSString *FIRCLS256HashNSData(NSData *data) { + return FIRCLS256HashBytes(data.bytes, data.length); +} + +void FIRCLSEnumerateByteRangesOfNSDataUsingBlock( + NSData *data, void (^block)(const void *bytes, NSRange byteRange, BOOL *stop)) { + if ([data respondsToSelector:@selector(enumerateByteRangesUsingBlock:)]) { + [data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) { + block(bytes, byteRange, stop); + }]; + + return; + } + + // Fall back to the less-efficient mechanism for older OSes. Safe + // to ignore the return value of stop, since we'll only ever + // call this once anyways + BOOL stop = NO; + + block(data.bytes, NSMakeRange(0, data.length), &stop); +} diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSConstants.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSConstants.h new file mode 100644 index 000000000..c17ee02c5 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSConstants.h @@ -0,0 +1,45 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +FOUNDATION_EXPORT NSString *const FIRCLSDeveloperToken; + +FOUNDATION_EXPORT NSString *const FIRCLSVersion; + +// User Messages +FOUNDATION_EXPORT NSString *const FIRCLSMissingConsumerKeyMsg; +FOUNDATION_EXPORT NSString *const FIRCLSMissingConsumerSecretMsg; + +// Exceptions +FOUNDATION_EXPORT NSString *const FIRCLSException; + +// Endpoints +FOUNDATION_EXPORT NSString *const FIRCLSSettingsEndpoint; +FOUNDATION_EXPORT NSString *const FIRCLSConfigureEndpoint; +FOUNDATION_EXPORT NSString *const FIRCLSReportsEndpoint; + +// Network requests +FOUNDATION_EXPORT NSString *const FIRCLSNetworkAccept; +FOUNDATION_EXPORT NSString *const FIRCLSNetworkAcceptCharset; +FOUNDATION_EXPORT NSString *const FIRCLSNetworkApplicationJson; +FOUNDATION_EXPORT NSString *const FIRCLSNetworkAcceptLanguage; +FOUNDATION_EXPORT NSString *const FIRCLSNetworkContentLanguage; +FOUNDATION_EXPORT NSString *const FIRCLSNetworkCrashlyticsAPIClientDisplayVersion; +FOUNDATION_EXPORT NSString *const FIRCLSNetworkCrashlyticsAPIClientId; +FOUNDATION_EXPORT NSString *const FIRCLSNetworkCrashlyticsDeveloperToken; +FOUNDATION_EXPORT NSString *const FIRCLSNetworkCrashlyticsGoogleAppId; +FOUNDATION_EXPORT NSString *const FIRCLSNetworkCrashlyticsOrgId; +FOUNDATION_EXPORT NSString *const FIRCLSNetworkUserAgent; +FOUNDATION_EXPORT NSString *const FIRCLSNetworkUTF8; diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSConstants.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSConstants.m new file mode 100644 index 000000000..f733f0de7 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSConstants.m @@ -0,0 +1,49 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSConstants.h" + +#define STR_HELPER(x) #x +#define STR(x) STR_HELPER(x) + +NSString* const FIRCLSDeveloperToken = @"77f0789d8e230eccdb4b99b82dccd78d47f9b604"; + +NSString* const FIRCLSVersion = @STR(DISPLAY_VERSION); + +// User Messages +NSString* const FIRCLSMissingConsumerKeyMsg = @"consumer key is nil or zero length"; +NSString* const FIRCLSMissingConsumerSecretMsg = @"consumer secret is nil or zero length"; + +// Exceptions +NSString* const FIRCLSException = @"FIRCLSException"; + +// Endpoints +NSString* const FIRCLSSettingsEndpoint = @"https://firebase-settings.crashlytics.com"; +NSString* const FIRCLSConfigureEndpoint = @"https://update.crashlytics.com"; +NSString* const FIRCLSReportsEndpoint = @"https://reports.crashlytics.com"; + +// Network requests +NSString* const FIRCLSNetworkAccept = @"Accept"; +NSString* const FIRCLSNetworkAcceptCharset = @"Accept-Charset"; +NSString* const FIRCLSNetworkApplicationJson = @"application/json"; +NSString* const FIRCLSNetworkAcceptLanguage = @"Accept-Language"; +NSString* const FIRCLSNetworkContentLanguage = @"Content-Language"; +NSString* const FIRCLSNetworkCrashlyticsAPIClientDisplayVersion = + @"X-Crashlytics-API-Client-Display-Version"; +NSString* const FIRCLSNetworkCrashlyticsAPIClientId = @"X-Crashlytics-API-Client-Id"; +NSString* const FIRCLSNetworkCrashlyticsDeveloperToken = @"X-Crashlytics-Developer-Token"; +NSString* const FIRCLSNetworkCrashlyticsGoogleAppId = @"X-Crashlytics-Google-App-Id"; +NSString* const FIRCLSNetworkCrashlyticsOrgId = @"X-Crashlytics-Org-Id"; +NSString* const FIRCLSNetworkUserAgent = @"User-Agent"; +NSString* const FIRCLSNetworkUTF8 = @"utf-8"; diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSFABHost.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSFABHost.h new file mode 100644 index 000000000..82c8fccfd --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSFABHost.h @@ -0,0 +1,35 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +/** + * Returns the OS version of the host device + */ +NSOperatingSystemVersion FIRCLSHostGetOSVersion(void); + +/** + * Returns model info for the device on which app is running + */ +NSString *FIRCLSHostModelInfo(void); + +/** + * Returns a string representing the OS build + */ +NSString *FIRCLSHostOSBuildVersion(void); + +/** + * Returns a concatenated string of the OS version(majorVersion.minorVersion.patchVersion) + */ +NSString *FIRCLSHostOSDisplayVersion(void); diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSFABHost.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSFABHost.m new file mode 100644 index 000000000..4c3206c1e --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSFABHost.m @@ -0,0 +1,119 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSFABHost.h" + +#if TARGET_OS_WATCH +#import <WatchKit/WatchKit.h> +#elif TARGET_OS_IPHONE +#import <UIKit/UIKit.h> +#endif + +#include <sys/sysctl.h> + +#define FIRCLS_HOST_SYSCTL_BUFFER_SIZE (128) + +#pragma mark - OS Versions + +#pragma mark Private + +static NSString *FIRCLSHostSysctlEntry(const char *sysctlKey) { + char buffer[FIRCLS_HOST_SYSCTL_BUFFER_SIZE]; + size_t bufferSize = FIRCLS_HOST_SYSCTL_BUFFER_SIZE; + if (sysctlbyname(sysctlKey, buffer, &bufferSize, NULL, 0) != 0) { + return nil; + } + return [NSString stringWithUTF8String:buffer]; +} + +#pragma mark Public + +NSOperatingSystemVersion FIRCLSHostGetOSVersion(void) { + // works on macos(10.10), ios(8.0), watchos(2.0), tvos(9.0) + if ([NSProcessInfo.processInfo respondsToSelector:@selector(operatingSystemVersion)]) { + return [NSProcessInfo.processInfo operatingSystemVersion]; + } + + NSOperatingSystemVersion version = {0, 0, 0}; + +#if TARGET_OS_IPHONE + +#if TARGET_OS_WATCH + NSString *versionString = [[WKInterfaceDevice currentDevice] systemVersion]; +#else + NSString *versionString = [[UIDevice currentDevice] systemVersion]; +#endif + + NSArray *parts = [versionString componentsSeparatedByString:@"."]; + + if (parts.count > 0) { + version.majorVersion = [[parts objectAtIndex:0] integerValue]; + } + + if ([parts count] > 1) { + version.minorVersion = [[parts objectAtIndex:1] integerValue]; + } + + if ([parts count] > 2) { + version.patchVersion = [[parts objectAtIndex:2] integerValue]; + } + +#endif + + return version; +} + +NSString *FIRCLSHostOSBuildVersion(void) { + return FIRCLSHostSysctlEntry("kern.osversion"); +} + +NSString *FIRCLSHostOSDisplayVersion(void) { + NSOperatingSystemVersion version = FIRCLSHostGetOSVersion(); + return [NSString stringWithFormat:@"%ld.%ld.%ld", (long)version.majorVersion, + (long)version.minorVersion, (long)version.patchVersion]; +} + +#pragma mark - Host Models + +#pragma mark Public + +NSString *FIRCLSHostModelInfo(void) { + NSString *model = nil; + +#if TARGET_OS_SIMULATOR +#if TARGET_OS_WATCH + model = @"watchOS Simulator"; +#elif TARGET_OS_TV + model = @"tvOS Simulator"; +#elif TARGET_OS_IPHONE + switch (UI_USER_INTERFACE_IDIOM()) { + case UIUserInterfaceIdiomPhone: + model = @"iOS Simulator (iPhone)"; + break; + case UIUserInterfaceIdiomPad: + model = @"iOS Simulator (iPad)"; + break; + default: + model = @"iOS Simulator (Unknown)"; + break; + } +#endif +#elif TARGET_OS_EMBEDDED + model = FIRCLSHostSysctlEntry("hw.machine"); +#else + model = FIRCLSHostSysctlEntry("hw.model"); +#endif + + return model; +} diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSCodeMapping.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSCodeMapping.h new file mode 100644 index 000000000..ae80c46ad --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSCodeMapping.h @@ -0,0 +1,34 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +typedef enum { + FIRCLSCodeMappingSourceUnknown, + FIRCLSCodeMappingSourceBuild, + FIRCLSCodeSourceCache, + FIRCLSCodeSourceSpotlight +} FIRCLSCodeMappingSource; + +@interface FIRCLSCodeMapping : NSObject + ++ (instancetype)mappingWithURL:(NSURL*)URL; + +- (instancetype)initWithURL:(NSURL*)URL; + +@property(nonatomic, copy, readonly) NSURL* URL; +@property(nonatomic, assign) FIRCLSCodeMappingSource source; +@property(nonatomic, copy, readonly) NSString* sourceName; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSCodeMapping.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSCodeMapping.m new file mode 100644 index 000000000..c212ce7d1 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSCodeMapping.m @@ -0,0 +1,40 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSCodeMapping.h" + +@interface FIRCLSCodeMapping () { + FIRCLSCodeMappingSource _source; +} + +@end + +@implementation FIRCLSCodeMapping + ++ (instancetype)mappingWithURL:(NSURL*)URL { + return [[self alloc] initWithURL:URL]; +} + +- (instancetype)initWithURL:(NSURL*)URL { + self = [super init]; + if (!self) { + return nil; + } + + _URL = [URL copy]; + + return self; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachO.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachO.h new file mode 100644 index 000000000..59b460556 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachO.h @@ -0,0 +1,110 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include <mach-o/arch.h> +#include <mach-o/loader.h> +#include <sys/types.h> + +#include <CoreFoundation/CoreFoundation.h> + +struct FIRCLSMachOFile { + int fd; + size_t mappedSize; + void* mappedFile; +}; +typedef struct FIRCLSMachOFile* FIRCLSMachOFileRef; + +struct FIRCLSMachOSlice { + const void* startAddress; + cpu_type_t cputype; + cpu_subtype_t cpusubtype; +}; +typedef struct FIRCLSMachOSlice* FIRCLSMachOSliceRef; + +typedef struct { + uint32_t major; + uint32_t minor; + uint32_t bugfix; +} FIRCLSMachOVersion; + +typedef struct { + uint64_t addr; + uint64_t size; + uint32_t offset; +} FIRCLSMachOSection; + +typedef struct { + char segname[16]; + uint64_t vmaddr; + uint64_t vmsize; +} FIRCLSMachOSegmentCommand; + +typedef void (^FIRCLSMachOSliceIterator)(FIRCLSMachOSliceRef slice); +typedef void (^FIRCLSMachOLoadCommandIterator)(uint32_t type, + uint32_t size, + const struct load_command* cmd); + +__BEGIN_DECLS + +bool FIRCLSMachOFileInitWithPath(FIRCLSMachOFileRef file, const char* path); +bool FIRCLSMachOFileInitWithCurrent(FIRCLSMachOFileRef file); +void FIRCLSMachOFileDestroy(FIRCLSMachOFileRef file); +void FIRCLSMachOFileEnumerateSlices(FIRCLSMachOFileRef file, FIRCLSMachOSliceIterator block); +struct FIRCLSMachOSlice FIRCLSMachOFileSliceWithArchitectureName(FIRCLSMachOFileRef file, + const char* name); + +void FIRCLSMachOEnumerateSlicesAtAddress(void* executableData, FIRCLSMachOSliceIterator block); +void FIRCLSMachOSliceEnumerateLoadCommands(FIRCLSMachOSliceRef slice, + FIRCLSMachOLoadCommandIterator block); +struct FIRCLSMachOSlice FIRCLSMachOSliceGetCurrent(void); +struct FIRCLSMachOSlice FIRCLSMachOSliceWithHeader(void* machHeader); + +const char* FIRCLSMachOSliceGetExecutablePath(FIRCLSMachOSliceRef slice); +const char* FIRCLSMachOSliceGetArchitectureName(FIRCLSMachOSliceRef slice); +bool FIRCLSMachOSliceIs64Bit(FIRCLSMachOSliceRef slice); +bool FIRCLSMachOSliceGetSectionByName(FIRCLSMachOSliceRef slice, + const char* segName, + const char* sectionName, + const void** ptr); +bool FIRCLSMachOSliceInitSectionByName(FIRCLSMachOSliceRef slice, + const char* segName, + const char* sectionName, + FIRCLSMachOSection* section); +void FIRCLSMachOSliceGetUnwindInformation(FIRCLSMachOSliceRef slice, + const void** ehFrame, + const void** unwindInfo); + +// load-command-specific calls for convenience + +// returns a pointer to the 16-byte UUID +uint8_t const* FIRCLSMachOGetUUID(const struct load_command* cmd); +const char* FIRCLSMachOGetDylibPath(const struct load_command* cmd); + +// return true if the header indicates the binary is encrypted +bool FIRCLSMachOGetEncrypted(const struct load_command* cmd); + +// SDK minimums +FIRCLSMachOVersion FIRCLSMachOGetMinimumOSVersion(const struct load_command* cmd); +FIRCLSMachOVersion FIRCLSMachOGetLinkedSDKVersion(const struct load_command* cmd); + +// Helpers +FIRCLSMachOSegmentCommand FIRCLSMachOGetSegmentCommand(const struct load_command* cmd); + +#ifdef __OBJC__ +NSString* FIRCLSMachONormalizeUUID(CFUUIDBytes* uuidBytes); +NSString* FIRCLSMachOFormatVersion(FIRCLSMachOVersion* version); +#endif +__END_DECLS diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachO.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachO.m new file mode 100644 index 000000000..386438c46 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachO.m @@ -0,0 +1,509 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "FIRCLSMachO.h" + +#include <Foundation/Foundation.h> + +#include <mach-o/dyld.h> +#include <mach-o/fat.h> +#include <mach-o/getsect.h> +#include <mach-o/ldsyms.h> + +#include <sys/mman.h> +#include <sys/stat.h> + +#include <dlfcn.h> +#include <fcntl.h> + +#include <stdio.h> + +#include <unistd.h> + +// This is defined in newer versions of iOS/macOS in usr/include/mach/machine.h +#define CLS_CPU_SUBTYPE_ARM64E ((cpu_subtype_t)2) + +static void FIRCLSMachOHeaderValues(FIRCLSMachOSliceRef slice, + const struct load_command** cmds, + uint32_t* cmdCount); +static bool FIRCLSMachOSliceIsValid(FIRCLSMachOSliceRef slice); + +bool FIRCLSMachOFileInitWithPath(FIRCLSMachOFileRef file, const char* path) { + struct stat statBuffer; + + if (!file || !path) { + return false; + } + + file->fd = 0; + file->mappedFile = NULL; + file->mappedSize = 0; + + file->fd = open(path, O_RDONLY); + if (file->fd < 0) { + // unable to open mach-o file + return false; + } + + if (fstat(file->fd, &statBuffer) == -1) { + close(file->fd); + return false; + } + + // We need some minimum size for this to even be a possible mach-o file. I believe + // its probably quite a bit bigger than this, but this at least covers something. + // We also need it to be a regular file. + file->mappedSize = (size_t)statBuffer.st_size; + if (statBuffer.st_size < 16 || !(statBuffer.st_mode & S_IFREG)) { + close(file->fd); + return false; + } + + // Map the file to memory. MAP_SHARED can potentially reduce the amount of actual private + // memory needed to do this mapping. Also, be sure to check for the correct failure result. + file->mappedFile = mmap(0, file->mappedSize, PROT_READ, MAP_FILE | MAP_SHARED, file->fd, 0); + if (!file->mappedFile || (file->mappedFile == MAP_FAILED)) { + close(file->fd); + return false; + } + + return true; +} + +bool FIRCLSMachOFileInitWithCurrent(FIRCLSMachOFileRef file) { + struct FIRCLSMachOSlice slice = FIRCLSMachOSliceGetCurrent(); + + const char* imagePath = FIRCLSMachOSliceGetExecutablePath(&slice); + + return FIRCLSMachOFileInitWithPath(file, imagePath); +} + +void FIRCLSMachOFileDestroy(FIRCLSMachOFileRef file) { + if (!file) { + return; + } + + if (file->mappedFile && file->mappedSize > 0) { + munmap(file->mappedFile, file->mappedSize); + } + + close(file->fd); +} + +void FIRCLSMachOFileEnumerateSlices(FIRCLSMachOFileRef file, FIRCLSMachOSliceIterator block) { + FIRCLSMachOEnumerateSlicesAtAddress(file->mappedFile, block); +} + +void FIRCLSMachOEnumerateSlicesAtAddress(void* executableData, FIRCLSMachOSliceIterator block) { + // check the magic value, to determine if we have a fat header or not + uint32_t magicValue; + uint32_t archCount; + const struct fat_arch* fatArch; + struct FIRCLSMachOSlice slice; + + memset(&slice, 0, sizeof(struct FIRCLSMachOSlice)); + + magicValue = ((struct fat_header*)executableData)->magic; + if ((magicValue != FAT_MAGIC) && (magicValue != FAT_CIGAM)) { + slice.startAddress = executableData; + + // use this to fill in the values + FIRCLSMachOHeaderValues(&slice, NULL, NULL); + + block(&slice); + + return; + } + + archCount = OSSwapBigToHostInt32(((struct fat_header*)executableData)->nfat_arch); + fatArch = executableData + sizeof(struct fat_header); + + for (uint32_t i = 0; i < archCount; ++i) { + slice.cputype = OSSwapBigToHostInt32(fatArch->cputype); + slice.cpusubtype = OSSwapBigToHostInt32(fatArch->cpusubtype); + slice.startAddress = executableData + OSSwapBigToHostInt32(fatArch->offset); + + block(&slice); + + // advance to the next fat_arch structure + fatArch = (struct fat_arch*)((uintptr_t)fatArch + sizeof(struct fat_arch)); + } +} + +struct FIRCLSMachOSlice FIRCLSMachOFileSliceWithArchitectureName(FIRCLSMachOFileRef file, + const char* name) { + __block struct FIRCLSMachOSlice value; + + memset(&value, 0, sizeof(struct FIRCLSMachOSlice)); + + FIRCLSMachOFileEnumerateSlices(file, ^(FIRCLSMachOSliceRef slice) { + if (strcmp(FIRCLSMachOSliceGetArchitectureName(slice), name) == 0) { + value = *slice; + } + }); + + return value; +} + +static void FIRCLSMachOHeaderValues(FIRCLSMachOSliceRef slice, + const struct load_command** cmds, + uint32_t* cmdCount) { + const struct mach_header* header32 = (const struct mach_header*)slice->startAddress; + const struct mach_header_64* header64 = (const struct mach_header_64*)slice->startAddress; + uint32_t commandCount; + const void* commandsAddress; + + if (cmds) { + *cmds = NULL; + } + + if (cmdCount) { + *cmdCount = 0; + } + + if (!slice->startAddress) { + return; + } + + // the 32 and 64 bit versions have an identical structures, so this will work + switch (header32->magic) { + case MH_MAGIC: // 32-bit + case MH_CIGAM: + slice->cputype = header32->cputype; + slice->cpusubtype = header32->cpusubtype; + commandCount = header32->ncmds; + commandsAddress = slice->startAddress + sizeof(struct mach_header); + break; + case MH_MAGIC_64: // 64-bit + case MH_CIGAM_64: + slice->cputype = header64->cputype; + slice->cpusubtype = header64->cpusubtype; + commandCount = header64->ncmds; + commandsAddress = slice->startAddress + sizeof(struct mach_header_64); + break; + default: + // not a valid header + return; + } + + // assign everything back by reference + if (cmds) { + *cmds = commandsAddress; + } + + if (cmdCount) { + *cmdCount = commandCount; + } +} + +static bool FIRCLSMachOSliceIsValid(FIRCLSMachOSliceRef slice) { + if (!slice) { + return false; + } + + if (!slice->startAddress) { + return false; + } + + return true; +} + +void FIRCLSMachOSliceEnumerateLoadCommands(FIRCLSMachOSliceRef slice, + FIRCLSMachOLoadCommandIterator block) { + const struct load_command* cmd; + uint32_t cmdCount; + + if (!block) { + return; + } + + if (!FIRCLSMachOSliceIsValid(slice)) { + return; + } + + FIRCLSMachOHeaderValues(slice, &cmd, &cmdCount); + + for (uint32_t i = 0; cmd != NULL && i < cmdCount; ++i) { + block(cmd->cmd, cmd->cmdsize, cmd); + + cmd = (struct load_command*)((uintptr_t)cmd + cmd->cmdsize); + } +} + +struct FIRCLSMachOSlice FIRCLSMachOSliceGetCurrent(void) { + const NXArchInfo* archInfo; + struct FIRCLSMachOSlice slice; + void* executableSymbol; + Dl_info dlinfo; + + archInfo = NXGetLocalArchInfo(); + if (archInfo) { + slice.cputype = archInfo->cputype; + slice.cpusubtype = archInfo->cpusubtype; + } + + slice.startAddress = NULL; + + // This call can fail when Exported Symbols File in Build Settings is missing the symbol value + // defined as _MH_EXECUTE_SYM (if you look in the header the underscored MH_EXECUTE_SYM define is + // there) + executableSymbol = dlsym(RTLD_MAIN_ONLY, MH_EXECUTE_SYM); + + // get the address of the main function + if (dladdr(executableSymbol, &dlinfo) != 0) { + slice.startAddress = dlinfo.dli_fbase; + } + + return slice; +} + +struct FIRCLSMachOSlice FIRCLSMachOSliceWithHeader(void* machHeader) { + struct FIRCLSMachOSlice slice; + + slice.startAddress = machHeader; + + return slice; +} + +const char* FIRCLSMachOSliceGetExecutablePath(FIRCLSMachOSliceRef slice) { + Dl_info info; + + if (!FIRCLSMachOSliceIsValid(slice)) { + return NULL; + } + + // use dladdr here to look up the information we need for a binary image + if (dladdr(slice->startAddress, &info) == 0) { + return NULL; + } + + return info.dli_fname; +} + +const char* FIRCLSMachOSliceGetArchitectureName(FIRCLSMachOSliceRef slice) { + const NXArchInfo* archInfo; + + // there are some special cases here for types not handled by earlier OSes + if (slice->cputype == CPU_TYPE_ARM && slice->cpusubtype == CPU_SUBTYPE_ARM_V7S) { + return "armv7s"; + } + + if (slice->cputype == (CPU_TYPE_ARM | CPU_ARCH_ABI64)) { + if (slice->cpusubtype == CLS_CPU_SUBTYPE_ARM64E) { + return "arm64e"; + } else if (slice->cpusubtype == CPU_SUBTYPE_ARM64_ALL) { + return "arm64"; + } + } + + if (slice->cputype == (CPU_TYPE_ARM) && slice->cpusubtype == CPU_SUBTYPE_ARM_V7K) { + return "armv7k"; + } + + archInfo = NXGetArchInfoFromCpuType(slice->cputype, slice->cpusubtype); + if (!archInfo) { + return "unknown"; + } + + return archInfo->name; +} + +bool FIRCLSMachOSliceIs64Bit(FIRCLSMachOSliceRef slice) { + // I'm pretty sure this is sufficient... + return (slice->cputype & CPU_ARCH_ABI64) == CPU_ARCH_ABI64; +} + +bool FIRCLSMachOSliceGetSectionByName(FIRCLSMachOSliceRef slice, + const char* segName, + const char* sectionName, + const void** ptr) { + if (!ptr) { + return false; + } + + *ptr = NULL; // make sure this is set before returning + + FIRCLSMachOSection section; + + if (!FIRCLSMachOSliceInitSectionByName(slice, segName, sectionName, §ion)) { + return false; + } + + // WARNING: this calculation isn't correct, but is here to maintain backwards + // compatibility for now with callers of FIRCLSMachOSliceGetSectionByName. All new + // users should be calling FIRCLSMachOSliceInitSectionByName + *ptr = (const void*)((uintptr_t)slice->startAddress + section.offset); + + return true; +} + +bool FIRCLSMachOSliceInitSectionByName(FIRCLSMachOSliceRef slice, + const char* segName, + const char* sectionName, + FIRCLSMachOSection* section) { + if (!FIRCLSMachOSliceIsValid(slice)) { + return false; + } + + if (!section) { + return false; + } + + memset(section, 0, sizeof(FIRCLSMachOSection)); + + if (FIRCLSMachOSliceIs64Bit(slice)) { + const struct section_64* sect = + getsectbynamefromheader_64(slice->startAddress, segName, sectionName); + if (!sect) { + return false; + } + + section->addr = sect->addr; + section->size = sect->size; + section->offset = sect->offset; + } else { + const struct section* sect = getsectbynamefromheader(slice->startAddress, segName, sectionName); + if (!sect) { + return false; + } + + section->addr = sect->addr; + section->size = sect->size; + section->offset = sect->offset; + } + + return true; +} + +// TODO: this is left in-place just to ensure that old crashltyics + new fabric are still compatible +// with each other. As a happy bonus, if that situation does come up, this will also fix the bug +// that was preventing compact unwind on arm64 + iOS 9 from working correctly. +void FIRCLSMachOSliceGetUnwindInformation(FIRCLSMachOSliceRef slice, + const void** ehFrame, + const void** unwindInfo) { + if (!unwindInfo && !ehFrame) { + return; + } + + bool found = false; + intptr_t slide = 0; + + // This is inefficient, but we have no other safe way to do this correctly. Modifying the + // FIRCLSMachOSlice structure is tempting, but could introduce weird binary-compatibility issues + // with version mis-matches. + for (uint32_t i = 0; i < _dyld_image_count(); ++i) { + const struct mach_header* header = _dyld_get_image_header(i); + + if (header == slice->startAddress) { + found = true; + slide = _dyld_get_image_vmaddr_slide(i); + break; + } + } + + // make sure we were able to find a matching value + if (!found) { + return; + } + + FIRCLSMachOSection section; + + if (unwindInfo) { + if (FIRCLSMachOSliceInitSectionByName(slice, SEG_TEXT, "__unwind_info", §ion)) { + *unwindInfo = (void*)(section.addr + slide); + } + } + + if (ehFrame) { + if (FIRCLSMachOSliceInitSectionByName(slice, SEG_TEXT, "__eh_frame", §ion)) { + *ehFrame = (void*)(section.addr + slide); + } + } +} + +uint8_t const* FIRCLSMachOGetUUID(const struct load_command* cmd) { + return ((const struct uuid_command*)cmd)->uuid; +} + +const char* FIRCLSMachOGetDylibPath(const struct load_command* cmd) { + const struct dylib_command* dylibcmd = (const struct dylib_command*)cmd; + + return (const char*)((uintptr_t)cmd + dylibcmd->dylib.name.offset); +} + +bool FIRCLSMachOGetEncrypted(const struct load_command* cmd) { + return ((struct encryption_info_command*)cmd)->cryptid > 0; +} + +static FIRCLSMachOVersion FIRCLSMachOVersionFromEncoded(uint32_t encoded) { + FIRCLSMachOVersion version; + + version.major = (encoded & 0xffff0000) >> 16; + version.minor = (encoded & 0x0000ff00) >> 8; + version.bugfix = encoded & 0x000000ff; + + return version; +} + +FIRCLSMachOVersion FIRCLSMachOGetMinimumOSVersion(const struct load_command* cmd) { + return FIRCLSMachOVersionFromEncoded(((const struct version_min_command*)cmd)->version); +} + +FIRCLSMachOVersion FIRCLSMachOGetLinkedSDKVersion(const struct load_command* cmd) { + return FIRCLSMachOVersionFromEncoded(((const struct version_min_command*)cmd)->sdk); +} + +FIRCLSMachOSegmentCommand FIRCLSMachOGetSegmentCommand(const struct load_command* cmd) { + FIRCLSMachOSegmentCommand segmentCommand; + + memset(&segmentCommand, 0, sizeof(FIRCLSMachOSegmentCommand)); + + if (!cmd) { + return segmentCommand; + } + + if (cmd->cmd == LC_SEGMENT) { + struct segment_command* segCmd = (struct segment_command*)cmd; + + memcpy(segmentCommand.segname, segCmd->segname, 16); + segmentCommand.vmaddr = segCmd->vmaddr; + segmentCommand.vmsize = segCmd->vmsize; + } else if (cmd->cmd == LC_SEGMENT_64) { + struct segment_command_64* segCmd = (struct segment_command_64*)cmd; + + memcpy(segmentCommand.segname, segCmd->segname, 16); + segmentCommand.vmaddr = segCmd->vmaddr; + segmentCommand.vmsize = segCmd->vmsize; + } + + return segmentCommand; +} + +NSString* FIRCLSMachONormalizeUUID(CFUUIDBytes* uuidBytes) { + CFUUIDRef uuid = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, *uuidBytes); + + NSString* string = CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, uuid)); + + CFRelease(uuid); + + return [[string stringByReplacingOccurrencesOfString:@"-" withString:@""] lowercaseString]; +} + +NSString* FIRCLSMachOFormatVersion(FIRCLSMachOVersion* version) { + if (!version) { + return nil; + } + + return [NSString stringWithFormat:@"%d.%d.%d", version->major, version->minor, version->bugfix]; +} diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOBinary.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOBinary.h new file mode 100644 index 000000000..57d54988a --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOBinary.h @@ -0,0 +1,41 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> +#import "FIRCLSMachO.h" + +@class FIRCLSMachOSlice; + +@interface FIRCLSMachOBinary : NSObject { + NSURL* _url; + + struct FIRCLSMachOFile _file; + NSMutableArray* _slices; + NSString* _instanceIdentifier; +} + ++ (id)MachOBinaryWithPath:(NSString*)path; + +- (id)initWithURL:(NSURL*)url; + +@property(nonatomic, copy, readonly) NSURL* URL; +@property(nonatomic, copy, readonly) NSString* path; +@property(nonatomic, strong, readonly) NSArray* slices; +@property(nonatomic, copy, readonly) NSString* instanceIdentifier; + +- (void)enumerateUUIDs:(void (^)(NSString* uuid, NSString* architecture))block; + +- (FIRCLSMachOSlice*)sliceForArchitecture:(NSString*)architecture; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOBinary.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOBinary.m new file mode 100644 index 000000000..12598e331 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOBinary.m @@ -0,0 +1,175 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSMachOBinary.h" + +#import "FIRCLSMachOSlice.h" + +#import <CommonCrypto/CommonHMAC.h> + +static void FIRCLSSafeHexToString(const uint8_t* value, size_t length, char* outputBuffer); +static NSString* FIRCLSNSDataToNSString(NSData* data); +static NSString* FIRCLSHashBytes(const void* bytes, size_t length); +static NSString* FIRCLSHashNSString(NSString* value); + +@interface FIRCLSMachOBinary () + ++ (NSString*)hashNSString:(NSString*)value; + +@end + +@implementation FIRCLSMachOBinary + ++ (id)MachOBinaryWithPath:(NSString*)path { + return [[self alloc] initWithURL:[NSURL fileURLWithPath:path]]; +} + +@synthesize slices = _slices; + +- (id)initWithURL:(NSURL*)url { + self = [super init]; + if (self) { + _url = [url copy]; + + if (!FIRCLSMachOFileInitWithPath(&_file, [[_url path] fileSystemRepresentation])) { + return nil; + } + + _slices = [NSMutableArray new]; + FIRCLSMachOFileEnumerateSlices(&_file, ^(FIRCLSMachOSliceRef slice) { + FIRCLSMachOSlice* sliceObject; + + sliceObject = [[FIRCLSMachOSlice alloc] initWithSlice:slice]; + + [self->_slices addObject:sliceObject]; + }); + } + + return self; +} + +- (void)dealloc { + FIRCLSMachOFileDestroy(&_file); +} + +- (NSURL*)URL { + return _url; +} + +- (NSString*)path { + return [_url path]; +} + +- (NSString*)instanceIdentifier { + if (_instanceIdentifier) { + return _instanceIdentifier; + } + + NSMutableString* prehashedString = [NSMutableString new]; + + // sort the slices by architecture + NSArray* sortedSlices = + [_slices sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { + return [[obj1 architectureName] compare:[obj2 architectureName]]; + }]; + + // append them all into a big string + for (FIRCLSMachOSlice* slice in sortedSlices) { + [prehashedString appendString:[slice uuid]]; + } + + _instanceIdentifier = [FIRCLSHashNSString(prehashedString) copy]; + + return _instanceIdentifier; +} + +- (void)enumerateUUIDs:(void (^)(NSString* uuid, NSString* architecture))block { + for (FIRCLSMachOSlice* slice in _slices) { + block([slice uuid], [slice architectureName]); + } +} + +- (FIRCLSMachOSlice*)sliceForArchitecture:(NSString*)architecture { + for (FIRCLSMachOSlice* slice in [self slices]) { + if ([[slice architectureName] isEqualToString:architecture]) { + return slice; + } + } + + return nil; +} + ++ (NSString*)hashNSString:(NSString*)value { + return FIRCLSHashNSString(value); +} + +@end + +// TODO: Functions copied from the SDK. We should figure out a way to share this. +static void FIRCLSSafeHexToString(const uint8_t* value, size_t length, char* outputBuffer) { + const char hex[] = "0123456789abcdef"; + + if (!value) { + outputBuffer[0] = '\0'; + return; + } + + for (size_t i = 0; i < length; ++i) { + unsigned char c = value[i]; + outputBuffer[i * 2] = hex[c >> 4]; + outputBuffer[i * 2 + 1] = hex[c & 0x0F]; + } + + outputBuffer[length * 2] = '\0'; // null terminate +} + +static NSString* FIRCLSNSDataToNSString(NSData* data) { + NSString* string; + char* buffer; + size_t size; + NSUInteger length; + + // we need 2 hex char for every byte of data, plus one more spot for a + // null terminator + length = [data length]; + size = (length * 2) + 1; + buffer = malloc(sizeof(char) * size); + + if (!buffer) { + return nil; + } + + FIRCLSSafeHexToString([data bytes], length, buffer); + + string = [NSString stringWithUTF8String:buffer]; + + free(buffer); + + return string; +} + +static NSString* FIRCLSHashBytes(const void* bytes, size_t length) { + uint8_t digest[CC_SHA1_DIGEST_LENGTH] = {0}; + CC_SHA1(bytes, (CC_LONG)length, digest); + + NSData* result = [NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH]; + + return FIRCLSNSDataToNSString(result); +} + +static NSString* FIRCLSHashNSString(NSString* value) { + const char* s = [value cStringUsingEncoding:NSUTF8StringEncoding]; + + return FIRCLSHashBytes(s, strlen(s)); +} diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOSlice.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOSlice.h new file mode 100644 index 000000000..9f7bcb43f --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOSlice.h @@ -0,0 +1,37 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> +#import "FIRCLSMachO.h" + +@interface FIRCLSMachOSlice : NSObject { + struct FIRCLSMachOSlice _slice; + + NSString* _uuidString; + NSArray* _linkedDylibs; + FIRCLSMachOVersion _minimumOSVersion; + FIRCLSMachOVersion _linkedSDKVersion; +} + ++ (id)runningSlice; + +- (id)initWithSlice:(FIRCLSMachOSliceRef)sliceRef; + +@property(nonatomic, copy, readonly) NSString* uuid; +@property(nonatomic, copy, readonly) NSString* architectureName; +@property(nonatomic, strong, readonly) NSArray* linkedDylibs; +@property(nonatomic, assign, readonly) FIRCLSMachOVersion minimumOSVersion; +@property(nonatomic, assign, readonly) FIRCLSMachOVersion linkedSDKVersion; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOSlice.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOSlice.m new file mode 100644 index 000000000..961e144a8 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOSlice.m @@ -0,0 +1,93 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSMachOSlice.h" + +#include <mach-o/loader.h> + +// this is defined only if __OPEN_SOURCE__ is *not* defined in the TVOS SDK's mach-o/loader.h +// also, it has not yet made it back to the OSX SDKs, for example +#ifndef LC_VERSION_MIN_TVOS +#define LC_VERSION_MIN_TVOS 0x2F +#endif + +@implementation FIRCLSMachOSlice + ++ (id)runningSlice { + struct FIRCLSMachOSlice slice; + + slice = FIRCLSMachOSliceGetCurrent(); + + return [[self alloc] initWithSlice:&slice]; +} + +@synthesize minimumOSVersion = _minimumOSVersion; +@synthesize linkedSDKVersion = _linkedSDKVersion; + +- (id)initWithSlice:(FIRCLSMachOSliceRef)sliceRef { + self = [super init]; + if (self) { + NSMutableArray* dylibs; + + _slice = *sliceRef; + + _minimumOSVersion.major = 0; + _minimumOSVersion.minor = 0; + _minimumOSVersion.bugfix = 0; + + _linkedSDKVersion.major = 0; + _linkedSDKVersion.minor = 0; + _linkedSDKVersion.bugfix = 0; + + dylibs = [NSMutableArray array]; + + FIRCLSMachOSliceEnumerateLoadCommands( + &_slice, ^(uint32_t type, uint32_t size, const struct load_command* cmd) { + switch (type) { + case LC_UUID: + self->_uuidString = + [FIRCLSMachONormalizeUUID((CFUUIDBytes*)FIRCLSMachOGetUUID(cmd)) copy]; + break; + case LC_LOAD_DYLIB: + [dylibs addObject:[NSString stringWithUTF8String:FIRCLSMachOGetDylibPath(cmd)]]; + break; + case LC_VERSION_MIN_IPHONEOS: + case LC_VERSION_MIN_MACOSX: + case LC_VERSION_MIN_WATCHOS: + case LC_VERSION_MIN_TVOS: + self->_minimumOSVersion = FIRCLSMachOGetMinimumOSVersion(cmd); + self->_linkedSDKVersion = FIRCLSMachOGetLinkedSDKVersion(cmd); + break; + } + }); + + _linkedDylibs = [dylibs copy]; + } + + return self; +} + +- (NSString*)architectureName { + return [NSString stringWithUTF8String:FIRCLSMachOSliceGetArchitectureName(&_slice)]; +} + +- (NSString*)uuid { + return _uuidString; +} + +- (NSArray*)linkedDylibs { + return _linkedDylibs; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSdSYM.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSdSYM.h new file mode 100644 index 000000000..c80ac745f --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSdSYM.h @@ -0,0 +1,38 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +@class FIRCLSMachOBinary; + +@interface FIRCLSdSYM : NSObject + +NS_ASSUME_NONNULL_BEGIN + ++ (id)dSYMWithURL:(NSURL*)url; + +- (id)initWithURL:(NSURL*)url; + +@property(nonatomic, readonly) FIRCLSMachOBinary* binary; +@property(nonatomic, copy, readonly, nullable) NSString* bundleIdentifier; +@property(nonatomic, copy, readonly) NSURL* executableURL; +@property(nonatomic, copy, readonly) NSString* executablePath; +@property(nonatomic, copy, readonly) NSString* bundleVersion; +@property(nonatomic, copy, readonly) NSString* shortBundleVersion; + +- (void)enumerateUUIDs:(void (^)(NSString* uuid, NSString* architecture))block; + +NS_ASSUME_NONNULL_END + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSdSYM.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSdSYM.m new file mode 100644 index 000000000..cda787914 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSdSYM.m @@ -0,0 +1,109 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSdSYM.h" + +#import "FIRCLSMachOBinary.h" + +#define CLS_XCODE_DSYM_PREFIX (@"com.apple.xcode.dsym.") + +@interface FIRCLSdSYM () + +@property(nonatomic, readonly) NSBundle* bundle; + +@end + +@implementation FIRCLSdSYM + ++ (id)dSYMWithURL:(NSURL*)url { + return [[self alloc] initWithURL:url]; +} + +- (id)initWithURL:(NSURL*)url { + self = [super init]; + if (self) { + NSDirectoryEnumerator* enumerator; + NSString* path; + NSFileManager* fileManager; + BOOL isDirectory; + BOOL fileExistsAtPath; + NSArray* itemsInDWARFDir; + + fileManager = [NSFileManager defaultManager]; + + // Is there a file at this path? + if (![fileManager fileExistsAtPath:[url path]]) { + return nil; + } + + _bundle = [NSBundle bundleWithURL:url]; + if (!_bundle) { + return nil; + } + + path = [[url path] stringByAppendingPathComponent:@"Contents/Resources/DWARF"]; + + // Does this path exist and is it a directory? + fileExistsAtPath = [fileManager fileExistsAtPath:path isDirectory:&isDirectory]; + if (!fileExistsAtPath || !isDirectory) { + return nil; + } + + enumerator = [fileManager enumeratorAtPath:path]; + itemsInDWARFDir = [enumerator allObjects]; + // Do we have a Contents/Resources/DWARF dir but no contents? + if ([itemsInDWARFDir count] == 0) { + return nil; + } + + path = [path stringByAppendingPathComponent:[itemsInDWARFDir objectAtIndex:0]]; + + _binary = [[FIRCLSMachOBinary alloc] initWithURL:[NSURL fileURLWithPath:path]]; + } + + return self; +} + +- (NSString*)bundleIdentifier { + NSString* identifier; + + identifier = [_bundle bundleIdentifier]; + if ([identifier hasPrefix:CLS_XCODE_DSYM_PREFIX]) { + return [identifier substringFromIndex:[CLS_XCODE_DSYM_PREFIX length]]; + } + + return identifier; +} + +- (NSURL*)executableURL { + return [_binary URL]; +} + +- (NSString*)executablePath { + return [_binary path]; +} + +- (NSString*)bundleVersion { + return [[_bundle infoDictionary] objectForKey:@"CFBundleVersion"]; +} + +- (NSString*)shortBundleVersion { + return [[_bundle infoDictionary] objectForKey:@"CFBundleShortVersionString"]; +} + +- (void)enumerateUUIDs:(void (^)(NSString* uuid, NSString* architecture))block { + [_binary enumerateUUIDs:block]; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSFABNetworkClient.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSFABNetworkClient.h new file mode 100644 index 000000000..ebbd26c91 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSFABNetworkClient.h @@ -0,0 +1,56 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +OBJC_EXTERN const NSUInteger FIRCLSNetworkMaximumRetryCount; + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^FIRCLSNetworkDataTaskCompletionHandlerBlock)(NSData *__nullable data, + NSURLResponse *__nullable response, + NSError *__nullable error); +typedef void (^FIRCLSNetworkDownloadTaskCompletionHandlerBlock)(NSURL *__nullable location, + NSURLResponse *__nullable response, + NSError *__nullable error); + +@interface FIRCLSFABNetworkClient : NSObject + +- (instancetype)init; +- (instancetype)initWithQueue:(nullable NSOperationQueue *)operationQueue; +- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)config + queue:(nullable NSOperationQueue *)operationQueue + NS_DESIGNATED_INITIALIZER; + +- (void)startDataTaskWithRequest:(NSURLRequest *)request + retryLimit:(NSUInteger)retryLimit + completionHandler:(FIRCLSNetworkDataTaskCompletionHandlerBlock)completionHandler; +- (void)startDownloadTaskWithRequest:(NSURLRequest *)request + retryLimit:(NSUInteger)retryLimit + completionHandler: + (FIRCLSNetworkDownloadTaskCompletionHandlerBlock)completionHandler; + +- (void)invalidateAndCancel; + +// Backwards compatibility (we cannot change an interface in Fabric Base that other kits rely on, +// since we have no control of versioning dependencies) +- (void)startDataTaskWithRequest:(NSURLRequest *)request + completionHandler:(FIRCLSNetworkDataTaskCompletionHandlerBlock)completionHandler; +- (void)startDownloadTaskWithRequest:(NSURLRequest *)request + completionHandler: + (FIRCLSNetworkDownloadTaskCompletionHandlerBlock)completionHandler; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSFABNetworkClient.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSFABNetworkClient.m new file mode 100644 index 000000000..d11b3b611 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSFABNetworkClient.m @@ -0,0 +1,280 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSFABNetworkClient.h" + +#if FIRCLSURLSESSION_REQUIRED +#import "FIRCLSURLSession.h" +#endif + +#import "FIRCLSNetworkResponseHandler.h" + +static const float FIRCLSNetworkMinimumRetryJitter = 0.90f; +static const float FIRCLSNetworkMaximumRetryJitter = 1.10f; +const NSUInteger FIRCLSNetworkMaximumRetryCount = 10; + +@interface FIRCLSFABNetworkClient () <NSURLSessionDelegate, NSURLSessionTaskDelegate> + +@property(nonatomic, strong, readonly) NSURLSession *session; + +@end + +@implementation FIRCLSFABNetworkClient + +- (instancetype)init { + return [self initWithQueue:nil]; +} + +- (instancetype)initWithQueue:(nullable NSOperationQueue *)operationQueue { +#if !FIRCLSURLSESSION_REQUIRED + NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; +#else + NSURLSessionConfiguration *config = [FIRCLSURLSessionConfiguration defaultSessionConfiguration]; +#endif + return [self initWithSessionConfiguration:config queue:operationQueue]; +} + +- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)config + queue:(nullable NSOperationQueue *)operationQueue { + self = [super init]; + if (!self) { + return nil; + } + +#if !FIRCLSURLSESSION_REQUIRED + _session = [NSURLSession sessionWithConfiguration:config + delegate:self + delegateQueue:operationQueue]; +#else + _session = [FIRCLSURLSession sessionWithConfiguration:config + delegate:self + delegateQueue:operationQueue]; +#endif + if (!_session) { + return nil; + } + + return self; +} + +- (void)dealloc { + [_session finishTasksAndInvalidate]; +} + +#pragma mark - Delay Handling +- (double)randomDoubleWithMin:(double)min max:(double)max { + return min + ((max - min) * drand48()); +} + +- (double)generateRandomJitter { + return [self randomDoubleWithMin:FIRCLSNetworkMinimumRetryJitter + max:FIRCLSNetworkMaximumRetryJitter]; +} + +- (NSTimeInterval)computeDelayForResponse:(NSURLResponse *)response + withRetryCount:(NSUInteger)count { + NSTimeInterval initialValue = [FIRCLSNetworkResponseHandler retryValueForResponse:response]; + + // make sure count is > 0 + count = MAX(count, 1); + // make sure initialValue is >2 for exponential backoff to work reasonably with low count numbers + initialValue = MAX(initialValue, 2.0); + + const double jitter = [self generateRandomJitter]; + + return pow(initialValue, count) * jitter; // exponential backoff +} + +- (void)runAfterRetryValueFromResponse:(NSURLResponse *)response + attempts:(NSUInteger)count + onQueue:(dispatch_queue_t)queue + block:(void (^)(void))block { + const NSTimeInterval delay = [self computeDelayForResponse:response withRetryCount:count]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (uint64_t)(delay * NSEC_PER_SEC)), queue, block); +} + +- (void)runAfterRetryValueFromResponse:(NSURLResponse *)response + attempts:(NSUInteger)count + block:(void (^)(void))block { + dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + + [self runAfterRetryValueFromResponse:response attempts:count onQueue:queue block:block]; +} + +#pragma mark - Tasks + +- (void)startDataTaskWithRequest:(NSURLRequest *)request + retryLimit:(NSUInteger)retryLimit + tries:(NSUInteger)tries + completionHandler:(FIRCLSNetworkDataTaskCompletionHandlerBlock)completionHandler { + NSURLSessionTask *task = [self.session + dataTaskWithRequest:request + completionHandler:^(NSData *data, NSURLResponse *response, NSError *taskError) { + [FIRCLSNetworkResponseHandler + handleCompletedResponse:response + forOriginalRequest:request + error:taskError + block:^(BOOL retry, NSError *error) { + if (!retry) { + completionHandler(data, response, error); + return; + } + + if (tries >= retryLimit) { + NSDictionary *userInfo = @{ + @"retryLimit" : @(retryLimit), + NSURLErrorFailingURLStringErrorKey : request.URL + }; + completionHandler( + nil, nil, + [NSError + errorWithDomain:FIRCLSNetworkErrorDomain + code:FIRCLSNetworkErrorMaximumAttemptsReached + userInfo:userInfo]); + return; + } + + [self + runAfterRetryValueFromResponse:response + attempts:tries + block:^{ + [self + startDataTaskWithRequest: + request + retryLimit: + retryLimit + tries: + (tries + + 1) + completionHandler: + completionHandler]; + }]; + }]; + }]; + + [task resume]; + + if (!task) { + completionHandler(nil, nil, + [NSError errorWithDomain:FIRCLSNetworkErrorDomain + code:FIRCLSNetworkErrorFailedToStartOperation + userInfo:nil]); + } +} + +- (void)startDataTaskWithRequest:(NSURLRequest *)request + retryLimit:(NSUInteger)retryLimit + completionHandler:(FIRCLSNetworkDataTaskCompletionHandlerBlock)completionHandler { + [self startDataTaskWithRequest:request + retryLimit:retryLimit + tries:0 + completionHandler:completionHandler]; +} + +- (void)startDataTaskWithRequest:(NSURLRequest *)request + completionHandler:(FIRCLSNetworkDataTaskCompletionHandlerBlock)completionHandler { + [self startDataTaskWithRequest:request + retryLimit:FIRCLSNetworkMaximumRetryCount + completionHandler:completionHandler]; +} + +- (void)startDownloadTaskWithRequest:(NSURLRequest *)request + retryLimit:(NSUInteger)retryLimit + tries:(NSUInteger)tries + completionHandler: + (FIRCLSNetworkDownloadTaskCompletionHandlerBlock)completionHandler { + NSURLSessionTask *task = [self.session + downloadTaskWithRequest:request + completionHandler:^(NSURL *location, NSURLResponse *response, NSError *taskError) { + [FIRCLSNetworkResponseHandler + handleCompletedResponse:response + forOriginalRequest:request + error:taskError + block:^(BOOL retry, NSError *error) { + if (!retry) { + completionHandler(location, response, error); + return; + } + + if (tries >= retryLimit) { + NSDictionary *userInfo = @{ + @"retryLimit" : @(retryLimit), + NSURLErrorFailingURLStringErrorKey : request.URL + }; + completionHandler( + nil, nil, + [NSError + errorWithDomain:FIRCLSNetworkErrorDomain + code: + FIRCLSNetworkErrorMaximumAttemptsReached + userInfo:userInfo]); + return; + } + + [self + runAfterRetryValueFromResponse:response + attempts:tries + block:^{ + [self + startDownloadTaskWithRequest: + request + retryLimit: + retryLimit + tries: + (tries + + 1) + completionHandler: + completionHandler]; + }]; + }]; + }]; + + [task resume]; + + if (!task) { + completionHandler(nil, nil, + [NSError errorWithDomain:FIRCLSNetworkErrorDomain + code:FIRCLSNetworkErrorFailedToStartOperation + userInfo:nil]); + } +} + +- (void)startDownloadTaskWithRequest:(NSURLRequest *)request + retryLimit:(NSUInteger)retryLimit + completionHandler: + (FIRCLSNetworkDownloadTaskCompletionHandlerBlock)completionHandler { + [self startDownloadTaskWithRequest:request + retryLimit:retryLimit + tries:0 + completionHandler:completionHandler]; +} + +- (void)startDownloadTaskWithRequest:(NSURLRequest *)request + completionHandler: + (FIRCLSNetworkDownloadTaskCompletionHandlerBlock)completionHandler { + [self startDownloadTaskWithRequest:request + retryLimit:FIRCLSNetworkMaximumRetryCount + completionHandler:completionHandler]; +} + +- (void)invalidateAndCancel { + [self.session invalidateAndCancel]; +} + +#pragma mark - NSURLSession Delegate +- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error { +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSMultipartMimeStreamEncoder.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSMultipartMimeStreamEncoder.h new file mode 100644 index 000000000..c3630a5b4 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSMultipartMimeStreamEncoder.h @@ -0,0 +1,88 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +/** + * This class is a helper class for generating Multipart requests, as described in + * http://www.w3.org/Protocols/rfc1341/7_2_Multipart.html. In the case of multiple part messages, in + * which one or more different sets of data are combined in a single body, a "multipart" + * Content-Type field must appear in the entity's header. The body must then contain one or more + * "body parts," each preceded by an encapsulation boundary, and the last one followed by a closing + * boundary. Each part starts with an encapsulation boundary, and then contains a body part + * consisting of header area, a blank line, and a body area. + */ +@interface FIRCLSMultipartMimeStreamEncoder : NSObject + +/** + * Convenience class method to populate a NSMutableURLRequest with data from a block that takes an + * instance of this class as input. + */ ++ (void)populateRequest:(NSMutableURLRequest *)request + withDataFromEncoder:(void (^)(FIRCLSMultipartMimeStreamEncoder *encoder))block; + +/** + * Returns a NSString instance with multipart/form-data appended to the boundary. + */ ++ (NSString *)contentTypeHTTPHeaderValueWithBoundary:(NSString *)boundary; +/** + * Convenience class method that returns an instance of this class + */ ++ (instancetype)encoderWithStream:(NSOutputStream *)stream andBoundary:(NSString *)boundary; +/** + * Returns a unique boundary string. + */ ++ (NSString *)generateBoundary; +/** + * Designated initializer + * @param stream NSOutputStream associated with the Multipart request + * @param boundary the unique Boundary string to be used + */ +- (instancetype)initWithStream:(NSOutputStream *)stream + andBoundary:(NSString *)boundary NS_DESIGNATED_INITIALIZER; +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; +/** + * Encodes this block within the boundary on the output stream + */ +- (void)encode:(void (^)(void))block; +/** + * Adds the contents of the file data with given Mime type anf fileName within the boundary in + * stream + */ +- (void)addFileData:(NSData *)data + fileName:(NSString *)fileName + mimeType:(NSString *)mimeType + fieldName:(NSString *)name; +/** + * Convenience method for the method above. Converts fileURL to data and calls the above method. + */ +- (void)addFile:(NSURL *)fileURL + fileName:(NSString *)fileName + mimeType:(NSString *)mimeType + fieldName:(NSString *)name; +/** + * Adds this field and value in the stream + */ +- (void)addValue:(id)value fieldName:(NSString *)name; +/** + * String referring to the multipart MIME type with boundary + */ +@property(nonatomic, copy, readonly) NSString *contentTypeHTTPHeaderValue; +/** + * Length of the data written to stream + */ +@property(nonatomic, copy, readonly) NSString *contentLengthHTTPHeaderValue; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSMultipartMimeStreamEncoder.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSMultipartMimeStreamEncoder.m new file mode 100644 index 000000000..134b1cefb --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSMultipartMimeStreamEncoder.m @@ -0,0 +1,208 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSMultipartMimeStreamEncoder.h" + +#import "FIRCLSByteUtility.h" +#import "FIRCLSLogger.h" +#import "FIRCLSUUID.h" + +@interface FIRCLSMultipartMimeStreamEncoder () <NSStreamDelegate> + +@property(nonatomic) NSUInteger length; +@property(nonatomic, copy) NSString *boundary; +@property(nonatomic, copy, readonly) NSData *headerData; +@property(nonatomic, copy, readonly) NSData *footerData; +@property(nonatomic, strong) NSOutputStream *outputStream; + +@end + +@implementation FIRCLSMultipartMimeStreamEncoder + ++ (void)populateRequest:(NSMutableURLRequest *)request + withDataFromEncoder:(void (^)(FIRCLSMultipartMimeStreamEncoder *encoder))block { + NSString *boundary = [self generateBoundary]; + + NSOutputStream *stream = [NSOutputStream outputStreamToMemory]; + + FIRCLSMultipartMimeStreamEncoder *encoder = + [[FIRCLSMultipartMimeStreamEncoder alloc] initWithStream:stream andBoundary:boundary]; + + [encoder encode:^{ + block(encoder); + }]; + + [request setValue:encoder.contentTypeHTTPHeaderValue forHTTPHeaderField:@"Content-Type"]; + [request setValue:encoder.contentLengthHTTPHeaderValue forHTTPHeaderField:@"Content-Length"]; + + NSData *data = [stream propertyForKey:NSStreamDataWrittenToMemoryStreamKey]; + request.HTTPBody = data; +} + ++ (NSString *)contentTypeHTTPHeaderValueWithBoundary:(NSString *)boundary { + return [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary]; +} + ++ (instancetype)encoderWithStream:(NSOutputStream *)stream andBoundary:(NSString *)boundary { + return [[self alloc] initWithStream:stream andBoundary:boundary]; +} + ++ (NSString *)generateBoundary { + return FIRCLSGenerateUUID(); +} + +- (instancetype)initWithStream:(NSOutputStream *)stream andBoundary:(NSString *)boundary { + self = [super init]; + if (!self) { + return nil; + } + + self.outputStream = stream; + + if (!boundary) { + boundary = [FIRCLSMultipartMimeStreamEncoder generateBoundary]; + } + + _boundary = boundary; + + return self; +} + +- (void)encode:(void (^)(void))block { + [self beginEncoding]; + + block(); + + [self endEncoding]; +} + +- (NSString *)contentTypeHTTPHeaderValue { + return [[self class] contentTypeHTTPHeaderValueWithBoundary:self.boundary]; +} + +- (NSString *)contentLengthHTTPHeaderValue { + return [NSString stringWithFormat:@"%lu", (unsigned long)_length]; +} + +#pragma - mark MIME part API +- (void)beginEncoding { + _length = 0; + + [self.outputStream open]; + + [self writeData:self.headerData]; +} + +- (void)endEncoding { + [self writeData:self.footerData]; + + [self.outputStream close]; +} + +- (NSData *)headerData { + return [@"MIME-Version: 1.0\r\n" dataUsingEncoding:NSUTF8StringEncoding]; +} + +- (NSData *)footerData { + return [[NSString stringWithFormat:@"--%@--\r\n", self.boundary] + dataUsingEncoding:NSUTF8StringEncoding]; +} + +- (void)addFileData:(NSData *)data + fileName:(NSString *)fileName + mimeType:(NSString *)mimeType + fieldName:(NSString *)name { + if ([data length] == 0) { + FIRCLSErrorLog(@"Unable to MIME encode data with zero length (%@)", name); + return; + } + + if ([name length] == 0 || [fileName length] == 0) { + FIRCLSErrorLog(@"name (%@) or fieldname (%@) is invalid", name, fileName); + return; + } + + NSMutableString *string; + + string = [NSMutableString + stringWithFormat:@"--%@\r\nContent-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", + self.boundary, name, fileName]; + + if (mimeType) { + [string appendFormat:@"Content-Type: %@\r\n", mimeType]; + [string appendString:@"Content-Transfer-Encoding: binary\r\n\r\n"]; + } else { + [string appendString:@"Content-Type: application/octet-stream\r\n\r\n"]; + } + + [self writeData:[string dataUsingEncoding:NSUTF8StringEncoding]]; + + [self writeData:data]; + + [self writeData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; +} + +- (void)addValue:(id)value fieldName:(NSString *)name { + if ([name length] == 0 || !value || value == NSNull.null) { + FIRCLSErrorLog(@"name (%@) or value (%@) is invalid", name, value); + return; + } + + NSMutableString *string; + + string = + [NSMutableString stringWithFormat:@"--%@\r\nContent-Disposition: form-data; name=\"%@\"\r\n", + self.boundary, name]; + [string appendString:@"Content-Type: text/plain\r\n\r\n"]; + [string appendFormat:@"%@\r\n", value]; + + [self writeData:[string dataUsingEncoding:NSUTF8StringEncoding]]; +} + +- (void)addFile:(NSURL *)fileURL + fileName:(NSString *)fileName + mimeType:(NSString *)mimeType + fieldName:(NSString *)name { + NSData *data = [NSData dataWithContentsOfURL:fileURL]; + + [self addFileData:data fileName:fileName mimeType:mimeType fieldName:name]; +} + +- (BOOL)writeBytes:(const void *)bytes ofLength:(NSUInteger)length { + if ([self.outputStream write:bytes maxLength:length] != length) { + FIRCLSErrorLog(@"Failed to write bytes to stream"); + return NO; + } + + _length += length; + + return YES; +} + +- (void)writeData:(NSData *)data { + FIRCLSEnumerateByteRangesOfNSDataUsingBlock( + data, ^(const void *bytes, NSRange byteRange, BOOL *stop) { + NSUInteger length = byteRange.length; + + if ([self.outputStream write:bytes maxLength:length] != length) { + FIRCLSErrorLog(@"Failed to write data to stream"); + *stop = YES; + return; + } + + self->_length += length; + }); +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSNetworkResponseHandler.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSNetworkResponseHandler.h new file mode 100644 index 000000000..42f0bb493 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSNetworkResponseHandler.h @@ -0,0 +1,87 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +/** + * Type to indicate response status + */ +typedef NS_ENUM(NSInteger, FIRCLSNetworkClientResponseType) { + FIRCLSNetworkClientResponseSuccess, + FIRCLSNetworkClientResponseInvalid, + FIRCLSNetworkClientResponseFailure, + FIRCLSNetworkClientResponseRetry, + FIRCLSNetworkClientResponseBackOff +}; + +typedef NS_ENUM(NSInteger, FIRCLSNetworkErrorType) { + FIRCLSNetworkErrorUnknown = -1, + FIRCLSNetworkErrorFailedToStartOperation = -3, + FIRCLSNetworkErrorResponseInvalid = -4, + FIRCLSNetworkErrorRequestFailed = -5, + FIRCLSNetworkErrorMaximumAttemptsReached = -6, +}; + +extern NSInteger const FIRCLSNetworkErrorUnknownURLCancelReason; + +/** + * This block is an input parameter to handleCompletedResponse: and handleCompletedTask: methods of + * this class. + * @param retryMightSucceed is YES if the request should be retried. + * @param error is the error received back in response. + */ +typedef void (^FIRCLSNetworkResponseCompletionHandlerBlock)(BOOL retryMightSucceed, NSError *error); + +/** + * Error domain for Crashlytics network errors + */ +extern NSString *const FIRCLSNetworkErrorDomain; +/** + * This class handles network responses. + */ +@interface FIRCLSNetworkResponseHandler : NSObject +/** + * Returns the header in the given NSURLResponse with name as key + */ ++ (NSString *)headerForResponse:(NSURLResponse *)response withKey:(NSString *)key; +/** + * Returns Retry-After header value in response, and if absent returns a default retry value + */ ++ (NSTimeInterval)retryValueForResponse:(NSURLResponse *)response; +/** + * Checks if the content type for response matches the request + */ ++ (BOOL)contentTypeForResponse:(NSURLResponse *)response matchesRequest:(NSURLRequest *)request; + ++ (NSInteger)cancelReasonFromURLError:(NSError *)error; + ++ (BOOL)retryableURLError:(NSError *)error; + +/** + * Convenience method that calls back the input block with FIRCLSNetworkClientResponseType after + * checking the response code in response + */ ++ (void)clientResponseType:(NSURLResponse *)response + handler:(void (^)(FIRCLSNetworkClientResponseType type, + NSInteger statusCode))responseTypeAndStatusCodeHandlerBlock; +/** + * Handles a completed response for request and calls back input block. Populates error even if + * error was nil, but response code indicated an error. + */ ++ (void)handleCompletedResponse:(NSURLResponse *)response + forOriginalRequest:(NSURLRequest *)originalRequest + error:(NSError *)error + block:(FIRCLSNetworkResponseCompletionHandlerBlock)completionHandlerBlock; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSNetworkResponseHandler.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSNetworkResponseHandler.m new file mode 100644 index 000000000..d82cdf69a --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSNetworkResponseHandler.m @@ -0,0 +1,290 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSNetworkResponseHandler.h" + +@implementation FIRCLSNetworkResponseHandler + +static const NSTimeInterval kFIRCLSNetworkResponseHandlerDefaultRetryInterval = 2.0; +static NSString *const kFIRCLSNetworkResponseHandlerContentType = @"Content-Type"; +NSString *const FIRCLSNetworkErrorDomain = @"FIRCLSNetworkError"; + +NSInteger const FIRCLSNetworkErrorUnknownURLCancelReason = -1; + +#pragma mark - Header Handling ++ (NSString *)headerForResponse:(NSURLResponse *)response withKey:(NSString *)key { + if (![response respondsToSelector:@selector(allHeaderFields)]) { + return nil; + } + + return [((NSHTTPURLResponse *)response).allHeaderFields objectForKey:key]; +} + ++ (NSTimeInterval)retryValueForResponse:(NSURLResponse *)response { + NSString *retryValueString = [self headerForResponse:response withKey:@"Retry-After"]; + if (!retryValueString) { + return kFIRCLSNetworkResponseHandlerDefaultRetryInterval; + } + + NSTimeInterval value = retryValueString.doubleValue; + if (value < 0.0) { + return kFIRCLSNetworkResponseHandlerDefaultRetryInterval; + } + + return value; +} + ++ (NSString *)requestIdForResponse:(NSURLResponse *)response { + return [self headerForResponse:response withKey:@"X-Request-Id"]; +} + ++ (BOOL)contentTypeForResponse:(NSURLResponse *)response matchesRequest:(NSURLRequest *)request { + NSString *accept = [request.allHTTPHeaderFields objectForKey:@"Accept"]; + if (!accept) { + // An omitted accept header is defined to match everything + return YES; + } + + NSString *contentHeader = [self.class headerForResponse:response + withKey:kFIRCLSNetworkResponseHandlerContentType]; + if (!contentHeader) { + // FIRCLSDeveloperLog("Network", @"Content-Type not present in response"); + return NO; + } + + NSString *acceptCharset = request.allHTTPHeaderFields[@"Accept-Charset"]; + + NSArray *parts = [contentHeader componentsSeparatedByString:@"; charset="]; + if (!parts) { + parts = @[ contentHeader ]; + } + + if ([[parts objectAtIndex:0] caseInsensitiveCompare:accept] != NSOrderedSame) { + // FIRCLSDeveloperLog("Network", @"Content-Type does not match Accept"); + return NO; + } + + if (!acceptCharset) { + return YES; + } + + if (parts.count < 2) { + return YES; + } + + return [[parts objectAtIndex:1] caseInsensitiveCompare:acceptCharset] == NSOrderedSame; +} + ++ (NSInteger)cancelReasonFromURLError:(NSError *)error { + if (![[error domain] isEqualToString:NSURLErrorDomain]) { + return FIRCLSNetworkErrorUnknownURLCancelReason; + } + + if ([error code] != NSURLErrorCancelled) { + return FIRCLSNetworkErrorUnknownURLCancelReason; + } + + NSNumber *reason = [[error userInfo] objectForKey:NSURLErrorBackgroundTaskCancelledReasonKey]; + if (reason == nil) { + return FIRCLSNetworkErrorUnknownURLCancelReason; + } + + return [reason integerValue]; +} + ++ (BOOL)retryableURLError:(NSError *)error { + // So far, the only task errors seen are NSURLErrorDomain. For others, we're not + // sure what to do. + if (![[error domain] isEqualToString:NSURLErrorDomain]) { + return NO; + } + + // cases that we know are definitely not retryable + switch ([error code]) { + case NSURLErrorBadURL: + case NSURLErrorUnsupportedURL: + case NSURLErrorHTTPTooManyRedirects: + case NSURLErrorRedirectToNonExistentLocation: + case NSURLErrorUserCancelledAuthentication: + case NSURLErrorUserAuthenticationRequired: + case NSURLErrorAppTransportSecurityRequiresSecureConnection: + case NSURLErrorFileDoesNotExist: + case NSURLErrorFileIsDirectory: + case NSURLErrorDataLengthExceedsMaximum: + case NSURLErrorSecureConnectionFailed: + case NSURLErrorServerCertificateHasBadDate: + case NSURLErrorServerCertificateUntrusted: + case NSURLErrorServerCertificateHasUnknownRoot: + case NSURLErrorServerCertificateNotYetValid: + case NSURLErrorClientCertificateRejected: + case NSURLErrorClientCertificateRequired: + case NSURLErrorBackgroundSessionRequiresSharedContainer: + return NO; + } + + // All other errors, as far as I can tell, are things that could clear up + // without action on the part of the client. + + // NSURLErrorCancelled is a potential special-case. I believe there are + // situations where a cancelled request cannot be successfully restarted. But, + // until I can prove it, we'll retry. There are defnitely many cases where + // a cancelled request definitely can be restarted and will work. + + return YES; +} + +#pragma mark - Error Creation ++ (NSError *)errorForCode:(NSInteger)code userInfo:(NSDictionary *)userInfo { + return [NSError errorWithDomain:FIRCLSNetworkErrorDomain code:code userInfo:userInfo]; +} + ++ (NSError *)errorForResponse:(NSURLResponse *)response + ofType:(FIRCLSNetworkClientResponseType)type + status:(NSInteger)status { + if (type == FIRCLSNetworkClientResponseSuccess) { + return nil; + } + + NSString *requestId = [self requestIdForResponse:response]; + NSString *contentType = [self headerForResponse:response + withKey:kFIRCLSNetworkResponseHandlerContentType]; + + // this could be nil, so be careful + requestId = requestId ? requestId : @""; + contentType = contentType ? contentType : @""; + + NSDictionary *userInfo = @{ + @"type" : @(type), + @"status_code" : @(status), + @"request_id" : requestId, + @"content_type" : contentType + }; + + // compute a reasonable error code type + NSInteger errorCode = FIRCLSNetworkErrorUnknown; + switch (type) { + case FIRCLSNetworkClientResponseFailure: + errorCode = FIRCLSNetworkErrorRequestFailed; + break; + case FIRCLSNetworkClientResponseInvalid: + errorCode = FIRCLSNetworkErrorResponseInvalid; + break; + default: + break; + } + + return [self errorForCode:errorCode userInfo:userInfo]; +} + ++ (void)clientResponseType:(NSURLResponse *)response + handler:(void (^)(FIRCLSNetworkClientResponseType type, + NSInteger statusCode))responseTypeAndStatusCodeHandlerBlock { + if (![response respondsToSelector:@selector(statusCode)]) { + responseTypeAndStatusCodeHandlerBlock(FIRCLSNetworkClientResponseInvalid, 0); + return; + } + + NSInteger code = ((NSHTTPURLResponse *)response).statusCode; + + switch (code) { + case 200: + case 201: + case 202: + case 204: + case 304: + responseTypeAndStatusCodeHandlerBlock(FIRCLSNetworkClientResponseSuccess, code); + return; + case 420: + case 429: + responseTypeAndStatusCodeHandlerBlock(FIRCLSNetworkClientResponseBackOff, code); + return; + case 408: + responseTypeAndStatusCodeHandlerBlock(FIRCLSNetworkClientResponseRetry, code); + return; + case 400: + case 401: + case 403: + case 404: + case 406: + case 410: + case 411: + case 413: + case 419: + case 422: + case 431: + responseTypeAndStatusCodeHandlerBlock(FIRCLSNetworkClientResponseFailure, code); + return; + } + + // check for a 5xx + if (code >= 500 && code <= 599) { + responseTypeAndStatusCodeHandlerBlock(FIRCLSNetworkClientResponseRetry, code); + return; + } + + responseTypeAndStatusCodeHandlerBlock(FIRCLSNetworkClientResponseInvalid, code); +} + ++ (void)handleCompletedResponse:(NSURLResponse *)response + forOriginalRequest:(NSURLRequest *)originalRequest + error:(NSError *)originalError + block: + (FIRCLSNetworkResponseCompletionHandlerBlock)completionHandlerBlock { + // if we have an error, we can just continue + if (originalError) { + BOOL retryable = [self retryableURLError:originalError]; + + completionHandlerBlock(retryable, originalError); + return; + } + + [self.class clientResponseType:response + handler:^(FIRCLSNetworkClientResponseType type, NSInteger statusCode) { + NSError *error = nil; + + switch (type) { + case FIRCLSNetworkClientResponseInvalid: + error = [self errorForResponse:response + ofType:type + status:statusCode]; + break; + case FIRCLSNetworkClientResponseBackOff: + case FIRCLSNetworkClientResponseRetry: + error = [self errorForResponse:response + ofType:type + status:statusCode]; + completionHandlerBlock(YES, error); + return; + case FIRCLSNetworkClientResponseFailure: + error = [self errorForResponse:response + ofType:type + status:statusCode]; + break; + case FIRCLSNetworkClientResponseSuccess: + if (![self contentTypeForResponse:response + matchesRequest:originalRequest]) { + error = [self errorForResponse:response + ofType:FIRCLSNetworkClientResponseInvalid + status:statusCode]; + break; + } + + break; + } + + completionHandlerBlock(NO, error); + }]; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSURLBuilder.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSURLBuilder.h new file mode 100644 index 000000000..c8fbaa94a --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSURLBuilder.h @@ -0,0 +1,44 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +/** + * This is a convenience class to ease constructing NSURLs. + */ +@interface FIRCLSURLBuilder : NSObject + +/** + * Convenience method that returns a FIRCLSURLBuilder instance with the input base URL appended to + * it. + */ ++ (instancetype)URLWithBase:(NSString *)base; +/** + * Appends the component to the URL being built by FIRCLSURLBuilder instance + */ +- (void)appendComponent:(NSString *)component; +/** + * Escapes and appends the component to the URL being built by FIRCLSURLBuilder instance + */ +- (void)escapeAndAppendComponent:(NSString *)component; +/** + * Adds a query and value to the URL being built + */ +- (void)appendValue:(id)value forQueryParam:(NSString *)param; +/** + * Returns the built URL + */ +- (NSURL *)URL; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSURLBuilder.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSURLBuilder.m new file mode 100644 index 000000000..e832c8987 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSURLBuilder.m @@ -0,0 +1,103 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSURLBuilder.h" + +#import "FIRCLSLogger.h" + +@interface FIRCLSURLBuilder () + +@property(nonatomic) NSMutableString *URLString; +@property(nonatomic) NSUInteger queryParams; + +- (NSString *)escapeString:(NSString *)string; + +@end + +@implementation FIRCLSURLBuilder + ++ (instancetype)URLWithBase:(NSString *)base { + FIRCLSURLBuilder *url = [[FIRCLSURLBuilder alloc] init]; + + [url appendComponent:base]; + + return url; +} + +- (instancetype)init { + self = [super init]; + if (!self) { + return nil; + } + + _URLString = [[NSMutableString alloc] init]; + _queryParams = 0; + + return self; +} + +- (NSString *)escapeString:(NSString *)string { +#if TARGET_OS_WATCH + // TODO: Question - Why does watchOS use a different encoding from the other platforms and the + // Android SDK? + return + [string stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet + URLPathAllowedCharacterSet]]; +#else + return + [string stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet + .URLQueryAllowedCharacterSet]; +#endif +} + +- (void)appendComponent:(NSString *)component { + if (component.length == 0) { + FIRCLSErrorLog(@"URLBuilder parameter component must not be empty"); + return; + } + + [self.URLString appendString:component]; +} + +- (void)escapeAndAppendComponent:(NSString *)component { + [self appendComponent:[self escapeString:component]]; +} + +- (void)appendValue:(id)value forQueryParam:(NSString *)param { + if (!value) { + return; + } + + if (self.queryParams == 0) { + [self appendComponent:@"?"]; + } else { + [self appendComponent:@"&"]; + } + + self.queryParams += 1; + + [self appendComponent:param]; + [self appendComponent:@"="]; + if ([value isKindOfClass:NSString.class]) { + [self escapeAndAppendComponent:value]; + } else { + [self escapeAndAppendComponent:[value description]]; + } +} + +- (NSURL *)URL { + return [NSURL URLWithString:self.URLString]; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSCompoundOperation.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSCompoundOperation.h new file mode 100644 index 000000000..63b9362a9 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSCompoundOperation.h @@ -0,0 +1,58 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSFABAsyncOperation.h" + +/** + * If the compound operation is sent a @c -[cancel] message while executing, it will attempt to + * cancel all operations on its internal queue, and will return an error in its @c asyncCompletion + * block with this value as its code. + */ +FOUNDATION_EXPORT const NSUInteger FIRCLSCompoundOperationErrorCodeCancelled; + +/** + * If one or more of the operations on the @c compoundQueue fail, this operation returns an error + * in its @c asyncCompletion block with this code, and an array of @c NSErrors keyed on @c + * FIRCLSCompoundOperationErrorUserInfoKeyUnderlyingErrors in the @c userInfo dictionary. + */ +FOUNDATION_EXPORT const NSUInteger FIRCLSCompoundOperationErrorCodeSuboperationFailed; + +/** + * When all the operations complete, this @c FIRCLSCompoundOperation instance's @c asyncCompletion + * block is called. If any errors were passed by the suboperations' @c asyncCompletion blocks, they + * are put in an array which can be accessed in the @c userInfo dictionary in the error parameter + * for this instance's @c asyncCompletion block. + */ +FOUNDATION_EXPORT NSString *const FIRCLSCompoundOperationErrorUserInfoKeyUnderlyingErrors; + +/** + * An operation that executes a collection of suboperations on an internal private queue. Any + * instance of @c FIRCLSFABAsyncOperation passed into this instance's @c operations property has the + * potential to return an @c NSError in its @c asyncCompletion block. This instance's @c + * asyncCompletion block will put all such errors in an @c NSArray and return an @c NSError whose @c + * userInfo contains that array keyed by @c FIRCLSCompoundOperationErrorUserInfoKeyUnderlyingErrors. + */ +@interface FIRCLSCompoundOperation : FIRCLSFABAsyncOperation + +/** + * An array of @c NSOperations to execute, which can include instances of @c FIRCLSFABAsyncOperation + * or + * @c FIRCLSCompoundOperation. This operation will not be marked as finished until all suboperations + * are marked as finished. + */ +@property(copy, nonatomic) NSArray<NSOperation *> *operations; + +@property(strong, nonatomic, readonly) NSOperationQueue *compoundQueue; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSCompoundOperation.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSCompoundOperation.m new file mode 100644 index 000000000..5dcf42885 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSCompoundOperation.m @@ -0,0 +1,165 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSCompoundOperation.h" + +#import "FIRCLSFABAsyncOperation_Private.h" + +#define FIRCLS_DISPATCH_QUEUES_AS_OBJECTS OS_OBJECT_USE_OBJC_RETAIN_RELEASE + +const NSUInteger FIRCLSCompoundOperationErrorCodeCancelled = UINT_MAX - 1; +const NSUInteger FIRCLSCompoundOperationErrorCodeSuboperationFailed = UINT_MAX - 2; + +NSString *const FIRCLSCompoundOperationErrorUserInfoKeyUnderlyingErrors = + @"com.google.firebase.crashlytics.FIRCLSCompoundOperation.error.user-info-key.underlying-" + @"errors"; + +static NSString *const FIRCLSCompoundOperationErrorDomain = + @"com.google.firebase.crashlytics.FIRCLSCompoundOperation.error"; +static char *const FIRCLSCompoundOperationCountingQueueLabel = + "com.google.firebase.crashlytics.FIRCLSCompoundOperation.dispatch-queue.counting-queue"; + +@interface FIRCLSCompoundOperation () + +@property(strong, nonatomic, readwrite) NSOperationQueue *compoundQueue; +@property(assign, nonatomic) NSUInteger completedOperations; +@property(strong, nonatomic) NSMutableArray *errors; +#if FIRCLS_DISPATCH_QUEUES_AS_OBJECTS +@property(strong, nonatomic) dispatch_queue_t countingQueue; +#else +@property(assign, nonatomic) dispatch_queue_t countingQueue; +#endif + +@end + +@implementation FIRCLSCompoundOperation + +- (instancetype)init { + self = [super init]; + if (!self) { + return nil; + } + + _compoundQueue = [[NSOperationQueue alloc] init]; + _completedOperations = 0; + _errors = [NSMutableArray array]; + _countingQueue = + dispatch_queue_create(FIRCLSCompoundOperationCountingQueueLabel, DISPATCH_QUEUE_SERIAL); + + return self; +} + +#if !FIRCLS_DISPATCH_QUEUES_AS_OBJECTS +- (void)dealloc { + if (_countingQueue) { + dispatch_release(_countingQueue); + } +} +#endif + +- (void)main { + for (FIRCLSFABAsyncOperation *operation in self.operations) { + [self injectCompoundAsyncCompletionInOperation:operation]; + [self injectCompoundSyncCompletionInOperation:operation]; + + [self.compoundQueue addOperation:operation]; + } +} + +- (void)cancel { + if (self.compoundQueue.operations.count > 0) { + [self.compoundQueue cancelAllOperations]; + dispatch_sync(self.countingQueue, ^{ + [self attemptCompoundCompletion]; + }); + } else { + for (NSOperation *operation in self.operations) { + [operation cancel]; + } + + // we have to add the operations to the queue in order for their isFinished property to be set + // to true. + [self.compoundQueue addOperations:self.operations waitUntilFinished:NO]; + } + [super cancel]; +} + +- (void)injectCompoundAsyncCompletionInOperation:(FIRCLSFABAsyncOperation *)operation { + __weak FIRCLSCompoundOperation *weakSelf = self; + FIRCLSFABAsyncOperationCompletionBlock originalAsyncCompletion = [operation.asyncCompletion copy]; + FIRCLSFABAsyncOperationCompletionBlock completion = ^(NSError *error) { + __strong FIRCLSCompoundOperation *strongSelf = weakSelf; + + if (originalAsyncCompletion) { + dispatch_sync(strongSelf.countingQueue, ^{ + originalAsyncCompletion(error); + }); + } + + [strongSelf updateCompletionCountsWithError:error]; + }; + operation.asyncCompletion = completion; +} + +- (void)injectCompoundSyncCompletionInOperation:(FIRCLSFABAsyncOperation *)operation { + __weak FIRCLSCompoundOperation *weakSelf = self; + void (^originalSyncCompletion)(void) = [operation.completionBlock copy]; + void (^completion)(void) = ^{ + __strong FIRCLSCompoundOperation *strongSelf = weakSelf; + + if (originalSyncCompletion) { + dispatch_sync(strongSelf.countingQueue, ^{ + originalSyncCompletion(); + }); + } + + dispatch_sync(strongSelf.countingQueue, ^{ + [strongSelf attemptCompoundCompletion]; + }); + }; + operation.completionBlock = completion; +} + +- (void)updateCompletionCountsWithError:(NSError *)error { + dispatch_sync(self.countingQueue, ^{ + if (!error) { + self.completedOperations += 1; + } else { + [self.errors addObject:error]; + } + }); +} + +- (void)attemptCompoundCompletion { + if (self.isCancelled) { + [self finishWithError:[NSError errorWithDomain:FIRCLSCompoundOperationErrorDomain + code:FIRCLSCompoundOperationErrorCodeCancelled + userInfo:@{ + NSLocalizedDescriptionKey : [NSString + stringWithFormat:@"%@ cancelled", self.name] + }]]; + self.asyncCompletion = nil; + } else if (self.completedOperations + self.errors.count == self.operations.count) { + NSError *error = nil; + if (self.errors.count > 0) { + error = [NSError + errorWithDomain:FIRCLSCompoundOperationErrorDomain + code:FIRCLSCompoundOperationErrorCodeSuboperationFailed + userInfo:@{FIRCLSCompoundOperationErrorUserInfoKeyUnderlyingErrors : self.errors}]; + } + [self finishWithError:error]; + } +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation.h new file mode 100644 index 000000000..e5d2c7ef4 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation.h @@ -0,0 +1,39 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +/** + * Completion block that can be called in your subclass implementation. It is up to you when you + * want to call it. + */ +typedef void (^FIRCLSFABAsyncOperationCompletionBlock)(NSError *__nullable error); + +/** + * FIRCLSFABAsyncOperation is a subclass of NSOperation that allows for asynchronous work to be + * performed, for things like networking, IPC or UI-driven logic. Create your own subclasses to + * encapsulate custom logic. + * @warning When subclassing to create your own operations, be sure to call -[finishWithError:] at + * some point, or program execution will hang. + * @see -[finishWithError:] in FIRCLSFABAsyncOperation_Private.h + */ +@interface FIRCLSFABAsyncOperation : NSOperation + +/** + * Add a callback method for consumers of your subclasses to set when the asynchronous work is + * marked as complete with -[finishWithError:]. + */ +@property(copy, nonatomic, nullable) FIRCLSFABAsyncOperationCompletionBlock asyncCompletion; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation.m new file mode 100644 index 000000000..dcad16adf --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation.m @@ -0,0 +1,146 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSFABAsyncOperation.h" + +#import "FIRCLSFABAsyncOperation_Private.h" + +@interface FIRCLSFABAsyncOperation () { + BOOL _internalExecuting; + BOOL _internalFinished; +} + +@property(nonatomic, strong) NSRecursiveLock *lock; + +@end + +@implementation FIRCLSFABAsyncOperation + +- (instancetype)init { + self = [super init]; + if (!self) { + return nil; + } + + _internalExecuting = NO; + _internalFinished = NO; + + _lock = [[NSRecursiveLock alloc] init]; + _lock.name = [NSString stringWithFormat:@"com.google.firebase.crashlytics.%@-lock", [self class]]; + ; + + return self; +} + +#pragma mark - NSOperation Overrides +- (BOOL)isConcurrent { + return YES; +} + +- (BOOL)isAsynchronous { + return YES; +} + +- (BOOL)isExecuting { + [self.lock lock]; + BOOL result = _internalExecuting; + [self.lock unlock]; + + return result; +} + +- (BOOL)isFinished { + [self.lock lock]; + BOOL result = _internalFinished; + [self.lock unlock]; + + return result; +} + +- (void)start { + if ([self checkForCancellation]) { + return; + } + + [self markStarted]; + + [self main]; +} + +#pragma mark - Utilities +- (void)changeValueForKey:(NSString *)key inBlock:(void (^)(void))block { + [self willChangeValueForKey:key]; + block(); + [self didChangeValueForKey:key]; +} + +- (void)lock:(void (^)(void))block { + [self.lock lock]; + block(); + [self.lock unlock]; +} + +- (BOOL)checkForCancellation { + if ([self isCancelled]) { + [self markDone]; + return YES; + } + + return NO; +} + +#pragma mark - State Management +- (void)unlockedMarkFinished { + [self changeValueForKey:@"isFinished" + inBlock:^{ + self->_internalFinished = YES; + }]; +} + +- (void)unlockedMarkStarted { + [self changeValueForKey:@"isExecuting" + inBlock:^{ + self->_internalExecuting = YES; + }]; +} + +- (void)unlockedMarkComplete { + [self changeValueForKey:@"isExecuting" + inBlock:^{ + self->_internalExecuting = NO; + }]; +} + +- (void)markStarted { + [self lock:^{ + [self unlockedMarkStarted]; + }]; +} + +- (void)markDone { + [self lock:^{ + [self unlockedMarkComplete]; + [self unlockedMarkFinished]; + }]; +} + +#pragma mark - Protected +- (void)finishWithError:(NSError *)error { + if (self.asyncCompletion) { + self.asyncCompletion(error); + } + [self markDone]; +} + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation_Private.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation_Private.h new file mode 100644 index 000000000..d1e5797b3 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation_Private.h @@ -0,0 +1,32 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSFABAsyncOperation.h" + +@interface FIRCLSFABAsyncOperation (Private) + +/** + * Subclasses must call this method when they are done performing work. When it is called is up to + * you; it can be directly after kicking of a network request, say, or in the callback for its + * response. Once this method is called, the operation queue it is on will begin executing the next + * waiting operation. If you directly invoked -[start] on the instance, execution will proceed to + * the next code statement. + * @note as soon as this method is called, @c NSOperation's standard @c completionBlock will be + * executed if one exists, as a result of setting the operation's isFinished property to YES, and + * the asyncCompletion block is called. + * @param error Any error to pass to asyncCompletion, or nil if there is none. + */ +- (void)finishWithError:(NSError *__nullable)error; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSOperation.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSOperation.h new file mode 100644 index 000000000..83fc69473 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSOperation.h @@ -0,0 +1,19 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +#import "FIRCLSCompoundOperation.h" +#import "FIRCLSFABAsyncOperation.h" +#import "FIRCLSFABAsyncOperation_Private.h" diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSUUID.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSUUID.h new file mode 100644 index 000000000..dc3aedae2 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSUUID.h @@ -0,0 +1,27 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> +#import "FIRCLSConstants.h" + +/** + * Generates and returns a UUID + * This is also used by used by Answers to generate UUIDs. + */ +NSString *FIRCLSGenerateUUID(void); + +/** + * Converts the input uint8_t UUID to NSString + */ +NSString *FIRCLSUUIDToNSString(const uint8_t *uuid); diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSUUID.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSUUID.m new file mode 100644 index 000000000..6534d417f --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSUUID.m @@ -0,0 +1,39 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FIRCLSUUID.h" + +#import "FIRCLSByteUtility.h" + +static NSInteger const FIRCLSUUIDStringLength = 33; + +#pragma mark Public methods + +NSString *FIRCLSGenerateUUID(void) { + NSString *string; + + CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault); + string = CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, uuid)); + CFRelease(uuid); + + return string; +} + +NSString *FIRCLSUUIDToNSString(const uint8_t *uuid) { + char uuidString[FIRCLSUUIDStringLength]; + + FIRCLSSafeHexToString(uuid, 16, uuidString); + + return [NSString stringWithUTF8String:uuidString]; +} diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/third_party/libunwind/dwarf.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/third_party/libunwind/dwarf.h new file mode 100644 index 000000000..9c81868a0 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/third_party/libunwind/dwarf.h @@ -0,0 +1,256 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang <davidm@hpl.hp.com> + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#pragma once + +// +#define DWARF_EXTENDED_LENGTH_FLAG (0xffffffff) +#define DWARF_CIE_ID_CIE_FLAG (0) + +// Exception Handling Pointer Encoding constants +#define DW_EH_PE_VALUE_MASK (0x0F) +#define DW_EH_PE_RELATIVE_OFFSET_MASK (0x70) + +// Register Definitions +#define DW_EN_MAX_REGISTER_NUMBER (120) + +enum { + DW_EH_PE_ptr = 0x00, + DW_EH_PE_uleb128 = 0x01, + DW_EH_PE_udata2 = 0x02, + DW_EH_PE_udata4 = 0x03, + DW_EH_PE_udata8 = 0x04, + DW_EH_PE_signed = 0x08, + DW_EH_PE_sleb128 = 0x09, + DW_EH_PE_sdata2 = 0x0A, + DW_EH_PE_sdata4 = 0x0B, + DW_EH_PE_sdata8 = 0x0C, + + DW_EH_PE_absptr = 0x00, + DW_EH_PE_pcrel = 0x10, + DW_EH_PE_textrel = 0x20, + DW_EH_PE_datarel = 0x30, + DW_EH_PE_funcrel = 0x40, + DW_EH_PE_aligned = 0x50, + DW_EH_PE_indirect = 0x80, + DW_EH_PE_omit = 0xFF +}; + +// Unwind Instructions + +#define DW_CFA_OPCODE_MASK (0xC0) +#define DW_CFA_OPERAND_MASK (0x3F) + +enum { + DW_CFA_nop = 0x0, + DW_CFA_set_loc = 0x1, + DW_CFA_advance_loc1 = 0x2, + DW_CFA_advance_loc2 = 0x3, + DW_CFA_advance_loc4 = 0x4, + DW_CFA_offset_extended = 0x5, + DW_CFA_restore_extended = 0x6, + DW_CFA_undefined = 0x7, + DW_CFA_same_value = 0x8, + DW_CFA_register = 0x9, + DW_CFA_remember_state = 0xA, + DW_CFA_restore_state = 0xB, + DW_CFA_def_cfa = 0xC, + DW_CFA_def_cfa_register = 0xD, + DW_CFA_def_cfa_offset = 0xE, + DW_CFA_def_cfa_expression = 0xF, + DW_CFA_expression = 0x10, + DW_CFA_offset_extended_sf = 0x11, + DW_CFA_def_cfa_sf = 0x12, + DW_CFA_def_cfa_offset_sf = 0x13, + DW_CFA_val_offset = 0x14, + DW_CFA_val_offset_sf = 0x15, + DW_CFA_val_expression = 0x16, + + // opcode is in high 2 bits, operand in is lower 6 bits + DW_CFA_advance_loc = 0x40, // operand is delta + DW_CFA_offset = 0x80, // operand is register + DW_CFA_restore = 0xC0, // operand is register + + // GNU extensions + DW_CFA_GNU_window_save = 0x2D, + DW_CFA_GNU_args_size = 0x2E, + DW_CFA_GNU_negative_offset_extended = 0x2F +}; + +// Expression Instructions +enum { + DW_OP_addr = 0x03, + DW_OP_deref = 0x06, + DW_OP_const1u = 0x08, + DW_OP_const1s = 0x09, + DW_OP_const2u = 0x0A, + DW_OP_const2s = 0x0B, + DW_OP_const4u = 0x0C, + DW_OP_const4s = 0x0D, + DW_OP_const8u = 0x0E, + DW_OP_const8s = 0x0F, + DW_OP_constu = 0x10, + DW_OP_consts = 0x11, + DW_OP_dup = 0x12, + DW_OP_drop = 0x13, + DW_OP_over = 0x14, + DW_OP_pick = 0x15, + DW_OP_swap = 0x16, + DW_OP_rot = 0x17, + DW_OP_xderef = 0x18, + DW_OP_abs = 0x19, + DW_OP_and = 0x1A, + DW_OP_div = 0x1B, + DW_OP_minus = 0x1C, + DW_OP_mod = 0x1D, + DW_OP_mul = 0x1E, + DW_OP_neg = 0x1F, + DW_OP_not = 0x20, + DW_OP_or = 0x21, + DW_OP_plus = 0x22, + DW_OP_plus_uconst = 0x23, + DW_OP_shl = 0x24, + DW_OP_shr = 0x25, + DW_OP_shra = 0x26, + DW_OP_xor = 0x27, + DW_OP_skip = 0x2F, + DW_OP_bra = 0x28, + DW_OP_eq = 0x29, + DW_OP_ge = 0x2A, + DW_OP_gt = 0x2B, + DW_OP_le = 0x2C, + DW_OP_lt = 0x2D, + DW_OP_ne = 0x2E, + DW_OP_lit0 = 0x30, + DW_OP_lit1 = 0x31, + DW_OP_lit2 = 0x32, + DW_OP_lit3 = 0x33, + DW_OP_lit4 = 0x34, + DW_OP_lit5 = 0x35, + DW_OP_lit6 = 0x36, + DW_OP_lit7 = 0x37, + DW_OP_lit8 = 0x38, + DW_OP_lit9 = 0x39, + DW_OP_lit10 = 0x3A, + DW_OP_lit11 = 0x3B, + DW_OP_lit12 = 0x3C, + DW_OP_lit13 = 0x3D, + DW_OP_lit14 = 0x3E, + DW_OP_lit15 = 0x3F, + DW_OP_lit16 = 0x40, + DW_OP_lit17 = 0x41, + DW_OP_lit18 = 0x42, + DW_OP_lit19 = 0x43, + DW_OP_lit20 = 0x44, + DW_OP_lit21 = 0x45, + DW_OP_lit22 = 0x46, + DW_OP_lit23 = 0x47, + DW_OP_lit24 = 0x48, + DW_OP_lit25 = 0x49, + DW_OP_lit26 = 0x4A, + DW_OP_lit27 = 0x4B, + DW_OP_lit28 = 0x4C, + DW_OP_lit29 = 0x4D, + DW_OP_lit30 = 0x4E, + DW_OP_lit31 = 0x4F, + DW_OP_reg0 = 0x50, + DW_OP_reg1 = 0x51, + DW_OP_reg2 = 0x52, + DW_OP_reg3 = 0x53, + DW_OP_reg4 = 0x54, + DW_OP_reg5 = 0x55, + DW_OP_reg6 = 0x56, + DW_OP_reg7 = 0x57, + DW_OP_reg8 = 0x58, + DW_OP_reg9 = 0x59, + DW_OP_reg10 = 0x5A, + DW_OP_reg11 = 0x5B, + DW_OP_reg12 = 0x5C, + DW_OP_reg13 = 0x5D, + DW_OP_reg14 = 0x5E, + DW_OP_reg15 = 0x5F, + DW_OP_reg16 = 0x60, + DW_OP_reg17 = 0x61, + DW_OP_reg18 = 0x62, + DW_OP_reg19 = 0x63, + DW_OP_reg20 = 0x64, + DW_OP_reg21 = 0x65, + DW_OP_reg22 = 0x66, + DW_OP_reg23 = 0x67, + DW_OP_reg24 = 0x68, + DW_OP_reg25 = 0x69, + DW_OP_reg26 = 0x6A, + DW_OP_reg27 = 0x6B, + DW_OP_reg28 = 0x6C, + DW_OP_reg29 = 0x6D, + DW_OP_reg30 = 0x6E, + DW_OP_reg31 = 0x6F, + DW_OP_breg0 = 0x70, + DW_OP_breg1 = 0x71, + DW_OP_breg2 = 0x72, + DW_OP_breg3 = 0x73, + DW_OP_breg4 = 0x74, + DW_OP_breg5 = 0x75, + DW_OP_breg6 = 0x76, + DW_OP_breg7 = 0x77, + DW_OP_breg8 = 0x78, + DW_OP_breg9 = 0x79, + DW_OP_breg10 = 0x7A, + DW_OP_breg11 = 0x7B, + DW_OP_breg12 = 0x7C, + DW_OP_breg13 = 0x7D, + DW_OP_breg14 = 0x7E, + DW_OP_breg15 = 0x7F, + DW_OP_breg16 = 0x80, + DW_OP_breg17 = 0x81, + DW_OP_breg18 = 0x82, + DW_OP_breg19 = 0x83, + DW_OP_breg20 = 0x84, + DW_OP_breg21 = 0x85, + DW_OP_breg22 = 0x86, + DW_OP_breg23 = 0x87, + DW_OP_breg24 = 0x88, + DW_OP_breg25 = 0x89, + DW_OP_breg26 = 0x8A, + DW_OP_breg27 = 0x8B, + DW_OP_breg28 = 0x8C, + DW_OP_breg29 = 0x8D, + DW_OP_breg30 = 0x8E, + DW_OP_breg31 = 0x8F, + DW_OP_regx = 0x90, + DW_OP_fbreg = 0x91, + DW_OP_bregx = 0x92, + DW_OP_piece = 0x93, + DW_OP_deref_size = 0x94, + DW_OP_xderef_size = 0x95, + DW_OP_nop = 0x96, + DW_OP_push_object_addres = 0x97, + DW_OP_call2 = 0x98, + DW_OP_call4 = 0x99, + DW_OP_call_ref = 0x9A, + DW_OP_lo_user = 0xE0, + DW_OP_APPLE_uninit = 0xF0, + DW_OP_hi_user = 0xFF +}; diff --git a/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRAppInternal.h b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRAppInternal.h new file mode 100644 index 000000000..9a0c943db --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRAppInternal.h @@ -0,0 +1,173 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIRApp.h" +#else +#import <FirebaseCore/FIRApp.h> +#endif + +// The has_include is a workaround so the old IID needed for the FIS tests can find FIRErrors.h +#if __has_include("FirebaseCore/Sources/Private/FIRErrors.h") +#import "FirebaseCore/Sources/Private/FIRErrors.h" +#else +#import <FirebaseCore/FIRErrors.h> +#endif + +@class FIRComponentContainer; +@protocol FIRLibrary; + +/** + * The internal interface to FIRApp. This is meant for first-party integrators, who need to receive + * FIRApp notifications, log info about the success or failure of their configuration, and access + * other internal functionality of FIRApp. + * + * TODO(b/28296561): Restructure this header. + */ +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, FIRConfigType) { + FIRConfigTypeCore = 1, + FIRConfigTypeSDK = 2, +}; + +extern NSString *const kFIRDefaultAppName; +extern NSString *const kFIRAppReadyToConfigureSDKNotification; +extern NSString *const kFIRAppDeleteNotification; +extern NSString *const kFIRAppIsDefaultAppKey; +extern NSString *const kFIRAppNameKey; +extern NSString *const kFIRGoogleAppIDKey; + +/** + * The format string for the User Defaults key used for storing the data collection enabled flag. + * This includes formatting to append the Firebase App's name. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat; + +/** + * The plist key used for storing the data collection enabled flag. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey; + +/** + * A notification fired containing diagnostic information when SDK errors occur. + */ +extern NSString *const kFIRAppDiagnosticsNotification; + +/** @var FIRAuthStateDidChangeInternalNotification + @brief The name of the @c NSNotificationCenter notification which is posted when the auth state + changes (e.g. a new token has been produced, a user logs in or out). The object parameter of + the notification is a dictionary possibly containing the key: + @c FIRAuthStateDidChangeInternalNotificationTokenKey (the new access token.) If it does not + contain this key it indicates a sign-out event took place. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotification; + +/** @var FIRAuthStateDidChangeInternalNotificationTokenKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new access token. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey; + +/** @var FIRAuthStateDidChangeInternalNotificationAppKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the FIRApp associated with the auth instance. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationAppKey; + +/** @var FIRAuthStateDidChangeInternalNotificationUIDKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new user's UID (or nil if there is no longer a user signed in). + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey; + +@interface FIRApp () + +/** + * A flag indicating if this is the default app (has the default app name). + */ +@property(nonatomic, readonly) BOOL isDefaultApp; + +/* + * The container of interop SDKs for this app. + */ +@property(nonatomic) FIRComponentContainer *container; + +/** + * Creates an error for failing to configure a subspec service. This method is called by each + * FIRApp notification listener. + */ ++ (NSError *)errorForSubspecConfigurationFailureWithDomain:(NSString *)domain + errorCode:(FIRErrorCode)code + service:(NSString *)service + reason:(NSString *)reason; +/** + * Checks if the default app is configured without trying to configure it. + */ ++ (BOOL)isDefaultAppConfigured; + +/** + * Registers a given third-party library with the given version number to be reported for + * analytics. + * + * @param name Name of the library. + * @param version Version of the library. + */ ++ (void)registerLibrary:(nonnull NSString *)name withVersion:(nonnull NSString *)version; + +/** + * Registers a given internal library with the given version number to be reported for + * analytics. + * + * @param library Optional parameter for component registration. + * @param name Name of the library. + * @param version Version of the library. + */ ++ (void)registerInternalLibrary:(nonnull Class<FIRLibrary>)library + withName:(nonnull NSString *)name + withVersion:(nonnull NSString *)version; + +/** + * A concatenated string representing all the third-party libraries and version numbers. + */ ++ (NSString *)firebaseUserAgent; + +/** + * Used by each SDK to send logs about SDK configuration status to Clearcut. + * + * @note This API is a no-op, please remove calls to it. + */ +- (void)sendLogsWithServiceName:(NSString *)serviceName + version:(NSString *)version + error:(NSError *)error; + +/** + * Can be used by the unit tests in eack SDK to reset FIRApp. This method is thread unsafe. + */ ++ (void)resetApps; + +/** + * Can be used by the unit tests in each SDK to set customized options. + */ +- (instancetype)initInstanceWithName:(NSString *)name options:(FIROptions *)options; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRComponent.h b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRComponent.h new file mode 100644 index 000000000..cb51ee70e --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRComponent.h @@ -0,0 +1,91 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +@class FIRApp; +@class FIRComponentContainer; + +NS_ASSUME_NONNULL_BEGIN + +/// Provides a system to clean up cached instances returned from the component system. +NS_SWIFT_NAME(ComponentLifecycleMaintainer) +@protocol FIRComponentLifecycleMaintainer +/// The associated app will be deleted, clean up any resources as they are about to be deallocated. +- (void)appWillBeDeleted:(FIRApp *)app; +@end + +typedef _Nullable id (^FIRComponentCreationBlock)(FIRComponentContainer *container, + BOOL *isCacheable) + NS_SWIFT_NAME(ComponentCreationBlock); + +@class FIRDependency; + +/// Describes the timing of instantiation. Note: new components should default to lazy unless there +/// is a strong reason to be eager. +typedef NS_ENUM(NSInteger, FIRInstantiationTiming) { + FIRInstantiationTimingLazy, + FIRInstantiationTimingAlwaysEager, + FIRInstantiationTimingEagerInDefaultApp +} NS_SWIFT_NAME(InstantiationTiming); + +/// A component that can be used from other Firebase SDKs. +NS_SWIFT_NAME(Component) +@interface FIRComponent : NSObject + +/// The protocol describing functionality provided from the Component. +@property(nonatomic, strong, readonly) Protocol *protocol; + +/// The timing of instantiation. +@property(nonatomic, readonly) FIRInstantiationTiming instantiationTiming; + +/// An array of dependencies for the component. +@property(nonatomic, copy, readonly) NSArray<FIRDependency *> *dependencies; + +/// A block to instantiate an instance of the component with the appropriate dependencies. +@property(nonatomic, copy, readonly) FIRComponentCreationBlock creationBlock; + +// There's an issue with long NS_SWIFT_NAMES that causes compilation to fail, disable clang-format +// for the next two methods. +// clang-format off + +/// Creates a component with no dependencies that will be lazily initialized. ++ (instancetype)componentWithProtocol:(Protocol *)protocol + creationBlock:(FIRComponentCreationBlock)creationBlock +NS_SWIFT_NAME(init(_:creationBlock:)); + +/// Creates a component to be registered with the component container. +/// +/// @param protocol - The protocol describing functionality provided by the component. +/// @param instantiationTiming - When the component should be initialized. Use .lazy unless there's +/// a good reason to be instantiated earlier. +/// @param dependencies - Any dependencies the `implementingClass` has, optional or required. +/// @param creationBlock - A block to instantiate the component with a container, and if +/// @return A component that can be registered with the component container. ++ (instancetype)componentWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray<FIRDependency *> *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock +NS_SWIFT_NAME(init(_:instantiationTiming:dependencies:creationBlock:)); + +// clang-format on + +/// Unavailable. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRComponentContainer.h b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRComponentContainer.h new file mode 100644 index 000000000..db2bafef8 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRComponentContainer.h @@ -0,0 +1,50 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import <Foundation/Foundation.h> + +// The has_include is a workaround so the old IID needed for the FIS tests can find the headers. +#if __has_include("FirebaseCore/Sources/Private/FIRComponentType.h") +#import "FirebaseCore/Sources/Private/FIRComponentType.h" +#import "FirebaseCore/Sources/Private/FIRLibrary.h" +#else +#import <FirebaseCore/FIRComponentType.h> +#import <FirebaseCore/FIRLibrary.h> +#endif + +NS_ASSUME_NONNULL_BEGIN + +/// A type-safe macro to retrieve a component from a container. This should be used to retrieve +/// components instead of using the container directly. +#define FIR_COMPONENT(type, container) \ + [FIRComponentType<id<type>> instanceForProtocol:@protocol(type) inContainer:container] + +@class FIRApp; + +/// A container that holds different components that are registered via the +/// `registerAsComponentRegistrant:` call. These classes should conform to `FIRComponentRegistrant` +/// in order to properly register components for Core. +NS_SWIFT_NAME(FirebaseComponentContainer) +@interface FIRComponentContainer : NSObject + +/// A weak reference to the app that an instance of the container belongs to. +@property(nonatomic, weak, readonly) FIRApp *app; + +/// Unavailable. Use the `container` property on `FIRApp`. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRComponentType.h b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRComponentType.h new file mode 100644 index 000000000..6f2aca7b8 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRComponentType.h @@ -0,0 +1,34 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +@class FIRComponentContainer; + +NS_ASSUME_NONNULL_BEGIN + +/// Do not use directly. A placeholder type in order to provide a macro that will warn users of +/// mis-matched protocols. +NS_SWIFT_NAME(ComponentType) +@interface FIRComponentType<__covariant T> : NSObject + +/// Do not use directly. A factory method to retrieve an instance that provides a specific +/// functionality. ++ (T)instanceForProtocol:(Protocol *)protocol inContainer:(FIRComponentContainer *)container; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h new file mode 100644 index 000000000..76c0c05f0 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +@class FIRDiagnosticsData; +@class FIROptions; + +NS_ASSUME_NONNULL_BEGIN + +/** Connects FIRCore with the CoreDiagnostics library. */ +@interface FIRCoreDiagnosticsConnector : NSObject + +/** Logs FirebaseCore related data. + * + * @param options The options object containing data to log. + */ ++ (void)logCoreTelemetryWithOptions:(FIROptions *)options; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRDependency.h b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRDependency.h new file mode 100644 index 000000000..46e9b7ea6 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRDependency.h @@ -0,0 +1,45 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +/// A dependency on a specific protocol's functionality. +NS_SWIFT_NAME(Dependency) +@interface FIRDependency : NSObject + +/// The protocol describing functionality being depended on. +@property(nonatomic, strong, readonly) Protocol *protocol; + +/// A flag to specify if the dependency is required or not. +@property(nonatomic, readonly) BOOL isRequired; + +/// Initializes a dependency that is required. Calls `initWithProtocol:isRequired` with `YES` for +/// the required parameter. +/// Creates a required dependency on the specified protocol's functionality. ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol; + +/// Creates a dependency on the specified protocol's functionality and specify if it's required for +/// the class's functionality. ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol isRequired:(BOOL)required; + +/// Use `dependencyWithProtocol:isRequired:` instead. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRErrorCode.h b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRErrorCode.h new file mode 100644 index 000000000..c90d9eecf --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRErrorCode.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** Error codes in Firebase error domain. */ +typedef NS_ENUM(NSInteger, FIRErrorCode) { + /** + * Unknown error. + */ + FIRErrorCodeUnknown = 0, + /** + * Loading data from the GoogleService-Info.plist file failed. This is a fatal error and should + * not be ignored. Further calls to the API will fail and/or possibly cause crashes. + */ + FIRErrorCodeInvalidPlistFile = -100, + + /** + * Validating the Google App ID format failed. + */ + FIRErrorCodeInvalidAppID = -101, + + /** + * Error code for failing to configure a specific service. It's deprecated, but + * still used after copybara. + */ + FIRErrorCodeConfigFailed = -114, +}; diff --git a/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRErrors.h b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRErrors.h new file mode 100644 index 000000000..19e47328a --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRErrors.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +#include "FIRErrorCode.h" + +extern NSString *const kFirebaseErrorDomain; +extern NSString *const kFirebaseConfigErrorDomain; +extern NSString *const kFirebaseCoreErrorDomain; +extern NSString *const kFirebasePerfErrorDomain; diff --git a/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h new file mode 100644 index 000000000..bfff73e5d --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h @@ -0,0 +1,39 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRHeartbeatInfo : NSObject + +// Enum representing the different heartbeat codes. +typedef NS_ENUM(NSInteger, FIRHeartbeatInfoCode) { + FIRHeartbeatInfoCodeNone = 0, + FIRHeartbeatInfoCodeSDK = 1, + FIRHeartbeatInfoCodeGlobal = 2, + FIRHeartbeatInfoCodeCombined = 3, +}; + +/** + * Get heartbeat code requred for the sdk. + * @param heartbeatTag String representing the sdk heartbeat tag. + * @return Heartbeat code indicating whether or not an sdk/global heartbeat + * needs to be sent + */ ++ (FIRHeartbeatInfoCode)heartbeatCodeForTag:(NSString *)heartbeatTag; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRLibrary.h b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRLibrary.h new file mode 100644 index 000000000..e7a9e077c --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRLibrary.h @@ -0,0 +1,50 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRLibrary_h +#define FIRLibrary_h + +#import <Foundation/Foundation.h> + +// The has_include is a workaround so the old IID needed for the FIS tests can find the headers. +#if __has_include("FirebaseCore/Sources/Private/FIRComponent.h") +#import "FirebaseCore/Sources/Private/FIRComponent.h" +#else +#import <FirebaseCore/FIRComponent.h> +#endif + +@class FIRApp; + +NS_ASSUME_NONNULL_BEGIN + +/// Provide an interface to register a library for userAgent logging and availability to others. +NS_SWIFT_NAME(Library) +@protocol FIRLibrary + +/// Returns one or more FIRComponents that will be registered in +/// FIRApp and participate in dependency resolution and injection. ++ (NSArray<FIRComponent *> *)componentsToRegister; + +@optional +/// Implement this method if the library needs notifications for lifecycle events. This method is +/// called when the developer calls `FirebaseApp.configure()`. ++ (void)configureWithApp:(FIRApp *)app; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* FIRLibrary_h */ diff --git a/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRLogger.h b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRLogger.h new file mode 100644 index 000000000..6fd778441 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRLogger.h @@ -0,0 +1,156 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIRLoggerLevel.h" +#else +#import <FirebaseCore/FIRLoggerLevel.h> +#endif + +NS_ASSUME_NONNULL_BEGIN + +/** + * The Firebase services used in Firebase logger. + */ +typedef NSString *const FIRLoggerService; + +extern FIRLoggerService kFIRLoggerABTesting; +extern FIRLoggerService kFIRLoggerAdMob; +extern FIRLoggerService kFIRLoggerAnalytics; +extern FIRLoggerService kFIRLoggerAuth; +extern FIRLoggerService kFIRLoggerCrash; +extern FIRLoggerService kFIRLoggerCore; +extern FIRLoggerService kFIRLoggerMLKit; +extern FIRLoggerService kFIRLoggerPerf; +extern FIRLoggerService kFIRLoggerRemoteConfig; + +/** + * The key used to store the logger's error count. + */ +extern NSString *const kFIRLoggerErrorCountKey; + +/** + * The key used to store the logger's warning count. + */ +extern NSString *const kFIRLoggerWarningCountKey; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Enables or disables Analytics debug mode. + * If set to YES, the logging level for Analytics will be set to FIRLoggerLevelDebug. + * Enabling the debug mode has no effect if the app is running from App Store. + * (required) analytics debug mode flag. + */ +void FIRSetAnalyticsDebugMode(BOOL analyticsDebugMode); + +/** + * Changes the default logging level of FIRLoggerLevelNotice to a user-specified level. + * The default level cannot be set above FIRLoggerLevelNotice if the app is running from App Store. + * (required) log level (one of the FIRLoggerLevel enum values). + */ +void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel); + +/** + * Checks if the specified logger level is loggable given the current settings. + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) whether or not this function is called from the Analytics component. + */ +BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel, BOOL analyticsComponent); + +/** + * Logs a message to the Xcode console and the device log. If running from AppStore, will + * not log any messages with a level higher than FIRLoggerLevelNotice to avoid log spamming. + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) service name of type FIRLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ +extern void FIRLogBasic(FIRLoggerLevel level, + FIRLoggerService service, + NSString *messageCode, + NSString *message, +// On 64-bit simulators, va_list is not a pointer, so cannot be marked nullable +// See: http://stackoverflow.com/q/29095469 +#if __LP64__ && TARGET_OS_SIMULATOR || TARGET_OS_OSX + va_list args_ptr +#else + va_list _Nullable args_ptr +#endif +); + +/** + * The following functions accept the following parameters in order: + * (required) service name of type FIRLoggerService. + * (required) message code starting from "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * See go/firebase-log-proposal for details. + * (required) message string which can be a format string. + * (optional) the list of arguments to substitute into the format string. + * Example usage: + * FIRLogError(kFIRLoggerCore, @"I-COR000001", @"Configuration of %@ failed.", app.name); + */ +extern void FIRLogError(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogWarning(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogNotice(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogInfo(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogDebug(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +@interface FIRLoggerWrapper : NSObject + +/** + * Objective-C wrapper for FIRLogBasic to allow weak linking to FIRLogger + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) service name of type FIRLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ + ++ (void)logWithLevel:(FIRLoggerLevel)level + withService:(FIRLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIROptionsInternal.h b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIROptionsInternal.h new file mode 100644 index 000000000..acaf45868 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIROptionsInternal.h @@ -0,0 +1,119 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIROptions.h" +#else +#import <FirebaseCore/FIROptions.h> +#endif + +/** + * Keys for the strings in the plist file. + */ +extern NSString *const kFIRAPIKey; +extern NSString *const kFIRTrackingID; +extern NSString *const kFIRGoogleAppID; +extern NSString *const kFIRClientID; +extern NSString *const kFIRGCMSenderID; +extern NSString *const kFIRAndroidClientID; +extern NSString *const kFIRDatabaseURL; +extern NSString *const kFIRStorageBucket; +extern NSString *const kFIRBundleID; +extern NSString *const kFIRProjectID; + +/** + * Keys for the plist file name + */ +extern NSString *const kServiceInfoFileName; + +extern NSString *const kServiceInfoFileType; + +/** + * This header file exposes the initialization of FIROptions to internal use. + */ +@interface FIROptions () + +/** + * resetDefaultOptions and initInternalWithOptionsDictionary: are exposed only for unit tests. + */ ++ (void)resetDefaultOptions; + +/** + * Initializes the options with dictionary. The above strings are the keys of the dictionary. + * This is the designated initializer. + */ +- (instancetype)initInternalWithOptionsDictionary:(NSDictionary *)serviceInfoDictionary; + +/** + * defaultOptions and defaultOptionsDictionary are exposed in order to be used in FIRApp and + * other first party services. + */ ++ (FIROptions *)defaultOptions; + ++ (NSDictionary *)defaultOptionsDictionary; + +/** + * Indicates whether or not Analytics collection was explicitly enabled via a plist flag or at + * runtime. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionExplicitlySet; + +/** + * Whether or not Analytics Collection was enabled. Analytics Collection is enabled unless + * explicitly disabled in GoogleService-Info.plist. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionEnabled; + +/** + * Whether or not Analytics Collection was completely disabled. If YES, then + * isAnalyticsCollectionEnabled will be NO. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionDeactivated; + +/** + * The version ID of the client library, e.g. @"1100000". + */ +@property(nonatomic, readonly, copy) NSString *libraryVersionID; + +/** + * The flag indicating whether this object was constructed with the values in the default plist + * file. + */ +@property(nonatomic) BOOL usingOptionsFromDefaultPlist; + +/** + * Whether or not Measurement was enabled. Measurement is enabled unless explicitly disabled in + * GoogleService-Info.plist. + */ +@property(nonatomic, readonly) BOOL isMeasurementEnabled; + +/** + * Whether or not Analytics was enabled in the developer console. + */ +@property(nonatomic, readonly) BOOL isAnalyticsEnabled; + +/** + * Whether or not SignIn was enabled in the developer console. + */ +@property(nonatomic, readonly) BOOL isSignInEnabled; + +/** + * Whether or not editing is locked. This should occur after FIROptions has been set on a FIRApp. + */ +@property(nonatomic, getter=isEditingLocked) BOOL editingLocked; + +@end diff --git a/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FirebaseCoreInternal.h b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FirebaseCoreInternal.h new file mode 100644 index 000000000..93af6cb8d --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FirebaseCoreInternal.h @@ -0,0 +1,31 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// An umbrella header, for any other libraries in this repo to access Firebase Public and Private +// headers. Any package manager complexity should be handled here. + +#if SWIFT_PACKAGE +@import FirebaseCore; +#else +#import <FirebaseCore/FirebaseCore.h> +#endif + +#import "FirebaseCore/Sources/Private/FIRAppInternal.h" +#import "FirebaseCore/Sources/Private/FIRComponent.h" +#import "FirebaseCore/Sources/Private/FIRComponentContainer.h" +#import "FirebaseCore/Sources/Private/FIRDependency.h" +#import "FirebaseCore/Sources/Private/FIRHeartbeatInfo.h" +#import "FirebaseCore/Sources/Private/FIRLibrary.h" +#import "FirebaseCore/Sources/Private/FIRLogger.h" +#import "FirebaseCore/Sources/Private/FIROptionsInternal.h" diff --git a/ios/Pods/FirebaseCrashlytics/Interop/Analytics/Public/FIRAnalyticsInterop.h b/ios/Pods/FirebaseCrashlytics/Interop/Analytics/Public/FIRAnalyticsInterop.h new file mode 100644 index 000000000..6581b5368 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Interop/Analytics/Public/FIRAnalyticsInterop.h @@ -0,0 +1,66 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +@protocol FIRAnalyticsInteropListener; + +NS_ASSUME_NONNULL_BEGIN + +/// Block typedef callback parameter to getUserPropertiesWithCallback:. +typedef void (^FIRAInteropUserPropertiesCallback)(NSDictionary<NSString *, id> *userProperties); + +/// Connector for bridging communication between Firebase SDKs and FirebaseAnalytics API. +@protocol FIRAnalyticsInterop + +/// Sets user property when trigger event is logged. This API is only available in the SDK. +- (void)setConditionalUserProperty:(NSDictionary<NSString *, id> *)conditionalUserProperty; + +/// Clears user property if set. +- (void)clearConditionalUserProperty:(NSString *)userPropertyName + forOrigin:(NSString *)origin + clearEventName:(NSString *)clearEventName + clearEventParameters:(NSDictionary<NSString *, NSString *> *)clearEventParameters; + +/// Returns currently set user properties. +- (NSArray<NSDictionary<NSString *, NSString *> *> *)conditionalUserProperties:(NSString *)origin + propertyNamePrefix: + (NSString *)propertyNamePrefix; + +/// Returns the maximum number of user properties. +- (NSInteger)maxUserProperties:(NSString *)origin; + +/// Returns the user properties to a callback function. +- (void)getUserPropertiesWithCallback:(FIRAInteropUserPropertiesCallback)callback; + +/// Logs events. +- (void)logEventWithOrigin:(NSString *)origin + name:(NSString *)name + parameters:(nullable NSDictionary<NSString *, id> *)parameters; + +/// Sets user property. +- (void)setUserPropertyWithOrigin:(NSString *)origin name:(NSString *)name value:(id)value; + +/// Registers an Analytics listener for the given origin. +- (void)registerAnalyticsListener:(id<FIRAnalyticsInteropListener>)listener + withOrigin:(NSString *)origin; + +/// Unregisters an Analytics listener for the given origin. +- (void)unregisterAnalyticsListenerWithOrigin:(NSString *)origin; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseCrashlytics/Interop/Analytics/Public/FIRAnalyticsInteropListener.h b/ios/Pods/FirebaseCrashlytics/Interop/Analytics/Public/FIRAnalyticsInteropListener.h new file mode 100644 index 000000000..45cde5506 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Interop/Analytics/Public/FIRAnalyticsInteropListener.h @@ -0,0 +1,24 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/// Handles events and messages from Analytics. +@protocol FIRAnalyticsInteropListener <NSObject> + +/// Triggers when an Analytics event happens for the registered origin with +/// `FIRAnalyticsInterop`s `registerAnalyticsListener:withOrigin:`. +- (void)messageTriggered:(NSString *)name parameters:(NSDictionary *)parameters; + +@end \ No newline at end of file diff --git a/ios/Pods/FirebaseCrashlytics/Interop/Analytics/Public/FIRInteropEventNames.h b/ios/Pods/FirebaseCrashlytics/Interop/Analytics/Public/FIRInteropEventNames.h new file mode 100644 index 000000000..efc54ab22 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Interop/Analytics/Public/FIRInteropEventNames.h @@ -0,0 +1,28 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/// @file FIRInteropEventNames.h + +#import <Foundation/Foundation.h> + +/// Notification open event name. +static NSString *const kFIRIEventNotificationOpen = @"_no"; + +/// Notification foreground event name. +static NSString *const kFIRIEventNotificationForeground = @"_nf"; + +/// Campaign event name. +static NSString *const kFIRIEventFirebaseCampaign = @"_cmp"; diff --git a/ios/Pods/FirebaseCrashlytics/Interop/Analytics/Public/FIRInteropParameterNames.h b/ios/Pods/FirebaseCrashlytics/Interop/Analytics/Public/FIRInteropParameterNames.h new file mode 100644 index 000000000..ae440becf --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/Interop/Analytics/Public/FIRInteropParameterNames.h @@ -0,0 +1,73 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +/// @file FIRInteropParameterNames.h +/// +/// Predefined event parameter names used by Firebase. This file is a subset of the +/// FirebaseAnalytics FIRParameterNames.h public header. +/// +/// The origin of your traffic, such as an Ad network (for example, google) or partner (urban +/// airship). Identify the advertiser, site, publication, etc. that is sending traffic to your +/// property. Highly recommended (NSString). +/// <pre> +/// NSDictionary *params = @{ +/// kFIRParameterSource : @"InMobi", +/// // ... +/// }; +/// </pre> +static NSString *const kFIRIParameterSource NS_SWIFT_NAME(AnalyticsParameterSource) = @"source"; + +/// The advertising or marketing medium, for example: cpc, banner, email, push. Highly recommended +/// (NSString). +/// <pre> +/// NSDictionary *params = @{ +/// kFIRParameterMedium : @"email", +/// // ... +/// }; +/// </pre> +static NSString *const kFIRIParameterMedium NS_SWIFT_NAME(AnalyticsParameterMedium) = @"medium"; + +/// The individual campaign name, slogan, promo code, etc. Some networks have pre-defined macro to +/// capture campaign information, otherwise can be populated by developer. Highly Recommended +/// (NSString). +/// <pre> +/// NSDictionary *params = @{ +/// kFIRParameterCampaign : @"winter_promotion", +/// // ... +/// }; +/// </pre> +static NSString *const kFIRIParameterCampaign NS_SWIFT_NAME(AnalyticsParameterCampaign) = + @"campaign"; + +/// Message identifier. +static NSString *const kFIRIParameterMessageIdentifier = @"_nmid"; + +/// Message name. +static NSString *const kFIRIParameterMessageName = @"_nmn"; + +/// Message send time. +static NSString *const kFIRIParameterMessageTime = @"_nmt"; + +/// Message device time. +static NSString *const kFIRIParameterMessageDeviceTime = @"_ndt"; + +/// Topic message. +static NSString *const kFIRIParameterTopic = @"_nt"; + +/// Stores the message_id of the last notification opened by the app. +static NSString *const kFIRIUserPropertyLastNotification = @"_ln"; diff --git a/ios/Pods/FirebaseCrashlytics/README.md b/ios/Pods/FirebaseCrashlytics/README.md new file mode 100644 index 000000000..d778205ff --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/README.md @@ -0,0 +1,311 @@ +[![Version](https://img.shields.io/cocoapods/v/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) + +[![Actions Status][gh-abtesting-badge]][gh-actions] +[![Actions Status][gh-auth-badge]][gh-actions] +[![Actions Status][gh-core-badge]][gh-actions] +[![Actions Status][gh-crashlytics-badge]][gh-actions] +[![Actions Status][gh-database-badge]][gh-actions] +[![Actions Status][gh-datatransport-badge]][gh-actions] +[![Actions Status][gh-dynamiclinks-badge]][gh-actions] +[![Actions Status][gh-firebasepod-badge]][gh-actions] +[![Actions Status][gh-firestore-badge]][gh-actions] +[![Actions Status][gh-functions-badge]][gh-actions] +[![Actions Status][gh-inappmessaging-badge]][gh-actions] +[![Actions Status][gh-interop-badge]][gh-actions] +[![Actions Status][gh-messaging-badge]][gh-actions] +[![Actions Status][gh-remoteconfig-badge]][gh-actions] +[![Actions Status][gh-storage-badge]][gh-actions] +[![Actions Status][gh-symbolcollision-badge]][gh-actions] +[![Actions Status][gh-zip-badge]][gh-actions] +[![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +# Firebase Apple Open Source Development + +This repository contains all Apple platform Firebase SDK source except FirebaseAnalytics, +FirebasePerformance, and FirebaseML. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +### Using Firebase from a Framework or a library + +[Using Firebase from a Framework or a library](docs/firebase_in_libraries.md) + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.3 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Managing Headers and Imports + +See [HeadersImports.md](HeadersImports.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c6f1cbd/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c13eda8/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage (Deprecated) + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](FirebaseAuth/Tests/Sample/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +The Firebase Database Integration tests can be run against a locally running Database Emulator +or against a production instance. + +To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before +running the integration test. + +To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to +`Example/Database/App/GoogleService-Info.plist`. Your Security Rule must be set to +[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are +running. + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](FirebaseStorage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, watchOS and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, watchOS and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). +For watchOS, currently only Messaging and Storage (and their dependencies) have limited support. Checkout the +[Independent Watch App Sample](Example/watchOSSample). + +Keep in mind that macOS, tvOS, watchOS and Catalyst are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS, tvOS or watchOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/watchOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' # No watchOS support yet +pod 'Firebase/Auth' # No watchOS support yet +pod 'Firebase/Crashlytics' # No watchOS support yet +pod 'Firebase/Database' # No watchOS support yet +pod 'Firebase/Firestore' # No watchOS support yet +pod 'Firebase/Functions' # No watchOS support yet +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' # No watchOS support yet +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). + +[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg +[gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg +[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg +[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg +[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg +[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg +[gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg +[gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg +[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg +[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg +[gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg +[gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg +[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg +[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg +[gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg +[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/ios/Pods/FirebaseCrashlytics/run b/ios/Pods/FirebaseCrashlytics/run new file mode 100755 index 000000000..9316eeaf7 --- /dev/null +++ b/ios/Pods/FirebaseCrashlytics/run @@ -0,0 +1,76 @@ +#!/bin/sh + +# Copyright 2019 Google +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# run +# +# This script is meant to be run as a Run Script in the "Build Phases" section +# of your Xcode project. It sends debug symbols to symbolicate stacktraces, +# sends build events to track versions, and onboards apps for Crashlytics. +# +# This script calls upload-symbols twice: +# +# 1) First it calls upload-symbols synchronously in "validation" mode. If the +# script finds issues with the build environment, it will report errors to Xcode. +# In validation mode it exits before doing any time consuming work. +# +# 2) Then it calls upload-symbols in the background to actually send the build +# event and upload symbols. It does this in the background so that it doesn't +# slow down your builds. If an error happens here, you won't see it in Xcode. +# +# You can find the output for the background execution in Console.app, by +# searching for "upload-symbols". +# +# If you want verbose output, you can pass the --debug flag to this script +# + +# Figure out where we're being called from +DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# If the first argument is specified without a dash, treat it as the Fabric API +# Key and add it as an argument. +if [ -z "$1" ] || [[ $1 == -* ]]; then + API_KEY_ARG="" +else + API_KEY_ARG="-a $1"; shift +fi + +# Build up the arguments list, passing through any flags added after the +# API Key +ARGUMENTS="$API_KEY_ARG $@" +VALIDATE_ARGUMENTS="$ARGUMENTS --build-phase --validate" +UPLOAD_ARGUMENTS="$ARGUMENTS --build-phase" + +# Quote the path to handle folders with special characters +COMMAND_PATH="\"$DIR/upload-symbols\" " + +# Ensure params are as expected, run in sync mode to validate, +# and cause a build error if validation fails +eval $COMMAND_PATH$VALIDATE_ARGUMENTS +return_code=$? + +if [[ $return_code != 0 ]]; then + exit $return_code +fi + +# Verification passed, convert and upload cSYMs in the background to prevent +# build delays +# +# Note: Validation is performed again at this step before upload +# +# Note: Output can still be found in Console.app, by searching for +# "upload-symbols" +# +eval $COMMAND_PATH$UPLOAD_ARGUMENTS > /dev/null 2>&1 & diff --git a/ios/Pods/FirebaseCrashlytics/upload-symbols b/ios/Pods/FirebaseCrashlytics/upload-symbols new file mode 100755 index 000000000..76738d0c4 Binary files /dev/null and b/ios/Pods/FirebaseCrashlytics/upload-symbols differ diff --git a/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRAppInternal.h b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRAppInternal.h new file mode 100644 index 000000000..9a0c943db --- /dev/null +++ b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRAppInternal.h @@ -0,0 +1,173 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIRApp.h" +#else +#import <FirebaseCore/FIRApp.h> +#endif + +// The has_include is a workaround so the old IID needed for the FIS tests can find FIRErrors.h +#if __has_include("FirebaseCore/Sources/Private/FIRErrors.h") +#import "FirebaseCore/Sources/Private/FIRErrors.h" +#else +#import <FirebaseCore/FIRErrors.h> +#endif + +@class FIRComponentContainer; +@protocol FIRLibrary; + +/** + * The internal interface to FIRApp. This is meant for first-party integrators, who need to receive + * FIRApp notifications, log info about the success or failure of their configuration, and access + * other internal functionality of FIRApp. + * + * TODO(b/28296561): Restructure this header. + */ +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, FIRConfigType) { + FIRConfigTypeCore = 1, + FIRConfigTypeSDK = 2, +}; + +extern NSString *const kFIRDefaultAppName; +extern NSString *const kFIRAppReadyToConfigureSDKNotification; +extern NSString *const kFIRAppDeleteNotification; +extern NSString *const kFIRAppIsDefaultAppKey; +extern NSString *const kFIRAppNameKey; +extern NSString *const kFIRGoogleAppIDKey; + +/** + * The format string for the User Defaults key used for storing the data collection enabled flag. + * This includes formatting to append the Firebase App's name. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat; + +/** + * The plist key used for storing the data collection enabled flag. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey; + +/** + * A notification fired containing diagnostic information when SDK errors occur. + */ +extern NSString *const kFIRAppDiagnosticsNotification; + +/** @var FIRAuthStateDidChangeInternalNotification + @brief The name of the @c NSNotificationCenter notification which is posted when the auth state + changes (e.g. a new token has been produced, a user logs in or out). The object parameter of + the notification is a dictionary possibly containing the key: + @c FIRAuthStateDidChangeInternalNotificationTokenKey (the new access token.) If it does not + contain this key it indicates a sign-out event took place. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotification; + +/** @var FIRAuthStateDidChangeInternalNotificationTokenKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new access token. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey; + +/** @var FIRAuthStateDidChangeInternalNotificationAppKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the FIRApp associated with the auth instance. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationAppKey; + +/** @var FIRAuthStateDidChangeInternalNotificationUIDKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new user's UID (or nil if there is no longer a user signed in). + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey; + +@interface FIRApp () + +/** + * A flag indicating if this is the default app (has the default app name). + */ +@property(nonatomic, readonly) BOOL isDefaultApp; + +/* + * The container of interop SDKs for this app. + */ +@property(nonatomic) FIRComponentContainer *container; + +/** + * Creates an error for failing to configure a subspec service. This method is called by each + * FIRApp notification listener. + */ ++ (NSError *)errorForSubspecConfigurationFailureWithDomain:(NSString *)domain + errorCode:(FIRErrorCode)code + service:(NSString *)service + reason:(NSString *)reason; +/** + * Checks if the default app is configured without trying to configure it. + */ ++ (BOOL)isDefaultAppConfigured; + +/** + * Registers a given third-party library with the given version number to be reported for + * analytics. + * + * @param name Name of the library. + * @param version Version of the library. + */ ++ (void)registerLibrary:(nonnull NSString *)name withVersion:(nonnull NSString *)version; + +/** + * Registers a given internal library with the given version number to be reported for + * analytics. + * + * @param library Optional parameter for component registration. + * @param name Name of the library. + * @param version Version of the library. + */ ++ (void)registerInternalLibrary:(nonnull Class<FIRLibrary>)library + withName:(nonnull NSString *)name + withVersion:(nonnull NSString *)version; + +/** + * A concatenated string representing all the third-party libraries and version numbers. + */ ++ (NSString *)firebaseUserAgent; + +/** + * Used by each SDK to send logs about SDK configuration status to Clearcut. + * + * @note This API is a no-op, please remove calls to it. + */ +- (void)sendLogsWithServiceName:(NSString *)serviceName + version:(NSString *)version + error:(NSError *)error; + +/** + * Can be used by the unit tests in eack SDK to reset FIRApp. This method is thread unsafe. + */ ++ (void)resetApps; + +/** + * Can be used by the unit tests in each SDK to set customized options. + */ +- (instancetype)initInstanceWithName:(NSString *)name options:(FIROptions *)options; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRComponent.h b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRComponent.h new file mode 100644 index 000000000..cb51ee70e --- /dev/null +++ b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRComponent.h @@ -0,0 +1,91 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +@class FIRApp; +@class FIRComponentContainer; + +NS_ASSUME_NONNULL_BEGIN + +/// Provides a system to clean up cached instances returned from the component system. +NS_SWIFT_NAME(ComponentLifecycleMaintainer) +@protocol FIRComponentLifecycleMaintainer +/// The associated app will be deleted, clean up any resources as they are about to be deallocated. +- (void)appWillBeDeleted:(FIRApp *)app; +@end + +typedef _Nullable id (^FIRComponentCreationBlock)(FIRComponentContainer *container, + BOOL *isCacheable) + NS_SWIFT_NAME(ComponentCreationBlock); + +@class FIRDependency; + +/// Describes the timing of instantiation. Note: new components should default to lazy unless there +/// is a strong reason to be eager. +typedef NS_ENUM(NSInteger, FIRInstantiationTiming) { + FIRInstantiationTimingLazy, + FIRInstantiationTimingAlwaysEager, + FIRInstantiationTimingEagerInDefaultApp +} NS_SWIFT_NAME(InstantiationTiming); + +/// A component that can be used from other Firebase SDKs. +NS_SWIFT_NAME(Component) +@interface FIRComponent : NSObject + +/// The protocol describing functionality provided from the Component. +@property(nonatomic, strong, readonly) Protocol *protocol; + +/// The timing of instantiation. +@property(nonatomic, readonly) FIRInstantiationTiming instantiationTiming; + +/// An array of dependencies for the component. +@property(nonatomic, copy, readonly) NSArray<FIRDependency *> *dependencies; + +/// A block to instantiate an instance of the component with the appropriate dependencies. +@property(nonatomic, copy, readonly) FIRComponentCreationBlock creationBlock; + +// There's an issue with long NS_SWIFT_NAMES that causes compilation to fail, disable clang-format +// for the next two methods. +// clang-format off + +/// Creates a component with no dependencies that will be lazily initialized. ++ (instancetype)componentWithProtocol:(Protocol *)protocol + creationBlock:(FIRComponentCreationBlock)creationBlock +NS_SWIFT_NAME(init(_:creationBlock:)); + +/// Creates a component to be registered with the component container. +/// +/// @param protocol - The protocol describing functionality provided by the component. +/// @param instantiationTiming - When the component should be initialized. Use .lazy unless there's +/// a good reason to be instantiated earlier. +/// @param dependencies - Any dependencies the `implementingClass` has, optional or required. +/// @param creationBlock - A block to instantiate the component with a container, and if +/// @return A component that can be registered with the component container. ++ (instancetype)componentWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray<FIRDependency *> *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock +NS_SWIFT_NAME(init(_:instantiationTiming:dependencies:creationBlock:)); + +// clang-format on + +/// Unavailable. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRComponentContainer.h b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRComponentContainer.h new file mode 100644 index 000000000..db2bafef8 --- /dev/null +++ b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRComponentContainer.h @@ -0,0 +1,50 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import <Foundation/Foundation.h> + +// The has_include is a workaround so the old IID needed for the FIS tests can find the headers. +#if __has_include("FirebaseCore/Sources/Private/FIRComponentType.h") +#import "FirebaseCore/Sources/Private/FIRComponentType.h" +#import "FirebaseCore/Sources/Private/FIRLibrary.h" +#else +#import <FirebaseCore/FIRComponentType.h> +#import <FirebaseCore/FIRLibrary.h> +#endif + +NS_ASSUME_NONNULL_BEGIN + +/// A type-safe macro to retrieve a component from a container. This should be used to retrieve +/// components instead of using the container directly. +#define FIR_COMPONENT(type, container) \ + [FIRComponentType<id<type>> instanceForProtocol:@protocol(type) inContainer:container] + +@class FIRApp; + +/// A container that holds different components that are registered via the +/// `registerAsComponentRegistrant:` call. These classes should conform to `FIRComponentRegistrant` +/// in order to properly register components for Core. +NS_SWIFT_NAME(FirebaseComponentContainer) +@interface FIRComponentContainer : NSObject + +/// A weak reference to the app that an instance of the container belongs to. +@property(nonatomic, weak, readonly) FIRApp *app; + +/// Unavailable. Use the `container` property on `FIRApp`. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRComponentType.h b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRComponentType.h new file mode 100644 index 000000000..6f2aca7b8 --- /dev/null +++ b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRComponentType.h @@ -0,0 +1,34 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +@class FIRComponentContainer; + +NS_ASSUME_NONNULL_BEGIN + +/// Do not use directly. A placeholder type in order to provide a macro that will warn users of +/// mis-matched protocols. +NS_SWIFT_NAME(ComponentType) +@interface FIRComponentType<__covariant T> : NSObject + +/// Do not use directly. A factory method to retrieve an instance that provides a specific +/// functionality. ++ (T)instanceForProtocol:(Protocol *)protocol inContainer:(FIRComponentContainer *)container; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h new file mode 100644 index 000000000..76c0c05f0 --- /dev/null +++ b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +@class FIRDiagnosticsData; +@class FIROptions; + +NS_ASSUME_NONNULL_BEGIN + +/** Connects FIRCore with the CoreDiagnostics library. */ +@interface FIRCoreDiagnosticsConnector : NSObject + +/** Logs FirebaseCore related data. + * + * @param options The options object containing data to log. + */ ++ (void)logCoreTelemetryWithOptions:(FIROptions *)options; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRDependency.h b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRDependency.h new file mode 100644 index 000000000..46e9b7ea6 --- /dev/null +++ b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRDependency.h @@ -0,0 +1,45 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +/// A dependency on a specific protocol's functionality. +NS_SWIFT_NAME(Dependency) +@interface FIRDependency : NSObject + +/// The protocol describing functionality being depended on. +@property(nonatomic, strong, readonly) Protocol *protocol; + +/// A flag to specify if the dependency is required or not. +@property(nonatomic, readonly) BOOL isRequired; + +/// Initializes a dependency that is required. Calls `initWithProtocol:isRequired` with `YES` for +/// the required parameter. +/// Creates a required dependency on the specified protocol's functionality. ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol; + +/// Creates a dependency on the specified protocol's functionality and specify if it's required for +/// the class's functionality. ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol isRequired:(BOOL)required; + +/// Use `dependencyWithProtocol:isRequired:` instead. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRErrorCode.h b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRErrorCode.h new file mode 100644 index 000000000..c90d9eecf --- /dev/null +++ b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRErrorCode.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** Error codes in Firebase error domain. */ +typedef NS_ENUM(NSInteger, FIRErrorCode) { + /** + * Unknown error. + */ + FIRErrorCodeUnknown = 0, + /** + * Loading data from the GoogleService-Info.plist file failed. This is a fatal error and should + * not be ignored. Further calls to the API will fail and/or possibly cause crashes. + */ + FIRErrorCodeInvalidPlistFile = -100, + + /** + * Validating the Google App ID format failed. + */ + FIRErrorCodeInvalidAppID = -101, + + /** + * Error code for failing to configure a specific service. It's deprecated, but + * still used after copybara. + */ + FIRErrorCodeConfigFailed = -114, +}; diff --git a/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRErrors.h b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRErrors.h new file mode 100644 index 000000000..19e47328a --- /dev/null +++ b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRErrors.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +#include "FIRErrorCode.h" + +extern NSString *const kFirebaseErrorDomain; +extern NSString *const kFirebaseConfigErrorDomain; +extern NSString *const kFirebaseCoreErrorDomain; +extern NSString *const kFirebasePerfErrorDomain; diff --git a/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h new file mode 100644 index 000000000..bfff73e5d --- /dev/null +++ b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h @@ -0,0 +1,39 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRHeartbeatInfo : NSObject + +// Enum representing the different heartbeat codes. +typedef NS_ENUM(NSInteger, FIRHeartbeatInfoCode) { + FIRHeartbeatInfoCodeNone = 0, + FIRHeartbeatInfoCodeSDK = 1, + FIRHeartbeatInfoCodeGlobal = 2, + FIRHeartbeatInfoCodeCombined = 3, +}; + +/** + * Get heartbeat code requred for the sdk. + * @param heartbeatTag String representing the sdk heartbeat tag. + * @return Heartbeat code indicating whether or not an sdk/global heartbeat + * needs to be sent + */ ++ (FIRHeartbeatInfoCode)heartbeatCodeForTag:(NSString *)heartbeatTag; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRLibrary.h b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRLibrary.h new file mode 100644 index 000000000..e7a9e077c --- /dev/null +++ b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRLibrary.h @@ -0,0 +1,50 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRLibrary_h +#define FIRLibrary_h + +#import <Foundation/Foundation.h> + +// The has_include is a workaround so the old IID needed for the FIS tests can find the headers. +#if __has_include("FirebaseCore/Sources/Private/FIRComponent.h") +#import "FirebaseCore/Sources/Private/FIRComponent.h" +#else +#import <FirebaseCore/FIRComponent.h> +#endif + +@class FIRApp; + +NS_ASSUME_NONNULL_BEGIN + +/// Provide an interface to register a library for userAgent logging and availability to others. +NS_SWIFT_NAME(Library) +@protocol FIRLibrary + +/// Returns one or more FIRComponents that will be registered in +/// FIRApp and participate in dependency resolution and injection. ++ (NSArray<FIRComponent *> *)componentsToRegister; + +@optional +/// Implement this method if the library needs notifications for lifecycle events. This method is +/// called when the developer calls `FirebaseApp.configure()`. ++ (void)configureWithApp:(FIRApp *)app; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* FIRLibrary_h */ diff --git a/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRLogger.h b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRLogger.h new file mode 100644 index 000000000..6fd778441 --- /dev/null +++ b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRLogger.h @@ -0,0 +1,156 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIRLoggerLevel.h" +#else +#import <FirebaseCore/FIRLoggerLevel.h> +#endif + +NS_ASSUME_NONNULL_BEGIN + +/** + * The Firebase services used in Firebase logger. + */ +typedef NSString *const FIRLoggerService; + +extern FIRLoggerService kFIRLoggerABTesting; +extern FIRLoggerService kFIRLoggerAdMob; +extern FIRLoggerService kFIRLoggerAnalytics; +extern FIRLoggerService kFIRLoggerAuth; +extern FIRLoggerService kFIRLoggerCrash; +extern FIRLoggerService kFIRLoggerCore; +extern FIRLoggerService kFIRLoggerMLKit; +extern FIRLoggerService kFIRLoggerPerf; +extern FIRLoggerService kFIRLoggerRemoteConfig; + +/** + * The key used to store the logger's error count. + */ +extern NSString *const kFIRLoggerErrorCountKey; + +/** + * The key used to store the logger's warning count. + */ +extern NSString *const kFIRLoggerWarningCountKey; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Enables or disables Analytics debug mode. + * If set to YES, the logging level for Analytics will be set to FIRLoggerLevelDebug. + * Enabling the debug mode has no effect if the app is running from App Store. + * (required) analytics debug mode flag. + */ +void FIRSetAnalyticsDebugMode(BOOL analyticsDebugMode); + +/** + * Changes the default logging level of FIRLoggerLevelNotice to a user-specified level. + * The default level cannot be set above FIRLoggerLevelNotice if the app is running from App Store. + * (required) log level (one of the FIRLoggerLevel enum values). + */ +void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel); + +/** + * Checks if the specified logger level is loggable given the current settings. + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) whether or not this function is called from the Analytics component. + */ +BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel, BOOL analyticsComponent); + +/** + * Logs a message to the Xcode console and the device log. If running from AppStore, will + * not log any messages with a level higher than FIRLoggerLevelNotice to avoid log spamming. + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) service name of type FIRLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ +extern void FIRLogBasic(FIRLoggerLevel level, + FIRLoggerService service, + NSString *messageCode, + NSString *message, +// On 64-bit simulators, va_list is not a pointer, so cannot be marked nullable +// See: http://stackoverflow.com/q/29095469 +#if __LP64__ && TARGET_OS_SIMULATOR || TARGET_OS_OSX + va_list args_ptr +#else + va_list _Nullable args_ptr +#endif +); + +/** + * The following functions accept the following parameters in order: + * (required) service name of type FIRLoggerService. + * (required) message code starting from "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * See go/firebase-log-proposal for details. + * (required) message string which can be a format string. + * (optional) the list of arguments to substitute into the format string. + * Example usage: + * FIRLogError(kFIRLoggerCore, @"I-COR000001", @"Configuration of %@ failed.", app.name); + */ +extern void FIRLogError(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogWarning(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogNotice(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogInfo(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogDebug(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +@interface FIRLoggerWrapper : NSObject + +/** + * Objective-C wrapper for FIRLogBasic to allow weak linking to FIRLogger + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) service name of type FIRLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ + ++ (void)logWithLevel:(FIRLoggerLevel)level + withService:(FIRLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIROptionsInternal.h b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIROptionsInternal.h new file mode 100644 index 000000000..acaf45868 --- /dev/null +++ b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIROptionsInternal.h @@ -0,0 +1,119 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIROptions.h" +#else +#import <FirebaseCore/FIROptions.h> +#endif + +/** + * Keys for the strings in the plist file. + */ +extern NSString *const kFIRAPIKey; +extern NSString *const kFIRTrackingID; +extern NSString *const kFIRGoogleAppID; +extern NSString *const kFIRClientID; +extern NSString *const kFIRGCMSenderID; +extern NSString *const kFIRAndroidClientID; +extern NSString *const kFIRDatabaseURL; +extern NSString *const kFIRStorageBucket; +extern NSString *const kFIRBundleID; +extern NSString *const kFIRProjectID; + +/** + * Keys for the plist file name + */ +extern NSString *const kServiceInfoFileName; + +extern NSString *const kServiceInfoFileType; + +/** + * This header file exposes the initialization of FIROptions to internal use. + */ +@interface FIROptions () + +/** + * resetDefaultOptions and initInternalWithOptionsDictionary: are exposed only for unit tests. + */ ++ (void)resetDefaultOptions; + +/** + * Initializes the options with dictionary. The above strings are the keys of the dictionary. + * This is the designated initializer. + */ +- (instancetype)initInternalWithOptionsDictionary:(NSDictionary *)serviceInfoDictionary; + +/** + * defaultOptions and defaultOptionsDictionary are exposed in order to be used in FIRApp and + * other first party services. + */ ++ (FIROptions *)defaultOptions; + ++ (NSDictionary *)defaultOptionsDictionary; + +/** + * Indicates whether or not Analytics collection was explicitly enabled via a plist flag or at + * runtime. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionExplicitlySet; + +/** + * Whether or not Analytics Collection was enabled. Analytics Collection is enabled unless + * explicitly disabled in GoogleService-Info.plist. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionEnabled; + +/** + * Whether or not Analytics Collection was completely disabled. If YES, then + * isAnalyticsCollectionEnabled will be NO. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionDeactivated; + +/** + * The version ID of the client library, e.g. @"1100000". + */ +@property(nonatomic, readonly, copy) NSString *libraryVersionID; + +/** + * The flag indicating whether this object was constructed with the values in the default plist + * file. + */ +@property(nonatomic) BOOL usingOptionsFromDefaultPlist; + +/** + * Whether or not Measurement was enabled. Measurement is enabled unless explicitly disabled in + * GoogleService-Info.plist. + */ +@property(nonatomic, readonly) BOOL isMeasurementEnabled; + +/** + * Whether or not Analytics was enabled in the developer console. + */ +@property(nonatomic, readonly) BOOL isAnalyticsEnabled; + +/** + * Whether or not SignIn was enabled in the developer console. + */ +@property(nonatomic, readonly) BOOL isSignInEnabled; + +/** + * Whether or not editing is locked. This should occur after FIROptions has been set on a FIRApp. + */ +@property(nonatomic, getter=isEditingLocked) BOOL editingLocked; + +@end diff --git a/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FirebaseCoreInternal.h b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FirebaseCoreInternal.h new file mode 100644 index 000000000..93af6cb8d --- /dev/null +++ b/ios/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FirebaseCoreInternal.h @@ -0,0 +1,31 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// An umbrella header, for any other libraries in this repo to access Firebase Public and Private +// headers. Any package manager complexity should be handled here. + +#if SWIFT_PACKAGE +@import FirebaseCore; +#else +#import <FirebaseCore/FirebaseCore.h> +#endif + +#import "FirebaseCore/Sources/Private/FIRAppInternal.h" +#import "FirebaseCore/Sources/Private/FIRComponent.h" +#import "FirebaseCore/Sources/Private/FIRComponentContainer.h" +#import "FirebaseCore/Sources/Private/FIRDependency.h" +#import "FirebaseCore/Sources/Private/FIRHeartbeatInfo.h" +#import "FirebaseCore/Sources/Private/FIRLibrary.h" +#import "FirebaseCore/Sources/Private/FIRLogger.h" +#import "FirebaseCore/Sources/Private/FIROptionsInternal.h" diff --git a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h index 5bc21a11c..941aa3dd1 100644 --- a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h +++ b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h @@ -16,7 +16,7 @@ #import <Foundation/Foundation.h> -#import <FirebaseInstallations/FIRInstallationsErrors.h> +#import "FirebaseInstallations/Source/Library/Public/FIRInstallationsErrors.h" @class FIRInstallationsHTTPError; diff --git a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.m b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.m index f85923ace..1b3357005 100644 --- a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.m +++ b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.m @@ -14,9 +14,9 @@ * limitations under the License. */ -#import "FIRInstallationsErrorUtil.h" +#import "FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h" -#import "FIRInstallationsHTTPError.h" +#import "FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.h" NSString *const kFirebaseInstallationsErrorDomain = @"com.firebase.installations"; diff --git a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.m b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.m index 5b3eae22b..4236f452e 100644 --- a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.m +++ b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.m @@ -14,8 +14,8 @@ * limitations under the License. */ -#import "FIRInstallationsHTTPError.h" -#import "FIRInstallationsErrorUtil.h" +#import "FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.h" +#import "FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h" @implementation FIRInstallationsHTTPError @@ -41,9 +41,10 @@ + (NSDictionary *)userInfoWithHTTPResponse:(NSHTTPURLResponse *)HTTPResponse data:(nullable NSData *)data { NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; - NSString *failureReason = [NSString - stringWithFormat:@"The server responded with an error. HTTP response: %@\nResponse body: %@", - HTTPResponse, responseString]; + NSString *failureReason = + [NSString stringWithFormat:@"The server responded with an error: \n - URL: %@ \n - HTTP " + @"status code: %ld \n - Response body: %@", + HTTPResponse.URL, (long)HTTPResponse.statusCode, responseString]; return @{NSLocalizedFailureReasonErrorKey : failureReason}; } diff --git a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallations.m b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallations.m index 71e7dd434..cbdd8b299 100644 --- a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallations.m +++ b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallations.m @@ -14,7 +14,7 @@ * limitations under the License. */ -#import "FIRInstallations.h" +#import "FirebaseInstallations/Source/Library/Public/FIRInstallations.h" #if __has_include(<FBLPromises/FBLPromises.h>) #import <FBLPromises/FBLPromises.h> @@ -22,21 +22,16 @@ #import "FBLPromises.h" #endif -#import <FirebaseCore/FIRAppInternal.h> -#import <FirebaseCore/FIRComponent.h> -#import <FirebaseCore/FIRComponentContainer.h> -#import <FirebaseCore/FIRLibrary.h> -#import <FirebaseCore/FIRLogger.h> -#import <FirebaseCore/FIROptions.h> +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" -#import "FIRInstallationsAuthTokenResultInternal.h" +#import "FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResultInternal.h" -#import "FIRInstallationsErrorUtil.h" -#import "FIRInstallationsIDController.h" -#import "FIRInstallationsItem.h" -#import "FIRInstallationsLogger.h" -#import "FIRInstallationsStoredAuthToken.h" -#import "FIRInstallationsVersion.h" +#import "FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h" +#import "FirebaseInstallations/Source/Library/FIRInstallationsItem.h" +#import "FirebaseInstallations/Source/Library/FIRInstallationsLogger.h" +#import "FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.h" +#import "FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.h" +#import "FirebaseInstallations/Source/Library/Public/FIRInstallationsVersion.h" NS_ASSUME_NONNULL_BEGIN @@ -89,10 +84,12 @@ NS_ASSUME_NONNULL_BEGIN projectID:appOptions.projectID GCMSenderID:appOptions.GCMSenderID accessGroup:appOptions.appGroupID]; + + // `prefetchAuthToken` is disabled due to b/156746574. return [self initWithAppOptions:appOptions appName:appName installationsIDController:IDController - prefetchAuthToken:YES]; + prefetchAuthToken:NO]; } /// The initializer is supposed to be used by tests to inject `installationsStore`. diff --git a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResult.m b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResult.m index 92e5fab19..47a71e845 100644 --- a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResult.m +++ b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResult.m @@ -14,7 +14,7 @@ * limitations under the License. */ -#import "FIRInstallationsAuthTokenResultInternal.h" +#import "FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResultInternal.h" @implementation FIRInstallationsAuthTokenResult diff --git a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResultInternal.h b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResultInternal.h index 0c959dba5..2233dd346 100644 --- a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResultInternal.h +++ b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResultInternal.h @@ -14,7 +14,7 @@ * limitations under the License. */ -#import <FirebaseInstallations/FIRInstallationsAuthTokenResult.h> +#import "FirebaseInstallations/Source/Library/Public/FIRInstallationsAuthTokenResult.h" NS_ASSUME_NONNULL_BEGIN diff --git a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.h b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.h index 95fdf835f..4b64b7fc1 100644 --- a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.h +++ b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.h @@ -16,7 +16,7 @@ #import <Foundation/Foundation.h> -#import "FIRInstallationsStatus.h" +#import "FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsStatus.h" @class FIRInstallationsStoredItem; @class FIRInstallationsStoredAuthToken; diff --git a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.m b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.m index bc819bf8a..200d8ae41 100644 --- a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.m +++ b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.m @@ -14,10 +14,10 @@ * limitations under the License. */ -#import "FIRInstallationsItem.h" +#import "FirebaseInstallations/Source/Library/FIRInstallationsItem.h" -#import "FIRInstallationsStoredAuthToken.h" -#import "FIRInstallationsStoredItem.h" +#import "FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.h" +#import "FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.h" @implementation FIRInstallationsItem diff --git a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.h b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.h index baeadb2e3..e4192bf66 100644 --- a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.h +++ b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.h @@ -16,7 +16,7 @@ #import <Foundation/Foundation.h> -#import <FirebaseCore/FIRLogger.h> +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" extern FIRLoggerService kFIRLoggerInstallations; diff --git a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.m b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.m index c2bdf37f1..edfcde970 100644 --- a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.m +++ b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.m @@ -14,7 +14,7 @@ * limitations under the License. */ -#import "FIRInstallationsLogger.h" +#import "FirebaseInstallations/Source/Library/FIRInstallationsLogger.h" FIRLoggerService kFIRLoggerInstallations = @"[Firebase/Installations]"; diff --git a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsVersion.m b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsVersion.m index a75e3f5be..8509680f9 100644 --- a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsVersion.m +++ b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsVersion.m @@ -14,7 +14,7 @@ * limitations under the License. */ -#import "FIRInstallationsVersion.h" +#import "FirebaseInstallations/Source/Library/Public/FIRInstallationsVersion.h" // Convert the macro to a string #define STR(x) STR_EXPAND(x) diff --git a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.m b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.m index 1f3a82afa..1a77831df 100644 --- a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.m +++ b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.m @@ -14,7 +14,7 @@ * limitations under the License. */ -#import "FIRInstallationsIIDStore.h" +#import "FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.h" #if __has_include(<FBLPromises/FBLPromises.h>) #import <FBLPromises/FBLPromises.h> @@ -23,7 +23,7 @@ #endif #import <CommonCrypto/CommonDigest.h> -#import "FIRInstallationsErrorUtil.h" +#import "FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h" static NSString *const kFIRInstallationsIIDKeyPairPublicTagPrefix = @"com.google.iid.keypair.public-"; diff --git a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.m b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.m index b2b69313e..7d6226353 100644 --- a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.m +++ b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.m @@ -14,7 +14,7 @@ * limitations under the License. */ -#import "FIRInstallationsIIDTokenStore.h" +#import "FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.h" #if __has_include(<FBLPromises/FBLPromises.h>) #import <FBLPromises/FBLPromises.h> @@ -22,9 +22,9 @@ #import "FBLPromises.h" #endif -#import <GoogleUtilities/GULKeychainUtils.h> +#import "GoogleUtilities/Environment/Private/GULKeychainUtils.h" -#import "FIRInstallationsErrorUtil.h" +#import "FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h" static NSString *const kFIRInstallationsIIDTokenKeychainId = @"com.google.iid-tokens"; diff --git a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.m b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.m index 6e7462203..8f38e0c6c 100644 --- a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.m +++ b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.m @@ -14,9 +14,9 @@ * limitations under the License. */ -#import "FIRInstallationsAPIService.h" +#import "FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.h" -#import <FirebaseInstallations/FIRInstallationsVersion.h> +#import "FirebaseInstallations/Source/Library/Public/FIRInstallationsVersion.h" #if __has_include(<FBLPromises/FBLPromises.h>) #import <FBLPromises/FBLPromises.h> @@ -24,11 +24,10 @@ #import "FBLPromises.h" #endif -#import <FirebaseCore/FIRAppInternal.h> -#import <FirebaseCore/FIRHeartbeatInfo.h> -#import "FIRInstallationsErrorUtil.h" -#import "FIRInstallationsItem+RegisterInstallationAPI.h" -#import "FIRInstallationsLogger.h" +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" +#import "FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h" +#import "FirebaseInstallations/Source/Library/FIRInstallationsLogger.h" +#import "FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.h" NSString *const kFIRInstallationsAPIBaseURL = @"https://firebaseinstallations.googleapis.com"; NSString *const kFIRInstallationsAPIKey = @"X-Goog-Api-Key"; diff --git a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.h b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.h index cc6b54320..0e4af55e4 100644 --- a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.h +++ b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.h @@ -14,7 +14,7 @@ * limitations under the License. */ -#import "FIRInstallationsItem.h" +#import "FirebaseInstallations/Source/Library/FIRInstallationsItem.h" @class FIRInstallationsStoredAuthToken; diff --git a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.m b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.m index 569e35b99..e5c736010 100644 --- a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.m +++ b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.m @@ -14,10 +14,10 @@ * limitations under the License. */ -#import "FIRInstallationsItem+RegisterInstallationAPI.h" +#import "FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.h" -#import "FIRInstallationsErrorUtil.h" -#import "FIRInstallationsStoredAuthToken.h" +#import "FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h" +#import "FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.h" @implementation FIRInstallationsItem (RegisterInstallationAPI) diff --git a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.m b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.m index 1b8ddcbfa..b6ea4b24f 100644 --- a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.m +++ b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.m @@ -14,7 +14,7 @@ * limitations under the License. */ -#import "FIRInstallationsIDController.h" +#import "FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.h" #if __has_include(<FBLPromises/FBLPromises.h>) #import <FBLPromises/FBLPromises.h> @@ -22,20 +22,20 @@ #import "FBLPromises.h" #endif -#import <FirebaseCore/FIRAppInternal.h> -#import <GoogleUtilities/GULKeychainStorage.h> +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" +#import "GoogleUtilities/Environment/Private/GULKeychainStorage.h" -#import "FIRInstallationsAPIService.h" -#import "FIRInstallationsErrorUtil.h" -#import "FIRInstallationsIIDStore.h" -#import "FIRInstallationsIIDTokenStore.h" -#import "FIRInstallationsItem.h" -#import "FIRInstallationsLogger.h" -#import "FIRInstallationsSingleOperationPromiseCache.h" -#import "FIRInstallationsStore.h" +#import "FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h" +#import "FirebaseInstallations/Source/Library/FIRInstallationsItem.h" +#import "FirebaseInstallations/Source/Library/FIRInstallationsLogger.h" +#import "FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.h" +#import "FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.h" +#import "FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.h" +#import "FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.h" +#import "FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.h" -#import "FIRInstallationsHTTPError.h" -#import "FIRInstallationsStoredAuthToken.h" +#import "FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.h" +#import "FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.h" const NSNotificationName FIRInstallationIDDidChangeNotification = @"FIRInstallationIDDidChangeNotification"; @@ -44,6 +44,8 @@ NSString *const kFIRInstallationIDDidChangeNotificationAppNameKey = NSTimeInterval const kFIRInstallationsTokenExpirationThreshold = 60 * 60; // 1 hour. +static NSString *const kKeychainService = @"com.firebase.FIRInstallations.installations"; + @interface FIRInstallationsIDController () @property(nonatomic, readonly) NSString *appID; @property(nonatomic, readonly) NSString *appName; @@ -71,9 +73,9 @@ NSTimeInterval const kFIRInstallationsTokenExpirationThreshold = 60 * 60; // 1 APIKey:(NSString *)APIKey projectID:(NSString *)projectID GCMSenderID:(NSString *)GCMSenderID - accessGroup:(NSString *)accessGroup { - GULKeychainStorage *secureStorage = - [[GULKeychainStorage alloc] initWithService:@"com.firebase.FIRInstallations.installations"]; + accessGroup:(nullable NSString *)accessGroup { + NSString *serviceName = [FIRInstallationsIDController keychainServiceWithAppID:appID]; + GULKeychainStorage *secureStorage = [[GULKeychainStorage alloc] initWithService:serviceName]; FIRInstallationsStore *installationsStore = [[FIRInstallationsStore alloc] initWithSecureStorage:secureStorage accessGroup:accessGroup]; @@ -256,9 +258,9 @@ NSTimeInterval const kFIRInstallationsTokenExpirationThreshold = 60 * 60; // 1 if ([self doesRegistrationErrorRequireConfigChange:error]) { FIRLogError(kFIRLoggerInstallations, kFIRInstallationsMessageCodeInvalidFirebaseConfiguration, - @"Firebase Installation registration failed for app with name: %@, error: " + @"Firebase Installation registration failed for app with name: %@, error:\n" @"%@\nPlease make sure you use valid GoogleService-Info.plist", - self.appName, error); + self.appName, error.userInfo[NSLocalizedFailureReasonErrorKey]); } }) .then(^id(FIRInstallationsItem *registeredInstallation) { @@ -456,4 +458,23 @@ NSTimeInterval const kFIRInstallationsTokenExpirationThreshold = 60 * 60; // 1 return [self.appName isEqualToString:kFIRDefaultAppName]; } +#pragma mark - Keychain + ++ (NSString *)keychainServiceWithAppID:(NSString *)appID { +#if TARGET_OS_MACCATALYST || TARGET_OS_OSX + // We need to keep service name unique per application on macOS. + // Applications on macOS may request access to Keychain items stored by other applications. It + // means that when the app looks up for a relevant Keychain item in the service scope it will + // request user password to grant access to the Keychain if there are other Keychain items from + // other applications stored under the same Keychain Service. + return [kKeychainService stringByAppendingFormat:@".%@", appID]; +#else + // Use a constant Keychain service for non-macOS because: + // 1. Keychain items cannot be shared between apps until configured specifically so the service + // name collisions are not a concern + // 2. We don't want to change the service name to avoid doing a migration. + return kKeychainService; +#endif +} + @end diff --git a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.m b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.m index dfccfe36d..7ae8781f8 100644 --- a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.m +++ b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.m @@ -14,7 +14,7 @@ * limitations under the License. */ -#import "FIRInstallationsSingleOperationPromiseCache.h" +#import "FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.h" #if __has_include(<FBLPromises/FBLPromises.h>) #import <FBLPromises/FBLPromises.h> diff --git a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.m b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.m index 46f58dba7..72041000d 100644 --- a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.m +++ b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.m @@ -14,9 +14,9 @@ * limitations under the License. */ -#import "FIRInstallationsStore.h" +#import "FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.h" -#import <GoogleUtilities/GULUserDefaults.h> +#import "GoogleUtilities/UserDefaults/Private/GULUserDefaults.h" #if __has_include(<FBLPromises/FBLPromises.h>) #import <FBLPromises/FBLPromises.h> @@ -24,11 +24,11 @@ #import "FBLPromises.h" #endif -#import <GoogleUtilities/GULKeychainStorage.h> +#import "GoogleUtilities/Environment/Private/GULKeychainStorage.h" -#import "FIRInstallationsErrorUtil.h" -#import "FIRInstallationsItem.h" -#import "FIRInstallationsStoredItem.h" +#import "FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h" +#import "FirebaseInstallations/Source/Library/FIRInstallationsItem.h" +#import "FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.h" NSString *const kFIRInstallationsStoreUserDefaultsID = @"com.firebase.FIRInstallations"; diff --git a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.m b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.m index b21f6dd23..8236f2a63 100644 --- a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.m +++ b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.m @@ -14,9 +14,9 @@ * limitations under the License. */ -#import "FIRInstallationsStoredAuthToken.h" +#import "FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.h" -#import "FIRInstallationsLogger.h" +#import "FirebaseInstallations/Source/Library/FIRInstallationsLogger.h" NSString *const kFIRInstallationsStoredAuthTokenStatusKey = @"status"; NSString *const kFIRInstallationsStoredAuthTokenTokenKey = @"token"; diff --git a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.h b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.h index 4926588c2..83902deb0 100644 --- a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.h +++ b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.h @@ -16,7 +16,7 @@ #import <Foundation/Foundation.h> -#import "FIRInstallationsStatus.h" +#import "FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsStatus.h" @class FIRInstallationsStoredAuthToken; @class FIRInstallationsStoredIIDCheckin; diff --git a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.m b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.m index 0c7655c39..4e199559a 100644 --- a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.m +++ b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.m @@ -14,10 +14,10 @@ * limitations under the License. */ -#import "FIRInstallationsStoredItem.h" +#import "FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.h" -#import "FIRInstallationsLogger.h" -#import "FIRInstallationsStoredAuthToken.h" +#import "FirebaseInstallations/Source/Library/FIRInstallationsLogger.h" +#import "FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.h" NSString *const kFIRInstallationsStoredItemFirebaseInstallationIDKey = @"firebaseInstallationID"; NSString *const kFIRInstallationsStoredItemRefreshTokenKey = @"refreshToken"; diff --git a/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Private/FirebaseInstallationsInternal.h b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Private/FirebaseInstallationsInternal.h new file mode 100644 index 000000000..cd40f1723 --- /dev/null +++ b/ios/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Private/FirebaseInstallationsInternal.h @@ -0,0 +1,23 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// An umbrella header, for any other libraries in this repo to access Firebase +// Installations Public headers. Any package manager complexity should be +// handled here. + +#if SWIFT_PACKAGE +@import FirebaseInstallations; +#else +#import <FirebaseInstallations/FirebaseInstallations.h> +#endif diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h b/ios/Pods/FirebaseInstallations/GoogleUtilities/Environment/Private/GULAppEnvironmentUtil.h similarity index 91% rename from ios/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h rename to ios/Pods/FirebaseInstallations/GoogleUtilities/Environment/Private/GULAppEnvironmentUtil.h index d5502647c..2fb162261 100644 --- a/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h +++ b/ios/Pods/FirebaseInstallations/GoogleUtilities/Environment/Private/GULAppEnvironmentUtil.h @@ -41,6 +41,7 @@ + (BOOL)isAppExtension; /// @return Returns @YES when is run on iOS version greater or equal to 7.0 -+ (BOOL)isIOS7OrHigher; ++ (BOOL)isIOS7OrHigher DEPRECATED_MSG_ATTRIBUTE( + "Always `YES` because only iOS 8 and higher supported. The method will be removed."); @end diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULHeartbeatDateStorage.h b/ios/Pods/FirebaseInstallations/GoogleUtilities/Environment/Private/GULHeartbeatDateStorage.h similarity index 100% rename from ios/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULHeartbeatDateStorage.h rename to ios/Pods/FirebaseInstallations/GoogleUtilities/Environment/Private/GULHeartbeatDateStorage.h diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULKeychainStorage.h b/ios/Pods/FirebaseInstallations/GoogleUtilities/Environment/Private/GULKeychainStorage.h similarity index 100% rename from ios/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULKeychainStorage.h rename to ios/Pods/FirebaseInstallations/GoogleUtilities/Environment/Private/GULKeychainStorage.h diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULKeychainUtils.h b/ios/Pods/FirebaseInstallations/GoogleUtilities/Environment/Private/GULKeychainUtils.h similarity index 100% rename from ios/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULKeychainUtils.h rename to ios/Pods/FirebaseInstallations/GoogleUtilities/Environment/Private/GULKeychainUtils.h diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULSecureCoding.h b/ios/Pods/FirebaseInstallations/GoogleUtilities/Environment/Private/GULSecureCoding.h similarity index 100% rename from ios/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULSecureCoding.h rename to ios/Pods/FirebaseInstallations/GoogleUtilities/Environment/Private/GULSecureCoding.h diff --git a/ios/Pods/FirebaseInstallations/GoogleUtilities/UserDefaults/Private/GULUserDefaults.h b/ios/Pods/FirebaseInstallations/GoogleUtilities/UserDefaults/Private/GULUserDefaults.h new file mode 100644 index 000000000..0d0478184 --- /dev/null +++ b/ios/Pods/FirebaseInstallations/GoogleUtilities/UserDefaults/Private/GULUserDefaults.h @@ -0,0 +1,110 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +/// A thread-safe user defaults that uses C functions from CFPreferences.h instead of +/// `NSUserDefaults`. This is to avoid sending an `NSNotification` when it's changed from a +/// background thread to avoid crashing. // TODO: Insert radar number here. +@interface GULUserDefaults : NSObject + +/// A shared user defaults similar to +[NSUserDefaults standardUserDefaults] and accesses the same +/// data of the standardUserDefaults. ++ (GULUserDefaults *)standardUserDefaults; + +/// Initializes preferences with a suite name that is the same with the NSUserDefaults' suite name. +/// Both of CFPreferences and NSUserDefaults share the same plist file so their data will exactly +/// the same. +/// +/// @param suiteName The name of the suite of the user defaults. +- (instancetype)initWithSuiteName:(nullable NSString *)suiteName; + +#pragma mark - Getters + +/// Searches the receiver's search list for a default with the key 'defaultName' and return it. If +/// another process has changed defaults in the search list, NSUserDefaults will automatically +/// update to the latest values. If the key in question has been marked as ubiquitous via a Defaults +/// Configuration File, the latest value may not be immediately available, and the registered value +/// will be returned instead. +- (nullable id)objectForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it will return nil if the value is not an NSArray. +- (nullable NSArray *)arrayForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it will return nil if the value +/// is not an NSDictionary. +- (nullable NSDictionary<NSString *, id> *)dictionaryForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it will convert NSNumber values to their NSString +/// representation. If a non-string non-number value is found, nil will be returned. +- (nullable NSString *)stringForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it converts the returned value to an NSInteger. If the +/// value is an NSNumber, the result of -integerValue will be returned. If the value is an NSString, +/// it will be converted to NSInteger if possible. If the value is a boolean, it will be converted +/// to either 1 for YES or 0 for NO. If the value is absent or can't be converted to an integer, 0 +/// will be returned. +- (NSInteger)integerForKey:(NSString *)defaultName; + +/// Similar to -integerForKey:, except that it returns a float, and boolean values will not be +/// converted. +- (float)floatForKey:(NSString *)defaultName; + +/// Similar to -integerForKey:, except that it returns a double, and boolean values will not be +/// converted. +- (double)doubleForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it converts the returned value to a BOOL. If the value +/// is an NSNumber, NO will be returned if the value is 0, YES otherwise. If the value is an +/// NSString, values of "YES" or "1" will return YES, and values of "NO", "0", or any other string +/// will return NO. If the value is absent or can't be converted to a BOOL, NO will be returned. +- (BOOL)boolForKey:(NSString *)defaultName; + +#pragma mark - Setters + +/// Immediately stores a value (or removes the value if `nil` is passed as the value) for the +/// provided key in the search list entry for the receiver's suite name in the current user and any +/// host, then asynchronously stores the value persistently, where it is made available to other +/// processes. +- (void)setObject:(nullable id)value forKey:(NSString *)defaultName; + +/// Equivalent to -setObject:forKey: except that the value is converted from a float to an NSNumber. +- (void)setFloat:(float)value forKey:(NSString *)defaultName; + +/// Equivalent to -setObject:forKey: except that the value is converted from a double to an +/// NSNumber. +- (void)setDouble:(double)value forKey:(NSString *)defaultName; + +/// Equivalent to -setObject:forKey: except that the value is converted from an NSInteger to an +/// NSNumber. +- (void)setInteger:(NSInteger)value forKey:(NSString *)defaultName; + +/// Equivalent to -setObject:forKey: except that the value is converted from a BOOL to an NSNumber. +- (void)setBool:(BOOL)value forKey:(NSString *)defaultName; + +#pragma mark - Removing Defaults + +/// Equivalent to -[... setObject:nil forKey:defaultName] +- (void)removeObjectForKey:(NSString *)defaultName; + +#pragma mark - Save data + +/// Blocks the calling thread until all in-progress set operations have completed. +- (void)synchronize; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/FirebaseInstallations/README.md b/ios/Pods/FirebaseInstallations/README.md index b04a27099..1d9f0f678 100644 --- a/ios/Pods/FirebaseInstallations/README.md +++ b/ios/Pods/FirebaseInstallations/README.md @@ -1,18 +1,29 @@ -# Firebase iOS Open Source Development - [![Actions Status][gh-auth-badge]][gh-actions] - [![Actions Status][gh-core-badge]][gh-actions] - [![Actions Status][gh-datatransport-badge]][gh-actions] - [![Actions Status][gh-dynamiclinks-badge]][gh-actions] - [![Actions Status][gh-firebasepod-badge]][gh-actions] - [![Actions Status][gh-firestore-badge]][gh-actions] - [![Actions Status][gh-interop-badge]][gh-actions] - [![Actions Status][gh-messaging-badge]][gh-actions] - [![Actions Status][gh-storage-badge]][gh-actions] - [![Actions Status][gh-symbolcollision-badge]][gh-actions] - [![Actions Status][gh-zip-badge]][gh-actions] - [![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) +[![Version](https://img.shields.io/cocoapods/v/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) -This repository contains all Firebase iOS SDK source except FirebaseAnalytics, +[![Actions Status][gh-abtesting-badge]][gh-actions] +[![Actions Status][gh-auth-badge]][gh-actions] +[![Actions Status][gh-core-badge]][gh-actions] +[![Actions Status][gh-crashlytics-badge]][gh-actions] +[![Actions Status][gh-database-badge]][gh-actions] +[![Actions Status][gh-datatransport-badge]][gh-actions] +[![Actions Status][gh-dynamiclinks-badge]][gh-actions] +[![Actions Status][gh-firebasepod-badge]][gh-actions] +[![Actions Status][gh-firestore-badge]][gh-actions] +[![Actions Status][gh-functions-badge]][gh-actions] +[![Actions Status][gh-inappmessaging-badge]][gh-actions] +[![Actions Status][gh-interop-badge]][gh-actions] +[![Actions Status][gh-messaging-badge]][gh-actions] +[![Actions Status][gh-remoteconfig-badge]][gh-actions] +[![Actions Status][gh-storage-badge]][gh-actions] +[![Actions Status][gh-symbolcollision-badge]][gh-actions] +[![Actions Status][gh-zip-badge]][gh-actions] +[![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +# Firebase Apple Open Source Development + +This repository contains all Apple platform Firebase SDK source except FirebaseAnalytics, FirebasePerformance, and FirebaseML. The repository also includes GoogleUtilities source. The @@ -87,7 +98,7 @@ Instructions for installing binary frameworks via To develop Firebase software in this repository, ensure that you have at least the following software: - * Xcode 10.1 (or later) + * Xcode 10.3 (or later) * CocoaPods 1.7.2 (or later) * [CocoaPods generate](https://github.com/square/cocoapods-generate) @@ -118,6 +129,10 @@ Firestore has a self contained Xcode project. See See [AddNewPod.md](AddNewPod.md). +### Managing Headers and Imports + +See [HeadersImports.md](HeadersImports.md). + ### Code Formatting To ensure that the code is formatted consistently, run the script @@ -125,21 +140,13 @@ To ensure that the code is formatted consistently, run the script before creating a PR. Travis will verify that any code changes are done in a style compliant way. Install -`clang-format` and `swiftformat`. -These commands will get the right versions: +`clang-format` and `swiftformat`: ``` -brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c6f1cbd/Formula/clang-format.rb -brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c13eda8/Formula/swiftformat.rb +brew install clang-format +brew install swiftformat ``` -Note: if you already have a newer version of these installed you may need to -`brew switch` to this version. - -To update this section, find the versions of clang-format and swiftformat.rb to -match the versions in the CI failure logs -[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). - ### Running Unit Tests Select a scheme and press Command-u to build a component and run its unit tests. @@ -162,12 +169,7 @@ files without real values, but can be replaced with real plist files. To get you 2. Create a new Firebase project, if you don't already have one 3. For each sample app you want to test, create a new Firebase app with the sample app's bundle identifier (e.g. `com.google.Database-Example`) -4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file -(e.g. in [Example/Database/App/](Example/Database/App/)); - -Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require -special Apple capabilities, and you will have to change the sample app to use a unique bundle -identifier that you can control in your own Apple Developer account. +4. Download the resulting `GoogleService-Info.plist` and add it to the Xcode project. ## Specific Component Instructions See the sections below for any special instructions for those components. @@ -180,8 +182,16 @@ building and running the FirebaseAuth pod along with various samples and tests. ### Firebase Database -To run the Database Integration tests, make your database authentication rules -[public](https://firebase.google.com/docs/database/security/quickstart). +The Firebase Database Integration tests can be run against a locally running Database Emulator +or against a production instance. + +To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before +running the integration test. + +To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to +`FirebaseDatabase/Tests/Resources/GoogleService-Info.plist`. Your Security Rule must be set to +[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are +running. ### Firebase Storage @@ -269,14 +279,20 @@ Your use of Firebase is governed by the [Terms of Service for Firebase Services](https://firebase.google.com/terms/). [gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg [gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg [gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg +[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg [gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg [gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg [gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg [gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg +[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg +[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg [gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg [gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg +[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg [gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg [gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg [gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/ios/Pods/Flipper/README.md b/ios/Pods/Flipper/README.md index 47df05320..b028c7ec3 100644 --- a/ios/Pods/Flipper/README.md +++ b/ios/Pods/Flipper/README.md @@ -38,19 +38,19 @@ Both Flipper's desktop app and native mobile SDKs are open-source and MIT licens This repository includes all parts of Flipper. This includes: -* Flipper's desktop app built using [Electron](https://electronjs.org) (`/src`) +* Flipper's desktop app built using [Electron](https://electronjs.org) (`/desktop`) * native Flipper SDKs for iOS (`/iOS`) * native Flipper SDKs for Android (`/android`) * Plugins: - * Logs (`/src/device-plugins/logs`) - * Layout inspector (`/src/plugins/layout`) - * Network inspector (`/src/plugins/network`) - * Shared Preferences/NSUserDefaults inspector (`/src/plugins/shared_preferences`) + * Logs (`/desktop/src/device-plugins/logs`) + * Layout inspector (`/desktop/plugins/layout`) + * Network inspector (`/desktop/plugins/network`) + * Shared Preferences/NSUserDefaults inspector (`/desktop/plugins/shared_preferences`) * website and documentation (`/website` / `/docs`) # Getting started -Please refer to our [Getting Started guide](https://fbflipper.com/docs/getting-started.html) to set up Flipper. +Please refer to our [Getting Started guide](https://fbflipper.com/docs/getting-started/index) to set up Flipper. ## Requirements @@ -66,7 +66,7 @@ Please refer to our [Getting Started guide](https://fbflipper.com/docs/getting-s ``` git clone https://github.com/facebook/flipper.git -cd flipper +cd flipper/desktop yarn yarn start ``` @@ -119,9 +119,9 @@ Alternatively, the app can be started on `iOS` by running `yarn ios`. Older yarn versions might show an error / hang with the message 'Waiting for the other yarn instance to finish'. If that happens, run the command `yarn` first separately in the directory `react-native/react-native-flipper`. -## Documentation +# Documentation -Find the full documentation for this project at [fbflipper.com](https://fbflipper.com/docs). +Find the full documentation for this project at [fbflipper.com](https://fbflipper.com/). Our documentation is built with [Docusaurus](https://docusaurus.io/). You can build it locally by running this: diff --git a/ios/Pods/Flipper/xplat/Flipper/FlipperClient.cpp b/ios/Pods/Flipper/xplat/Flipper/FlipperClient.cpp index dc3325e54..6b897d581 100644 --- a/ios/Pods/Flipper/xplat/Flipper/FlipperClient.cpp +++ b/ios/Pods/Flipper/xplat/Flipper/FlipperClient.cpp @@ -69,12 +69,6 @@ void FlipperClient::addPlugin(std::shared_ptr<FlipperPlugin> plugin) { step->complete(); if (connected_) { refreshPlugins(); - if (plugin->runInBackground()) { - auto& conn = connections_[plugin->identifier()]; - conn = std::make_shared<FlipperConnectionImpl>( - socket_.get(), plugin->identifier()); - plugin->didConnect(conn); - } } }); } @@ -95,27 +89,6 @@ void FlipperClient::removePlugin(std::shared_ptr<FlipperPlugin> plugin) { }); } -void FlipperClient::startBackgroundPlugins() { - std::cout << "Activating Background Plugins..." << std::endl; - for (std::map<std::string, std::shared_ptr<FlipperPlugin>>::iterator it = - plugins_.begin(); - it != plugins_.end(); - ++it) { - std::cout << it->first << std::endl; - if (it->second.get()->runInBackground()) { - try { - auto& conn = connections_[it->first]; - conn = - std::make_shared<FlipperConnectionImpl>(socket_.get(), it->first); - it->second.get()->didConnect(conn); - } catch (std::exception& e) { - log("Exception starting background plugin: " + it->first + ". " + - e.what()); - } - } - } -} - std::shared_ptr<FlipperPlugin> FlipperClient::getPlugin( const std::string& identifier) { std::lock_guard<std::mutex> lock(mutex_); @@ -130,6 +103,15 @@ bool FlipperClient::hasPlugin(const std::string& identifier) { return plugins_.find(identifier) != plugins_.end(); } +void FlipperClient::connect(std::shared_ptr<FlipperPlugin> plugin) { + if (connections_.find(plugin->identifier()) == connections_.end()) { + auto& conn = connections_[plugin->identifier()]; + conn = std::make_shared<FlipperConnectionImpl>( + socket_.get(), plugin->identifier()); + plugin->didConnect(conn); + } +} + void FlipperClient::disconnect(std::shared_ptr<FlipperPlugin> plugin) { const auto& conn = connections_.find(plugin->identifier()); if (conn != connections_.end()) { @@ -151,7 +133,6 @@ void FlipperClient::onConnected() { std::lock_guard<std::mutex> lock(mutex_); connected_ = true; - startBackgroundPlugins(); }); } @@ -189,6 +170,18 @@ void FlipperClient::onMessageReceived( return; } + if (method == "getBackgroundPlugins") { + dynamic identifiers = dynamic::array(); + for (const auto& elem : plugins_) { + if (elem.second->runInBackground()) { + identifiers.push_back(elem.first); + } + } + dynamic response = dynamic::object("plugins", identifiers); + responder->success(response); + return; + } + if (method == "init") { const auto identifier = params["plugin"].getString(); if (plugins_.find(identifier) == plugins_.end()) { @@ -200,12 +193,7 @@ void FlipperClient::onMessageReceived( return; } const auto plugin = plugins_.at(identifier); - if (!plugin.get()->runInBackground()) { - auto& conn = connections_[plugin->identifier()]; - conn = std::make_shared<FlipperConnectionImpl>( - socket_.get(), plugin->identifier()); - plugin->didConnect(conn); - } + connect(plugin); return; } @@ -220,9 +208,7 @@ void FlipperClient::onMessageReceived( return; } const auto plugin = plugins_.at(identifier); - if (!plugin.get()->runInBackground()) { - disconnect(plugin); - } + disconnect(plugin); return; } diff --git a/ios/Pods/Flipper/xplat/Flipper/FlipperClient.h b/ios/Pods/Flipper/xplat/Flipper/FlipperClient.h index 1c107d6a6..28071e818 100644 --- a/ios/Pods/Flipper/xplat/Flipper/FlipperClient.h +++ b/ios/Pods/Flipper/xplat/Flipper/FlipperClient.h @@ -108,8 +108,8 @@ class FlipperClient : public FlipperConnectionManager::Callbacks { std::mutex mutex_; std::shared_ptr<FlipperState> flipperState_; + void connect(std::shared_ptr<FlipperPlugin> plugin); void disconnect(std::shared_ptr<FlipperPlugin> plugin); - void startBackgroundPlugins(); std::string callstack(); void handleError(std::exception& e); }; diff --git a/ios/Pods/Flipper/xplat/Flipper/FlipperConnectionManagerImpl.cpp b/ios/Pods/Flipper/xplat/Flipper/FlipperConnectionManagerImpl.cpp index 9cbcfb5e9..c10fab364 100644 --- a/ios/Pods/Flipper/xplat/Flipper/FlipperConnectionManagerImpl.cpp +++ b/ios/Pods/Flipper/xplat/Flipper/FlipperConnectionManagerImpl.cpp @@ -35,7 +35,7 @@ static constexpr int maxPayloadSize = 0xFFFFFF; // Not a public-facing version number. // Used for compatibility checking with desktop flipper. // To be bumped for every core platform interface change. -static constexpr int sdkVersion = 3; +static constexpr int sdkVersion = 4; namespace facebook { namespace flipper { @@ -127,34 +127,36 @@ void FlipperConnectionManagerImpl::startSync() { : "Establish main connection"); try { if (isClientSetupStep) { - doCertificateExchange(); + bool success = doCertificateExchange(); + if (!success) { + reconnect(); + return; + } } else { - connectSecurely(); + if (!connectSecurely()) { + // The expected code path when flipper desktop is not running. + // Don't count as a failed attempt, or it would invalidate the + // connection files for no reason. On iOS devices, we can always connect + // to the local port forwarding server even when it can't connect to + // flipper. In that case we get a Network error instead of a Port not + // open error, so we treat them the same. + step->fail( + "No route to flipper found. Is flipper desktop running? Retrying..."); + reconnect(); + } } step->complete(); } catch (const folly::AsyncSocketException& e) { - if (e.getType() == folly::AsyncSocketException::NOT_OPEN || - e.getType() == folly::AsyncSocketException::NETWORK_ERROR) { - // The expected code path when flipper desktop is not running. - // Don't count as a failed attempt, or it would invalidate the connection - // files for no reason. On iOS devices, we can always connect to the local - // port forwarding server even when it can't connect to flipper. In that - // case we get a Network error instead of a Port not open error, so we - // treat them the same. - step->fail( - "No route to flipper found. Is flipper desktop running? Retrying..."); + if (e.getType() == folly::AsyncSocketException::SSL_ERROR) { + auto message = std::string(e.what()) + + "\nMake sure the date and time of your device is up to date."; + log(message); + step->fail(message); } else { - if (e.getType() == folly::AsyncSocketException::SSL_ERROR) { - auto message = std::string(e.what()) + - "\nMake sure the date and time of your device is up to date."; - log(message); - step->fail(message); - } else { - log(e.what()); - step->fail(e.what()); - } - failedConnectionAttempts_++; + log(e.what()); + step->fail(e.what()); } + failedConnectionAttempts_++; reconnect(); } catch (const std::exception& e) { log(e.what()); @@ -164,7 +166,7 @@ void FlipperConnectionManagerImpl::startSync() { } } -void FlipperConnectionManagerImpl::doCertificateExchange() { +bool FlipperConnectionManagerImpl::doCertificateExchange() { rsocket::SetupParameters parameters; folly::SocketAddress address; @@ -175,7 +177,7 @@ void FlipperConnectionManagerImpl::doCertificateExchange() { auto connectingInsecurely = flipperState_->start("Connect insecurely"); connectionIsTrusted_ = false; - client_ = + auto newClient = rsocket::RSocket::createConnectedClient( std::make_unique<rsocket::TcpConnectionFactory>( *connectionEventBase_->getEventBase(), std::move(address)), @@ -184,7 +186,22 @@ void FlipperConnectionManagerImpl::doCertificateExchange() { std::chrono::seconds(connectionKeepaliveSeconds), // keepaliveInterval nullptr, // stats std::make_shared<ConnectionEvents>(this)) + .thenError<folly::AsyncSocketException>([](const auto& e) { + if (e.getType() == folly::AsyncSocketException::NOT_OPEN || + e.getType() == folly::AsyncSocketException::NETWORK_ERROR) { + // This is the state where no Flipper desktop client is connected. + // We don't want an exception thrown here. + return std::unique_ptr<rsocket::RSocketClient>(nullptr); + } + throw e; + }) .get(); + + if (newClient.get() == nullptr) { + return false; + } + + client_ = std::move(newClient); connectingInsecurely->complete(); auto resettingState = flipperState_->start("Reset state"); @@ -192,9 +209,10 @@ void FlipperConnectionManagerImpl::doCertificateExchange() { resettingState->complete(); requestSignedCertFromFlipper(); + return true; } -void FlipperConnectionManagerImpl::connectSecurely() { +bool FlipperConnectionManagerImpl::connectSecurely() { rsocket::SetupParameters parameters; folly::SocketAddress address; @@ -216,7 +234,8 @@ void FlipperConnectionManagerImpl::connectSecurely() { contextStore_->getSSLContext(); auto connectingSecurely = flipperState_->start("Connect securely"); connectionIsTrusted_ = true; - client_ = + + auto newClient = rsocket::RSocket::createConnectedClient( std::make_unique<rsocket::TcpConnectionFactory>( *connectionEventBase_->getEventBase(), @@ -227,9 +246,24 @@ void FlipperConnectionManagerImpl::connectSecurely() { std::chrono::seconds(connectionKeepaliveSeconds), // keepaliveInterval nullptr, // stats std::make_shared<ConnectionEvents>(this)) + .thenError<folly::AsyncSocketException>([](const auto& e) { + if (e.getType() == folly::AsyncSocketException::NOT_OPEN || + e.getType() == folly::AsyncSocketException::NETWORK_ERROR) { + // This is the state where no Flipper desktop client is connected. + // We don't want an exception thrown here. + return std::unique_ptr<rsocket::RSocketClient>(nullptr); + } + throw e; + }) .get(); + if (newClient.get() == nullptr) { + return false; + } + + client_ = std::move(newClient); connectingSecurely->complete(); failedConnectionAttempts_ = 0; + return true; } void FlipperConnectionManagerImpl::reconnect() { diff --git a/ios/Pods/Flipper/xplat/Flipper/FlipperConnectionManagerImpl.h b/ios/Pods/Flipper/xplat/Flipper/FlipperConnectionManagerImpl.h index 9763748ce..004c5be31 100644 --- a/ios/Pods/Flipper/xplat/Flipper/FlipperConnectionManagerImpl.h +++ b/ios/Pods/Flipper/xplat/Flipper/FlipperConnectionManagerImpl.h @@ -68,8 +68,8 @@ class FlipperConnectionManagerImpl : public FlipperConnectionManager { std::shared_ptr<ConnectionContextStore> contextStore_; void startSync(); - void doCertificateExchange(); - void connectSecurely(); + bool doCertificateExchange(); + bool connectSecurely(); bool isCertificateExchangeNeeded(); void requestSignedCertFromFlipper(); bool isRunningInOwnThread(); diff --git a/ios/Pods/FlipperKit/README.md b/ios/Pods/FlipperKit/README.md index 47df05320..b028c7ec3 100644 --- a/ios/Pods/FlipperKit/README.md +++ b/ios/Pods/FlipperKit/README.md @@ -38,19 +38,19 @@ Both Flipper's desktop app and native mobile SDKs are open-source and MIT licens This repository includes all parts of Flipper. This includes: -* Flipper's desktop app built using [Electron](https://electronjs.org) (`/src`) +* Flipper's desktop app built using [Electron](https://electronjs.org) (`/desktop`) * native Flipper SDKs for iOS (`/iOS`) * native Flipper SDKs for Android (`/android`) * Plugins: - * Logs (`/src/device-plugins/logs`) - * Layout inspector (`/src/plugins/layout`) - * Network inspector (`/src/plugins/network`) - * Shared Preferences/NSUserDefaults inspector (`/src/plugins/shared_preferences`) + * Logs (`/desktop/src/device-plugins/logs`) + * Layout inspector (`/desktop/plugins/layout`) + * Network inspector (`/desktop/plugins/network`) + * Shared Preferences/NSUserDefaults inspector (`/desktop/plugins/shared_preferences`) * website and documentation (`/website` / `/docs`) # Getting started -Please refer to our [Getting Started guide](https://fbflipper.com/docs/getting-started.html) to set up Flipper. +Please refer to our [Getting Started guide](https://fbflipper.com/docs/getting-started/index) to set up Flipper. ## Requirements @@ -66,7 +66,7 @@ Please refer to our [Getting Started guide](https://fbflipper.com/docs/getting-s ``` git clone https://github.com/facebook/flipper.git -cd flipper +cd flipper/desktop yarn yarn start ``` @@ -119,9 +119,9 @@ Alternatively, the app can be started on `iOS` by running `yarn ios`. Older yarn versions might show an error / hang with the message 'Waiting for the other yarn instance to finish'. If that happens, run the command `yarn` first separately in the directory `react-native/react-native-flipper`. -## Documentation +# Documentation -Find the full documentation for this project at [fbflipper.com](https://fbflipper.com/docs). +Find the full documentation for this project at [fbflipper.com](https://fbflipper.com/). Our documentation is built with [Docusaurus](https://docusaurus.io/). You can build it locally by running this: diff --git a/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h b/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h index 6cb5f6251..c27aaf46b 100644 --- a/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h +++ b/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h @@ -10,6 +10,7 @@ #import <Foundation/Foundation.h> #import <FlipperKit/FlipperPlugin.h> +#import <FlipperKit/SKMacros.h> #import "SKDescriptorMapper.h" #import "SKInvalidation.h" @@ -29,4 +30,7 @@ @end +/** Exposed for tests only. */ +SK_EXTERN_C dispatch_queue_t SKLayoutPluginSerialBackgroundQueue(void); + #endif diff --git a/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.mm b/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.mm index d64db0b0d..2ef733b97 100644 --- a/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.mm +++ b/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.mm @@ -24,9 +24,8 @@ NSMapTable<NSString*, id>* _trackedObjects; NSString* _lastHighlightedNode; NSMutableSet* _invalidObjects; - Boolean _invalidateMessageQueued; - NSDate* _lastInvalidateMessage; - std::mutex invalidObjectsMutex; + BOOL _invalidateMessageQueued; + std::mutex _invalidObjectsMutex; id<NSObject> _rootNode; id<SKTapListener> _tapListener; @@ -49,10 +48,7 @@ if (self = [super init]) { _descriptorMapper = mapper; _trackedObjects = [NSMapTable strongToWeakObjectsMapTable]; - _lastHighlightedNode = nil; _invalidObjects = [NSMutableSet new]; - _invalidateMessageQueued = false; - _lastInvalidateMessage = [NSDate date]; _rootNode = rootNode; _tapListener = tapListener; @@ -95,15 +91,6 @@ responder); }]; - [connection receive:@"getAllNodes" - withBlock:^(NSDictionary* params, id<FlipperResponder> responder) { - FlipperPerformBlockOnMainThread( - ^{ - [weakSelf onCallGetAllNodesWithResponder:responder]; - }, - responder); - }]; - [connection receive:@"getNodes" withBlock:^(NSDictionary* params, id<FlipperResponder> responder) { FlipperPerformBlockOnMainThread( @@ -189,19 +176,6 @@ [responder success:rootNode]; } -- (void)populateAllNodesFromNode:(nonnull NSString*)identifier - inDictionary: - (nonnull NSMutableDictionary<NSString*, NSDictionary*>*) - mutableDict { - NSDictionary* nodeDict = [self getNode:identifier]; - mutableDict[identifier] = nodeDict; - NSArray* arr = nodeDict[@"children"]; - for (NSString* childIdentifier in arr) { - [self populateAllNodesFromNode:childIdentifier inDictionary:mutableDict]; - } - return; -} - - (void)populateAllNodesFromNode:(nonnull NSString*)identifier inArray:(nonnull NSMutableArray<NSDictionary*>*) mutableArray { @@ -216,26 +190,6 @@ } } -- (void)onCallGetAllNodesWithResponder:(nonnull id<FlipperResponder>)responder { - NSMutableArray<NSDictionary*>* allNodes = @[].mutableCopy; - NSString* identifier = [self trackObject:_rootNode]; - NSDictionary* rootNode = [self getNode:identifier]; - if (!rootNode) { - return [responder error:@{ - @"error" : [NSString - stringWithFormat: - @"getNode returned nil for the rootNode %@, while getting all the nodes", - identifier] - }]; - } - [allNodes addObject:rootNode]; - NSMutableDictionary* allNodesDict = @{}.mutableCopy; - [self populateAllNodesFromNode:identifier inDictionary:allNodesDict]; - [responder success:@{ - @"allNodes" : @{@"rootElement" : identifier, @"elements" : allNodesDict} - }]; -} - - (NSMutableArray*)getChildrenForNode:(id)node withDescriptor:(SKNodeDescriptor*)descriptor { NSMutableArray* children = [NSMutableArray new]; @@ -262,7 +216,10 @@ [elements addObject:node]; } - [responder success:@{@"elements" : elements}]; + // Converting to folly::dynamic is expensive, do it on a bg queue: + dispatch_async(SKLayoutPluginSerialBackgroundQueue(), ^{ + [responder success:@{@"elements" : elements}]; + }); } - (void)onCallSetData:(NSString*)objectId @@ -399,36 +356,37 @@ [descriptor invalidateNode:node]; // Collect invalidate messages before sending in a batch - std::lock_guard<std::mutex> lock(invalidObjectsMutex); + std::lock_guard<std::mutex> lock(_invalidObjectsMutex); [_invalidObjects addObject:nodeId]; if (_invalidateMessageQueued) { return; } - _invalidateMessageQueued = true; + _invalidateMessageQueued = YES; - if (_lastInvalidateMessage.timeIntervalSinceNow < -1) { - dispatch_after( - dispatch_time(DISPATCH_TIME_NOW, 500 * NSEC_PER_MSEC), - dispatch_get_main_queue(), - ^{ - [self reportInvalidatedObjects]; - }); - } + dispatch_after( + dispatch_time(DISPATCH_TIME_NOW, 500 * NSEC_PER_MSEC), + dispatch_get_main_queue(), + ^{ + [self _reportInvalidatedObjects]; + }); } -- (void)reportInvalidatedObjects { - std::lock_guard<std::mutex> lock(invalidObjectsMutex); +- (void)invalidateRootNode { + [self invalidateNode:_rootNode]; +} + +- (void)_reportInvalidatedObjects { NSMutableArray* nodes = [NSMutableArray new]; - for (NSString* nodeId in self->_invalidObjects) { - [nodes addObject:[NSDictionary dictionaryWithObject:nodeId forKey:@"id"]]; - } - [self->_connection send:@"invalidate" - withParams:[NSDictionary dictionaryWithObject:nodes - forKey:@"nodes"]]; - self->_lastInvalidateMessage = [NSDate date]; - self->_invalidObjects = [NSMutableSet new]; - self->_invalidateMessageQueued = false; - return; + { // scope mutex acquisition + std::lock_guard<std::mutex> lock(_invalidObjectsMutex); + for (NSString* nodeId in _invalidObjects) { + [nodes addObject:@{@"id" : nodeId}]; + } + _invalidObjects = [NSMutableSet new]; + _invalidateMessageQueued = NO; + } // release mutex before calling out to other code + + [_connection send:@"invalidate" withParams:@{@"nodes" : nodes}]; } - (void)updateNodeReference:(id<NSObject>)node { @@ -567,4 +525,22 @@ @end +/** + Operations like converting NSDictionary to folly::dynamic can be expensive. + Do them on this serial background queue to avoid blocking the main thread. + (Of course, ideally we wouldn't bother with building NSDictionary objects + in the first place, in favor of just using folly::dynamic directly...) + */ +dispatch_queue_t SKLayoutPluginSerialBackgroundQueue(void) { + static dispatch_queue_t queue; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + queue = dispatch_queue_create("flipper.layout.bg", DISPATCH_QUEUE_SERIAL); + // This should be relatively high priority, to prevent Flipper lag. + dispatch_set_target_queue( + queue, dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)); + }); + return queue; +} + #endif diff --git a/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/SKInvalidation.h b/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/SKInvalidation.h index 9b26d599e..f2eee5819 100644 --- a/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/SKInvalidation.h +++ b/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/SKInvalidation.h @@ -10,7 +10,7 @@ @protocol SKInvalidationDelegate - (void)invalidateNode:(id<NSObject>)node; - +- (void)invalidateRootNode; - (void)updateNodeReference:(id<NSObject>)node; @end diff --git a/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/SKNodeDescriptor.h b/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/SKNodeDescriptor.h index c805b8c64..b00289c5e 100644 --- a/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/SKNodeDescriptor.h +++ b/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/SKNodeDescriptor.h @@ -45,9 +45,13 @@ typedef void (^SKNodeUpdateData)(id value); - (NSString*)identifierForNode:(T)node; /** - An ID which is equal between reflowing components is needed to get the - identifier of root node of a tree which need to be invalidated on - FlipperKitLayoutPlugin side. + When the setData command is received from Flipper to change a node's data, + an "invalidateWithData" command is sent back to signal that the node has + changed. However sometimes you may want to invalidate some other node, + not the node that had its data actually modified; usually some ancestor. + This method allows you to substitute another node's identifier. + If you do not override it, the default behavior is to simply return + the node's identifier. */ - (NSString*)identifierForInvalidation:(T)node; diff --git a/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/UIView+SKInvalidation.mm b/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/UIView+SKInvalidation.mm index 3da4f961b..10058261c 100644 --- a/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/UIView+SKInvalidation.mm +++ b/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/UIView+SKInvalidation.mm @@ -9,7 +9,6 @@ #import <UIKit/UIKit.h> #import <objc/runtime.h> - #import "SKInvalidation.h" #import "SKSwizzle.h" #import "UIView+SKInvalidation.h" @@ -31,6 +30,14 @@ FB_LINKABLE(UIView_SKInvalidation) }); } +/** +This function takes in a view and returns true if the view is a UIWindow and its +windowLevel is an alert one otherwise it returns false. +*/ +static auto shouldInvalidateRootNode(UIView* view) -> bool { + return [view isKindOfClass:[UIWindow class]]; +} + - (void)swizzle_setHidden:(BOOL)hidden { [self swizzle_setHidden:hidden]; @@ -47,7 +54,11 @@ FB_LINKABLE(UIView_SKInvalidation) id<SKInvalidationDelegate> delegate = [SKInvalidation sharedInstance].delegate; if (delegate != nil) { - [delegate invalidateNode:view]; + if (shouldInvalidateRootNode(view.superview)) { + [delegate invalidateRootNode]; + return; + } + [delegate invalidateNode:view.superview]; } } @@ -55,6 +66,10 @@ FB_LINKABLE(UIView_SKInvalidation) id<SKInvalidationDelegate> delegate = [SKInvalidation sharedInstance].delegate; if (delegate != nil && self.superview != nil) { + if (shouldInvalidateRootNode(self.superview)) { + [delegate invalidateRootNode]; + return; + } [delegate invalidateNode:self.superview]; } diff --git a/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/descriptors/SKViewDescriptor.mm b/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/descriptors/SKViewDescriptor.mm index 0a6bc759e..44bef0406 100644 --- a/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/descriptors/SKViewDescriptor.mm +++ b/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/descriptors/SKViewDescriptor.mm @@ -453,6 +453,11 @@ static NSDictionary* YGUnitEnumMap = nil; @"Accessibility.accessibilityTraits.UIAccessibilityTraitCausesPageTurn": ^(NSNumber *value) { node.accessibilityTraits = AccessibilityTraitsToggle(node.accessibilityTraits, UIAccessibilityTraitCausesPageTurn, [value boolValue]); }, + @"Accessibility.accessibilityTraits.UIAccessibilityTraitTabBar": ^(NSNumber *value) { + if (@available(iOS 10.0, *)) { + node.accessibilityTraits = AccessibilityTraitsToggle(node.accessibilityTraits, UIAccessibilityTraitTabBar, [value boolValue]); + } + }, @"Accessibility.accessibilityViewIsModal": ^(NSNumber *value) { node.accessibilityViewIsModal = [value boolValue]; }, diff --git a/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitNetworkPlugin/FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.mm b/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitNetworkPlugin/FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.mm index ab17894db..f102aeeaf 100644 --- a/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitNetworkPlugin/FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.mm +++ b/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitNetworkPlugin/FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.mm @@ -78,6 +78,11 @@ } - (void)didObserveResponse:(SKResponseInfo*)response { + // Only track HTTP(S) calls, data URLs cannot be casted to NSHTTPURLResponse + if (![response.response isKindOfClass:[NSHTTPURLResponse class]]) { + return; + } + NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response.response; NSMutableArray<NSDictionary<NSString*, id>*>* headers = [NSMutableArray new]; diff --git a/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitNetworkPlugin/FlipperKitNetworkPlugin/SKResponseInfo.m b/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitNetworkPlugin/FlipperKitNetworkPlugin/SKResponseInfo.m index 1213dd16d..668e03c13 100644 --- a/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitNetworkPlugin/FlipperKitNetworkPlugin/SKResponseInfo.m +++ b/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitNetworkPlugin/FlipperKitNetworkPlugin/SKResponseInfo.m @@ -29,6 +29,11 @@ } + (BOOL)shouldStripReponseBodyWithResponse:(NSURLResponse*)response { + // Only HTTP(S) responses have Content-Type headers + if (![response isKindOfClass:[NSHTTPURLResponse class]]) { + return YES; + } + NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response; NSString* contentType = httpResponse.allHeaderFields[@"content-type"]; if (!contentType) { diff --git a/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.m b/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.m index ced17e17a..d995fb874 100644 --- a/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.m +++ b/ios/Pods/FlipperKit/iOS/Plugins/FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.m @@ -82,6 +82,15 @@ static NSString* const kAppSuiteUserDefaultsName = @"App Suite UserDefaults"; forKey:preferenceName]; [responder success:[sharedPreferences dictionaryRepresentation]]; }]; + + [connection receive:@"deleteSharedPreference" + withBlock:^(NSDictionary* params, id<FlipperResponder> responder) { + NSUserDefaults* sharedPreferences = + [self sharedPreferencesForParams:params]; + NSString* preferenceName = params[@"preferenceName"]; + [sharedPreferences removeObjectForKey:preferenceName]; + [responder success:[sharedPreferences dictionaryRepresentation]]; + }]; } - (void)didDisconnect { diff --git a/ios/Pods/Folly/LICENSE b/ios/Pods/Folly/LICENSE index f433b1a53..48bdb1282 100644 --- a/ios/Pods/Folly/LICENSE +++ b/ios/Pods/Folly/LICENSE @@ -175,3 +175,26 @@ of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + + +Files in folly/external/farmhash licensed as follows + + Copyright (c) 2014 Google, Inc. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. diff --git a/ios/Pods/Folly/README.md b/ios/Pods/Folly/README.md index cd093f41e..f50d687b9 100644 --- a/ios/Pods/Folly/README.md +++ b/ios/Pods/Folly/README.md @@ -66,13 +66,13 @@ is to look at the headers in [top level `folly/` directory](https://github.com/f check the [`docs` folder](folly/docs) for documentation, starting with the [overview](folly/docs/Overview.md). -Folly is published on Github at https://github.com/facebook/folly +Folly is published on GitHub at https://github.com/facebook/folly ### Build Notes #### Dependencies -folly requires gcc 4.9+ and a version of boost compiled with C++14 support. +folly requires gcc 5.1+ and a version of boost compiled with C++14 support. googletest is required to build and run folly's tests. You can download it from https://github.com/google/googletest/archive/release-1.8.0.tar.gz @@ -104,6 +104,11 @@ cmake \ -DCMAKE_LIBRARY_PATH=/alt/lib/path1:/alt/lib/path2 ... ``` +#### Building tests + +By default, building the tests is disabled as part of the CMake `all` target. +To build the tests, specify `-DBUILD_TESTS=ON` to CMake at configure time. + #### Ubuntu 16.04 LTS The following packages are required (feel free to cut and paste the apt-get @@ -127,7 +132,21 @@ sudo apt-get install \ binutils-dev \ libjemalloc-dev \ libssl-dev \ - pkg-config + pkg-config \ + libunwind-dev +``` + +Folly relies on [fmt](https://github.com/fmtlib/fmt) which needs to be installed from source. +The following commands will download, compile, and install fmt. + +``` +git clone https://github.com/fmtlib/fmt.git && cd fmt + +mkdir _build && cd _build +cmake .. + +make -j$(nproc) +sudo make install ``` If advanced debugging functionality is required, use: @@ -139,12 +158,12 @@ sudo apt-get install \ libdwarf-dev ``` -In the folly directory, run: +In the folly directory (e.g. the checkout root or the archive unpack root), run: ``` mkdir _build && cd _build cmake .. make -j $(nproc) - make install + make install # with either sudo or DESTDIR as necessary ``` #### OS X (Homebrew) @@ -154,19 +173,19 @@ folly is available as a Formula and releases may be built via `brew install foll You may also use `folly/build/bootstrap-osx-homebrew.sh` to build against `master`: ``` - cd folly - ./build/bootstrap-osx-homebrew.sh + ./folly/build/bootstrap-osx-homebrew.sh ``` +This will create a build directory `_build` in the top-level. + #### OS X (MacPorts) Install the required packages from MacPorts: ``` sudo port install \ - autoconf \ - automake \ boost \ + cmake \ gflags \ git \ google-glog \ @@ -174,8 +193,9 @@ Install the required packages from MacPorts: libtool \ lz4 \ lzma \ - scons \ + openssl \ snappy \ + xz \ zlib ``` @@ -193,9 +213,10 @@ Download and install folly with the parameters listed below: ``` git clone https://github.com/facebook/folly.git - cd folly/folly - autoreconf -ivf - ./configure CPPFLAGS="-I/opt/local/include" LDFLAGS="-L/opt/local/lib" + cd folly + mkdir _build + cd _build + cmake .. make sudo make install ``` diff --git a/ios/Pods/Folly/folly/AtomicHashArray-inl.h b/ios/Pods/Folly/folly/AtomicHashArray-inl.h index 91a66f61d..d05801160 100644 --- a/ios/Pods/Folly/folly/AtomicHashArray-inl.h +++ b/ios/Pods/Folly/folly/AtomicHashArray-inl.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -21,7 +21,9 @@ #include <type_traits> #include <folly/detail/AtomicHashUtils.h> +#include <folly/detail/Iterators.h> #include <folly/lang/Bits.h> +#include <folly/lang/Exception.h> namespace folly { @@ -58,7 +60,11 @@ AtomicHashArray< numEntries_(0, cacheSize), numPendingEntries_(0, cacheSize), isFull_(0), - numErases_(0) {} + numErases_(0) { + if (capacity == 0) { + throw_exception<std::invalid_argument>("capacity"); + } +} /* * findInternal -- @@ -480,10 +486,10 @@ struct AtomicHashArray< Allocator, ProbeFcn, KeyConvertFcn>::aha_iterator - : boost::iterator_facade< + : detail::IteratorFacade< aha_iterator<ContT, IterVal>, IterVal, - boost::forward_traversal_tag> { + std::forward_iterator_tag> { explicit aha_iterator() : aha_(nullptr) {} // Conversion ctor for interoperability between const_iterator and @@ -514,7 +520,8 @@ struct AtomicHashArray< private: friend class AtomicHashArray; - friend class boost::iterator_core_access; + friend class detail:: + IteratorFacade<aha_iterator, IterVal, std::forward_iterator_tag>; void increment() { ++offset_; diff --git a/ios/Pods/Folly/folly/AtomicHashArray.h b/ios/Pods/Folly/folly/AtomicHashArray.h index 0bb4aa60b..cd62a2329 100644 --- a/ios/Pods/Folly/folly/AtomicHashArray.h +++ b/ios/Pods/Folly/folly/AtomicHashArray.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -34,9 +34,6 @@ #include <atomic> -#include <boost/iterator/iterator_facade.hpp> -#include <boost/noncopyable.hpp> - #include <folly/ThreadCachedInt.h> #include <folly/Utility.h> #include <folly/hash/Hash.h> @@ -102,7 +99,7 @@ template < class Allocator = std::allocator<char>, class ProbeFcn = AtomicHashArrayLinearProbeFcn, class KeyConvertFcn = Identity> -class AtomicHashArray : boost::noncopyable { +class AtomicHashArray { static_assert( (std::is_convertible<KeyT, int32_t>::value || std::is_convertible<KeyT, int64_t>::value || @@ -422,6 +419,9 @@ class AtomicHashArray : boost::noncopyable { double maxLoadFactor, uint32_t cacheSize); + AtomicHashArray(const AtomicHashArray&) = delete; + AtomicHashArray& operator=(const AtomicHashArray&) = delete; + ~AtomicHashArray() = default; inline void unlockCell(value_type* const cell, KeyT newKey) { diff --git a/ios/Pods/Folly/folly/AtomicHashMap-inl.h b/ios/Pods/Folly/folly/AtomicHashMap-inl.h index 65498baa3..f15f07e2b 100644 --- a/ios/Pods/Folly/folly/AtomicHashMap-inl.h +++ b/ios/Pods/Folly/folly/AtomicHashMap-inl.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -19,6 +19,9 @@ #endif #include <folly/detail/AtomicHashUtils.h> +#include <folly/detail/Iterators.h> + +#include <type_traits> namespace folly { @@ -566,10 +569,10 @@ struct AtomicHashMap< Allocator, ProbeFcn, KeyConvertFcn>::ahm_iterator - : boost::iterator_facade< + : detail::IteratorFacade< ahm_iterator<ContT, IterVal, SubIt>, IterVal, - boost::forward_traversal_tag> { + std::forward_iterator_tag> { explicit ahm_iterator() : ahm_(nullptr) {} // Conversion ctor for interoperability between const_iterator and @@ -596,7 +599,8 @@ struct AtomicHashMap< explicit ahm_iterator(ContT* ahm, uint32_t subMap, const SubIt& subIt) : ahm_(ahm), subMap_(subMap), subIt_(subIt) {} - friend class boost::iterator_core_access; + friend class detail:: + IteratorFacade<ahm_iterator, IterVal, std::forward_iterator_tag>; void increment() { CHECK(!isEnd()); diff --git a/ios/Pods/Folly/folly/AtomicHashMap.h b/ios/Pods/Folly/folly/AtomicHashMap.h index 75aeeceb4..a98d0866f 100644 --- a/ios/Pods/Folly/folly/AtomicHashMap.h +++ b/ios/Pods/Folly/folly/AtomicHashMap.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + /* * AtomicHashMap -- * @@ -81,10 +82,6 @@ #pragma once #define FOLLY_ATOMICHASHMAP_H_ -#include <boost/iterator/iterator_facade.hpp> -#include <boost/noncopyable.hpp> -#include <boost/type_traits/is_convertible.hpp> - #include <atomic> #include <functional> #include <stdexcept> @@ -162,7 +159,7 @@ template < class Allocator, class ProbeFcn, class KeyConvertFcn> -class AtomicHashMap : boost::noncopyable { +class AtomicHashMap { typedef AtomicHashArray< KeyT, ValueT, @@ -206,6 +203,9 @@ class AtomicHashMap : boost::noncopyable { // and a Config object to specify more advanced options. explicit AtomicHashMap(size_t finalSizeEst, const Config& c = Config()); + AtomicHashMap(const AtomicHashMap&) = delete; + AtomicHashMap& operator=(const AtomicHashMap&) = delete; + ~AtomicHashMap() { const unsigned int numMaps = numMapsAllocated_.load(std::memory_order_relaxed); diff --git a/ios/Pods/Folly/folly/AtomicIntrusiveLinkedList.h b/ios/Pods/Folly/folly/AtomicIntrusiveLinkedList.h index 95868bf97..aa2a866e0 100644 --- a/ios/Pods/Folly/folly/AtomicIntrusiveLinkedList.h +++ b/ios/Pods/Folly/folly/AtomicIntrusiveLinkedList.h @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/AtomicLinkedList.h b/ios/Pods/Folly/folly/AtomicLinkedList.h index 254a48a08..ecff27ab3 100644 --- a/ios/Pods/Folly/folly/AtomicLinkedList.h +++ b/ios/Pods/Folly/folly/AtomicLinkedList.h @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/AtomicUnorderedMap.h b/ios/Pods/Folly/folly/AtomicUnorderedMap.h index 28209ca3b..f7e84d7af 100644 --- a/ios/Pods/Folly/folly/AtomicUnorderedMap.h +++ b/ios/Pods/Folly/folly/AtomicUnorderedMap.h @@ -1,11 +1,11 @@ /* - * Copyright 2013-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -24,11 +24,10 @@ #include <system_error> #include <type_traits> -#include <boost/type_traits/has_trivial_destructor.hpp> - #include <folly/Conv.h> #include <folly/Likely.h> #include <folly/Random.h> +#include <folly/Traits.h> #include <folly/detail/AtomicUnorderedMapUtils.h> #include <folly/lang/Bits.h> #include <folly/portability/SysMman.h> @@ -135,8 +134,8 @@ template < typename Hash = std::hash<Key>, typename KeyEqual = std::equal_to<Key>, bool SkipKeyValueDeletion = - (boost::has_trivial_destructor<Key>::value && - boost::has_trivial_destructor<Value>::value), + (std::is_trivially_destructible<Key>::value && + std::is_trivially_destructible<Value>::value), template <typename> class Atom = std::atomic, typename IndexType = uint32_t, typename Allocator = folly::detail::MMapAlloc> @@ -362,8 +361,7 @@ struct AtomicUnorderedInsertMap { IndexType next_; /// Key and Value - typename std::aligned_storage<sizeof(value_type), alignof(value_type)>::type - raw_; + aligned_storage_for_t<value_type> raw_; ~Slot() { auto s = state(); @@ -463,7 +461,7 @@ struct AtomicUnorderedInsertMap { void zeroFillSlots() { using folly::detail::GivesZeroFilledMemory; if (!GivesZeroFilledMemory<Allocator>::value) { - memset(slots_, 0, mmapRequested_); + memset(static_cast<void*>(slots_), 0, mmapRequested_); } } }; @@ -478,8 +476,8 @@ template < typename Hash = std::hash<Key>, typename KeyEqual = std::equal_to<Key>, bool SkipKeyValueDeletion = - (boost::has_trivial_destructor<Key>::value && - boost::has_trivial_destructor<Value>::value), + (std::is_trivially_destructible<Key>::value && + std::is_trivially_destructible<Value>::value), template <typename> class Atom = std::atomic, typename Allocator = folly::detail::MMapAlloc> using AtomicUnorderedInsertMap64 = AtomicUnorderedInsertMap< diff --git a/ios/Pods/Folly/folly/Benchmark.h b/ios/Pods/Folly/folly/Benchmark.h index a2b286a24..f4d8fc7b0 100644 --- a/ios/Pods/Folly/folly/Benchmark.h +++ b/ios/Pods/Folly/folly/Benchmark.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -28,6 +28,7 @@ #include <functional> #include <limits> #include <type_traits> +#include <unordered_map> #include <boost/function_types/function_arity.hpp> #include <glog/logging.h> @@ -52,22 +53,41 @@ inline bool runBenchmarksOnFlag() { return FLAGS_benchmark; } -namespace detail { +class UserMetric { + public: + enum class Type { CUSTOM, TIME, METRIC }; -using TimeIterPair = - std::pair<std::chrono::high_resolution_clock::duration, unsigned int>; -using BenchmarkFun = std::function<detail::TimeIterPair(unsigned int)>; + int64_t value{}; + Type type{Type::CUSTOM}; + + UserMetric() = default; + /* implicit */ UserMetric(int64_t val, Type typ = Type::CUSTOM) + : value(val), type(typ) {} +}; + +using UserCounters = std::unordered_map<std::string, UserMetric>; + +namespace detail { +struct TimeIterData { + std::chrono::high_resolution_clock::duration duration; + unsigned int niter; + UserCounters userCounters; +}; + +using BenchmarkFun = std::function<TimeIterData(unsigned int)>; struct BenchmarkRegistration { std::string file; std::string name; BenchmarkFun func; + bool useCounter = false; }; struct BenchmarkResult { std::string file; std::string name; double timeInNs; + UserCounters counters; }; /** @@ -77,7 +97,8 @@ struct BenchmarkResult { void addBenchmarkImpl( const char* file, const char* name, - std::function<TimeIterPair(unsigned int)>); + BenchmarkFun, + bool useCounter); } // namespace detail @@ -166,9 +187,7 @@ struct BenchmarkSuspender { * function). */ template <typename Lambda> -typename std::enable_if< - boost::function_types::function_arity< - decltype(&Lambda::operator())>::value == 2>::type +typename std::enable_if<folly::is_invocable<Lambda, unsigned>::value>::type addBenchmark(const char* file, const char* name, Lambda&& lambda) { auto execute = [=](unsigned int times) { BenchmarkSuspender::timeSpent = {}; @@ -179,13 +198,11 @@ addBenchmark(const char* file, const char* name, Lambda&& lambda) { niter = lambda(times); auto end = std::chrono::high_resolution_clock::now(); // CORE MEASUREMENT ENDS - - return detail::TimeIterPair( - (end - start) - BenchmarkSuspender::timeSpent, niter); + return detail::TimeIterData{ + (end - start) - BenchmarkSuspender::timeSpent, niter, UserCounters{}}; }; - detail::addBenchmarkImpl( - file, name, std::function<detail::TimeIterPair(unsigned int)>(execute)); + detail::addBenchmarkImpl(file, name, detail::BenchmarkFun(execute), false); } /** @@ -195,9 +212,7 @@ addBenchmark(const char* file, const char* name, Lambda&& lambda) { * (iteration occurs outside the function). */ template <typename Lambda> -typename std::enable_if< - boost::function_types::function_arity< - decltype(&Lambda::operator())>::value == 1>::type +typename std::enable_if<folly::is_invocable<Lambda>::value>::type addBenchmark(const char* file, const char* name, Lambda&& lambda) { addBenchmark(file, name, [=](unsigned int times) { unsigned int niter = 0; @@ -208,6 +223,47 @@ addBenchmark(const char* file, const char* name, Lambda&& lambda) { }); } +/** + * similar as previous two template specialization, but lambda will also take + * customized counters in the following two cases + */ +template <typename Lambda> +typename std::enable_if< + folly::is_invocable<Lambda, UserCounters&, unsigned>::value>::type +addBenchmark(const char* file, const char* name, Lambda&& lambda) { + auto execute = [=](unsigned int times) { + BenchmarkSuspender::timeSpent = {}; + unsigned int niter; + + // CORE MEASUREMENT STARTS + auto start = std::chrono::high_resolution_clock::now(); + UserCounters counters; + niter = lambda(counters, times); + auto end = std::chrono::high_resolution_clock::now(); + // CORE MEASUREMENT ENDS + return detail::TimeIterData{ + (end - start) - BenchmarkSuspender::timeSpent, niter, counters}; + }; + + detail::addBenchmarkImpl( + file, + name, + std::function<detail::TimeIterData(unsigned int)>(execute), + true); +} + +template <typename Lambda> +typename std::enable_if<folly::is_invocable<Lambda, UserCounters&>::value>::type +addBenchmark(const char* file, const char* name, Lambda&& lambda) { + addBenchmark(file, name, [=](UserCounters& counters, unsigned int times) { + unsigned int niter = 0; + while (times-- > 0) { + niter += lambda(counters); + } + return niter; + }); +} + /** * Call doNotOptimizeAway(var) to ensure that var will be computed even * post-optimization. Use it for variables that are computed during @@ -315,32 +371,50 @@ void printResultComparison( * Introduces a benchmark function. Used internally, see BENCHMARK and * friends below. */ -#define BENCHMARK_IMPL(funName, stringName, rv, paramType, paramName) \ - static void funName(paramType); \ - static bool FB_ANONYMOUS_VARIABLE(follyBenchmarkUnused) = \ - (::folly::addBenchmark( \ - __FILE__, \ - stringName, \ - [](paramType paramName) -> unsigned { \ - funName(paramName); \ - return rv; \ - }), \ - true); \ + +#define BENCHMARK_IMPL(funName, stringName, rv, paramType, paramName) \ + static void funName(paramType); \ + FOLLY_MAYBE_UNUSED static bool FB_ANONYMOUS_VARIABLE(follyBenchmarkUnused) = \ + (::folly::addBenchmark( \ + __FILE__, \ + stringName, \ + [](paramType paramName) -> unsigned { \ + funName(paramName); \ + return rv; \ + }), \ + true); \ static void funName(paramType paramName) +#define BENCHMARK_IMPL_COUNTERS( \ + funName, stringName, counters, rv, paramType, paramName) \ + static void funName( \ + ::folly::UserCounters& FOLLY_PP_DETAIL_APPEND_VA_ARG(paramType)); \ + FOLLY_MAYBE_UNUSED static bool FB_ANONYMOUS_VARIABLE(follyBenchmarkUnused) = \ + (::folly::addBenchmark( \ + __FILE__, \ + stringName, \ + [](::folly::UserCounters& counters FOLLY_PP_DETAIL_APPEND_VA_ARG( \ + paramType paramName)) -> unsigned { \ + funName(counters FOLLY_PP_DETAIL_APPEND_VA_ARG(paramName)); \ + return rv; \ + }), \ + true); \ + static void funName(::folly::UserCounters& counters \ + FOLLY_PP_DETAIL_APPEND_VA_ARG(paramType paramName)) + /** * Introduces a benchmark function with support for returning the actual * number of iterations. Used internally, see BENCHMARK_MULTI and friends * below. */ -#define BENCHMARK_MULTI_IMPL(funName, stringName, paramType, paramName) \ - static unsigned funName(paramType); \ - static bool FB_ANONYMOUS_VARIABLE(follyBenchmarkUnused) = \ - (::folly::addBenchmark( \ - __FILE__, \ - stringName, \ - [](paramType paramName) { return funName(paramName); }), \ - true); \ +#define BENCHMARK_MULTI_IMPL(funName, stringName, paramType, paramName) \ + static unsigned funName(paramType); \ + FOLLY_MAYBE_UNUSED static bool FB_ANONYMOUS_VARIABLE(follyBenchmarkUnused) = \ + (::folly::addBenchmark( \ + __FILE__, \ + stringName, \ + [](paramType paramName) { return funName(paramName); }), \ + true); \ static unsigned funName(paramType paramName) /** @@ -355,9 +429,9 @@ void printResultComparison( * v.push_back(42); * } * - * BENCHMARK(insertVectorBegin, n) { + * BENCHMARK(insertVectorBegin, iters) { * vector<int> v; - * FOR_EACH_RANGE (i, 0, n) { + * FOR_EACH_RANGE (i, 0, iters) { * v.insert(v.begin(), 42); * } * } @@ -365,11 +439,33 @@ void printResultComparison( #define BENCHMARK(name, ...) \ BENCHMARK_IMPL( \ name, \ - FB_STRINGIZE(name), \ + FOLLY_PP_STRINGIZE(name), \ FB_ARG_2_OR_1(1, ##__VA_ARGS__), \ FB_ONE_OR_NONE(unsigned, ##__VA_ARGS__), \ __VA_ARGS__) +/** + * Allow users to record customized counter during benchmarking, + * there will be one extra column showing in the output result for each counter + * + * BENCHMARK_COUNTERS(insertVectorBegin, couters, iters) { + * vector<int> v; + * FOR_EACH_RANGE (i, 0, iters) { + * v.insert(v.begin(), 42); + * } + * BENCHMARK_SUSPEND { + * counters["foo"] = 10; + * } + * } + */ +#define BENCHMARK_COUNTERS(name, counters, ...) \ + BENCHMARK_IMPL_COUNTERS( \ + name, \ + FOLLY_PP_STRINGIZE(name), \ + counters, \ + FB_ARG_2_OR_1(1, ##__VA_ARGS__), \ + FB_ONE_OR_NONE(unsigned, ##__VA_ARGS__), \ + __VA_ARGS__) /** * Like BENCHMARK above, but allows the user to return the actual * number of iterations executed in the function body. This can be @@ -388,7 +484,7 @@ void printResultComparison( #define BENCHMARK_MULTI(name, ...) \ BENCHMARK_MULTI_IMPL( \ name, \ - FB_STRINGIZE(name), \ + FOLLY_PP_STRINGIZE(name), \ FB_ONE_OR_NONE(unsigned, ##__VA_ARGS__), \ __VA_ARGS__) @@ -446,27 +542,27 @@ void printResultComparison( * BENCHMARK_NAMED_PARAM(addValue, 0_to_1000, 10, 0, 1000) * BENCHMARK_NAMED_PARAM(addValue, 5k_to_20k, 250, 5000, 20000) */ -#define BENCHMARK_NAMED_PARAM(name, param_name, ...) \ - BENCHMARK_IMPL( \ - FB_CONCATENATE(name, FB_CONCATENATE(_, param_name)), \ - FB_STRINGIZE(name) "(" FB_STRINGIZE(param_name) ")", \ - iters, \ - unsigned, \ - iters) { \ - name(iters, ##__VA_ARGS__); \ +#define BENCHMARK_NAMED_PARAM(name, param_name, ...) \ + BENCHMARK_IMPL( \ + FB_CONCATENATE(name, FB_CONCATENATE(_, param_name)), \ + FOLLY_PP_STRINGIZE(name) "(" FOLLY_PP_STRINGIZE(param_name) ")", \ + iters, \ + unsigned, \ + iters) { \ + name(iters, ##__VA_ARGS__); \ } /** * Same as BENCHMARK_NAMED_PARAM, but allows one to return the actual number * of iterations that have been run. */ -#define BENCHMARK_NAMED_PARAM_MULTI(name, param_name, ...) \ - BENCHMARK_MULTI_IMPL( \ - FB_CONCATENATE(name, FB_CONCATENATE(_, param_name)), \ - FB_STRINGIZE(name) "(" FB_STRINGIZE(param_name) ")", \ - unsigned, \ - iters) { \ - return name(iters, ##__VA_ARGS__); \ +#define BENCHMARK_NAMED_PARAM_MULTI(name, param_name, ...) \ + BENCHMARK_MULTI_IMPL( \ + FB_CONCATENATE(name, FB_CONCATENATE(_, param_name)), \ + FOLLY_PP_STRINGIZE(name) "(" FOLLY_PP_STRINGIZE(param_name) ")", \ + unsigned, \ + iters) { \ + return name(iters, ##__VA_ARGS__); \ } /** @@ -496,11 +592,19 @@ void printResultComparison( #define BENCHMARK_RELATIVE(name, ...) \ BENCHMARK_IMPL( \ name, \ - "%" FB_STRINGIZE(name), \ + "%" FOLLY_PP_STRINGIZE(name), \ FB_ARG_2_OR_1(1, ##__VA_ARGS__), \ FB_ONE_OR_NONE(unsigned, ##__VA_ARGS__), \ __VA_ARGS__) +#define BENCHMARK_COUNTERS_RELATIVE(name, counters, ...) \ + BENCHMARK_IMPL_COUNTERS( \ + name, \ + "%" FOLLY_PP_STRINGIZE(name), \ + counters, \ + FB_ARG_2_OR_1(1, ##__VA_ARGS__), \ + FB_ONE_OR_NONE(unsigned, ##__VA_ARGS__), \ + __VA_ARGS__) /** * Same as BENCHMARK_RELATIVE, but allows one to return the actual number * of iterations that have been run. @@ -508,7 +612,7 @@ void printResultComparison( #define BENCHMARK_RELATIVE_MULTI(name, ...) \ BENCHMARK_MULTI_IMPL( \ name, \ - "%" FB_STRINGIZE(name), \ + "%" FOLLY_PP_STRINGIZE(name), \ FB_ONE_OR_NONE(unsigned, ##__VA_ARGS__), \ __VA_ARGS__) @@ -528,35 +632,35 @@ void printResultComparison( /** * A combination of BENCHMARK_RELATIVE and BENCHMARK_NAMED_PARAM. */ -#define BENCHMARK_RELATIVE_NAMED_PARAM(name, param_name, ...) \ - BENCHMARK_IMPL( \ - FB_CONCATENATE(name, FB_CONCATENATE(_, param_name)), \ - "%" FB_STRINGIZE(name) "(" FB_STRINGIZE(param_name) ")", \ - iters, \ - unsigned, \ - iters) { \ - name(iters, ##__VA_ARGS__); \ +#define BENCHMARK_RELATIVE_NAMED_PARAM(name, param_name, ...) \ + BENCHMARK_IMPL( \ + FB_CONCATENATE(name, FB_CONCATENATE(_, param_name)), \ + "%" FOLLY_PP_STRINGIZE(name) "(" FOLLY_PP_STRINGIZE(param_name) ")", \ + iters, \ + unsigned, \ + iters) { \ + name(iters, ##__VA_ARGS__); \ } /** * Same as BENCHMARK_RELATIVE_NAMED_PARAM, but allows one to return the * actual number of iterations that have been run. */ -#define BENCHMARK_RELATIVE_NAMED_PARAM_MULTI(name, param_name, ...) \ - BENCHMARK_MULTI_IMPL( \ - FB_CONCATENATE(name, FB_CONCATENATE(_, param_name)), \ - "%" FB_STRINGIZE(name) "(" FB_STRINGIZE(param_name) ")", \ - unsigned, \ - iters) { \ - return name(iters, ##__VA_ARGS__); \ +#define BENCHMARK_RELATIVE_NAMED_PARAM_MULTI(name, param_name, ...) \ + BENCHMARK_MULTI_IMPL( \ + FB_CONCATENATE(name, FB_CONCATENATE(_, param_name)), \ + "%" FOLLY_PP_STRINGIZE(name) "(" FOLLY_PP_STRINGIZE(param_name) ")", \ + unsigned, \ + iters) { \ + return name(iters, ##__VA_ARGS__); \ } /** * Draws a line of dashes. */ -#define BENCHMARK_DRAW_LINE() \ - static bool FB_ANONYMOUS_VARIABLE(follyBenchmarkUnused) = \ - (::folly::addBenchmark(__FILE__, "-", []() -> unsigned { return 0; }), \ +#define BENCHMARK_DRAW_LINE() \ + FOLLY_MAYBE_UNUSED static bool FB_ANONYMOUS_VARIABLE(follyBenchmarkUnused) = \ + (::folly::addBenchmark(__FILE__, "-", []() -> unsigned { return 0; }), \ true) /** diff --git a/ios/Pods/Folly/folly/Bits.h b/ios/Pods/Folly/folly/Bits.h index e5cf5be2f..1569d598c 100644 --- a/ios/Pods/Folly/folly/Bits.h +++ b/ios/Pods/Folly/folly/Bits.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/CPortability.h b/ios/Pods/Folly/folly/CPortability.h index 82a1e8e07..976daf069 100644 --- a/ios/Pods/Folly/folly/CPortability.h +++ b/ios/Pods/Folly/folly/CPortability.h @@ -1,11 +1,11 @@ /* - * Copyright 2013-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -68,12 +68,14 @@ * itself was compiled without ASAN but a downstream project that uses folly is * compiling with ASAN enabled. * - * Use FOLLY_ASAN_ENABLED (defined in folly-config.h) to check if folly itself - * was compiled with ASAN enabled. + * Use FOLLY_LIBRARY_SANITIZE_ADDRESS (defined in folly-config.h) to check if + * folly itself was compiled with ASAN enabled. */ +#ifndef FOLLY_SANITIZE_ADDRESS #if FOLLY_HAS_FEATURE(address_sanitizer) || __SANITIZE_ADDRESS__ #define FOLLY_SANITIZE_ADDRESS 1 #endif +#endif /* Define attribute wrapper for function attribute used to disable * address sanitizer instrumentation. Unfortunately, this attribute @@ -101,17 +103,46 @@ /* Define a convenience macro to test when thread sanitizer is being used * across the different compilers (e.g. clang, gcc) */ +#ifndef FOLLY_SANITIZE_THREAD #if FOLLY_HAS_FEATURE(thread_sanitizer) || __SANITIZE_THREAD__ #define FOLLY_SANITIZE_THREAD 1 #endif +#endif + +#if FOLLY_SANITIZE_THREAD +#define FOLLY_DISABLE_THREAD_SANITIZER \ + __attribute__((no_sanitize_thread, noinline)) +#else +#define FOLLY_DISABLE_THREAD_SANITIZER +#endif /** - * Define a convenience macro to test when ASAN, UBSAN or TSAN sanitizer are - * being used + * Define a convenience macro to test when memory sanitizer is being used + * across the different compilers (e.g. clang, gcc) */ -#if defined(FOLLY_SANITIZE_ADDRESS) || defined(FOLLY_SANITIZE_THREAD) +#ifndef FOLLY_SANITIZE_MEMORY +#if FOLLY_HAS_FEATURE(memory_sanitizer) || __SANITIZE_MEMORY__ +#define FOLLY_SANITIZE_MEMORY 1 +#endif +#endif + +#if FOLLY_SANITIZE_MEMORY +#define FOLLY_DISABLE_MEMORY_SANITIZER \ + __attribute__((no_sanitize_memory, noinline)) +#else +#define FOLLY_DISABLE_MEMORY_SANITIZER +#endif + +/** + * Define a convenience macro to test when ASAN, UBSAN, TSAN or MSAN sanitizer + * are being used + */ +#ifndef FOLLY_SANITIZE +#if defined(FOLLY_SANITIZE_ADDRESS) || defined(FOLLY_SANITIZE_THREAD) || \ + defined(FOLLY_SANITIZE_MEMORY) #define FOLLY_SANITIZE 1 #endif +#endif #if FOLLY_SANITIZE #define FOLLY_DISABLE_UNDEFINED_BEHAVIOR_SANITIZER(...) \ @@ -120,15 +151,15 @@ #define FOLLY_DISABLE_UNDEFINED_BEHAVIOR_SANITIZER(...) #endif // FOLLY_SANITIZE +#define FOLLY_DISABLE_SANITIZERS \ + FOLLY_DISABLE_ADDRESS_SANITIZER FOLLY_DISABLE_THREAD_SANITIZER \ + FOLLY_DISABLE_UNDEFINED_BEHAVIOR_SANITIZER("undefined") + /** * Macro for marking functions as having public visibility. */ #if defined(__GNUC__) -#if __GNUC_PREREQ(4, 9) -#define FOLLY_EXPORT [[gnu::visibility("default")]] -#else #define FOLLY_EXPORT __attribute__((__visibility__("default"))) -#endif #else #define FOLLY_EXPORT #endif @@ -136,7 +167,7 @@ // noinline #ifdef _MSC_VER #define FOLLY_NOINLINE __declspec(noinline) -#elif defined(__clang__) || defined(__GNUC__) +#elif defined(__GNUC__) #define FOLLY_NOINLINE __attribute__((__noinline__)) #else #define FOLLY_NOINLINE @@ -145,16 +176,16 @@ // always inline #ifdef _MSC_VER #define FOLLY_ALWAYS_INLINE __forceinline -#elif defined(__clang__) || defined(__GNUC__) +#elif defined(__GNUC__) #define FOLLY_ALWAYS_INLINE inline __attribute__((__always_inline__)) #else #define FOLLY_ALWAYS_INLINE inline #endif // attribute hidden -#if _MSC_VER +#if defined(_MSC_VER) #define FOLLY_ATTR_VISIBILITY_HIDDEN -#elif defined(__clang__) || defined(__GNUC__) +#elif defined(__GNUC__) #define FOLLY_ATTR_VISIBILITY_HIDDEN __attribute__((__visibility__("hidden"))) #else #define FOLLY_ATTR_VISIBILITY_HIDDEN @@ -174,21 +205,38 @@ #endif #endif -// These functions are defined by the TSAN runtime library and enable -// annotating mutexes for TSAN. -extern "C" FOLLY_ATTR_WEAK void -AnnotateRWLockCreate(const char* f, int l, const volatile void* addr); -extern "C" FOLLY_ATTR_WEAK void -AnnotateRWLockCreateStatic(const char* f, int l, const volatile void* addr); -extern "C" FOLLY_ATTR_WEAK void -AnnotateRWLockDestroy(const char* f, int l, const volatile void* addr); -extern "C" FOLLY_ATTR_WEAK void -AnnotateRWLockAcquired(const char* f, int l, const volatile void* addr, long w); -extern "C" FOLLY_ATTR_WEAK void -AnnotateRWLockReleased(const char* f, int l, const volatile void* addr, long w); -extern "C" FOLLY_ATTR_WEAK void AnnotateBenignRaceSized( - const char* f, - int l, - const volatile void* addr, - long size, - const char* desc); +// FOLLY_ERASE +// +// A conceptual attribute/syntax combo for erasing a function from the build +// artifacts and forcing all call-sites to inline the callee, at least as far +// as each compiler supports. +// +// Semantically includes the inline specifier. +#define FOLLY_ERASE FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN + +// FOLLY_ERASE_HACK_GCC +// +// Equivalent to FOLLY_ERASE, but without hiding under gcc. Useful when applied +// to a function which may sometimes be hidden separately, for example by being +// declared in an anonymous namespace, since in such cases with -Wattributes +// enabled, gcc would emit: 'visibility' attribute ignored. +// +// Semantically includes the inline specifier. +#if defined(__GNUC__) && !defined(__clang__) +#define FOLLY_ERASE_HACK_GCC FOLLY_ALWAYS_INLINE +#else +#define FOLLY_ERASE_HACK_GCC FOLLY_ERASE +#endif + +// FOLLY_ERASE_TRYCATCH +// +// Equivalent to FOLLY_ERASE, but for code which might contain explicit +// exception handling. Has the effect of FOLLY_ERASE, except under MSVC which +// warns about __forceinline when functions contain exception handling. +// +// Semantically includes the inline specifier. +#ifdef _MSC_VER +#define FOLLY_ERASE_TRYCATCH inline +#else +#define FOLLY_ERASE_TRYCATCH FOLLY_ERASE +#endif diff --git a/ios/Pods/Folly/folly/CachelinePadded.h b/ios/Pods/Folly/folly/CachelinePadded.h index d706b18ad..635bc53da 100644 --- a/ios/Pods/Folly/folly/CachelinePadded.h +++ b/ios/Pods/Folly/folly/CachelinePadded.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -17,9 +17,11 @@ #pragma once #include <cstddef> +#include <cstdint> #include <utility> #include <folly/lang/Align.h> +#include <folly/lang/SafeAssert.h> namespace folly { @@ -29,17 +31,20 @@ namespace folly { * * If `sizeof(T) <= alignof(T)` then the inner `T` will be entirely within one * false sharing range (AKA cache line). + * + * CachelinePadded may add padding both before and after the value. Consider + * whether alignas(folly::hardware_destructive_interference_size) suffices. */ template <typename T> class CachelinePadded { - static_assert( - alignof(T) <= max_align_v, - "CachelinePadded does not support over-aligned types."); - public: template <typename... Args> explicit CachelinePadded(Args&&... args) - : inner_(std::forward<Args>(args)...) {} + : inner_(std::forward<Args>(args)...) { + FOLLY_SAFE_DCHECK( + (reinterpret_cast<uintptr_t>(&inner_) % alignof(T)) == 0, + "CachelinePadded requires types aligned to their ABI requirement"); + } T* get() { return &inner_; diff --git a/ios/Pods/Folly/folly/CancellationToken-inl.h b/ios/Pods/Folly/folly/CancellationToken-inl.h new file mode 100644 index 000000000..8ce5c5c79 --- /dev/null +++ b/ios/Pods/Folly/folly/CancellationToken-inl.h @@ -0,0 +1,351 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <algorithm> +#include <cstdint> +#include <limits> +#include <utility> + +#include <glog/logging.h> + +namespace folly { + +namespace detail { + +// Internal cancellation state object. +class CancellationState { + public: + FOLLY_NODISCARD static CancellationStateSourcePtr create(); + + private: + // Constructed initially with a CancellationSource reference count of 1. + CancellationState() noexcept; + + ~CancellationState(); + + friend struct CancellationStateTokenDeleter; + friend struct CancellationStateSourceDeleter; + + void removeTokenReference() noexcept; + void removeSourceReference() noexcept; + + public: + FOLLY_NODISCARD CancellationStateTokenPtr addTokenReference() noexcept; + + FOLLY_NODISCARD CancellationStateSourcePtr addSourceReference() noexcept; + + bool tryAddCallback( + CancellationCallback* callback, + bool incrementRefCountIfSuccessful) noexcept; + + void removeCallback(CancellationCallback* callback) noexcept; + + bool isCancellationRequested() const noexcept; + bool canBeCancelled() const noexcept; + + // Request cancellation. + // Return 'true' if cancellation had already been requested. + // Return 'false' if this was the first thread to request + // cancellation. + bool requestCancellation() noexcept; + + private: + void lock() noexcept; + void unlock() noexcept; + void unlockAndIncrementTokenCount() noexcept; + void unlockAndDecrementTokenCount() noexcept; + bool tryLockAndCancelUnlessCancelled() noexcept; + + template <typename Predicate> + bool tryLock(Predicate predicate) noexcept; + + static bool canBeCancelled(std::uint64_t state) noexcept; + static bool isCancellationRequested(std::uint64_t state) noexcept; + static bool isLocked(std::uint64_t state) noexcept; + + static constexpr std::uint64_t kCancellationRequestedFlag = 1; + static constexpr std::uint64_t kLockedFlag = 2; + static constexpr std::uint64_t kTokenReferenceCountIncrement = 4; + static constexpr std::uint64_t kSourceReferenceCountIncrement = + std::uint64_t(1) << 33u; + static constexpr std::uint64_t kTokenReferenceCountMask = + (kSourceReferenceCountIncrement - 1u) - + (kTokenReferenceCountIncrement - 1u); + static constexpr std::uint64_t kSourceReferenceCountMask = + std::numeric_limits<std::uint64_t>::max() - + (kSourceReferenceCountIncrement - 1u); + + // Bit 0 - Cancellation Requested + // Bit 1 - Locked Flag + // Bits 2-32 - Token reference count (max ~2 billion) + // Bits 33-63 - Source reference count (max ~2 billion) + std::atomic<std::uint64_t> state_; + CancellationCallback* head_; + std::thread::id signallingThreadId_; +}; + +inline void CancellationStateTokenDeleter::operator()( + CancellationState* state) noexcept { + state->removeTokenReference(); +} + +inline void CancellationStateSourceDeleter::operator()( + CancellationState* state) noexcept { + state->removeSourceReference(); +} + +} // namespace detail + +inline CancellationToken::CancellationToken( + const CancellationToken& other) noexcept + : state_() { + if (other.state_) { + state_ = other.state_->addTokenReference(); + } +} + +inline CancellationToken::CancellationToken(CancellationToken&& other) noexcept + : state_(std::move(other.state_)) {} + +inline CancellationToken& CancellationToken::operator=( + const CancellationToken& other) noexcept { + if (state_ != other.state_) { + CancellationToken temp{other}; + swap(temp); + } + return *this; +} + +inline CancellationToken& CancellationToken::operator=( + CancellationToken&& other) noexcept { + state_ = std::move(other.state_); + return *this; +} + +inline bool CancellationToken::isCancellationRequested() const noexcept { + return state_ != nullptr && state_->isCancellationRequested(); +} + +inline bool CancellationToken::canBeCancelled() const noexcept { + return state_ != nullptr && state_->canBeCancelled(); +} + +inline void CancellationToken::swap(CancellationToken& other) noexcept { + std::swap(state_, other.state_); +} + +inline CancellationToken::CancellationToken( + detail::CancellationStateTokenPtr state) noexcept + : state_(std::move(state)) {} + +inline bool operator==( + const CancellationToken& a, + const CancellationToken& b) noexcept { + return a.state_ == b.state_; +} + +inline bool operator!=( + const CancellationToken& a, + const CancellationToken& b) noexcept { + return !(a == b); +} + +inline CancellationSource::CancellationSource() + : state_(detail::CancellationState::create()) {} + +inline CancellationSource::CancellationSource( + const CancellationSource& other) noexcept + : state_() { + if (other.state_) { + state_ = other.state_->addSourceReference(); + } +} + +inline CancellationSource::CancellationSource( + CancellationSource&& other) noexcept + : state_(std::move(other.state_)) {} + +inline CancellationSource& CancellationSource::operator=( + const CancellationSource& other) noexcept { + if (state_ != other.state_) { + CancellationSource temp{other}; + swap(temp); + } + return *this; +} + +inline CancellationSource& CancellationSource::operator=( + CancellationSource&& other) noexcept { + state_ = std::move(other.state_); + return *this; +} + +inline CancellationSource CancellationSource::invalid() noexcept { + return CancellationSource{detail::CancellationStateSourcePtr{}}; +} + +inline bool CancellationSource::isCancellationRequested() const noexcept { + return state_ != nullptr && state_->isCancellationRequested(); +} + +inline bool CancellationSource::canBeCancelled() const noexcept { + return state_ != nullptr; +} + +inline CancellationToken CancellationSource::getToken() const noexcept { + if (state_ != nullptr) { + return CancellationToken{state_->addTokenReference()}; + } + return CancellationToken{}; +} + +inline bool CancellationSource::requestCancellation() const noexcept { + if (state_ != nullptr) { + return state_->requestCancellation(); + } + return false; +} + +inline void CancellationSource::swap(CancellationSource& other) noexcept { + std::swap(state_, other.state_); +} + +inline CancellationSource::CancellationSource( + detail::CancellationStateSourcePtr&& state) noexcept + : state_(std::move(state)) {} + +template < + typename Callable, + std::enable_if_t< + std::is_constructible<CancellationCallback::VoidFunction, Callable>:: + value, + int>> +inline CancellationCallback::CancellationCallback( + CancellationToken&& ct, + Callable&& callable) + : next_(nullptr), + prevNext_(nullptr), + state_(nullptr), + callback_(static_cast<Callable&&>(callable)), + destructorHasRunInsideCallback_(nullptr), + callbackCompleted_(false) { + if (ct.state_ != nullptr && ct.state_->tryAddCallback(this, false)) { + state_ = ct.state_.release(); + } +} + +template < + typename Callable, + std::enable_if_t< + std::is_constructible<CancellationCallback::VoidFunction, Callable>:: + value, + int>> +inline CancellationCallback::CancellationCallback( + const CancellationToken& ct, + Callable&& callable) + : next_(nullptr), + prevNext_(nullptr), + state_(nullptr), + callback_(static_cast<Callable&&>(callable)), + destructorHasRunInsideCallback_(nullptr), + callbackCompleted_(false) { + if (ct.state_ != nullptr && ct.state_->tryAddCallback(this, true)) { + state_ = ct.state_.get(); + } +} + +inline CancellationCallback::~CancellationCallback() { + if (state_ != nullptr) { + state_->removeCallback(this); + } +} + +inline void CancellationCallback::invokeCallback() noexcept { + // Invoke within a noexcept context so that we std::terminate() if it throws. + callback_(); +} + +namespace detail { + +inline CancellationStateSourcePtr CancellationState::create() { + return CancellationStateSourcePtr{new CancellationState()}; +} + +inline CancellationState::CancellationState() noexcept + : state_(kSourceReferenceCountIncrement), + head_(nullptr), + signallingThreadId_() {} + +inline CancellationStateTokenPtr +CancellationState::addTokenReference() noexcept { + state_.fetch_add(kTokenReferenceCountIncrement, std::memory_order_relaxed); + return CancellationStateTokenPtr{this}; +} + +inline void CancellationState::removeTokenReference() noexcept { + const auto oldState = state_.fetch_sub( + kTokenReferenceCountIncrement, std::memory_order_acq_rel); + DCHECK( + (oldState & kTokenReferenceCountMask) >= kTokenReferenceCountIncrement); + if (oldState < (2 * kTokenReferenceCountIncrement)) { + delete this; + } +} + +inline CancellationStateSourcePtr +CancellationState::addSourceReference() noexcept { + state_.fetch_add(kSourceReferenceCountIncrement, std::memory_order_relaxed); + return CancellationStateSourcePtr{this}; +} + +inline void CancellationState::removeSourceReference() noexcept { + const auto oldState = state_.fetch_sub( + kSourceReferenceCountIncrement, std::memory_order_acq_rel); + DCHECK( + (oldState & kSourceReferenceCountMask) >= kSourceReferenceCountIncrement); + if (oldState < + (kSourceReferenceCountIncrement + kTokenReferenceCountIncrement)) { + delete this; + } +} + +inline bool CancellationState::isCancellationRequested() const noexcept { + return isCancellationRequested(state_.load(std::memory_order_acquire)); +} + +inline bool CancellationState::canBeCancelled() const noexcept { + return canBeCancelled(state_.load(std::memory_order_acquire)); +} + +inline bool CancellationState::canBeCancelled(std::uint64_t state) noexcept { + // Can be cancelled if there is at least one CancellationSource ref-count + // or if cancellation has been requested. + return (state >= kSourceReferenceCountIncrement) || + isCancellationRequested(state); +} + +inline bool CancellationState::isCancellationRequested( + std::uint64_t state) noexcept { + return (state & kCancellationRequestedFlag) != 0; +} + +inline bool CancellationState::isLocked(std::uint64_t state) noexcept { + return (state & kLockedFlag) != 0; +} + +} // namespace detail + +} // namespace folly diff --git a/ios/Pods/Folly/folly/CancellationToken.h b/ios/Pods/Folly/folly/CancellationToken.h new file mode 100644 index 000000000..bdda121b0 --- /dev/null +++ b/ios/Pods/Folly/folly/CancellationToken.h @@ -0,0 +1,298 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <folly/CppAttributes.h> +#include <folly/Function.h> + +#include <atomic> +#include <memory> +#include <thread> +#include <type_traits> + +namespace folly { + +class CancellationCallback; +class CancellationSource; +struct OperationCancelled : public std::exception { + const char* what() const noexcept override { + return "coroutine operation cancelled"; + } +}; + +namespace detail { +class CancellationState; +struct CancellationStateTokenDeleter { + void operator()(CancellationState*) noexcept; +}; +struct CancellationStateSourceDeleter { + void operator()(CancellationState*) noexcept; +}; +using CancellationStateTokenPtr = + std::unique_ptr<CancellationState, CancellationStateTokenDeleter>; +using CancellationStateSourcePtr = + std::unique_ptr<CancellationState, CancellationStateSourceDeleter>; +} // namespace detail + +// A CancellationToken is an object that can be passed into an function or +// operation that allows the caller to later request that the operation be +// cancelled. +// +// A CancellationToken object can be obtained by calling the .getToken() +// method on a CancellationSource or by copying another CancellationToken +// object. All CancellationToken objects obtained from the same original +// CancellationSource object all reference the same underlying cancellation +// state and will all be cancelled together. +// +// If your function needs to be cancellable but does not need to request +// cancellation then you should take a CancellationToken as a parameter. +// If your function needs to be able to request cancellation then you +// should instead take a CancellationSource as a parameter. +class CancellationToken { + public: + // Constructs to a token that can never be cancelled. + // + // Pass a default-constructed CancellationToken into an operation that + // you never intend to cancel. These objects are very cheap to create. + CancellationToken() noexcept = default; + + // Construct a copy of the token that shares the same underlying state. + CancellationToken(const CancellationToken& other) noexcept; + CancellationToken(CancellationToken&& other) noexcept; + + CancellationToken& operator=(const CancellationToken& other) noexcept; + CancellationToken& operator=(CancellationToken&& other) noexcept; + + // Query whether someone has called .requestCancellation() on an instance + // of CancellationSource object associated with this CancellationToken. + bool isCancellationRequested() const noexcept; + + // Query whether this CancellationToken can ever have cancellation requested + // on it. + // + // This will return false if the CancellationToken is not associated with a + // CancellationSource object. eg. because the CancellationToken was + // default-constructed, has been moved-from or because the last + // CancellationSource object associated with the underlying cancellation state + // has been destroyed and the operation has not yet been cancelled and so + // never will be. + // + // Implementations of operations may be able to take more efficient code-paths + // if they know they can never be cancelled. + bool canBeCancelled() const noexcept; + + void swap(CancellationToken& other) noexcept; + + friend bool operator==( + const CancellationToken& a, + const CancellationToken& b) noexcept; + + private: + friend class CancellationCallback; + friend class CancellationSource; + + explicit CancellationToken(detail::CancellationStateTokenPtr state) noexcept; + + detail::CancellationStateTokenPtr state_; +}; + +bool operator==( + const CancellationToken& a, + const CancellationToken& b) noexcept; +bool operator!=( + const CancellationToken& a, + const CancellationToken& b) noexcept; + +// A CancellationSource object provides the ability to request cancellation of +// operations that an associated CancellationToken was passed to. +// +// Example usage: +// CancellationSource cs; +// Future<void> f = startSomeOperation(cs.getToken()); +// +// // Later... +// cs.requestCancellation(); +class CancellationSource { + public: + // Construct to a new, independent cancellation source. + CancellationSource(); + + // Construct a new reference to the same underlying cancellation state. + // + // Either the original or the new copy can be used to request cancellation + // of associated work. + CancellationSource(const CancellationSource& other) noexcept; + + // This leaves 'other' in an empty state where 'requestCancellation()' is a + // no-op and 'canBeCancelled()' returns false. + CancellationSource(CancellationSource&& other) noexcept; + + CancellationSource& operator=(const CancellationSource& other) noexcept; + CancellationSource& operator=(CancellationSource&& other) noexcept; + + // Construct a CancellationSource that cannot be cancelled. + // + // This factory function can be used to obtain a CancellationSource that + // is equivalent to a moved-from CancellationSource object without needing + // to allocate any shared-state. + static CancellationSource invalid() noexcept; + + // Query if cancellation has already been requested on this CancellationSource + // or any other CancellationSource object copied from the same original + // CancellationSource object. + bool isCancellationRequested() const noexcept; + + // Query if cancellation can be requested through this CancellationSource + // object. This will only return false if the CancellationSource object has + // been moved-from. + bool canBeCancelled() const noexcept; + + // Obtain a CancellationToken linked to this CancellationSource. + // + // This token can be passed into cancellable operations to allow the caller + // to later request cancellation of that operation. + CancellationToken getToken() const noexcept; + + // Request cancellation of work associated with this CancellationSource. + // + // This will ensure subsequent calls to isCancellationRequested() on any + // CancellationSource or CancellationToken object associated with the same + // underlying cancellation state to return true. + // + // If this is the first call to requestCancellation() on any + // CancellationSource object with the same underlying state then this call + // will also execute the callbacks associated with any CancellationCallback + // objects that were constructed with an associated CancellationToken. + // + // Note that it is possible that another thread may be concurrently + // registering a callback with CancellationCallback. This method guarantees + // that either this thread will see the callback registration and will + // ensure that the callback is called, or the CancellationCallback constructor + // will see the cancellation-requested signal and will execute the callback + // inline inside the constructor. + // + // Returns the previous state of 'isCancellationRequested()'. i.e. + // - 'true' if cancellation had previously been requested. + // - 'false' if this was the first call to request cancellation. + bool requestCancellation() const noexcept; + + void swap(CancellationSource& other) noexcept; + + friend bool operator==( + const CancellationSource& a, + const CancellationSource& b) noexcept; + + private: + explicit CancellationSource( + detail::CancellationStateSourcePtr&& state) noexcept; + + detail::CancellationStateSourcePtr state_; +}; + +bool operator==( + const CancellationSource& a, + const CancellationSource& b) noexcept; +bool operator!=( + const CancellationSource& a, + const CancellationSource& b) noexcept; + +class CancellationCallback { + using VoidFunction = folly::Function<void()>; + + public: + // Constructing a CancellationCallback object registers the callback + // with the specified CancellationToken such that the callback will be + // executed if the corresponding CancellationSource object has the + // requestCancellation() method called on it. + // + // If the CancellationToken object already had cancellation requested + // then the callback will be executed inline on the current thread before + // the constructor returns. Otherwise, the callback will be executed on + // in the execution context of the first thread to call requestCancellation() + // on a corresponding CancellationSource. + // + // The callback object must not throw any unhandled exceptions. Doing so + // will result in the program terminating via std::terminate(). + template < + typename Callable, + std::enable_if_t< + std::is_constructible<VoidFunction, Callable>::value, + int> = 0> + CancellationCallback(CancellationToken&& ct, Callable&& callable); + template < + typename Callable, + std::enable_if_t< + std::is_constructible<VoidFunction, Callable>::value, + int> = 0> + CancellationCallback(const CancellationToken& ct, Callable&& callable); + + // Deregisters the callback from the CancellationToken. + // + // If cancellation has been requested concurrently on another thread and the + // callback is currently executing then the destructor will block until after + // the callback has returned (otherwise it might be left with a dangling + // reference). + // + // You should generally try to implement your callback functions to be lock + // free to avoid deadlocks between the callback executing and the + // CancellationCallback destructor trying to deregister the callback. + // + // If the callback has not started executing yet then the callback will be + // deregistered from the CancellationToken before the destructor completes. + // + // Once the destructor returns you can be guaranteed that the callback will + // not be called by a subsequent call to 'requestCancellation()' on a + // CancellationSource associated with the CancellationToken passed to the + // constructor. + ~CancellationCallback(); + + // Not copyable/movable + CancellationCallback(const CancellationCallback&) = delete; + CancellationCallback(CancellationCallback&&) = delete; + CancellationCallback& operator=(const CancellationCallback&) = delete; + CancellationCallback& operator=(CancellationCallback&&) = delete; + + private: + friend class detail::CancellationState; + + void invokeCallback() noexcept; + + CancellationCallback* next_; + + // Pointer to the pointer that points to this node in the linked list. + // This could be the 'next_' of a previous CancellationCallback or could + // be the 'head_' pointer of the CancellationState. + // If this node is inserted in the list then this will be non-null. + CancellationCallback** prevNext_; + + detail::CancellationState* state_; + VoidFunction callback_; + + // Pointer to a flag stored on the stack of the caller to invokeCallback() + // that is used to indicate to the caller of invokeCallback() that the + // destructor has run and it is no longer valid to access the callback + // object. + bool* destructorHasRunInsideCallback_; + + // Flag used to signal that the callback has completed executing on another + // thread and it is now safe to exit the destructor. + std::atomic<bool> callbackCompleted_; +}; + +} // namespace folly + +#include <folly/CancellationToken-inl.h> diff --git a/ios/Pods/Folly/folly/Chrono.h b/ios/Pods/Folly/folly/Chrono.h index 06ca07fd3..3b3838b43 100644 --- a/ios/Pods/Folly/folly/Chrono.h +++ b/ios/Pods/Folly/folly/Chrono.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -31,11 +31,12 @@ * * std::chrono::round */ -#if __cpp_lib_chrono >= 201510 || _MSC_VER +#if __cpp_lib_chrono >= 201510 || _LIBCPP_STD_VER > 14 || _MSC_VER namespace folly { namespace chrono { +/* using override */ using std::chrono::abs; /* using override */ using std::chrono::ceil; /* using override */ using std::chrono::floor; /* using override */ using std::chrono::round; @@ -81,6 +82,18 @@ constexpr To round_impl(Duration const& d, To const& t0) { } } // namespace detail +// mimic: std::chrono::abs, C++17 +template < + typename Rep, + typename Period, + typename = typename std::enable_if< + std::chrono::duration<Rep, Period>::min() < + std::chrono::duration<Rep, Period>::zero()>::type> +constexpr std::chrono::duration<Rep, Period> abs( + std::chrono::duration<Rep, Period> const& d) { + return d < std::chrono::duration<Rep, Period>::zero() ? -d : d; +} + // mimic: std::chrono::ceil, C++17 // from: http://en.cppreference.com/w/cpp/chrono/duration/ceil, CC-BY-SA template < @@ -168,17 +181,18 @@ struct coarse_steady_clock { using time_point = std::chrono::time_point<coarse_steady_clock, duration>; constexpr static bool is_steady = true; - static time_point now() { + static time_point now() noexcept { #ifndef CLOCK_MONOTONIC_COARSE return time_point(std::chrono::duration_cast<duration>( std::chrono::steady_clock::now().time_since_epoch())); #else timespec ts; auto ret = clock_gettime(CLOCK_MONOTONIC_COARSE, &ts); - if (ret != 0) { + if (kIsDebug && (ret != 0)) { throw_exception<std::runtime_error>( "Error using CLOCK_MONOTONIC_COARSE."); } + return time_point(std::chrono::duration_cast<duration>( std::chrono::seconds(ts.tv_sec) + std::chrono::nanoseconds(ts.tv_nsec))); diff --git a/ios/Pods/Folly/folly/ClockGettimeWrappers.h b/ios/Pods/Folly/folly/ClockGettimeWrappers.h index dfb28f826..8c403193e 100644 --- a/ios/Pods/Folly/folly/ClockGettimeWrappers.h +++ b/ios/Pods/Folly/folly/ClockGettimeWrappers.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/AtomicBitSet.h b/ios/Pods/Folly/folly/ConcurrentBitSet.h similarity index 75% rename from ios/Pods/Folly/folly/AtomicBitSet.h rename to ios/Pods/Folly/folly/ConcurrentBitSet.h index 967821d3c..2be6e2162 100644 --- a/ios/Pods/Folly/folly/AtomicBitSet.h +++ b/ios/Pods/Folly/folly/ConcurrentBitSet.h @@ -1,11 +1,11 @@ /* - * Copyright 2013-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -22,22 +22,26 @@ #include <cstddef> #include <limits> -#include <boost/noncopyable.hpp> - #include <folly/Portability.h> namespace folly { /** * An atomic bitset of fixed size (specified at compile time). + * + * Formerly known as AtomicBitSet. It was renamed while fixing a bug + * to avoid any silent breakages during run time. */ template <size_t N> -class AtomicBitSet : private boost::noncopyable { +class ConcurrentBitSet { public: /** - * Construct an AtomicBitSet; all bits are initially false. + * Construct a ConcurrentBitSet; all bits are initially false. */ - AtomicBitSet(); + ConcurrentBitSet(); + + ConcurrentBitSet(const ConcurrentBitSet&) = delete; + ConcurrentBitSet& operator=(const ConcurrentBitSet&) = delete; /** * Set bit idx to true, using the given memory order. Returns the @@ -115,43 +119,44 @@ class AtomicBitSet : private boost::noncopyable { // avoid casts static constexpr BlockType kOne = 1; - - std::array<AtomicBlockType, N> data_; + static constexpr size_t kNumBlocks = (N + kBitsPerBlock - 1) / kBitsPerBlock; + std::array<AtomicBlockType, kNumBlocks> data_; }; // value-initialize to zero template <size_t N> -inline AtomicBitSet<N>::AtomicBitSet() : data_() {} +inline ConcurrentBitSet<N>::ConcurrentBitSet() : data_() {} template <size_t N> -inline bool AtomicBitSet<N>::set(size_t idx, std::memory_order order) { - assert(idx < N * kBitsPerBlock); +inline bool ConcurrentBitSet<N>::set(size_t idx, std::memory_order order) { + assert(idx < N); BlockType mask = kOne << bitOffset(idx); return data_[blockIndex(idx)].fetch_or(mask, order) & mask; } template <size_t N> -inline bool AtomicBitSet<N>::reset(size_t idx, std::memory_order order) { - assert(idx < N * kBitsPerBlock); +inline bool ConcurrentBitSet<N>::reset(size_t idx, std::memory_order order) { + assert(idx < N); BlockType mask = kOne << bitOffset(idx); return data_[blockIndex(idx)].fetch_and(~mask, order) & mask; } template <size_t N> inline bool -AtomicBitSet<N>::set(size_t idx, bool value, std::memory_order order) { +ConcurrentBitSet<N>::set(size_t idx, bool value, std::memory_order order) { return value ? set(idx, order) : reset(idx, order); } template <size_t N> -inline bool AtomicBitSet<N>::test(size_t idx, std::memory_order order) const { - assert(idx < N * kBitsPerBlock); +inline bool ConcurrentBitSet<N>::test(size_t idx, std::memory_order order) + const { + assert(idx < N); BlockType mask = kOne << bitOffset(idx); return data_[blockIndex(idx)].load(order) & mask; } template <size_t N> -inline bool AtomicBitSet<N>::operator[](size_t idx) const { +inline bool ConcurrentBitSet<N>::operator[](size_t idx) const { return test(idx); } diff --git a/ios/Pods/Folly/folly/ConcurrentSkipList-inl.h b/ios/Pods/Folly/folly/ConcurrentSkipList-inl.h index a4e5ddbcf..a0eec3076 100644 --- a/ios/Pods/Folly/folly/ConcurrentSkipList-inl.h +++ b/ios/Pods/Folly/folly/ConcurrentSkipList-inl.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -27,9 +27,7 @@ #include <type_traits> #include <vector> -#include <boost/noncopyable.hpp> #include <boost/random.hpp> -#include <boost/type_traits.hpp> #include <glog/logging.h> #include <folly/Memory.h> @@ -43,7 +41,7 @@ template <typename ValT, typename NodeT> class csl_iterator; template <typename T> -class SkipListNode : private boost::noncopyable { +class SkipListNode { enum : uint16_t { IS_HEAD_NODE = 1, MARKED_FOR_REMOVAL = (1 << 1), @@ -53,6 +51,9 @@ class SkipListNode : private boost::noncopyable { public: typedef T value_type; + SkipListNode(const SkipListNode&) = delete; + SkipListNode& operator=(const SkipListNode&) = delete; + template < typename NodeAlloc, typename U, @@ -81,7 +82,7 @@ class SkipListNode : private boost::noncopyable { template <typename NodeAlloc> struct DestroyIsNoOp : StrictConjunction< AllocatorHasTrivialDeallocate<NodeAlloc>, - boost::has_trivial_destructor<SkipListNode>> {}; + std::is_trivially_destructible<SkipListNode>> {}; // copy the head node to a new head node assuming lock acquired SkipListNode* copyHead(SkipListNode* node) { diff --git a/ios/Pods/Folly/folly/ConcurrentSkipList.h b/ios/Pods/Folly/folly/ConcurrentSkipList.h index 1e7638c7f..ab75ce397 100644 --- a/ios/Pods/Folly/folly/ConcurrentSkipList.h +++ b/ios/Pods/Folly/folly/ConcurrentSkipList.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -125,12 +125,12 @@ Sample usage: #include <memory> #include <type_traits> -#include <boost/iterator/iterator_facade.hpp> #include <glog/logging.h> #include <folly/ConcurrentSkipList-inl.h> #include <folly/Likely.h> #include <folly/Memory.h> +#include <folly/detail/Iterators.h> #include <folly/synchronization/MicroSpinLock.h> namespace folly { @@ -158,7 +158,7 @@ class ConcurrentSkipList { typedef T key_type; typedef detail::csl_iterator<value_type, NodeType> iterator; - typedef detail::csl_iterator<const value_type, const NodeType> const_iterator; + typedef detail::csl_iterator<const value_type, NodeType> const_iterator; class Accessor; class Skipper; @@ -709,10 +709,10 @@ class ConcurrentSkipList<T, Comp, NodeAlloc, MAX_HEIGHT>::Accessor { // implements forward iterator concept. template <typename ValT, typename NodeT> -class detail::csl_iterator : public boost::iterator_facade< +class detail::csl_iterator : public detail::IteratorFacade< csl_iterator<ValT, NodeT>, ValT, - boost::forward_traversal_tag> { + std::forward_iterator_tag> { public: typedef ValT value_type; typedef value_type& reference; @@ -738,9 +738,10 @@ class detail::csl_iterator : public boost::iterator_facade< } private: - friend class boost::iterator_core_access; template <class, class> friend class csl_iterator; + friend class detail:: + IteratorFacade<csl_iterator, ValT, std::forward_iterator_tag>; void increment() { node_ = node_->next(); diff --git a/ios/Pods/Folly/folly/ConstexprMath.h b/ios/Pods/Folly/folly/ConstexprMath.h index 3dae93a2c..4a70ff6cd 100644 --- a/ios/Pods/Folly/folly/ConstexprMath.h +++ b/ios/Pods/Folly/folly/ConstexprMath.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -17,49 +17,11 @@ #pragma once #include <cstdint> +#include <functional> #include <limits> #include <type_traits> namespace folly { - -// TODO: Replace with std::equal_to, etc., after upgrading to C++14. -template <typename T> -struct constexpr_equal_to { - constexpr bool operator()(T const& a, T const& b) const { - return a == b; - } -}; -template <typename T> -struct constexpr_not_equal_to { - constexpr bool operator()(T const& a, T const& b) const { - return a != b; - } -}; -template <typename T> -struct constexpr_less { - constexpr bool operator()(T const& a, T const& b) const { - return a < b; - } -}; -template <typename T> -struct constexpr_less_equal { - constexpr bool operator()(T const& a, T const& b) const { - return a <= b; - } -}; -template <typename T> -struct constexpr_greater { - constexpr bool operator()(T const& a, T const& b) const { - return a > b; - } -}; -template <typename T> -struct constexpr_greater_equal { - constexpr bool operator()(T const& a, T const& b) const { - return a >= b; - } -}; - // TLDR: Prefer using operator< for ordering. And when // a and b are equivalent objects, we return b to make // sorting stable. @@ -91,7 +53,7 @@ constexpr_clamp(T const& v, T const& lo, T const& hi, Less less) { } template <typename T> constexpr T const& constexpr_clamp(T const& v, T const& lo, T const& hi) { - return constexpr_clamp(v, lo, hi, constexpr_less<T>{}); + return constexpr_clamp(v, lo, hi, std::less<T>{}); } namespace detail { diff --git a/ios/Pods/Folly/folly/Conv.cpp b/ios/Pods/Folly/folly/Conv.cpp index 76e14c982..d74df582f 100644 --- a/ios/Pods/Folly/folly/Conv.cpp +++ b/ios/Pods/Folly/folly/Conv.cpp @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include <folly/Conv.h> #include <array> @@ -275,7 +276,7 @@ Expected<bool, ConversionCode> str_to_bool(StringPiece* src) noexcept { } bool result; - size_t len = size_t(e - b); + auto len = size_t(e - b); switch (*b) { case '0': case '1': { @@ -399,7 +400,7 @@ Expected<Tgt, ConversionCode> str_to_floating(StringPiece* src) noexcept { // There must be non-whitespace, otherwise we would have caught this above assert(b < e); - size_t size = size_t(e - b); + auto size = size_t(e - b); bool negative = false; if (*b == '-') { @@ -543,7 +544,7 @@ inline Expected<Tgt, ConversionCode> digits_to( return makeUnexpected(err); } - size_t size = size_t(e - b); + auto size = size_t(e - b); /* Although the string is entirely made of digits, we still need to * check for overflow. @@ -777,7 +778,7 @@ ConversionError makeConversionError(ConversionCode code, StringPiece input) { if (err.quote) { tmp.append(1, '"'); } - if (input.size() > 0) { + if (!input.empty()) { tmp.append(input.data(), input.size()); } if (err.quote) { diff --git a/ios/Pods/Folly/folly/Conv.h b/ios/Pods/Folly/folly/Conv.h index b187d01a6..b6c0b87e1 100644 --- a/ios/Pods/Folly/folly/Conv.h +++ b/ios/Pods/Folly/folly/Conv.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -15,15 +15,92 @@ */ /** - * Converts anything to anything, with an emphasis on performance and - * safety. * - * @author Andrei Alexandrescu (andrei.alexandrescu@fb.com) + * This file provides a generic interface for converting objects to and from + * string-like types (std::string, fbstring, StringPiece), as well as + * range-checked conversions between numeric and enum types. The mechanisms are + * extensible, so that user-specified types can add folly::to support. + * + ******************************************************************************* + * TYPE -> STRING CONVERSIONS + ******************************************************************************* + * You can call the to<std::string> or to<fbstring>. These are variadic + * functions that convert their arguments to strings, and concatenate them to + * form a result. So, for example, + * + * auto str = to<std::string>(123, "456", 789); + * + * Sets str to "123456789". + * + * In addition to just concatenating the arguments, related functions can + * delimit them with some string: toDelim<std::string>(",", "123", 456, "789") + * will return the string "123,456,789". + * + * toAppend does not return a string; instead, it takes a pointer to a string as + * its last argument, and appends the result of the concatenation into it: + * std::string str = "123"; + * toAppend(456, "789", &str); // Now str is "123456789". + * + * The toAppendFit function acts like toAppend, but it precalculates the size + * required to perform the append operation, and reserves that space in the + * output string before actually inserting its arguments. This can sometimes + * save on string expansion, but beware: appending to the same string many times + * with toAppendFit is likely a pessimization, since it will resize the string + * once per append. + * + * The combination of the append and delim variants also exist: toAppendDelim + * and toAppendDelimFit are defined, with the obvious semantics. + * + ******************************************************************************* + * STRING -> TYPE CONVERSIONS + ******************************************************************************* + * Going in the other direction, and parsing a string into a C++ type, is also + * supported: + * to<int>("123"); // Returns 123. + * + * Out of range (e.g. to<std::uint8_t>("1000")), or invalidly formatted (e.g. + * to<int>("four")) inputs will throw. If throw-on-error is undesirable (for + * instance: you're dealing with untrusted input, and want to protect yourself + * from users sending you down a very slow exception-throwing path), you can use + * tryTo<T>, which will return an Expected<T, ConversionCode>. + * + * There are overloads of to() and tryTo() that take a StringPiece*. These parse + * out a type from the beginning of a string, and modify the passed-in + * StringPiece to indicate the portion of the string not consumed. + * + ******************************************************************************* + * NUMERIC / ENUM CONVERSIONS + ******************************************************************************* + * Conv also supports a to<T>(S) overload, where T and S are numeric or enum + * types, that checks to see that the target type can represent its argument, + * and will throw if it cannot. This includes cases where a floating point -> + * integral conversion is attempted on a value with a non-zero fractional + * component, and integral -> floating point conversions that would lose + * precision. Enum conversions are range-checked for the underlying type of the + * enum, but there is no check that the input value is a valid choice of enum + * value. + * + ******************************************************************************* + * CUSTOM TYPE CONVERSIONS + ******************************************************************************* + * Users may customize the string conversion functionality for their own data + * types, . The key functions you should implement are: + * // Two functions to allow conversion to your type from a string. + * Expected<StringPiece, ConversionCode> parseTo(folly::StringPiece in, + * YourType& out); + * YourErrorType makeConversionError(YourErrorType in, StringPiece in); + * // Two functions to allow conversion from your type to a string. + * template <class String> + * void toAppend(const YourType& in, String* out); + * size_t estimateSpaceNeeded(const YourType& in); + * + * These are documented below, inline. */ #pragma once #include <algorithm> +#include <cassert> #include <cctype> #include <climits> #include <cstddef> @@ -32,7 +109,6 @@ #include <string> #include <tuple> #include <type_traits> -#include <typeinfo> #include <utility> #include <double-conversion/double-conversion.h> // V8 JavaScript implementation @@ -44,7 +120,9 @@ #include <folly/Range.h> #include <folly/Traits.h> #include <folly/Unit.h> +#include <folly/Utility.h> #include <folly/lang/Exception.h> +#include <folly/lang/Pretty.h> #include <folly/portability/Math.h> namespace folly { @@ -109,7 +187,7 @@ class ConversionError : public ConversionErrorBase { * return YourConversionError(messageString); * } ******************************************************************************/ -ConversionError makeConversionError(ConversionCode code, StringPiece sp); +ConversionError makeConversionError(ConversionCode code, StringPiece input); namespace detail { /** @@ -648,15 +726,13 @@ template <class Tgt, class Src> typename std::enable_if< std::is_enum<Src>::value && IsSomeString<Tgt>::value>::type toAppend(Src value, Tgt* result) { - toAppend( - static_cast<typename std::underlying_type<Src>::type>(value), result); + toAppend(to_underlying(value), result); } template <class Src> typename std::enable_if<std::is_enum<Src>::value, size_t>::type estimateSpaceNeeded(Src value) { - return estimateSpaceNeeded( - static_cast<typename std::underlying_type<Src>::type>(value)); + return estimateSpaceNeeded(to_underlying(value)); } /******************************************************************************* @@ -699,8 +775,9 @@ toAppend( case DoubleToStringConverter::FIXED: conv.ToFixed(value, int(numDigits), &builder); break; + case DoubleToStringConverter::PRECISION: default: - CHECK(mode == DoubleToStringConverter::PRECISION); + assert(mode == DoubleToStringConverter::PRECISION); conv.ToPrecision(value, int(numDigits), &builder); break; } @@ -1216,8 +1293,8 @@ typename std::enable_if< Expected<Tgt, ConversionCode>>::type convertTo(const Src& value) noexcept { if /* constexpr */ ( - folly::_t<std::make_unsigned<Tgt>>(std::numeric_limits<Tgt>::max()) < - folly::_t<std::make_unsigned<Src>>(std::numeric_limits<Src>::max())) { + std::make_unsigned_t<Tgt>(std::numeric_limits<Tgt>::max()) < + std::make_unsigned_t<Src>(std::numeric_limits<Src>::max())) { if (greater_than<Tgt, std::numeric_limits<Tgt>::max()>(value)) { return makeUnexpected(ConversionCode::ARITH_POSITIVE_OVERFLOW); } @@ -1335,11 +1412,7 @@ convertTo(const Src& value) noexcept { template <typename Tgt, typename Src> inline std::string errorValue(const Src& value) { -#ifdef FOLLY_HAS_RTTI - return to<std::string>("(", demangle(typeid(Tgt)), ") ", value); -#else - return to<std::string>(value); -#endif + return to<std::string>("(", pretty_name<Tgt>(), ") ", value); } template <typename Tgt, typename Src> @@ -1551,8 +1624,7 @@ typename std::enable_if< !std::is_convertible<Tgt, StringPiece>::value, Expected<Tgt, ConversionCode>>::type tryTo(const Src& value) { - using I = typename std::underlying_type<Src>::type; - return tryTo<Tgt>(static_cast<I>(value)); + return tryTo<Tgt>(to_underlying(value)); } template <class Tgt, class Src> @@ -1571,7 +1643,7 @@ typename std::enable_if< !std::is_convertible<Tgt, StringPiece>::value, Tgt>::type to(const Src& value) { - return to<Tgt>(static_cast<typename std::underlying_type<Src>::type>(value)); + return to<Tgt>(to_underlying(value)); } template <class Tgt, class Src> diff --git a/ios/Pods/Folly/folly/CppAttributes.h b/ios/Pods/Folly/folly/CppAttributes.h index 00cc39332..cd02fa3fd 100644 --- a/ios/Pods/Folly/folly/CppAttributes.h +++ b/ios/Pods/Folly/folly/CppAttributes.h @@ -1,11 +1,11 @@ /* - * Copyright 2015-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/CpuId.h b/ios/Pods/Folly/folly/CpuId.h index 8d92f8b7b..517ccb571 100644 --- a/ios/Pods/Folly/folly/CpuId.h +++ b/ios/Pods/Folly/folly/CpuId.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -105,108 +105,108 @@ class CpuId { #endif } -#define X(name, r, bit) \ - FOLLY_ALWAYS_INLINE bool name() const { \ - return ((r) & (1U << bit)) != 0; \ +#define FOLLY_DETAIL_CPUID_X(name, r, bit) \ + FOLLY_ALWAYS_INLINE bool name() const { \ + return ((r) & (1U << bit)) != 0; \ } // cpuid(1): Processor Info and Feature Bits. -#define C(name, bit) X(name, f1c_, bit) - C(sse3, 0) - C(pclmuldq, 1) - C(dtes64, 2) - C(monitor, 3) - C(dscpl, 4) - C(vmx, 5) - C(smx, 6) - C(eist, 7) - C(tm2, 8) - C(ssse3, 9) - C(cnxtid, 10) - C(fma, 12) - C(cx16, 13) - C(xtpr, 14) - C(pdcm, 15) - C(pcid, 17) - C(dca, 18) - C(sse41, 19) - C(sse42, 20) - C(x2apic, 21) - C(movbe, 22) - C(popcnt, 23) - C(tscdeadline, 24) - C(aes, 25) - C(xsave, 26) - C(osxsave, 27) - C(avx, 28) - C(f16c, 29) - C(rdrand, 30) -#undef C -#define D(name, bit) X(name, f1d_, bit) - D(fpu, 0) - D(vme, 1) - D(de, 2) - D(pse, 3) - D(tsc, 4) - D(msr, 5) - D(pae, 6) - D(mce, 7) - D(cx8, 8) - D(apic, 9) - D(sep, 11) - D(mtrr, 12) - D(pge, 13) - D(mca, 14) - D(cmov, 15) - D(pat, 16) - D(pse36, 17) - D(psn, 18) - D(clfsh, 19) - D(ds, 21) - D(acpi, 22) - D(mmx, 23) - D(fxsr, 24) - D(sse, 25) - D(sse2, 26) - D(ss, 27) - D(htt, 28) - D(tm, 29) - D(pbe, 31) -#undef D +#define FOLLY_DETAIL_CPUID_C(name, bit) FOLLY_DETAIL_CPUID_X(name, f1c_, bit) + FOLLY_DETAIL_CPUID_C(sse3, 0) + FOLLY_DETAIL_CPUID_C(pclmuldq, 1) + FOLLY_DETAIL_CPUID_C(dtes64, 2) + FOLLY_DETAIL_CPUID_C(monitor, 3) + FOLLY_DETAIL_CPUID_C(dscpl, 4) + FOLLY_DETAIL_CPUID_C(vmx, 5) + FOLLY_DETAIL_CPUID_C(smx, 6) + FOLLY_DETAIL_CPUID_C(eist, 7) + FOLLY_DETAIL_CPUID_C(tm2, 8) + FOLLY_DETAIL_CPUID_C(ssse3, 9) + FOLLY_DETAIL_CPUID_C(cnxtid, 10) + FOLLY_DETAIL_CPUID_C(fma, 12) + FOLLY_DETAIL_CPUID_C(cx16, 13) + FOLLY_DETAIL_CPUID_C(xtpr, 14) + FOLLY_DETAIL_CPUID_C(pdcm, 15) + FOLLY_DETAIL_CPUID_C(pcid, 17) + FOLLY_DETAIL_CPUID_C(dca, 18) + FOLLY_DETAIL_CPUID_C(sse41, 19) + FOLLY_DETAIL_CPUID_C(sse42, 20) + FOLLY_DETAIL_CPUID_C(x2apic, 21) + FOLLY_DETAIL_CPUID_C(movbe, 22) + FOLLY_DETAIL_CPUID_C(popcnt, 23) + FOLLY_DETAIL_CPUID_C(tscdeadline, 24) + FOLLY_DETAIL_CPUID_C(aes, 25) + FOLLY_DETAIL_CPUID_C(xsave, 26) + FOLLY_DETAIL_CPUID_C(osxsave, 27) + FOLLY_DETAIL_CPUID_C(avx, 28) + FOLLY_DETAIL_CPUID_C(f16c, 29) + FOLLY_DETAIL_CPUID_C(rdrand, 30) +#undef FOLLY_DETAIL_CPUID_C +#define FOLLY_DETAIL_CPUID_D(name, bit) FOLLY_DETAIL_CPUID_X(name, f1d_, bit) + FOLLY_DETAIL_CPUID_D(fpu, 0) + FOLLY_DETAIL_CPUID_D(vme, 1) + FOLLY_DETAIL_CPUID_D(de, 2) + FOLLY_DETAIL_CPUID_D(pse, 3) + FOLLY_DETAIL_CPUID_D(tsc, 4) + FOLLY_DETAIL_CPUID_D(msr, 5) + FOLLY_DETAIL_CPUID_D(pae, 6) + FOLLY_DETAIL_CPUID_D(mce, 7) + FOLLY_DETAIL_CPUID_D(cx8, 8) + FOLLY_DETAIL_CPUID_D(apic, 9) + FOLLY_DETAIL_CPUID_D(sep, 11) + FOLLY_DETAIL_CPUID_D(mtrr, 12) + FOLLY_DETAIL_CPUID_D(pge, 13) + FOLLY_DETAIL_CPUID_D(mca, 14) + FOLLY_DETAIL_CPUID_D(cmov, 15) + FOLLY_DETAIL_CPUID_D(pat, 16) + FOLLY_DETAIL_CPUID_D(pse36, 17) + FOLLY_DETAIL_CPUID_D(psn, 18) + FOLLY_DETAIL_CPUID_D(clfsh, 19) + FOLLY_DETAIL_CPUID_D(ds, 21) + FOLLY_DETAIL_CPUID_D(acpi, 22) + FOLLY_DETAIL_CPUID_D(mmx, 23) + FOLLY_DETAIL_CPUID_D(fxsr, 24) + FOLLY_DETAIL_CPUID_D(sse, 25) + FOLLY_DETAIL_CPUID_D(sse2, 26) + FOLLY_DETAIL_CPUID_D(ss, 27) + FOLLY_DETAIL_CPUID_D(htt, 28) + FOLLY_DETAIL_CPUID_D(tm, 29) + FOLLY_DETAIL_CPUID_D(pbe, 31) +#undef FOLLY_DETAIL_CPUID_D // cpuid(7): Extended Features. -#define B(name, bit) X(name, f7b_, bit) - B(bmi1, 3) - B(hle, 4) - B(avx2, 5) - B(smep, 7) - B(bmi2, 8) - B(erms, 9) - B(invpcid, 10) - B(rtm, 11) - B(mpx, 14) - B(avx512f, 16) - B(avx512dq, 17) - B(rdseed, 18) - B(adx, 19) - B(smap, 20) - B(avx512ifma, 21) - B(pcommit, 22) - B(clflushopt, 23) - B(clwb, 24) - B(avx512pf, 26) - B(avx512er, 27) - B(avx512cd, 28) - B(sha, 29) - B(avx512bw, 30) - B(avx512vl, 31) -#undef B -#define C(name, bit) X(name, f7c_, bit) - C(prefetchwt1, 0) - C(avx512vbmi, 1) -#undef C +#define FOLLY_DETAIL_CPUID_B(name, bit) FOLLY_DETAIL_CPUID_X(name, f7b_, bit) + FOLLY_DETAIL_CPUID_B(bmi1, 3) + FOLLY_DETAIL_CPUID_B(hle, 4) + FOLLY_DETAIL_CPUID_B(avx2, 5) + FOLLY_DETAIL_CPUID_B(smep, 7) + FOLLY_DETAIL_CPUID_B(bmi2, 8) + FOLLY_DETAIL_CPUID_B(erms, 9) + FOLLY_DETAIL_CPUID_B(invpcid, 10) + FOLLY_DETAIL_CPUID_B(rtm, 11) + FOLLY_DETAIL_CPUID_B(mpx, 14) + FOLLY_DETAIL_CPUID_B(avx512f, 16) + FOLLY_DETAIL_CPUID_B(avx512dq, 17) + FOLLY_DETAIL_CPUID_B(rdseed, 18) + FOLLY_DETAIL_CPUID_B(adx, 19) + FOLLY_DETAIL_CPUID_B(smap, 20) + FOLLY_DETAIL_CPUID_B(avx512ifma, 21) + FOLLY_DETAIL_CPUID_B(pcommit, 22) + FOLLY_DETAIL_CPUID_B(clflushopt, 23) + FOLLY_DETAIL_CPUID_B(clwb, 24) + FOLLY_DETAIL_CPUID_B(avx512pf, 26) + FOLLY_DETAIL_CPUID_B(avx512er, 27) + FOLLY_DETAIL_CPUID_B(avx512cd, 28) + FOLLY_DETAIL_CPUID_B(sha, 29) + FOLLY_DETAIL_CPUID_B(avx512bw, 30) + FOLLY_DETAIL_CPUID_B(avx512vl, 31) +#undef FOLLY_DETAIL_CPUID_B +#define FOLLY_DETAIL_CPUID_C(name, bit) FOLLY_DETAIL_CPUID_X(name, f7c_, bit) + FOLLY_DETAIL_CPUID_C(prefetchwt1, 0) + FOLLY_DETAIL_CPUID_C(avx512vbmi, 1) +#undef FOLLY_DETAIL_CPUID_C -#undef X +#undef FOLLY_DETAIL_CPUID_X private: uint32_t f1c_ = 0; diff --git a/ios/Pods/Folly/folly/DefaultKeepAliveExecutor.h b/ios/Pods/Folly/folly/DefaultKeepAliveExecutor.h index 5f8b8ea95..c5d7f6065 100644 --- a/ios/Pods/Folly/folly/DefaultKeepAliveExecutor.h +++ b/ios/Pods/Folly/folly/DefaultKeepAliveExecutor.h @@ -1,11 +1,11 @@ /* - * Copyright 2018-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -46,6 +46,15 @@ class DefaultKeepAliveExecutor : public virtual Executor { keepAliveReleaseBaton_.wait(); } + void joinAndResetKeepAlive() { + joinKeepAlive(); + auto keepAliveCount = + controlBlock_->keepAliveCount_.exchange(1, std::memory_order_relaxed); + DCHECK_EQ(keepAliveCount, 0); + keepAliveReleaseBaton_.reset(); + keepAlive_ = makeKeepAlive(this); + } + private: struct ControlBlock { std::atomic<ssize_t> keepAliveCount_{1}; @@ -143,8 +152,7 @@ class DefaultKeepAliveExecutor : public virtual Executor { std::shared_ptr<ControlBlock> controlBlock_{std::make_shared<ControlBlock>()}; Baton<> keepAliveReleaseBaton_; - KeepAlive<DefaultKeepAliveExecutor> keepAlive_{ - makeKeepAlive<DefaultKeepAliveExecutor>(this)}; + KeepAlive<DefaultKeepAliveExecutor> keepAlive_{makeKeepAlive(this)}; }; } // namespace folly diff --git a/ios/Pods/Folly/folly/Demangle.cpp b/ios/Pods/Folly/folly/Demangle.cpp index c51632135..0df902c00 100644 --- a/ios/Pods/Folly/folly/Demangle.cpp +++ b/ios/Pods/Folly/folly/Demangle.cpp @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -20,6 +20,7 @@ #include <cstring> #include <folly/detail/Demangle.h> +#include <folly/lang/CString.h> #include <folly/portability/Config.h> #if FOLLY_DETAIL_HAVE_DEMANGLE_H @@ -33,6 +34,9 @@ namespace folly { #if FOLLY_DETAIL_HAVE_DEMANGLE_H fbstring demangle(const char* name) { + if (!name) { + return fbstring(); + } #ifdef FOLLY_DEMANGLE_MAX_SYMBOL_SIZE // GCC's __cxa_demangle() uses on-stack data structures for the // parser state which are linear in the number of components of the @@ -118,14 +122,4 @@ size_t demangle(const char* name, char* out, size_t outSize) { #endif -size_t strlcpy(char* dest, const char* const src, size_t size) { - size_t len = strlen(src); - if (size != 0) { - size_t n = std::min(len, size - 1); // always null terminate! - memcpy(dest, src, n); - dest[n] = '\0'; - } - return len; -} - } // namespace folly diff --git a/ios/Pods/Folly/folly/Demangle.h b/ios/Pods/Folly/folly/Demangle.h index 13537dd50..da13fb178 100644 --- a/ios/Pods/Folly/folly/Demangle.h +++ b/ios/Pods/Folly/folly/Demangle.h @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -54,12 +54,9 @@ inline fbstring demangle(const std::type_info& type) { * libiberty), so it is possible for the fbstring version to work, while this * version returns the original, mangled name. */ -size_t demangle(const char* name, char* buf, size_t bufSize); +size_t demangle(const char* name, char* out, size_t outSize); inline size_t demangle(const std::type_info& type, char* buf, size_t bufSize) { return demangle(type.name(), buf, bufSize); } -// glibc doesn't have strlcpy -size_t strlcpy(char* dest, const char* const src, size_t size); - } // namespace folly diff --git a/ios/Pods/Folly/folly/DiscriminatedPtr.h b/ios/Pods/Folly/folly/DiscriminatedPtr.h index dab199787..0f49bd688 100644 --- a/ios/Pods/Folly/folly/DiscriminatedPtr.h +++ b/ios/Pods/Folly/folly/DiscriminatedPtr.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/DynamicConverter.h b/ios/Pods/Folly/folly/DynamicConverter.h index 1f323fd0d..04aec594e 100644 --- a/ios/Pods/Folly/folly/DynamicConverter.h +++ b/ios/Pods/Folly/folly/DynamicConverter.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -27,7 +27,9 @@ #include <folly/Likely.h> #include <folly/Optional.h> #include <folly/Traits.h> +#include <folly/Utility.h> #include <folly/dynamic.h> +#include <folly/lang/Exception.h> namespace folly { template <typename T> @@ -110,7 +112,7 @@ struct Dereferencer { static inline void derefToCache( Optional<T>* /* mem */, const dynamic::const_item_iterator& /* it */) { - throw TypeError("array", dynamic::Type::OBJECT); + throw_exception<TypeError>("array", dynamic::Type::OBJECT); } static inline void derefToCache( @@ -249,7 +251,7 @@ struct DynamicConverter<std::pair<F, S>> { auto it = d.items().begin(); return std::make_pair(convertTo<F>(it->first), convertTo<S>(it->second)); } else { - throw TypeError("array (size 2) or object (size 1)", d.type()); + throw_exception<TypeError>("array (size 2) or object (size 1)", d.type()); } } }; @@ -271,7 +273,7 @@ struct DynamicConverter< dynamicconverter_detail::conversionIterator<C>(d.items().begin()), dynamicconverter_detail::conversionIterator<C>(d.items().end())); } else { - throw TypeError("object or array", d.type()); + throw_exception<TypeError>("object or array", d.type()); } } }; @@ -295,7 +297,7 @@ struct DynamicConverter< dynamicconverter_detail::conversionIterator<C>(d.items().begin()), dynamicconverter_detail::conversionIterator<C>(d.items().end())); } else { - throw TypeError("object or array", d.type()); + throw_exception<TypeError>("object or array", d.type()); } return ret; } @@ -327,6 +329,16 @@ struct DynamicConstructor< } }; +// enums +template <typename C> +struct DynamicConstructor< + C, + typename std::enable_if<std::is_enum<C>::value>::type> { + static dynamic construct(const C& x) { + return dynamic(to_underlying(x)); + } +}; + // maps template <typename C> struct DynamicConstructor< diff --git a/ios/Pods/Folly/folly/Exception.h b/ios/Pods/Folly/folly/Exception.h index 19d7509d1..b050d641d 100644 --- a/ios/Pods/Folly/folly/Exception.h +++ b/ios/Pods/Folly/folly/Exception.h @@ -1,11 +1,11 @@ /* - * Copyright 2013-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -63,12 +63,12 @@ std::system_error makeSystemError(Args&&... args) { // Helper to throw std::system_error [[noreturn]] inline void throwSystemErrorExplicit(int err, const char* msg) { - throw makeSystemErrorExplicit(err, msg); + throw_exception(makeSystemErrorExplicit(err, msg)); } template <class... Args> [[noreturn]] void throwSystemErrorExplicit(int err, Args&&... args) { - throw makeSystemErrorExplicit(err, std::forward<Args>(args)...); + throw_exception(makeSystemErrorExplicit(err, std::forward<Args>(args)...)); } // Helper to throw std::system_error from errno and components of a string @@ -132,11 +132,11 @@ void checkFopenErrorExplicit(FILE* fp, int savedErrno, Args&&... args) { * If cond is not true, raise an exception of type E. E must have a ctor that * works with const char* (a description of the failure). */ -#define CHECK_THROW(cond, E) \ - do { \ - if (!(cond)) { \ - throw E("Check failed: " #cond); \ - } \ +#define CHECK_THROW(cond, E) \ + do { \ + if (!(cond)) { \ + folly::throw_exception<E>("Check failed: " #cond); \ + } \ } while (0) } // namespace folly diff --git a/ios/Pods/Folly/folly/ExceptionString.h b/ios/Pods/Folly/folly/ExceptionString.h index 5c3a2760c..13042ead4 100644 --- a/ios/Pods/Folly/folly/ExceptionString.h +++ b/ios/Pods/Folly/folly/ExceptionString.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -31,7 +31,7 @@ namespace folly { * defined. */ inline fbstring exceptionStr(const std::exception& e) { -#ifdef FOLLY_HAS_RTTI +#if FOLLY_HAS_RTTI fbstring rv(demangle(typeid(e))); rv += ": "; #else @@ -41,29 +41,27 @@ inline fbstring exceptionStr(const std::exception& e) { return rv; } -// Empirically, this indicates if the runtime supports -// std::exception_ptr, as not all (arm, for instance) do. -#if defined(__GNUC__) && defined(__GCC_ATOMIC_INT_LOCK_FREE) && \ - __GCC_ATOMIC_INT_LOCK_FREE > 1 inline fbstring exceptionStr(std::exception_ptr ep) { - try { - std::rethrow_exception(ep); - } catch (const std::exception& e) { - return exceptionStr(e); - } catch (...) { - return "<unknown exception>"; + if (!kHasExceptions) { + return "Exception (catch unavailable)"; } + return catch_exception( + [&]() -> fbstring { + return catch_exception<std::exception const&>( + [&]() -> fbstring { std::rethrow_exception(ep); }, + [](auto&& e) { return exceptionStr(e); }); + }, + []() -> fbstring { return "<unknown exception>"; }); } -#endif template <typename E> auto exceptionStr(const E& e) -> typename std:: enable_if<!std::is_base_of<std::exception, E>::value, fbstring>::type { -#ifdef FOLLY_HAS_RTTI +#if FOLLY_HAS_RTTI return demangle(typeid(e)); #else (void)e; - return "Exception (no RTTI available) "; + return "Exception (no RTTI available)"; #endif } diff --git a/ios/Pods/Folly/folly/ExceptionWrapper-inl.h b/ios/Pods/Folly/folly/ExceptionWrapper-inl.h index a585e74cc..16fb5d4b6 100644 --- a/ios/Pods/Folly/folly/ExceptionWrapper-inl.h +++ b/ios/Pods/Folly/folly/ExceptionWrapper-inl.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + /* * * Author: Eric Niebler <eniebler@fb.com> @@ -201,7 +202,7 @@ inline void exception_wrapper::InPlace<Ex>::delete_(exception_wrapper* that) { template <class Ex> [[noreturn]] inline void exception_wrapper::InPlace<Ex>::throw_( exception_wrapper const* that) { - throw that->buff_.as<Ex>(); // @nolint + throw that->buff_.as<Ex>(); } template <class Ex> inline std::type_info const* exception_wrapper::InPlace<Ex>::type_( @@ -226,7 +227,7 @@ inline exception_wrapper exception_wrapper::InPlace<Ex>::get_exception_ptr_( template <class Ex> [[noreturn]] inline void exception_wrapper::SharedPtr::Impl<Ex>::throw_() const { - throw ex_; // @nolint + throw ex_; } template <class Ex> inline std::exception const* @@ -343,7 +344,7 @@ inline exception_wrapper::exception_wrapper( namespace exception_wrapper_detail { template <class Ex> Ex&& dont_slice(Ex&& ex) { - assert(typeid(ex) == typeid(_t<std::decay<Ex>>) || + assert(typeid(ex) == typeid(std::decay_t<Ex>) || !"Dynamic and static exception types don't match. Exception would " "be sliced when storing in exception_wrapper."); return std::forward<Ex>(ex); @@ -479,12 +480,12 @@ template <class Ex> template <class CatchFn, bool IsConst> struct exception_wrapper::ExceptionTypeOf { - using type = arg_type<_t<std::decay<CatchFn>>>; + using type = arg_type<std::decay_t<CatchFn>>; static_assert( std::is_reference<type>::value, "Always catch exceptions by reference."); static_assert( - !IsConst || std::is_const<_t<std::remove_reference<type>>>::value, + !IsConst || std::is_const<std::remove_reference_t<type>>::value, "handle() or with_exception() called on a const exception_wrapper " "and asked to catch a non-const exception. Handler will never fire. " "Catch exception by const reference to fix this."); @@ -550,7 +551,7 @@ struct exception_wrapper::HandleStdExceptReduce { return [th = std::forward<ThrowFn>(th), &ca](auto&& continuation) -> StdEx* { if (auto e = const_cast<StdEx*>(th(continuation))) { - if (auto e2 = dynamic_cast<_t<std::add_pointer<Ex>>>(e)) { + if (auto e2 = dynamic_cast<std::add_pointer_t<Ex>>(e)) { ca(*e2); } else { return e; diff --git a/ios/Pods/Folly/folly/ExceptionWrapper.h b/ios/Pods/Folly/folly/ExceptionWrapper.h index 3bdc7ae02..8fb287b7d 100644 --- a/ios/Pods/Folly/folly/ExceptionWrapper.h +++ b/ios/Pods/Folly/folly/ExceptionWrapper.h @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + /* * Author: Eric Niebler <eniebler@fb.com> */ @@ -52,7 +53,7 @@ FOLLY_GCC_DISABLE_NEW_SHADOW_WARNINGS namespace folly { #define FOLLY_REQUIRES_DEF(...) \ - _t<std::enable_if<static_cast<bool>(__VA_ARGS__), long>> + std::enable_if_t<static_cast<bool>(__VA_ARGS__), long> #define FOLLY_REQUIRES(...) FOLLY_REQUIRES_DEF(__VA_ARGS__) = __LINE__ @@ -62,16 +63,15 @@ template <template <class> class T, class... As> using AllOf = StrictConjunction<T<As>...>; template <bool If, class T> -using AddConstIf = _t<std::conditional<If, const T, T>>; +using AddConstIf = std::conditional_t<If, const T, T>; template <class Fn, class A> -FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN auto fold(Fn&&, A&& a) { +FOLLY_ERASE auto fold(Fn&&, A&& a) { return static_cast<A&&>(a); } template <class Fn, class A, class B, class... Bs> -FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN auto -fold(Fn&& fn, A&& a, B&& b, Bs&&... bs) { +FOLLY_ERASE auto fold(Fn&& fn, A&& a, B&& b, Bs&&... bs) { return fold( // This looks like a use of fn after a move of fn, but in reality, this is // just a cast and not a move. That's because regardless of which fold @@ -206,12 +206,12 @@ class exception_wrapper final { static VTable const uninit_; template <class Ex> - using IsStdException = std::is_base_of<std::exception, _t<std::decay<Ex>>>; + using IsStdException = std::is_base_of<std::exception, std::decay_t<Ex>>; template <bool B, class T> using AddConstIf = exception_wrapper_detail::AddConstIf<B, T>; template <class CatchFn> using IsCatchAll = - std::is_same<arg_type<_t<std::decay<CatchFn>>>, AnyException>; + std::is_same<arg_type<std::decay_t<CatchFn>>, AnyException>; struct Unknown {}; @@ -221,7 +221,7 @@ class exception_wrapper final { // and runtime_error can be safely stored internally. struct Buffer { using Storage = - _t<std::aligned_storage<2 * sizeof(void*), alignof(std::exception)>>; + std::aligned_storage_t<2 * sizeof(void*), alignof(std::exception)>; Storage buff_; Buffer() : buff_{} {} @@ -239,16 +239,16 @@ class exception_wrapper final { struct OnHeapTag {}; template <class T> - using PlacementOf = _t<std::conditional< + using PlacementOf = std::conditional_t< !IsStdException<T>::value, ThrownTag, - _t<std::conditional< + std::conditional_t< sizeof(T) <= sizeof(Buffer::Storage) && alignof(T) <= alignof(Buffer::Storage) && noexcept(T(std::declval<T&&>())) && noexcept(T(std::declval<T const&>())), InSituTag, - OnHeapTag>>>>; + OnHeapTag>>; static std::exception const* as_exception_or_null_(std::exception const& ex); static std::exception const* as_exception_or_null_(AnyException); @@ -429,7 +429,7 @@ class exception_wrapper final { //! converted to an `exception_wrapper`. template < class Ex, - class Ex_ = _t<std::decay<Ex>>, + class Ex_ = std::decay_t<Ex>, FOLLY_REQUIRES( Conjunction<IsStdException<Ex_>, IsRegularExceptionType<Ex_>>::value)> /* implicit */ exception_wrapper(Ex&& ex); @@ -443,7 +443,7 @@ class exception_wrapper final { //! `folly::in_place` as the first parameter. template < class Ex, - class Ex_ = _t<std::decay<Ex>>, + class Ex_ = std::decay_t<Ex>, FOLLY_REQUIRES(IsRegularExceptionType<Ex_>::value)> exception_wrapper(in_place_t, Ex&& ex); diff --git a/ios/Pods/Folly/folly/Executor.h b/ios/Pods/Folly/folly/Executor.h index c81afd4d1..8ca5e79ff 100644 --- a/ios/Pods/Folly/folly/Executor.h +++ b/ios/Pods/Folly/folly/Executor.h @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -18,14 +18,38 @@ #include <cassert> #include <climits> +#include <utility> #include <folly/Function.h> #include <folly/Utility.h> namespace folly { +namespace pushmi { +// derive from this for types that need to find operator|() overloads by ADL +struct folly_pipeorigin {}; +} // namespace pushmi using Func = Function<void()>; +namespace detail { + +class ExecutorKeepAliveBase { + public: + // A dummy keep-alive is a keep-alive to an executor which does not support + // the keep-alive mechanism. + static constexpr uintptr_t kDummyFlag = uintptr_t(1) << 0; + + // An alias keep-alive is a keep-alive to an executor to which there is + // known to be another keep-alive whose lifetime surrounds the lifetime of + // the alias. + static constexpr uintptr_t kAliasFlag = uintptr_t(1) << 1; + + static constexpr uintptr_t kFlagMask = kDummyFlag | kAliasFlag; + static constexpr uintptr_t kExecutorMask = ~kFlagMask; +}; + +} // namespace detail + /// An Executor accepts units of work with add(), which should be /// threadsafe. class Executor { @@ -49,9 +73,25 @@ class Executor { static const int8_t MID_PRI = 0; static const int8_t HI_PRI = SCHAR_MAX; + /** + * Executor::KeepAlive is a safe pointer to an Executor. + * For any Executor that supports KeepAlive functionality, Executor's + * destructor will block until all the KeepAlive objects associated with that + * Executor are destroyed. + * For Executors that don't support the KeepAlive funcionality, KeepAlive + * doesn't provide such protection. + * + * KeepAlive should *always* be used instead of Executor*. KeepAlive can be + * implicitly constructed from Executor*. getKeepAliveToken() helper method + * can be used to construct a KeepAlive in templated code if you need to + * preserve the original Executor type. + */ template <typename ExecutorT = Executor> - class KeepAlive { + class KeepAlive : pushmi::folly_pipeorigin, + private detail::ExecutorKeepAliveBase { public: + using KeepAliveFunc = Function<void(KeepAlive&&)>; + KeepAlive() = default; ~KeepAlive() { @@ -59,23 +99,41 @@ class Executor { } KeepAlive(KeepAlive&& other) noexcept - : executorAndDummyFlag_(exchange(other.executorAndDummyFlag_, 0)) {} + : storage_(std::exchange(other.storage_, 0)) {} + + KeepAlive(const KeepAlive& other) noexcept + : KeepAlive(getKeepAliveToken(other.get())) {} template < typename OtherExecutor, typename = typename std::enable_if< std::is_convertible<OtherExecutor*, ExecutorT*>::value>::type> /* implicit */ KeepAlive(KeepAlive<OtherExecutor>&& other) noexcept - : KeepAlive(other.get(), other.executorAndDummyFlag_ & kDummyFlag) { - other.executorAndDummyFlag_ = 0; + : KeepAlive(other.get(), other.storage_ & kFlagMask) { + other.storage_ = 0; + } + + template < + typename OtherExecutor, + typename = typename std::enable_if< + std::is_convertible<OtherExecutor*, ExecutorT*>::value>::type> + /* implicit */ KeepAlive(const KeepAlive<OtherExecutor>& other) noexcept + : KeepAlive(getKeepAliveToken(other.get())) {} + + /* implicit */ KeepAlive(ExecutorT* executor) { + *this = getKeepAliveToken(executor); } KeepAlive& operator=(KeepAlive&& other) { reset(); - executorAndDummyFlag_ = exchange(other.executorAndDummyFlag_, 0); + storage_ = std::exchange(other.storage_, 0); return *this; } + KeepAlive& operator=(KeepAlive const& other) { + return operator=(folly::copy(other)); + } + template < typename OtherExecutor, typename = typename std::enable_if< @@ -84,22 +142,29 @@ class Executor { return *this = KeepAlive(std::move(other)); } + template < + typename OtherExecutor, + typename = typename std::enable_if< + std::is_convertible<OtherExecutor*, ExecutorT*>::value>::type> + KeepAlive& operator=(const KeepAlive<OtherExecutor>& other) { + return *this = KeepAlive(other); + } + void reset() { if (Executor* executor = get()) { - if (exchange(executorAndDummyFlag_, 0) & kDummyFlag) { - return; + auto const flags = std::exchange(storage_, 0) & kFlagMask; + if (!(flags & (kDummyFlag | kAliasFlag))) { + executor->keepAliveRelease(); } - executor->keepAliveRelease(); } } explicit operator bool() const { - return executorAndDummyFlag_; + return storage_; } ExecutorT* get() const { - return reinterpret_cast<ExecutorT*>( - executorAndDummyFlag_ & kExecutorMask); + return reinterpret_cast<ExecutorT*>(storage_ & kExecutorMask); } ExecutorT& operator*() const { @@ -111,27 +176,42 @@ class Executor { } KeepAlive copy() const { - return getKeepAliveToken(get()); + return isKeepAliveDummy(*this) // + ? makeKeepAliveDummy(get()) + : getKeepAliveToken(get()); + } + + KeepAlive get_alias() const { + return KeepAlive(storage_ | kAliasFlag); + } + + template <class KAF> + void add(KAF&& f) && { + static_assert( + is_invocable<KAF, KeepAlive&&>::value, + "Parameter to add must be void(KeepAlive&&)>"); + auto ex = get(); + ex->add([ka = std::move(*this), f = std::forward<KAF>(f)]() mutable { + f(std::move(ka)); + }); } private: - static constexpr intptr_t kDummyFlag = 1; - static constexpr intptr_t kExecutorMask = ~kDummyFlag; - friend class Executor; template <typename OtherExecutor> friend class KeepAlive; - KeepAlive(ExecutorT* executor, bool dummy) - : executorAndDummyFlag_( - reinterpret_cast<intptr_t>(executor) | (dummy ? kDummyFlag : 0)) { + KeepAlive(ExecutorT* executor, uintptr_t flags) noexcept + : storage_(reinterpret_cast<uintptr_t>(executor) | flags) { assert(executor); - assert( - (reinterpret_cast<intptr_t>(executor) & kExecutorMask) == - reinterpret_cast<intptr_t>(executor)); + assert(!(reinterpret_cast<uintptr_t>(executor) & ~kExecutorMask)); + assert(!(flags & kExecutorMask)); } - intptr_t executorAndDummyFlag_{reinterpret_cast<intptr_t>(nullptr)}; + explicit KeepAlive(uintptr_t storage) noexcept : storage_(storage) {} + + // Combined storage for the executor pointer and for all flags. + uintptr_t storage_{reinterpret_cast<uintptr_t>(nullptr)}; }; template <typename ExecutorT> @@ -164,8 +244,7 @@ class Executor { */ template <typename ExecutorT> static bool isKeepAliveDummy(const KeepAlive<ExecutorT>& keepAlive) { - return reinterpret_cast<intptr_t>(keepAlive.executorAndDummyFlag_) & - KeepAlive<ExecutorT>::kDummyFlag; + return keepAlive.storage_ & KeepAlive<ExecutorT>::kDummyFlag; } // Acquire a keep alive token. Should return false if keep-alive mechanism @@ -180,7 +259,7 @@ class Executor { static_assert( std::is_base_of<Executor, ExecutorT>::value, "makeKeepAlive only works for folly::Executor implementations."); - return KeepAlive<ExecutorT>{executor, false}; + return KeepAlive<ExecutorT>{executor, uintptr_t(0)}; } private: @@ -189,7 +268,7 @@ class Executor { static_assert( std::is_base_of<Executor, ExecutorT>::value, "makeKeepAliveDummy only works for folly::Executor implementations."); - return KeepAlive<ExecutorT>{executor, true}; + return KeepAlive<ExecutorT>{executor, KeepAlive<ExecutorT>::kDummyFlag}; } }; @@ -212,4 +291,10 @@ Executor::KeepAlive<ExecutorT> getKeepAliveToken(ExecutorT& executor) { return getKeepAliveToken(&executor); } +template <typename ExecutorT> +Executor::KeepAlive<ExecutorT> getKeepAliveToken( + Executor::KeepAlive<ExecutorT>& ka) { + return ka.copy(); +} + } // namespace folly diff --git a/ios/Pods/Folly/folly/Expected.h b/ios/Pods/Folly/folly/Expected.h index 9a8c9ad4b..3cc1ce2c7 100644 --- a/ios/Pods/Folly/folly/Expected.h +++ b/ios/Pods/Folly/folly/Expected.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + /** * Like folly::Optional, but can store a value *or* an error. * @@ -37,7 +38,6 @@ #include <folly/Traits.h> #include <folly/Unit.h> #include <folly/Utility.h> -#include <folly/lang/ColdClass.h> #include <folly/lang/Exception.h> #define FOLLY_EXPECTED_ID(X) FB_CONCATENATE(FB_CONCATENATE(Folly, X), __LINE__) @@ -52,17 +52,6 @@ #define FOLLY_REQUIRES(...) template <FOLLY_REQUIRES_IMPL(__VA_ARGS__)> -/** - * gcc-4.7 warns about use of uninitialized memory around the use of storage_ - * even though this is explicitly initialized at each point. - */ -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wuninitialized" -#pragma GCC diagnostic ignored "-Wpragmas" -#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" -#endif // __GNUC__ - namespace folly { /** @@ -101,15 +90,8 @@ namespace expected_detail { template <typename Value, typename Error> struct PromiseReturn; -#ifdef _MSC_VER -// MSVC 2015 can't handle the StrictConjunction, so we have -// to use std::conjunction instead. -template <template <class...> class Trait, class... Ts> -using StrictAllOf = std::conjunction<Trait<Ts>...>; -#else template <template <class...> class Trait, class... Ts> using StrictAllOf = StrictConjunction<Trait<Ts>...>; -#endif template <class T> using IsCopyable = StrictConjunction< @@ -230,6 +212,7 @@ struct ExpectedStorage { case Which::eError: this->assignError(static_cast<Other&&>(that).error()); break; + case Which::eEmpty: default: this->clear(); break; @@ -244,11 +227,6 @@ struct ExpectedStorage { Value&& value() && { return std::move(value_); } - // TODO (t17322426): remove when VS2015 support is deprecated - // VS2015 static analyzer incorrectly flags these as unreachable in certain - // circumstances. VS2017 does not have this problem on the same code. - FOLLY_PUSH_WARNING - FOLLY_MSVC_DISABLE_WARNING(4702) // unreachable code Error& error() & { return error_; } @@ -258,7 +236,6 @@ struct ExpectedStorage { Error&& error() && { return std::move(error_); } - FOLLY_POP_WARNING }; template <class Value, class Error> @@ -430,6 +407,7 @@ struct ExpectedStorage<Value, Error, StorageType::eUnion> case Which::eError: this->error().~Error(); break; + case Which::eEmpty: default: break; } @@ -480,6 +458,7 @@ struct ExpectedStorage<Value, Error, StorageType::eUnion> case Which::eError: this->assignError(static_cast<Other&&>(that).error()); break; + case Which::eEmpty: default: this->clear(); break; @@ -531,6 +510,7 @@ struct ExpectedStorage<Value, Error, StorageType::ePODStruct> { case Which::eError: this->assignError(static_cast<Other&&>(that).error()); break; + case Which::eEmpty: default: this->clear(); break; @@ -545,11 +525,6 @@ struct ExpectedStorage<Value, Error, StorageType::ePODStruct> { Value&& value() && { return std::move(value_); } - // TODO (t17322426): remove when VS2015 support is deprecated - // VS2015 static analyzer incorrectly flags these as unreachable in certain - // circumstances. VS2017 does not have this problem on the same code. - FOLLY_PUSH_WARNING - FOLLY_MSVC_DISABLE_WARNING(4702) // unreachable code Error& error() & { return error_; } @@ -559,7 +534,6 @@ struct ExpectedStorage<Value, Error, StorageType::ePODStruct> { Error&& error() && { return std::move(error_); } - FOLLY_POP_WARNING }; namespace expected_detail_ExpectedHelper { @@ -675,7 +649,7 @@ namespace expected_detail { * Expected objects in the error state. */ template <class Error> -class Unexpected final : ColdClass { +class Unexpected final { template <class E> friend class Unexpected; template <class V, class E> @@ -712,8 +686,10 @@ class Unexpected final : ColdClass { Unexpected(Unexpected&&) = default; Unexpected& operator=(const Unexpected&) = default; Unexpected& operator=(Unexpected&&) = default; - constexpr /* implicit */ Unexpected(const Error& err) : error_(err) {} - constexpr /* implicit */ Unexpected(Error&& err) : error_(std::move(err)) {} + FOLLY_COLD constexpr /* implicit */ Unexpected(const Error& err) + : error_(err) {} + FOLLY_COLD constexpr /* implicit */ Unexpected(Error&& err) + : error_(std::move(err)) {} template <class Other FOLLY_REQUIRES_TRAILING( std::is_constructible<Error, Other&&>::value)> @@ -931,7 +907,7 @@ class Expected final : expected_detail::ExpectedStorage<Value, Error> { std::is_constructible<Value, V&&>::value && std::is_constructible<Error, E&&>::value)> Expected(Expected<V, E> that) : Base{expected_detail::EmptyTag{}} { - *this = std::move(that); + this->assign(std::move(that)); } FOLLY_REQUIRES(std::is_copy_constructible<Value>::value) @@ -1425,10 +1401,6 @@ bool operator>(const Value& other, const Expected<Value, Error>&) = delete; } // namespace folly -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif - #undef FOLLY_REQUIRES #undef FOLLY_REQUIRES_TRAILING diff --git a/ios/Pods/Folly/folly/FBString.h b/ios/Pods/Folly/folly/FBString.h index 5a64d4ff0..8b607dff9 100644 --- a/ios/Pods/Folly/folly/FBString.h +++ b/ios/Pods/Folly/folly/FBString.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -26,29 +26,15 @@ #include <stdexcept> #include <type_traits> -// This file appears in two locations: inside fbcode and in the -// libstdc++ source code (when embedding fbstring as std::string). -// To aid in this schizophrenic use, _LIBSTDCXX_FBSTRING is defined in -// libstdc++'s c++config.h, to gate use inside fbcode v. libstdc++. -#ifdef _LIBSTDCXX_FBSTRING - -#pragma GCC system_header - -#include <basic_fbstring_malloc.h> // @manual - -// When used as std::string replacement always disable assertions. -#define FBSTRING_ASSERT(expr) /* empty */ - -#else // !_LIBSTDCXX_FBSTRING - -#include <folly/CppAttributes.h> -#include <folly/Portability.h> - -// libc++ doesn't provide this header, nor does msvc -#if __has_include(<bits/c++config.h>) -#include <bits/c++config.h> +#if FOLLY_HAS_STRING_VIEW +#include <string_view> #endif +#include <folly/CPortability.h> +#include <folly/CppAttributes.h> +#include <folly/Likely.h> +#include <folly/Portability.h> + #include <algorithm> #include <cassert> #include <cstring> @@ -57,60 +43,15 @@ #include <folly/Traits.h> #include <folly/hash/Hash.h> +#include <folly/lang/Assume.h> #include <folly/lang/Exception.h> #include <folly/memory/Malloc.h> -// When used in folly, assertions are not disabled. -#define FBSTRING_ASSERT(expr) assert(expr) - -#endif - -// We defined these here rather than including Likely.h to avoid -// redefinition errors when fbstring is imported into libstdc++. -#if defined(__GNUC__) && __GNUC__ >= 4 -#define FBSTRING_LIKELY(x) (__builtin_expect((x), 1)) -#define FBSTRING_UNLIKELY(x) (__builtin_expect((x), 0)) -#else -#define FBSTRING_LIKELY(x) (x) -#define FBSTRING_UNLIKELY(x) (x) -#endif - FOLLY_PUSH_WARNING // Ignore shadowing warnings within this file, so includers can use -Wshadow. FOLLY_GNU_DISABLE_WARNING("-Wshadow") -// GCC 4.9 has a false positive in setSmallSize (probably -// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124), disable -// compile-time array bound checking. -FOLLY_GNU_DISABLE_WARNING("-Warray-bounds") -// FBString cannot use throw when replacing std::string, though it may still -// use folly::throw_exception -// nolint -#define throw FOLLY_FBSTRING_MAY_NOT_USE_THROW - -#ifdef _LIBSTDCXX_FBSTRING -#define FOLLY_FBSTRING_BEGIN_NAMESPACE \ - namespace std _GLIBCXX_VISIBILITY(default) { \ - _GLIBCXX_BEGIN_NAMESPACE_VERSION -#define FOLLY_FBSTRING_END_NAMESPACE \ - _GLIBCXX_END_NAMESPACE_VERSION \ - } // namespace std -#else -#define FOLLY_FBSTRING_BEGIN_NAMESPACE namespace folly { -#define FOLLY_FBSTRING_END_NAMESPACE } // namespace folly -#endif - -FOLLY_FBSTRING_BEGIN_NAMESPACE - -#if defined(__clang__) -#if __has_feature(address_sanitizer) -#define FBSTRING_SANITIZE_ADDRESS -#endif -#elif defined(__GNUC__) && \ - (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ >= 5)) && \ - __SANITIZE_ADDRESS__ -#define FBSTRING_SANITIZE_ADDRESS -#endif +namespace folly { // When compiling with ASan, always heap-allocate the string even if // it would fit in-situ, so that ASan can detect access to the string @@ -118,7 +59,7 @@ FOLLY_FBSTRING_BEGIN_NAMESPACE // Note that this flag doesn't remove support for in-situ strings, as // that would break ABI-compatibility and wouldn't allow linking code // compiled with this flag with code compiled without. -#ifdef FBSTRING_SANITIZE_ADDRESS +#ifdef FOLLY_SANITIZE_ADDRESS #define FBSTRING_DISABLE_SSO true #else #define FBSTRING_DISABLE_SSO false @@ -139,7 +80,7 @@ inline std::pair<InIt, OutIt> copy_n( template <class Pod, class T> inline void podFill(Pod* b, Pod* e, T c) { - FBSTRING_ASSERT(b && e && b <= e); + assert(b && e && b <= e); constexpr auto kUseMemset = sizeof(T) == 1; if /* constexpr */ (kUseMemset) { memset(b, c, size_t(e - b)); @@ -172,11 +113,11 @@ inline void podFill(Pod* b, Pod* e, T c) { */ template <class Pod> inline void podCopy(const Pod* b, const Pod* e, Pod* d) { - FBSTRING_ASSERT(b != nullptr); - FBSTRING_ASSERT(e != nullptr); - FBSTRING_ASSERT(d != nullptr); - FBSTRING_ASSERT(e >= b); - FBSTRING_ASSERT(d >= e || d + (e - b) <= b); + assert(b != nullptr); + assert(e != nullptr); + assert(d != nullptr); + assert(e >= b); + assert(d >= e || d + (e - b) <= b); memcpy(d, b, (e - b) * sizeof(Pod)); } @@ -186,30 +127,9 @@ inline void podCopy(const Pod* b, const Pod* e, Pod* d) { */ template <class Pod> inline void podMove(const Pod* b, const Pod* e, Pod* d) { - FBSTRING_ASSERT(e >= b); + assert(e >= b); memmove(d, b, (e - b) * sizeof(*b)); } - -// always inline -#if defined(__GNUC__) // Clang also defines __GNUC__ -#define FBSTRING_ALWAYS_INLINE inline __attribute__((__always_inline__)) -#elif defined(_MSC_VER) -#define FBSTRING_ALWAYS_INLINE __forceinline -#else -#define FBSTRING_ALWAYS_INLINE inline -#endif - -[[noreturn]] FBSTRING_ALWAYS_INLINE void assume_unreachable() { -#if defined(__GNUC__) // Clang also defines __GNUC__ - __builtin_unreachable(); -#elif defined(_MSC_VER) - __assume(0); -#else - // Well, it's better than nothing. - std::abort(); -#endif -} - } // namespace fbstring_detail /** @@ -235,6 +155,7 @@ class fbstring_core_model { public: fbstring_core_model(); fbstring_core_model(const fbstring_core_model &); + fbstring_core_model& operator=(const fbstring_core_model &) = delete; ~fbstring_core_model(); // Returns a pointer to string's buffer (currently only contiguous // strings are supported). The pointer is guaranteed to be valid @@ -281,9 +202,6 @@ class fbstring_core_model { // the string without reallocation. For reference-counted strings, // it should fork the data even if minCapacity < size(). void reserve(size_t minCapacity); - private: - // Do not implement - fbstring_core_model& operator=(const fbstring_core_model &); }; */ @@ -325,25 +243,13 @@ class fbstring_core_model { */ template <class Char> class fbstring_core { - protected: -// It's MSVC, so we just have to guess ... and allow an override -#ifdef _MSC_VER -#ifdef FOLLY_ENDIAN_BE - static constexpr auto kIsLittleEndian = false; -#else - static constexpr auto kIsLittleEndian = true; -#endif -#else - static constexpr auto kIsLittleEndian = - __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__; -#endif public: fbstring_core() noexcept { reset(); } fbstring_core(const fbstring_core& rhs) { - FBSTRING_ASSERT(&rhs != this); + assert(&rhs != this); switch (rhs.category()) { case Category::isSmall: copySmall(rhs); @@ -355,12 +261,14 @@ class fbstring_core { copyLarge(rhs); break; default: - fbstring_detail::assume_unreachable(); + folly::assume_unreachable(); } - FBSTRING_ASSERT(size() == rhs.size()); - FBSTRING_ASSERT(memcmp(data(), rhs.data(), size() * sizeof(Char)) == 0); + assert(size() == rhs.size()); + assert(memcmp(data(), rhs.data(), size() * sizeof(Char)) == 0); } + fbstring_core& operator=(const fbstring_core& rhs) = delete; + fbstring_core(fbstring_core&& goner) noexcept { // Take goner's guts ml_ = goner.ml_; @@ -379,9 +287,8 @@ class fbstring_core { } else { initLarge(data, size); } - FBSTRING_ASSERT(this->size() == size); - FBSTRING_ASSERT( - size == 0 || memcmp(this->data(), data, size * sizeof(Char)) == 0); + assert(this->size() == size); + assert(size == 0 || memcmp(this->data(), data, size * sizeof(Char)) == 0); } ~fbstring_core() noexcept { @@ -404,8 +311,8 @@ class fbstring_core { const size_t allocatedSize, AcquireMallocatedString) { if (size > 0) { - FBSTRING_ASSERT(allocatedSize >= size + 1); - FBSTRING_ASSERT(data[size] == '\0'); + assert(allocatedSize >= size + 1); + assert(data[size] == '\0'); // Use the medium string storage ml_.data_ = data; ml_.size_ = size; @@ -433,6 +340,10 @@ class fbstring_core { return c_str(); } + Char* data() { + return c_str(); + } + Char* mutableData() { switch (category()) { case Category::isSmall: @@ -442,7 +353,7 @@ class fbstring_core { case Category::isLarge: return mutableDataLarge(); } - fbstring_detail::assume_unreachable(); + folly::assume_unreachable(); } const Char* c_str() const { @@ -463,7 +374,7 @@ class fbstring_core { } } - FOLLY_MALLOC_NOINLINE + FOLLY_NOINLINE void reserve(size_t minCapacity, bool disableSSO = FBSTRING_DISABLE_SSO) { switch (category()) { case Category::isSmall: @@ -476,9 +387,9 @@ class fbstring_core { reserveLarge(minCapacity); break; default: - fbstring_detail::assume_unreachable(); + folly::assume_unreachable(); } - FBSTRING_ASSERT(capacity() >= minCapacity); + assert(capacity() >= minCapacity); } Char* expandNoinit( @@ -518,6 +429,7 @@ class fbstring_core { return ml_.size_; } break; + case Category::isMedium: default: break; } @@ -529,16 +441,20 @@ class fbstring_core { } private: - // Disabled - fbstring_core& operator=(const fbstring_core& rhs); + Char* c_str() { + Char* ptr = ml_.data_; + // With this syntax, GCC and Clang generate a CMOV instead of a branch. + ptr = (category() == Category::isSmall) ? small_ : ptr; + return ptr; + } void reset() { setSmallSize(0); } - FOLLY_MALLOC_NOINLINE void destroyMediumLarge() noexcept { + FOLLY_NOINLINE void destroyMediumLarge() noexcept { auto const c = category(); - FBSTRING_ASSERT(c != Category::isSmall); + assert(c != Category::isSmall); if (c == Category::isMedium) { free(ml_.data_); } else { @@ -571,7 +487,7 @@ class fbstring_core { static void decrementRefs(Char* p) { auto const dis = fromData(p); size_t oldcnt = dis->refCount_.fetch_sub(1, std::memory_order_acq_rel); - FBSTRING_ASSERT(oldcnt > 0); + assert(oldcnt > 0); if (oldcnt == 1) { free(dis); } @@ -589,7 +505,7 @@ class fbstring_core { static RefCounted* create(const Char* data, size_t* size) { const size_t effectiveSize = *size; auto result = create(size); - if (FBSTRING_LIKELY(effectiveSize > 0)) { + if (FOLLY_LIKELY(effectiveSize > 0)) { fbstring_detail::podCopy(data, data + effectiveSize, result->data_); } return result; @@ -600,17 +516,17 @@ class fbstring_core { const size_t currentSize, const size_t currentCapacity, size_t* newCapacity) { - FBSTRING_ASSERT(*newCapacity > 0 && *newCapacity > currentSize); + assert(*newCapacity > 0 && *newCapacity > currentSize); const size_t allocNewCapacity = goodMallocSize(getDataOffset() + (*newCapacity + 1) * sizeof(Char)); auto const dis = fromData(data); - FBSTRING_ASSERT(dis->refCount_.load(std::memory_order_acquire) == 1); + assert(dis->refCount_.load(std::memory_order_acquire) == 1); auto result = static_cast<RefCounted*>(smartRealloc( dis, getDataOffset() + (currentSize + 1) * sizeof(Char), getDataOffset() + (currentCapacity + 1) * sizeof(Char), allocNewCapacity)); - FBSTRING_ASSERT(result->refCount_.load(std::memory_order_acquire) == 1); + assert(result->refCount_.load(std::memory_order_acquire) == 1); *newCapacity = (allocNewCapacity - getDataOffset()) / sizeof(Char) - 1; return result; } @@ -665,10 +581,10 @@ class fbstring_core { "Corrupt memory layout for fbstring."); size_t smallSize() const { - FBSTRING_ASSERT(category() == Category::isSmall); + assert(category() == Category::isSmall); constexpr auto shift = kIsLittleEndian ? 0 : 2; auto smallShifted = static_cast<size_t>(small_[maxSmallSize]) >> shift; - FBSTRING_ASSERT(static_cast<size_t>(maxSmallSize) >= smallShifted); + assert(static_cast<size_t>(maxSmallSize) >= smallShifted); return static_cast<size_t>(maxSmallSize) - smallShifted; } @@ -676,11 +592,11 @@ class fbstring_core { // Warning: this should work with uninitialized strings too, // so don't assume anything about the previous value of // small_[maxSmallSize]. - FBSTRING_ASSERT(s <= maxSmallSize); + assert(s <= maxSmallSize); constexpr auto shift = kIsLittleEndian ? 0 : 2; small_[maxSmallSize] = char((maxSmallSize - s) << shift); small_[s] = '\0'; - FBSTRING_ASSERT(category() == Category::isSmall && size() == s); + assert(category() == Category::isSmall && size() == s); } void copySmall(const fbstring_core&); @@ -718,12 +634,11 @@ inline void fbstring_core<Char>::copySmall(const fbstring_core& rhs) { // which stores a short string's length, is shared with the // ml_.capacity field). ml_ = rhs.ml_; - FBSTRING_ASSERT( - category() == Category::isSmall && this->size() == rhs.size()); + assert(category() == Category::isSmall && this->size() == rhs.size()); } template <class Char> -FOLLY_MALLOC_NOINLINE inline void fbstring_core<Char>::copyMedium( +FOLLY_NOINLINE inline void fbstring_core<Char>::copyMedium( const fbstring_core& rhs) { // Medium strings are copied eagerly. Don't forget to allocate // one extra Char for the null terminator. @@ -734,16 +649,16 @@ FOLLY_MALLOC_NOINLINE inline void fbstring_core<Char>::copyMedium( rhs.ml_.data_, rhs.ml_.data_ + rhs.ml_.size_ + 1, ml_.data_); ml_.size_ = rhs.ml_.size_; ml_.setCapacity(allocSize / sizeof(Char) - 1, Category::isMedium); - FBSTRING_ASSERT(category() == Category::isMedium); + assert(category() == Category::isMedium); } template <class Char> -FOLLY_MALLOC_NOINLINE inline void fbstring_core<Char>::copyLarge( +FOLLY_NOINLINE inline void fbstring_core<Char>::copyLarge( const fbstring_core& rhs) { // Large strings are just refcounted ml_ = rhs.ml_; RefCounted::incrementRefs(ml_.data_); - FBSTRING_ASSERT(category() == Category::isLarge && size() == rhs.size()); + assert(category() == Category::isLarge && size() == rhs.size()); } // Small strings are bitblitted @@ -767,7 +682,7 @@ inline void fbstring_core<Char>::initSmall( // The word-wise path reads bytes which are outside the range of // the string, and makes ASan unhappy, so we disable it when // compiling with ASan. -#ifndef FBSTRING_SANITIZE_ADDRESS +#ifndef FOLLY_SANITIZE_ADDRESS if ((reinterpret_cast<size_t>(data) & (sizeof(size_t) - 1)) == 0) { const size_t byteSize = size * sizeof(Char); constexpr size_t wordWidth = sizeof(size_t); @@ -795,14 +710,14 @@ inline void fbstring_core<Char>::initSmall( } template <class Char> -FOLLY_MALLOC_NOINLINE inline void fbstring_core<Char>::initMedium( +FOLLY_NOINLINE inline void fbstring_core<Char>::initMedium( const Char* const data, const size_t size) { // Medium strings are allocated normally. Don't forget to // allocate one extra Char for the terminating null. auto const allocSize = goodMallocSize((1 + size) * sizeof(Char)); ml_.data_ = static_cast<Char*>(checkedMalloc(allocSize)); - if (FBSTRING_LIKELY(size > 0)) { + if (FOLLY_LIKELY(size > 0)) { fbstring_detail::podCopy(data, data + size, ml_.data_); } ml_.size_ = size; @@ -811,7 +726,7 @@ FOLLY_MALLOC_NOINLINE inline void fbstring_core<Char>::initMedium( } template <class Char> -FOLLY_MALLOC_NOINLINE inline void fbstring_core<Char>::initLarge( +FOLLY_NOINLINE inline void fbstring_core<Char>::initLarge( const Char* const data, const size_t size) { // Large strings are allocated differently @@ -824,14 +739,13 @@ FOLLY_MALLOC_NOINLINE inline void fbstring_core<Char>::initLarge( } template <class Char> -FOLLY_MALLOC_NOINLINE inline void fbstring_core<Char>::unshare( - size_t minCapacity) { - FBSTRING_ASSERT(category() == Category::isLarge); +FOLLY_NOINLINE inline void fbstring_core<Char>::unshare(size_t minCapacity) { + assert(category() == Category::isLarge); size_t effectiveCapacity = std::max(minCapacity, ml_.capacity()); auto const newRC = RefCounted::create(&effectiveCapacity); // If this fails, someone placed the wrong capacity in an // fbstring. - FBSTRING_ASSERT(effectiveCapacity >= ml_.capacity()); + assert(effectiveCapacity >= ml_.capacity()); // Also copies terminator. fbstring_detail::podCopy(ml_.data_, ml_.data_ + ml_.size_ + 1, newRC->data_); RefCounted::decrementRefs(ml_.data_); @@ -842,7 +756,7 @@ FOLLY_MALLOC_NOINLINE inline void fbstring_core<Char>::unshare( template <class Char> inline Char* fbstring_core<Char>::mutableDataLarge() { - FBSTRING_ASSERT(category() == Category::isLarge); + assert(category() == Category::isLarge); if (RefCounted::refs(ml_.data_) > 1) { // Ensure unique. unshare(); } @@ -850,9 +764,9 @@ inline Char* fbstring_core<Char>::mutableDataLarge() { } template <class Char> -FOLLY_MALLOC_NOINLINE inline void fbstring_core<Char>::reserveLarge( +FOLLY_NOINLINE inline void fbstring_core<Char>::reserveLarge( size_t minCapacity) { - FBSTRING_ASSERT(category() == Category::isLarge); + assert(category() == Category::isLarge); if (RefCounted::refs(ml_.data_) > 1) { // Ensure unique // We must make it unique regardless; in-place reallocation is // useless if the string is shared. In order to not surprise @@ -869,14 +783,14 @@ FOLLY_MALLOC_NOINLINE inline void fbstring_core<Char>::reserveLarge( ml_.data_ = newRC->data_; ml_.setCapacity(minCapacity, Category::isLarge); } - FBSTRING_ASSERT(capacity() >= minCapacity); + assert(capacity() >= minCapacity); } } template <class Char> -FOLLY_MALLOC_NOINLINE inline void fbstring_core<Char>::reserveMedium( +FOLLY_NOINLINE inline void fbstring_core<Char>::reserveMedium( const size_t minCapacity) { - FBSTRING_ASSERT(category() == Category::isMedium); + assert(category() == Category::isMedium); // String is not shared if (minCapacity <= ml_.capacity()) { return; // nothing to do, there's enough room @@ -902,15 +816,15 @@ FOLLY_MALLOC_NOINLINE inline void fbstring_core<Char>::reserveMedium( fbstring_detail::podCopy( ml_.data_, ml_.data_ + ml_.size_ + 1, nascent.ml_.data_); nascent.swap(*this); - FBSTRING_ASSERT(capacity() >= minCapacity); + assert(capacity() >= minCapacity); } } template <class Char> -FOLLY_MALLOC_NOINLINE inline void fbstring_core<Char>::reserveSmall( +FOLLY_NOINLINE inline void fbstring_core<Char>::reserveSmall( size_t minCapacity, const bool disableSSO) { - FBSTRING_ASSERT(category() == Category::isSmall); + assert(category() == Category::isSmall); if (!disableSSO && minCapacity <= maxSmallSize) { // small // Nothing to do, everything stays put @@ -935,7 +849,7 @@ FOLLY_MALLOC_NOINLINE inline void fbstring_core<Char>::reserveSmall( ml_.data_ = newRC->data_; ml_.size_ = size; ml_.setCapacity(minCapacity, Category::isLarge); - FBSTRING_ASSERT(capacity() >= minCapacity); + assert(capacity() >= minCapacity); } } @@ -945,12 +859,12 @@ inline Char* fbstring_core<Char>::expandNoinit( bool expGrowth, /* = false */ bool disableSSO /* = FBSTRING_DISABLE_SSO */) { // Strategy is simple: make room, then change size - FBSTRING_ASSERT(capacity() >= size()); + assert(capacity() >= size()); size_t sz, newSz; if (category() == Category::isSmall) { sz = smallSize(); newSz = sz + delta; - if (!disableSSO && FBSTRING_LIKELY(newSz <= maxSmallSize)) { + if (!disableSSO && FOLLY_LIKELY(newSz <= maxSmallSize)) { setSmallSize(newSz); return small_ + sz; } @@ -959,25 +873,24 @@ inline Char* fbstring_core<Char>::expandNoinit( } else { sz = ml_.size_; newSz = sz + delta; - if (FBSTRING_UNLIKELY(newSz > capacity())) { + if (FOLLY_UNLIKELY(newSz > capacity())) { // ensures not shared reserve(expGrowth ? std::max(newSz, 1 + capacity() * 3 / 2) : newSz); } } - FBSTRING_ASSERT(capacity() >= newSz); + assert(capacity() >= newSz); // Category can't be small - we took care of that above - FBSTRING_ASSERT( - category() == Category::isMedium || category() == Category::isLarge); + assert(category() == Category::isMedium || category() == Category::isLarge); ml_.size_ = newSz; ml_.data_[newSz] = '\0'; - FBSTRING_ASSERT(size() == newSz); + assert(size() == newSz); return ml_.data_ + sz; } template <class Char> inline void fbstring_core<Char>::shrinkSmall(const size_t delta) { // Check for underflow - FBSTRING_ASSERT(delta <= smallSize()); + assert(delta <= smallSize()); setSmallSize(smallSize() - delta); } @@ -985,14 +898,14 @@ template <class Char> inline void fbstring_core<Char>::shrinkMedium(const size_t delta) { // Medium strings and unique large strings need no special // handling. - FBSTRING_ASSERT(ml_.size_ >= delta); + assert(ml_.size_ >= delta); ml_.size_ -= delta; ml_.data_[ml_.size_] = '\0'; } template <class Char> inline void fbstring_core<Char>::shrinkLarge(const size_t delta) { - FBSTRING_ASSERT(ml_.size_ >= delta); + assert(ml_.size_ >= delta); // Shared large string, must make unique. This is because of the // durn terminator must be written, which may trample the shared // data. @@ -1002,7 +915,6 @@ inline void fbstring_core<Char>::shrinkLarge(const size_t delta) { // No need to write the terminator. } -#ifndef _LIBSTDCXX_FBSTRING /** * Dummy fbstring core that uses an actual std::string. This doesn't * make any sense - it's just for testing purposes. @@ -1024,7 +936,7 @@ class dummy_fbstring_core { return const_cast<Char*>(backend_.data()); } void shrink(size_t delta) { - FBSTRING_ASSERT(delta <= size()); + assert(delta <= size()); backend_.resize(size() - delta); } Char* expandNoinit(size_t delta) { @@ -1051,22 +963,17 @@ class dummy_fbstring_core { private: std::basic_string<Char> backend_; }; -#endif // !_LIBSTDCXX_FBSTRING /** * This is the basic_string replacement. For conformity, * basic_fbstring takes the same template parameters, plus the last * one which is the core. */ -#ifdef _LIBSTDCXX_FBSTRING -template <typename E, class T, class A, class Storage> -#else template < typename E, class T = std::char_traits<E>, class A = std::allocator<E>, class Storage = fbstring_core<E>> -#endif class basic_fbstring { template <typename Ex, typename... Args> FOLLY_ALWAYS_INLINE static void enforce(bool condition, Args&&... args) { @@ -1085,10 +992,10 @@ class basic_fbstring { struct Invariant { Invariant& operator=(const Invariant&) = delete; explicit Invariant(const basic_fbstring& s) noexcept : s_(s) { - FBSTRING_ASSERT(s_.isSane()); + assert(s_.isSane()); } ~Invariant() noexcept { - FBSTRING_ASSERT(s_.isSane()); + assert(s_.isSane()); } private: @@ -1150,12 +1057,10 @@ class basic_fbstring { basic_fbstring(basic_fbstring&& goner) noexcept : store_(std::move(goner.store_)) {} -#ifndef _LIBSTDCXX_FBSTRING // This is defined for compatibility with std::string template <typename A2> /* implicit */ basic_fbstring(const std::basic_string<E, T, A2>& str) : store_(str.data(), str.size()) {} -#endif basic_fbstring( const basic_fbstring& str, @@ -1165,22 +1070,22 @@ class basic_fbstring { assign(str, pos, n); } - FOLLY_MALLOC_NOINLINE + FOLLY_NOINLINE /* implicit */ basic_fbstring(const value_type* s, const A& /*a*/ = A()) : store_(s, traitsLength(s)) {} - FOLLY_MALLOC_NOINLINE + FOLLY_NOINLINE basic_fbstring(const value_type* s, size_type n, const A& /*a*/ = A()) : store_(s, n) {} - FOLLY_MALLOC_NOINLINE + FOLLY_NOINLINE basic_fbstring(size_type n, value_type c, const A& /*a*/ = A()) { auto const pData = store_.expandNoinit(n); fbstring_detail::podFill(pData, pData + n, c); } template <class InIt> - FOLLY_MALLOC_NOINLINE basic_fbstring( + FOLLY_NOINLINE basic_fbstring( InIt begin, InIt end, typename std::enable_if< @@ -1191,7 +1096,7 @@ class basic_fbstring { } // Specialization for const char*, const char* - FOLLY_MALLOC_NOINLINE + FOLLY_NOINLINE basic_fbstring(const value_type* b, const value_type* e, const A& /*a*/ = A()) : store_(b, size_type(e - b)) {} @@ -1204,7 +1109,7 @@ class basic_fbstring { : store_(s, n, c, a) {} // Construction from initialization list - FOLLY_MALLOC_NOINLINE + FOLLY_NOINLINE basic_fbstring(std::initializer_list<value_type> il) { assign(il.begin(), il.end()); } @@ -1216,7 +1121,6 @@ class basic_fbstring { // Move assignment basic_fbstring& operator=(basic_fbstring&& goner) noexcept; -#ifndef _LIBSTDCXX_FBSTRING // Compatibility with std::string template <typename A2> basic_fbstring& operator=(const std::basic_string<E, T, A2>& rhs) { @@ -1227,17 +1131,13 @@ class basic_fbstring { std::basic_string<E, T, A> toStdString() const { return std::basic_string<E, T, A>(data(), size()); } -#else - // A lot of code in fbcode still uses this method, so keep it here for now. - const basic_fbstring& toStdString() const { - return *this; - } -#endif basic_fbstring& operator=(const value_type* s) { return assign(s); } + basic_fbstring& operator=(value_type c); + // This actually goes directly against the C++ spec, but the // value_type overload is dangerous, so we're explicitly deleting // any overloads of operator= that could implicitly convert to @@ -1246,21 +1146,27 @@ class basic_fbstring { // otherwise MSVC 2017 will aggressively pre-resolve value_type to // traits_type::char_type, which won't compare as equal when determining // which overload the implementation is referring to. - // Also note that MSVC 2015 Update 3 requires us to explicitly specify the - // namespace in-which to search for basic_fbstring, otherwise it tries to - // look for basic_fbstring::basic_fbstring, which is just plain wrong. template <typename TP> typename std::enable_if< - std::is_same< - typename std::decay<TP>::type, - typename folly::basic_fbstring<E, T, A, Storage>::value_type>::value, + std::is_convertible< + TP, + typename basic_fbstring<E, T, A, Storage>::value_type>::value && + !std::is_same< + typename std::decay<TP>::type, + typename basic_fbstring<E, T, A, Storage>::value_type>::value, basic_fbstring<E, T, A, Storage>&>::type - operator=(TP c); + operator=(TP c) = delete; basic_fbstring& operator=(std::initializer_list<value_type> il) { return assign(il.begin(), il.end()); } +#if FOLLY_HAS_STRING_VIEW + operator std::basic_string_view<value_type, traits_type>() const noexcept { + return {data(), size()}; + } +#endif + // C++11 21.4.3 iterators: iterator begin() { return store_.mutableData(); @@ -1316,7 +1222,7 @@ class basic_fbstring { return *begin(); } const value_type& back() const { - FBSTRING_ASSERT(!empty()); + assert(!empty()); // Should be begin()[size() - 1], but that branches twice return *(end() - 1); } @@ -1324,12 +1230,12 @@ class basic_fbstring { return *begin(); } value_type& back() { - FBSTRING_ASSERT(!empty()); + assert(!empty()); // Should be begin()[size() - 1], but that branches twice return *(end() - 1); } void pop_back() { - FBSTRING_ASSERT(!empty()); + assert(!empty()); store_.shrink(1); } @@ -1503,7 +1409,6 @@ class basic_fbstring { return begin() + pos; } -#ifndef _LIBSTDCXX_FBSTRING private: typedef std::basic_istream<value_type, traits_type> istream_type; istream_type& getlineImpl(istream_type& is, value_type delim); @@ -1517,7 +1422,6 @@ class basic_fbstring { friend inline istream_type& getline(istream_type& is, basic_fbstring& str) { return getline(is, str, '\n'); } -#endif private: iterator @@ -1717,6 +1621,10 @@ class basic_fbstring { return c_str(); } + value_type* data() { + return store_.data(); + } + allocator_type get_allocator() const { return allocator_type(); } @@ -1874,7 +1782,7 @@ class basic_fbstring { }; template <typename E, class T, class A, class S> -FOLLY_MALLOC_NOINLINE inline typename basic_fbstring<E, T, A, S>::size_type +FOLLY_NOINLINE inline typename basic_fbstring<E, T, A, S>::size_type basic_fbstring<E, T, A, S>::traitsLength(const value_type* s) { return s ? traits_type::length(s) : (throw_exception<std::logic_error>( @@ -1887,7 +1795,7 @@ inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::operator=( const basic_fbstring& lhs) { Invariant checker(*this); - if (FBSTRING_UNLIKELY(&lhs == this)) { + if (FOLLY_UNLIKELY(&lhs == this)) { return *this; } @@ -1898,7 +1806,7 @@ inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::operator=( template <typename E, class T, class A, class S> inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::operator=( basic_fbstring&& goner) noexcept { - if (FBSTRING_UNLIKELY(&goner == this)) { + if (FOLLY_UNLIKELY(&goner == this)) { // Compatibility with std::basic_string<>, // C++11 21.4.2 [string.cons] / 23 requires self-move-assignment support. return *this; @@ -1911,13 +1819,8 @@ inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::operator=( } template <typename E, class T, class A, class S> -template <typename TP> -inline typename std::enable_if< - std::is_same< - typename std::decay<TP>::type, - typename folly::basic_fbstring<E, T, A, S>::value_type>::value, - basic_fbstring<E, T, A, S>&>::type -basic_fbstring<E, T, A, S>::operator=(TP c) { +inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::operator=( + value_type c) { Invariant checker(*this); if (empty()) { @@ -1946,7 +1849,7 @@ inline void basic_fbstring<E, T, A, S>::resize( auto pData = store_.expandNoinit(delta); fbstring_detail::podFill(pData, pData + delta, c); } - FBSTRING_ASSERT(this->size() == n); + assert(this->size() == n); } template <typename E, class T, class A, class S> @@ -1956,7 +1859,7 @@ inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::append( auto desiredSize = size() + str.size(); #endif append(str.data(), str.size()); - FBSTRING_ASSERT(size() == desiredSize); + assert(size() == desiredSize); return *this; } @@ -1972,11 +1875,11 @@ inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::append( } template <typename E, class T, class A, class S> -FOLLY_MALLOC_NOINLINE inline basic_fbstring<E, T, A, S>& +FOLLY_NOINLINE inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::append(const value_type* s, size_type n) { Invariant checker(*this); - if (FBSTRING_UNLIKELY(!n)) { + if (FOLLY_UNLIKELY(!n)) { // Unlikely but must be done return *this; } @@ -1991,8 +1894,8 @@ basic_fbstring<E, T, A, S>::append(const value_type* s, size_type n) { // over pointers. See discussion at http://goo.gl/Cy2ya for more // info. std::less_equal<const value_type*> le; - if (FBSTRING_UNLIKELY(le(oldData, s) && !le(oldData + oldSize, s))) { - FBSTRING_ASSERT(le(s + n, oldData + oldSize)); + if (FOLLY_UNLIKELY(le(oldData, s) && !le(oldData + oldSize, s))) { + assert(le(s + n, oldData + oldSize)); // expandNoinit() could have moved the storage, restore the source. s = data() + (s - oldData); fbstring_detail::podMove(s, s + n, pData); @@ -2000,7 +1903,7 @@ basic_fbstring<E, T, A, S>::append(const value_type* s, size_type n) { fbstring_detail::podCopy(s, s + n, pData); } - FBSTRING_ASSERT(size() == oldSize + n); + assert(size() == oldSize + n); return *this; } @@ -2026,7 +1929,7 @@ inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::assign( } template <typename E, class T, class A, class S> -FOLLY_MALLOC_NOINLINE inline basic_fbstring<E, T, A, S>& +FOLLY_NOINLINE inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::assign(const value_type* s, const size_type n) { Invariant checker(*this); @@ -2036,7 +1939,7 @@ basic_fbstring<E, T, A, S>::assign(const value_type* s, const size_type n) { // s can alias this, we need to use podMove. fbstring_detail::podMove(s, s + n, store_.mutableData()); store_.shrink(size() - n); - FBSTRING_ASSERT(size() == n); + assert(size() == n); } else { // If n is larger than size(), s cannot alias this string's // storage. @@ -2046,11 +1949,10 @@ basic_fbstring<E, T, A, S>::assign(const value_type* s, const size_type n) { fbstring_detail::podCopy(s, s + n, store_.expandNoinit(n)); } - FBSTRING_ASSERT(size() == n); + assert(size() == n); return *this; } -#ifndef _LIBSTDCXX_FBSTRING template <typename E, class T, class A, class S> inline typename basic_fbstring<E, T, A, S>::istream_type& basic_fbstring<E, T, A, S>::getlineImpl(istream_type& is, value_type delim) { @@ -2074,8 +1976,8 @@ basic_fbstring<E, T, A, S>::getlineImpl(istream_type& is, value_type delim) { break; } - FBSTRING_ASSERT(size == this->size()); - FBSTRING_ASSERT(size == capacity()); + assert(size == this->size()); + assert(size == capacity()); // Start at minimum allocation 63 + terminator = 64. reserve(std::max<size_t>(63, 3 * size / 2)); // Clear the error so we can continue reading. @@ -2083,7 +1985,6 @@ basic_fbstring<E, T, A, S>::getlineImpl(istream_type& is, value_type delim) { } return is; } -#endif template <typename E, class T, class A, class S> inline typename basic_fbstring<E, T, A, S>::size_type @@ -2126,7 +2027,7 @@ basic_fbstring<E, T, A, S>::find( // Here we know that the last char matches // Continue in pedestrian mode for (size_t j = 0;;) { - FBSTRING_ASSERT(j < nsize); + assert(j < nsize); if (i[j] != needle[j]) { // Not found, we can skip // Compute the skip value lazily @@ -2158,7 +2059,7 @@ basic_fbstring<E, T, A, S>::insertImplDiscr( std::true_type) { Invariant checker(*this); - FBSTRING_ASSERT(i >= cbegin() && i <= cend()); + assert(i >= cbegin() && i <= cend()); const size_type pos = i - cbegin(); auto oldSize = size(); @@ -2192,10 +2093,10 @@ basic_fbstring<E, T, A, S>::insertImpl( std::forward_iterator_tag) { Invariant checker(*this); - FBSTRING_ASSERT(i >= cbegin() && i <= cend()); + assert(i >= cbegin() && i <= cend()); const size_type pos = i - cbegin(); auto n = std::distance(s1, s2); - FBSTRING_ASSERT(n >= 0); + assert(n >= 0); auto oldSize = size(); store_.expandNoinit(n, /* expGrowth = */ true); @@ -2231,9 +2132,9 @@ inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::replaceImplDiscr( const value_type* s, size_type n, std::integral_constant<int, 2>) { - FBSTRING_ASSERT(i1 <= i2); - FBSTRING_ASSERT(begin() <= i1 && i1 <= end()); - FBSTRING_ASSERT(begin() <= i2 && i2 <= end()); + assert(i1 <= i2); + assert(begin() <= i1 && i1 <= end()); + assert(begin() <= i2 && i2 <= end()); return replace(i1, i2, s, s + n); } @@ -2252,7 +2153,7 @@ inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::replaceImplDiscr( std::fill(i1, i2, c); insert(i2, n2 - n1, c); } - FBSTRING_ASSERT(isSane()); + assert(isSane()); return *this; } @@ -2309,9 +2210,9 @@ inline void basic_fbstring<E, T, A, S>::replaceImpl( } auto const n1 = i2 - i1; - FBSTRING_ASSERT(n1 >= 0); + assert(n1 >= 0); auto const n2 = std::distance(s1, s2); - FBSTRING_ASSERT(n2 >= 0); + assert(n2 >= 0); if (n1 > n2) { // shrinks @@ -2322,7 +2223,7 @@ inline void basic_fbstring<E, T, A, S>::replaceImpl( s1 = fbstring_detail::copy_n(s1, n1, i1).first; insert(i2, s1, s2); } - FBSTRING_ASSERT(isSane()); + assert(isSane()); } template <typename E, class T, class A, class S> @@ -2450,7 +2351,7 @@ inline basic_fbstring<E, T, A, S> operator+( basic_fbstring<E, T, A, S> result; result.reserve(lhs.size() + rhs.size()); result.append(lhs).append(rhs); - return std::move(result); + return result; } // C++11 21.4.8.1/2 @@ -2736,7 +2637,7 @@ operator>>( _istream_type; typename _istream_type::sentry sentry(is); size_t extracted = 0; - auto err = _istream_type::goodbit; + typename _istream_type::iostate err = _istream_type::goodbit; if (sentry) { auto n = is.width(); if (n <= 0) { @@ -2813,7 +2714,6 @@ template <typename E1, class T, class A, class S> constexpr typename basic_fbstring<E1, T, A, S>::size_type basic_fbstring<E1, T, A, S>::npos; -#ifndef _LIBSTDCXX_FBSTRING // basic_string compatibility routines template <typename E, class T, class A, class S, class A2> @@ -2900,24 +2800,15 @@ inline bool operator>=( return !(lhs < rhs); } -#if !defined(_LIBSTDCXX_FBSTRING) typedef basic_fbstring<char> fbstring; -#endif // fbstring is relocatable template <class T, class R, class A, class S> FOLLY_ASSUME_RELOCATABLE(basic_fbstring<T, R, A, S>); -#endif +} // namespace folly -FOLLY_FBSTRING_END_NAMESPACE - -#ifndef _LIBSTDCXX_FBSTRING - -// Hash functions to make fbstring usable with e.g. hash_map -// -// Handle interaction with different C++ standard libraries, which -// expect these types to be in different namespaces. +// Hash functions to make fbstring usable with e.g. unordered_map #define FOLLY_FBSTRING_HASH1(T) \ template <> \ @@ -2927,7 +2818,7 @@ FOLLY_FBSTRING_END_NAMESPACE } \ }; -// The C++11 standard says that these four are defined +// The C++11 standard says that these four are defined for basic_string #define FOLLY_FBSTRING_HASH \ FOLLY_FBSTRING_HASH1(char) \ FOLLY_FBSTRING_HASH1(char16_t) \ @@ -2943,18 +2834,10 @@ FOLLY_FBSTRING_HASH #undef FOLLY_FBSTRING_HASH #undef FOLLY_FBSTRING_HASH1 -#endif // _LIBSTDCXX_FBSTRING - FOLLY_POP_WARNING #undef FBSTRING_DISABLE_SSO -#undef FBSTRING_SANITIZE_ADDRESS -#undef throw -#undef FBSTRING_LIKELY -#undef FBSTRING_UNLIKELY -#undef FBSTRING_ASSERT -#ifndef _LIBSTDCXX_FBSTRING namespace folly { template <class T> struct IsSomeString; @@ -2962,4 +2845,3 @@ struct IsSomeString; template <> struct IsSomeString<fbstring> : std::true_type {}; } // namespace folly -#endif diff --git a/ios/Pods/Folly/folly/FBVector.h b/ios/Pods/Folly/folly/FBVector.h index 7d7f39d59..29ef06b43 100644 --- a/ios/Pods/Folly/folly/FBVector.h +++ b/ios/Pods/Folly/folly/FBVector.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -37,6 +37,7 @@ #include <folly/FormatTraits.h> #include <folly/Likely.h> +#include <folly/ScopeGuard.h> #include <folly/Traits.h> #include <folly/lang/Exception.h> #include <folly/memory/Malloc.h> @@ -117,7 +118,7 @@ class fbvector { // allocation // note that 'allocate' and 'deallocate' are inherited from Allocator T* D_allocate(size_type n) { - if (usingStdAllocator::value) { + if (usingStdAllocator) { return static_cast<T*>(checkedMalloc(n * sizeof(T))); } else { return std::allocator_traits<Allocator>::allocate(*this, n); @@ -125,7 +126,7 @@ class fbvector { } void D_deallocate(T* p, size_type n) noexcept { - if (usingStdAllocator::value) { + if (usingStdAllocator) { free(p); } else { std::allocator_traits<Allocator>::deallocate(*this, p, n); @@ -145,7 +146,7 @@ class fbvector { // THIS DISPATCH CODE IS DUPLICATED IN fbvector::D_destroy_range_a. // It has been inlined here for speed. It calls the static fbvector // methods to perform the actual destruction. - if (usingStdAllocator::value) { + if (usingStdAllocator) { S_destroy_range(b_, e_); } else { S_destroy_range_a(*this, b_, e_); @@ -174,12 +175,9 @@ class fbvector { void reset(size_type newCap) { destroy(); - try { - init(newCap); - } catch (...) { - init(0); - throw; - } + auto rollback = makeGuard([&] { init(0); }); + init(newCap); + rollback.dismiss(); } void reset() { // same as reset(0) destroy(); @@ -189,7 +187,7 @@ class fbvector { static void swap(Impl& a, Impl& b) { using std::swap; - if (!usingStdAllocator::value) { + if (!usingStdAllocator) { swap(static_cast<Allocator&>(a), static_cast<Allocator&>(b)); } a.swapData(b); @@ -213,22 +211,16 @@ class fbvector { typedef std::reverse_iterator<const_iterator> const_reverse_iterator; private: - typedef bool_constant< + static constexpr bool should_pass_by_value = is_trivially_copyable<T>::value && - sizeof(T) <= 16 // don't force large structures to be passed by value - > - should_pass_by_value; - typedef - typename std::conditional<should_pass_by_value::value, T, const T&>::type - VT; - typedef - typename std::conditional<should_pass_by_value::value, T, T&&>::type MT; + sizeof(T) <= 16; // don't force large structures to be passed by value + typedef typename std::conditional<should_pass_by_value, T, const T&>::type VT; + typedef typename std::conditional<should_pass_by_value, T, T&&>::type MT; - typedef bool_constant<std::is_same<Allocator, std::allocator<T>>::value> - usingStdAllocator; + static constexpr bool usingStdAllocator = + std::is_same<Allocator, std::allocator<T>>::value; typedef bool_constant< - usingStdAllocator::value || - A::propagate_on_container_move_assignment::value> + usingStdAllocator || A::propagate_on_container_move_assignment::value> moveIsSwap; //=========================================================================== @@ -257,7 +249,7 @@ class fbvector { template <typename U, typename... Args> void M_construct(U* p, Args&&... args) { - if (usingStdAllocator::value) { + if (usingStdAllocator) { new (p) U(std::forward<Args>(args)...); } else { std::allocator_traits<Allocator>::construct( @@ -282,7 +274,7 @@ class fbvector { typename U, typename Enable = typename std::enable_if<std::is_scalar<U>::value>::type> void M_construct(U* p, U arg) { - if (usingStdAllocator::value) { + if (usingStdAllocator) { *p = arg; } else { std::allocator_traits<Allocator>::construct(impl_, p, arg); @@ -309,7 +301,7 @@ class fbvector { typename Enable = typename std::enable_if<!std::is_scalar<U>::value>::type> void M_construct(U* p, const U& value) { - if (usingStdAllocator::value) { + if (usingStdAllocator) { new (p) U(value); } else { std::allocator_traits<Allocator>::construct(impl_, p, value); @@ -336,7 +328,7 @@ class fbvector { // destroy void M_destroy(T* p) noexcept { - if (usingStdAllocator::value) { + if (usingStdAllocator) { if (!std::is_trivially_destructible<T>::value) { p->~T(); } @@ -361,7 +353,7 @@ class fbvector { // dispatch // THIS DISPATCH CODE IS DUPLICATED IN IMPL. SEE IMPL FOR DETAILS. void D_destroy_range_a(T* first, T* last) noexcept { - if (usingStdAllocator::value) { + if (usingStdAllocator) { S_destroy_range(first, last); } else { S_destroy_range_a(impl_, first, last); @@ -380,7 +372,7 @@ class fbvector { if (!std::is_trivially_destructible<T>::value) { #define FOLLY_FBV_OP(p) (p)->~T() // EXPERIMENTAL DATA on fbvector<vector<int>> (where each vector<int> has - // size 0). + // size 0), were vector<int> to be relocatable. // The unrolled version seems to work faster for small to medium sized // fbvectors. It gets a 10% speedup on fbvectors of size 1024, 64, and // 16. @@ -411,7 +403,7 @@ class fbvector { // dispatch void D_uninitialized_fill_n_a(T* dest, size_type sz) { - if (usingStdAllocator::value) { + if (usingStdAllocator) { S_uninitialized_fill_n(dest, sz); } else { S_uninitialized_fill_n_a(impl_, dest, sz); @@ -419,7 +411,7 @@ class fbvector { } void D_uninitialized_fill_n_a(T* dest, size_type sz, VT value) { - if (usingStdAllocator::value) { + if (usingStdAllocator) { S_uninitialized_fill_n(dest, sz, value); } else { S_uninitialized_fill_n_a(impl_, dest, sz, value); @@ -435,51 +427,44 @@ class fbvector { Args&&... args) { auto b = dest; auto e = dest + sz; - try { - for (; b != e; ++b) { - std::allocator_traits<Allocator>::construct( - a, b, std::forward<Args>(args)...); - } - } catch (...) { - S_destroy_range_a(a, dest, b); - throw; + auto rollback = makeGuard([&] { S_destroy_range_a(a, dest, b); }); + for (; b != e; ++b) { + std::allocator_traits<Allocator>::construct( + a, b, std::forward<Args>(args)...); } + rollback.dismiss(); } // optimized static void S_uninitialized_fill_n(T* dest, size_type n) { if (folly::IsZeroInitializable<T>::value) { if (LIKELY(n != 0)) { - std::memset(dest, 0, sizeof(T) * n); + std::memset((void*)dest, 0, sizeof(T) * n); } } else { auto b = dest; auto e = dest + n; - try { - for (; b != e; ++b) { - S_construct(b); - } - } catch (...) { + auto rollback = makeGuard([&] { --b; for (; b >= dest; --b) { b->~T(); } - throw; + }); + for (; b != e; ++b) { + S_construct(b); } + rollback.dismiss(); } } static void S_uninitialized_fill_n(T* dest, size_type n, const T& value) { auto b = dest; auto e = dest + n; - try { - for (; b != e; ++b) { - S_construct(b, value); - } - } catch (...) { - S_destroy_range(dest, b); - throw; + auto rollback = makeGuard([&] { S_destroy_range(dest, b); }); + for (; b != e; ++b) { + S_construct(b, value); } + rollback.dismiss(); } //--------------------------------------------------------------------------- @@ -504,7 +489,7 @@ class fbvector { // dispatch template <typename It> void D_uninitialized_copy_a(T* dest, It first, It last) { - if (usingStdAllocator::value) { + if (usingStdAllocator) { if (folly::is_trivially_copyable<T>::value) { S_uninitialized_copy_bits(dest, first, last); } else { @@ -525,28 +510,22 @@ class fbvector { template <typename It> static void S_uninitialized_copy_a(Allocator& a, T* dest, It first, It last) { auto b = dest; - try { - for (; first != last; ++first, ++b) { - std::allocator_traits<Allocator>::construct(a, b, *first); - } - } catch (...) { - S_destroy_range_a(a, dest, b); - throw; + auto rollback = makeGuard([&] { S_destroy_range_a(a, dest, b); }); + for (; first != last; ++first, ++b) { + std::allocator_traits<Allocator>::construct(a, b, *first); } + rollback.dismiss(); } // optimized template <typename It> static void S_uninitialized_copy(T* dest, It first, It last) { auto b = dest; - try { - for (; first != last; ++first, ++b) { - S_construct(b, *first); - } - } catch (...) { - S_destroy_range(dest, b); - throw; + auto rollback = makeGuard([&] { S_destroy_range(dest, b); }); + for (; first != last; ++first, ++b) { + S_construct(b, *first); } + rollback.dismiss(); } static void @@ -654,13 +633,11 @@ class fbvector { } // dispatch type trait - typedef bool_constant< - folly::IsRelocatable<T>::value && usingStdAllocator::value> + typedef bool_constant<folly::IsRelocatable<T>::value && usingStdAllocator> relocate_use_memcpy; typedef bool_constant< - (std::is_nothrow_move_constructible<T>::value && - usingStdAllocator::value) || + (std::is_nothrow_move_constructible<T>::value && usingStdAllocator) || !std::is_copy_constructible<T>::value> relocate_use_move; @@ -689,7 +666,7 @@ class fbvector { // done void relocate_done(T* /*dest*/, T* first, T* last) noexcept { - if (folly::IsRelocatable<T>::value && usingStdAllocator::value) { + if (folly::IsRelocatable<T>::value && usingStdAllocator) { // used memcpy; data has been relocated, do not call destructor } else { D_destroy_range_a(first, last); @@ -698,11 +675,10 @@ class fbvector { // undo void relocate_undo(T* dest, T* first, T* last) noexcept { - if (folly::IsRelocatable<T>::value && usingStdAllocator::value) { + if (folly::IsRelocatable<T>::value && usingStdAllocator) { // used memcpy, old data is still valid, nothing to do } else if ( - std::is_nothrow_move_constructible<T>::value && - usingStdAllocator::value) { + std::is_nothrow_move_constructible<T>::value && usingStdAllocator) { // noexcept move everything back, aka relocate_move relocate_move(first, dest, dest + (last - first)); } else if (!std::is_copy_constructible<T>::value) { @@ -769,7 +745,7 @@ class fbvector { return *this; } - if (!usingStdAllocator::value && + if (!usingStdAllocator && A::propagate_on_container_copy_assignment::value) { if (impl_ != other.impl_) { // can't use other's different allocator to clean up self @@ -906,7 +882,7 @@ class fbvector { // contract dispatch for aliasing under VT optimization bool dataIsInternalAndNotVT(const T& t) { - if (should_pass_by_value::value) { + if (should_pass_by_value) { return false; } return dataIsInternal(t); @@ -1011,11 +987,10 @@ class fbvector { auto newCap = folly::goodMallocSize(n * sizeof(T)) / sizeof(T); auto newB = M_allocate(newCap); - try { + { + auto rollback = makeGuard([&] { M_deallocate(newB, newCap); }); M_relocate(newB); - } catch (...) { - M_deallocate(newB, newCap); - throw; + rollback.dismiss(); } if (impl_.b_) { M_deallocate(impl_.b_, size_type(impl_.z_ - impl_.b_)); @@ -1042,21 +1017,31 @@ class fbvector { void* p = impl_.b_; // xallocx() will shrink to precisely newCapacityBytes (which was generated // by goodMallocSize()) if it successfully shrinks in place. - if ((usingJEMalloc() && usingStdAllocator::value) && + if ((usingJEMalloc() && usingStdAllocator) && newCapacityBytes >= folly::jemallocMinInPlaceExpandable && xallocx(p, newCapacityBytes, 0, 0) == newCapacityBytes) { impl_.z_ += newCap - oldCap; } else { T* newB; // intentionally uninitialized - try { - newB = M_allocate(newCap); - try { - M_relocate(newB); - } catch (...) { - M_deallocate(newB, newCap); - return; // swallow the error - } - } catch (...) { + if (!catch_exception( + [&] { + newB = M_allocate(newCap); + return true; + }, + [&] { // + return false; + })) { + return; + } + if (!catch_exception( + [&] { + M_relocate(newB); + return true; + }, + [&] { + M_deallocate(newB, newCap); + return false; + })) { return; } if (impl_.b_) { @@ -1070,7 +1055,7 @@ class fbvector { private: bool reserve_in_place(size_type n) { - if (!usingStdAllocator::value || !usingJEMalloc()) { + if (!usingStdAllocator || !usingJEMalloc()) { return false; } @@ -1145,13 +1130,14 @@ class fbvector { // modifiers (common) public: template <class... Args> - void emplace_back(Args&&... args) { + reference emplace_back(Args&&... args) { if (impl_.e_ != impl_.z_) { M_construct(impl_.e_, std::forward<Args>(args)...); ++impl_.e_; } else { emplace_back_aux(std::forward<Args>(args)...); } + return back(); } void push_back(const T& value) { @@ -1179,7 +1165,7 @@ class fbvector { } void swap(fbvector& other) noexcept { - if (!usingStdAllocator::value && A::propagate_on_container_swap::value) { + if (!usingStdAllocator && A::propagate_on_container_swap::value) { swap(impl_, other.impl_); } else { impl_.swapData(other.impl_); @@ -1223,7 +1209,69 @@ class fbvector { } template <class... Args> - void emplace_back_aux(Args&&... args); + void emplace_back_aux(Args&&... args) { + size_type byte_sz = + folly::goodMallocSize(computePushBackCapacity() * sizeof(T)); + if (usingStdAllocator && usingJEMalloc() && + ((impl_.z_ - impl_.b_) * sizeof(T) >= + folly::jemallocMinInPlaceExpandable)) { + // Try to reserve in place. + // Ask xallocx to allocate in place at least size()+1 and at most sz + // space. + // xallocx will allocate as much as possible within that range, which + // is the best possible outcome: if sz space is available, take it all, + // otherwise take as much as possible. If nothing is available, then + // fail. + // In this fashion, we never relocate if there is a possibility of + // expanding in place, and we never reallocate by less than the desired + // amount unless we cannot expand further. Hence we will not reallocate + // sub-optimally twice in a row (modulo the blocking memory being freed). + size_type lower = folly::goodMallocSize(sizeof(T) + size() * sizeof(T)); + size_type upper = byte_sz; + size_type extra = upper - lower; + + void* p = impl_.b_; + size_t actual; + + if ((actual = xallocx(p, lower, extra, 0)) >= lower) { + impl_.z_ = impl_.b_ + actual / sizeof(T); + M_construct(impl_.e_, std::forward<Args>(args)...); + ++impl_.e_; + return; + } + } + + // Reallocation failed. Perform a manual relocation. + size_type sz = byte_sz / sizeof(T); + auto newB = M_allocate(sz); + auto newE = newB + size(); + { + auto rollback1 = makeGuard([&] { M_deallocate(newB, sz); }); + if (folly::IsRelocatable<T>::value && usingStdAllocator) { + // For linear memory access, relocate before construction. + // By the test condition, relocate is noexcept. + // Note that there is no cleanup to do if M_construct throws - that's + // one of the beauties of relocation. + // Benchmarks for this code have high variance, and seem to be close. + relocate_move(newB, impl_.b_, impl_.e_); + M_construct(newE, std::forward<Args>(args)...); + ++newE; + } else { + M_construct(newE, std::forward<Args>(args)...); + ++newE; + auto rollback2 = makeGuard([&] { M_destroy(newE - 1); }); + M_relocate(newB); + rollback2.dismiss(); + } + rollback1.dismiss(); + } + if (impl_.b_) { + M_deallocate(impl_.b_, size()); + } + impl_.b_ = newB; + impl_.e_ = newE; + impl_.z_ = newB + sz; + } //=========================================================================== //--------------------------------------------------------------------------- @@ -1240,12 +1288,13 @@ class fbvector { if (last == end()) { M_destroy_range_e((iterator)first); } else { - if (folly::IsRelocatable<T>::value && usingStdAllocator::value) { + if (folly::IsRelocatable<T>::value && usingStdAllocator) { D_destroy_range_a((iterator)first, (iterator)last); if (last - first >= cend() - last) { std::memcpy((void*)first, (void*)last, (cend() - last) * sizeof(T)); } else { - std::memmove((iterator)first, last, (cend() - last) * sizeof(T)); + std::memmove( + (void*)first, (void*)last, (cend() - last) * sizeof(T)); } impl_.e_ -= (last - first); } else { @@ -1339,20 +1388,21 @@ class fbvector { relocate_done(position + n, position, impl_.e_); impl_.e_ += n; } else { - if (folly::IsRelocatable<T>::value && usingStdAllocator::value) { - std::memmove(position + n, position, tail * sizeof(T)); + if (folly::IsRelocatable<T>::value && usingStdAllocator) { + std::memmove((void*)(position + n), (void*)position, tail * sizeof(T)); impl_.e_ += n; } else { D_uninitialized_move_a(impl_.e_, impl_.e_ - n, impl_.e_); - try { + { + auto rollback = makeGuard([&] { + D_destroy_range_a(impl_.e_ - n, impl_.e_ + n); + impl_.e_ -= n; + }); std::copy_backward( std::make_move_iterator(position), std::make_move_iterator(impl_.e_ - n), impl_.e_); - } catch (...) { - D_destroy_range_a(impl_.e_ - n, impl_.e_ + n); - impl_.e_ -= n; - throw; + rollback.dismiss(); } impl_.e_ += n; D_destroy_range_a(position, position + n); @@ -1373,11 +1423,12 @@ class fbvector { assert(n != 0); relocate_move(ledge, impl_.b_, impl_.b_ + idx); - try { + { + auto rollback = makeGuard([&] { // + relocate_undo(ledge, impl_.b_, impl_.b_ + idx); + }); relocate_move(ledge + idx + n, impl_.b_ + idx, impl_.e_); - } catch (...) { - relocate_undo(ledge, impl_.b_, impl_.b_ + idx); - throw; + rollback.dismiss(); } relocate_done(ledge, impl_.b_, impl_.b_ + idx); relocate_done(ledge + idx + n, impl_.b_ + idx, impl_.e_); @@ -1449,30 +1500,32 @@ class fbvector { } T* start = b + idx; - try { + { + auto rollback = makeGuard([&] { + if (fresh) { + M_deallocate(b, newCap); + } else { + if (!at_end) { + undo_window(position, n); + } else { + impl_.e_ -= n; + } + } + }); // construct the inserted elements constructFunc(start); - } catch (...) { - if (fresh) { - M_deallocate(b, newCap); - } else { - if (!at_end) { - undo_window(position, n); - } else { - impl_.e_ -= n; - } - } - throw; + rollback.dismiss(); } if (fresh) { - try { + { + auto rollback = makeGuard([&] { + // delete the inserted elements (exception has been thrown) + destroyFunc(start); + M_deallocate(b, newCap); + }); wrap_frame(b, idx, n); - } catch (...) { - // delete the inserted elements (exception has been thrown) - destroyFunc(start); - M_deallocate(b, newCap); - throw; + rollback.dismiss(); } if (impl_.b_) { M_deallocate(impl_.b_, capacity()); @@ -1618,78 +1671,6 @@ class fbvector { }; // class fbvector -//============================================================================= -//----------------------------------------------------------------------------- -// outlined functions (gcc, you finicky compiler you) - -template <typename T, typename Allocator> -template <class... Args> -void fbvector<T, Allocator>::emplace_back_aux(Args&&... args) { - size_type byte_sz = - folly::goodMallocSize(computePushBackCapacity() * sizeof(T)); - if (usingStdAllocator::value && usingJEMalloc() && - ((impl_.z_ - impl_.b_) * sizeof(T) >= - folly::jemallocMinInPlaceExpandable)) { - // Try to reserve in place. - // Ask xallocx to allocate in place at least size()+1 and at most sz space. - // xallocx will allocate as much as possible within that range, which - // is the best possible outcome: if sz space is available, take it all, - // otherwise take as much as possible. If nothing is available, then fail. - // In this fashion, we never relocate if there is a possibility of - // expanding in place, and we never reallocate by less than the desired - // amount unless we cannot expand further. Hence we will not reallocate - // sub-optimally twice in a row (modulo the blocking memory being freed). - size_type lower = folly::goodMallocSize(sizeof(T) + size() * sizeof(T)); - size_type upper = byte_sz; - size_type extra = upper - lower; - - void* p = impl_.b_; - size_t actual; - - if ((actual = xallocx(p, lower, extra, 0)) >= lower) { - impl_.z_ = impl_.b_ + actual / sizeof(T); - M_construct(impl_.e_, std::forward<Args>(args)...); - ++impl_.e_; - return; - } - } - - // Reallocation failed. Perform a manual relocation. - size_type sz = byte_sz / sizeof(T); - auto newB = M_allocate(sz); - auto newE = newB + size(); - try { - if (folly::IsRelocatable<T>::value && usingStdAllocator::value) { - // For linear memory access, relocate before construction. - // By the test condition, relocate is noexcept. - // Note that there is no cleanup to do if M_construct throws - that's - // one of the beauties of relocation. - // Benchmarks for this code have high variance, and seem to be close. - relocate_move(newB, impl_.b_, impl_.e_); - M_construct(newE, std::forward<Args>(args)...); - ++newE; - } else { - M_construct(newE, std::forward<Args>(args)...); - ++newE; - try { - M_relocate(newB); - } catch (...) { - M_destroy(newE - 1); - throw; - } - } - } catch (...) { - M_deallocate(newB, sz); - throw; - } - if (impl_.b_) { - M_deallocate(impl_.b_, size()); - } - impl_.b_ = newB; - impl_.e_ = newE; - impl_.z_ = newB + sz; -} - //============================================================================= //----------------------------------------------------------------------------- // specialized functions @@ -1756,4 +1737,22 @@ void attach(fbvector<T, A>& v, T* data, size_t sz, size_t cap) { v.impl_.z_ = data + cap; } +#if __cpp_deduction_guides >= 201703 +template < + class InputIt, + class Allocator = + std::allocator<typename std::iterator_traits<InputIt>::value_type>> +fbvector(InputIt, InputIt, Allocator = Allocator()) + ->fbvector<typename std::iterator_traits<InputIt>::value_type, Allocator>; +#endif + +template <class T, class A, class U> +void erase(fbvector<T, A>& v, U value) { + v.erase(std::remove(v.begin(), v.end(), value), v.end()); +} + +template <class T, class A, class Predicate> +void erase_if(fbvector<T, A>& v, Predicate predicate) { + v.erase(std::remove_if(v.begin(), v.end(), predicate), v.end()); +} } // namespace folly diff --git a/ios/Pods/Folly/folly/File.h b/ios/Pods/Folly/folly/File.h index aa4edd967..d6766a339 100644 --- a/ios/Pods/Folly/folly/File.h +++ b/ios/Pods/Folly/folly/File.h @@ -1,11 +1,11 @@ /* - * Copyright 2013-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/FileUtil.cpp b/ios/Pods/Folly/folly/FileUtil.cpp new file mode 100644 index 000000000..0c2a1b771 --- /dev/null +++ b/ios/Pods/Folly/folly/FileUtil.cpp @@ -0,0 +1,258 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <folly/FileUtil.h> + +#include <cerrno> +#include <string> +#include <system_error> +#include <vector> + +#include <folly/detail/FileUtilDetail.h> +#include <folly/net/NetOps.h> +#include <folly/portability/Fcntl.h> +#include <folly/portability/Sockets.h> +#include <folly/portability/Stdlib.h> +#include <folly/portability/SysFile.h> +#include <folly/portability/SysStat.h> + +namespace folly { + +using namespace fileutil_detail; + +int openNoInt(const char* name, int flags, mode_t mode) { + return int(wrapNoInt(open, name, flags, mode)); +} + +static int filterCloseReturn(int r) { + // Ignore EINTR. On Linux, close() may only return EINTR after the file + // descriptor has been closed, so you must not retry close() on EINTR -- + // in the best case, you'll get EBADF, and in the worst case, you'll end up + // closing a different file (one opened from another thread). + // + // Interestingly enough, the Single Unix Specification says that the state + // of the file descriptor is unspecified if close returns EINTR. In that + // case, the safe thing to do is also not to retry close() -- leaking a file + // descriptor is definitely better than closing the wrong file. + if (r == -1 && errno == EINTR) { + return 0; + } + return r; +} + +int closeNoInt(int fd) { + return filterCloseReturn(close(fd)); +} + +int closeNoInt(NetworkSocket fd) { + return filterCloseReturn(netops::close(fd)); +} + +int fsyncNoInt(int fd) { + return int(wrapNoInt(fsync, fd)); +} + +int dupNoInt(int fd) { + return int(wrapNoInt(dup, fd)); +} + +int dup2NoInt(int oldfd, int newfd) { + return int(wrapNoInt(dup2, oldfd, newfd)); +} + +int fdatasyncNoInt(int fd) { +#if defined(__APPLE__) + return int(wrapNoInt(fcntl, fd, F_FULLFSYNC)); +#elif defined(__FreeBSD__) || defined(_MSC_VER) + return int(wrapNoInt(fsync, fd)); +#else + return int(wrapNoInt(fdatasync, fd)); +#endif +} + +int ftruncateNoInt(int fd, off_t len) { + return int(wrapNoInt(ftruncate, fd, len)); +} + +int truncateNoInt(const char* path, off_t len) { + return int(wrapNoInt(truncate, path, len)); +} + +int flockNoInt(int fd, int operation) { + return int(wrapNoInt(flock, fd, operation)); +} + +int shutdownNoInt(NetworkSocket fd, int how) { + return int(wrapNoInt(netops::shutdown, fd, how)); +} + +ssize_t readNoInt(int fd, void* buf, size_t count) { + return wrapNoInt(read, fd, buf, count); +} + +ssize_t preadNoInt(int fd, void* buf, size_t count, off_t offset) { + return wrapNoInt(pread, fd, buf, count, offset); +} + +ssize_t readvNoInt(int fd, const iovec* iov, int count) { + return wrapNoInt(readv, fd, iov, count); +} + +ssize_t preadvNoInt(int fd, const iovec* iov, int count, off_t offset) { + return wrapNoInt(preadv, fd, iov, count, offset); +} + +ssize_t writeNoInt(int fd, const void* buf, size_t count) { + return wrapNoInt(write, fd, buf, count); +} + +ssize_t pwriteNoInt(int fd, const void* buf, size_t count, off_t offset) { + return wrapNoInt(pwrite, fd, buf, count, offset); +} + +ssize_t writevNoInt(int fd, const iovec* iov, int count) { + return wrapNoInt(writev, fd, iov, count); +} + +ssize_t pwritevNoInt(int fd, const iovec* iov, int count, off_t offset) { + return wrapNoInt(pwritev, fd, iov, count, offset); +} + +ssize_t readFull(int fd, void* buf, size_t count) { + return wrapFull(read, fd, buf, count); +} + +ssize_t preadFull(int fd, void* buf, size_t count, off_t offset) { + return wrapFull(pread, fd, buf, count, offset); +} + +ssize_t writeFull(int fd, const void* buf, size_t count) { + return wrapFull(write, fd, const_cast<void*>(buf), count); +} + +ssize_t pwriteFull(int fd, const void* buf, size_t count, off_t offset) { + return wrapFull(pwrite, fd, const_cast<void*>(buf), count, offset); +} + +ssize_t readvFull(int fd, iovec* iov, int count) { + return wrapvFull(readv, fd, iov, count); +} + +ssize_t preadvFull(int fd, iovec* iov, int count, off_t offset) { + return wrapvFull(preadv, fd, iov, count, offset); +} + +ssize_t writevFull(int fd, iovec* iov, int count) { + return wrapvFull(writev, fd, iov, count); +} + +ssize_t pwritevFull(int fd, iovec* iov, int count, off_t offset) { + return wrapvFull(pwritev, fd, iov, count, offset); +} + +int writeFileAtomicNoThrow( + StringPiece filename, + iovec* iov, + int count, + mode_t permissions) { + // We write the data to a temporary file name first, then atomically rename + // it into place. This ensures that the file contents will always be valid, + // even if we crash or are killed partway through writing out data. + // + // Create a buffer that will contain two things: + // - A nul-terminated version of the filename + // - The temporary file name + std::vector<char> pathBuffer; + // Note that we have to explicitly pass in the size here to make + // sure the nul byte gets included in the data. + constexpr folly::StringPiece suffix(".XXXXXX\0", 8); + pathBuffer.resize((2 * filename.size()) + 1 + suffix.size()); + // Copy in the filename and then a nul terminator + memcpy(pathBuffer.data(), filename.data(), filename.size()); + pathBuffer[filename.size()] = '\0'; + const char* const filenameCStr = pathBuffer.data(); + // Now prepare the temporary path template + char* const tempPath = pathBuffer.data() + filename.size() + 1; + memcpy(tempPath, filename.data(), filename.size()); + memcpy(tempPath + filename.size(), suffix.data(), suffix.size()); + + auto tmpFD = mkstemp(tempPath); + if (tmpFD == -1) { + return errno; + } + bool success = false; + SCOPE_EXIT { + if (tmpFD != -1) { + close(tmpFD); + } + if (!success) { + unlink(tempPath); + } + }; + + auto rc = writevFull(tmpFD, iov, count); + if (rc == -1) { + return errno; + } + + rc = fchmod(tmpFD, permissions); + if (rc == -1) { + return errno; + } + + // Close the file before renaming to make sure all data has + // been successfully written. + rc = close(tmpFD); + tmpFD = -1; + if (rc == -1) { + return errno; + } + + rc = rename(tempPath, filenameCStr); + if (rc == -1) { + return errno; + } + success = true; + return 0; +} + +void writeFileAtomic( + StringPiece filename, + iovec* iov, + int count, + mode_t permissions) { + auto rc = writeFileAtomicNoThrow(filename, iov, count, permissions); + if (rc != 0) { + auto msg = std::string(__func__) + "() failed to update " + filename.str(); + throw std::system_error(rc, std::generic_category(), msg); + } +} + +void writeFileAtomic(StringPiece filename, ByteRange data, mode_t permissions) { + iovec iov; + iov.iov_base = const_cast<unsigned char*>(data.data()); + iov.iov_len = data.size(); + writeFileAtomic(filename, &iov, 1, permissions); +} + +void writeFileAtomic( + StringPiece filename, + StringPiece data, + mode_t permissions) { + writeFileAtomic(filename, ByteRange(data), permissions); +} + +} // namespace folly diff --git a/ios/Pods/Folly/folly/FileUtil.h b/ios/Pods/Folly/folly/FileUtil.h index da5da8749..a50e809a4 100644 --- a/ios/Pods/Folly/folly/FileUtil.h +++ b/ios/Pods/Folly/folly/FileUtil.h @@ -1,11 +1,11 @@ /* - * Copyright 2013-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -25,6 +25,7 @@ #include <folly/Portability.h> #include <folly/Range.h> #include <folly/ScopeGuard.h> +#include <folly/net/NetworkSocket.h> #include <folly/portability/Fcntl.h> #include <folly/portability/SysUio.h> #include <folly/portability/Unistd.h> @@ -38,7 +39,9 @@ namespace folly { * semantics of underlying system calls. */ int openNoInt(const char* name, int flags, mode_t mode = 0666); +// Two overloads, as we may be closing either a file or a socket. int closeNoInt(int fd); +int closeNoInt(NetworkSocket fd); int dupNoInt(int fd); int dup2NoInt(int oldfd, int newfd); int fsyncNoInt(int fd); @@ -46,15 +49,17 @@ int fdatasyncNoInt(int fd); int ftruncateNoInt(int fd, off_t len); int truncateNoInt(const char* path, off_t len); int flockNoInt(int fd, int operation); -int shutdownNoInt(int fd, int how); +int shutdownNoInt(NetworkSocket fd, int how); -ssize_t readNoInt(int fd, void* buf, size_t n); -ssize_t preadNoInt(int fd, void* buf, size_t n, off_t offset); +ssize_t readNoInt(int fd, void* buf, size_t count); +ssize_t preadNoInt(int fd, void* buf, size_t count, off_t offset); ssize_t readvNoInt(int fd, const iovec* iov, int count); +ssize_t preadvNoInt(int fd, const iovec* iov, int count, off_t offset); -ssize_t writeNoInt(int fd, const void* buf, size_t n); -ssize_t pwriteNoInt(int fd, const void* buf, size_t n, off_t offset); +ssize_t writeNoInt(int fd, const void* buf, size_t count); +ssize_t pwriteNoInt(int fd, const void* buf, size_t count, off_t offset); ssize_t writevNoInt(int fd, const iovec* iov, int count); +ssize_t pwritevNoInt(int fd, const iovec* iov, int count, off_t offset); /** * Wrapper around read() (and pread()) that, in addition to retrying on @@ -78,8 +83,8 @@ ssize_t writevNoInt(int fd, const iovec* iov, int count); * readv and preadv. The contents of iov after these functions return * is unspecified. */ -FOLLY_NODISCARD ssize_t readFull(int fd, void* buf, size_t n); -FOLLY_NODISCARD ssize_t preadFull(int fd, void* buf, size_t n, off_t offset); +FOLLY_NODISCARD ssize_t readFull(int fd, void* buf, size_t count); +FOLLY_NODISCARD ssize_t preadFull(int fd, void* buf, size_t count, off_t offset); FOLLY_NODISCARD ssize_t readvFull(int fd, iovec* iov, int count); FOLLY_NODISCARD ssize_t preadvFull(int fd, iovec* iov, int count, off_t offset); @@ -100,8 +105,8 @@ FOLLY_NODISCARD ssize_t preadvFull(int fd, iovec* iov, int count, off_t offset); * These functions return -1 on error, or the total number of bytes written * (which is always the same as the number of requested bytes) on success. */ -ssize_t writeFull(int fd, const void* buf, size_t n); -ssize_t pwriteFull(int fd, const void* buf, size_t n, off_t offset); +ssize_t writeFull(int fd, const void* buf, size_t count); +ssize_t pwriteFull(int fd, const void* buf, size_t count, off_t offset); ssize_t writevFull(int fd, iovec* iov, int count); ssize_t pwritevFull(int fd, iovec* iov, int count, off_t offset); @@ -126,7 +131,7 @@ bool readFile( size_t soFar = 0; // amount of bytes successfully read SCOPE_EXIT { - DCHECK(out.size() >= soFar); // resize better doesn't throw + assert(out.size() >= soFar); // resize better doesn't throw out.resize(soFar); }; @@ -170,7 +175,7 @@ bool readFile( const char* file_name, Container& out, size_t num_bytes = std::numeric_limits<size_t>::max()) { - DCHECK(file_name); + assert(file_name); const auto fd = openNoInt(file_name, O_RDONLY | O_CLOEXEC); if (fd == -1) { diff --git a/ios/Pods/Folly/folly/Fingerprint.h b/ios/Pods/Folly/folly/Fingerprint.h index 59b3176fd..568606228 100644 --- a/ios/Pods/Folly/folly/Fingerprint.h +++ b/ios/Pods/Folly/folly/Fingerprint.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -72,7 +72,7 @@ template <int BITS> const poly_table<BITS> FingerprintTable<BITS>::table = {}; #ifndef _MSC_VER -// MSVC 2015 can't handle these extern specialization declarations, +// MSVC as of 2017 can't handle these extern specialization declarations, // but they aren't needed for things to work right, so we just don't // declare them in the header for MSVC. diff --git a/ios/Pods/Folly/folly/FixedString.h b/ios/Pods/Folly/folly/FixedString.h index 08f6e4b7a..5a4276bdb 100644 --- a/ios/Pods/Folly/folly/FixedString.h +++ b/ios/Pods/Folly/folly/FixedString.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -79,6 +79,10 @@ constexpr std::size_t checkOverflowOrNpos(std::size_t i, std::size_t max) { : (i <= max ? i : (void(assertOutOfBounds()), max)); } +constexpr std::size_t checkOverflowIfDebug(std::size_t i, std::size_t size) { + return kIsDebug ? checkOverflow(i, size) : i; +} + // Intentionally NOT constexpr. See note above for assertOutOfBounds [[noreturn]] inline void assertNotNullTerminated() noexcept { assert(!"Non-null terminated string used to initialize a BasicFixedString"); @@ -100,13 +104,6 @@ constexpr const Char (&checkNullTerminated(const Char (&a)[N]) noexcept)[N] { : (assertNotNullTerminated(), decltype(a)(a)); } -// Rather annoyingly, GCC's -Warray-bounds warning issues false positives for -// this code. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61971 -#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 5 -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Warray-bounds" -#endif - template <class Left, class Right> constexpr ordering compare_( const Left& left, @@ -271,7 +268,7 @@ struct Helper { std::size_t left_count, const Right& right, std::size_t right_count, - folly::index_sequence<Is...> is) noexcept { + std::index_sequence<Is...> is) noexcept { return {left, left_count, right, right_count, is}; } @@ -284,7 +281,7 @@ struct Helper { const Right& right, std::size_t right_pos, std::size_t right_count, - folly::index_sequence<Is...> is) noexcept { + std::index_sequence<Is...> is) noexcept { return {left, left_size, left_pos, @@ -302,12 +299,8 @@ struct Helper { } }; -#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 4 -#pragma GCC diagnostic pop -#endif - template <class T> -FOLLY_CPP14_CONSTEXPR void constexpr_swap(T& a, T& b) noexcept( +constexpr void constexpr_swap(T& a, T& b) noexcept( noexcept(a = T(std::move(a)))) { T tmp((std::move(a))); a = std::move(b); @@ -336,8 +329,7 @@ struct ReverseIterator { constexpr ReverseIterator() = default; constexpr ReverseIterator(const ReverseIterator&) = default; - FOLLY_CPP14_CONSTEXPR ReverseIterator& operator=(const ReverseIterator&) = - default; + constexpr ReverseIterator& operator=(const ReverseIterator&) = default; constexpr explicit ReverseIterator(T* p) noexcept : p_(p) {} constexpr /* implicit */ ReverseIterator(const other& that) noexcept : p_(that.p_) {} @@ -354,25 +346,25 @@ struct ReverseIterator { constexpr reference operator*() const { return *(p_ - 1); } - FOLLY_CPP14_CONSTEXPR ReverseIterator& operator++() noexcept { + constexpr ReverseIterator& operator++() noexcept { --p_; return *this; } - FOLLY_CPP14_CONSTEXPR ReverseIterator operator++(int) noexcept { + constexpr ReverseIterator operator++(int) noexcept { auto tmp(*this); --p_; return tmp; } - FOLLY_CPP14_CONSTEXPR ReverseIterator& operator--() noexcept { + constexpr ReverseIterator& operator--() noexcept { ++p_; return *this; } - FOLLY_CPP14_CONSTEXPR ReverseIterator operator--(int) noexcept { + constexpr ReverseIterator operator--(int) noexcept { auto tmp(*this); ++p_; return tmp; } - FOLLY_CPP14_CONSTEXPR ReverseIterator& operator+=(std::ptrdiff_t i) noexcept { + constexpr ReverseIterator& operator+=(std::ptrdiff_t i) noexcept { p_ -= i; return *this; } @@ -386,7 +378,7 @@ struct ReverseIterator { std::ptrdiff_t i) noexcept { return ReverseIterator{that.p_ - i}; } - FOLLY_CPP14_CONSTEXPR ReverseIterator& operator-=(std::ptrdiff_t i) noexcept { + constexpr ReverseIterator& operator-=(std::ptrdiff_t i) noexcept { p_ += i; return *this; } @@ -528,13 +520,13 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { Char data_[N + 1u]; // +1 for the null terminator std::size_t size_; // Nbr of chars, not incl. null terminator. size_ <= N. - using Indices = folly::make_index_sequence<N>; + using Indices = std::make_index_sequence<N>; template <class That, std::size_t... Is> constexpr BasicFixedString( const That& that, std::size_t size, - folly::index_sequence<Is...>, + std::index_sequence<Is...>, std::size_t pos = 0, std::size_t count = npos) noexcept : data_{(Is < (size - pos) && Is < count ? that[Is + pos] : Char(0))..., @@ -545,7 +537,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { constexpr BasicFixedString( std::size_t count, Char ch, - folly::index_sequence<Is...>) noexcept + std::index_sequence<Is...>) noexcept : data_{((Is < count) ? ch : Char(0))..., Char(0)}, size_{count} {} // Concatenation constructor @@ -555,7 +547,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { std::size_t left_size, const Right& right, std::size_t right_size, - folly::index_sequence<Is...>) noexcept + std::index_sequence<Is...>) noexcept : data_{detail::fixedstring::char_at_<Char>( left, left_size, @@ -575,7 +567,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { const Right& right, std::size_t right_pos, std::size_t right_count, - folly::index_sequence<Is...>) noexcept + std::index_sequence<Is...>) noexcept : data_{detail::fixedstring::char_at_<Char>( left, left_size, @@ -664,7 +656,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { : BasicFixedString{ that.data_, that.size_, - folly::make_index_sequence<(M < N ? M : N)>{}, + std::make_index_sequence<(M < N ? M : N)>{}, pos, detail::fixedstring::checkOverflow( detail::fixedstring::checkOverflowOrNpos( @@ -685,7 +677,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { constexpr /* implicit */ BasicFixedString(const Char (&that)[M]) noexcept : BasicFixedString{detail::fixedstring::checkNullTerminated(that), M - 1u, - folly::make_index_sequence<M - 1u>{}} {} + std::make_index_sequence<M - 1u>{}} {} /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** * Construct from a `const Char*` and count @@ -728,8 +720,8 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { constexpr BasicFixedString(std::initializer_list<Char> il) noexcept(false) : BasicFixedString{il.begin(), il.size()} {} - FOLLY_CPP14_CONSTEXPR BasicFixedString& operator=( - const BasicFixedString&) noexcept = default; + constexpr BasicFixedString& operator=(const BasicFixedString&) noexcept = + default; /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** * Assign from a `BasicFixedString<Char, M>`. @@ -745,7 +737,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \return `*this` */ template <std::size_t M> - FOLLY_CPP14_CONSTEXPR BasicFixedString& operator=( + constexpr BasicFixedString& operator=( const BasicFixedString<Char, M>& that) noexcept(M <= N) { detail::fixedstring::checkOverflow(that.size_, N); size_ = that.copy(data_, that.size_); @@ -764,8 +756,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \return `*this` */ template <std::size_t M, class = typename std::enable_if<(M - 1u <= N)>::type> - FOLLY_CPP14_CONSTEXPR BasicFixedString& operator=( - const Char (&that)[M]) noexcept { + constexpr BasicFixedString& operator=(const Char (&that)[M]) noexcept { return assign(detail::fixedstring::checkNullTerminated(that), M - 1u); } @@ -778,7 +769,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \throw std::out_of_range when il.size() > N * \return `*this` */ - FOLLY_CPP14_CONSTEXPR BasicFixedString& operator=( + constexpr BasicFixedString& operator=( std::initializer_list<Char> il) noexcept(false) { detail::fixedstring::checkOverflow(il.size(), N); for (std::size_t i = 0u; i < il.size(); ++i) { @@ -793,7 +784,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * Conversion to folly::Range * \return `Range<Char*>{begin(), end()}` */ - FOLLY_CPP14_CONSTEXPR Range<Char*> toRange() noexcept { + constexpr Range<Char*> toRange() noexcept { return {begin(), end()}; } @@ -821,7 +812,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { // to compile. But it creates ambiguities when passing a FixedString to an // API that has overloads for `const char*` and `folly::Range`, for instance. // using ArrayType = Char[N]; - // FOLLY_CPP14_CONSTEXPR /* implicit */ operator ArrayType&() noexcept { + // constexpr /* implicit */ operator ArrayType&() noexcept { // return data_; // } @@ -841,9 +832,8 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \throw std::out_of_range when count > N * \return `*this` */ - FOLLY_CPP14_CONSTEXPR BasicFixedString& assign( - std::size_t count, - Char ch) noexcept(false) { + constexpr BasicFixedString& assign(std::size_t count, Char ch) noexcept( + false) { detail::fixedstring::checkOverflow(count, N); for (std::size_t i = 0u; i < count; ++i) { data_[i] = ch; @@ -858,7 +848,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \note Equivalent to `assign(that, 0, that.size())` */ template <std::size_t M> - FOLLY_CPP14_CONSTEXPR BasicFixedString& assign( + constexpr BasicFixedString& assign( const BasicFixedString<Char, M>& that) noexcept(M <= N) { return *this = that; } @@ -868,7 +858,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { // N is a count of characters. In the latter, it would be a position, which // totally changes the meaning of the code. template <std::size_t M> - FOLLY_CPP14_CONSTEXPR BasicFixedString& assign( + constexpr BasicFixedString& assign( const BasicFixedString<Char, M>& that, std::size_t pos) noexcept(false) = delete; @@ -890,7 +880,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \return `*this` */ template <std::size_t M> - FOLLY_CPP14_CONSTEXPR BasicFixedString& assign( + constexpr BasicFixedString& assign( const BasicFixedString<Char, M>& that, std::size_t pos, std::size_t count) noexcept(false) { @@ -907,8 +897,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \note Equivalent to `assign(that, M - 1)` */ template <std::size_t M, class = typename std::enable_if<(M - 1u <= N)>::type> - FOLLY_CPP14_CONSTEXPR BasicFixedString& assign( - const Char (&that)[M]) noexcept { + constexpr BasicFixedString& assign(const Char (&that)[M]) noexcept { return assign(detail::fixedstring::checkNullTerminated(that), M - 1u); } @@ -924,7 +913,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \throw std::out_of_range when count > N * \return `*this` */ - FOLLY_CPP14_CONSTEXPR BasicFixedString& assign( + constexpr BasicFixedString& assign( const Char* that, std::size_t count) noexcept(false) { detail::fixedstring::checkOverflow(count, N); @@ -939,7 +928,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** * Swap the contents of this string with `that`. */ - FOLLY_CPP14_CONSTEXPR void swap(BasicFixedString& that) noexcept { + constexpr void swap(BasicFixedString& that) noexcept { // less-than-or-equal here to copy the null terminator: for (std::size_t i = 0u; i <= folly::constexpr_max(size_, that.size_); ++i) { @@ -952,7 +941,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * Return a pointer to a range of `size()+1` characters, the last of which * is `Char(0)`. */ - FOLLY_CPP14_CONSTEXPR Char* data() noexcept { + constexpr Char* data() noexcept { return data_; } @@ -973,7 +962,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** * \return `data()`. */ - FOLLY_CPP14_CONSTEXPR Char* begin() noexcept { + constexpr Char* begin() noexcept { return data_; } @@ -994,7 +983,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** * \return `data() + size()`. */ - FOLLY_CPP14_CONSTEXPR Char* end() noexcept { + constexpr Char* end() noexcept { return data_ + size_; } @@ -1016,7 +1005,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * Returns a reverse iterator to the first character of the reversed string. * It corresponds to the last + 1 character of the non-reversed string. */ - FOLLY_CPP14_CONSTEXPR reverse_iterator rbegin() noexcept { + constexpr reverse_iterator rbegin() noexcept { return reverse_iterator{data_ + size_}; } @@ -1038,7 +1027,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * Returns a reverse iterator to the last + 1 character of the reversed * string. It corresponds to the first character of the non-reversed string. */ - FOLLY_CPP14_CONSTEXPR reverse_iterator rend() noexcept { + constexpr reverse_iterator rend() noexcept { return reverse_iterator{data_}; } @@ -1102,7 +1091,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \return `*(data() + i)` * \throw std::out_of_range when i > size() */ - FOLLY_CPP14_CONSTEXPR Char& at(std::size_t i) noexcept(false) { + constexpr Char& at(std::size_t i) noexcept(false) { return i <= size_ ? data_[i] : (throw_exception<std::out_of_range>( "Out of range in BasicFixedString::at"), @@ -1124,29 +1113,21 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \note `(*this)[size()]` is allowed will return `Char(0)`. * \return `*(data() + i)` */ - FOLLY_CPP14_CONSTEXPR Char& operator[](std::size_t i) noexcept { -#ifdef NDEBUG - return data_[i]; -#else - return data_[detail::fixedstring::checkOverflow(i, size_)]; -#endif + constexpr Char& operator[](std::size_t i) noexcept { + return data_[detail::fixedstring::checkOverflowIfDebug(i, size_)]; } /** * \overload */ constexpr const Char& operator[](std::size_t i) const noexcept { -#ifdef NDEBUG - return data_[i]; -#else - return data_[detail::fixedstring::checkOverflow(i, size_)]; -#endif + return data_[detail::fixedstring::checkOverflowIfDebug(i, size_)]; } /** * \note Equivalent to `(*this)[0]` */ - FOLLY_CPP14_CONSTEXPR Char& front() noexcept { + constexpr Char& front() noexcept { return (*this)[0u]; } @@ -1161,23 +1142,15 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \note Equivalent to `at(size()-1)` * \pre `!empty()` */ - FOLLY_CPP14_CONSTEXPR Char& back() noexcept { -#ifdef NDEBUG - return data_[size_ - 1u]; -#else - return data_[size_ - detail::fixedstring::checkOverflow(1u, size_)]; -#endif + constexpr Char& back() noexcept { + return data_[size_ - detail::fixedstring::checkOverflowIfDebug(1u, size_)]; } /** * \overload */ constexpr const Char& back() const noexcept { -#ifdef NDEBUG - return data_[size_ - 1u]; -#else - return data_[size_ - detail::fixedstring::checkOverflow(1u, size_)]; -#endif + return data_[size_ - detail::fixedstring::checkOverflowIfDebug(1u, size_)]; } /** @@ -1185,7 +1158,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \post `size() == 0u` * \post `at(size()) == Char(0)` */ - FOLLY_CPP14_CONSTEXPR void clear() noexcept { + constexpr void clear() noexcept { data_[0u] = Char(0); size_ = 0u; } @@ -1193,7 +1166,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { /** * \note Equivalent to `append(1u, ch)`. */ - FOLLY_CPP14_CONSTEXPR void push_back(Char ch) noexcept(false) { + constexpr void push_back(Char ch) noexcept(false) { detail::fixedstring::checkOverflow(1u, N - size_); data_[size_] = ch; data_[++size_] = Char(0); @@ -1214,7 +1187,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \post The characters in the half-open range `[0,size()-1)` are unmodified. * \throw std::out_of_range if empty(). */ - FOLLY_CPP14_CONSTEXPR void pop_back() noexcept(false) { + constexpr void pop_back() noexcept(false) { detail::fixedstring::checkOverflow(1u, size_); --size_; data_[size_] = Char(0); @@ -1237,9 +1210,8 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \post `size() == old_size + count` * \throw std::out_of_range if count > N - size(). */ - FOLLY_CPP14_CONSTEXPR BasicFixedString& append( - std::size_t count, - Char ch) noexcept(false) { + constexpr BasicFixedString& append(std::size_t count, Char ch) noexcept( + false) { detail::fixedstring::checkOverflow(count, N - size_); for (std::size_t i = 0u; i < count; ++i) { data_[size_ + i] = ch; @@ -1253,7 +1225,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \note Equivalent to `append(*this, 0, that.size())`. */ template <std::size_t M> - FOLLY_CPP14_CONSTEXPR BasicFixedString& append( + constexpr BasicFixedString& append( const BasicFixedString<Char, M>& that) noexcept(false) { return append(that, 0u, that.size_); } @@ -1262,7 +1234,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { // append("null-terminated", N), where N would be a count instead // of a position. template <std::size_t M> - FOLLY_CPP14_CONSTEXPR BasicFixedString& append( + constexpr BasicFixedString& append( const BasicFixedString<Char, M>& that, std::size_t pos) noexcept(false) = delete; @@ -1283,7 +1255,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * `old_size + count > N`. */ template <std::size_t M> - FOLLY_CPP14_CONSTEXPR BasicFixedString& append( + constexpr BasicFixedString& append( const BasicFixedString<Char, M>& that, std::size_t pos, std::size_t count) noexcept(false) { @@ -1301,8 +1273,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { /** * \note Equivalent to `append(that, strlen(that))`. */ - FOLLY_CPP14_CONSTEXPR BasicFixedString& append(const Char* that) noexcept( - false) { + constexpr BasicFixedString& append(const Char* that) noexcept(false) { return append(that, folly::constexpr_strlen(that)); } @@ -1315,7 +1286,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \post `at(size()) == Char(0)` * \throw std::out_of_range if old_size + count > N. */ - FOLLY_CPP14_CONSTEXPR BasicFixedString& append( + constexpr BasicFixedString& append( const Char* that, std::size_t count) noexcept(false) { detail::fixedstring::checkOverflow(count, N - size_); @@ -1401,8 +1372,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * Appends characters from a null-terminated string literal to this string. * \note Equivalent to `append(that)`. */ - FOLLY_CPP14_CONSTEXPR BasicFixedString& operator+=(const Char* that) noexcept( - false) { + constexpr BasicFixedString& operator+=(const Char* that) noexcept(false) { return append(that); } @@ -1411,7 +1381,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \note Equivalent to `append(that)`. */ template <std::size_t M> - FOLLY_CPP14_CONSTEXPR BasicFixedString& operator+=( + constexpr BasicFixedString& operator+=( const BasicFixedString<Char, M>& that) noexcept(false) { return append(that, 0u, that.size_); } @@ -1420,7 +1390,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * Appends a character to this string. * \note Equivalent to `push_back(ch)`. */ - FOLLY_CPP14_CONSTEXPR BasicFixedString& operator+=(Char ch) noexcept(false) { + constexpr BasicFixedString& operator+=(Char ch) noexcept(false) { push_back(ch); return *this; } @@ -1429,7 +1399,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * Appends characters from an `initializer_list` to this string. * \note Equivalent to `append(il.begin(), il.size())`. */ - FOLLY_CPP14_CONSTEXPR BasicFixedString& operator+=( + constexpr BasicFixedString& operator+=( std::initializer_list<Char> il) noexcept(false) { return append(il.begin(), il.size()); } @@ -1439,7 +1409,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \note Equivalent to `clear()` * \return *this; */ - FOLLY_CPP14_CONSTEXPR BasicFixedString& erase() noexcept { + constexpr BasicFixedString& erase() noexcept { clear(); return *this; } @@ -1454,15 +1424,16 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \return *this; * \throw std::out_of_range when pos > size(). */ - FOLLY_CPP14_CONSTEXPR BasicFixedString& erase( + constexpr BasicFixedString& erase( std::size_t pos, std::size_t count = npos) noexcept(false) { using A = const Char[1]; + constexpr A a{Char(0)}; return replace( pos, detail::fixedstring::checkOverflowOrNpos( count, size_ - detail::fixedstring::checkOverflow(pos, size_)), - A{Char(0)}, + a, 0u); } @@ -1470,7 +1441,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \note Equivalent to `erase(first - data(), 1)` * \return A pointer to the first character after the erased character. */ - FOLLY_CPP14_CONSTEXPR Char* erase(const Char* first) noexcept(false) { + constexpr Char* erase(const Char* first) noexcept(false) { erase(first - data_, 1u); return data_ + (first - data_); } @@ -1479,9 +1450,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \note Equivalent to `erase(first - data(), last - first)` * \return A pointer to the first character after the erased characters. */ - FOLLY_CPP14_CONSTEXPR Char* erase( - const Char* first, - const Char* last) noexcept(false) { + constexpr Char* erase(const Char* first, const Char* last) noexcept(false) { erase(first - data_, last - first); return data_ + (first - data_); } @@ -1660,7 +1629,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * `replace(first - data(), last - first, that.data(), that.size())` */ template <std::size_t M> - FOLLY_CPP14_CONSTEXPR BasicFixedString& replace( + constexpr BasicFixedString& replace( const Char* first, const Char* last, const BasicFixedString<Char, M>& that) noexcept(false) { @@ -1676,7 +1645,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * that.size() - that_pos)</tt> */ template <std::size_t M> - FOLLY_CPP14_CONSTEXPR BasicFixedString& replace( + constexpr BasicFixedString& replace( std::size_t this_pos, std::size_t this_count, const BasicFixedString<Char, M>& that, @@ -1693,7 +1662,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * `replace(this_pos, this_count, that.data() + that_pos, that_count)` */ template <std::size_t M> - FOLLY_CPP14_CONSTEXPR BasicFixedString& replace( + constexpr BasicFixedString& replace( std::size_t this_pos, std::size_t this_count, const BasicFixedString<Char, M>& that, @@ -1708,7 +1677,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \note Equivalent to * `replace(this_pos, this_count, that, strlen(that))` */ - FOLLY_CPP14_CONSTEXPR BasicFixedString& replace( + constexpr BasicFixedString& replace( std::size_t this_pos, std::size_t this_count, const Char* that) noexcept(false) { @@ -1723,7 +1692,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \note Equivalent to * `replace(first - data(), last - first, that, strlen(that))` */ - FOLLY_CPP14_CONSTEXPR BasicFixedString& replace( + constexpr BasicFixedString& replace( const Char* first, const Char* last, const Char* that) noexcept(false) { @@ -1748,7 +1717,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * - `this_count > size() - this_pos` * - `size() - this_count + that_count > N` */ - FOLLY_CPP14_CONSTEXPR BasicFixedString& replace( + constexpr BasicFixedString& replace( std::size_t this_pos, std::size_t this_count, const Char* that, @@ -1771,7 +1740,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \note Equivalent to * `replace(this_pos, this_count, BasicFixedString{that_count, ch})` */ - FOLLY_CPP14_CONSTEXPR BasicFixedString& replace( + constexpr BasicFixedString& replace( std::size_t this_pos, std::size_t this_count, std::size_t that_count, @@ -1785,7 +1754,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \note Equivalent to * `replace(first - data(), last - first, BasicFixedString{that_count, ch})` */ - FOLLY_CPP14_CONSTEXPR BasicFixedString& replace( + constexpr BasicFixedString& replace( const Char* first, const Char* last, std::size_t that_count, @@ -1802,7 +1771,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \note Equivalent to * `replace(this_pos, this_count, il.begin(), il.size())` */ - FOLLY_CPP14_CONSTEXPR BasicFixedString& replace( + constexpr BasicFixedString& replace( const Char* first, const Char* last, std::initializer_list<Char> il) noexcept(false) { @@ -1871,7 +1840,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { detail::fixedstring::checkOverflow(that_pos, that.size_), detail::fixedstring::checkOverflowOrNpos( that_count, that.size_ - that_pos), - folly::make_index_sequence<N + M>{}); + std::make_index_sequence<N + M>{}); } /** @@ -1971,7 +1940,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { detail::fixedstring::checkNullTerminated(that), detail::fixedstring::checkOverflow(that_pos, M - 1u), detail::fixedstring::checkOverflowOrNpos(that_count, M - 1u - that_pos), - folly::make_index_sequence<N + M - 1u>{}); + std::make_index_sequence<N + M - 1u>{}); } /** @@ -2013,8 +1982,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * from this string into the buffer pointed to by `dest`. * \return The number of characters copied. */ - FOLLY_CPP14_CONSTEXPR std::size_t copy(Char* dest, std::size_t count) const - noexcept { + constexpr std::size_t copy(Char* dest, std::size_t count) const noexcept { return copy(dest, count, 0u); } @@ -2025,8 +1993,8 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * \return The number of characters copied. * \throw std::out_of_range if `pos > size()` */ - FOLLY_CPP14_CONSTEXPR std::size_t - copy(Char* dest, std::size_t count, std::size_t pos) const noexcept(false) { + constexpr std::size_t copy(Char* dest, std::size_t count, std::size_t pos) + const noexcept(false) { detail::fixedstring::checkOverflow(pos, size_); for (std::size_t i = 0u; i < count; ++i) { if (i + pos == size_) { @@ -2041,7 +2009,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * Resizes the current string. * \note Equivalent to `resize(count, Char(0))` */ - FOLLY_CPP14_CONSTEXPR void resize(std::size_t count) noexcept(false) { + constexpr void resize(std::size_t count) noexcept(false) { resize(count, Char(0)); } @@ -2050,8 +2018,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { * `data()[count]` to `Char(0)`. If `count > old_size`, the characters * in the range [`old_size`,`count`) are set to `ch`. */ - FOLLY_CPP14_CONSTEXPR void resize(std::size_t count, Char ch) noexcept( - false) { + constexpr void resize(std::size_t count, Char ch) noexcept(false) { detail::fixedstring::checkOverflow(count, N); if (count == size_) { } else if (count < size_) { @@ -2850,7 +2817,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { M - 1u, b.data_, b.size_, - folly::make_index_sequence<N + M - 1u>{}); + std::make_index_sequence<N + M - 1u>{}); } /** @@ -2865,7 +2832,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { a.size_, detail::fixedstring::checkNullTerminated(b), M - 1u, - folly::make_index_sequence<N + M - 1u>{}); + std::make_index_sequence<N + M - 1u>{}); } /** @@ -2880,7 +2847,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { 1u, b.data_, b.size_, - folly::make_index_sequence<N + 1u>{}); + std::make_index_sequence<N + 1u>{}); } /** @@ -2895,7 +2862,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { a.size_, A{b, Char(0)}, 1u, - folly::make_index_sequence<N + 1u>{}); + std::make_index_sequence<N + 1u>{}); } }; @@ -2976,7 +2943,7 @@ constexpr BasicFixedString<Char, N + M> operator+( a.size(), detail::fixedstring::Helper::data_(b), b.size(), - folly::make_index_sequence<N + M>{}); + std::make_index_sequence<N + M>{}); } /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** @@ -2997,7 +2964,7 @@ constexpr BasicFixedString<Char, N - 1u> makeFixedString( * Swap function */ template <class Char, std::size_t N> -FOLLY_CPP14_CONSTEXPR void swap( +constexpr void swap( BasicFixedString<Char, N>& a, BasicFixedString<Char, N>& b) noexcept { a.swap(b); @@ -3038,14 +3005,8 @@ constexpr const std::size_t& npos = detail::fixedstring::FixedStringBase::npos; */ template <class Char, Char... Cs> constexpr BasicFixedString<Char, sizeof...(Cs)> operator"" _fs() noexcept { -#if __cplusplus >= 201402L const Char a[] = {Cs..., Char(0)}; return {+a, sizeof...(Cs)}; -#else - using A = const Char[sizeof...(Cs) + 1u]; - // The `+` in `+A{etc}` forces the array type to decay to a pointer - return {+A{Cs..., Char(0)}, sizeof...(Cs)}; -#endif } #pragma GCC diagnostic pop diff --git a/ios/Pods/Folly/folly/Format-inl.h b/ios/Pods/Folly/folly/Format-inl.h index 3908d41dd..593c54e78 100644 --- a/ios/Pods/Folly/folly/Format-inl.h +++ b/ios/Pods/Folly/folly/Format-inl.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -32,9 +32,10 @@ #include <folly/lang/Exception.h> #include <folly/portability/Windows.h> -// Ignore -Wformat-nonliteral warnings within this file +// Ignore -Wformat-nonliteral and -Wconversion warnings within this file FOLLY_PUSH_WARNING FOLLY_GNU_DISABLE_WARNING("-Wformat-nonliteral") +FOLLY_GNU_DISABLE_WARNING("-Wconversion") namespace folly { @@ -260,11 +261,9 @@ void BaseFormatter<Derived, containerMode, Args...>::operator()( arg.width = asDerived().getSizeArg(size_t(arg.widthIndex), arg); } - try { - argIndex = to<int>(piece); - } catch (const std::out_of_range&) { - arg.error("argument index must be integer"); - } + auto result = tryTo<int>(piece); + arg.enforce(result, "argument index must be integer"); + argIndex = *result; arg.enforce(argIndex >= 0, "argument index must be non-negative"); hasExplicitArgIndex = true; } @@ -340,6 +339,7 @@ void formatString(StringPiece val, FormatArg& arg, FormatCallback& cb) { case FormatArg::Align::PAD_AFTER_SIGN: pad(padChars); break; + case FormatArg::Align::INVALID: default: abort(); break; @@ -451,7 +451,9 @@ class FormatValue< char sign; if (std::is_signed<T>::value) { if (folly::is_negative(val_)) { - uval = UT(-static_cast<UT>(val_)); + // avoid unary negation of unsigned types, which may be warned against + // avoid ub signed integer overflow, which ubsan checks against + uval = UT(0 - static_cast<UT>(val_)); sign = '-'; } else { uval = static_cast<UT>(val_); @@ -462,6 +464,9 @@ class FormatValue< case FormatArg::Sign::SPACE_OR_MINUS: sign = ' '; break; + case FormatArg::Sign::DEFAULT: + case FormatArg::Sign::MINUS: + case FormatArg::Sign::INVALID: default: sign = '\0'; break; diff --git a/ios/Pods/Folly/folly/Format.cpp b/ios/Pods/Folly/folly/Format.cpp index 50b3ef553..89007e76f 100644 --- a/ios/Pods/Folly/folly/Format.cpp +++ b/ios/Pods/Folly/folly/Format.cpp @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -16,6 +16,8 @@ #include <folly/Format.h> +#include <cassert> + #include <folly/ConstexprMath.h> #include <folly/CppAttributes.h> #include <folly/container/Array.h> @@ -49,7 +51,8 @@ struct format_table_conv_make_item { std::size_t index{}; constexpr explicit make_item(std::size_t index_) : index(index_) {} // gcc49 constexpr char alpha(std::size_t ord) const { - return ord < 10 ? '0' + ord : (Upper ? 'A' : 'a') + (ord - 10); + return static_cast<char>( + ord < 10 ? '0' + ord : (Upper ? 'A' : 'a') + (ord - 10)); } constexpr char operator()(std::size_t offset) const { return alpha(index / constexpr_pow(Base, Size - offset - 1) % Base); @@ -131,6 +134,9 @@ void FormatValue<double>::formatHelper( case FormatArg::Sign::SPACE_OR_MINUS: plusSign = ' '; break; + case FormatArg::Sign::DEFAULT: + case FormatArg::Sign::MINUS: + case FormatArg::Sign::INVALID: default: plusSign = '\0'; break; @@ -206,9 +212,9 @@ void FormatValue<double>::formatHelper( arg.error("invalid specifier '", arg.presentation, "'"); } - int len = builder.position(); + auto len = builder.position(); builder.Finalize(); - DCHECK_GT(len, 0); + assert(len > 0); // Add '+' or ' ' sign if needed char* p = buf + 1; @@ -264,7 +270,7 @@ void FormatArg::initSlow() { } Sign s; - unsigned char uSign = static_cast<unsigned char>(*p); + auto uSign = static_cast<unsigned char>(*p); if ((s = formatSignTable[uSign]) != Sign::INVALID) { sign = s; if (++p == end) { @@ -385,7 +391,7 @@ void FormatArg::validate(Type type) const { namespace detail { void insertThousandsGroupingUnsafe(char* start_buffer, char** end_buffer) { - uint32_t remaining_digits = uint32_t(*end_buffer - start_buffer); + auto remaining_digits = uint32_t(*end_buffer - start_buffer); uint32_t separator_size = (remaining_digits - 1) / 3; uint32_t result_size = remaining_digits + separator_size; *end_buffer = *end_buffer + separator_size; diff --git a/ios/Pods/Folly/folly/Format.h b/ios/Pods/Folly/folly/Format.h index 29be4dada..780126b16 100644 --- a/ios/Pods/Folly/folly/Format.h +++ b/ios/Pods/Folly/folly/Format.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -18,6 +18,7 @@ #define FOLLY_FORMAT_H_ #include <cstdio> +#include <ios> #include <stdexcept> #include <tuple> #include <type_traits> @@ -241,9 +242,9 @@ class Formatter : public BaseFormatter< /** * Formatter objects can be written to streams. */ -template <bool containerMode, class... Args> +template <class C, bool containerMode, class... Args> std::ostream& operator<<( - std::ostream& out, + std::basic_ostream<C>& out, const Formatter<containerMode, Args...>& formatter) { auto writer = [&out](StringPiece sp) { out.write(sp.data(), std::streamsize(sp.size())); diff --git a/ios/Pods/Folly/folly/FormatArg.h b/ios/Pods/Folly/folly/FormatArg.h index a203f392f..1ff843f96 100644 --- a/ios/Pods/Folly/folly/FormatArg.h +++ b/ios/Pods/Folly/folly/FormatArg.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -72,8 +72,9 @@ struct FormatArg { * message will contain the argument string as well as any passed-in * arguments to enforce, formatted using folly::to<std::string>. */ - template <typename... Args> - void enforce(bool v, Args&&... args) const { + template <typename Check, typename... Args> + void enforce(Check const& v, Args&&... args) const { + static_assert(std::is_constructible<bool, Check>::value, "not castable"); if (UNLIKELY(!v)) { error(std::forward<Args>(args)...); } @@ -268,12 +269,9 @@ inline int FormatArg::splitIntKey() { nextKeyMode_ = NextKeyMode::NONE; return nextIntKey_; } - try { - return to<int>(doSplitKey<true>()); - } catch (const std::out_of_range&) { - error("integer key required"); - return 0; // unreached - } + auto result = tryTo<int>(doSplitKey<true>()); + enforce(result, "integer key required"); + return *result; } } // namespace folly diff --git a/ios/Pods/Folly/folly/FormatTraits.h b/ios/Pods/Folly/folly/FormatTraits.h index 3e68a7571..b84715c30 100644 --- a/ios/Pods/Folly/folly/FormatTraits.h +++ b/ios/Pods/Folly/folly/FormatTraits.h @@ -1,11 +1,11 @@ /* - * Copyright 2015-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/Function.h b/ios/Pods/Folly/folly/Function.h index eb9676641..ee470ec75 100644 --- a/ios/Pods/Folly/folly/Function.h +++ b/ios/Pods/Folly/folly/Function.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + /* * @author Eric Niebler (eniebler@fb.com), Sven Over (over@fb.com) * Acknowledgements: Giuseppe Ottaviano (ott@fb.com) @@ -181,7 +182,7 @@ * the function accepts a non-const one. * * How does the const behaviour compare to `std::function`? - * `std::function` can wrap object with non-const invokation behaviour but + * `std::function` can wrap object with non-const invocation behaviour but * exposes them as const. The equivalent behaviour can be achieved with * `folly::Function` like so: * @@ -200,15 +201,15 @@ * `std::function` always involves this potentially dangerous aspect, which * is why it is not considered fully const-safe or even const-correct. * However, in most of the cases you will not need the dangerous aspect at all. - * Either you do not require invokation of the function from a const context, + * Either you do not require invocation of the function from a const context, * in which case you do not need to use `constCastFunction` and just * use the inner `folly::Function` in the example above, i.e. just use a - * non-const `folly::Function`. Or, you may need invokation from const, but + * non-const `folly::Function`. Or, you may need invocation from const, but * the callable you are wrapping does not mutate its state (e.g. it is a class * object and implements `operator() const`, or it is a normal, * non-mutable lambda), in which case you can wrap the callable in a const * `folly::Function` directly, without using `constCastFunction`. - * Only if you require invokation from a const context of a callable that + * Only if you require invocation from a const context of a callable that * may mutate itself when invoked you have to go through the above procedure. * However, in that case what you do is potentially dangerous and requires * the equivalent of a `const_cast`, hence you need to call @@ -273,13 +274,26 @@ using EnableIfNotFunction = struct CoerceTag {}; +template <typename, typename T> +struct IsFunctionNullptrTestable : std::false_type {}; + template <typename T> -bool isNullPtrFn(T* p) { - return p == nullptr; +struct IsFunctionNullptrTestable< + void_t<decltype( + static_cast<bool>(static_cast<T const&>(T(nullptr)) == nullptr))>, + T> : std::true_type {}; + +template <typename T> +constexpr std::enable_if_t< // + !IsFunctionNullptrTestable<void, T>::value, + std::false_type> +isEmptyFunction(T const&) { + return {}; } template <typename T> -std::false_type isNullPtrFn(T&&) { - return {}; +constexpr std::enable_if_t<IsFunctionNullptrTestable<void, T>::value, bool> +isEmptyFunction(T const& t) { + return static_cast<bool>(t == nullptr); } template <typename F, typename... Args> @@ -292,12 +306,70 @@ template < !std::is_reference<To>::value || std::is_reference<From>::value>::type> using SafeResultOf = decltype(static_cast<To>(std::declval<From>())); +#if defined(_MSC_VER) +// Need a workaround for MSVC to avoid the inscrutable error: +// +// folly\function.h(...) : fatal error C1001: An internal error has +// occurred in the compiler. +// (compiler file 'f:\dd\vctools\compiler\utc\src\p2\main.c', line 258) +// To work around this problem, try simplifying or changing the program +// near the locations listed above. +template <typename T> +using CallArg = T&&; +#else +template <typename T> +using CallArg = conditional_t<is_trivially_copyable<T>::value, T, T&&>; +#endif + +template <typename F, typename R, typename... A> +class FunctionTraitsSharedProxy { + std::shared_ptr<Function<F>> sp_; + + public: + explicit FunctionTraitsSharedProxy(std::nullptr_t) noexcept {} + explicit FunctionTraitsSharedProxy(Function<F>&& func) + : sp_(func ? std::make_shared<Function<F>>(std::move(func)) + : std::shared_ptr<Function<F>>()) {} + R operator()(A&&... args) const { + if (!sp_) { + throw_exception<std::bad_function_call>(); + } + return (*sp_)(static_cast<A&&>(args)...); + } + + explicit operator bool() const noexcept { + return sp_ != nullptr; + } + + friend bool operator==( + FunctionTraitsSharedProxy<F, R, A...> const& proxy, + std::nullptr_t) noexcept { + return proxy.sp_ == nullptr; + } + friend bool operator!=( + FunctionTraitsSharedProxy<F, R, A...> const& proxy, + std::nullptr_t) noexcept { + return proxy.sp_ != nullptr; + } + + friend bool operator==( + std::nullptr_t, + FunctionTraitsSharedProxy<F, R, A...> const& proxy) noexcept { + return proxy.sp_ == nullptr; + } + friend bool operator!=( + std::nullptr_t, + FunctionTraitsSharedProxy<F, R, A...> const& proxy) noexcept { + return proxy.sp_ != nullptr; + } +}; + template <typename FunctionType> struct FunctionTraits; template <typename ReturnType, typename... Args> struct FunctionTraits<ReturnType(Args...)> { - using Call = ReturnType (*)(Data&, Args&&...); + using Call = ReturnType (*)(CallArg<Args>..., Data&); using IsConst = std::false_type; using ConstSignature = ReturnType(Args...) const; using NonConstSignature = ReturnType(Args...); @@ -305,91 +377,106 @@ struct FunctionTraits<ReturnType(Args...)> { template <typename F> using ResultOf = - SafeResultOf<CallableResult<_t<std::decay<F>>&, Args...>, ReturnType>; + SafeResultOf<CallableResult<std::decay_t<F>&, Args...>, ReturnType>; template <typename Fun> - static ReturnType callSmall(Data& p, Args&&... args) { - return static_cast<ReturnType>((*static_cast<Fun*>( - static_cast<void*>(&p.tiny)))(static_cast<Args&&>(args)...)); + static ReturnType callSmall(CallArg<Args>... args, Data& p) { + auto& fn = *static_cast<Fun*>(static_cast<void*>(&p.tiny)); +#if __cpp_if_constexpr >= 201606L + if constexpr (std::is_void<ReturnType>::value) { + fn(static_cast<Args&&>(args)...); + } else { + return fn(static_cast<Args&&>(args)...); + } +#else + return static_cast<ReturnType>(fn(static_cast<Args&&>(args)...)); +#endif } template <typename Fun> - static ReturnType callBig(Data& p, Args&&... args) { - return static_cast<ReturnType>( - (*static_cast<Fun*>(p.big))(static_cast<Args&&>(args)...)); + static ReturnType callBig(CallArg<Args>... args, Data& p) { + auto& fn = *static_cast<Fun*>(p.big); +#if __cpp_if_constexpr >= 201606L + if constexpr (std::is_void<ReturnType>::value) { + fn(static_cast<Args&&>(args)...); + } else { + return fn(static_cast<Args&&>(args)...); + } +#else + return static_cast<ReturnType>(fn(static_cast<Args&&>(args)...)); +#endif } - static ReturnType uninitCall(Data&, Args&&...) { - throw std::bad_function_call(); + static ReturnType uninitCall(CallArg<Args>..., Data&) { + throw_exception<std::bad_function_call>(); } ReturnType operator()(Args... args) { auto& fn = *static_cast<Function<NonConstSignature>*>(this); - return fn.call_(fn.data_, static_cast<Args&&>(args)...); + return fn.call_(static_cast<Args&&>(args)..., fn.data_); } - class SharedProxy { - std::shared_ptr<Function<NonConstSignature>> sp_; - - public: - explicit SharedProxy(Function<NonConstSignature>&& func) - : sp_(std::make_shared<Function<NonConstSignature>>(std::move(func))) {} - ReturnType operator()(Args&&... args) const { - return (*sp_)(static_cast<Args&&>(args)...); - } - }; + using SharedProxy = + FunctionTraitsSharedProxy<NonConstSignature, ReturnType, Args...>; }; template <typename ReturnType, typename... Args> struct FunctionTraits<ReturnType(Args...) const> { - using Call = ReturnType (*)(Data&, Args&&...); + using Call = ReturnType (*)(CallArg<Args>..., Data&); using IsConst = std::true_type; using ConstSignature = ReturnType(Args...) const; using NonConstSignature = ReturnType(Args...); using OtherSignature = NonConstSignature; template <typename F> - using ResultOf = SafeResultOf< - CallableResult<const _t<std::decay<F>>&, Args...>, - ReturnType>; + using ResultOf = + SafeResultOf<CallableResult<const std::decay_t<F>&, Args...>, ReturnType>; template <typename Fun> - static ReturnType callSmall(Data& p, Args&&... args) { - return static_cast<ReturnType>((*static_cast<const Fun*>( - static_cast<void*>(&p.tiny)))(static_cast<Args&&>(args)...)); + static ReturnType callSmall(CallArg<Args>... args, Data& p) { + auto& fn = *static_cast<const Fun*>(static_cast<void*>(&p.tiny)); +#if __cpp_if_constexpr >= 201606L + if constexpr (std::is_void<ReturnType>::value) { + fn(static_cast<Args&&>(args)...); + } else { + return fn(static_cast<Args&&>(args)...); + } +#else + return static_cast<ReturnType>(fn(static_cast<Args&&>(args)...)); +#endif } template <typename Fun> - static ReturnType callBig(Data& p, Args&&... args) { - return static_cast<ReturnType>( - (*static_cast<const Fun*>(p.big))(static_cast<Args&&>(args)...)); + static ReturnType callBig(CallArg<Args>... args, Data& p) { + auto& fn = *static_cast<const Fun*>(p.big); +#if __cpp_if_constexpr >= 201606L + if constexpr (std::is_void<ReturnType>::value) { + fn(static_cast<Args&&>(args)...); + } else { + return fn(static_cast<Args&&>(args)...); + } +#else + return static_cast<ReturnType>(fn(static_cast<Args&&>(args)...)); +#endif } - static ReturnType uninitCall(Data&, Args&&...) { - throw std::bad_function_call(); + static ReturnType uninitCall(CallArg<Args>..., Data&) { + throw_exception<std::bad_function_call>(); } ReturnType operator()(Args... args) const { auto& fn = *static_cast<const Function<ConstSignature>*>(this); - return fn.call_(fn.data_, static_cast<Args&&>(args)...); + return fn.call_(static_cast<Args&&>(args)..., fn.data_); } - class SharedProxy { - std::shared_ptr<Function<ConstSignature>> sp_; - - public: - explicit SharedProxy(Function<ConstSignature>&& func) - : sp_(std::make_shared<Function<ConstSignature>>(std::move(func))) {} - ReturnType operator()(Args&&... args) const { - return (*sp_)(static_cast<Args&&>(args)...); - } - }; + using SharedProxy = + FunctionTraitsSharedProxy<ConstSignature, ReturnType, Args...>; }; #if FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE template <typename ReturnType, typename... Args> struct FunctionTraits<ReturnType(Args...) noexcept> { - using Call = ReturnType (*)(Data&, Args&&...) noexcept; + using Call = ReturnType (*)(CallArg<Args>..., Data&) noexcept; using IsConst = std::false_type; using ConstSignature = ReturnType(Args...) const noexcept; using NonConstSignature = ReturnType(Args...) noexcept; @@ -397,90 +484,105 @@ struct FunctionTraits<ReturnType(Args...) noexcept> { template <typename F> using ResultOf = - SafeResultOf<CallableResult<_t<std::decay<F>>&, Args...>, ReturnType>; + SafeResultOf<CallableResult<std::decay_t<F>&, Args...>, ReturnType>; template <typename Fun> - static ReturnType callSmall(Data& p, Args&&... args) noexcept { - return static_cast<ReturnType>((*static_cast<Fun*>( - static_cast<void*>(&p.tiny)))(static_cast<Args&&>(args)...)); + static ReturnType callSmall(CallArg<Args>... args, Data& p) noexcept { + auto& fn = *static_cast<Fun*>(static_cast<void*>(&p.tiny)); +#if __cpp_if_constexpr >= 201606L + if constexpr (std::is_void<ReturnType>::value) { + fn(static_cast<Args&&>(args)...); + } else { + return fn(static_cast<Args&&>(args)...); + } +#else + return static_cast<ReturnType>(fn(static_cast<Args&&>(args)...)); +#endif } template <typename Fun> - static ReturnType callBig(Data& p, Args&&... args) noexcept { - return static_cast<ReturnType>( - (*static_cast<Fun*>(p.big))(static_cast<Args&&>(args)...)); + static ReturnType callBig(CallArg<Args>... args, Data& p) noexcept { + auto& fn = *static_cast<Fun*>(p.big); +#if __cpp_if_constexpr >= 201606L + if constexpr (std::is_void<ReturnType>::value) { + fn(static_cast<Args&&>(args)...); + } else { + return fn(static_cast<Args&&>(args)...); + } +#else + return static_cast<ReturnType>(fn(static_cast<Args&&>(args)...)); +#endif } - static ReturnType uninitCall(Data&, Args&&...) noexcept { + static ReturnType uninitCall(CallArg<Args>..., Data&) noexcept { terminate_with<std::bad_function_call>(); } ReturnType operator()(Args... args) noexcept { auto& fn = *static_cast<Function<NonConstSignature>*>(this); - return fn.call_(fn.data_, static_cast<Args&&>(args)...); + return fn.call_(static_cast<Args&&>(args)..., fn.data_); } - class SharedProxy { - std::shared_ptr<Function<NonConstSignature>> sp_; - - public: - explicit SharedProxy(Function<NonConstSignature>&& func) - : sp_(std::make_shared<Function<NonConstSignature>>(std::move(func))) {} - ReturnType operator()(Args&&... args) const { - return (*sp_)(static_cast<Args&&>(args)...); - } - }; + using SharedProxy = + FunctionTraitsSharedProxy<NonConstSignature, ReturnType, Args...>; }; template <typename ReturnType, typename... Args> struct FunctionTraits<ReturnType(Args...) const noexcept> { - using Call = ReturnType (*)(Data&, Args&&...) noexcept; + using Call = ReturnType (*)(CallArg<Args>..., Data&) noexcept; using IsConst = std::true_type; using ConstSignature = ReturnType(Args...) const noexcept; using NonConstSignature = ReturnType(Args...) noexcept; using OtherSignature = NonConstSignature; template <typename F> - using ResultOf = SafeResultOf< - CallableResult<const _t<std::decay<F>>&, Args...>, - ReturnType>; + using ResultOf = + SafeResultOf<CallableResult<const std::decay_t<F>&, Args...>, ReturnType>; template <typename Fun> - static ReturnType callSmall(Data& p, Args&&... args) noexcept { - return static_cast<ReturnType>((*static_cast<const Fun*>( - static_cast<void*>(&p.tiny)))(static_cast<Args&&>(args)...)); + static ReturnType callSmall(CallArg<Args>... args, Data& p) noexcept { + auto& fn = *static_cast<const Fun*>(static_cast<void*>(&p.tiny)); +#if __cpp_if_constexpr >= 201606L + if constexpr (std::is_void<ReturnType>::value) { + fn(static_cast<Args&&>(args)...); + } else { + return fn(static_cast<Args&&>(args)...); + } +#else + return static_cast<ReturnType>(fn(static_cast<Args&&>(args)...)); +#endif } template <typename Fun> - static ReturnType callBig(Data& p, Args&&... args) noexcept { - return static_cast<ReturnType>( - (*static_cast<const Fun*>(p.big))(static_cast<Args&&>(args)...)); + static ReturnType callBig(CallArg<Args>... args, Data& p) noexcept { + auto& fn = *static_cast<const Fun*>(p.big); +#if __cpp_if_constexpr >= 201606L + if constexpr (std::is_void<ReturnType>::value) { + fn(static_cast<Args&&>(args)...); + } else { + return fn(static_cast<Args&&>(args)...); + } +#else + return static_cast<ReturnType>(fn(static_cast<Args&&>(args)...)); +#endif } - static ReturnType uninitCall(Data&, Args&&...) noexcept { - throw std::bad_function_call(); + static ReturnType uninitCall(CallArg<Args>..., Data&) noexcept { + throw_exception<std::bad_function_call>(); } ReturnType operator()(Args... args) const noexcept { auto& fn = *static_cast<const Function<ConstSignature>*>(this); - return fn.call_(fn.data_, static_cast<Args&&>(args)...); + return fn.call_(static_cast<Args&&>(args)..., fn.data_); } - class SharedProxy { - std::shared_ptr<Function<ConstSignature>> sp_; - - public: - explicit SharedProxy(Function<ConstSignature>&& func) - : sp_(std::make_shared<Function<ConstSignature>>(std::move(func))) {} - ReturnType operator()(Args&&... args) const { - return (*sp_)(static_cast<Args&&>(args)...); - } - }; + using SharedProxy = + FunctionTraitsSharedProxy<ConstSignature, ReturnType, Args...>; }; #endif template <typename Fun> -bool execSmall(Op o, Data* src, Data* dst) { +std::size_t execSmall(Op o, Data* src, Data* dst) { switch (o) { case Op::MOVE: ::new (static_cast<void*>(&dst->tiny)) @@ -492,11 +594,11 @@ bool execSmall(Op o, Data* src, Data* dst) { case Op::HEAP: break; } - return false; + return 0U; } template <typename Fun> -bool execBig(Op o, Data* src, Data* dst) { +std::size_t execBig(Op o, Data* src, Data* dst) { switch (o) { case Op::MOVE: dst->big = src->big; @@ -508,7 +610,7 @@ bool execBig(Op o, Data* src, Data* dst) { case Op::HEAP: break; } - return true; + return sizeof(Fun); } } // namespace function @@ -527,7 +629,7 @@ class Function final : private detail::function::FunctionTraits<FunctionType> { using Traits = detail::function::FunctionTraits<FunctionType>; using Call = typename Traits::Call; - using Exec = bool (*)(Op, Data*, Data*); + using Exec = std::size_t (*)(Op, Data*, Data*); template <typename Fun> using IsSmall = detail::function::IsSmall<Fun>; @@ -540,8 +642,11 @@ class Function final : private detail::function::FunctionTraits<FunctionType> { Call call_{&Traits::uninitCall}; Exec exec_{nullptr}; - bool exec(Op o, Data* src, Data* dst) const { - return exec_ && exec_(o, src, dst); + std::size_t exec(Op o, Data* src, Data* dst) const { + if (!exec_) { + return 0U; + } + return exec_(o, src, dst); } friend Traits; @@ -552,7 +657,7 @@ class Function final : private detail::function::FunctionTraits<FunctionType> { template <typename Fun> Function(Fun&& fun, SmallTag) noexcept { using FunT = typename std::decay<Fun>::type; - if (!detail::function::isNullPtrFn(fun)) { + if (!detail::function::isEmptyFunction(fun)) { ::new (static_cast<void*>(&data_.tiny)) FunT(static_cast<Fun&&>(fun)); call_ = &Traits::template callSmall<FunT>; exec_ = &detail::function::execSmall<FunT>; @@ -562,9 +667,11 @@ class Function final : private detail::function::FunctionTraits<FunctionType> { template <typename Fun> Function(Fun&& fun, HeapTag) { using FunT = typename std::decay<Fun>::type; - data_.big = new FunT(static_cast<Fun&&>(fun)); - call_ = &Traits::template callBig<FunT>; - exec_ = &detail::function::execBig<FunT>; + if (!detail::function::isEmptyFunction(fun)) { + data_.big = new FunT(static_cast<Fun&&>(fun)); + call_ = &Traits::template callBig<FunT>; + exec_ = &detail::function::execBig<FunT>; + } } template <typename Signature> @@ -783,12 +890,11 @@ class Function final : private detail::function::FunctionTraits<FunctionType> { } /** - * Returns `true` if this `Function` stores the callable on the - * heap. If `false` is returned, there has been no additional memory - * allocation and the callable is stored inside the `Function` - * object itself. + * Returns the size of the allocation made to store the callable on the + * heap. If `0` is returned, there has been no additional memory + * allocation because the callable is stored within the `Function` object. */ - bool hasAllocatedMemory() const noexcept { + std::size_t heapAllocatedMemory() const noexcept { return exec(Op::HEAP, nullptr, nullptr); } @@ -894,15 +1000,18 @@ class FunctionRef; template <typename ReturnType, typename... Args> class FunctionRef<ReturnType(Args...)> final { - using Call = ReturnType (*)(void*, Args&&...); + template <typename Arg> + using CallArg = detail::function::CallArg<Arg>; - static ReturnType uninitCall(void*, Args&&...) { - throw std::bad_function_call(); + using Call = ReturnType (*)(CallArg<Args>..., void*); + + static ReturnType uninitCall(CallArg<Args>..., void*) { + throw_exception<std::bad_function_call>(); } template <typename Fun> - static ReturnType call(void* object, Args&&... args) { - using Pointer = _t<std::add_pointer<Fun>>; + static ReturnType call(CallArg<Args>... args, void* object) { + using Pointer = std::add_pointer_t<Fun>; return static_cast<ReturnType>(invoke( static_cast<Fun&&>(*static_cast<Pointer>(object)), static_cast<Args&&>(args)...)); @@ -917,7 +1026,14 @@ class FunctionRef<ReturnType(Args...)> final { * * Invoking it will throw std::bad_function_call. */ - FunctionRef() = default; + constexpr FunctionRef() = default; + + /** + * Like default constructor. Constructs an empty FunctionRef. + * + * Invoking it will throw std::bad_function_call. + */ + constexpr explicit FunctionRef(std::nullptr_t) noexcept {} /** * Construct a FunctionRef from a reference to a callable object. @@ -926,7 +1042,7 @@ class FunctionRef<ReturnType(Args...)> final { typename Fun, typename std::enable_if< Conjunction< - Negation<std::is_same<FunctionRef, _t<std::decay<Fun>>>>, + Negation<std::is_same<FunctionRef, std::decay_t<Fun>>>, is_invocable_r<ReturnType, Fun&&, Args&&...>>::value, int>::type = 0> constexpr /* implicit */ FunctionRef(Fun&& fun) noexcept @@ -936,15 +1052,37 @@ class FunctionRef<ReturnType(Args...)> final { // is a const type) inside `FunctionRef::call` : object_( const_cast<void*>(static_cast<void const*>(std::addressof(fun)))), - call_(&FunctionRef::call<Fun>) {} + call_(&FunctionRef::template call<Fun>) {} ReturnType operator()(Args... args) const { - return call_(object_, static_cast<Args&&>(args)...); + return call_(static_cast<Args&&>(args)..., object_); } - constexpr explicit operator bool() const { + constexpr explicit operator bool() const noexcept { return object_; } + + constexpr friend bool operator==( + FunctionRef<ReturnType(Args...)> ref, + std::nullptr_t) noexcept { + return ref.object_ == nullptr; + } + constexpr friend bool operator!=( + FunctionRef<ReturnType(Args...)> ref, + std::nullptr_t) noexcept { + return ref.object_ != nullptr; + } + + constexpr friend bool operator==( + std::nullptr_t, + FunctionRef<ReturnType(Args...)> ref) noexcept { + return ref.object_ == nullptr; + } + constexpr friend bool operator!=( + std::nullptr_t, + FunctionRef<ReturnType(Args...)> ref) noexcept { + return ref.object_ != nullptr; + } }; } // namespace folly diff --git a/ios/Pods/Folly/folly/GLog.h b/ios/Pods/Folly/folly/GLog.h index 3724aaa59..c8eae8b0b 100644 --- a/ios/Pods/Folly/folly/GLog.h +++ b/ios/Pods/Folly/folly/GLog.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/GroupVarint.h b/ios/Pods/Folly/folly/GroupVarint.h index b9ca1bb89..2b3775c62 100644 --- a/ios/Pods/Folly/folly/GroupVarint.h +++ b/ios/Pods/Folly/folly/GroupVarint.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -21,20 +21,24 @@ #include <glog/logging.h> -#if !defined(__GNUC__) && !defined(_MSC_VER) -#error GroupVarint.h requires GCC or MSVC -#endif - #include <folly/Portability.h> - -#if FOLLY_X64 || defined(__i386__) || FOLLY_PPC64 || FOLLY_AARCH64 -#define HAVE_GROUP_VARINT 1 - #include <folly/Range.h> #include <folly/detail/GroupVarintDetail.h> #include <folly/lang/Bits.h> #include <folly/portability/Builtins.h> +#if !defined(__GNUC__) && !defined(_MSC_VER) +#error GroupVarint.h requires GCC or MSVC +#endif + +#if FOLLY_X64 || defined(__i386__) || FOLLY_PPC64 || FOLLY_AARCH64 +#define FOLLY_HAVE_GROUP_VARINT 1 +#else +#define FOLLY_HAVE_GROUP_VARINT 0 +#endif + +#if FOLLY_HAVE_GROUP_VARINT + #if FOLLY_SSE >= 3 #include <nmmintrin.h> namespace folly { @@ -661,4 +665,4 @@ typedef GroupVarintDecoder<uint64_t> GroupVarint64Decoder; } // namespace folly -#endif /* FOLLY_X64 || defined(__i386__) || FOLLY_PPC64 */ +#endif // FOLLY_HAVE_GROUP_VARINT diff --git a/ios/Pods/Folly/folly/Hash.h b/ios/Pods/Folly/folly/Hash.h index b003c72cc..fba2bbc7f 100644 --- a/ios/Pods/Folly/folly/Hash.h +++ b/ios/Pods/Folly/folly/Hash.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/IPAddress.h b/ios/Pods/Folly/folly/IPAddress.h index 943c5cec2..a91e1b30f 100644 --- a/ios/Pods/Folly/folly/IPAddress.h +++ b/ios/Pods/Folly/folly/IPAddress.h @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -20,13 +20,16 @@ #include <iosfwd> #include <memory> #include <string> +#include <type_traits> #include <utility> // std::pair +#include <folly/ConstexprMath.h> #include <folly/IPAddressException.h> #include <folly/IPAddressV4.h> #include <folly/IPAddressV6.h> #include <folly/Range.h> #include <folly/detail/IPAddress.h> +#include <folly/lang/Exception.h> namespace folly { @@ -68,7 +71,68 @@ class IPAddress { private: template <typename F> auto pick(F f) const { - return isV4() ? f(asV4()) : f(asV6()); + return isV4() ? f(asV4()) : isV6() ? f(asV6()) : f(asNone()); + } + + class IPAddressNone { + public: + bool isZero() const { + return true; + } + size_t bitCount() const { + return 0; + } + std::string toJson() const { + return "{family:'AF_UNSPEC', addr:'', hash:0}"; + } + std::size_t hash() const { + return std::hash<uint64_t>{}(0); + } + bool isLoopback() const { + throw_exception<InvalidAddressFamilyException>("empty address"); + } + bool isLinkLocal() const { + throw_exception<InvalidAddressFamilyException>("empty address"); + } + bool isLinkLocalBroadcast() const { + throw_exception<InvalidAddressFamilyException>("empty address"); + } + bool isNonroutable() const { + throw_exception<InvalidAddressFamilyException>("empty address"); + } + bool isPrivate() const { + throw_exception<InvalidAddressFamilyException>("empty address"); + } + bool isMulticast() const { + throw_exception<InvalidAddressFamilyException>("empty address"); + } + IPAddress mask(uint8_t numBits) const { + (void)numBits; + return IPAddress(); + } + std::string str() const { + return ""; + } + std::string toFullyQualified() const { + return ""; + } + void toFullyQualifiedAppend(std::string& out) const { + (void)out; + return; + } + uint8_t version() const { + return 0; + } + const unsigned char* bytes() const { + return nullptr; + } + }; + + IPAddressNone const& asNone() const { + if (!empty()) { + throw_exception<InvalidAddressFamilyException>("not empty"); + } + return addr_.ipNoneAddr; } public: @@ -170,7 +234,7 @@ class IPAddress { * * @throws IPAddressFormatException */ - explicit IPAddress(StringPiece ip); + explicit IPAddress(StringPiece str); /** * Create an IPAddress from a sockaddr. @@ -187,10 +251,10 @@ class IPAddress { /* implicit */ IPAddress(const in6_addr& addr) noexcept; // Assign from V4 address - IPAddress& operator=(const IPAddressV4& ipV4Addr) noexcept; + IPAddress& operator=(const IPAddressV4& ipv4_addr) noexcept; // Assign from V6 address - IPAddress& operator=(const IPAddressV6& ipV6Addr) noexcept; + IPAddress& operator=(const IPAddressV6& ipv6_addr) noexcept; /** * Converts an IPAddress to an IPAddressV4 instance. @@ -266,7 +330,7 @@ class IPAddress { * @throws IPAddressFormatException if no /mask * @return true if address is part of specified subnet with cidr */ - bool inSubnet(StringPiece ipSlashCidr) const; + bool inSubnet(StringPiece cidrNetwork) const; /** * Check if an IPAddress belongs to a subnet. @@ -425,7 +489,7 @@ class IPAddress { return pick([&](auto& _) { return _.toFullyQualifiedAppend(out); }); } - // Address version (4 or 6) + // Address version (0 if empty, or 4 or 6 if nonempty) uint8_t version() const { return pick([&](auto& _) { return _.version(); }); } @@ -442,12 +506,10 @@ class IPAddress { [[noreturn]] void asV6Throw() const; typedef union IPAddressV46 { + IPAddressNone ipNoneAddr; IPAddressV4 ipV4Addr; IPAddressV6 ipV6Addr; - // default constructor - IPAddressV46() noexcept { - std::memset(this, 0, sizeof(IPAddressV46)); - } + IPAddressV46() noexcept : ipNoneAddr() {} explicit IPAddressV46(const IPAddressV4& addr) noexcept : ipV4Addr(addr) {} explicit IPAddressV46(const IPAddressV6& addr) noexcept : ipV6Addr(addr) {} } IPAddressV46; diff --git a/ios/Pods/Folly/folly/IPAddressException.h b/ios/Pods/Folly/folly/IPAddressException.h index feb0284ce..b98b2fb81 100644 --- a/ios/Pods/Folly/folly/IPAddressException.h +++ b/ios/Pods/Folly/folly/IPAddressException.h @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #pragma once #include <exception> diff --git a/ios/Pods/Folly/folly/IPAddressV4.h b/ios/Pods/Folly/folly/IPAddressV4.h index 061f53fc8..35dc61f59 100644 --- a/ios/Pods/Folly/folly/IPAddressV4.h +++ b/ios/Pods/Folly/folly/IPAddressV4.h @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -122,7 +122,7 @@ class IPAddressV4 { // Create an IPAddressV4 from a string // @throws IPAddressFormatException - explicit IPAddressV4(StringPiece ip); + explicit IPAddressV4(StringPiece addr); // ByteArray4 constructor explicit IPAddressV4(const ByteArray4& src) noexcept; @@ -251,7 +251,7 @@ class IPAddressV4 { * @throws abort if numBits == 0 or numBits > bitCount() * @return mask associated with numBits */ - static const ByteArray4 fetchMask(size_t numBits); + static ByteArray4 fetchMask(size_t numBits); // Given 2 IPAddressV4, mask pairs extract the longest common IPAddress, // mask pair diff --git a/ios/Pods/Folly/folly/IPAddressV6.h b/ios/Pods/Folly/folly/IPAddressV6.h index a06743080..31d17d13c 100644 --- a/ios/Pods/Folly/folly/IPAddressV6.h +++ b/ios/Pods/Folly/folly/IPAddressV6.h @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -140,7 +140,7 @@ class IPAddressV6 { // Create an IPAddressV6 from a string // @throws IPAddressFormatException // - explicit IPAddressV6(StringPiece ip); + explicit IPAddressV6(StringPiece addr); // ByteArray16 constructor explicit IPAddressV6(const ByteArray16& src) noexcept; @@ -338,7 +338,7 @@ class IPAddressV6 { * @throws abort if numBits == 0 or numBits > bitCount() * @return mask associated with numBits */ - static const ByteArray16 fetchMask(size_t numBits); + static ByteArray16 fetchMask(size_t numBits); // Given 2 IPAddressV6,mask pairs extract the longest common IPAddress, // mask pair static CIDRNetworkV6 longestCommonPrefix( diff --git a/ios/Pods/Folly/folly/Indestructible.h b/ios/Pods/Folly/folly/Indestructible.h index e266c0536..6e6c06478 100644 --- a/ios/Pods/Folly/folly/Indestructible.h +++ b/ios/Pods/Folly/folly/Indestructible.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -80,21 +80,21 @@ class Indestructible final { */ template < typename U = T, - _t<std::enable_if<std::is_constructible<T, U&&>::value>>* = nullptr, - _t<std::enable_if< - !std::is_same<Indestructible<T>, remove_cvref_t<U>>::value>>* = + std::enable_if_t<std::is_constructible<T, U&&>::value>* = nullptr, + std::enable_if_t< + !std::is_same<Indestructible<T>, remove_cvref_t<U>>::value>* = nullptr, - _t<std::enable_if<!std::is_convertible<U&&, T>::value>>* = nullptr> + std::enable_if_t<!std::is_convertible<U&&, T>::value>* = nullptr> explicit constexpr Indestructible(U&& u) noexcept( noexcept(T(std::declval<U>()))) : storage_(std::forward<U>(u)) {} template < typename U = T, - _t<std::enable_if<std::is_constructible<T, U&&>::value>>* = nullptr, - _t<std::enable_if< - !std::is_same<Indestructible<T>, remove_cvref_t<U>>::value>>* = + std::enable_if_t<std::is_constructible<T, U&&>::value>* = nullptr, + std::enable_if_t< + !std::is_same<Indestructible<T>, remove_cvref_t<U>>::value>* = nullptr, - _t<std::enable_if<std::is_convertible<U&&, T>::value>>* = nullptr> + std::enable_if_t<std::is_convertible<U&&, T>::value>* = nullptr> /* implicit */ constexpr Indestructible(U&& u) noexcept( noexcept(T(std::declval<U>()))) : storage_(std::forward<U>(u)) {} diff --git a/ios/Pods/Folly/folly/IndexedMemPool.h b/ios/Pods/Folly/folly/IndexedMemPool.h index 2cd512421..11b30f653 100644 --- a/ios/Pods/Folly/folly/IndexedMemPool.h +++ b/ios/Pods/Folly/folly/IndexedMemPool.h @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -22,7 +22,6 @@ #include <type_traits> -#include <boost/noncopyable.hpp> #include <folly/Portability.h> #include <folly/concurrency/CacheLocality.h> #include <folly/portability/SysMman.h> @@ -156,18 +155,25 @@ template < uint32_t LocalListLimit_ = 200, template <typename> class Atom = std::atomic, typename Traits = IndexedMemPoolTraits<T>> -struct IndexedMemPool : boost::noncopyable { +struct IndexedMemPool { typedef T value_type; typedef std::unique_ptr<T, detail::IndexedMemPoolRecycler<IndexedMemPool>> UniquePtr; + IndexedMemPool(const IndexedMemPool&) = delete; + IndexedMemPool& operator=(const IndexedMemPool&) = delete; + static_assert(LocalListLimit_ <= 255, "LocalListLimit must fit in 8 bits"); enum { NumLocalLists = NumLocalLists_, LocalListLimit = LocalListLimit_, }; + static_assert( + std::is_nothrow_default_constructible<Atom<uint32_t>>::value, + "Atom must be nothrow default constructible"); + // these are public because clients may need to reason about the number // of bits required to hold indices from a pool, given its capacity @@ -210,8 +216,11 @@ struct IndexedMemPool : boost::noncopyable { /// Destroys all of the contained elements ~IndexedMemPool() { + using A = Atom<uint32_t>; for (uint32_t i = maxAllocatedIndex(); i > 0; --i) { Traits::cleanup(&slots_[i].elem); + slots_[i].localNext.~A(); + slots_[i].globalNext.~A(); } munmap(slots_, mmapLength_); } @@ -424,9 +433,13 @@ struct IndexedMemPool : boost::noncopyable { void localPush(AtomicStruct<TaggedPtr, Atom>& head, uint32_t idx) { Slot& s = slot(idx); TaggedPtr h = head.load(std::memory_order_acquire); + bool recycled = false; while (true) { s.localNext.store(h.idx, std::memory_order_release); - Traits::onRecycle(&slot(idx).elem); + if (!recycled) { + Traits::onRecycle(&slot(idx).elem); + recycled = true; + } if (h.size() == LocalListLimit) { // push will overflow local list, steal it instead @@ -484,7 +497,14 @@ struct IndexedMemPool : boost::noncopyable { // allocation failed return 0; } - Traits::initialize(&slot(idx).elem); + Slot& s = slot(idx); + // Atom is enforced above to be nothrow-default-constructible + // As an optimization, use default-initialization (no parens) rather + // than direct-initialization (with parens): these locations are + // stored-to before they are loaded-from + new (&s.localNext) Atom<uint32_t>; + new (&s.globalNext) Atom<uint32_t>; + Traits::initialize(&s.elem); return idx; } diff --git a/ios/Pods/Folly/folly/IntrusiveList.h b/ios/Pods/Folly/folly/IntrusiveList.h index 10d277972..9e392a4d5 100644 --- a/ios/Pods/Folly/folly/IntrusiveList.h +++ b/ios/Pods/Folly/folly/IntrusiveList.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/Lazy.h b/ios/Pods/Folly/folly/Lazy.h index 941878c77..11f984e46 100644 --- a/ios/Pods/Folly/folly/Lazy.h +++ b/ios/Pods/Folly/folly/Lazy.h @@ -1,11 +1,11 @@ /* - * Copyright 2013-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/Likely.h b/ios/Pods/Folly/folly/Likely.h index 2dc92a4b9..e3597fff6 100644 --- a/ios/Pods/Folly/folly/Likely.h +++ b/ios/Pods/Folly/folly/Likely.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/LockTraits.h b/ios/Pods/Folly/folly/LockTraits.h index ae1d75f0c..1098ddcff 100644 --- a/ios/Pods/Folly/folly/LockTraits.h +++ b/ios/Pods/Folly/folly/LockTraits.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -41,10 +41,10 @@ namespace folly { namespace detail { namespace member { -FOLLY_CREATE_MEMBER_INVOKE_TRAITS(lock, lock); -FOLLY_CREATE_MEMBER_INVOKE_TRAITS(try_lock_for, try_lock_for); -FOLLY_CREATE_MEMBER_INVOKE_TRAITS(lock_shared, lock_shared); -FOLLY_CREATE_MEMBER_INVOKE_TRAITS(lock_upgrade, lock_upgrade); +FOLLY_CREATE_MEMBER_INVOKER(lock_invoker, lock); +FOLLY_CREATE_MEMBER_INVOKER(try_lock_for_invoker, try_lock_for); +FOLLY_CREATE_MEMBER_INVOKER(lock_shared_invoker, lock_shared); +FOLLY_CREATE_MEMBER_INVOKER(lock_upgrade_invoker, lock_upgrade); } // namespace member /** @@ -86,7 +86,7 @@ class LockInterfaceDispatcher { private: // assert that the mutex type has basic lock and unlock functions static_assert( - member::lock::is_invocable<Mutex>::value, + folly::is_invocable<member::lock_invoker, Mutex>::value, "The mutex type must support lock and unlock functions"); using duration = std::chrono::milliseconds; @@ -94,11 +94,11 @@ class LockInterfaceDispatcher { public: static constexpr bool has_lock_unique = true; static constexpr bool has_lock_timed = - member::try_lock_for::is_invocable<Mutex, duration>::value; + folly::is_invocable<member::try_lock_for_invoker, Mutex, duration>::value; static constexpr bool has_lock_shared = - member::lock_shared::is_invocable<Mutex>::value; + folly::is_invocable<member::lock_shared_invoker, Mutex>::value; static constexpr bool has_lock_upgrade = - member::lock_upgrade::is_invocable<Mutex>::value; + folly::is_invocable<member::lock_upgrade_invoker, Mutex>::value; }; /** @@ -370,6 +370,8 @@ struct LockTraitsImpl<Mutex, MutexLevel::UPGRADE, true> */ template <template <typename...> class LockTraits> struct UnlockPolicyExclusive { + constexpr static bool allows_concurrent_access = false; + template <typename Mutex> static void unlock(Mutex& mutex) { LockTraits<Mutex>::unlock(mutex); @@ -377,6 +379,8 @@ struct UnlockPolicyExclusive { }; template <template <typename...> class LockTraits> struct UnlockPolicyShared { + constexpr static bool allows_concurrent_access = true; + template <typename Mutex> static void unlock(Mutex& mutex) { LockTraits<Mutex>::unlock_shared(mutex); @@ -384,6 +388,8 @@ struct UnlockPolicyShared { }; template <template <typename...> class LockTraits> struct UnlockPolicyUpgrade { + constexpr static bool allows_concurrent_access = true; + template <typename Mutex> static void unlock(Mutex& mutex) { LockTraits<Mutex>::unlock_upgrade(mutex); diff --git a/ios/Pods/Folly/folly/LockTraitsBoost.h b/ios/Pods/Folly/folly/LockTraitsBoost.h deleted file mode 100644 index 019950882..000000000 --- a/ios/Pods/Folly/folly/LockTraitsBoost.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2016-present Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * This file contains LockTraits specializations for boost mutex types. - * - * These need to be specialized simply due to the fact that the timed - * methods take boost::chrono arguments instead of std::chrono. - */ -#pragma once - -#include <boost/thread.hpp> -#include <folly/LockTraits.h> - -#if FOLLY_LOCK_TRAITS_HAVE_TIMED_MUTEXES - -namespace folly { - -namespace detail { -/// Convert a std::chrono::duration argument to boost::chrono::duration -template <class Rep, std::intmax_t Num, std::intmax_t Denom> -boost::chrono::duration<Rep, boost::ratio<Num, Denom>> toBoostDuration( - const std::chrono::duration<Rep, std::ratio<Num, Denom>>& d) { - return boost::chrono::duration<Rep, boost::ratio<Num, Denom>>(d.count()); -} -} // namespace detail - -/** - * LockTraits specialization for boost::shared_mutex - */ -template <> -struct LockTraits<boost::shared_mutex> - : public LockTraitsBase<boost::shared_mutex> { - static constexpr bool is_shared = true; - static constexpr bool is_timed = true; - - template <class Rep, class Period> - static bool try_lock_for( - boost::shared_mutex& mutex, - const std::chrono::duration<Rep, Period>& timeout) { - return mutex.try_lock_for(detail::toBoostDuration(timeout)); - } - - template <class Rep, class Period> - static bool try_lock_shared_for( - boost::shared_mutex& mutex, - const std::chrono::duration<Rep, Period>& timeout) { - return mutex.try_lock_shared_for(detail::toBoostDuration(timeout)); - } -}; - -/** - * LockTraits specialization for boost::timed_mutex - */ -template <> -struct LockTraits<boost::timed_mutex> - : public LockTraitsBase<boost::timed_mutex> { - static constexpr bool is_shared = false; - static constexpr bool is_timed = true; - - template <class Rep, class Period> - static bool try_lock_for( - boost::timed_mutex& mutex, - const std::chrono::duration<Rep, Period>& timeout) { - return mutex.try_lock_for(detail::toBoostDuration(timeout)); - } -}; - -/** - * LockTraits specialization for boost::recursive_timed_mutex - */ -template <> -struct LockTraits<boost::recursive_timed_mutex> - : public LockTraitsBase<boost::recursive_timed_mutex> { - static constexpr bool is_shared = false; - static constexpr bool is_timed = true; - - template <class Rep, class Period> - static bool try_lock_for( - boost::recursive_timed_mutex& mutex, - const std::chrono::duration<Rep, Period>& timeout) { - return mutex.try_lock_for(detail::toBoostDuration(timeout)); - } -}; -} // namespace folly - -#endif // FOLLY_LOCK_TRAITS_HAVE_TIMED_MUTEXES diff --git a/ios/Pods/Folly/folly/MPMCPipeline.h b/ios/Pods/Folly/folly/MPMCPipeline.h index dd37e056d..a672b2899 100644 --- a/ios/Pods/Folly/folly/MPMCPipeline.h +++ b/ios/Pods/Folly/folly/MPMCPipeline.h @@ -1,11 +1,11 @@ /* - * Copyright 2013-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/MPMCQueue.h b/ios/Pods/Folly/folly/MPMCQueue.h index 5efb28bdf..9571b259b 100644 --- a/ios/Pods/Folly/folly/MPMCQueue.h +++ b/ios/Pods/Folly/folly/MPMCQueue.h @@ -1,11 +1,11 @@ /* - * Copyright 2013-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -23,8 +23,6 @@ #include <limits> #include <type_traits> -#include <boost/noncopyable.hpp> - #include <folly/Traits.h> #include <folly/concurrency/CacheLocality.h> #include <folly/detail/TurnSequencer.h> @@ -117,6 +115,9 @@ class MPMCQueue : public detail::MPMCQueueBase<MPMCQueue<T, Atom, Dynamic>> { MPMCQueue() noexcept {} }; +/// *** The dynamic version of MPMCQueue is deprecated. *** +/// Use UnboundedQueue instead. + /// The dynamic version of MPMCQueue allows dynamic expansion of queue /// capacity, such that a queue may start with a smaller capacity than /// specified and expand only if needed. Users may optionally specify @@ -210,8 +211,10 @@ class MPMCQueue<T, Atom, true> MPMCQueue(MPMCQueue<T, Atom, true>&& rhs) noexcept { this->capacity_ = rhs.capacity_; - this->slots_ = rhs.slots_; - this->stride_ = rhs.stride_; + new (&this->dslots_) + Atom<Slot*>(rhs.dslots_.load(std::memory_order_relaxed)); + new (&this->dstride_) + Atom<int>(rhs.dstride_.load(std::memory_order_relaxed)); this->dstate_.store( rhs.dstate_.load(std::memory_order_relaxed), std::memory_order_relaxed); this->dcapacity_.store( @@ -233,8 +236,8 @@ class MPMCQueue<T, Atom, true> closed_ = rhs.closed_; rhs.capacity_ = 0; - rhs.slots_ = nullptr; - rhs.stride_ = 0; + rhs.dslots_.store(nullptr, std::memory_order_relaxed); + rhs.dstride_.store(0, std::memory_order_relaxed); rhs.dstate_.store(0, std::memory_order_relaxed); rhs.dcapacity_.store(0, std::memory_order_relaxed); rhs.pushTicket_.store(0, std::memory_order_relaxed); @@ -260,6 +263,13 @@ class MPMCQueue<T, Atom, true> } delete[] closed_; } + using AtomInt = Atom<int>; + this->dstride_.~AtomInt(); + using AtomSlot = Atom<Slot*>; + // Sort of a hack to get ~MPMCQueueBase to free dslots_ + auto slots = this->dslots_.load(); + this->dslots_.~AtomSlot(); + this->slots_ = slots; } size_t allocatedCapacity() const noexcept { @@ -337,8 +347,9 @@ class MPMCQueue<T, Atom, true> ClosedArray* closed_; void initQueue(const size_t cap, const size_t mult) { - this->stride_ = this->computeStride(cap); - this->slots_ = new Slot[cap + 2 * this->kSlotPadding]; + new (&this->dstride_) Atom<int>(this->computeStride(cap)); + Slot* slots = new Slot[cap + 2 * this->kSlotPadding]; + new (&this->dslots_) Atom<Slot*>(slots); this->dstate_.store(0); this->dcapacity_.store(cap); dmult_ = mult; @@ -630,7 +641,7 @@ template < typename T, template <typename> class Atom, bool Dynamic> -class MPMCQueueBase<Derived<T, Atom, Dynamic>> : boost::noncopyable { +class MPMCQueueBase<Derived<T, Atom, Dynamic>> { // Note: Using CRTP static casts in several functions of this base // template instead of making called functions virtual or duplicating // the code of calling functions in the derived partially specialized @@ -648,6 +659,8 @@ class MPMCQueueBase<Derived<T, Atom, Dynamic>> : boost::noncopyable { explicit MPMCQueueBase(size_t queueCapacity) : capacity_(queueCapacity), + dstate_(0), + dcapacity_(0), pushTicket_(0), popTicket_(0), pushSpinCutoff_(0), @@ -721,6 +734,9 @@ class MPMCQueueBase<Derived<T, Atom, Dynamic>> : boost::noncopyable { return *this; } + MPMCQueueBase(const MPMCQueueBase&) = delete; + MPMCQueueBase& operator=(const MPMCQueueBase&) = delete; + /// MPMCQueue can only be safely destroyed when there are no /// pending enqueuers or dequeuers (this is not checked). ~MPMCQueueBase() { @@ -1427,7 +1443,7 @@ struct SingleElementQueue { private: /// Storage for a T constructed with placement new - typename std::aligned_storage<sizeof(T), alignof(T)>::type contents_; + aligned_storage_for_t<T> contents_; /// Even turns are pushes, odd turns are pops TurnSequencer<Atom> sequencer_; @@ -1442,9 +1458,9 @@ struct SingleElementQueue { } catch (...) { // g++ doesn't seem to have std::is_nothrow_destructible yet } -#ifndef NDEBUG - memset(&contents_, 'Q', sizeof(T)); -#endif + if (kIsDebug) { + memset(&contents_, 'Q', sizeof(T)); + } } /// Tag classes for dispatching to enqueue/dequeue implementation. @@ -1472,7 +1488,10 @@ struct SingleElementQueue { T&& goner, ImplByRelocation) noexcept { sequencer_.waitForTurn(turn * 2, spinCutoff, updateSpinCutoff); - memcpy(&contents_, &goner, sizeof(T)); + memcpy( + static_cast<void*>(&contents_), + static_cast<void const*>(&goner), + sizeof(T)); sequencer_.completeTurn(turn * 2); new (&goner) T(); } @@ -1491,7 +1510,10 @@ struct SingleElementQueue { // unlikely, but if we don't complete our turn the queue will die } sequencer_.waitForTurn(turn * 2 + 1, spinCutoff, updateSpinCutoff); - memcpy(&elem, &contents_, sizeof(T)); + memcpy( + static_cast<void*>(&elem), + static_cast<void const*>(&contents_), + sizeof(T)); sequencer_.completeTurn(turn * 2 + 1); } diff --git a/ios/Pods/Folly/folly/MacAddress.h b/ios/Pods/Folly/folly/MacAddress.h index 225c348fe..993d1dde2 100644 --- a/ios/Pods/Folly/folly/MacAddress.h +++ b/ios/Pods/Folly/folly/MacAddress.h @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -18,6 +18,7 @@ #include <iosfwd> +#include <folly/Conv.h> #include <folly/Range.h> #include <folly/lang/Bits.h> diff --git a/ios/Pods/Folly/folly/MapUtil.h b/ios/Pods/Folly/folly/MapUtil.h index 8c18ede75..565a1424b 100644 --- a/ios/Pods/Folly/folly/MapUtil.h +++ b/ios/Pods/Folly/folly/MapUtil.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -76,7 +76,7 @@ const typename Map::mapped_type& get_or_throw( if (pos != map.end()) { return pos->second; } - throw E(folly::to<std::string>(exceptionStrPrefix, key)); + throw_exception<E>(folly::to<std::string>(exceptionStrPrefix, key)); } template < @@ -91,7 +91,7 @@ typename Map::mapped_type& get_or_throw( if (pos != map.end()) { return pos->second; } - throw E(folly::to<std::string>(exceptionStrPrefix, key)); + throw_exception<E>(folly::to<std::string>(exceptionStrPrefix, key)); } /** diff --git a/ios/Pods/Folly/folly/Math.h b/ios/Pods/Folly/folly/Math.h index 8f44364f8..3228adbc1 100644 --- a/ios/Pods/Folly/folly/Math.h +++ b/ios/Pods/Folly/folly/Math.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/Memory.h b/ios/Pods/Folly/folly/Memory.h index 0e19155a6..f71f8803a 100644 --- a/ios/Pods/Folly/folly/Memory.h +++ b/ios/Pods/Folly/folly/Memory.h @@ -1,11 +1,11 @@ /* - * Copyright 2013-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -38,11 +38,27 @@ namespace folly { -#if _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || \ - (defined(__ANDROID__) && (__ANDROID_API__ > 16)) || \ - (defined(__APPLE__) && \ - (__MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_6 || \ - __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_3_0)) +/// allocateBytes and deallocateBytes work like a checkedMalloc/free pair, +/// but take advantage of sized deletion when available +inline void* allocateBytes(size_t n) { + return ::operator new(n); +} + +inline void deallocateBytes(void* p, size_t n) { +#if __cpp_sized_deallocation + return ::operator delete(p, n); +#else + (void)n; + return ::operator delete(p); +#endif +} + +#if _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || \ + (defined(__ANDROID__) && (__ANDROID_API__ > 16)) || \ + (defined(__APPLE__) && \ + (__MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_6 || \ + __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_3_0)) || \ + defined(__FreeBSD__) || defined(__wasm32__) inline void* aligned_malloc(size_t size, size_t align) { // use posix_memalign, but mimic the behaviour of memalign @@ -387,8 +403,8 @@ class DefaultAlign { assert(!(align_ < sizeof(void*)) && bool("bad align: too small")); assert(!(align_ & (align_ - 1)) && bool("bad align: not power-of-two")); } - std::size_t operator()() const noexcept { - return align_; + std::size_t operator()(std::size_t align) const noexcept { + return align_ < align ? align : align_; } friend bool operator==(Self const& a, Self const& b) noexcept { @@ -407,8 +423,8 @@ class FixedAlign { using Self = FixedAlign<Align>; public: - constexpr std::size_t operator()() const noexcept { - return Align; + constexpr std::size_t operator()(std::size_t align) const noexcept { + return Align < align ? align : Align; } friend bool operator==(Self const&, Self const&) noexcept { @@ -426,7 +442,8 @@ class FixedAlign { * aligned_free. * * Accepts a policy parameter for providing the alignment, which must: - * * be invocable as std::size_t() noexcept, returning the alignment + * * be invocable as std::size_t(std::size_t) noexcept + * * taking the type alignment and returning the allocation alignment * * be noexcept-copy-constructible * * have noexcept operator== * * have noexcept operator!= @@ -448,7 +465,9 @@ class AlignedSysAllocator : private Align { public: static_assert(std::is_nothrow_copy_constructible<Align>::value, ""); - static_assert(is_nothrow_invocable_r<std::size_t, Align>::value, ""); + static_assert( + is_nothrow_invocable_r<std::size_t, Align, std::size_t>::value, + ""); using value_type = T; @@ -458,10 +477,10 @@ class AlignedSysAllocator : private Align { using Align::Align; - // TODO: remove this ctor, which is required only by gcc49 + // TODO: remove this ctor, which is is no longer required as of under gcc7 template < typename S = Align, - _t<std::enable_if<std::is_default_constructible<S>::value, int>> = 0> + std::enable_if_t<std::is_default_constructible<S>::value, int> = 0> constexpr AlignedSysAllocator() noexcept(noexcept(Align())) : Align() {} template <typename U> @@ -471,7 +490,8 @@ class AlignedSysAllocator : private Align { T* allocate(size_t count) { using lifted = typename detail::lift_void_to_char<T>::type; - auto const p = aligned_malloc(sizeof(lifted) * count, align()()); + auto const a = align()(alignof(lifted)); + auto const p = aligned_malloc(sizeof(lifted) * count, a); if (!p) { if (FOLLY_UNLIKELY(errno != ENOMEM)) { std::terminate(); @@ -651,12 +671,12 @@ struct AllocatorHasTrivialDeallocate<CxxAllocatorAdaptor<T, Alloc>> namespace detail { // note that construct and destroy here are methods, not short names for // the constructor and destructor -FOLLY_CREATE_MEMBER_INVOKE_TRAITS(AllocatorConstruct_, construct); -FOLLY_CREATE_MEMBER_INVOKE_TRAITS(AllocatorDestroy_, destroy); +FOLLY_CREATE_MEMBER_INVOKER(AllocatorConstruct_, construct); +FOLLY_CREATE_MEMBER_INVOKER(AllocatorDestroy_, destroy); template <typename Void, typename Alloc, typename... Args> struct AllocatorCustomizesConstruct_ - : AllocatorConstruct_::template is_invocable<Alloc, Args...> {}; + : folly::is_invocable<AllocatorConstruct_, Alloc, Args...> {}; template <typename Alloc, typename... Args> struct AllocatorCustomizesConstruct_< @@ -666,7 +686,7 @@ struct AllocatorCustomizesConstruct_< template <typename Void, typename Alloc, typename... Args> struct AllocatorCustomizesDestroy_ - : AllocatorDestroy_::template is_invocable<Alloc, Args...> {}; + : folly::is_invocable<AllocatorDestroy_, Alloc, Args...> {}; template <typename Alloc, typename... Args> struct AllocatorCustomizesDestroy_< diff --git a/ios/Pods/Folly/folly/MicroLock.h b/ios/Pods/Folly/folly/MicroLock.h index 6f7b0aa63..231496f65 100644 --- a/ios/Pods/Folly/folly/MicroLock.h +++ b/ios/Pods/Folly/folly/MicroLock.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -23,12 +23,6 @@ #include <folly/Portability.h> #include <folly/detail/Futex.h> -#if defined(__clang__) -#define NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) -#else -#define NO_SANITIZE_ADDRESS -#endif - namespace folly { /** @@ -98,12 +92,7 @@ namespace folly { class MicroLockCore { protected: -#if defined(__SANITIZE_ADDRESS__) && !defined(__clang__) && \ - (defined(__GNUC__) || defined(__GNUG__)) - uint32_t lock_; -#else uint8_t lock_; -#endif inline detail::Futex<>* word() const; // Well, halfword on 64-bit systems inline uint32_t baseShift(unsigned slot) const; inline uint32_t heldBit(unsigned slot) const; @@ -116,7 +105,7 @@ class MicroLockCore { unsigned maxYields); public: - inline void unlock(unsigned slot) NO_SANITIZE_ADDRESS; + FOLLY_DISABLE_ADDRESS_SANITIZER inline void unlock(unsigned slot); inline void unlock() { unlock(0); } @@ -169,11 +158,11 @@ void MicroLockCore::unlock(unsigned slot) { template <unsigned MaxSpins = 1000, unsigned MaxYields = 0> class MicroLockBase : public MicroLockCore { public: - inline void lock(unsigned slot) NO_SANITIZE_ADDRESS; + FOLLY_DISABLE_ADDRESS_SANITIZER inline void lock(unsigned slot); inline void lock() { lock(0); } - inline bool try_lock(unsigned slot) NO_SANITIZE_ADDRESS; + FOLLY_DISABLE_ADDRESS_SANITIZER inline bool try_lock(unsigned slot); inline bool try_lock() { return try_lock(0); } diff --git a/ios/Pods/Folly/folly/MicroSpinLock.h b/ios/Pods/Folly/folly/MicroSpinLock.h index 5654705d1..d42b0d4d9 100644 --- a/ios/Pods/Folly/folly/MicroSpinLock.h +++ b/ios/Pods/Folly/folly/MicroSpinLock.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/MoveWrapper.h b/ios/Pods/Folly/folly/MoveWrapper.h index b8d31b4ce..58c29478a 100644 --- a/ios/Pods/Folly/folly/MoveWrapper.h +++ b/ios/Pods/Folly/folly/MoveWrapper.h @@ -1,11 +1,11 @@ /* - * Copyright 2013-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/Optional.h b/ios/Pods/Folly/folly/Optional.h index 3e8a43505..6b5a1ee7f 100644 --- a/ios/Pods/Folly/folly/Optional.h +++ b/ios/Pods/Folly/folly/Optional.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #pragma once /* @@ -71,15 +72,20 @@ template <class Value> class Optional; namespace detail { -struct NoneHelper {}; - template <class Value> struct OptionalPromiseReturn; } // namespace detail -typedef int detail::NoneHelper::*None; +struct None { + enum class _secret { _token }; -const None none = {}; + /** + * No default constructor to support both `op = {}` and `op = none` + * as syntax for clearing an Optional, just like std::nullopt_t. + */ + explicit constexpr None(_secret) {} +}; +constexpr None none{None::_secret::_token}; class FOLLY_EXPORT OptionalEmptyException : public std::runtime_error { public: @@ -99,7 +105,7 @@ class Optional { !std::is_abstract<Value>::value, "Optional may not be used with abstract types"); - FOLLY_CPP14_CONSTEXPR Optional() noexcept {} + constexpr Optional() noexcept {} Optional(const Optional& src) noexcept( std::is_nothrow_copy_constructible<Value>::value) { @@ -116,23 +122,33 @@ class Optional { } } - FOLLY_CPP14_CONSTEXPR /* implicit */ Optional(const None&) noexcept {} + constexpr /* implicit */ Optional(const None&) noexcept {} - FOLLY_CPP14_CONSTEXPR /* implicit */ Optional(Value&& newValue) noexcept( + constexpr /* implicit */ Optional(Value&& newValue) noexcept( std::is_nothrow_move_constructible<Value>::value) { construct(std::move(newValue)); } - FOLLY_CPP14_CONSTEXPR /* implicit */ Optional(const Value& newValue) noexcept( + constexpr /* implicit */ Optional(const Value& newValue) noexcept( std::is_nothrow_copy_constructible<Value>::value) { construct(newValue); } template <typename... Args> - FOLLY_CPP14_CONSTEXPR explicit Optional(in_place_t, Args&&... args) noexcept( - std::is_nothrow_constructible<Value, Args...>::value) { - construct(std::forward<Args>(args)...); - } + constexpr explicit Optional(in_place_t, Args&&... args) noexcept( + std::is_nothrow_constructible<Value, Args...>::value) + : Optional{PrivateConstructor{}, std::forward<Args>(args)...} {} + + template <typename U, typename... Args> + constexpr explicit Optional( + in_place_t, + std::initializer_list<U> il, + Args&&... args) noexcept(std:: + is_nothrow_constructible< + Value, + std::initializer_list<U>, + Args...>::value) + : Optional{PrivateConstructor{}, il, std::forward<Args>(args)...} {} // Used only when an Optional is used with coroutines on MSVC /* implicit */ Optional(const detail::OptionalPromiseReturn<Value>& p) @@ -179,6 +195,11 @@ class Optional { } } + Optional& operator=(None) noexcept { + reset(); + return *this; + } + template <class Arg> Optional& operator=(Arg&& arg) { assign(std::forward<Arg>(arg)); @@ -235,22 +256,22 @@ class Optional { } } - FOLLY_CPP14_CONSTEXPR const Value& value() const& { + constexpr const Value& value() const& { require_value(); return storage_.value; } - FOLLY_CPP14_CONSTEXPR Value& value() & { + constexpr Value& value() & { require_value(); return storage_.value; } - FOLLY_CPP14_CONSTEXPR Value&& value() && { + constexpr Value&& value() && { require_value(); return std::move(storage_.value); } - FOLLY_CPP14_CONSTEXPR const Value&& value() const&& { + constexpr const Value&& value() const&& { require_value(); return std::move(storage_.value); } @@ -263,41 +284,41 @@ class Optional { } Value* get_pointer() && = delete; - FOLLY_CPP14_CONSTEXPR bool has_value() const noexcept { + constexpr bool has_value() const noexcept { return storage_.hasValue; } - FOLLY_CPP14_CONSTEXPR bool hasValue() const noexcept { + constexpr bool hasValue() const noexcept { return has_value(); } - FOLLY_CPP14_CONSTEXPR explicit operator bool() const noexcept { + constexpr explicit operator bool() const noexcept { return has_value(); } - FOLLY_CPP14_CONSTEXPR const Value& operator*() const& { + constexpr const Value& operator*() const& { return value(); } - FOLLY_CPP14_CONSTEXPR Value& operator*() & { + constexpr Value& operator*() & { return value(); } - FOLLY_CPP14_CONSTEXPR const Value&& operator*() const&& { + constexpr const Value&& operator*() const&& { return std::move(value()); } - FOLLY_CPP14_CONSTEXPR Value&& operator*() && { + constexpr Value&& operator*() && { return std::move(value()); } - FOLLY_CPP14_CONSTEXPR const Value* operator->() const { + constexpr const Value* operator->() const { return &value(); } - FOLLY_CPP14_CONSTEXPR Value* operator->() { + constexpr Value* operator->() { return &value(); } // Return a copy of the value if set, or a given default if not. template <class U> - FOLLY_CPP14_CONSTEXPR Value value_or(U&& dflt) const& { + constexpr Value value_or(U&& dflt) const& { if (storage_.hasValue) { return storage_.value; } @@ -306,7 +327,7 @@ class Optional { } template <class U> - FOLLY_CPP14_CONSTEXPR Value value_or(U&& dflt) && { + constexpr Value value_or(U&& dflt) && { if (storage_.hasValue) { return std::move(storage_.value); } @@ -315,6 +336,30 @@ class Optional { } private: + template <class T> + friend constexpr Optional<std::decay_t<T>> make_optional(T&&); + template <class T, class... Args> + friend constexpr Optional<T> make_optional(Args&&... args); + template <class T, class U, class... As> + friend constexpr Optional<T> make_optional(std::initializer_list<U>, As&&...); + + /** + * Construct the optional in place, this is duplicated as a non-explicit + * constructor to allow returning values that are non-movable from + * make_optional using list initialization. + * + * Until C++17, at which point this will become unnecessary because of + * specified prvalue elision. + */ + struct PrivateConstructor { + explicit PrivateConstructor() = default; + }; + template <typename... Args> + constexpr Optional(PrivateConstructor, Args&&... args) noexcept( + std::is_constructible<Value, Args&&...>::value) { + construct(std::forward<Args>(args)...); + } + void require_value() const { if (!storage_.hasValue) { throw_exception<OptionalEmptyException>(); @@ -336,7 +381,8 @@ class Optional { }; bool hasValue; - StorageTriviallyDestructible() : hasValue{false} {} + constexpr StorageTriviallyDestructible() + : emptyState('\0'), hasValue{false} {} void clear() { hasValue = false; } @@ -349,17 +395,10 @@ class Optional { }; bool hasValue; - FOLLY_PUSH_WARNING - // These are both informational warnings, but they trigger rare - // enough that we've left them enabled. Needed as long as MSVC - // 2015 is supported. - FOLLY_MSVC_DISABLE_WARNING(4587) // constructor of .value is not called - FOLLY_MSVC_DISABLE_WARNING(4588) // destructor of .value is not called StorageNonTriviallyDestructible() : hasValue{false} {} ~StorageNonTriviallyDestructible() { clear(); } - FOLLY_POP_WARNING void clear() { if (hasValue) { @@ -392,9 +431,25 @@ void swap(Optional<T>& a, Optional<T>& b) noexcept(noexcept(a.swap(b))) { a.swap(b); } -template <class T, class Opt = Optional<typename std::decay<T>::type>> -constexpr Opt make_optional(T&& v) { - return Opt(std::forward<T>(v)); +template <class T> +constexpr Optional<std::decay_t<T>> make_optional(T&& v) { + using PrivateConstructor = + typename folly::Optional<std::decay_t<T>>::PrivateConstructor; + return {PrivateConstructor{}, std::forward<T>(v)}; +} + +template <class T, class... Args> +constexpr folly::Optional<T> make_optional(Args&&... args) { + using PrivateConstructor = typename folly::Optional<T>::PrivateConstructor; + return {PrivateConstructor{}, std::forward<Args>(args)...}; +} + +template <class T, class U, class... Args> +constexpr folly::Optional<T> make_optional( + std::initializer_list<U> il, + Args&&... args) { + using PrivateConstructor = typename folly::Optional<T>::PrivateConstructor; + return {PrivateConstructor{}, il, std::forward<Args>(args)...}; } /////////////////////////////////////////////////////////////////////////////// @@ -421,9 +476,7 @@ constexpr bool operator!=(const U& a, const Optional<V>& b) { } template <class U, class V> -FOLLY_CPP14_CONSTEXPR bool operator==( - const Optional<U>& a, - const Optional<V>& b) { +constexpr bool operator==(const Optional<U>& a, const Optional<V>& b) { if (a.hasValue() != b.hasValue()) { return false; } @@ -439,9 +492,7 @@ constexpr bool operator!=(const Optional<U>& a, const Optional<V>& b) { } template <class U, class V> -FOLLY_CPP14_CONSTEXPR bool operator<( - const Optional<U>& a, - const Optional<V>& b) { +constexpr bool operator<(const Optional<U>& a, const Optional<V>& b) { if (a.hasValue() != b.hasValue()) { return a.hasValue() < b.hasValue(); } diff --git a/ios/Pods/Folly/folly/Overload.h b/ios/Pods/Folly/folly/Overload.h index bd6e8e264..5b3e0b2dd 100644 --- a/ios/Pods/Folly/folly/Overload.h +++ b/ios/Pods/Folly/folly/Overload.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/PackedSyncPtr.h b/ios/Pods/Folly/folly/PackedSyncPtr.h index b5054bdf9..7a4894cda 100644 --- a/ios/Pods/Folly/folly/PackedSyncPtr.h +++ b/ios/Pods/Folly/folly/PackedSyncPtr.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/Padded.h b/ios/Pods/Folly/folly/Padded.h index db4d3030c..005b42a03 100644 --- a/ios/Pods/Folly/folly/Padded.h +++ b/ios/Pods/Folly/folly/Padded.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -517,7 +517,7 @@ class Adaptor { std::pair<Container, size_t> move() { std::pair<Container, size_t> p(std::move(c_), lastCount_); lastCount_ = Node::kElementCount; - return std::move(p); + return p; } /** diff --git a/ios/Pods/Folly/folly/Poly-inl.h b/ios/Pods/Folly/folly/Poly-inl.h index 1f04e38ee..205c2aef5 100644 --- a/ios/Pods/Folly/folly/Poly-inl.h +++ b/ios/Pods/Folly/folly/Poly-inl.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -52,11 +52,12 @@ inline PolyVal<I>::PolyVal(T&& t) { "This Poly<> requires copyability, and the source object is not " "copyable"); // The static and dynamic types should match; otherwise, this will slice. - assert(typeid(t) == typeid(_t<std::decay<T>>) || + assert(typeid(t) == typeid(std::decay_t<T>) || !"Dynamic and static exception types don't match. Object would " "be sliced when storing in Poly."); if (inSitu<U>()) { - ::new (static_cast<void*>(&_data_()->buff_)) U(static_cast<T&&>(t)); + auto const buff = static_cast<void*>(&_data_()->buff_); + ::new (buff) U(static_cast<T&&>(t)); } else { _data_()->pobj_ = new U(static_cast<T&&>(t)); } diff --git a/ios/Pods/Folly/folly/Poly.h b/ios/Pods/Folly/folly/Poly.h index 6da8a94dd..cccf1a83b 100644 --- a/ios/Pods/Folly/folly/Poly.h +++ b/ios/Pods/Folly/folly/Poly.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -25,10 +25,6 @@ #pragma once -#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5 -#error Folly.Poly requires gcc-5 or greater -#endif - #include <cassert> #include <new> #include <type_traits> @@ -54,6 +50,12 @@ namespace folly { template <class I> struct Poly; +// MSVC workaround +template <class Node, class Tfx, class Access> +struct PolySelf_ { + using type = decltype(Access::template self_<Node, Tfx>()); +}; + /** * Within the definition of interface `I`, `PolySelf<Base>` is an alias for * the instance of `Poly` that is currently being instantiated. It is @@ -105,7 +107,7 @@ template < class Node, class Tfx = detail::MetaIdentity, class Access = detail::PolyAccess> -using PolySelf = decltype(Access::template self_<Node, Tfx>()); +using PolySelf = _t<PolySelf_<Node, Tfx, Access>>; /** * When used in conjunction with `PolySelf`, controls how to construct `Poly` @@ -115,7 +117,7 @@ using PolySelf = decltype(Access::template self_<Node, Tfx>()); */ using PolyDecay = detail::MetaQuote<std::decay_t>; -#if !defined(__cpp_template_auto) +#if !FOLLY_POLY_NTTP_AUTO /** * Use `FOLLY_POLY_MEMBERS(MEMS...)` on pre-C++17 compilers to specify a @@ -422,15 +424,13 @@ constexpr bool poly_empty(Poly<I&> const&) noexcept { */ template < class I, - std::enable_if_t<detail::Not<std::is_reference<I>>::value, int> = 0> + std::enable_if_t<Negation<std::is_reference<I>>::value, int> = 0> constexpr Poly<I>&& poly_move(detail::PolyRoot<I>& that) noexcept { return static_cast<Poly<I>&&>(static_cast<Poly<I>&>(that)); } /// \overload -template < - class I, - std::enable_if_t<detail::Not<std::is_const<I>>::value, int> = 0> +template <class I, std::enable_if_t<Negation<std::is_const<I>>::value, int> = 0> Poly<I&&> poly_move(detail::PolyRoot<I&> const& that) noexcept { return detail::PolyAccess::move(that); } diff --git a/ios/Pods/Folly/folly/PolyException.h b/ios/Pods/Folly/folly/PolyException.h index 8aca9d47c..92090e7a3 100644 --- a/ios/Pods/Folly/folly/PolyException.h +++ b/ios/Pods/Folly/folly/PolyException.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -17,6 +17,7 @@ #pragma once #include <exception> +#include <typeinfo> #include <folly/CPortability.h> diff --git a/ios/Pods/Folly/folly/Portability.h b/ios/Pods/Folly/folly/Portability.h index a7b0e7746..290cf45d5 100644 --- a/ios/Pods/Folly/folly/Portability.h +++ b/ios/Pods/Folly/folly/Portability.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -16,10 +16,20 @@ #pragma once +// MSCV 2017 __cplusplus definition by default does not track the C++ version. +// https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ +#if !defined(_MSC_VER) || _MSC_VER >= 2000 +static_assert(__cplusplus >= 201402L, "__cplusplus >= 201402L"); +#endif + +#if defined(__GNUC__) && !defined(__clang__) +static_assert(__GNUC__ >= 5, "__GNUC__ >= 5"); +#endif + #include <cstddef> -#include <folly/portability/Config.h> #include <folly/CPortability.h> +#include <folly/portability/Config.h> // Unaligned loads and stores namespace folly { @@ -58,7 +68,7 @@ constexpr bool kHasUnalignedAccess = false; #if !defined FOLLY_NODISCARD #if defined(_MSC_VER) && (_MSC_VER >= 1700) #define FOLLY_NODISCARD _Check_return_ -#elif defined(__clang__) || defined(__GNUC__) +#elif defined(__GNUC__) #define FOLLY_NODISCARD __attribute__((__warn_unused_result__)) #else #define FOLLY_NODISCARD @@ -107,12 +117,18 @@ constexpr bool kIsArchPPC64 = FOLLY_PPC64 == 1; namespace folly { /** - * folly::kIsSanitizeAddress reports if folly was compiled with ASAN + * folly::kIsLibrarySanitizeAddress reports if folly was compiled with ASAN * enabled. Note that for compilation units outside of folly that include - * folly/Portability.h, the value of kIsSanitizeAddress may be different + * folly/Portability.h, the value of kIsLibrarySanitizeAddress may be different * from whether or not the current compilation unit is being compiled with ASAN. */ -#if FOLLY_ASAN_ENABLED +#if FOLLY_LIBRARY_SANITIZE_ADDRESS +constexpr bool kIsLibrarySanitizeAddress = true; +#else +constexpr bool kIsLibrarySanitizeAddress = false; +#endif + +#if FOLLY_SANITIZE_ADDRESS constexpr bool kIsSanitizeAddress = true; #else constexpr bool kIsSanitizeAddress = false; @@ -136,7 +152,7 @@ constexpr bool kIsSanitize = false; #define FOLLY_PACK_ATTR /**/ #define FOLLY_PACK_PUSH __pragma(pack(push, 1)) #define FOLLY_PACK_POP __pragma(pack(pop)) -#elif defined(__clang__) || defined(__GNUC__) +#elif defined(__GNUC__) #define FOLLY_PACK_ATTR __attribute__((__packed__)) #define FOLLY_PACK_PUSH /**/ #define FOLLY_PACK_POP /**/ @@ -192,11 +208,6 @@ constexpr bool kIsSanitize = false; #define FOLLY_GCC_DISABLE_NEW_SHADOW_WARNINGS /* empty */ #endif -// Globally disable -Wshadow for gcc < 5. -#if __GNUC__ == 4 && !__clang__ -FOLLY_GCC_DISABLE_NEW_SHADOW_WARNINGS -#endif - /* Platform specific TLS support * gcc implements __thread * msvc implements __declspec(thread) @@ -205,15 +216,18 @@ FOLLY_GCC_DISABLE_NEW_SHADOW_WARNINGS */ #if defined(_MSC_VER) #define FOLLY_TLS __declspec(thread) -#elif defined(__GNUC__) || defined(__clang__) +#elif defined(__GNUC__) #define FOLLY_TLS __thread #else #error cannot define platform specific thread local storage #endif -#if FOLLY_MOBILE +// disable FOLLY_TLS on 32 bit Apple/iOS +#if defined(__APPLE__) && FOLLY_MOBILE +#if (__SIZEOF_POINTER__ == 4) #undef FOLLY_TLS #endif +#endif // It turns out that GNU libstdc++ and LLVM libc++ differ on how they implement // the 'std' namespace; the latter uses inline namespaces. Wrap this decision @@ -243,19 +257,43 @@ FOLLY_GCC_DISABLE_NEW_SHADOW_WARNINGS #ifdef _MSC_VER #include <folly/portability/SysTypes.h> -// compiler specific to compiler specific -// nolint -#define __PRETTY_FUNCTION__ __FUNCSIG__ - // Hide a GCC specific thing that breaks MSVC if left alone. #define __extension__ // We have compiler support for the newest of the new, but // MSVC doesn't tell us that. +// +// Clang pretends to be MSVC on Windows, but it refuses to compile +// SSE4.2 intrinsics unless -march argument is specified. +// So cannot unconditionally define __SSE4_2__ in clang. +#ifndef __clang__ #define __SSE4_2__ 1 +// compiler specific to compiler specific +// nolint +#define __PRETTY_FUNCTION__ __FUNCSIG__ +#endif #endif +// Define FOLLY_HAS_EXCEPTIONS +#if __cpp_exceptions >= 199711 || FOLLY_HAS_FEATURE(cxx_exceptions) +#define FOLLY_HAS_EXCEPTIONS 1 +#elif __GNUC__ +#if __EXCEPTIONS +#define FOLLY_HAS_EXCEPTIONS 1 +#else // __EXCEPTIONS +#define FOLLY_HAS_EXCEPTIONS 0 +#endif // __EXCEPTIONS +#elif FOLLY_MICROSOFT_ABI_VER +#if _CPPUNWIND +#define FOLLY_HAS_EXCEPTIONS 1 +#else // _CPPUNWIND +#define FOLLY_HAS_EXCEPTIONS 0 +#endif // _CPPUNWIND +#else +#define FOLLY_HAS_EXCEPTIONS 1 // default assumption for unknown platforms +#endif + // Debug namespace folly { #ifdef NDEBUG @@ -265,6 +303,15 @@ constexpr auto kIsDebug = true; #endif } // namespace folly +// Exceptions +namespace folly { +#if FOLLY_HAS_EXCEPTIONS +constexpr auto kHasExceptions = true; +#else +constexpr auto kHasExceptions = false; +#endif +} // namespace folly + // Endianness namespace folly { #ifdef _MSC_VER @@ -330,8 +377,14 @@ using namespace FOLLY_GFLAGS_NAMESPACE; #if defined(__GXX_RTTI) || defined(__cpp_rtti) || \ (defined(_MSC_VER) && defined(_CPPRTTI)) #define FOLLY_HAS_RTTI 1 +#else +#define FOLLY_HAS_RTTI 0 #endif +namespace folly { +constexpr bool const kHasRtti = FOLLY_HAS_RTTI; +} // namespace folly + #if defined(__APPLE__) || defined(_MSC_VER) #define FOLLY_STATIC_CTOR_PRIORITY_MAX #else @@ -373,6 +426,12 @@ constexpr auto kIsGlibcxx = true; constexpr auto kIsGlibcxx = false; #endif +#if __GLIBCXX__ && _GLIBCXX_RELEASE // major version, 7+ +constexpr auto kGlibcxxVer = _GLIBCXX_RELEASE; +#else +constexpr auto kGlibcxxVer = 0; +#endif + #if _LIBCPP_VERSION constexpr auto kIsLibcpp = true; #else @@ -391,6 +450,18 @@ constexpr auto kMscVer = _MSC_VER; constexpr auto kMscVer = 0; #endif +#if __GNUC__ +constexpr auto kGnuc = __GNUC__; +#else +constexpr auto kGnuc = 0; +#endif + +#if __clang__ +constexpr auto kIsClang = true; +#else +constexpr auto kIsClang = false; +#endif + #if FOLLY_MICROSOFT_ABI_VER constexpr auto kMicrosoftAbiVer = FOLLY_MICROSOFT_ABI_VER; #else @@ -406,24 +477,6 @@ constexpr auto kCpplibVer = 0; #endif } // namespace folly -// Define FOLLY_USE_CPP14_CONSTEXPR to be true if the compiler's C++14 -// constexpr support is "good enough". -#ifndef FOLLY_USE_CPP14_CONSTEXPR -#if defined(__clang__) -#define FOLLY_USE_CPP14_CONSTEXPR __cplusplus >= 201300L -#elif defined(__GNUC__) -#define FOLLY_USE_CPP14_CONSTEXPR __cplusplus >= 201304L -#else -#define FOLLY_USE_CPP14_CONSTEXPR 0 // MSVC? -#endif -#endif - -#if FOLLY_USE_CPP14_CONSTEXPR -#define FOLLY_CPP14_CONSTEXPR constexpr -#else -#define FOLLY_CPP14_CONSTEXPR inline -#endif - // MSVC does not permit: // // extern int const num; @@ -434,28 +487,30 @@ constexpr auto kCpplibVer = 0; // extern int const num; // FOLLY_STORAGE_CONSTEXPR int const num = 3; // -// True for MSVC 2015 and MSVC 2017. +// True as of MSVC 2017. #if _MSC_VER #define FOLLY_STORAGE_CONSTEXPR -#define FOLLY_STORAGE_CPP14_CONSTEXPR -#else -#if __ICC -#define FOLLY_STORAGE_CONSTEXPR #else #define FOLLY_STORAGE_CONSTEXPR constexpr #endif -#if FOLLY_USE_CPP14_CONSTEXPR -#define FOLLY_STORAGE_CPP14_CONSTEXPR constexpr -#else -#define FOLLY_STORAGE_CPP14_CONSTEXPR -#endif -#endif +#if __cplusplus >= 201703L +// folly::coro requires C++17 support #if __cpp_coroutines >= 201703L && __has_include(<experimental/coroutine>) #define FOLLY_HAS_COROUTINES 1 +// This is mainly to workaround bugs triggered by LTO, when stack allocated +// variables in await_suspend end up on a coroutine frame. +#define FOLLY_CORO_AWAIT_SUSPEND_NONTRIVIAL_ATTRIBUTES FOLLY_NOINLINE #elif _MSC_VER && _RESUMABLE_FUNCTIONS_SUPPORTED -#define FOLLY_HAS_COROUTINES 1 +// NOTE: MSVC 2017 does not currently support the full Coroutines TS since it +// does not yet support symmetric-transfer. +#define FOLLY_HAS_COROUTINES 0 +#else +#define FOLLY_HAS_COROUTINES 0 #endif +#else +#define FOLLY_HAS_COROUTINES 0 +#endif // __cplusplus >= 201703L // MSVC 2017.5 && C++17 #if __cpp_noexcept_function_type >= 201510 || \ @@ -463,23 +518,12 @@ constexpr auto kCpplibVer = 0; #define FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE 1 #endif -// Define FOLLY_HAS_EXCEPTIONS -#if __cpp_exceptions >= 199711 || FOLLY_HAS_FEATURE(cxx_exceptions) -#define FOLLY_HAS_EXCEPTIONS 1 -#elif __GNUC__ -#if __EXCEPTIONS -#define FOLLY_HAS_EXCEPTIONS 1 -#else // __EXCEPTIONS -#define FOLLY_HAS_EXCEPTIONS 0 -#endif // __EXCEPTIONS -#elif FOLLY_MICROSOFT_ABI_VER -#if _CPPUNWIND -#define FOLLY_HAS_EXCEPTIONS 1 -#else // _CPPUNWIND -#define FOLLY_HAS_EXCEPTIONS 0 -#endif // _CPPUNWIND +#if __cpp_inline_variables >= 201606L +#define FOLLY_HAS_INLINE_VARIABLES 1 +#define FOLLY_INLINE_VARIABLE inline #else -#define FOLLY_HAS_EXCEPTIONS 1 // default assumption for unknown platforms +#define FOLLY_HAS_INLINE_VARIABLES 0 +#define FOLLY_INLINE_VARIABLE #endif // feature test __cpp_lib_string_view is defined in <string>, which is diff --git a/ios/Pods/Folly/folly/Preprocessor.h b/ios/Pods/Folly/folly/Preprocessor.h index 1926dd641..292bd9fff 100644 --- a/ios/Pods/Folly/folly/Preprocessor.h +++ b/ios/Pods/Folly/folly/Preprocessor.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -18,6 +18,8 @@ #pragma once +#include <folly/CPortability.h> + /** * Necessarily evil preprocessor-related amenities. */ @@ -87,17 +89,26 @@ #define FB_CONCATENATE_IMPL(s1, s2) s1##s2 #define FB_CONCATENATE(s1, s2) FB_CONCATENATE_IMPL(s1, s2) #ifdef __COUNTER__ +// Modular builds build each module with its own preprocessor state, meaning +// `__COUNTER__` no longer provides a unique number across a TU. Instead of +// calling back to just `__LINE__`, use a mix of `__COUNTER__` and `__LINE__` +// to try provide as much uniqueness as possible. +#if FOLLY_HAS_FEATURE(modules) +#define FB_ANONYMOUS_VARIABLE(str) \ + FB_CONCATENATE(FB_CONCATENATE(FB_CONCATENATE(str, __COUNTER__), _), __LINE__) +#else #define FB_ANONYMOUS_VARIABLE(str) FB_CONCATENATE(str, __COUNTER__) +#endif #else #define FB_ANONYMOUS_VARIABLE(str) FB_CONCATENATE(str, __LINE__) #endif #endif /** - * Use FB_STRINGIZE(x) when you'd want to do what #x does inside + * Use FOLLY_PP_STRINGIZE(x) when you'd want to do what #x does inside * another macro expansion. */ -#define FB_STRINGIZE(x) #x +#define FOLLY_PP_STRINGIZE(x) #x #define FOLLY_PP_DETAIL_NARGS_1(dummy, _7, _6, _5, _4, _3, _2, _1, _0, ...) _0 #define FOLLY_PP_DETAIL_NARGS(...) \ diff --git a/ios/Pods/Folly/folly/PriorityMPMCQueue.h b/ios/Pods/Folly/folly/PriorityMPMCQueue.h deleted file mode 100644 index d162c09b6..000000000 --- a/ios/Pods/Folly/folly/PriorityMPMCQueue.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2017-present Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#pragma once - -#include <glog/logging.h> -#include <algorithm> -#include <vector> - -#include <folly/MPMCQueue.h> - -namespace folly { - -/// PriorityMPMCQueue is a thin wrapper on MPMCQueue, providing priorities -/// by managing multiple underlying MPMCQueues. As of now, this does -/// not implement a blocking interface. For the purposes of this -/// class, lower number is higher priority - -template < - typename T, - template <typename> class Atom = std::atomic, - bool Dynamic = false> -class PriorityMPMCQueue { - public: - PriorityMPMCQueue(size_t numPriorities, size_t capacity) { - CHECK_GT(numPriorities, 0); - queues_.reserve(numPriorities); - for (size_t i = 0; i < numPriorities; i++) { - queues_.emplace_back(capacity); - } - } - - size_t getNumPriorities() { - return queues_.size(); - } - - // Add at medium priority by default - bool write(T&& item) { - return writeWithPriority(std::move(item), getNumPriorities() / 2); - } - - bool writeWithPriority(T&& item, size_t priority) { - size_t queue = std::min(getNumPriorities() - 1, priority); - CHECK_LT(queue, queues_.size()); - return queues_.at(queue).write(std::move(item)); - } - - bool writeWithPriority( - T&& item, - size_t priority, - std::chrono::milliseconds timeout) { - size_t queue = std::min(getNumPriorities() - 1, priority); - CHECK_LT(queue, queues_.size()); - return queues_.at(queue).tryWriteUntil( - std::chrono::steady_clock::now() + timeout, std::move(item)); - } - - bool read(T& item) { - for (auto& q : queues_) { - if (q.readIfNotEmpty(item)) { - return true; - } - } - return false; - } - - bool readWithPriority(T& item, size_t priority) { - return queues_[priority].readIfNotEmpty(item); - } - - size_t size() const { - size_t total_size = 0; - for (auto& q : queues_) { - // MPMCQueue can have a negative size if there are pending readers. - // Since we don't expose a blocking interface this shouldn't happen, - // But just in case we put a floor at 0 - total_size += std::max<ssize_t>(0, q.size()); - } - return total_size; - } - - size_t sizeGuess() const { - size_t total_size = 0; - for (auto& q : queues_) { - // MPMCQueue can have a negative size if there are pending readers. - // Since we don't expose a blocking interface this shouldn't happen, - // But just in case we put a floor at 0 - total_size += std::max<ssize_t>(0, q.sizeGuess()); - } - return total_size; - } - - /// Returns true if there are no items available for dequeue - bool isEmpty() const { - return size() == 0; - } - - private: - std::vector<folly::MPMCQueue<T, Atom, Dynamic>> queues_; -}; - -} // namespace folly diff --git a/ios/Pods/Folly/folly/ProducerConsumerQueue.h b/ios/Pods/Folly/folly/ProducerConsumerQueue.h index 5636a63fc..15cf70a2b 100644 --- a/ios/Pods/Folly/folly/ProducerConsumerQueue.h +++ b/ios/Pods/Folly/folly/ProducerConsumerQueue.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/RWSpinLock.h b/ios/Pods/Folly/folly/RWSpinLock.h index 259a4b492..4154f393b 100644 --- a/ios/Pods/Folly/folly/RWSpinLock.h +++ b/ios/Pods/Folly/folly/RWSpinLock.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/Random-inl.h b/ios/Pods/Folly/folly/Random-inl.h index d52aceee0..9434f0a54 100644 --- a/ios/Pods/Folly/folly/Random-inl.h +++ b/ios/Pods/Folly/folly/Random-inl.h @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/Random.h b/ios/Pods/Folly/folly/Random.h index f653ca866..764880ebb 100644 --- a/ios/Pods/Folly/folly/Random.h +++ b/ios/Pods/Folly/folly/Random.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -100,7 +100,7 @@ class Random { /** * Get secure random bytes. (On Linux and OSX, this means /dev/urandom). */ - static void secureRandom(void* data, size_t len); + static void secureRandom(void* data, size_t size); /** * Shortcut to get a secure random value of integral type. diff --git a/ios/Pods/Folly/folly/Range.h b/ios/Pods/Folly/folly/Range.h index ae1919e67..01e292e68 100644 --- a/ios/Pods/Folly/folly/Range.h +++ b/ios/Pods/Folly/folly/Range.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -59,8 +59,9 @@ namespace folly { template <class T> struct IsSomeString : std::false_type {}; -template <> -struct IsSomeString<std::string> : std::true_type {}; +template <typename Alloc> +struct IsSomeString<std::basic_string<char, std::char_traits<char>, Alloc>> + : std::true_type {}; template <class Iter> class Range; @@ -111,32 +112,6 @@ inline size_t qfind_first_of( */ namespace detail { -/** - * For random-access iterators, the value before is simply i[-1]. - */ -template <class Iter> -typename std::enable_if< - std::is_same< - typename std::iterator_traits<Iter>::iterator_category, - std::random_access_iterator_tag>::value, - typename std::iterator_traits<Iter>::reference>::type -value_before(Iter i) { - return i[-1]; -} - -/** - * For all other iterators, we need to use the decrement operator. - */ -template <class Iter> -typename std::enable_if< - !std::is_same< - typename std::iterator_traits<Iter>::iterator_category, - std::random_access_iterator_tag>::value, - typename std::iterator_traits<Iter>::reference>::type -value_before(Iter i) { - return *--i; -} - /* * Use IsCharPointer<T>::type to enable const char* or char*. * Use IsCharPointer<T>::const_type to enable only const char*. @@ -170,6 +145,10 @@ struct IsCharPointer<const char*> { */ template <class Iter> class Range { + private: + template <typename Alloc> + using string = std::basic_string<char, std::char_traits<char>, Alloc>; + public: typedef std::size_t size_type; typedef Iter iterator; @@ -209,9 +188,7 @@ class Range { // Works only for random-access iterators constexpr Range(Iter start, size_t size) : b_(start), e_(start + size) {} -#if !__clang__ || __CLANG_PREREQ(3, 7) // Clang 3.6 crashes on this line /* implicit */ Range(std::nullptr_t) = delete; -#endif constexpr /* implicit */ Range(Iter str) : b_(str), e_(str + constexpr_strlen(str)) { @@ -220,12 +197,18 @@ class Range { "This constructor is only available for character ranges"); } - template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0> - /* implicit */ Range(const std::string& str) + template < + class Alloc, + class T = Iter, + typename detail::IsCharPointer<T>::const_type = 0> + /* implicit */ Range(const string<Alloc>& str) : b_(str.data()), e_(b_ + str.size()) {} - template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0> - Range(const std::string& str, std::string::size_type startFrom) { + template < + class Alloc, + class T = Iter, + typename detail::IsCharPointer<T>::const_type = 0> + Range(const string<Alloc>& str, typename string<Alloc>::size_type startFrom) { if (UNLIKELY(startFrom > str.size())) { throw_exception<std::out_of_range>("index out of range"); } @@ -233,11 +216,14 @@ class Range { e_ = str.data() + str.size(); } - template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0> + template < + class Alloc, + class T = Iter, + typename detail::IsCharPointer<T>::const_type = 0> Range( - const std::string& str, - std::string::size_type startFrom, - std::string::size_type size) { + const string<Alloc>& str, + typename string<Alloc>::size_type startFrom, + typename string<Alloc>::size_type size) { if (UNLIKELY(startFrom > str.size())) { throw_exception<std::out_of_range>("index out of range"); } @@ -405,8 +391,11 @@ class Range { Range& operator=(const Range& rhs) & = default; Range& operator=(Range&& rhs) & = default; - template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0> - Range& operator=(std::string&& rhs) = delete; + template < + class Alloc, + class T = Iter, + typename detail::IsCharPointer<T>::const_type = 0> + Range& operator=(string<Alloc>&& rhs) = delete; void clear() { b_ = Iter(); @@ -424,17 +413,15 @@ class Range { } // Works only for Range<const char*> - void reset(const std::string& str) { + template <typename Alloc> + void reset(const string<Alloc>& str) { reset(str.data(), str.size()); } constexpr size_type size() const { - // It would be nice to assert(b_ <= e_) here. This can be achieved even - // in a C++11 compatible constexpr function: - // http://ericniebler.com/2014/09/27/assert-and-constexpr-in-cxx11/ - // Unfortunately current gcc versions have a bug causing it to reject - // this check in a constexpr function: - // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71448 +#if __clang__ || !__GNUC__ || __GNUC__ >= 7 + assert(b_ <= e_); +#endif return size_type(e_ - b_); } constexpr size_type walk_size() const { @@ -467,7 +454,7 @@ class Range { } value_type& back() { assert(b_ < e_); - return detail::value_before(e_); + return *std::prev(e_); } const value_type& front() const { assert(b_ < e_); @@ -475,7 +462,7 @@ class Range { } const value_type& back() const { assert(b_ < e_); - return detail::value_before(e_); + return *std::prev(e_); } private: @@ -496,13 +483,22 @@ class Range { // At the moment the set of implicit target types consists of just // std::string_view (when it is available). #if FOLLY_HAS_STRING_VIEW - using StringViewType = - std::basic_string_view<std::remove_const_t<value_type>>; + struct NotStringView {}; + template <typename ValueType> + struct StringViewType + : std::conditional< + std::is_pod<std::remove_const_t<ValueType>>::value, + std::basic_string_view<std::remove_const_t<ValueType>>, + NotStringView> {}; template <typename Target> - using IsConstructibleViaStringView = StrictConjunction< - std::is_constructible<StringViewType, Iter const&, size_type>, - std::is_constructible<Target, StringViewType>>; + struct IsConstructibleViaStringView + : Conjunction< + std::is_constructible< + _t<StringViewType<value_type>>, + Iter const&, + size_type>, + std::is_constructible<Target, _t<StringViewType<value_type>>>> {}; #else template <typename Target> using IsConstructibleViaStringView = std::false_type; @@ -542,11 +538,14 @@ class Range { /// implicit operator conversion to std::string_view template < typename Tgt, + typename ValueType = value_type, std::enable_if_t< StrictConjunction< - std::is_same<Tgt, StringViewType>, - std::is_constructible<StringViewType, Iter const&, size_type>>:: - value, + std::is_same<Tgt, _t<StringViewType<ValueType>>>, + std::is_constructible< + _t<StringViewType<ValueType>>, + Iter const&, + size_type>>::value, int> = 0> constexpr operator Tgt() const noexcept( std::is_nothrow_constructible<Tgt, Iter const&, size_type>::value) { @@ -599,7 +598,6 @@ class Range { return const_range_type(*this); } - // Works only for Range<const char*> and Range<char*> int compare(const const_range_type& o) const { const size_type tsize = this->size(); const size_type osize = o.size(); @@ -1236,8 +1234,9 @@ struct ComparableAsStringPiece { * operator== through conversion for Range<const char*> */ template <class T, class U> -_t<std::enable_if<detail::ComparableAsStringPiece<T, U>::value, bool>> -operator==(const T& lhs, const U& rhs) { +std::enable_if_t<detail::ComparableAsStringPiece<T, U>::value, bool> operator==( + const T& lhs, + const U& rhs) { return StringPiece(lhs) == StringPiece(rhs); } @@ -1245,8 +1244,9 @@ operator==(const T& lhs, const U& rhs) { * operator!= through conversion for Range<const char*> */ template <class T, class U> -_t<std::enable_if<detail::ComparableAsStringPiece<T, U>::value, bool>> -operator!=(const T& lhs, const U& rhs) { +std::enable_if_t<detail::ComparableAsStringPiece<T, U>::value, bool> operator!=( + const T& lhs, + const U& rhs) { return StringPiece(lhs) != StringPiece(rhs); } @@ -1254,8 +1254,9 @@ operator!=(const T& lhs, const U& rhs) { * operator< through conversion for Range<const char*> */ template <class T, class U> -_t<std::enable_if<detail::ComparableAsStringPiece<T, U>::value, bool>> -operator<(const T& lhs, const U& rhs) { +std::enable_if_t<detail::ComparableAsStringPiece<T, U>::value, bool> operator<( + const T& lhs, + const U& rhs) { return StringPiece(lhs) < StringPiece(rhs); } @@ -1263,8 +1264,9 @@ operator<(const T& lhs, const U& rhs) { * operator> through conversion for Range<const char*> */ template <class T, class U> -_t<std::enable_if<detail::ComparableAsStringPiece<T, U>::value, bool>> -operator>(const T& lhs, const U& rhs) { +std::enable_if_t<detail::ComparableAsStringPiece<T, U>::value, bool> operator>( + const T& lhs, + const U& rhs) { return StringPiece(lhs) > StringPiece(rhs); } @@ -1272,8 +1274,9 @@ operator>(const T& lhs, const U& rhs) { * operator< through conversion for Range<const char*> */ template <class T, class U> -_t<std::enable_if<detail::ComparableAsStringPiece<T, U>::value, bool>> -operator<=(const T& lhs, const U& rhs) { +std::enable_if_t<detail::ComparableAsStringPiece<T, U>::value, bool> operator<=( + const T& lhs, + const U& rhs) { return StringPiece(lhs) <= StringPiece(rhs); } @@ -1281,8 +1284,9 @@ operator<=(const T& lhs, const U& rhs) { * operator> through conversion for Range<const char*> */ template <class T, class U> -_t<std::enable_if<detail::ComparableAsStringPiece<T, U>::value, bool>> -operator>=(const T& lhs, const U& rhs) { +std::enable_if_t<detail::ComparableAsStringPiece<T, U>::value, bool> operator>=( + const T& lhs, + const U& rhs) { return StringPiece(lhs) >= StringPiece(rhs); } @@ -1491,10 +1495,16 @@ struct hasher; template <class T> struct hasher< folly::Range<T*>, - typename std::enable_if<std::is_pod<T>::value, void>::type> { + std::enable_if_t<std::is_integral<T>::value, void>> { using folly_is_avalanching = std::true_type; size_t operator()(folly::Range<T*> r) const { + // std::is_integral<T> is too restrictive, but is sufficient to + // guarantee we can just hash all of the underlying bytes to get a + // suitable hash of T. Something like absl::is_uniquely_represented<T> + // would be better. std::is_pod is not enough, because POD types + // can contain pointers and padding. Also, floating point numbers + // may be == without being bit-identical. return hash::SpookyHashV2::Hash64(r.begin(), r.size() * sizeof(T), 0); } }; diff --git a/ios/Pods/Folly/folly/Replaceable.h b/ios/Pods/Folly/folly/Replaceable.h index f35b61d5c..c0879f25d 100644 --- a/ios/Pods/Folly/folly/Replaceable.h +++ b/ios/Pods/Folly/folly/Replaceable.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -372,13 +372,8 @@ struct is_convertible_from_replaceable std::is_convertible<const Replaceable<T>&&, T>::value> {}; } // namespace replaceable_detail -// Type trait template to statically test whether a type is a specialization of -// Replaceable template <class T> -struct is_replaceable : std::false_type {}; - -template <class T> -struct is_replaceable<Replaceable<T>> : std::true_type {}; +using is_replaceable = detail::is_instantiation_of<Replaceable, T>; // Function to make a Replaceable with a type deduced from its input template <class T> @@ -439,7 +434,7 @@ class alignas(T) Replaceable template < class... Args, std::enable_if_t<std::is_constructible<T, Args&&...>::value, int> = 0> - FOLLY_CPP14_CONSTEXPR explicit Replaceable(in_place_t, Args&&... args) + constexpr explicit Replaceable(in_place_t, Args&&... args) // clang-format off noexcept(std::is_nothrow_constructible<T, Args&&...>::value) // clang-format on @@ -453,7 +448,7 @@ class alignas(T) Replaceable std::enable_if_t< std::is_constructible<T, std::initializer_list<U>, Args&&...>::value, int> = 0> - FOLLY_CPP14_CONSTEXPR explicit Replaceable( + constexpr explicit Replaceable( in_place_t, std::initializer_list<U> il, Args&&... args) @@ -475,7 +470,7 @@ class alignas(T) Replaceable !std::is_same<Replaceable<T>, std::decay_t<U>>::value && std::is_convertible<U&&, T>::value, int> = 0> - FOLLY_CPP14_CONSTEXPR /* implicit */ Replaceable(U&& other) + constexpr /* implicit */ Replaceable(U&& other) // clang-format off noexcept(std::is_nothrow_constructible<T, U&&>::value) // clang-format on @@ -491,7 +486,7 @@ class alignas(T) Replaceable !std::is_same<Replaceable<T>, std::decay_t<U>>::value && !std::is_convertible<U&&, T>::value, int> = 0> - FOLLY_CPP14_CONSTEXPR explicit Replaceable(U&& other) + constexpr explicit Replaceable(U&& other) // clang-format off noexcept(std::is_nothrow_constructible<T, U&&>::value) // clang-format on @@ -595,11 +590,8 @@ class alignas(T) Replaceable /** * `swap` just calls `swap(T&, T&)`. - * - * Should be `noexcept(std::is_nothrow_swappable<T>::value)` but we don't - * depend on C++17 features. */ - void swap(Replaceable& other) { + void swap(Replaceable& other) noexcept(IsNothrowSwappable<Replaceable>{}) { using std::swap; swap(*(*this), *other); } @@ -611,7 +603,7 @@ class alignas(T) Replaceable return launder(reinterpret_cast<T const*>(storage_)); } - FOLLY_CPP14_CONSTEXPR T* operator->() { + constexpr T* operator->() { return launder(reinterpret_cast<T*>(storage_)); } @@ -619,11 +611,11 @@ class alignas(T) Replaceable return *launder(reinterpret_cast<T const*>(storage_)); } - FOLLY_CPP14_CONSTEXPR T& operator*() & { + constexpr T& operator*() & { return *launder(reinterpret_cast<T*>(storage_)); } - FOLLY_CPP14_CONSTEXPR T&& operator*() && { + constexpr T&& operator*() && { return std::move(*launder(reinterpret_cast<T*>(storage_))); } @@ -637,11 +629,10 @@ class alignas(T) Replaceable friend struct replaceable_detail::copy_ctor_mixin<T>; friend struct replaceable_detail::move_assignment_mixin<T>; friend struct replaceable_detail::copy_assignment_mixin<T>; - std::aligned_storage_t<sizeof(T), alignof(T)> storage_[1]; + aligned_storage_for_t<T> storage_[1]; }; -#if __cplusplus > 201402L -// C++17 allows us to define a deduction guide: +#if __cpp_deduction_guides >= 201703 template <class T> Replaceable(T)->Replaceable<T>; #endif diff --git a/ios/Pods/Folly/folly/ScopeGuard.cpp b/ios/Pods/Folly/folly/ScopeGuard.cpp index f412a4f56..5678ea8d2 100644 --- a/ios/Pods/Folly/folly/ScopeGuard.cpp +++ b/ios/Pods/Folly/folly/ScopeGuard.cpp @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/ScopeGuard.h b/ios/Pods/Folly/folly/ScopeGuard.h index 39c10406f..26da53d1e 100644 --- a/ios/Pods/Folly/folly/ScopeGuard.h +++ b/ios/Pods/Folly/folly/ScopeGuard.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -26,6 +26,7 @@ #include <folly/Portability.h> #include <folly/Preprocessor.h> #include <folly/Utility.h> +#include <folly/lang/Exception.h> #include <folly/lang/UncaughtExceptions.h> namespace folly { @@ -89,7 +90,7 @@ class ScopeGuardImpl : public ScopeGuardImplBase { // on the value of other.dismissed_. The following lines only execute // if the move/copy succeeded, in which case *this assumes ownership of // the cleanup action and dismisses other. - dismissed_ = exchange(other.dismissed_, true); + dismissed_ = std::exchange(other.dismissed_, true); } ~ScopeGuardImpl() noexcept(InvokeNoexcept) { @@ -120,12 +121,9 @@ class ScopeGuardImpl : public ScopeGuardImplBase { void execute() noexcept(InvokeNoexcept) { if (InvokeNoexcept) { - try { - function_(); - } catch (...) { - warnAboutToCrash(); - std::terminate(); - } + using R = decltype(function_()); + auto catcher = []() -> R { warnAboutToCrash(), std::terminate(); }; + catch_exception(function_, catcher); } else { function_(); } @@ -142,7 +140,7 @@ using ScopeGuardImplDecay = ScopeGuardImpl<typename std::decay<F>::type, INE>; /** * ScopeGuard is a general implementation of the "Initialization is * Resource Acquisition" idiom. Basically, it guarantees that a function - * is executed upon leaving the currrent scope unless otherwise told. + * is executed upon leaving the current scope unless otherwise told. * * The makeGuard() function is used to create a new ScopeGuard object. * It can be instantiated with a lambda function, a std::function<void()>, @@ -181,7 +179,7 @@ using ScopeGuardImplDecay = ScopeGuardImpl<typename std::decay<F>::type, INE>; * http://www.codeproject.com/KB/cpp/scope_guard.aspx */ template <typename F> -detail::ScopeGuardImplDecay<F, true> makeGuard(F&& f) noexcept( +FOLLY_NODISCARD detail::ScopeGuardImplDecay<F, true> makeGuard(F&& f) noexcept( noexcept(detail::ScopeGuardImplDecay<F, true>(static_cast<F&&>(f)))) { return detail::ScopeGuardImplDecay<F, true>(static_cast<F&&>(f)); } diff --git a/ios/Pods/Folly/folly/SharedMutex.h b/ios/Pods/Folly/folly/SharedMutex.h index 47f617363..bffa81be1 100644 --- a/ios/Pods/Folly/folly/SharedMutex.h +++ b/ios/Pods/Folly/folly/SharedMutex.h @@ -1,11 +1,11 @@ /* - * Copyright 2015-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -49,7 +49,7 @@ // SharedMutexReadPriority gives priority to readers, // SharedMutexWritePriority gives priority to writers. SharedMutex is an // alias for SharedMutexWritePriority, because writer starvation is more -// likely than reader starvation for the read-heavy workloads targetted +// likely than reader starvation for the read-heavy workloads targeted // by SharedMutex. // // In my tests SharedMutex is as good or better than the other @@ -278,9 +278,9 @@ class SharedMutexImpl { typedef SharedMutexToken Token; - class ReadHolder; - class UpgradeHolder; - class WriteHolder; + class FOLLY_NODISCARD ReadHolder; + class FOLLY_NODISCARD UpgradeHolder; + class FOLLY_NODISCARD WriteHolder; constexpr SharedMutexImpl() noexcept : state_(0) {} @@ -303,25 +303,55 @@ class SharedMutexImpl { cleanupTokenlessSharedDeferred(state); } -#ifndef NDEBUG - // These asserts check that everybody has released the lock before it - // is destroyed. If you arrive here while debugging that is likely - // the problem. (You could also have general heap corruption.) + if (folly::kIsDebug) { + // These asserts check that everybody has released the lock before it + // is destroyed. If you arrive here while debugging that is likely + // the problem. (You could also have general heap corruption.) - // if a futexWait fails to go to sleep because the value has been - // changed, we don't necessarily clean up the wait bits, so it is - // possible they will be set here in a correct system - assert((state & ~(kWaitingAny | kMayDefer | kAnnotationCreated)) == 0); - if ((state & kMayDefer) != 0) { - for (uint32_t slot = 0; slot < kMaxDeferredReaders; ++slot) { - auto slotValue = deferredReader(slot)->load(std::memory_order_relaxed); - assert(!slotValueIsThis(slotValue)); + // if a futexWait fails to go to sleep because the value has been + // changed, we don't necessarily clean up the wait bits, so it is + // possible they will be set here in a correct system + assert((state & ~(kWaitingAny | kMayDefer | kAnnotationCreated)) == 0); + if ((state & kMayDefer) != 0) { + for (uint32_t slot = 0; slot < kMaxDeferredReaders; ++slot) { + auto slotValue = + deferredReader(slot)->load(std::memory_order_relaxed); + assert(!slotValueIsThis(slotValue)); + (void)slotValue; + } } } -#endif annotateDestroy(); } + // Checks if an exclusive lock could succeed so that lock elision could be + // enabled. Different from the two eligible_for_lock_{upgrade|shared}_elision + // functions, this is a conservative check since kMayDefer indicates + // "may-existing" deferred readers. + bool eligible_for_lock_elision() const { + // We rely on the transaction for linearization. Wait bits are + // irrelevant because a successful transaction will be in and out + // without affecting the wakeup. kBegunE is also okay for a similar + // reason. + auto state = state_.load(std::memory_order_relaxed); + return (state & (kHasS | kMayDefer | kHasE | kHasU)) == 0; + } + + // Checks if an upgrade lock could succeed so that lock elision could be + // enabled. + bool eligible_for_lock_upgrade_elision() const { + auto state = state_.load(std::memory_order_relaxed); + return (state & (kHasE | kHasU)) == 0; + } + + // Checks if a shared lock could succeed so that lock elision could be + // enabled. + bool eligible_for_lock_shared_elision() const { + // No need to honor kBegunE because a transaction doesn't block anybody + auto state = state_.load(std::memory_order_relaxed); + return (state & kHasE) == 0; + } + void lock() { WaitForever ctx; (void)lockExclusiveImpl(kHasSolo, ctx); @@ -457,9 +487,9 @@ class SharedMutexImpl { !tryUnlockSharedDeferred(token.slot_)) { unlockSharedInline(); } -#ifndef NDEBUG - token.type_ = Token::Type::INVALID; -#endif + if (folly::kIsDebug) { + token.type_ = Token::Type::INVALID; + } } void unlock_and_lock_shared() { @@ -1299,7 +1329,7 @@ class SharedMutexImpl { } public: - class ReadHolder { + class FOLLY_NODISCARD ReadHolder { ReadHolder() : lock_(nullptr) {} public: @@ -1361,7 +1391,7 @@ class SharedMutexImpl { SharedMutexToken token_; }; - class UpgradeHolder { + class FOLLY_NODISCARD UpgradeHolder { UpgradeHolder() : lock_(nullptr) {} public: @@ -1411,7 +1441,7 @@ class SharedMutexImpl { SharedMutexImpl* lock_; }; - class WriteHolder { + class FOLLY_NODISCARD WriteHolder { WriteHolder() : lock_(nullptr) {} public: diff --git a/ios/Pods/Folly/folly/Singleton-inl.h b/ios/Pods/Folly/folly/Singleton-inl.h index e269239e9..e3e92df66 100644 --- a/ios/Pods/Folly/folly/Singleton-inl.h +++ b/ios/Pods/Folly/folly/Singleton-inl.h @@ -1,11 +1,11 @@ /* - * Copyright 2015-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -20,13 +20,17 @@ namespace detail { template <typename T> template <typename Tag, typename VaultTag> -SingletonHolder<T>& SingletonHolder<T>::singleton() { - /* library-local */ static auto entry = - createGlobal<SingletonHolder<T>, std::pair<Tag, VaultTag>>([]() { - return new SingletonHolder<T>( - {typeid(T), typeid(Tag)}, *SingletonVault::singleton<VaultTag>()); - }); - return *entry; +struct SingletonHolder<T>::Impl : SingletonHolder<T> { + Impl() + : SingletonHolder<T>( + {typeid(T), typeid(Tag)}, + *SingletonVault::singleton<VaultTag>()) {} +}; + +template <typename T> +template <typename Tag, typename VaultTag> +inline SingletonHolder<T>& SingletonHolder<T>::singleton() { + return detail::createGlobal<Impl<Tag, VaultTag>, void>(); } [[noreturn]] void singletonWarnDoubleRegistrationAndAbort( @@ -53,6 +57,8 @@ void SingletonHolder<T>::registerSingleton(CreateFunc c, TeardownFunc t) { * Singleton<int> a([] { return new int(3); }); * Singleton<int> b([] { return new int(4); }); * + * Adding tags should fix this (see documentation in the header). + * */ singletonWarnDoubleRegistrationAndAbort(type()); } @@ -136,6 +142,12 @@ folly::ReadMostlySharedPtr<T> SingletonHolder<T>::try_get_fast() { return instance_weak_fast_.lock(); } +template <typename T> +template <typename Func> +invoke_result_t<Func, T*> detail::SingletonHolder<T>::apply(Func f) { + return f(try_get().get()); +} + template <typename T> void SingletonHolder<T>::vivify() { if (UNLIKELY( @@ -178,7 +190,7 @@ void SingletonHolder<T>::destroyInstance() { template <typename T> SingletonHolder<T>::SingletonHolder( TypeDescriptor typeDesc, - SingletonVault& vault) + SingletonVault& vault) noexcept : SingletonHolderBase(typeDesc), vault_(vault) {} template <typename T> diff --git a/ios/Pods/Folly/folly/Singleton.h b/ios/Pods/Folly/folly/Singleton.h index 970c81aeb..e4dee36bb 100644 --- a/ios/Pods/Folly/folly/Singleton.h +++ b/ios/Pods/Folly/folly/Singleton.h @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + // SingletonVault - a library to manage the creation and destruction // of interdependent singletons. // @@ -130,6 +131,7 @@ #include <folly/experimental/ReadMostlySharedPtr.h> #include <folly/hash/Hash.h> #include <folly/lang/Exception.h> +#include <folly/memory/SanitizeLeak.h> #include <folly/synchronization/Baton.h> #include <folly/synchronization/RWSpinLock.h> @@ -279,7 +281,8 @@ struct SingletonVaultState { // SingletonHolders. class SingletonHolderBase { public: - explicit SingletonHolderBase(TypeDescriptor typeDesc) : type_(typeDesc) {} + explicit SingletonHolderBase(TypeDescriptor typeDesc) noexcept + : type_(typeDesc) {} virtual ~SingletonHolderBase() = default; TypeDescriptor type() const { @@ -311,6 +314,8 @@ struct SingletonHolder : public SingletonHolderBase { inline std::weak_ptr<T> get_weak(); inline std::shared_ptr<T> try_get(); inline folly::ReadMostlySharedPtr<T> try_get_fast(); + template <typename Func> + inline invoke_result_t<Func, T*> apply(Func f); inline void vivify(); void registerSingleton(CreateFunc c, TeardownFunc t); @@ -322,7 +327,10 @@ struct SingletonHolder : public SingletonHolderBase { void destroyInstance() override; private: - SingletonHolder(TypeDescriptor type, SingletonVault& vault); + template <typename Tag, typename VaultTag> + struct Impl; + + SingletonHolder(TypeDescriptor type, SingletonVault& vault) noexcept; enum class SingletonHolderState { NotRegistered, @@ -406,7 +414,8 @@ class SingletonVault { static Type defaultVaultType(); - explicit SingletonVault(Type type = defaultVaultType()) : type_(type) {} + explicit SingletonVault(Type type = defaultVaultType()) noexcept + : type_(type) {} // Destructor is only called by unit tests to check destroyInstances. ~SingletonVault(); @@ -500,17 +509,7 @@ class SingletonVault { // tests only. template <typename VaultTag = detail::DefaultTag> static SingletonVault* singleton() { - /* library-local */ static auto vault = - detail::createGlobal<SingletonVault, VaultTag>(); - return vault; - } - - typedef std::string (*StackTraceGetterPtr)(); - - static std::atomic<StackTraceGetterPtr>& stackTraceGetter() { - /* library-local */ static auto stackTraceGetterPtr = detail:: - createGlobal<std::atomic<StackTraceGetterPtr>, SingletonVault>(); - return *stackTraceGetterPtr; + return &detail::createGlobal<SingletonVault, VaultTag>(); } void setType(Type type) { @@ -603,6 +602,22 @@ class Singleton { return getEntry().try_get_fast(); } + /** + * Applies a callback to the possibly-nullptr singleton instance, returning + * the callback's result. That is, the following two are functionally + * equivalent: + * singleton.apply(std::ref(f)); + * f(singleton.try_get().get()); + * + * For example, the following returns the singleton + * instance directly without any extra operations on the instance: + * auto ret = Singleton<T>::apply([](auto* v) { return v; }); + */ + template <typename Func> + static invoke_result_t<Func, T*> apply(Func f) { + return getEntry().apply(std::ref(f)); + } + // Quickly ensure the instance exists. static void vivify() { getEntry().vivify(); @@ -722,8 +737,7 @@ class LeakySingleton { auto& entry = entryInstance(); if (entry.ptr) { - // Make sure existing pointer doesn't get reported as a leak by LSAN. - entry.leakedPtrs.push_back(std::exchange(entry.ptr, nullptr)); + annotate_object_leaked(std::exchange(entry.ptr, nullptr)); } entry.createFunc = createFunc; entry.state = State::Dead; @@ -733,7 +747,7 @@ class LeakySingleton { enum class State { NotRegistered, Dead, Living }; struct Entry { - Entry() {} + Entry() noexcept {} Entry(const Entry&) = delete; Entry& operator=(const Entry&) = delete; @@ -742,12 +756,10 @@ class LeakySingleton { CreateFunc createFunc; std::mutex mutex; detail::TypeDescriptor type_{typeid(T), typeid(Tag)}; - std::list<T*> leakedPtrs; }; static Entry& entryInstance() { - /* library-local */ static auto entry = detail::createGlobal<Entry, Tag>(); - return *entry; + return detail::createGlobal<Entry, Tag>(); } static T& instance() { diff --git a/ios/Pods/Folly/folly/SingletonThreadLocal.h b/ios/Pods/Folly/folly/SingletonThreadLocal.h index 10d862912..76fa7660a 100644 --- a/ios/Pods/Folly/folly/SingletonThreadLocal.h +++ b/ios/Pods/Folly/folly/SingletonThreadLocal.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -16,13 +16,25 @@ #pragma once -#include <boost/intrusive/list.hpp> +#include <thread> +#include <type_traits> +#include <unordered_map> +#include <unordered_set> #include <folly/ScopeGuard.h> #include <folly/ThreadLocal.h> +#include <folly/detail/Iterators.h> #include <folly/detail/Singleton.h> +#include <folly/detail/UniqueInstance.h> #include <folly/functional/Invoke.h> +// we do not want to use FOLLY_TLS here for mobile +#if !FOLLY_MOBILE && defined(FOLLY_TLS) +#define FOLLY_STL_USE_FOLLY_TLS 1 +#else +#undef FOLLY_STL_USE_FOLLY_TLS +#endif + namespace folly { /// SingletonThreadLocal @@ -61,112 +73,166 @@ template < typename T, typename Tag = detail::DefaultTag, typename Make = detail::DefaultMake<T>, - typename TLTag = _t<std::conditional< - std::is_same<Tag, detail::DefaultTag>::value, - void, - Tag>>> + typename TLTag = std:: + conditional_t<std::is_same<Tag, detail::DefaultTag>::value, void, Tag>> class SingletonThreadLocal { private: + static detail::UniqueInstance unique; + struct Wrapper; - using NodeBase = boost::intrusive::list_base_hook< - boost::intrusive::link_mode<boost::intrusive::auto_unlink>>; - - struct Node : NodeBase { - Wrapper*& cache; - bool& stale; - - Node(Wrapper*& cache_, bool& stale_) : cache(cache_), stale(stale_) { - auto& wrapper = getWrapper(); - wrapper.caches.push_front(*this); - cache = &wrapper; - } - ~Node() { - clear(); - } - - void clear() { - cache = nullptr; - stale = true; - } + struct LocalCache { + Wrapper* cache; }; + static_assert(std::is_pod<LocalCache>::value, "non-pod"); - using List = - boost::intrusive::list<Node, boost::intrusive::constant_time_size<false>>; + struct LocalLifetime; struct Wrapper { - template <typename S> - using MakeRet = is_invocable_r<S, Make>; + using Object = invoke_result_t<Make>; + static_assert(std::is_convertible<Object&, T&>::value, "inconvertible"); + + using LocalCacheSet = std::unordered_set<LocalCache*>; // keep as first field, to save 1 instr in the fast path - union { - alignas(alignof(T)) unsigned char storage[sizeof(T)]; - T object; - }; - List caches; + Object object{Make{}()}; + + // per-cache refcounts, the number of lifetimes tracking that cache + std::unordered_map<LocalCache*, size_t> caches; + + // per-lifetime cache tracking; 1-M lifetimes may track 1-N caches + std::unordered_map<LocalLifetime*, LocalCacheSet> lifetimes; /* implicit */ operator T&() { return object; } - // normal make types - template <typename S = T, _t<std::enable_if<MakeRet<S>::value, int>> = 0> - Wrapper() { - (void)new (storage) S(Make{}()); - } - // default and special make types for non-move-constructible T, until C++17 - template <typename S = T, _t<std::enable_if<!MakeRet<S>::value, int>> = 0> - Wrapper() { - (void)Make{}(storage); - } ~Wrapper() { - for (auto& node : caches) { - node.clear(); + for (auto& kvp : caches) { + kvp.first->cache = nullptr; } - caches.clear(); - object.~T(); } }; using WrapperTL = ThreadLocal<Wrapper, TLTag>; + struct LocalLifetime { + ~LocalLifetime() { + auto& wrapper = getWrapper(); + auto& lifetimes = wrapper.lifetimes[this]; + for (auto cache : lifetimes) { + auto const it = wrapper.caches.find(cache); + if (!--it->second) { + wrapper.caches.erase(it); + cache->cache = nullptr; + } + } + wrapper.lifetimes.erase(this); + } + + void track(LocalCache& cache) { + auto& wrapper = getWrapper(); + cache.cache = &wrapper; + auto const inserted = wrapper.lifetimes[this].insert(&cache); + wrapper.caches[&cache] += inserted.second; + } + }; + SingletonThreadLocal() = delete; - FOLLY_EXPORT FOLLY_NOINLINE static WrapperTL& getWrapperTL() { - static auto& entry = *detail::createGlobal<WrapperTL, Tag>(); - return entry; + FOLLY_ALWAYS_INLINE static WrapperTL& getWrapperTL() { + return detail::createGlobal<WrapperTL, Tag>(); } FOLLY_NOINLINE static Wrapper& getWrapper() { + (void)unique; // force the object not to be thrown out as unused return *getWrapperTL(); } -#ifdef FOLLY_TLS - FOLLY_NOINLINE static T& getSlow(Wrapper*& cache) { - static thread_local Wrapper** check = &cache; - CHECK_EQ(check, &cache) << "inline function static thread_local merging"; - static thread_local bool stale; - static thread_local Node node(cache, stale); - return !stale && node.cache ? *node.cache : getWrapper(); +#ifdef FOLLY_STL_USE_FOLLY_TLS + FOLLY_NOINLINE static Wrapper& getSlow(LocalCache& cache) { + if (threadlocal_detail::StaticMetaBase::dying()) { + return getWrapper(); + } + static thread_local LocalLifetime lifetime; + lifetime.track(cache); // idempotent + return FOLLY_LIKELY(!!cache.cache) ? *cache.cache : getWrapper(); } #endif public: FOLLY_EXPORT FOLLY_ALWAYS_INLINE static T& get() { -#ifdef FOLLY_TLS - static thread_local Wrapper* cache; - return FOLLY_LIKELY(!!cache) ? *cache : getSlow(cache); +#ifdef FOLLY_STL_USE_FOLLY_TLS + static thread_local LocalCache cache; + return FOLLY_LIKELY(!!cache.cache) ? *cache.cache : getSlow(cache); #else return getWrapper(); #endif } + class Accessor { + private: + using Inner = typename WrapperTL::Accessor; + using IteratorBase = typename Inner::Iterator; + using IteratorTag = std::bidirectional_iterator_tag; + + Inner inner_; + + explicit Accessor(Inner inner) noexcept : inner_(std::move(inner)) {} + + public: + friend class SingletonThreadLocal<T, Tag, Make, TLTag>; + + class Iterator + : public detail:: + IteratorAdaptor<Iterator, IteratorBase, T, IteratorTag> { + private: + using Super = + detail::IteratorAdaptor<Iterator, IteratorBase, T, IteratorTag>; + using Super::Super; + + public: + friend class Accessor; + + T& dereference() const { + return const_cast<Iterator*>(this)->base()->object; + } + + std::thread::id getThreadId() const { + return this->base().getThreadId(); + } + + uint64_t getOSThreadId() const { + return this->base().getOSThreadId(); + } + }; + + Accessor(const Accessor&) = delete; + Accessor& operator=(const Accessor&) = delete; + Accessor(Accessor&&) = default; + Accessor& operator=(Accessor&&) = default; + + Iterator begin() const { + return Iterator(inner_.begin()); + } + + Iterator end() const { + return Iterator(inner_.end()); + } + }; + // Must use a unique Tag, takes a lock that is one per Tag - static typename WrapperTL::Accessor accessAllThreads() { - return getWrapperTL().accessAllThreads(); + static Accessor accessAllThreads() { + return Accessor(getWrapperTL().accessAllThreads()); } }; +template <typename T, typename Tag, typename Make, typename TLTag> +detail::UniqueInstance SingletonThreadLocal<T, Tag, Make, TLTag>::unique{ + "folly::SingletonThreadLocal", + tag_t<T, Tag>{}, + tag_t<Make, TLTag>{}}; + } // namespace folly /// FOLLY_DECLARE_REUSED diff --git a/ios/Pods/Folly/folly/SocketAddress.h b/ios/Pods/Folly/folly/SocketAddress.h index bfa5042cd..5c0a33300 100644 --- a/ios/Pods/Folly/folly/SocketAddress.h +++ b/ios/Pods/Folly/folly/SocketAddress.h @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -17,6 +17,8 @@ #pragma once #include <sys/types.h> + +#include <cassert> #include <cstddef> #include <iosfwd> #include <string> @@ -24,6 +26,7 @@ #include <folly/IPAddress.h> #include <folly/Portability.h> #include <folly/Range.h> +#include <folly/net/NetworkSocket.h> #include <folly/portability/Sockets.h> namespace folly { @@ -324,14 +327,14 @@ class SocketAddress { * * Raises std::system_error on error. */ - void setFromPeerAddress(int socket); + void setFromPeerAddress(NetworkSocket socket); /** * Initialize this SocketAddress from a socket's local address. * * Raises std::system_error on error. */ - void setFromLocalAddress(int socket); + void setFromLocalAddress(NetworkSocket socket); /** * Initialize this folly::SocketAddress from a struct sockaddr. @@ -402,7 +405,7 @@ class SocketAddress { socklen_t getActualSize() const; sa_family_t getFamily() const { - DCHECK(external_ || AF_UNIX != storage_.addr.family()); + assert(external_ || AF_UNIX != storage_.addr.family()); return external_ ? sa_family_t(AF_UNIX) : storage_.addr.family(); } @@ -578,9 +581,11 @@ class SocketAddress { struct addrinfo* getAddrInfo(const char* host, uint16_t port, int flags); struct addrinfo* getAddrInfo(const char* host, const char* port, int flags); - void setFromAddrInfo(const struct addrinfo* results); - void setFromLocalAddr(const struct addrinfo* results); - void setFromSocket(int socket, int (*fn)(int, struct sockaddr*, socklen_t*)); + void setFromAddrInfo(const struct addrinfo* info); + void setFromLocalAddr(const struct addrinfo* info); + void setFromSocket( + NetworkSocket socket, + int (*fn)(NetworkSocket, struct sockaddr*, socklen_t*)); std::string getIpString(int flags) const; void getIpString(char* buf, size_t buflen, int flags) const; diff --git a/ios/Pods/Folly/folly/SpinLock.h b/ios/Pods/Folly/folly/SpinLock.h index 333748f2a..9bc7b8daf 100644 --- a/ios/Pods/Folly/folly/SpinLock.h +++ b/ios/Pods/Folly/folly/SpinLock.h @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -34,8 +34,6 @@ #include <type_traits> -#include <boost/noncopyable.hpp> - #include <folly/Portability.h> #include <folly/synchronization/SmallLocks.h> @@ -43,16 +41,16 @@ namespace folly { class SpinLock { public: - FOLLY_ALWAYS_INLINE SpinLock() { + FOLLY_ALWAYS_INLINE SpinLock() noexcept { lock_.init(); } - FOLLY_ALWAYS_INLINE void lock() const { + FOLLY_ALWAYS_INLINE void lock() const noexcept { lock_.lock(); } - FOLLY_ALWAYS_INLINE void unlock() const { + FOLLY_ALWAYS_INLINE void unlock() const noexcept { lock_.unlock(); } - FOLLY_ALWAYS_INLINE bool try_lock() const { + FOLLY_ALWAYS_INLINE bool try_lock() const noexcept { return lock_.try_lock(); } @@ -61,11 +59,17 @@ class SpinLock { }; template <typename LOCK> -class SpinLockGuardImpl : private boost::noncopyable { +class SpinLockGuardImpl { public: - FOLLY_ALWAYS_INLINE explicit SpinLockGuardImpl(LOCK& lock) : lock_(lock) { + FOLLY_ALWAYS_INLINE explicit SpinLockGuardImpl(LOCK& lock) noexcept( + noexcept(lock.lock())) + : lock_(lock) { lock_.lock(); } + + SpinLockGuardImpl(const SpinLockGuardImpl&) = delete; + SpinLockGuardImpl& operator=(const SpinLockGuardImpl&) = delete; + FOLLY_ALWAYS_INLINE ~SpinLockGuardImpl() { lock_.unlock(); } diff --git a/ios/Pods/Folly/folly/String-inl.h b/ios/Pods/Folly/folly/String-inl.h index 63e88c949..04841caa0 100644 --- a/ios/Pods/Folly/folly/String-inl.h +++ b/ios/Pods/Folly/folly/String-inl.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -99,7 +99,7 @@ void cUnescape(StringPiece str, String& out, bool strict) { ++p; if (p == str.end()) { // backslash at end of string if (strict) { - throw std::invalid_argument("incomplete escape sequence"); + throw_exception<std::invalid_argument>("incomplete escape sequence"); } out.push_back('\\'); last = p; @@ -119,7 +119,8 @@ void cUnescape(StringPiece str, String& out, bool strict) { ++p; if (p == str.end()) { // \x at end of string if (strict) { - throw std::invalid_argument("incomplete hex escape sequence"); + throw_exception<std::invalid_argument>( + "incomplete hex escape sequence"); } out.append("\\x"); last = p; @@ -137,7 +138,7 @@ void cUnescape(StringPiece str, String& out, bool strict) { last = p; } else if (e == 'I') { // invalid if (strict) { - throw std::invalid_argument("invalid escape sequence"); + throw_exception<std::invalid_argument>("invalid escape sequence"); } out.push_back('\\'); out.push_back(*p); @@ -209,12 +210,14 @@ void uriUnescape(StringPiece str, String& out, UriEscapeMode mode) { switch (c) { case '%': { if (UNLIKELY(std::distance(p, str.end()) < 3)) { - throw std::invalid_argument("incomplete percent encode sequence"); + throw_exception<std::invalid_argument>( + "incomplete percent encode sequence"); } auto h1 = detail::hexTable[static_cast<unsigned char>(p[1])]; auto h2 = detail::hexTable[static_cast<unsigned char>(p[2])]; if (UNLIKELY(h1 == 16 || h2 == 16)) { - throw std::invalid_argument("invalid percent encode sequence"); + throw_exception<std::invalid_argument>( + "invalid percent encode sequence"); } out.append(&*last, size_t(p - last)); out.push_back((h1 << 4) | h2); @@ -395,7 +398,7 @@ template <class Delim, class String, class OutputType> void split( const Delim& delimiter, const String& input, - fbvector<OutputType>& out, + fbvector<OutputType, std::allocator<OutputType>>& out, bool ignoreEmpty) { detail::internalSplit<OutputType>( detail::prepareDelim(delimiter), diff --git a/ios/Pods/Folly/folly/String.cpp b/ios/Pods/Folly/folly/String.cpp index fd8ae6200..239f841bf 100644 --- a/ios/Pods/Folly/folly/String.cpp +++ b/ios/Pods/Folly/folly/String.cpp @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -81,11 +81,11 @@ struct string_table_c_unescape_make_item { struct string_table_hex_make_item { constexpr unsigned char operator()(std::size_t index) const { // clang-format off - return + return static_cast<unsigned char>( index >= '0' && index <= '9' ? index - '0' : index >= 'a' && index <= 'f' ? index - 'a' + 10 : index >= 'A' && index <= 'F' ? index - 'A' + 10 : - 16; + 16); // clang-format on } }; @@ -416,8 +416,8 @@ std::string prettyPrint(double val, PrettyType type, bool addSpace) { double prettyToDouble( folly::StringPiece* const prettyString, const PrettyType type) { - double value = folly::to<double>(prettyString); - while (prettyString->size() > 0 && std::isspace(prettyString->front())) { + auto value = folly::to<double>(prettyString); + while (!prettyString->empty() && std::isspace(prettyString->front())) { prettyString->advance(1); // Skipping spaces between number and suffix } const PrettySuffix* suffixes = kPrettySuffixes[type]; @@ -460,6 +460,45 @@ std::string hexDump(const void* ptr, size_t size) { return os.str(); } +// There are two variants of `strerror_r` function, one returns +// `int`, and another returns `char*`. Selecting proper version using +// preprocessor macros portably is extremely hard. +// +// For example, on Android function signature depends on `__USE_GNU` and +// `__ANDROID_API__` macros (https://git.io/fjBBE). +// +// So we are using C++ overloading trick: we pass a pointer of +// `strerror_r` to `invoke_strerror_r` function, and C++ compiler +// selects proper function. + +FOLLY_MAYBE_UNUSED +static fbstring invoke_strerror_r( + int (*strerror_r)(int, char*, size_t), + int err, + char* buf, + size_t buflen) { + // Using XSI-compatible strerror_r + int r = strerror_r(err, buf, buflen); + + // OSX/FreeBSD use EINVAL and Linux uses -1 so just check for non-zero + if (r != 0) { + return to<fbstring>( + "Unknown error ", err, " (strerror_r failed with error ", errno, ")"); + } else { + return buf; + } +} + +FOLLY_MAYBE_UNUSED +static fbstring invoke_strerror_r( + char* (*strerror_r)(int, char*, size_t), + int err, + char* buf, + size_t buflen) { + // Using GNU strerror_r + return strerror_r(err, buf, buflen); +} + fbstring errnoStr(int err) { int savedErrno = errno; @@ -484,21 +523,9 @@ fbstring errnoStr(int err) { } else { result.assign(buf); } -#elif FOLLY_HAVE_XSI_STRERROR_R || defined(__APPLE__) - - // Using XSI-compatible strerror_r - int r = strerror_r(err, buf, sizeof(buf)); - - // OSX/FreeBSD use EINVAL and Linux uses -1 so just check for non-zero - if (r != 0) { - result = to<fbstring>( - "Unknown error ", err, " (strerror_r failed with error ", errno, ")"); - } else { - result.assign(buf); - } #else - // Using GNU strerror_r - result.assign(strerror_r(err, buf, sizeof(buf))); + // Using any strerror_r + result.assign(invoke_strerror_r(strerror_r, err, buf, sizeof(buf))); #endif return result; @@ -515,7 +542,7 @@ void toLowerAscii8(char& c) { // by adding 0x20. // Step 1: Clear the high order bit. We'll deal with it in Step 5. - uint8_t rotated = uint8_t(c & 0x7f); + auto rotated = uint8_t(c & 0x7f); // Currently, the value of rotated, as a function of the original c is: // below 'A': 0- 64 // 'A'-'Z': 65- 90 @@ -604,7 +631,7 @@ void toLowerAscii(char* str, size_t length) { // Convert a character at a time until we reach an address that // is at least 32-bit aligned - size_t n = (size_t)str; + auto n = (size_t)str; n &= kAlignMask32; n = std::min(n, length); size_t offset = 0; diff --git a/ios/Pods/Folly/folly/String.h b/ios/Pods/Folly/folly/String.h index efaef2d50..9acd7c745 100644 --- a/ios/Pods/Folly/folly/String.h +++ b/ios/Pods/Folly/folly/String.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -27,7 +27,6 @@ #include <folly/Conv.h> #include <folly/ExceptionString.h> #include <folly/FBString.h> -#include <folly/FBVector.h> #include <folly/Portability.h> #include <folly/Range.h> #include <folly/ScopeGuard.h> @@ -172,7 +171,7 @@ std::string stringPrintf(FOLLY_PRINTF_FORMAT const char* format, ...) FOLLY_PRINTF_FORMAT_ATTR(1, 2); /* Similar to stringPrintf, with different signature. */ -void stringPrintf(std::string* out, FOLLY_PRINTF_FORMAT const char* fmt, ...) +void stringPrintf(std::string* out, FOLLY_PRINTF_FORMAT const char* format, ...) FOLLY_PRINTF_FORMAT_ATTR(2, 3); std::string& stringAppendf( @@ -261,7 +260,7 @@ OutputString hexlify(ByteRange input) { OutputString output; if (!hexlify(input, output)) { // hexlify() currently always returns true, so this can't really happen - throw std::runtime_error("hexlify failed"); + throw_exception<std::runtime_error>("hexlify failed"); } return output; } @@ -284,7 +283,7 @@ OutputString unhexlify(StringPiece input) { if (!unhexlify(input, output)) { // unhexlify() fails if the input has non-hexidecimal characters, // or if it doesn't consist of a whole number of bytes - throw std::domain_error("unhexlify() called with non-hex input"); + throw_exception<std::domain_error>("unhexlify() called with non-hex input"); } return output; } @@ -423,11 +422,14 @@ void split( std::vector<OutputType>& out, const bool ignoreEmpty = false); +template <class T, class Allocator> +class fbvector; + template <class Delim, class String, class OutputType> void split( const Delim& delimiter, const String& input, - folly::fbvector<OutputType>& out, + folly::fbvector<OutputType, std::allocator<OutputType>>& out, const bool ignoreEmpty = false); template < @@ -578,6 +580,41 @@ inline StringPiece skipWhitespace(StringPiece sp) { return ltrimWhitespace(sp); } +/** + * Returns a subpiece with all characters the provided @toTrim returns true + * for removed from the front of @sp. + */ +template <typename ToTrim> +StringPiece ltrim(StringPiece sp, ToTrim toTrim) { + while (!sp.empty() && toTrim(sp.front())) { + sp.pop_front(); + } + + return sp; +} + +/** + * Returns a subpiece with all characters the provided @toTrim returns true + * for removed from the back of @sp. + */ +template <typename ToTrim> +StringPiece rtrim(StringPiece sp, ToTrim toTrim) { + while (!sp.empty() && toTrim(sp.back())) { + sp.pop_back(); + } + + return sp; +} + +/** + * Returns a subpiece with all characters the provided @toTrim returns true + * for removed from the back and front of @sp. + */ +template <typename ToTrim> +StringPiece trim(StringPiece sp, ToTrim toTrim) { + return ltrim(rtrim(sp, std::ref(toTrim)), std::ref(toTrim)); +} + /** * Strips the leading and the trailing whitespace-only lines. Then looks for * the least indented non-whitespace-only line and removes its amount of diff --git a/ios/Pods/Folly/folly/Subprocess.h b/ios/Pods/Folly/folly/Subprocess.h index f88ad7e76..c5c0e3e39 100644 --- a/ios/Pods/Folly/folly/Subprocess.h +++ b/ios/Pods/Folly/folly/Subprocess.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + /** * Subprocess library, modeled after Python's subprocess module * (http://docs.python.org/2/library/subprocess.html) @@ -94,13 +95,9 @@ #include <signal.h> #include <sys/types.h> - -#if __APPLE__ #include <sys/wait.h> -#else -#include <wait.h> -#endif +#include <chrono> #include <exception> #include <string> #include <vector> @@ -215,7 +212,7 @@ class ProcessReturnCode { * Helper function to enforce a precondition based on this. * Throws std::logic_error if in an unexpected state. */ - void enforce(State state) const; + void enforce(State expected) const; private: explicit ProcessReturnCode(int rv) : rawStatus_(rv) {} @@ -386,9 +383,15 @@ class Subprocess { return *this; } -#if __linux__ +#if defined(__linux__) /** - * Child will receive a signal when the parent exits. + * Child will receive a signal when the parent *thread* exits. + * + * This is especially important when this option is used but the calling + * thread does not block for the duration of the subprocess. If the original + * thread that created the subprocess ends then the subprocess will + * terminate. For example, thread pool executors which can reap unused + * threads may trigger this behavior. */ Options& parentDeathSignal(int sig) { parentDeathSignal_ = sig; @@ -406,6 +409,23 @@ class Subprocess { return *this; } + /** + * Detach the spawned process, to allow destroying the Subprocess object + * without waiting for the child process to finish. + * + * This causes the code to fork twice before executing the command. + * The intermediate child process will exit immediately, causing the process + * running the executable to be reparented to init (pid 1). + * + * Subprocess objects created with detach() enabled will already be in an + * "EXITED" state when the constructor returns. The caller should not call + * wait() or poll() on the Subprocess, and pid() will return -1. + */ + Options& detach() { + detach_ = true; + return *this; + } + /** * *** READ THIS WHOLE DOCBLOCK BEFORE USING *** * @@ -443,7 +463,7 @@ class Subprocess { return *this; } -#if __linux__ +#if defined(__linux__) /** * This is an experimental feature, it is best you don't use it at this * point of time. @@ -471,14 +491,15 @@ class Subprocess { FdMap fdActions_; bool closeOtherFds_{false}; bool usePath_{false}; + bool processGroupLeader_{false}; + bool detach_{false}; std::string childDir_; // "" keeps the parent's working directory -#if __linux__ +#if defined(__linux__) int parentDeathSignal_{0}; #endif - bool processGroupLeader_{false}; DangerousPostForkPreExecCallback* dangerousPostForkPreExecCallback_{ nullptr}; -#if __linux__ +#if defined(__linux__) // none means `vfork()` instead of a custom `clone()` // Optional<> is used because value of '0' means do clone without any flags. Optional<clone_flags_t> cloneFlags_; @@ -572,7 +593,7 @@ class Subprocess { /** * Wait for the process to terminate and return its status. Like poll(), * the only exception this can throw is std::logic_error if you call this - * on a Subprocess whose status is RUNNING. Aborts on egregious + * on a Subprocess whose status is not RUNNING. Aborts on egregious * violations of contract, like an out-of-band waitpid(p.pid(), 0, 0). */ ProcessReturnCode wait(); @@ -582,6 +603,16 @@ class Subprocess { */ void waitChecked(); + using TimeoutDuration = std::chrono::milliseconds; + + /** + * Call `waitpid` non-blockingly up to `timeout`. Throws std::logic_error if + * called on a Subprocess whose status is not RUNNING. + * + * The return code will be running() if waiting timed out. + */ + ProcessReturnCode waitTimeout(TimeoutDuration timeout); + /** * Send a signal to the child. Shortcuts for the commonly used Unix * signals are below. @@ -594,6 +625,23 @@ class Subprocess { sendSignal(SIGKILL); } + /** + * Call `waitpid` non-blockingly up to `waitTimeout`. If the process hasn't + * terminated after that, fall back on `terminateOrKill` with + * `sigtermTimeoutSeconds`. + */ + ProcessReturnCode waitOrTerminateOrKill( + TimeoutDuration waitTimeout, + TimeoutDuration sigtermTimeout); + + /** + * Send the SIGTERM to terminate the process, poll `waitpid` non-blockingly + * several times up to `sigtermTimeout`. If the process hasn't terminated + * after that, send SIGKILL to kill the process and call `waitpid` blockingly. + * Return the exit code of process. + */ + ProcessReturnCode terminateOrKill(TimeoutDuration sigtermTimeout); + //// //// The methods below only affect the process's communication pipes, but //// not its return code or state (they do not poll() or wait()). diff --git a/ios/Pods/Folly/folly/Synchronized.h b/ios/Pods/Folly/folly/Synchronized.h index 5833bab2a..e86050de3 100644 --- a/ios/Pods/Folly/folly/Synchronized.h +++ b/ios/Pods/Folly/folly/Synchronized.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + /** * This module implements a Synchronized abstraction useful in * mutex-based concurrency. @@ -83,15 +84,25 @@ class SynchronizedBase; template <class Subclass> class SynchronizedBase<Subclass, detail::MutexLevel::SHARED> { public: - using LockedPtr = ::folly::LockedPtr<Subclass, LockPolicyExclusive>; + using WLockedPtr = ::folly::LockedPtr<Subclass, LockPolicyExclusive>; using ConstWLockedPtr = ::folly::LockedPtr<const Subclass, LockPolicyExclusive>; - using ConstLockedPtr = ::folly::LockedPtr<const Subclass, LockPolicyShared>; + + using RLockedPtr = ::folly::LockedPtr<Subclass, LockPolicyShared>; + using ConstRLockedPtr = ::folly::LockedPtr<const Subclass, LockPolicyShared>; using TryWLockedPtr = ::folly::LockedPtr<Subclass, LockPolicyTryExclusive>; using ConstTryWLockedPtr = ::folly::LockedPtr<const Subclass, LockPolicyTryExclusive>; - using TryRLockedPtr = ::folly::LockedPtr<const Subclass, LockPolicyTryShared>; + + using TryRLockedPtr = ::folly::LockedPtr<Subclass, LockPolicyTryShared>; + using ConstTryRLockedPtr = + ::folly::LockedPtr<const Subclass, LockPolicyTryShared>; + + // These aliases are deprecated. + // TODO: Codemod them away. + using LockedPtr = WLockedPtr; + using ConstLockedPtr = ConstRLockedPtr; /** * Acquire an exclusive lock, and return a LockedPtr that can be used to @@ -103,6 +114,9 @@ class SynchronizedBase<Subclass, detail::MutexLevel::SHARED> { LockedPtr wlock() { return LockedPtr(static_cast<Subclass*>(this)); } + ConstWLockedPtr wlock() const { + return ConstWLockedPtr(static_cast<const Subclass*>(this)); + } /** * Attempts to acquire the lock in exclusive mode. If acquisition is @@ -114,11 +128,18 @@ class SynchronizedBase<Subclass, detail::MutexLevel::SHARED> { TryWLockedPtr tryWLock() { return TryWLockedPtr{static_cast<Subclass*>(this)}; } + ConstTryWLockedPtr tryWLock() const { + return ConstTryWLockedPtr{static_cast<const Subclass*>(this)}; + } /** - * Acquire a read lock, and return a ConstLockedPtr that can be used to - * safely access the datum. + * Acquire a read lock. The returned LockedPtr will have force const + * access to the data unless the lock is acquired in non-const + * context and asNonConstUnsafe() is used. */ + RLockedPtr rlock() { + return RLockedPtr(static_cast<Subclass*>(this)); + } ConstLockedPtr rlock() const { return ConstLockedPtr(static_cast<const Subclass*>(this)); } @@ -130,8 +151,11 @@ class SynchronizedBase<Subclass, detail::MutexLevel::SHARED> { * (Use LockedPtr::operator bool() or LockedPtr::isNull() to check for * validity.) */ - TryRLockedPtr tryRLock() const { - return TryRLockedPtr{static_cast<const Subclass*>(this)}; + TryRLockedPtr tryRLock() { + return TryRLockedPtr{static_cast<Subclass*>(this)}; + } + ConstTryRLockedPtr tryRLock() const { + return ConstTryRLockedPtr{static_cast<const Subclass*>(this)}; } /** @@ -145,6 +169,10 @@ class SynchronizedBase<Subclass, detail::MutexLevel::SHARED> { LockedPtr wlock(const std::chrono::duration<Rep, Period>& timeout) { return LockedPtr(static_cast<Subclass*>(this), timeout); } + template <class Rep, class Period> + LockedPtr wlock(const std::chrono::duration<Rep, Period>& timeout) const { + return LockedPtr(static_cast<const Subclass*>(this), timeout); + } /** * Attempts to acquire the lock, or fails if the timeout elapses first. @@ -154,9 +182,13 @@ class SynchronizedBase<Subclass, detail::MutexLevel::SHARED> { * validity.) */ template <class Rep, class Period> - ConstLockedPtr rlock( + RLockedPtr rlock(const std::chrono::duration<Rep, Period>& timeout) { + return RLockedPtr(static_cast<Subclass*>(this), timeout); + } + template <class Rep, class Period> + ConstRLockedPtr rlock( const std::chrono::duration<Rep, Period>& timeout) const { - return ConstLockedPtr(static_cast<const Subclass*>(this), timeout); + return ConstRLockedPtr(static_cast<const Subclass*>(this), timeout); } /** @@ -177,6 +209,10 @@ class SynchronizedBase<Subclass, detail::MutexLevel::SHARED> { auto withWLock(Function&& function) { return function(*wlock()); } + template <class Function> + auto withWLock(Function&& function) const { + return function(*wlock()); + } /** * Invoke a function while holding the lock exclusively. @@ -191,6 +227,10 @@ class SynchronizedBase<Subclass, detail::MutexLevel::SHARED> { auto withWLockPtr(Function&& function) { return function(wlock()); } + template <class Function> + auto withWLockPtr(Function&& function) const { + return function(wlock()); + } /** * Invoke a function while holding an the lock in shared mode. @@ -203,6 +243,11 @@ class SynchronizedBase<Subclass, detail::MutexLevel::SHARED> { return function(*rlock()); } + template <class Function> + auto withRLockPtr(Function&& function) { + return function(rlock()); + } + template <class Function> auto withRLockPtr(Function&& function) const { return function(rlock()); @@ -214,7 +259,7 @@ class SynchronizedBase<Subclass, detail::MutexLevel::SHARED> { * * This class provides all the functionality provided by the SynchronizedBase * specialization for shared mutexes and a ulock() method that returns an - * upgradable lock RAII proxy + * upgrade lock RAII proxy */ template <class Subclass> class SynchronizedBase<Subclass, detail::MutexLevel::UPGRADE> @@ -230,14 +275,16 @@ class SynchronizedBase<Subclass, detail::MutexLevel::UPGRADE> ::folly::LockedPtr<const Subclass, LockPolicyTryUpgrade>; /** - * Acquire an upgrade lock and return a LockedPtr that can be used to safely - * access the datum - * - * And the const version + * Acquire an upgrade lock. The returned LockedPtr will have force + * const access to the data unless the lock is acquired in non-const + * context and asNonConstUnsafe() is used. */ UpgradeLockedPtr ulock() { return UpgradeLockedPtr(static_cast<Subclass*>(this)); } + ConstUpgradeLockedPtr ulock() const { + return ConstUpgradeLockedPtr(static_cast<const Subclass*>(this)); + } /** * Attempts to acquire the lock in upgrade mode. If acquisition is @@ -285,6 +332,10 @@ class SynchronizedBase<Subclass, detail::MutexLevel::UPGRADE> auto withULock(Function&& function) { return function(*ulock()); } + template <class Function> + auto withULock(Function&& function) const { + return function(*ulock()); + } /** * Invoke a function while holding the lock exclusively. @@ -302,6 +353,10 @@ class SynchronizedBase<Subclass, detail::MutexLevel::UPGRADE> auto withULockPtr(Function&& function) { return function(ulock()); } + template <class Function> + auto withULockPtr(Function&& function) const { + return function(ulock()); + } }; /** @@ -429,10 +484,6 @@ class SynchronizedBase<Subclass, detail::MutexLevel::UNIQUE> { * Supported mutexes that work by default include std::mutex, * std::recursive_mutex, std::timed_mutex, std::recursive_timed_mutex, * folly::SharedMutex, folly::RWSpinLock, and folly::SpinLock. - * Include LockTraitsBoost.h to get additional LockTraits specializations to - * support the following boost mutex types: boost::mutex, - * boost::recursive_mutex, boost::shared_mutex, boost::timed_mutex, and - * boost::recursive_timed_mutex. */ template <class T, class Mutex = SharedMutex> struct Synchronized : public SynchronizedBase< @@ -525,8 +576,8 @@ struct Synchronized : public SynchronizedBase< : Synchronized{std::piecewise_construct, std::move(datumArgs), std::move(mutexArgs), - make_index_sequence<sizeof...(DatumArgs)>{}, - make_index_sequence<sizeof...(MutexArgs)>{}} {} + std::make_index_sequence<sizeof...(DatumArgs)>{}, + std::make_index_sequence<sizeof...(MutexArgs)>{}} {} /** * Copy assignment operator; deprecated @@ -569,7 +620,7 @@ struct Synchronized : public SynchronizedBase< */ Synchronized& operator=(const T& rhs) { if (&datum_ != &rhs) { - auto guard = operator->(); + auto guard = LockedPtr{this}; datum_ = rhs; } return *this; @@ -580,7 +631,7 @@ struct Synchronized : public SynchronizedBase< */ Synchronized& operator=(T&& rhs) { if (&datum_ != &rhs) { - auto guard = operator->(); + auto guard = LockedPtr{this}; datum_ = std::move(rhs); } return *this; @@ -638,7 +689,8 @@ struct Synchronized : public SynchronizedBase< * NOTE: This API is planned to be deprecated in an upcoming diff. * Prefer using lock(), wlock(), or rlock() instead. */ - LockedPtr operator->() { + [[deprecated("use explicit lock(), wlock(), or rlock() instead")]] LockedPtr + operator->() { return LockedPtr(this); } @@ -648,7 +700,9 @@ struct Synchronized : public SynchronizedBase< * NOTE: This API is planned to be deprecated in an upcoming diff. * Prefer using lock(), wlock(), or rlock() instead. */ - ConstLockedPtr operator->() const { + [[deprecated( + "use explicit lock(), wlock(), or rlock() instead")]] ConstLockedPtr + operator->() const { return ConstLockedPtr(this); } @@ -688,8 +742,8 @@ struct Synchronized : public SynchronizedBase< if (this > &rhs) { return rhs.swap(*this); } - auto guard1 = operator->(); - auto guard2 = rhs.operator->(); + auto guard1 = LockedPtr{this}; + auto guard2 = LockedPtr{&rhs}; using std::swap; swap(datum_, rhs.datum_); @@ -718,9 +772,9 @@ struct Synchronized : public SynchronizedBase< /** * Copies datum to a given target. */ - void copy(T* target) const { + void copyInto(T& target) const { ConstLockedPtr guard(this); - *target = datum_; + target = datum_; } /** @@ -731,6 +785,23 @@ struct Synchronized : public SynchronizedBase< return datum_; } + /** + * Returns a reference to the datum without acquiring a lock. + * + * Provided as a backdoor for call-sites where it is known safe to be used. + * For example, when it is known that only one thread has access to the + * Synchronized instance. + * + * To be used with care - this method explicitly overrides the normal safety + * guarantees provided by the rest of the Synchronized API. + */ + T& unsafeGetUnlocked() { + return datum_; + } + const T& unsafeGetUnlocked() const { + return datum_; + } + private: template <class LockedType, class MutexType, class LockPolicy> friend class folly::LockedPtrBase; @@ -761,8 +832,8 @@ struct Synchronized : public SynchronizedBase< std::piecewise_construct_t, std::tuple<DatumArgs...> datumArgs, std::tuple<MutexArgs...> mutexArgs, - index_sequence<IndicesOne...>, - index_sequence<IndicesTwo...>) + std::index_sequence<IndicesOne...>, + std::index_sequence<IndicesTwo...>) : datum_{std::get<IndicesOne>(std::move(datumArgs))...}, mutex_{std::get<IndicesTwo>(std::move(mutexArgs))...} {} @@ -779,9 +850,9 @@ namespace detail { * A helper alias that resolves to "const T" if the template parameter * is a const Synchronized<T>, or "T" if the parameter is not const. */ -template <class SynchronizedType> +template <class SynchronizedType, bool AllowsConcurrentAccess> using SynchronizedDataType = typename std::conditional< - std::is_const<SynchronizedType>::value, + AllowsConcurrentAccess || std::is_const<SynchronizedType>::value, typename SynchronizedType::DataType const, typename SynchronizedType::DataType>::type; /* @@ -1036,7 +1107,7 @@ class LockedPtrBase { } } LockedPtrBase(LockedPtrBase&& rhs) noexcept - : parent_{exchange(rhs.parent_, nullptr)} {} + : parent_{std::exchange(rhs.parent_, nullptr)} {} LockedPtrBase& operator=(LockedPtrBase&& rhs) noexcept { assignImpl(*this, rhs); return *this; @@ -1057,7 +1128,7 @@ class LockedPtrBase { template <typename LockPolicyType> LockedPtrBase( LockedPtrBase<SynchronizedType, Mutex, LockPolicyType>&& rhs) noexcept - : parent_{exchange(rhs.parent_, nullptr)} {} + : parent_{std::exchange(rhs.parent_, nullptr)} {} template <typename LockPolicyType> LockedPtrBase& operator=( LockedPtrBase<SynchronizedType, Mutex, LockPolicyType>&& rhs) noexcept { @@ -1076,7 +1147,7 @@ class LockedPtrBase { LockPolicy::unlock(lhs.parent_->mutex_); } - lhs.parent_ = exchange(rhs.parent_, nullptr); + lhs.parent_ = std::exchange(rhs.parent_, nullptr); } using UnlockerData = SynchronizedType*; @@ -1138,7 +1209,8 @@ class LockedPtrBase<SynchronizedType, std::mutex, LockPolicy> { } LockedPtrBase(LockedPtrBase&& rhs) noexcept - : lock_{std::move(rhs.lock_)}, parent_{exchange(rhs.parent_, nullptr)} {} + : lock_{std::move(rhs.lock_)}, + parent_{std::exchange(rhs.parent_, nullptr)} {} LockedPtrBase& operator=(LockedPtrBase&& rhs) noexcept { assignImpl(*this, rhs); return *this; @@ -1154,7 +1226,7 @@ class LockedPtrBase<SynchronizedType, std::mutex, LockPolicy> { LockedPtrBase(LockedPtrBase<SynchronizedType, std::mutex, LockPolicyType>&& other) noexcept : lock_{std::move(other.lock_)}, - parent_{exchange(other.parent_, nullptr)} {} + parent_{std::exchange(other.parent_, nullptr)} {} template <typename LockPolicyType> LockedPtrBase& operator=( LockedPtrBase<SynchronizedType, std::mutex, LockPolicyType>&& @@ -1172,7 +1244,7 @@ class LockedPtrBase<SynchronizedType, std::mutex, LockPolicy> { LockedPtrBase<SynchronizedType, std::mutex, LockPolicyRhs>& rhs) noexcept { lhs.lock_ = std::move(rhs.lock_); - lhs.parent_ = exchange(rhs.parent_, nullptr); + lhs.parent_ = std::exchange(rhs.parent_, nullptr); } /** @@ -1251,7 +1323,8 @@ class ScopedUnlocker { ScopedUnlocker(const ScopedUnlocker&) = delete; ScopedUnlocker& operator=(const ScopedUnlocker&) = delete; ScopedUnlocker(ScopedUnlocker&& other) noexcept - : ptr_(exchange(other.ptr_, nullptr)), data_(std::move(other.data_)) {} + : ptr_(std::exchange(other.ptr_, nullptr)), + data_(std::move(other.data_)) {} ScopedUnlocker& operator=(ScopedUnlocker&& other) = delete; ~ScopedUnlocker() { @@ -1293,9 +1366,12 @@ class LockedPtr : public LockedPtrBase< SynchronizedType, typename SynchronizedType::MutexType, LockPolicy>; + constexpr static bool AllowsConcurrentAccess = + LockPolicy::allows_concurrent_access; using UnlockerData = typename Base::UnlockerData; // CDataType is the DataType with the appropriate const-qualification - using CDataType = detail::SynchronizedDataType<SynchronizedType>; + using CDataType = + detail::SynchronizedDataType<SynchronizedType, AllowsConcurrentAccess>; // Enable only if the unlock policy of the other LockPolicy is the same as // ours template <typename LockPolicyOther> @@ -1414,6 +1490,34 @@ class LockedPtr : public LockedPtrBase< return this->parent_->datum_; } + /** + * Locks that allow concurrent access (shared, upgrade) force const + * access with the standard accessors even if the Synchronized + * object is non-const. + * + * In some cases non-const access can be needed, for example: + * + * - Under an upgrade lock, to get references that will be mutated + * after upgrading to a write lock. + * + * - Under an read lock, if some mutating operations on the data + * are thread safe (e.g. mutating the value in an associative + * container with reference stability). + * + * asNonConstUnsafe() returns a non-const reference to the data if + * the parent Synchronized object was non-const at the point of lock + * acquisition. + */ + template <typename = void> + DataType& asNonConstUnsafe() const { + static_assert( + AllowsConcurrentAccess && !std::is_const<SynchronizedType>::value, + "asNonConstUnsafe() is only available on non-exclusive locks" + " acquired in a non-const context"); + + return this->parent_->datum_; + } + /** * Temporarily unlock the LockedPtr, and reset it to null. * @@ -1426,8 +1530,8 @@ class LockedPtr : public LockedPtrBase< } /*************************************************************************** - * Upgradable lock methods. - * These are disabled via SFINAE when the mutex is not upgradable + * Upgrade lock methods. + * These are disabled via SFINAE when the mutex is not an upgrade mutex. **************************************************************************/ /** * Move the locked ptr from an upgrade state to an exclusive state. The @@ -1440,7 +1544,7 @@ class LockedPtr : public LockedPtrBase< LockedPtr<SynchronizedType, LockPolicyFromUpgradeToExclusive> moveFromUpgradeToWrite() { return LockedPtr<SynchronizedType, LockPolicyFromUpgradeToExclusive>( - exchange(this->parent_, nullptr)); + std::exchange(this->parent_, nullptr)); } /** @@ -1454,7 +1558,7 @@ class LockedPtr : public LockedPtrBase< LockedPtr<SynchronizedType, LockPolicyFromExclusiveToUpgrade> moveFromWriteToUpgrade() { return LockedPtr<SynchronizedType, LockPolicyFromExclusiveToUpgrade>( - exchange(this->parent_, nullptr)); + std::exchange(this->parent_, nullptr)); } /** @@ -1468,7 +1572,7 @@ class LockedPtr : public LockedPtrBase< LockedPtr<SynchronizedType, LockPolicyFromUpgradeToShared> moveFromUpgradeToRead() { return LockedPtr<SynchronizedType, LockPolicyFromUpgradeToShared>( - exchange(this->parent_, nullptr)); + std::exchange(this->parent_, nullptr)); } /** @@ -1482,7 +1586,7 @@ class LockedPtr : public LockedPtrBase< LockedPtr<SynchronizedType, LockPolicyFromExclusiveToShared> moveFromWriteToRead() { return LockedPtr<SynchronizedType, LockPolicyFromExclusiveToShared>( - exchange(this->parent_, nullptr)); + std::exchange(this->parent_, nullptr)); } }; @@ -1519,6 +1623,10 @@ template <typename D, typename M, typename... Args> auto wlock(Synchronized<D, M>& synchronized, Args&&... args) { return detail::wlock(synchronized, std::forward<Args>(args)...); } +template <typename D, typename M, typename... Args> +auto wlock(const Synchronized<D, M>& synchronized, Args&&... args) { + return detail::wlock(synchronized, std::forward<Args>(args)...); +} template <typename Data, typename Mutex, typename... Args> auto rlock(const Synchronized<Data, Mutex>& synchronized, Args&&... args) { return detail::rlock(synchronized, std::forward<Args>(args)...); @@ -1667,6 +1775,10 @@ void swap(Synchronized<T, M>& lhs, Synchronized<T, M>& rhs) { #define SYNCHRONIZED_VAR(var) FB_CONCATENATE(SYNCHRONIZED_##var##_, __LINE__) /** + * NOTE: This API is deprecated. Use lock(), wlock(), rlock() or the withLock + * functions instead. In the future it will be marked with a deprecation + * attribute to emit build-time warnings, and then it will be removed entirely. + * * SYNCHRONIZED is the main facility that makes Synchronized<T> * helpful. It is a pseudo-statement that introduces a scope where the * object is locked. Inside that scope you get to access the unadorned @@ -1683,27 +1795,32 @@ void swap(Synchronized<T, M>& lhs, Synchronized<T, M>& rhs) { * Refer to folly/docs/Synchronized.md for a detailed explanation and more * examples. */ -#define SYNCHRONIZED(...) \ - FOLLY_PUSH_WARNING \ - FOLLY_GNU_DISABLE_WARNING("-Wshadow") \ - FOLLY_MSVC_DISABLE_WARNING(4189) /* initialized but unreferenced */ \ - FOLLY_MSVC_DISABLE_WARNING(4456) /* declaration hides local */ \ - FOLLY_MSVC_DISABLE_WARNING(4457) /* declaration hides parameter */ \ - FOLLY_MSVC_DISABLE_WARNING(4458) /* declaration hides member */ \ - FOLLY_MSVC_DISABLE_WARNING(4459) /* declaration hides global */ \ - FOLLY_GCC_DISABLE_NEW_SHADOW_WARNINGS \ - if (bool SYNCHRONIZED_VAR(state) = false) { \ - } else \ - for (auto SYNCHRONIZED_VAR(lockedPtr) = \ - (FB_VA_GLUE(FB_ARG_2_OR_1, (__VA_ARGS__))).operator->(); \ - !SYNCHRONIZED_VAR(state); \ - SYNCHRONIZED_VAR(state) = true) \ - for (auto& FB_VA_GLUE(FB_ARG_1, (__VA_ARGS__)) = \ - *SYNCHRONIZED_VAR(lockedPtr).operator->(); \ - !SYNCHRONIZED_VAR(state); \ - SYNCHRONIZED_VAR(state) = true) \ +#define SYNCHRONIZED(...) \ + FOLLY_PUSH_WARNING \ + FOLLY_GNU_DISABLE_WARNING("-Wshadow") \ + FOLLY_MSVC_DISABLE_WARNING(4189) /* initialized but unreferenced */ \ + FOLLY_MSVC_DISABLE_WARNING(4456) /* declaration hides local */ \ + FOLLY_MSVC_DISABLE_WARNING(4457) /* declaration hides parameter */ \ + FOLLY_MSVC_DISABLE_WARNING(4458) /* declaration hides member */ \ + FOLLY_MSVC_DISABLE_WARNING(4459) /* declaration hides global */ \ + FOLLY_GCC_DISABLE_NEW_SHADOW_WARNINGS \ + if (bool SYNCHRONIZED_VAR(state) = false) { \ + } else \ + for (auto SYNCHRONIZED_VAR(lockedPtr) = \ + (FB_VA_GLUE(FB_ARG_2_OR_1, (__VA_ARGS__))).contextualLock(); \ + !SYNCHRONIZED_VAR(state); \ + SYNCHRONIZED_VAR(state) = true) \ + for (auto& FB_VA_GLUE(FB_ARG_1, (__VA_ARGS__)) = \ + *SYNCHRONIZED_VAR(lockedPtr).operator->(); \ + !SYNCHRONIZED_VAR(state); \ + SYNCHRONIZED_VAR(state) = true) \ FOLLY_POP_WARNING +/** + * NOTE: This API is deprecated. Use lock(), wlock(), rlock() or the withLock + * functions instead. In the future it will be marked with a deprecation + * attribute to emit build-time warnings, and then it will be removed entirely. + */ #define TIMED_SYNCHRONIZED(timeout, ...) \ if (bool SYNCHRONIZED_VAR(state) = false) { \ } else \ @@ -1719,6 +1836,10 @@ void swap(Synchronized<T, M>& lhs, Synchronized<T, M>& rhs) { SYNCHRONIZED_VAR(state) = true) /** + * NOTE: This API is deprecated. Use lock(), wlock(), rlock() or the withLock + * functions instead. In the future it will be marked with a deprecation + * attribute to emit build-time warnings, and then it will be removed entirely. + * * Similar to SYNCHRONIZED, but only uses a read lock. */ #define SYNCHRONIZED_CONST(...) \ @@ -1727,6 +1848,10 @@ void swap(Synchronized<T, M>& lhs, Synchronized<T, M>& rhs) { as_const(FB_VA_GLUE(FB_ARG_2_OR_1, (__VA_ARGS__)))) /** + * NOTE: This API is deprecated. Use lock(), wlock(), rlock() or the withLock + * functions instead. In the future it will be marked with a deprecation + * attribute to emit build-time warnings, and then it will be removed entirely. + * * Similar to TIMED_SYNCHRONIZED, but only uses a read lock. */ #define TIMED_SYNCHRONIZED_CONST(timeout, ...) \ @@ -1736,6 +1861,10 @@ void swap(Synchronized<T, M>& lhs, Synchronized<T, M>& rhs) { as_const(FB_VA_GLUE(FB_ARG_2_OR_1, (__VA_ARGS__)))) /** + * NOTE: This API is deprecated. Use lock(), wlock(), rlock() or the withLock + * functions instead. In the future it will be marked with a deprecation + * attribute to emit build-time warnings, and then it will be removed entirely. + * * Synchronizes two Synchronized objects (they may encapsulate * different data). Synchronization is done in increasing address of * object order, so there is no deadlock risk. diff --git a/ios/Pods/Folly/folly/SynchronizedPtr.h b/ios/Pods/Folly/folly/SynchronizedPtr.h index b3790818e..53bb09d98 100644 --- a/ios/Pods/Folly/folly/SynchronizedPtr.h +++ b/ios/Pods/Folly/folly/SynchronizedPtr.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/ThreadCachedInt.h b/ios/Pods/Folly/folly/ThreadCachedInt.h index 2045a0e06..51f2f91a4 100644 --- a/ios/Pods/Folly/folly/ThreadCachedInt.h +++ b/ios/Pods/Folly/folly/ThreadCachedInt.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -24,8 +24,6 @@ #include <atomic> -#include <boost/noncopyable.hpp> - #include <folly/Likely.h> #include <folly/ThreadLocal.h> @@ -36,13 +34,16 @@ namespace folly { // ThreadCachedInt's you should considering breaking up the Tag space even // further. template <class IntT, class Tag = IntT> -class ThreadCachedInt : boost::noncopyable { +class ThreadCachedInt { struct IntCache; public: explicit ThreadCachedInt(IntT initialVal = 0, uint32_t cacheSize = 1000) : target_(initialVal), cacheSize_(cacheSize) {} + ThreadCachedInt(const ThreadCachedInt&) = delete; + ThreadCachedInt& operator=(const ThreadCachedInt&) = delete; + void increment(IntT inc) { auto cache = cache_.get(); if (UNLIKELY(cache == nullptr)) { diff --git a/ios/Pods/Folly/folly/ThreadLocal.h b/ios/Pods/Folly/folly/ThreadLocal.h index be61e84fe..b95df642e 100644 --- a/ios/Pods/Folly/folly/ThreadLocal.h +++ b/ios/Pods/Folly/folly/ThreadLocal.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -41,6 +41,7 @@ #pragma once #include <iterator> +#include <thread> #include <type_traits> #include <utility> @@ -60,13 +61,11 @@ class ThreadLocal { public: constexpr ThreadLocal() : constructor_([]() { return new T(); }) {} - template < - typename F, - _t<std::enable_if<is_invocable_r<T*, F>::value, int>> = 0> + template <typename F, std::enable_if_t<is_invocable_r<T*, F>::value, int> = 0> explicit ThreadLocal(F&& constructor) : constructor_(std::forward<F>(constructor)) {} - FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN T* get() const { + FOLLY_ERASE T* get() const { auto const ptr = tlp_.get(); return FOLLY_LIKELY(!!ptr) ? ptr : makeTlp(); } @@ -138,6 +137,8 @@ class ThreadLocalPtr { private: typedef threadlocal_detail::StaticMeta<Tag, AccessMode> StaticMeta; + using AccessAllThreadsEnabled = Negation<std::is_same<Tag, void>>; + public: constexpr ThreadLocalPtr() : id_() {} @@ -168,12 +169,16 @@ class ThreadLocalPtr { } T* release() { + auto rlock = getAccessAllThreadsLockReadHolderIfEnabled(); + threadlocal_detail::ElementWrapper& w = StaticMeta::get(&id_); return static_cast<T*>(w.release()); } void reset(T* newPtr = nullptr) { + auto rlock = getAccessAllThreadsLockReadHolderIfEnabled(); + auto guard = makeGuard([&] { delete newPtr; }); threadlocal_detail::ElementWrapper* w = &StaticMeta::get(&id_); @@ -226,6 +231,8 @@ class ThreadLocalPtr { */ template <class Deleter> void reset(T* newPtr, const Deleter& deleter) { + auto rlock = getAccessAllThreadsLockReadHolderIfEnabled(); + auto guard = makeGuard([&] { if (newPtr) { deleter(newPtr, TLPDestructionMode::THIS_THREAD); @@ -362,6 +369,14 @@ class ThreadLocalPtr { bool operator!=(Iterator const& rhs) const { return !equal(rhs); } + + std::thread::id getThreadId() const { + return e_->getThreadEntry()->tid(); + } + + uint64_t getOSThreadId() const { + return e_->getThreadEntry()->tid_os; + } }; ~Accessor() { @@ -436,7 +451,7 @@ class ThreadLocalPtr { // elements of this ThreadLocal instance. Holds a global lock for each <Tag> Accessor accessAllThreads() const { static_assert( - !std::is_same<Tag, void>::value, + AccessAllThreadsEnabled::value, "Must use a unique Tag to use the accessAllThreads feature"); return Accessor(id_.getOrAllocate(StaticMeta::instance())); } @@ -450,6 +465,13 @@ class ThreadLocalPtr { ThreadLocalPtr(const ThreadLocalPtr&) = delete; ThreadLocalPtr& operator=(const ThreadLocalPtr&) = delete; + static auto getAccessAllThreadsLockReadHolderIfEnabled() { + return SharedMutex::ReadHolder( + AccessAllThreadsEnabled::value + ? &StaticMeta::instance().accessAllThreadsLock_ + : nullptr); + } + mutable typename StaticMeta::EntryID id_; }; diff --git a/ios/Pods/Folly/folly/TimeoutQueue.h b/ios/Pods/Folly/folly/TimeoutQueue.h index d05389c78..af880c30e 100644 --- a/ios/Pods/Folly/folly/TimeoutQueue.h +++ b/ios/Pods/Folly/folly/TimeoutQueue.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -97,8 +97,7 @@ class TimeoutQueue { int64_t nextExpiration() const; private: - int64_t runInternal(int64_t now, bool runOnce); - // noncopyable + int64_t runInternal(int64_t now, bool onceOnly); TimeoutQueue(const TimeoutQueue&) = delete; TimeoutQueue& operator=(const TimeoutQueue&) = delete; diff --git a/ios/Pods/Folly/folly/TokenBucket.h b/ios/Pods/Folly/folly/TokenBucket.h index 48d87459d..d80d8ebbc 100644 --- a/ios/Pods/Folly/folly/TokenBucket.h +++ b/ios/Pods/Folly/folly/TokenBucket.h @@ -1,11 +1,11 @@ /* - * Copyright 2015-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -19,8 +19,10 @@ #include <algorithm> #include <atomic> #include <chrono> +#include <thread> #include <folly/Likely.h> +#include <folly/Optional.h> #include <folly/concurrency/CacheLocality.h> namespace folly { @@ -34,7 +36,14 @@ namespace folly { * bytes per second and the bytes come in finite packets (bursts). A token * bucket stores up to a fixed number of tokens (the burst size). Some number * of tokens are removed when an event occurs. The tokens are replenished at a - * fixed rate. + * fixed rate. Failure to allocate tokens implies resource is unavailable and + * caller needs to implement its own retry mechanism. For simple cases where + * caller is okay with a FIFO starvation-free scheduling behavior, there are + * also APIs to 'borrow' from the future effectively assigning a start time to + * the caller when it should proceed with using the resource. It is also + * possible to 'return' previously allocated tokens to make them available to + * other users. Returns in excess of burstSize are considered expired and + * will not be available to later callers. * * This implementation records the last time it was updated. This allows the * token bucket to add tokens "just in time" when tokens are requested. @@ -97,9 +106,8 @@ class BasicDynamicTokenBucket { * Returns the current time in seconds since Epoch. */ static double defaultClockNow() noexcept { - using dur = std::chrono::duration<double>; auto const now = Clock::now().time_since_epoch(); - return std::chrono::duration_cast<dur>(now).count(); + return std::chrono::duration<double>(now).count(); } /** @@ -126,6 +134,10 @@ class BasicDynamicTokenBucket { assert(rate > 0); assert(burstSize > 0); + if (nowInSeconds <= zeroTime_.load()) { + return 0; + } + return consumeImpl( rate, burstSize, nowInSeconds, [toConsume](double& tokens) { if (tokens < toConsume) { @@ -159,6 +171,10 @@ class BasicDynamicTokenBucket { assert(rate > 0); assert(burstSize > 0); + if (nowInSeconds <= zeroTime_.load()) { + return 0; + } + double consumed; consumeImpl( rate, burstSize, nowInSeconds, [&consumed, toConsume](double& tokens) { @@ -174,6 +190,83 @@ class BasicDynamicTokenBucket { return consumed; } + /** + * Return extra tokens back to the bucket. This will move the zeroTime_ + * value back based on the rate. + * + * Thread-safe. + */ + void returnTokens(double tokensToReturn, double rate) { + assert(rate > 0); + assert(tokensToReturn > 0); + + returnTokensImpl(tokensToReturn, rate); + } + + /** + * Like consumeOrDrain but the call will always satisfy the asked for count. + * It does so by borrowing tokens from the future (zeroTime_ will move + * forward) if the currently available count isn't sufficient. + * + * Returns a folly::Optional<double>. The optional wont be set if the request + * cannot be satisfied: only case is when it is larger than burstSize. The + * value of the optional is a double indicating the time in seconds that the + * caller needs to wait at which the reservation becomes valid. The caller + * could simply sleep for the returned duration to smooth out the allocation + * to match the rate limiter or do some other computation in the meantime. In + * any case, any regular consume or consumeOrDrain calls will fail to allocate + * any tokens until the future time is reached. + * + * Note: It is assumed the caller will not ask for a very large count nor use + * it immediately (if not waiting inline) as that would break the burst + * prevention the limiter is meant to be used for. + * + * Thread-safe. + */ + Optional<double> consumeWithBorrowNonBlocking( + double toConsume, + double rate, + double burstSize, + double nowInSeconds = defaultClockNow()) { + assert(rate > 0); + assert(burstSize > 0); + + if (burstSize < toConsume) { + return folly::none; + } + + while (toConsume > 0) { + double consumed = + consumeOrDrain(toConsume, rate, burstSize, nowInSeconds); + if (consumed > 0) { + toConsume -= consumed; + } else { + double zeroTimeNew = returnTokensImpl(-toConsume, rate); + double napTime = std::max(0.0, zeroTimeNew - nowInSeconds); + return napTime; + } + } + return 0; + } + + /** + * Convenience wrapper around non-blocking borrow to sleep inline until + * reservation is valid. + */ + bool consumeWithBorrowAndWait( + double toConsume, + double rate, + double burstSize, + double nowInSeconds = defaultClockNow()) { + auto res = + consumeWithBorrowNonBlocking(toConsume, rate, burstSize, nowInSeconds); + if (res.value_or(0) > 0) { + int64_t napUSec = res.value() * 1000000; + std::this_thread::sleep_for(std::chrono::microseconds(napUSec)); + } + return res.has_value(); + } + /** * Returns the number of tokens currently available. * @@ -186,7 +279,11 @@ class BasicDynamicTokenBucket { assert(rate > 0); assert(burstSize > 0); - return std::min((nowInSeconds - this->zeroTime_) * rate, burstSize); + double zt = this->zeroTime_.load(); + if (nowInSeconds <= zt) { + return 0; + } + return std::min((nowInSeconds - zt) * rate, burstSize); } private: @@ -210,6 +307,21 @@ class BasicDynamicTokenBucket { return true; } + /** + * Adjust zeroTime based on rate and tokenCount and return the new value of + * zeroTime_. Note: Token count can be negative to move the zeroTime_ value + * into the future. + */ + double returnTokensImpl(double tokenCount, double rate) { + auto zeroTimeOld = zeroTime_.load(); + double zeroTimeNew; + do { + zeroTimeNew = zeroTimeOld - tokenCount / rate; + } while ( + UNLIKELY(!zeroTime_.compare_exchange_weak(zeroTimeOld, zeroTimeNew))); + return zeroTimeNew; + } + alignas(hardware_destructive_interference_size) std::atomic<double> zeroTime_; }; @@ -339,6 +451,34 @@ class BasicTokenBucket { toConsume, rate_, burstSize_, nowInSeconds); } + /** + * Returns extra token back to the bucket. + */ + void returnTokens(double tokensToReturn) { + return tokenBucket_.returnTokens(tokensToReturn, rate_); + } + + /** + * Reserve tokens and return time to wait for in order for the reservation to + * be compatible with the bucket configuration. + */ + Optional<double> consumeWithBorrowNonBlocking( + double toConsume, + double nowInSeconds = defaultClockNow()) { + return tokenBucket_.consumeWithBorrowNonBlocking( + toConsume, rate_, burstSize_, nowInSeconds); + } + + /** + * Reserve tokens. Blocks if need be until reservation is satisfied. + */ + bool consumeWithBorrowAndWait( + double toConsume, + double nowInSeconds = defaultClockNow()) { + return tokenBucket_.consumeWithBorrowAndWait( + toConsume, rate_, burstSize_, nowInSeconds); + } + /** * Returns the number of tokens currently available. * diff --git a/ios/Pods/Folly/folly/Traits.h b/ios/Pods/Folly/folly/Traits.h index 9fd77a7d1..2a3bd4ccd 100644 --- a/ios/Pods/Folly/folly/Traits.h +++ b/ios/Pods/Folly/folly/Traits.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -21,21 +21,11 @@ #include <functional> #include <limits> #include <memory> +#include <tuple> #include <type_traits> #include <folly/Portability.h> -// libc++ doesn't provide this header, nor does msvc -#if __has_include(<bits/c++config.h>) -// This file appears in two locations: inside fbcode and in the -// libstdc++ source code (when embedding fbstring as std::string). -// To aid in this schizophrenic use, two macros are defined in -// c++config.h: -// _LIBSTDCXX_FBSTRING - Set inside libstdc++. This is useful to -// gate use inside fbcode v. libstdc++ -#include <bits/c++config.h> -#endif - #define FOLLY_CREATE_HAS_MEMBER_TYPE_TRAITS(classname, type_name) \ template <typename TTheClass_> \ struct classname##__folly_traits_impl__ { \ @@ -134,6 +124,16 @@ namespace folly { +template <typename...> +struct tag_t {}; + +#if __cplusplus >= 201703L + +template <typename... T> +inline constexpr tag_t<T...> tag; + +#endif + #if __cpp_lib_bool_constant || _MSC_VER using std::bool_constant; @@ -149,6 +149,64 @@ using bool_constant = std::integral_constant<bool, B>; template <std::size_t I> using index_constant = std::integral_constant<std::size_t, I>; +namespace detail { + +/** + * A type trait to check if a given type is an instantiation of a class + * template. + * + * Note that this only works with template type parameters. It does not work + * with non-type template parameters, template template parameters, or alias + * templates. + */ +template <template <typename...> class, typename> +struct is_instantiation_of : std::false_type {}; +template <template <typename...> class C, typename... T> +struct is_instantiation_of<C, C<T...>> : std::true_type {}; +template <template <typename...> class C, typename T> +constexpr bool is_instantiation_of_v = is_instantiation_of<C, T>::value; + +} // namespace detail + +namespace detail { + +template <bool, typename T> +struct is_constexpr_default_constructible_; +template <typename T> +struct is_constexpr_default_constructible_<false, T> { + using type = std::false_type; +}; +template <typename T> +struct is_constexpr_default_constructible_<true, T> { + static constexpr int take(T) { + return 0; + } + template <int = take(T{})> + static std::true_type sfinae(int); + static std::false_type sfinae(...); + using type = decltype(sfinae(0)); +}; + +} // namespace detail + +// is_constexpr_default_constructible +// is_constexpr_default_constructible_v +// +// A type trait, with associated variable template, which determines whether +// its type parameter is constexpr default-constructible, that is, default- +// constructible in a constexpr context. +// +// Instantiations of is_constexpr_default_constructible unambiguously inherit +// std::integral_constant<bool, V> for some bool V. +template <typename T> +struct is_constexpr_default_constructible + : detail::is_constexpr_default_constructible_< + std::is_default_constructible<T>::value, + T>::type {}; +template <typename T> +FOLLY_INLINE_VARIABLE constexpr bool is_constexpr_default_constructible_v = + is_constexpr_default_constructible<T>::value; + /*** * _t * @@ -301,18 +359,23 @@ using type_t = typename traits_detail::type_t_<T, Ts...>::type; template <class... Ts> using void_t = type_t<void, Ts...>; +template <typename T> +using aligned_storage_for_t = + typename std::aligned_storage<sizeof(T), alignof(T)>::type; + // Older versions of libstdc++ do not provide std::is_trivially_copyable #if defined(__clang__) && !defined(_LIBCPP_VERSION) template <class T> struct is_trivially_copyable : bool_constant<__is_trivially_copyable(T)> {}; -#elif defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5 -template <class T> -struct is_trivially_copyable : std::is_trivial<T> {}; #else template <class T> using is_trivially_copyable = std::is_trivially_copyable<T>; #endif +template <class T> +FOLLY_INLINE_VARIABLE constexpr bool is_trivially_copyable_v = + is_trivially_copyable<T>::value; + /** * IsRelocatable<T>::value describes the ability of moving around * memory a value of type T by using memcpy (as opposed to the @@ -415,15 +478,15 @@ struct IsLessThanComparable namespace traits_detail_IsNothrowSwappable { #if defined(__cpp_lib_is_swappable) || (_CPPLIB_VER && _HAS_CXX17) -// MSVC 2015+ already implements the C++17 P0185R1 proposal which -// adds std::is_nothrow_swappable, so use it instead if C++17 mode -// is enabled. +// MSVC already implements the C++17 P0185R1 proposal which adds +// std::is_nothrow_swappable, so use it instead if C++17 mode is +// enabled. template <typename T> using IsNothrowSwappable = std::is_nothrow_swappable<T>; #elif _CPPLIB_VER -// MSVC 2015+ defines the base even if C++17 is disabled, and -// MSVC 2015 has issues with our fallback implementation due to -// over-eager evaluation of noexcept. +// MSVC defines the base even if C++17 is disabled, and MSVC has +// issues with our fallback implementation due to over-eager +// evaluation of noexcept. template <typename T> using IsNothrowSwappable = std::_Is_nothrow_swappable<T>; #else @@ -454,6 +517,31 @@ struct IsZeroInitializable traits_detail::has_true_IsZeroInitializable<T>, bool_constant<!std::is_class<T>::value>>::type {}; +namespace detail { +template <bool> +struct conditional_; +template <> +struct conditional_<false> { + template <typename, typename T> + using apply = T; +}; +template <> +struct conditional_<true> { + template <typename T, typename> + using apply = T; +}; +} // namespace detail + +// conditional_t +// +// Like std::conditional_t but with only two total class template instances, +// rather than as many class template instances as there are uses. +// +// As one effect, the result can be used in deducible contexts, allowing +// deduction of conditional_t<V, T, F> to work when T or F is a template param. +template <bool V, typename T, typename F> +using conditional_t = typename detail::conditional_<V>::template apply<T, F>; + template <typename...> struct Conjunction : std::true_type {}; template <typename T> @@ -491,6 +579,21 @@ struct StrictDisjunction : Negation< std::is_same<Bools<Ts::value...>, Bools<(Ts::value && false)...>>> {}; +namespace detail { +template <typename, typename> +struct is_transparent_ : std::false_type {}; +template <typename T> +struct is_transparent_<void_t<typename T::is_transparent>, T> : std::true_type { +}; +} // namespace detail + +// is_transparent +// +// To test whether a less, equal-to, or hash type follows the is-transparent +// protocol used by containers with optional heterogeneous access. +template <typename T> +struct is_transparent : detail::is_transparent_<void, T> {}; + } // namespace folly /** @@ -564,39 +667,6 @@ struct StrictDisjunction FOLLY_ASSUME_RELOCATABLE(__VA_ARGS__<T1, T2, T3, T4>); \ } -/** - * Instantiate FOLLY_ASSUME_FBVECTOR_COMPATIBLE for a few types. It is - * safe to assume that pair is compatible if both of its components - * are. Furthermore, all STL containers can be assumed to comply, - * although that is not guaranteed by the standard. - */ - -FOLLY_NAMESPACE_STD_BEGIN - -template <class T, class U> -struct pair; -#ifndef _GLIBCXX_USE_FB -FOLLY_GLIBCXX_NAMESPACE_CXX11_BEGIN -template <class T, class R, class A> -class basic_string; -FOLLY_GLIBCXX_NAMESPACE_CXX11_END -#else -template <class T, class R, class A, class S> -class basic_string; -#endif -template <class T, class A> -class vector; -template <class T, class A> -class deque; -template <class T, class C, class A> -class set; -template <class K, class V, class C, class A> -class map; -template <class T> -class shared_ptr; - -FOLLY_NAMESPACE_STD_END - namespace folly { // STL commonly-used types @@ -620,29 +690,14 @@ using IsOneOf = StrictDisjunction<std::is_same<T, Ts>...>; namespace detail { -template <typename T, bool> -struct is_negative_impl { - constexpr static bool check(T x) { - return x < 0; - } -}; - -template <typename T> -struct is_negative_impl<T, false> { - constexpr static bool check(T) { - return false; - } -}; - // folly::to integral specializations can end up generating code // inside what are really static ifs (not executed because of the templated // types) that violate -Wsign-compare and/or -Wbool-compare so suppress them // in order to not prevent all calling code from using it. FOLLY_PUSH_WARNING FOLLY_GNU_DISABLE_WARNING("-Wsign-compare") -#if __GNUC_PREREQ(5, 0) -FOLLY_GNU_DISABLE_WARNING("-Wbool-compare") -#endif +FOLLY_GCC_DISABLE_WARNING("-Wbool-compare") +FOLLY_MSVC_DISABLE_WARNING(4287) // unsigned/negative constant mismatch FOLLY_MSVC_DISABLE_WARNING(4388) // sign-compare FOLLY_MSVC_DISABLE_WARNING(4804) // bool-compare @@ -673,7 +728,7 @@ FOLLY_POP_WARNING // same as `x < 0` template <typename T> constexpr bool is_negative(T x) { - return folly::detail::is_negative_impl<T, std::is_signed<T>::value>::check(x); + return std::is_signed<T>::value && x < T(0); } // same as `x <= 0` @@ -710,15 +765,8 @@ bool greater_than(LHS const lhs) { // Assume nothing when compiling with MSVC. #ifndef _MSC_VER -// gcc-5.0 changed string's implementation in libstdc++ to be non-relocatable -#if !_GLIBCXX_USE_CXX11_ABI -FOLLY_ASSUME_FBVECTOR_COMPATIBLE_3(std::basic_string) -#endif -FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(std::vector) -FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(std::deque) FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(std::unique_ptr) FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(std::shared_ptr) -FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(std::function) #endif /* Some combinations of compilers and C++ libraries make __int128 and @@ -762,3 +810,23 @@ template <> struct is_unsigned<unsigned __int128> : ::std::true_type {}; FOLLY_NAMESPACE_STD_END #endif // FOLLY_SUPPLY_MISSING_INT128_TRAITS + +namespace folly { + +/** + * Extension point for containers to provide an order such that if entries are + * inserted into a new instance in that order, iteration order of the new + * instance matches the original's. This can be useful for containers that have + * defined but non-FIFO iteration order, such as F14Vector*. + * + * Should return an iterable view (a type that provides begin() and end()). + * + * Containers should provide overloads in their own namespace; resolution is + * expected to be done via ADL. + */ +template <typename Container> +const Container& order_preserving_reinsertion_view(const Container& container) { + return container; +} + +} // namespace folly diff --git a/ios/Pods/Folly/folly/Try-inl.h b/ios/Pods/Folly/folly/Try-inl.h index c7a801044..f0e29a70b 100644 --- a/ios/Pods/Folly/folly/Try-inl.h +++ b/ios/Pods/Folly/folly/Try-inl.h @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -21,6 +21,7 @@ #include <stdexcept> #include <tuple> +#include <utility> namespace folly { @@ -167,6 +168,7 @@ void Try<T>::throwIfFailed() const { return; case Contains::EXCEPTION: e_.throw_exception(); + case Contains::NOTHING: default: throw_exception<UsingUninitializedTry>(); } @@ -174,7 +176,7 @@ void Try<T>::throwIfFailed() const { template <class T> void Try<T>::destroy() noexcept { - auto oldContains = folly::exchange(contains_, Contains::NOTHING); + auto oldContains = std::exchange(contains_, Contains::NOTHING); if (LIKELY(oldContains == Contains::VALUE)) { value_.~T(); } else if (UNLIKELY(oldContains == Contains::EXCEPTION)) { @@ -220,7 +222,7 @@ template <typename F> typename std::enable_if< !std::is_same<invoke_result_t<F>, void>::value, Try<invoke_result_t<F>>>::type -makeTryWith(F&& f) { +makeTryWithNoUnwrap(F&& f) { using ResultType = invoke_result_t<F>; try { return Try<ResultType>(f()); @@ -234,7 +236,7 @@ makeTryWith(F&& f) { template <typename F> typename std:: enable_if<std::is_same<invoke_result_t<F>, void>::value, Try<void>>::type - makeTryWith(F&& f) { + makeTryWithNoUnwrap(F&& f) { try { f(); return Try<void>(); @@ -245,6 +247,27 @@ typename std:: } } +template <typename F> +typename std:: + enable_if<!isTry<invoke_result_t<F>>::value, Try<invoke_result_t<F>>>::type + makeTryWith(F&& f) { + return makeTryWithNoUnwrap(std::forward<F>(f)); +} + +template <typename F> +typename std::enable_if<isTry<invoke_result_t<F>>::value, invoke_result_t<F>>:: + type + makeTryWith(F&& f) { + using ResultType = invoke_result_t<F>; + try { + return f(); + } catch (std::exception& e) { + return ResultType(exception_wrapper(std::current_exception(), e)); + } catch (...) { + return ResultType(exception_wrapper(std::current_exception())); + } +} + template <typename T, typename... Args> T* tryEmplace(Try<T>& t, Args&&... args) noexcept { try { @@ -309,7 +332,7 @@ struct RemoveTry<TupleType<folly::Try<Types>...>> { }; template <std::size_t... Indices, typename Tuple> -auto unwrapTryTupleImpl(folly::index_sequence<Indices...>, Tuple&& instance) { +auto unwrapTryTupleImpl(std::index_sequence<Indices...>, Tuple&& instance) { using std::get; using ReturnType = typename RemoveTry<typename std::decay<Tuple>::type>::type; return ReturnType{(get<Indices>(std::forward<Tuple>(instance)).value())...}; @@ -319,7 +342,7 @@ auto unwrapTryTupleImpl(folly::index_sequence<Indices...>, Tuple&& instance) { template <typename Tuple> auto unwrapTryTuple(Tuple&& instance) { using TupleDecayed = typename std::decay<Tuple>::type; - using Seq = folly::make_index_sequence<std::tuple_size<TupleDecayed>::value>; + using Seq = std::make_index_sequence<std::tuple_size<TupleDecayed>::value>; return try_detail::unwrapTryTupleImpl(Seq{}, std::forward<Tuple>(instance)); } diff --git a/ios/Pods/Folly/folly/Try.h b/ios/Pods/Folly/folly/Try.h index e6ba72adb..5404ec2ea 100644 --- a/ios/Pods/Folly/folly/Try.h +++ b/ios/Pods/Folly/folly/Try.h @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #pragma once #include <folly/ExceptionWrapper.h> @@ -585,6 +586,12 @@ class Try<void> { }; }; +template <typename T> +struct isTry : std::false_type {}; + +template <typename T> +struct isTry<Try<T>> : std::true_type {}; + /* * @param f a function to execute and capture the result of (value or exception) * @@ -594,7 +601,7 @@ template <typename F> typename std::enable_if< !std::is_same<invoke_result_t<F>, void>::value, Try<invoke_result_t<F>>>::type -makeTryWith(F&& f); +makeTryWithNoUnwrap(F&& f); /* * Specialization of makeTryWith for void return @@ -606,6 +613,30 @@ makeTryWith(F&& f); template <typename F> typename std:: enable_if<std::is_same<invoke_result_t<F>, void>::value, Try<void>>::type + makeTryWithNoUnwrap(F&& f); + +/* + * @param f a function to execute and capture the result of (value or exception) + * + * @returns Try holding the result of f + */ +template <typename F> +typename std:: + enable_if<!isTry<invoke_result_t<F>>::value, Try<invoke_result_t<F>>>::type + makeTryWith(F&& f); + +/* + * Specialization of makeTryWith for functions that return Try<T> + * Causes makeTryWith to not double-wrap the try. + * + * @param f a function to execute and capture the result of + * + * @returns result of f if f did not throw. Otherwise Try<T> containing + * exception + */ +template <typename F> +typename std::enable_if<isTry<invoke_result_t<F>>::value, invoke_result_t<F>>:: + type makeTryWith(F&& f); /* diff --git a/ios/Pods/Folly/folly/UTF8String.h b/ios/Pods/Folly/folly/UTF8String.h index 01f6df450..17333764b 100644 --- a/ios/Pods/Folly/folly/UTF8String.h +++ b/ios/Pods/Folly/folly/UTF8String.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/Unicode.cpp b/ios/Pods/Folly/folly/Unicode.cpp index dfb38a882..e75864520 100644 --- a/ios/Pods/Folly/folly/Unicode.cpp +++ b/ios/Pods/Folly/folly/Unicode.cpp @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/Unicode.h b/ios/Pods/Folly/folly/Unicode.h index dd8c73609..bafe63854 100644 --- a/ios/Pods/Folly/folly/Unicode.h +++ b/ios/Pods/Folly/folly/Unicode.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/Unit.h b/ios/Pods/Folly/folly/Unit.h index 2e4277787..45ce444f5 100644 --- a/ios/Pods/Folly/folly/Unit.h +++ b/ios/Pods/Folly/folly/Unit.h @@ -1,11 +1,11 @@ /* - * Copyright 2015-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/Uri-inl.h b/ios/Pods/Folly/folly/Uri-inl.h index b5b741ed6..bd286f525 100644 --- a/ios/Pods/Folly/folly/Uri-inl.h +++ b/ios/Pods/Folly/folly/Uri-inl.h @@ -1,11 +1,11 @@ /* - * Copyright 2013-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/Uri.h b/ios/Pods/Folly/folly/Uri.h index d08c57d59..a8bfa63b3 100644 --- a/ios/Pods/Folly/folly/Uri.h +++ b/ios/Pods/Folly/folly/Uri.h @@ -1,11 +1,11 @@ /* - * Copyright 2013-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/Utility.h b/ios/Pods/Folly/folly/Utility.h index 1e3e10a52..22c28c910 100644 --- a/ios/Pods/Folly/folly/Utility.h +++ b/ios/Pods/Folly/folly/Utility.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -22,6 +22,7 @@ #include <utility> #include <folly/CPortability.h> +#include <folly/Portability.h> #include <folly/Traits.h> namespace folly { @@ -51,7 +52,7 @@ namespace folly { * Note: If passed an rvalue, invokes the move-ctor, not the copy-ctor. This * can be used to to force a move, where just using std::move would not: * - * std::copy(std::move(data)); // force-move, not just a cast to && + * folly::copy(std::move(data)); // force-move, not just a cast to && * * Note: The following text appears in the standard: * @@ -86,7 +87,7 @@ constexpr typename std::decay<T>::type copy(T&& value) noexcept( * * Like C++17's std::as_const. See http://wg21.link/p0007 */ -#if __cpp_lib_as_const || _MSC_VER +#if __cpp_lib_as_const || _LIBCPP_STD_VER > 14 || _MSC_VER /* using override */ using std::as_const; @@ -108,108 +109,6 @@ constexpr like_t<Src, Dst>&& forward_like(Dst&& dst) noexcept { return static_cast<like_t<Src, Dst>&&>(std::forward<Dst>(dst)); } -#if __cpp_lib_exchange_function || _LIBCPP_STD_VER > 11 || _MSC_VER - -/* using override */ using std::exchange; - -#else - -// mimic: std::exchange, C++14 -// from: http://en.cppreference.com/w/cpp/utility/exchange, CC-BY-SA -template <class T, class U = T> -T exchange(T& obj, U&& new_value) { - T old_value = std::move(obj); - obj = std::forward<U>(new_value); - return old_value; -} - -#endif - -namespace utility_detail { -template <typename...> -struct make_seq_cat; -template < - template <typename T, T...> class S, - typename T, - T... Ta, - T... Tb, - T... Tc> -struct make_seq_cat<S<T, Ta...>, S<T, Tb...>, S<T, Tc...>> { - using type = - S<T, - Ta..., - (sizeof...(Ta) + Tb)..., - (sizeof...(Ta) + sizeof...(Tb) + Tc)...>; -}; - -// Not parameterizing by `template <typename T, T...> class, typename` because -// clang precisely v4.0 fails to compile that. Note that clang v3.9 and v5.0 -// handle that code correctly. -// -// For this to work, `S0` is required to be `Sequence<T>` and `S1` is required -// to be `Sequence<T, 0>`. - -template <std::size_t Size> -struct make_seq { - template <typename S0, typename S1> - using apply = typename make_seq_cat< - typename make_seq<Size / 2>::template apply<S0, S1>, - typename make_seq<Size / 2>::template apply<S0, S1>, - typename make_seq<Size % 2>::template apply<S0, S1>>::type; -}; -template <> -struct make_seq<1> { - template <typename S0, typename S1> - using apply = S1; -}; -template <> -struct make_seq<0> { - template <typename S0, typename S1> - using apply = S0; -}; -} // namespace utility_detail - -#if __cpp_lib_integer_sequence || _MSC_VER - -/* using override */ using std::index_sequence; -/* using override */ using std::integer_sequence; - -#else - -// TODO: Remove after upgrading to C++14 baseline - -template <class T, T... Ints> -struct integer_sequence { - using value_type = T; - - static constexpr std::size_t size() noexcept { - return sizeof...(Ints); - } -}; - -template <std::size_t... Ints> -using index_sequence = integer_sequence<std::size_t, Ints...>; - -#endif - -#if FOLLY_HAS_BUILTIN(__make_integer_seq) || _MSC_FULL_VER >= 190023918 - -template <typename T, std::size_t Size> -using make_integer_sequence = __make_integer_seq<integer_sequence, T, Size>; - -#else - -template <typename T, std::size_t Size> -using make_integer_sequence = typename utility_detail::make_seq< - Size>::template apply<integer_sequence<T>, integer_sequence<T, 0>>; - -#endif - -template <std::size_t Size> -using make_index_sequence = make_integer_sequence<std::size_t, Size>; -template <class... T> -using index_sequence_for = make_index_sequence<sizeof...(T)>; - /** * Backports from C++17 of: * std::in_place_t @@ -250,7 +149,7 @@ inline in_place_index_tag<I> in_place_index(in_place_index_tag<I> = {}) { * construction. * * Further standard conforming compilers *strongly* favor an - * std::initalizer_list overload for construction if one exists. The + * std::initializer_list overload for construction if one exists. The * following is a simple tag used to disambiguate construction with * initializer lists and regular uniform initialization. * @@ -289,47 +188,52 @@ inline in_place_index_tag<I> in_place_index(in_place_index_tag<I> = {}) { struct initlist_construct_t {}; constexpr initlist_construct_t initlist_construct{}; -/** - * A generic tag type to indicate that some constructor or method accepts a - * presorted container. - * - * Example: - * - * void takes_numbers(std::vector<int> alist) { - * std::sort(alist.begin(), alist.end()); - * takes_numbers(folly::presorted, alist); - * } - * - * void takes_numbers(folly::presorted_t, std::vector<int> alist) { - * assert(std::is_sorted(alist.begin(), alist.end())); // debug mode only - * for (i : alist) { - * // some behavior which is defined and safe only when alist is sorted ... - * } - * } - */ -struct presorted_t {}; -constexpr presorted_t presorted{}; +// sorted_unique_t, sorted_unique +// +// A generic tag type and value to indicate that some constructor or method +// accepts a container in which the values are sorted and unique. +// +// Example: +// +// void takes_numbers(folly::sorted_unique_t, std::vector<int> alist) { +// assert(std::is_sorted(alist.begin(), alist.end())); +// assert(std::unique(alist.begin(), alist.end()) == alist.end()); +// for (i : alist) { +// // some behavior which safe only when alist is sorted and unique +// } +// } +// void takes_numbers(std::vector<int> alist) { +// std::sort(alist.begin(), alist.end()); +// alist.erase(std::unique(alist.begin(), alist.end()), alist.end()); +// takes_numbers(folly::sorted_unique, alist); +// } +// +// mimic: std::sorted_unique_t, std::sorted_unique, p0429r6 +struct sorted_unique_t {}; +constexpr sorted_unique_t sorted_unique; -/** - * A generic tag type to indicate that some constructor or method accepts an - * unsorted container. Useful in contexts which might have some reason to assume - * a container to be sorted. - * - * Example: - * - * void takes_numbers(std::vector<int> alist) { - * takes_numbers(folly::unsorted, alist); - * } - * - * void takes_numbers(folly::unsorted_t, std::vector<int> alist) { - * std::sort(alist.begin(), alist.end()); - * for (i : alist) { - * // some behavior which is defined and safe only when alist is sorted ... - * } - * } - */ -struct unsorted_t {}; -constexpr unsorted_t unsorted{}; +// sorted_equivalent_t, sorted_equivalent +// +// A generic tag type and value to indicate that some constructor or method +// accepts a container in which the values are sorted but not necessarily +// unique. +// +// Example: +// +// void takes_numbers(folly::sorted_equivalent_t, std::vector<int> alist) { +// assert(std::is_sorted(alist.begin(), alist.end())); +// for (i : alist) { +// // some behavior which safe only when alist is sorted +// } +// } +// void takes_numbers(std::vector<int> alist) { +// std::sort(alist.begin(), alist.end()); +// takes_numbers(folly::sorted_equivalent, alist); +// } +// +// mimic: std::sorted_equivalent_t, std::sorted_equivalent, p0429r6 +struct sorted_equivalent_t {}; +constexpr sorted_equivalent_t sorted_equivalent; template <typename T> struct transparent : T { @@ -391,8 +295,8 @@ constexpr auto to_signed(T const& t) -> typename std::make_signed<T>::type { // note: static_cast<S>(t) would be more straightforward, but it would also be // implementation-defined behavior and that is typically to be avoided; the // following code optimized into the same thing, though - return std::numeric_limits<S>::max() < t ? -static_cast<S>(~t) + S{-1} - : static_cast<S>(t); + constexpr auto m = static_cast<T>(std::numeric_limits<S>::max()); + return m < t ? -static_cast<S>(~t) + S{-1} : static_cast<S>(t); } template <typename T> @@ -401,4 +305,62 @@ constexpr auto to_unsigned(T const& t) -> typename std::make_unsigned<T>::type { return static_cast<U>(t); } +template <typename Src> +class to_narrow_convertible { + public: + static_assert(std::is_integral<Src>::value, "not an integer"); + + explicit constexpr to_narrow_convertible(Src const& value) noexcept + : value_(value) {} +#if __cplusplus >= 201703L + explicit to_narrow_convertible(to_narrow_convertible const&) = default; + explicit to_narrow_convertible(to_narrow_convertible&&) = default; +#else + to_narrow_convertible(to_narrow_convertible const&) = default; + to_narrow_convertible(to_narrow_convertible&&) = default; +#endif + to_narrow_convertible& operator=(to_narrow_convertible const&) = default; + to_narrow_convertible& operator=(to_narrow_convertible&&) = default; + + template < + typename Dst, + std::enable_if_t< + std::is_integral<Dst>::value && + std::is_signed<Dst>::value == std::is_signed<Src>::value, + int> = 0> + /* implicit */ constexpr operator Dst() const noexcept { + FOLLY_PUSH_WARNING + FOLLY_GNU_DISABLE_WARNING("-Wconversion") + return value_; + FOLLY_POP_WARNING + } + + private: + Src value_; +}; + +// to_narrow +// +// A utility for performing explicit possibly-narrowing integral conversion +// without specifying the destination type. Does not permit changing signs. +// Sometimes preferable to static_cast<Dst>(src) to document the intended +// semantics of the cast. +// +// Models explicit conversion with an elided destination type. Sits in between +// a stricter explicit conversion with a named destination type and a more +// lenient implicit conversion. Implemented with implicit conversion in order +// to take advantage of the undefined-behavior sanitizer's inspection of all +// implicit conversions - it checks for truncation, with suppressions in place +// for warnings which guard against narrowing implicit conversions. +template <typename Src> +constexpr auto to_narrow(Src const& src) -> to_narrow_convertible<Src> { + return to_narrow_convertible<Src>{src}; +} + +template <class E> +constexpr std::underlying_type_t<E> to_underlying(E e) noexcept { + static_assert(std::is_enum<E>::value, "not an enum type"); + return static_cast<std::underlying_type_t<E>>(e); +} + } // namespace folly diff --git a/ios/Pods/Folly/folly/Varint.h b/ios/Pods/Folly/folly/Varint.h index a8f76ad20..4dc47a418 100644 --- a/ios/Pods/Folly/folly/Varint.h +++ b/ios/Pods/Folly/folly/Varint.h @@ -1,11 +1,11 @@ /* - * Copyright 2013-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/VirtualExecutor.h b/ios/Pods/Folly/folly/VirtualExecutor.h index e649da193..fc28c2e49 100644 --- a/ios/Pods/Folly/folly/VirtualExecutor.h +++ b/ios/Pods/Folly/folly/VirtualExecutor.h @@ -1,11 +1,11 @@ /* - * Copyright 2018-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/container/Access.h b/ios/Pods/Folly/folly/container/Access.h index 3ff4b974d..f830822dc 100644 --- a/ios/Pods/Folly/folly/container/Access.h +++ b/ios/Pods/Folly/folly/container/Access.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/container/Array.h b/ios/Pods/Folly/folly/container/Array.h index ec7c4fb69..ed0ce81d0 100644 --- a/ios/Pods/Folly/folly/container/Array.h +++ b/ios/Pods/Folly/folly/container/Array.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #pragma once #include <array> @@ -26,10 +27,8 @@ namespace folly { namespace array_detail { -template <typename> -struct is_ref_wrapper : std::false_type {}; -template <typename T> -struct is_ref_wrapper<std::reference_wrapper<T>> : std::true_type {}; +template <class T> +using is_ref_wrapper = detail::is_instantiation_of<std::reference_wrapper, T>; template <typename T> using not_ref_wrapper = @@ -61,9 +60,9 @@ constexpr array_detail::return_type<D, TList...> make_array(TList&&... t) { namespace array_detail { template <typename MakeItem, std::size_t... Index> -FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN constexpr auto make_array_with( +FOLLY_ERASE constexpr auto make_array_with_( MakeItem const& make, - index_sequence<Index...>) { + std::index_sequence<Index...>) { return std::array<decltype(make(0)), sizeof...(Index)>{{make(Index)...}}; } } // namespace array_detail @@ -73,7 +72,7 @@ FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN constexpr auto make_array_with( // Constructs a std::array<..., Size> with elements m(i) for i in [0, Size). template <std::size_t Size, typename MakeItem> constexpr auto make_array_with(MakeItem const& make) { - return array_detail::make_array_with(make, make_index_sequence<Size>{}); + return array_detail::make_array_with_(make, std::make_index_sequence<Size>{}); } } // namespace folly diff --git a/ios/Pods/Folly/folly/container/BitIterator.h b/ios/Pods/Folly/folly/container/BitIterator.h index 75e9e61ed..cb5b7cca3 100644 --- a/ios/Pods/Folly/folly/container/BitIterator.h +++ b/ios/Pods/Folly/folly/container/BitIterator.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/container/Enumerate.h b/ios/Pods/Folly/folly/container/Enumerate.h index 2badc4109..55f2d263d 100644 --- a/ios/Pods/Folly/folly/container/Enumerate.h +++ b/ios/Pods/Folly/folly/container/Enumerate.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/container/EvictingCacheMap.h b/ios/Pods/Folly/folly/container/EvictingCacheMap.h index 1c54d9740..7d5f85a7a 100644 --- a/ios/Pods/Folly/folly/container/EvictingCacheMap.h +++ b/ios/Pods/Folly/folly/container/EvictingCacheMap.h @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #pragma once #include <algorithm> @@ -47,7 +48,7 @@ namespace folly { * callback and the hasher to hash the keys can all be supplied by the caller. * * If at a given state, N1 - N6 are the nodes in MRU to LRU order and hashing - * to index keys as {(N1,N5)->H1, (N4,N5,N5)->H2, N3->Hi}, the datastructure + * to index keys as {(N1,N5)->H1, (N4,N2,N6)->H2, N3->Hi}, the datastructure * layout is as below. N1 .. N6 is a list threaded through the hash. * Assuming, each the number of nodes hashed to each index key is bounded, the * following operations run in constant time. @@ -122,8 +123,20 @@ class EvictingCacheMap { boost::bidirectional_traversal_tag> { public: iterator_base() {} + explicit iterator_base(TIterator it) : iterator_base::iterator_adaptor_(it) {} + + template < + typename V, + typename I, + std::enable_if_t< + std::is_same<V const, Value>::value && + std::is_convertible<I, TIterator>::value, + int> = 0> + /* implicit */ iterator_base(iterator_base<V, I> const& other) + : iterator_base::iterator_adaptor_(other.base()) {} + Value& dereference() const { return this->base_reference()->pr; } @@ -181,7 +194,7 @@ class EvictingCacheMap { * bad, e.g., the nIndexBuckets_ is still 100 after maxSize is updated to 1M. * * Calling this function with an arugment of 0 removes the limit on the cache - * size and elements are not evicted unless clients explictly call prune. + * size and elements are not evicted unless clients explicitly call prune. * * If you intend to resize dynamically using this, then picking an index size * that works well and initializing with corresponding maxSize is the only @@ -292,14 +305,24 @@ class EvictingCacheMap { */ bool erase(const TKey& key) { auto it = findInIndex(key); - if (it == index_.end()) { - return false; + if (it != index_.end()) { + erase(const_iterator(lru_.iterator_to(*it))); + return true; } - auto node = &(*it); + return false; + } + + /** + * Erase the key-value pair associated with pos + * @param pos iterator to the element to be erased + * @return iterator to the following element or end() if pos was the last + * element + */ + iterator erase(const_iterator pos) { + auto* node = const_cast<Node*>(&(*pos.base())); std::unique_ptr<Node> nptr(node); - lru_.erase(lru_.iterator_to(*node)); - index_.erase(it); - return true; + index_.erase(index_.iterator_to(*node)); + return iterator(lru_.erase(pos.base())); } /** @@ -335,6 +358,31 @@ class EvictingCacheMap { } } + /** + * Insert a new key-value pair in the dictionary if no element exists for key + * @param key key to associate with value + * @param value value to associate with the key + * @param pruneHook callback to use on eviction (if it occurs). + * @return a pair consisting of an iterator to the inserted element (or to the + * element that prevented the insertion) and a bool denoting whether the + * insertion took place. + */ + std::pair<iterator, bool> + insert(const TKey& key, TValue value, PruneHookCall pruneHook = nullptr) { + auto node = std::make_unique<Node>(key, std::move(value)); + auto pair = index_.insert(*node); + if (pair.second) { + lru_.push_front(*node); + node.release(); + + // no evictions if maxSize_ is 0 i.e. unlimited capacity + if (maxSize_ > 0 && size() > maxSize_) { + prune(clearSize_, pruneHook); + } + } + return std::make_pair(iterator(lru_.iterator_to(*pair.first)), pair.second); + } + /** * Get the number of elements in the dictionary * @return the size of the dictionary diff --git a/ios/Pods/Folly/folly/container/F14Map-fwd.h b/ios/Pods/Folly/folly/container/F14Map-fwd.h index 2c2af3fd9..c76906cf6 100644 --- a/ios/Pods/Folly/folly/container/F14Map-fwd.h +++ b/ios/Pods/Folly/folly/container/F14Map-fwd.h @@ -1,11 +1,11 @@ /* - * Copyright 2018-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -19,6 +19,7 @@ #include <utility> #include <folly/container/detail/F14Defaults.h> +#include <folly/memory/MemoryResource.h> namespace folly { template < @@ -53,4 +54,60 @@ template < typename Alloc = f14::DefaultAlloc<std::pair<Key const, Mapped>>> class F14FastMap; +#if FOLLY_HAS_MEMORY_RESOURCE +namespace pmr { +template < + typename Key, + typename Mapped, + typename Hasher = f14::DefaultHasher<Key>, + typename KeyEqual = f14::DefaultKeyEqual<Key>> +using F14NodeMap = folly::F14NodeMap< + Key, + Mapped, + Hasher, + KeyEqual, + folly::detail::std_pmr::polymorphic_allocator< + std::pair<Key const, Mapped>>>; + +template < + typename Key, + typename Mapped, + typename Hasher = f14::DefaultHasher<Key>, + typename KeyEqual = f14::DefaultKeyEqual<Key>> +using F14ValueMap = folly::F14ValueMap< + Key, + Mapped, + Hasher, + KeyEqual, + folly::detail::std_pmr::polymorphic_allocator< + std::pair<Key const, Mapped>>>; + +template < + typename Key, + typename Mapped, + typename Hasher = f14::DefaultHasher<Key>, + typename KeyEqual = f14::DefaultKeyEqual<Key>> +using F14VectorMap = folly::F14VectorMap< + Key, + Mapped, + Hasher, + KeyEqual, + folly::detail::std_pmr::polymorphic_allocator< + std::pair<Key const, Mapped>>>; + +template < + typename Key, + typename Mapped, + typename Hasher = f14::DefaultHasher<Key>, + typename KeyEqual = f14::DefaultKeyEqual<Key>> +using F14FastMap = folly::F14FastMap< + Key, + Mapped, + Hasher, + KeyEqual, + folly::detail::std_pmr::polymorphic_allocator< + std::pair<Key const, Mapped>>>; +} // namespace pmr +#endif // FOLLY_HAS_MEMORY_RESOURCE + } // namespace folly diff --git a/ios/Pods/Folly/folly/container/F14Map.h b/ios/Pods/Folly/folly/container/F14Map.h index b8de5e0fa..b7ec5d361 100644 --- a/ios/Pods/Folly/folly/container/F14Map.h +++ b/ios/Pods/Folly/folly/container/F14Map.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -19,7 +19,7 @@ /** * F14NodeMap, F14ValueMap, and F14VectorMap * - * F14FastMap conditionally inherits from F14ValueMap or F14VectorMap + * F14FastMap conditionally works like F14ValueMap or F14VectorMap * * See F14.md * @@ -29,143 +29,17 @@ #include <stdexcept> +#include <folly/Range.h> #include <folly/Traits.h> -#include <folly/functional/ApplyTuple.h> #include <folly/lang/Exception.h> #include <folly/lang/SafeAssert.h> #include <folly/container/F14Map-fwd.h> #include <folly/container/detail/F14Policy.h> #include <folly/container/detail/F14Table.h> +#include <folly/container/detail/Util.h> -#if !FOLLY_F14_VECTOR_INTRINSICS_AVAILABLE - -//////// Compatibility for unsupported platforms (not x86_64 and not aarch64) - -#include <string> -#include <unordered_map> - -namespace folly { - -namespace f14 { -namespace detail { -template <typename K, typename M, typename H, typename E, typename A> -class F14BasicMap : public std::unordered_map<K, M, H, E, A> { - using Super = std::unordered_map<K, M, H, E, A>; - - public: - using typename Super::pointer; - using typename Super::value_type; - - F14BasicMap() = default; - - using Super::Super; - - //// PUBLIC - F14 Extensions - - // exact for libstdc++, approximate for others - std::size_t getAllocatedMemorySize() const { - std::size_t rv = 0; - visitAllocationClasses( - [&](std::size_t bytes, std::size_t n) { rv += bytes * n; }); - return rv; - } - - // exact for libstdc++, approximate for others - template <typename V> - void visitAllocationClasses(V&& visitor) const { - auto bc = this->bucket_count(); - if (bc > 1) { - visitor(bc * sizeof(pointer), 1); - } - if (this->size() > 0) { - visitor(sizeof(StdNodeReplica<K, value_type, H>), this->size()); - } - } - - template <typename V> - void visitContiguousRanges(V&& visitor) const { - for (value_type const& entry : *this) { - value_type const* b = std::addressof(entry); - visitor(b, b + 1); - } - } -}; -} // namespace detail -} // namespace f14 - -template < - typename Key, - typename Mapped, - typename Hasher, - typename KeyEqual, - typename Alloc> -class F14ValueMap - : public f14::detail::F14BasicMap<Key, Mapped, Hasher, KeyEqual, Alloc> { - using Super = f14::detail::F14BasicMap<Key, Mapped, Hasher, KeyEqual, Alloc>; - - public: - using typename Super::value_type; - - F14ValueMap() = default; - - using Super::Super; - - F14ValueMap& operator=(std::initializer_list<value_type> ilist) { - Super::operator=(ilist); - return *this; - } -}; - -template < - typename Key, - typename Mapped, - typename Hasher, - typename KeyEqual, - typename Alloc> -class F14NodeMap - : public f14::detail::F14BasicMap<Key, Mapped, Hasher, KeyEqual, Alloc> { - using Super = f14::detail::F14BasicMap<Key, Mapped, Hasher, KeyEqual, Alloc>; - - public: - using typename Super::value_type; - - F14NodeMap() = default; - - using Super::Super; - - F14NodeMap& operator=(std::initializer_list<value_type> ilist) { - Super::operator=(ilist); - return *this; - } -}; - -template < - typename Key, - typename Mapped, - typename Hasher, - typename KeyEqual, - typename Alloc> -class F14VectorMap - : public f14::detail::F14BasicMap<Key, Mapped, Hasher, KeyEqual, Alloc> { - using Super = f14::detail::F14BasicMap<Key, Mapped, Hasher, KeyEqual, Alloc>; - - public: - using typename Super::value_type; - - F14VectorMap() = default; - - using Super::Super; - - F14VectorMap& operator=(std::initializer_list<value_type> ilist) { - Super::operator=(ilist); - return *this; - } -}; - -} // namespace folly - -#else // FOLLY_F14_VECTOR_INTRINSICS_AVAILABLE +#if FOLLY_F14_VECTOR_INTRINSICS_AVAILABLE //////// Common case for supported platforms @@ -443,7 +317,11 @@ class F14BasicMap { FOLLY_ALWAYS_INLINE void bulkInsert(InputIt first, InputIt last, bool autoReserve) { if (autoReserve) { - table_.reserveForInsert(std::distance(first, last)); + auto n = std::distance(first, last); + if (n == 0) { + return; + } + table_.reserveForInsert(n); } while (first != last) { insert(*first); @@ -527,73 +405,20 @@ class F14BasicMap { } private: - std::pair<ItemIter, bool> emplaceItem() { - // rare but valid - return table_.tryEmplaceValue(key_type{}); - } - - template <typename U1, typename U2> - std::pair<ItemIter, bool> emplaceItem(U1&& x, U2&& y) { - using K = KeyTypeForEmplace<key_type, hasher, key_equal, U1>; - K key(std::forward<U1>(x)); - - // TODO(T31574848): piecewise_construct is to work around libstdc++ versions - // (e.g., GCC < 6) with no implementation of N4387 ("perfect initialization" - // for pairs and tuples). Otherwise we could just pass key, forwarded key, - // and forwarded y to tryEmplaceValue. - return table_.tryEmplaceValue( - key, - std::piecewise_construct, - std::forward_as_tuple(std::forward<K>(key)), - std::forward_as_tuple(std::forward<U2>(y))); - } - - template <typename U1, typename U2> - std::pair<ItemIter, bool> emplaceItem(std::pair<U1, U2> const& p) { - return emplaceItem(p.first, p.second); - } - - template <typename U1, typename U2> - std::pair<ItemIter, bool> emplaceItem(std::pair<U1, U2>&& p) { - return emplaceItem(std::move(p.first), std::move(p.second)); - } - - template <typename Arg1, typename... Args2> - std::pair<ItemIter, bool> emplaceItem( - std::piecewise_construct_t, - std::tuple<Arg1>&& first_args, - std::tuple<Args2...>&& second_args) { - using K = KeyTypeForEmplace<key_type, hasher, key_equal, Arg1>; - K key(std::get<0>(std::move(first_args))); - - // Args2&&... holds only references even if the caller gave us a - // tuple that directly contains values. - return table_.tryEmplaceValue( - key, - std::piecewise_construct, - std::forward_as_tuple(std::forward<K>(key)), - std::tuple<Args2&&...>(std::move(second_args))); - } - - template <typename... Args1, typename... Args2> - std::enable_if_t<sizeof...(Args1) != 1, std::pair<ItemIter, bool>> - emplaceItem( - std::piecewise_construct_t, - std::tuple<Args1...>&& first_args, - std::tuple<Args2...>&& second_args) { - auto key = make_from_tuple<key_type>( - std::tuple<Args1&&...>(std::move(first_args))); - return table_.tryEmplaceValue( - key, - std::piecewise_construct, - std::forward_as_tuple(std::move(key)), - std::tuple<Args2&&...>(std::move(second_args))); - } + template <typename Arg> + using UsableAsKey = + EligibleForHeterogeneousFind<key_type, hasher, key_equal, Arg>; public: template <typename... Args> std::pair<iterator, bool> emplace(Args&&... args) { - auto rv = emplaceItem(std::forward<Args>(args)...); + auto rv = folly::detail::callWithExtractedKey<key_type, UsableAsKey>( + table_.alloc(), + [&](auto&&... inner) { + return table_.tryEmplaceValue( + std::forward<decltype(inner)>(inner)...); + }, + std::forward<Args>(args)...); return std::make_pair(table_.makeIter(rv.first), rv.second); } @@ -662,7 +487,7 @@ class F14BasicMap { // This form avoids ambiguity when key_type has a templated constructor // that accepts const_iterator - iterator erase(iterator pos) { + FOLLY_ALWAYS_INLINE iterator erase(iterator pos) { auto itemPos = table_.unwrapIter(pos); table_.eraseIter(itemPos); itemPos.advanceLikelyDead(); @@ -721,14 +546,14 @@ class F14BasicMap { return try_emplace(std::forward<K>(key)).first->second; } - FOLLY_ALWAYS_INLINE std::size_t count(key_type const& key) const { - return table_.find(key).atEnd() ? 0 : 1; + FOLLY_ALWAYS_INLINE size_type count(key_type const& key) const { + return contains(key) ? 1 : 0; } template <typename K> - FOLLY_ALWAYS_INLINE EnableHeterogeneousFind<K, std::size_t> count( + FOLLY_ALWAYS_INLINE EnableHeterogeneousFind<K, size_type> count( K const& key) const { - return table_.find(key).atEnd() ? 0 : 1; + return contains(key) ? 1 : 0; } // prehash(key) does the work of evaluating hash_function()(key) @@ -797,6 +622,29 @@ class F14BasicMap { return table_.makeConstIter(table_.find(token, key)); } + FOLLY_ALWAYS_INLINE bool contains(key_type const& key) const { + return !table_.find(key).atEnd(); + } + + template <typename K> + FOLLY_ALWAYS_INLINE EnableHeterogeneousFind<K, bool> contains( + K const& key) const { + return !table_.find(key).atEnd(); + } + + FOLLY_ALWAYS_INLINE bool contains( + F14HashToken const& token, + key_type const& key) const { + return !table_.find(token, key).atEnd(); + } + + template <typename K> + FOLLY_ALWAYS_INLINE EnableHeterogeneousFind<K, bool> contains( + F14HashToken const& token, + K const& key) const { + return !table_.find(token, key).atEnd(); + } + std::pair<iterator, iterator> equal_range(key_type const& key) { return equal_range(*this, key); } @@ -865,6 +713,17 @@ class F14BasicMap { //// PUBLIC - F14 Extensions + // containsEqualValue returns true iff there is an element in the map + // that compares equal to value using operator==. It is undefined + // behavior to call this function if operator== on key_type can ever + // return true when the same keys passed to key_eq() would return false + // (the opposite is allowed). + bool containsEqualValue(value_type const& value) const { + auto it = table_.findMatching( + value.first, [&](auto& key) { return value.first == key; }); + return !it.atEnd() && value.second == table_.valueAtItem(it.citem()).second; + } + // Get memory footprint, not including sizeof(*this). std::size_t getAllocatedMemorySize() const { return table_.getAllocatedMemorySize(); @@ -918,33 +777,6 @@ class F14BasicMap { protected: F14Table<Policy> table_; }; - -template <typename M> -bool mapsEqual(M const& lhs, M const& rhs) { - if (lhs.size() != rhs.size()) { - return false; - } - for (auto& kv : lhs) { - auto iter = rhs.find(kv.first); - if (iter == rhs.end()) { - return false; - } - if (std::is_same< - typename M::key_equal, - std::equal_to<typename M::key_type>>::value) { - // find already checked key, just check value - if (!(kv.second == iter->second)) { - return false; - } - } else { - // spec says we compare key with == as well as with key_eq() - if (!(kv == *iter)) { - return false; - } - } - } - return true; -} } // namespace detail } // namespace f14 @@ -962,6 +794,7 @@ class F14ValueMap Hasher, KeyEqual, Alloc>> { + protected: using Policy = f14::detail::MapPolicyWithDefaults< f14::detail::ValueContainerPolicy, Key, @@ -969,6 +802,8 @@ class F14ValueMap Hasher, KeyEqual, Alloc>; + + private: using Super = f14::detail::F14BasicMap<Policy>; public: @@ -993,20 +828,6 @@ class F14ValueMap } }; -template <typename K, typename M, typename H, typename E, typename A> -bool operator==( - F14ValueMap<K, M, H, E, A> const& lhs, - F14ValueMap<K, M, H, E, A> const& rhs) { - return mapsEqual(lhs, rhs); -} - -template <typename K, typename M, typename H, typename E, typename A> -bool operator!=( - F14ValueMap<K, M, H, E, A> const& lhs, - F14ValueMap<K, M, H, E, A> const& rhs) { - return !(lhs == rhs); -} - template < typename Key, typename Mapped, @@ -1021,6 +842,7 @@ class F14NodeMap Hasher, KeyEqual, Alloc>> { + protected: using Policy = f14::detail::MapPolicyWithDefaults< f14::detail::NodeContainerPolicy, Key, @@ -1028,6 +850,8 @@ class F14NodeMap Hasher, KeyEqual, Alloc>; + + private: using Super = f14::detail::F14BasicMap<Policy>; public: @@ -1057,46 +881,39 @@ class F14NodeMap // TODO extract and node_handle insert }; -template <typename K, typename M, typename H, typename E, typename A> -bool operator==( - F14NodeMap<K, M, H, E, A> const& lhs, - F14NodeMap<K, M, H, E, A> const& rhs) { - return mapsEqual(lhs, rhs); -} - -template <typename K, typename M, typename H, typename E, typename A> -bool operator!=( - F14NodeMap<K, M, H, E, A> const& lhs, - F14NodeMap<K, M, H, E, A> const& rhs) { - return !(lhs == rhs); -} - +namespace f14 { +namespace detail { template < typename Key, typename Mapped, typename Hasher, typename KeyEqual, - typename Alloc> -class F14VectorMap - : public f14::detail::F14BasicMap<f14::detail::MapPolicyWithDefaults< - f14::detail::VectorContainerPolicy, - Key, - Mapped, - Hasher, - KeyEqual, - Alloc>> { - using Policy = f14::detail::MapPolicyWithDefaults< - f14::detail::VectorContainerPolicy, + typename Alloc, + typename EligibleForPerturbedInsertionOrder> +class F14VectorMapImpl : public F14BasicMap<MapPolicyWithDefaults< + VectorContainerPolicy, + Key, + Mapped, + Hasher, + KeyEqual, + Alloc, + EligibleForPerturbedInsertionOrder>> { + protected: + using Policy = MapPolicyWithDefaults< + VectorContainerPolicy, Key, Mapped, Hasher, KeyEqual, - Alloc>; - using Super = f14::detail::F14BasicMap<Policy>; + Alloc, + EligibleForPerturbedInsertionOrder>; + + private: + using Super = F14BasicMap<Policy>; template <typename K, typename T> using EnableHeterogeneousVectorErase = std::enable_if_t< - f14::detail::EligibleForHeterogeneousFind< + EligibleForHeterogeneousFind< typename Policy::Value, typename Policy::Hasher, typename Policy::KeyEqual, @@ -1114,8 +931,138 @@ class F14VectorMap using typename Super::iterator; using typename Super::key_type; using typename Super::value_type; - using reverse_iterator = typename Policy::ReverseIter; - using const_reverse_iterator = typename Policy::ConstReverseIter; + + F14VectorMapImpl() = default; + + // inherit constructors + using Super::Super; + + F14VectorMapImpl& operator=(std::initializer_list<value_type> ilist) { + Super::operator=(ilist); + return *this; + } + + iterator begin() { + return this->table_.linearBegin(this->size()); + } + const_iterator begin() const { + return cbegin(); + } + const_iterator cbegin() const { + return this->table_.linearBegin(this->size()); + } + + iterator end() { + return this->table_.linearEnd(); + } + const_iterator end() const { + return cend(); + } + const_iterator cend() const { + return this->table_.linearEnd(); + } + + private: + void eraseUnderlying(typename Policy::ItemIter underlying) { + Alloc& a = this->table_.alloc(); + auto values = this->table_.values_; + + // Remove the ptr from the base table and destroy the value. + auto index = underlying.item(); + // The item still needs to be hashable during this call, so we must destroy + // the value _afterwards_. + this->table_.eraseIter(underlying); + Policy::AllocTraits::destroy(a, std::addressof(values[index])); + + // move the last element in values_ down and fix up the inbound index + auto tailIndex = this->size(); + if (tailIndex != index) { + auto tail = this->table_.find( + VectorContainerIndexSearch{static_cast<uint32_t>(tailIndex)}); + tail.item() = index; + auto p = std::addressof(values[index]); + assume(p != nullptr); + this->table_.transfer(a, std::addressof(values[tailIndex]), p, 1); + } + } + + template <typename K> + std::size_t eraseUnderlyingKey(K const& key) { + auto underlying = this->table_.find(key); + if (underlying.atEnd()) { + return 0; + } else { + eraseUnderlying(underlying); + return 1; + } + } + + public: + FOLLY_ALWAYS_INLINE iterator erase(const_iterator pos) { + auto index = this->table_.iterToIndex(pos); + auto underlying = this->table_.find(VectorContainerIndexSearch{index}); + eraseUnderlying(underlying); + return index == 0 ? end() : this->table_.indexToIter(index - 1); + } + + // This form avoids ambiguity when key_type has a templated constructor + // that accepts const_iterator + FOLLY_ALWAYS_INLINE iterator erase(iterator pos) { + const_iterator cpos{pos}; + return erase(cpos); + } + + iterator erase(const_iterator first, const_iterator last) { + while (first != last) { + first = erase(first); + } + auto index = this->table_.iterToIndex(first); + return index == 0 ? end() : this->table_.indexToIter(index - 1); + } + + std::size_t erase(key_type const& key) { + return eraseUnderlyingKey(key); + } + + template <typename K> + EnableHeterogeneousVectorErase<K, std::size_t> erase(K const& key) { + return eraseUnderlyingKey(key); + } + + template <typename V> + void visitContiguousRanges(V&& visitor) const { + auto n = this->table_.size(); + if (n > 0) { + value_type const* b = std::addressof(this->table_.values_[0]); + visitor(b, b + n); + } + } +}; +} // namespace detail +} // namespace f14 + +template < + typename Key, + typename Mapped, + typename Hasher, + typename KeyEqual, + typename Alloc> +class F14VectorMap : public f14::detail::F14VectorMapImpl< + Key, + Mapped, + Hasher, + KeyEqual, + Alloc, + std::false_type> { + using Super = f14::detail:: + F14VectorMapImpl<Key, Mapped, Hasher, KeyEqual, Alloc, std::false_type>; + + public: + using typename Super::const_iterator; + using typename Super::iterator; + using typename Super::value_type; + using reverse_iterator = typename Super::Policy::ReverseIter; + using const_reverse_iterator = typename Super::Policy::ConstReverseIter; F14VectorMap() = default; @@ -1127,7 +1074,7 @@ class F14VectorMap return *this; } - void swap(F14VectorMap& rhs) noexcept(Policy::kSwapIsNoexcept) { + void swap(F14VectorMap& rhs) noexcept(Super::Policy::kSwapIsNoexcept) { this->table_.swap(rhs.table_); } @@ -1151,26 +1098,11 @@ class F14VectorMap // by std::map and std::unordered_map. erase(iter) invalidates iter // and all iterators before iter in the non-reverse iteration order. // Every successful erase invalidates all reverse iterators. - - iterator begin() { - return this->table_.linearBegin(this->size()); - } - const_iterator begin() const { - return cbegin(); - } - const_iterator cbegin() const { - return this->table_.linearBegin(this->size()); - } - - iterator end() { - return this->table_.linearEnd(); - } - const_iterator end() const { - return cend(); - } - const_iterator cend() const { - return this->table_.linearEnd(); - } + // + // No erase is provided for reverse_iterator or const_reverse_iterator + // to make it harder to shoot yourself in the foot by erasing while + // reverse-iterating. You can write that as map.erase(map.iter(riter)) + // if you really need it. reverse_iterator rbegin() { return this->table_.values_; @@ -1206,88 +1138,265 @@ class F14VectorMap const_reverse_iterator riter(const_iterator it) const { return this->table_.riter(it); } +}; - private: - void eraseUnderlying(typename Policy::ItemIter underlying) { - Alloc& a = this->table_.alloc(); - auto values = this->table_.values_; +template <typename K, typename M, typename H, typename E, typename A> +Range<typename F14VectorMap<K, M, H, E, A>::const_reverse_iterator> +order_preserving_reinsertion_view(const F14VectorMap<K, M, H, E, A>& c) { + return {c.rbegin(), c.rend()}; +} - // Remove the ptr from the base table and destroy the value. - auto index = underlying.item(); - // The item still needs to be hashable during this call, so we must destroy - // the value _afterwards_. - this->table_.eraseIter(underlying); - Policy::AllocTraits::destroy(a, std::addressof(values[index])); - - // move the last element in values_ down and fix up the inbound index - auto tailIndex = this->size(); - if (tailIndex != index) { - auto tail = this->table_.find(f14::detail::VectorContainerIndexSearch{ - static_cast<uint32_t>(tailIndex)}); - tail.item() = index; - auto p = std::addressof(values[index]); - assume(p != nullptr); - this->table_.transfer(a, std::addressof(values[tailIndex]), p, 1); - } - } - - template <typename K> - std::size_t eraseUnderlyingKey(K const& key) { - auto underlying = this->table_.find(key); - if (underlying.atEnd()) { - return 0; - } else { - eraseUnderlying(underlying); - return 1; - } - } +template < + typename Key, + typename Mapped, + typename Hasher, + typename KeyEqual, + typename Alloc> +class F14FastMap : public std::conditional_t< + sizeof(std::pair<Key const, Mapped>) < 24, + F14ValueMap<Key, Mapped, Hasher, KeyEqual, Alloc>, + f14::detail::F14VectorMapImpl< + Key, + Mapped, + Hasher, + KeyEqual, + Alloc, + std::true_type>> { + using Super = std::conditional_t< + sizeof(std::pair<Key const, Mapped>) < 24, + F14ValueMap<Key, Mapped, Hasher, KeyEqual, Alloc>, + f14::detail::F14VectorMapImpl< + Key, + Mapped, + Hasher, + KeyEqual, + Alloc, + std::true_type>>; public: - FOLLY_ALWAYS_INLINE iterator erase(const_iterator pos) { - auto index = this->table_.iterToIndex(pos); - auto underlying = - this->table_.find(f14::detail::VectorContainerIndexSearch{index}); - eraseUnderlying(underlying); - return index == 0 ? end() : this->table_.indexToIter(index - 1); + using typename Super::value_type; + + F14FastMap() = default; + + using Super::Super; + + F14FastMap& operator=(std::initializer_list<value_type> ilist) { + Super::operator=(ilist); + return *this; } - // This form avoids ambiguity when key_type has a templated constructor - // that accepts const_iterator - FOLLY_ALWAYS_INLINE iterator erase(iterator pos) { - const_iterator cpos{pos}; - return erase(cpos); + void swap(F14FastMap& rhs) noexcept(Super::Policy::kSwapIsNoexcept) { + this->table_.swap(rhs.table_); } +}; +} // namespace folly - iterator erase(const_iterator first, const_iterator last) { - while (first != last) { - first = erase(first); +#else // !if FOLLY_F14_VECTOR_INTRINSICS_AVAILABLE + +//////// Compatibility for unsupported platforms (not x86_64 and not aarch64) + +#include <string> +#include <unordered_map> + +namespace folly { + +namespace f14 { +namespace detail { +template <typename K, typename M, typename H, typename E, typename A> +class F14BasicMap : public std::unordered_map<K, M, H, E, A> { + using Super = std::unordered_map<K, M, H, E, A>; + + public: + using typename Super::pointer; + using typename Super::value_type; + + F14BasicMap() = default; + + using Super::Super; + + //// PUBLIC - F14 Extensions + + bool containsEqualValue(value_type const& value) const { + auto slot = this->bucket(value.first); + auto e = this->end(slot); + for (auto b = this->begin(slot); b != e; ++b) { + if (b->first == value.first) { + return b->second == value.second; + } } - auto index = this->table_.iterToIndex(first); - return index == 0 ? end() : this->table_.indexToIter(index - 1); + return false; } - // No erase is provided for reverse_iterator or const_reverse_iterator - // to make it harder to shoot yourself in the foot by erasing while - // reverse-iterating. You can write that as map.erase(map.iter(riter)). - - std::size_t erase(key_type const& key) { - return eraseUnderlyingKey(key); + // exact for libstdc++, approximate for others + std::size_t getAllocatedMemorySize() const { + std::size_t rv = 0; + visitAllocationClasses( + [&](std::size_t bytes, std::size_t n) { rv += bytes * n; }); + return rv; } - template <typename K> - EnableHeterogeneousVectorErase<K, std::size_t> erase(K const& key) { - return eraseUnderlyingKey(key); + // exact for libstdc++, approximate for others + template <typename V> + void visitAllocationClasses(V&& visitor) const { + auto bc = this->bucket_count(); + if (bc > 1) { + visitor(bc * sizeof(pointer), 1); + } + if (this->size() > 0) { + visitor(sizeof(StdNodeReplica<K, value_type, H>), this->size()); + } } template <typename V> void visitContiguousRanges(V&& visitor) const { - auto n = this->table_.size(); - if (n > 0) { - value_type const* b = std::addressof(this->table_.values_[0]); - visitor(b, b + n); + for (value_type const& entry : *this) { + value_type const* b = std::addressof(entry); + visitor(b, b + 1); } } }; +} // namespace detail +} // namespace f14 + +template < + typename Key, + typename Mapped, + typename Hasher, + typename KeyEqual, + typename Alloc> +class F14ValueMap + : public f14::detail::F14BasicMap<Key, Mapped, Hasher, KeyEqual, Alloc> { + using Super = f14::detail::F14BasicMap<Key, Mapped, Hasher, KeyEqual, Alloc>; + + public: + using typename Super::value_type; + + F14ValueMap() = default; + + using Super::Super; + + F14ValueMap& operator=(std::initializer_list<value_type> ilist) { + Super::operator=(ilist); + return *this; + } +}; + +template < + typename Key, + typename Mapped, + typename Hasher, + typename KeyEqual, + typename Alloc> +class F14NodeMap + : public f14::detail::F14BasicMap<Key, Mapped, Hasher, KeyEqual, Alloc> { + using Super = f14::detail::F14BasicMap<Key, Mapped, Hasher, KeyEqual, Alloc>; + + public: + using typename Super::value_type; + + F14NodeMap() = default; + + using Super::Super; + + F14NodeMap& operator=(std::initializer_list<value_type> ilist) { + Super::operator=(ilist); + return *this; + } +}; + +template < + typename Key, + typename Mapped, + typename Hasher, + typename KeyEqual, + typename Alloc> +class F14VectorMap + : public f14::detail::F14BasicMap<Key, Mapped, Hasher, KeyEqual, Alloc> { + using Super = f14::detail::F14BasicMap<Key, Mapped, Hasher, KeyEqual, Alloc>; + + public: + using typename Super::value_type; + + F14VectorMap() = default; + + using Super::Super; + + F14VectorMap& operator=(std::initializer_list<value_type> ilist) { + Super::operator=(ilist); + return *this; + } +}; + +template < + typename Key, + typename Mapped, + typename Hasher, + typename KeyEqual, + typename Alloc> +class F14FastMap + : public f14::detail::F14BasicMap<Key, Mapped, Hasher, KeyEqual, Alloc> { + using Super = f14::detail::F14BasicMap<Key, Mapped, Hasher, KeyEqual, Alloc>; + + public: + using typename Super::value_type; + + F14FastMap() = default; + + using Super::Super; + + F14FastMap& operator=(std::initializer_list<value_type> ilist) { + Super::operator=(ilist); + return *this; + } +}; +} // namespace folly +#endif // if FOLLY_F14_VECTOR_INTRINSICS_AVAILABLE else + +namespace folly { +namespace f14 { +namespace detail { +template <typename M> +bool mapsEqual(M const& lhs, M const& rhs) { + if (lhs.size() != rhs.size()) { + return false; + } + for (auto& kv : lhs) { + if (!rhs.containsEqualValue(kv)) { + return false; + } + } + return true; +} +} // namespace detail +} // namespace f14 + +template <typename K, typename M, typename H, typename E, typename A> +bool operator==( + F14ValueMap<K, M, H, E, A> const& lhs, + F14ValueMap<K, M, H, E, A> const& rhs) { + return mapsEqual(lhs, rhs); +} + +template <typename K, typename M, typename H, typename E, typename A> +bool operator!=( + F14ValueMap<K, M, H, E, A> const& lhs, + F14ValueMap<K, M, H, E, A> const& rhs) { + return !(lhs == rhs); +} + +template <typename K, typename M, typename H, typename E, typename A> +bool operator==( + F14NodeMap<K, M, H, E, A> const& lhs, + F14NodeMap<K, M, H, E, A> const& rhs) { + return mapsEqual(lhs, rhs); +} + +template <typename K, typename M, typename H, typename E, typename A> +bool operator!=( + F14NodeMap<K, M, H, E, A> const& lhs, + F14NodeMap<K, M, H, E, A> const& rhs) { + return !(lhs == rhs); +} template <typename K, typename M, typename H, typename E, typename A> bool operator==( @@ -1303,39 +1412,19 @@ bool operator!=( return !(lhs == rhs); } -} // namespace folly +template <typename K, typename M, typename H, typename E, typename A> +bool operator==( + F14FastMap<K, M, H, E, A> const& lhs, + F14FastMap<K, M, H, E, A> const& rhs) { + return mapsEqual(lhs, rhs); +} -#endif // FOLLY_F14_VECTOR_INTRINSICS_AVAILABLE - -namespace folly { - -template < - typename Key, - typename Mapped, - typename Hasher, - typename KeyEqual, - typename Alloc> -class F14FastMap : public std::conditional_t< - sizeof(std::pair<Key const, Mapped>) < 24, - F14ValueMap<Key, Mapped, Hasher, KeyEqual, Alloc>, - F14VectorMap<Key, Mapped, Hasher, KeyEqual, Alloc>> { - using Super = std::conditional_t< - sizeof(std::pair<Key const, Mapped>) < 24, - F14ValueMap<Key, Mapped, Hasher, KeyEqual, Alloc>, - F14VectorMap<Key, Mapped, Hasher, KeyEqual, Alloc>>; - - public: - using typename Super::value_type; - - F14FastMap() = default; - - using Super::Super; - - F14FastMap& operator=(std::initializer_list<value_type> ilist) { - Super::operator=(ilist); - return *this; - } -}; +template <typename K, typename M, typename H, typename E, typename A> +bool operator!=( + F14FastMap<K, M, H, E, A> const& lhs, + F14FastMap<K, M, H, E, A> const& rhs) { + return !(lhs == rhs); +} template <typename K, typename M, typename H, typename E, typename A> void swap( @@ -1365,4 +1454,48 @@ void swap( lhs.swap(rhs); } +template < + typename K, + typename M, + typename H, + typename E, + typename A, + typename Pred> +void erase_if(F14ValueMap<K, M, H, E, A>& c, Pred pred) { + f14::detail::erase_if_impl(c, pred); +} + +template < + typename K, + typename M, + typename H, + typename E, + typename A, + typename Pred> +void erase_if(F14NodeMap<K, M, H, E, A>& c, Pred pred) { + f14::detail::erase_if_impl(c, pred); +} + +template < + typename K, + typename M, + typename H, + typename E, + typename A, + typename Pred> +void erase_if(F14VectorMap<K, M, H, E, A>& c, Pred pred) { + f14::detail::erase_if_impl(c, pred); +} + +template < + typename K, + typename M, + typename H, + typename E, + typename A, + typename Pred> +void erase_if(F14FastMap<K, M, H, E, A>& c, Pred pred) { + f14::detail::erase_if_impl(c, pred); +} + } // namespace folly diff --git a/ios/Pods/Folly/folly/container/F14Set-fwd.h b/ios/Pods/Folly/folly/container/F14Set-fwd.h index db1b75c1b..db484fa16 100644 --- a/ios/Pods/Folly/folly/container/F14Set-fwd.h +++ b/ios/Pods/Folly/folly/container/F14Set-fwd.h @@ -1,11 +1,11 @@ /* - * Copyright 2018-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -17,6 +17,7 @@ #pragma once #include <folly/container/detail/F14Defaults.h> +#include <folly/memory/MemoryResource.h> namespace folly { template < @@ -47,4 +48,48 @@ template < typename Alloc = f14::DefaultAlloc<Key>> class F14FastSet; +#if FOLLY_HAS_MEMORY_RESOURCE +namespace pmr { +template < + typename Key, + typename Hasher = f14::DefaultHasher<Key>, + typename KeyEqual = f14::DefaultKeyEqual<Key>> +using F14NodeSet = folly::F14NodeSet< + Key, + Hasher, + KeyEqual, + folly::detail::std_pmr::polymorphic_allocator<Key>>; + +template < + typename Key, + typename Hasher = f14::DefaultHasher<Key>, + typename KeyEqual = f14::DefaultKeyEqual<Key>> +using F14ValueSet = folly::F14ValueSet< + Key, + Hasher, + KeyEqual, + folly::detail::std_pmr::polymorphic_allocator<Key>>; + +template < + typename Key, + typename Hasher = f14::DefaultHasher<Key>, + typename KeyEqual = f14::DefaultKeyEqual<Key>> +using F14VectorSet = folly::F14VectorSet< + Key, + Hasher, + KeyEqual, + folly::detail::std_pmr::polymorphic_allocator<Key>>; + +template < + typename Key, + typename Hasher = f14::DefaultHasher<Key>, + typename KeyEqual = f14::DefaultKeyEqual<Key>> +using F14FastSet = folly::F14FastSet< + Key, + Hasher, + KeyEqual, + folly::detail::std_pmr::polymorphic_allocator<Key>>; +} // namespace pmr +#endif // FOLLY_HAS_MEMORY_RESOURCE + } // namespace folly diff --git a/ios/Pods/Folly/folly/container/F14Set.h b/ios/Pods/Folly/folly/container/F14Set.h index b4cebbcae..96bb5dbfb 100644 --- a/ios/Pods/Folly/folly/container/F14Set.h +++ b/ios/Pods/Folly/folly/container/F14Set.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -19,7 +19,7 @@ /** * F14NodeSet, F14ValueSet, and F14VectorSet * - * F14FastSet conditionally inherits from F14ValueSet or F14VectorSet + * F14FastSet conditionally works like F14ValueSet or F14VectorSet * * See F14.md * @@ -34,119 +34,9 @@ #include <folly/container/F14Set-fwd.h> #include <folly/container/detail/F14Policy.h> #include <folly/container/detail/F14Table.h> +#include <folly/container/detail/Util.h> -#if !FOLLY_F14_VECTOR_INTRINSICS_AVAILABLE - -//////// Compatibility for unsupported platforms (not x86_64 and not aarch64) - -#include <unordered_set> - -namespace folly { - -namespace f14 { -namespace detail { -template <typename K, typename H, typename E, typename A> -class F14BasicSet : public std::unordered_set<K, H, E, A> { - using Super = std::unordered_set<K, H, E, A>; - - public: - using typename Super::pointer; - using typename Super::value_type; - - F14BasicSet() = default; - - using Super::Super; - - //// PUBLIC - F14 Extensions - - // exact for libstdc++, approximate for others - std::size_t getAllocatedMemorySize() const { - std::size_t rv = 0; - visitAllocationClasses( - [&](std::size_t bytes, std::size_t n) { rv += bytes * n; }); - return rv; - } - - // exact for libstdc++, approximate for others - template <typename V> - void visitAllocationClasses(V&& visitor) const { - auto bc = this->bucket_count(); - if (bc > 1) { - visitor(bc * sizeof(pointer), 1); - } - if (this->size() > 0) { - visitor(sizeof(StdNodeReplica<K, value_type, H>), this->size()); - } - } - - template <typename V> - void visitContiguousRanges(V&& visitor) const { - for (value_type const& entry : *this) { - value_type const* b = std::addressof(entry); - visitor(b, b + 1); - } - } -}; -} // namespace detail -} // namespace f14 - -template <typename Key, typename Hasher, typename KeyEqual, typename Alloc> -class F14NodeSet - : public f14::detail::F14BasicSet<Key, Hasher, KeyEqual, Alloc> { - using Super = f14::detail::F14BasicSet<Key, Hasher, KeyEqual, Alloc>; - - public: - using typename Super::value_type; - - F14NodeSet() = default; - - using Super::Super; - - F14NodeSet& operator=(std::initializer_list<value_type> ilist) { - Super::operator=(ilist); - return *this; - } -}; - -template <typename Key, typename Hasher, typename KeyEqual, typename Alloc> -class F14ValueSet - : public f14::detail::F14BasicSet<Key, Hasher, KeyEqual, Alloc> { - using Super = f14::detail::F14BasicSet<Key, Hasher, KeyEqual, Alloc>; - - public: - using typename Super::value_type; - - F14ValueSet() : Super() {} - - using Super::Super; - - F14ValueSet& operator=(std::initializer_list<value_type> ilist) { - Super::operator=(ilist); - return *this; - } -}; - -template <typename Key, typename Hasher, typename KeyEqual, typename Alloc> -class F14VectorSet - : public f14::detail::F14BasicSet<Key, Hasher, KeyEqual, Alloc> { - using Super = f14::detail::F14BasicSet<Key, Hasher, KeyEqual, Alloc>; - - public: - using typename Super::value_type; - - F14VectorSet() = default; - - using Super::Super; - - F14VectorSet& operator=(std::initializer_list<value_type> ilist) { - Super::operator=(ilist); - return *this; - } -}; - -} // namespace folly - -#else // FOLLY_F14_VECTOR_INTRINSICS_AVAILABLE +#if FOLLY_F14_VECTOR_INTRINSICS_AVAILABLE //////// Common case for supported platforms @@ -387,7 +277,11 @@ class F14BasicSet { FOLLY_ALWAYS_INLINE void bulkInsert(InputIt first, InputIt last, bool autoReserve) { if (autoReserve) { - table_.reserveForInsert(std::distance(first, last)); + auto n = std::distance(first, last); + if (n == 0) { + return; + } + table_.reserveForInsert(n); } while (first != last) { insert(*first); @@ -430,18 +324,21 @@ class F14BasicSet { insert(ilist.begin(), ilist.end()); } + private: + template <typename Arg> + using UsableAsKey = + EligibleForHeterogeneousFind<key_type, hasher, key_equal, Arg>; + + public: template <class... Args> std::pair<iterator, bool> emplace(Args&&... args) { - using K = KeyTypeForEmplace<key_type, hasher, key_equal, Args...>; - - // If args is a single arg that can be emplaced directly (either - // key_type or a heterogeneous find + conversion to key_type) key will - // just be a reference to that arg, otherwise this will construct an - // intermediate key. - K key(std::forward<Args>(args)...); - - auto rv = table_.tryEmplaceValue(key, std::forward<K>(key)); - + auto rv = folly::detail::callWithConstructedKey<key_type, UsableAsKey>( + table_.alloc(), + [&](auto&&... inner) { + return table_.tryEmplaceValue( + std::forward<decltype(inner)>(inner)...); + }, + std::forward<Args>(args)...); return std::make_pair(table_.makeIter(rv.first), rv.second); } @@ -508,14 +405,14 @@ class F14BasicSet { //// PUBLIC - Lookup - FOLLY_ALWAYS_INLINE std::size_t count(key_type const& key) const { - return table_.find(key).atEnd() ? 0 : 1; + FOLLY_ALWAYS_INLINE size_type count(key_type const& key) const { + return contains(key) ? 1 : 0; } template <typename K> FOLLY_ALWAYS_INLINE EnableHeterogeneousFind<K, size_type> count( K const& key) const { - return table_.find(key).atEnd() ? 0 : 1; + return contains(key) ? 1 : 0; } // prehash(key) does the work of evaluating hash_function()(key) @@ -584,6 +481,29 @@ class F14BasicSet { return table_.makeIter(table_.find(token, key)); } + FOLLY_ALWAYS_INLINE bool contains(key_type const& key) const { + return !table_.find(key).atEnd(); + } + + template <typename K> + FOLLY_ALWAYS_INLINE EnableHeterogeneousFind<K, bool> contains( + K const& key) const { + return !table_.find(key).atEnd(); + } + + FOLLY_ALWAYS_INLINE bool contains( + F14HashToken const& token, + key_type const& key) const { + return !table_.find(token, key).atEnd(); + } + + template <typename K> + FOLLY_ALWAYS_INLINE EnableHeterogeneousFind<K, bool> contains( + F14HashToken const& token, + K const& key) const { + return !table_.find(token, key).atEnd(); + } + std::pair<iterator, iterator> equal_range(key_type const& key) { return equal_range(*this, key); } @@ -652,6 +572,17 @@ class F14BasicSet { //// PUBLIC - F14 Extensions + // containsEqualValue returns true iff there is an element in the set + // that compares equal to key using operator==. It is undefined + // behjavior to call this function if operator== on key_type can ever + // return true when the same keys passed to key_eq() would return false + // (the opposite is allowed). When using the default key_eq this function + // is equivalent to contains(). + bool containsEqualValue(value_type const& value) const { + return !table_.findMatching(value, [&](auto& k) { return value == k; }) + .atEnd(); + } + // Get memory footprint, not including sizeof(*this). std::size_t getAllocatedMemorySize() const { return table_.getAllocatedMemorySize(); @@ -696,28 +627,6 @@ class F14BasicSet { protected: F14Table<Policy> table_; }; - -template <typename S> -bool setsEqual(S const& lhs, S const& rhs) { - if (lhs.size() != rhs.size()) { - return false; - } - for (auto& k : lhs) { - auto iter = rhs.find(k); - if (iter == rhs.end()) { - return false; - } - if (!std::is_same< - typename S::key_equal, - std::equal_to<typename S::value_type>>::value) { - // spec says we compare key with == as well as with key_eq() - if (!(k == *iter)) { - return false; - } - } - } - return true; -} } // namespace detail } // namespace f14 @@ -729,12 +638,15 @@ class F14ValueSet Hasher, KeyEqual, Alloc>> { + protected: using Policy = f14::detail::SetPolicyWithDefaults< f14::detail::ValueContainerPolicy, Key, Hasher, KeyEqual, Alloc>; + + private: using Super = f14::detail::F14BasicSet<Policy>; public: @@ -759,20 +671,6 @@ class F14ValueSet } }; -template <typename K, typename H, typename E, typename A> -bool operator==( - F14ValueSet<K, H, E, A> const& lhs, - F14ValueSet<K, H, E, A> const& rhs) { - return setsEqual(lhs, rhs); -} - -template <typename K, typename H, typename E, typename A> -bool operator!=( - F14ValueSet<K, H, E, A> const& lhs, - F14ValueSet<K, H, E, A> const& rhs) { - return !(lhs == rhs); -} - template <typename Key, typename Hasher, typename KeyEqual, typename Alloc> class F14NodeSet : public f14::detail::F14BasicSet<f14::detail::SetPolicyWithDefaults< @@ -781,12 +679,15 @@ class F14NodeSet Hasher, KeyEqual, Alloc>> { + protected: using Policy = f14::detail::SetPolicyWithDefaults< f14::detail::NodeContainerPolicy, Key, Hasher, KeyEqual, Alloc>; + + private: using Super = f14::detail::F14BasicSet<Policy>; public: @@ -814,39 +715,36 @@ class F14NodeSet } }; -template <typename K, typename H, typename E, typename A> -bool operator==( - F14NodeSet<K, H, E, A> const& lhs, - F14NodeSet<K, H, E, A> const& rhs) { - return setsEqual(lhs, rhs); -} - -template <typename K, typename H, typename E, typename A> -bool operator!=( - F14NodeSet<K, H, E, A> const& lhs, - F14NodeSet<K, H, E, A> const& rhs) { - return !(lhs == rhs); -} - -template <typename Key, typename Hasher, typename KeyEqual, typename Alloc> -class F14VectorSet - : public f14::detail::F14BasicSet<f14::detail::SetPolicyWithDefaults< - f14::detail::VectorContainerPolicy, - Key, - Hasher, - KeyEqual, - Alloc>> { - using Policy = f14::detail::SetPolicyWithDefaults< - f14::detail::VectorContainerPolicy, +namespace f14 { +namespace detail { +template < + typename Key, + typename Hasher, + typename KeyEqual, + typename Alloc, + typename EligibleForPerturbedInsertionOrder> +class F14VectorSetImpl : public F14BasicSet<SetPolicyWithDefaults< + VectorContainerPolicy, + Key, + Hasher, + KeyEqual, + Alloc, + EligibleForPerturbedInsertionOrder>> { + protected: + using Policy = SetPolicyWithDefaults< + VectorContainerPolicy, Key, Hasher, KeyEqual, - Alloc>; - using Super = f14::detail::F14BasicSet<Policy>; + Alloc, + EligibleForPerturbedInsertionOrder>; + + private: + using Super = F14BasicSet<Policy>; template <typename K, typename T> using EnableHeterogeneousVectorErase = std::enable_if_t< - f14::detail::EligibleForHeterogeneousFind< + EligibleForHeterogeneousFind< typename Policy::Value, typename Policy::Hasher, typename Policy::KeyEqual, @@ -860,43 +758,16 @@ class F14VectorSet using typename Super::iterator; using typename Super::key_type; using typename Super::value_type; - using reverse_iterator = typename Policy::ReverseIter; - using const_reverse_iterator = reverse_iterator; - F14VectorSet() = default; + F14VectorSetImpl() = default; using Super::Super; - F14VectorSet& operator=(std::initializer_list<value_type> ilist) { + F14VectorSetImpl& operator=(std::initializer_list<value_type> ilist) { Super::operator=(ilist); return *this; } - void swap(F14VectorSet& rhs) noexcept(Policy::kSwapIsNoexcept) { - this->table_.swap(rhs.table_); - } - - // ITERATION ORDER - // - // Deterministic iteration order for insert-only workloads is part of - // F14VectorSet's supported API: iterator is LIFO and reverse_iterator - // is FIFO. - // - // If there have been no calls to erase() then iterator and - // const_iterator enumerate entries in the opposite of insertion order. - // begin()->first is the key most recently inserted. reverse_iterator - // and reverse_const_iterator, therefore, enumerate in LIFO (insertion) - // order for insert-only workloads. Deterministic iteration order is - // only guaranteed if no keys were removed since the last time the - // set was empty. Iteration order is preserved across rehashes and - // F14VectorSet copies and moves. - // - // iterator uses LIFO order so that erasing while iterating with begin() - // and end() is safe using the erase(it++) idiom, which is supported - // by std::set and std::unordered_set. erase(iter) invalidates iter - // and all iterators before iter in the non-reverse iteration order. - // Every successful erase invalidates all reverse iterators. - iterator begin() { return cbegin(); } @@ -917,41 +788,6 @@ class F14VectorSet return this->table_.linearEnd(); } - reverse_iterator rbegin() { - return this->table_.values_; - } - const_reverse_iterator rbegin() const { - return crbegin(); - } - const_reverse_iterator crbegin() const { - return this->table_.values_; - } - - reverse_iterator rend() { - return this->table_.values_ + this->table_.size(); - } - const_reverse_iterator rend() const { - return crend(); - } - const_reverse_iterator crend() const { - return this->table_.values_ + this->table_.size(); - } - - // explicit conversions between iterator and reverse_iterator - iterator iter(reverse_iterator riter) { - return this->table_.iter(riter); - } - const_iterator iter(const_reverse_iterator riter) const { - return this->table_.iter(riter); - } - - reverse_iterator riter(iterator it) { - return this->table_.riter(it); - } - const_reverse_iterator riter(const_iterator it) const { - return this->table_.riter(it); - } - private: template <typename BeforeDestroy> void eraseUnderlying( @@ -968,8 +804,8 @@ class F14VectorSet // move the last element in values_ down and fix up the inbound index auto tailIndex = this->size(); if (tailIndex != index) { - auto tail = this->table_.find(f14::detail::VectorContainerIndexSearch{ - static_cast<uint32_t>(tailIndex)}); + auto tail = this->table_.find( + VectorContainerIndexSearch{static_cast<uint32_t>(tailIndex)}); tail.item() = index; auto p = std::addressof(values[index]); assume(p != nullptr); @@ -997,10 +833,6 @@ class F14VectorSet return eraseInto(first, last, [](value_type&&) {}); } - // No erase is provided for reverse_iterator (AKA const_reverse_iterator) - // to make it harder to shoot yourself in the foot by erasing while - // reverse-iterating. You can write that as set.erase(set.iter(riter)). - std::size_t erase(key_type const& key) { return eraseInto(key, [](value_type&&) {}); } @@ -1014,7 +846,7 @@ class F14VectorSet FOLLY_ALWAYS_INLINE iterator eraseInto(const_iterator pos, BeforeDestroy&& beforeDestroy) { auto underlying = this->table_.find( - f14::detail::VectorContainerIndexSearch{this->table_.iterToIndex(pos)}); + VectorContainerIndexSearch{this->table_.iterToIndex(pos)}); eraseUnderlying(underlying, beforeDestroy); return ++pos; } @@ -1051,6 +883,321 @@ class F14VectorSet } } }; +} // namespace detail +} // namespace f14 + +template <typename Key, typename Hasher, typename KeyEqual, typename Alloc> +class F14VectorSet + : public f14::detail:: + F14VectorSetImpl<Key, Hasher, KeyEqual, Alloc, std::false_type> { + using Super = f14::detail:: + F14VectorSetImpl<Key, Hasher, KeyEqual, Alloc, std::false_type>; + + public: + using typename Super::const_iterator; + using typename Super::iterator; + using typename Super::value_type; + using reverse_iterator = typename Super::Policy::ReverseIter; + using const_reverse_iterator = reverse_iterator; + + F14VectorSet() = default; + + using Super::Super; + + F14VectorSet& operator=(std::initializer_list<value_type> ilist) { + Super::operator=(ilist); + return *this; + } + + void swap(F14VectorSet& rhs) noexcept(Super::Policy::kSwapIsNoexcept) { + this->table_.swap(rhs.table_); + } + + // ITERATION ORDER + // + // Deterministic iteration order for insert-only workloads is part of + // F14VectorSet's supported API: iterator is LIFO and reverse_iterator + // is FIFO. + // + // If there have been no calls to erase() then iterator and + // const_iterator enumerate entries in the opposite of insertion order. + // begin()->first is the key most recently inserted. reverse_iterator + // and reverse_const_iterator, therefore, enumerate in LIFO (insertion) + // order for insert-only workloads. Deterministic iteration order is + // only guaranteed if no keys were removed since the last time the + // set was empty. Iteration order is preserved across rehashes and + // F14VectorSet copies and moves. + // + // iterator uses LIFO order so that erasing while iterating with begin() + // and end() is safe using the erase(it++) idiom, which is supported + // by std::set and std::unordered_set. erase(iter) invalidates iter + // and all iterators before iter in the non-reverse iteration order. + // Every successful erase invalidates all reverse iterators. + // + // No erase is provided for reverse_iterator (AKA const_reverse_iterator) + // to make it harder to shoot yourself in the foot by erasing while + // reverse-iterating. You can write that as set.erase(set.iter(riter)) + // if you need it. + + reverse_iterator rbegin() { + return this->table_.values_; + } + const_reverse_iterator rbegin() const { + return crbegin(); + } + const_reverse_iterator crbegin() const { + return this->table_.values_; + } + + reverse_iterator rend() { + return this->table_.values_ + this->table_.size(); + } + const_reverse_iterator rend() const { + return crend(); + } + const_reverse_iterator crend() const { + return this->table_.values_ + this->table_.size(); + } + + // explicit conversions between iterator and reverse_iterator + iterator iter(reverse_iterator riter) { + return this->table_.iter(riter); + } + const_iterator iter(const_reverse_iterator riter) const { + return this->table_.iter(riter); + } + + reverse_iterator riter(iterator it) { + return this->table_.riter(it); + } + const_reverse_iterator riter(const_iterator it) const { + return this->table_.riter(it); + } +}; + +template <typename K, typename H, typename E, typename A> +Range<typename F14VectorSet<K, H, E, A>::const_reverse_iterator> +order_preserving_reinsertion_view(const F14VectorSet<K, H, E, A>& c) { + return {c.rbegin(), c.rend()}; +} + +template <typename Key, typename Hasher, typename KeyEqual, typename Alloc> +class F14FastSet + : public std::conditional_t< + sizeof(Key) < 24, + F14ValueSet<Key, Hasher, KeyEqual, Alloc>, + f14::detail:: + F14VectorSetImpl<Key, Hasher, KeyEqual, Alloc, std::true_type>> { + using Super = std::conditional_t< + sizeof(Key) < 24, + F14ValueSet<Key, Hasher, KeyEqual, Alloc>, + f14::detail:: + F14VectorSetImpl<Key, Hasher, KeyEqual, Alloc, std::true_type>>; + + public: + using typename Super::value_type; + + F14FastSet() = default; + + using Super::Super; + + F14FastSet& operator=(std::initializer_list<value_type> ilist) { + Super::operator=(ilist); + return *this; + } + + void swap(F14FastSet& rhs) noexcept(Super::Policy::kSwapIsNoexcept) { + this->table_.swap(rhs.table_); + } +}; +} // namespace folly + +#else // !if FOLLY_F14_VECTOR_INTRINSICS_AVAILABLE + +//////// Compatibility for unsupported platforms (not x86_64 and not aarch64) + +#include <unordered_set> + +namespace folly { + +namespace f14 { +namespace detail { +template <typename K, typename H, typename E, typename A> +class F14BasicSet : public std::unordered_set<K, H, E, A> { + using Super = std::unordered_set<K, H, E, A>; + + public: + using typename Super::pointer; + using typename Super::value_type; + + F14BasicSet() = default; + + using Super::Super; + + //// PUBLIC - F14 Extensions + + bool containsEqualValue(value_type const& value) const { + auto slot = this->bucket(value); + auto e = this->end(slot); + for (auto b = this->begin(slot); b != e; ++b) { + if (*b == value) { + return true; + } + } + return false; + } + + // exact for libstdc++, approximate for others + std::size_t getAllocatedMemorySize() const { + std::size_t rv = 0; + visitAllocationClasses( + [&](std::size_t bytes, std::size_t n) { rv += bytes * n; }); + return rv; + } + + // exact for libstdc++, approximate for others + template <typename V> + void visitAllocationClasses(V&& visitor) const { + auto bc = this->bucket_count(); + if (bc > 1) { + visitor(bc * sizeof(pointer), 1); + } + if (this->size() > 0) { + visitor(sizeof(StdNodeReplica<K, value_type, H>), this->size()); + } + } + + template <typename V> + void visitContiguousRanges(V&& visitor) const { + for (value_type const& entry : *this) { + value_type const* b = std::addressof(entry); + visitor(b, b + 1); + } + } +}; +} // namespace detail +} // namespace f14 + +template <typename Key, typename Hasher, typename KeyEqual, typename Alloc> +class F14NodeSet + : public f14::detail::F14BasicSet<Key, Hasher, KeyEqual, Alloc> { + using Super = f14::detail::F14BasicSet<Key, Hasher, KeyEqual, Alloc>; + + public: + using typename Super::value_type; + + F14NodeSet() = default; + + using Super::Super; + + F14NodeSet& operator=(std::initializer_list<value_type> ilist) { + Super::operator=(ilist); + return *this; + } +}; + +template <typename Key, typename Hasher, typename KeyEqual, typename Alloc> +class F14ValueSet + : public f14::detail::F14BasicSet<Key, Hasher, KeyEqual, Alloc> { + using Super = f14::detail::F14BasicSet<Key, Hasher, KeyEqual, Alloc>; + + public: + using typename Super::value_type; + + F14ValueSet() : Super() {} + + using Super::Super; + + F14ValueSet& operator=(std::initializer_list<value_type> ilist) { + Super::operator=(ilist); + return *this; + } +}; + +template <typename Key, typename Hasher, typename KeyEqual, typename Alloc> +class F14VectorSet + : public f14::detail::F14BasicSet<Key, Hasher, KeyEqual, Alloc> { + using Super = f14::detail::F14BasicSet<Key, Hasher, KeyEqual, Alloc>; + + public: + using typename Super::value_type; + + F14VectorSet() = default; + + using Super::Super; + + F14VectorSet& operator=(std::initializer_list<value_type> ilist) { + Super::operator=(ilist); + return *this; + } +}; + +template <typename Key, typename Hasher, typename KeyEqual, typename Alloc> +class F14FastSet + : public f14::detail::F14BasicSet<Key, Hasher, KeyEqual, Alloc> { + using Super = f14::detail::F14BasicSet<Key, Hasher, KeyEqual, Alloc>; + + public: + using typename Super::value_type; + + F14FastSet() = default; + + using Super::Super; + + F14FastSet& operator=(std::initializer_list<value_type> ilist) { + Super::operator=(ilist); + return *this; + } +}; +} // namespace folly + +#endif // if FOLLY_F14_VECTOR_INTRINSICS_AVAILABLE else + +namespace folly { +namespace f14 { +namespace detail { +template <typename S> +bool setsEqual(S const& lhs, S const& rhs) { + if (lhs.size() != rhs.size()) { + return false; + } + for (auto& k : lhs) { + if (!rhs.containsEqualValue(k)) { + return false; + } + } + return true; +} +} // namespace detail +} // namespace f14 + +template <typename K, typename H, typename E, typename A> +bool operator==( + F14ValueSet<K, H, E, A> const& lhs, + F14ValueSet<K, H, E, A> const& rhs) { + return setsEqual(lhs, rhs); +} + +template <typename K, typename H, typename E, typename A> +bool operator!=( + F14ValueSet<K, H, E, A> const& lhs, + F14ValueSet<K, H, E, A> const& rhs) { + return !(lhs == rhs); +} + +template <typename K, typename H, typename E, typename A> +bool operator==( + F14NodeSet<K, H, E, A> const& lhs, + F14NodeSet<K, H, E, A> const& rhs) { + return setsEqual(lhs, rhs); +} + +template <typename K, typename H, typename E, typename A> +bool operator!=( + F14NodeSet<K, H, E, A> const& lhs, + F14NodeSet<K, H, E, A> const& rhs) { + return !(lhs == rhs); +} template <typename K, typename H, typename E, typename A> bool operator==( @@ -1065,33 +1212,20 @@ bool operator!=( F14VectorSet<K, H, E, A> const& rhs) { return !(lhs == rhs); } -} // namespace folly -#endif // FOLLY_F14_VECTOR_INTRINSICS_AVAILABLE +template <typename K, typename H, typename E, typename A> +bool operator==( + F14FastSet<K, H, E, A> const& lhs, + F14FastSet<K, H, E, A> const& rhs) { + return setsEqual(lhs, rhs); +} -namespace folly { -template <typename Key, typename Hasher, typename KeyEqual, typename Alloc> -class F14FastSet : public std::conditional_t< - sizeof(Key) < 24, - F14ValueSet<Key, Hasher, KeyEqual, Alloc>, - F14VectorSet<Key, Hasher, KeyEqual, Alloc>> { - using Super = std::conditional_t< - sizeof(Key) < 24, - F14ValueSet<Key, Hasher, KeyEqual, Alloc>, - F14VectorSet<Key, Hasher, KeyEqual, Alloc>>; - - public: - using typename Super::value_type; - - F14FastSet() = default; - - using Super::Super; - - F14FastSet& operator=(std::initializer_list<value_type> ilist) { - Super::operator=(ilist); - return *this; - } -}; +template <typename K, typename H, typename E, typename A> +bool operator!=( + F14FastSet<K, H, E, A> const& lhs, + F14FastSet<K, H, E, A> const& rhs) { + return !(lhs == rhs); +} template <typename K, typename H, typename E, typename A> void swap(F14ValueSet<K, H, E, A>& lhs, F14ValueSet<K, H, E, A>& rhs) noexcept( @@ -1118,4 +1252,24 @@ void swap(F14FastSet<K, H, E, A>& lhs, F14FastSet<K, H, E, A>& rhs) noexcept( lhs.swap(rhs); } +template <typename K, typename H, typename E, typename A, typename Pred> +void erase_if(F14ValueSet<K, H, E, A>& c, Pred pred) { + f14::detail::erase_if_impl(c, pred); +} + +template <typename K, typename H, typename E, typename A, typename Pred> +void erase_if(F14NodeSet<K, H, E, A>& c, Pred pred) { + f14::detail::erase_if_impl(c, pred); +} + +template <typename K, typename H, typename E, typename A, typename Pred> +void erase_if(F14VectorSet<K, H, E, A>& c, Pred pred) { + f14::detail::erase_if_impl(c, pred); +} + +template <typename K, typename H, typename E, typename A, typename Pred> +void erase_if(F14FastSet<K, H, E, A>& c, Pred pred) { + f14::detail::erase_if_impl(c, pred); +} + } // namespace folly diff --git a/ios/Pods/Folly/folly/container/Foreach-inl.h b/ios/Pods/Folly/folly/container/Foreach-inl.h index 1079b8dad..3ae127ed7 100644 --- a/ios/Pods/Folly/folly/container/Foreach-inl.h +++ b/ios/Pods/Folly/folly/container/Foreach-inl.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -207,7 +207,7 @@ void for_each_range_impl(index_constant<1>, Sequence&& range, Func& func) { */ template <typename Sequence, typename Func, std::size_t... Indices> void for_each_tuple_impl( - index_sequence<Indices...>, + std::index_sequence<Indices...>, Sequence&& seq, Func& func) { using _ = int[]; @@ -246,7 +246,9 @@ void for_each_tuple_impl(index_constant<2>, Sequence&& seq, Func& func) { // optimization over manual template "tail recursion" unrolling using size = std::tuple_size<typename std::decay<Sequence>::type>; for_each_tuple_impl( - make_index_sequence<size::value>{}, std::forward<Sequence>(seq), func); + std::make_index_sequence<size::value>{}, + std::forward<Sequence>(seq), + func); } template <typename Sequence, typename Func> void for_each_tuple_impl(index_constant<1>, Sequence&& seq, Func& func) { @@ -267,14 +269,14 @@ void for_each_tuple_impl(index_constant<1>, Sequence&& seq, Func& func) { * range rather than as a tuple */ template <typename Sequence, typename Func> -static void for_each_impl(TupleTag, Sequence&& range, Func& func) { +void for_each_impl(TupleTag, Sequence&& range, Func& func) { using type = decltype(get_impl<0>(std::declval<Sequence>())); using tag = ForEachImplTag<Func, type, void>; static_assert(!std::is_same<tag, void>::value, "unknown invocability"); for_each_tuple_impl(tag{}, std::forward<Sequence>(range), func); } template <typename Sequence, typename Func> -static void for_each_impl(RangeTag, Sequence&& range, Func& func) { +void for_each_impl(RangeTag, Sequence&& range, Func& func) { using iter = decltype(adl::adl_begin(std::declval<Sequence>())); using type = decltype(*std::declval<iter>()); using tag = ForEachImplTag<Func, type, iter>; @@ -311,7 +313,7 @@ decltype(auto) fetch_impl(RangeTag, Sequence&& sequence, Index&& index) { } // namespace for_each_detail template <typename Sequence, typename Func> -FOLLY_CPP14_CONSTEXPR Func for_each(Sequence&& sequence, Func func) { +constexpr Func for_each(Sequence&& sequence, Func func) { namespace fed = for_each_detail; using tag = fed::SequenceTag<Sequence>; fed::for_each_impl(tag{}, std::forward<Sequence>(sequence), func); @@ -319,7 +321,7 @@ FOLLY_CPP14_CONSTEXPR Func for_each(Sequence&& sequence, Func func) { } template <typename Sequence, typename Index> -FOLLY_CPP14_CONSTEXPR decltype(auto) fetch(Sequence&& sequence, Index&& index) { +constexpr decltype(auto) fetch(Sequence&& sequence, Index&& index) { namespace fed = for_each_detail; using tag = fed::SequenceTag<Sequence>; return for_each_detail::fetch_impl( diff --git a/ios/Pods/Folly/folly/container/Foreach.h b/ios/Pods/Folly/folly/container/Foreach.h index f61fed8af..e35a8f5eb 100644 --- a/ios/Pods/Folly/folly/container/Foreach.h +++ b/ios/Pods/Folly/folly/container/Foreach.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -83,7 +83,7 @@ namespace folly { * }); */ template <typename Range, typename Func> -FOLLY_CPP14_CONSTEXPR Func for_each(Range&& range, Func func); +constexpr Func for_each(Range&& range, Func func); /** * The user should return loop_break and loop_continue if they want to iterate @@ -119,7 +119,7 @@ constexpr auto loop_continue = for_each_detail::LoopControl::CONTINUE; * required element. */ template <typename Sequence, typename Index> -FOLLY_CPP14_CONSTEXPR decltype(auto) fetch(Sequence&& sequence, Index&& index); +constexpr decltype(auto) fetch(Sequence&& sequence, Index&& index); } // namespace folly @@ -149,7 +149,7 @@ FOLLY_CPP14_CONSTEXPR decltype(auto) fetch(Sequence&& sequence, Index&& index); /* * If you just want the element values, please use this (ranges-v3) construct: * - * for (auto&& element : collection | view::reverse) + * for (auto&& element : collection | views::reverse) * * If you need access to the iterators please write an explicit iterator loop */ @@ -179,11 +179,11 @@ FOLLY_CPP14_CONSTEXPR decltype(auto) fetch(Sequence&& sequence, Index&& index); /** * If you just want the keys, please use this (ranges-v3) construct: * - * for (auto&& element : collection | view::keys) + * for (auto&& element : collection | views::keys) * * If you just want the values, please use this (ranges-v3) construct: * - * for (auto&& element : collection | view::values) + * for (auto&& element : collection | views::values) * * If you need to see both, use: * @@ -208,21 +208,6 @@ FOLLY_CPP14_CONSTEXPR decltype(auto) fetch(Sequence&& sequence, Index&& index); namespace folly { namespace detail { -// Boost 1.48 lacks has_less, we emulate a subset of it here. -template <typename T, typename U> -class HasLess { - struct BiggerThanChar { - char unused[2]; - }; - template <typename C, typename D> - static char test(decltype(C() < D())*); - template <typename, typename> - static BiggerThanChar test(...); - - public: - enum { value = sizeof(test<T, U>(nullptr)) == 1 }; -}; - /** * notThereYet helps the FOR_EACH_RANGE macro by opportunistically * using "<" instead of "!=" whenever available when checking for loop @@ -231,34 +216,10 @@ class HasLess { * forever. At the same time, some iterator types define "!=" but not * "<". The notThereYet function will dispatch differently for those. * - * Below is the correct implementation of notThereYet. It is disabled - * because of a bug in Boost 1.46: The filesystem::path::iterator - * defines operator< (via boost::iterator_facade), but that in turn - * uses distance_to which is undefined for that particular - * iterator. So HasLess (defined above) identifies - * boost::filesystem::path as properly comparable with <, but in fact - * attempting to do so will yield a compile-time error. - * - * The else branch (active) contains a conservative - * implementation. + * The code below uses `<` for a conservative subset of types for which + * it is known to be valid. */ -#if 0 - -template <class T, class U> -typename std::enable_if<HasLess<T, U>::value, bool>::type -notThereYet(T& iter, const U& end) { - return iter < end; -} - -template <class T, class U> -typename std::enable_if<!HasLess<T, U>::value, bool>::type -notThereYet(T& iter, const U& end) { - return iter != end; -} - -#else - template <class T, class U> typename std::enable_if< (std::is_arithmetic<T>::value && std::is_arithmetic<U>::value) || @@ -277,30 +238,6 @@ notThereYet(T& iter, const U& end) { return iter != end; } -#endif - -/** - * downTo is similar to notThereYet, but in reverse - it helps the - * FOR_EACH_RANGE_R macro. - */ -template <class T, class U> -typename std::enable_if<HasLess<U, T>::value, bool>::type downTo( - T& iter, - const U& begin) { - return begin < iter--; -} - -template <class T, class U> -typename std::enable_if<!HasLess<U, T>::value, bool>::type downTo( - T& iter, - const U& begin) { - if (iter == begin) { - return false; - } - --iter; - return true; -} - } // namespace detail } // namespace folly @@ -308,20 +245,11 @@ typename std::enable_if<!HasLess<U, T>::value, bool>::type downTo( * Look at the Ranges-v3 views and you'll probably find an easier way to build * the view you want but the equivalent is roughly: * - * for (auto& element : make_iterator_range(begin, end)) + * for (auto& element : make_subrange(begin, end)) */ #define FOR_EACH_RANGE(i, begin, end) \ for (auto i = (true ? (begin) : (end)); \ ::folly::detail::notThereYet(i, (end)); \ ++i) -/* - * Look at the Ranges-v3 views and you'll probably find an easier way to build - * the view you want but the equivalent is roughly: - * - * for (auto& element : make_iterator_range(begin, end) | view::reverse) - */ -#define FOR_EACH_RANGE_R(i, begin, end) \ - for (auto i = (false ? (begin) : (end)); ::folly::detail::downTo(i, (begin));) - #include <folly/container/Foreach-inl.h> diff --git a/ios/Pods/Folly/folly/container/HeterogeneousAccess-fwd.h b/ios/Pods/Folly/folly/container/HeterogeneousAccess-fwd.h new file mode 100644 index 000000000..bbe2a057e --- /dev/null +++ b/ios/Pods/Folly/folly/container/HeterogeneousAccess-fwd.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +namespace folly { + +template <typename T, typename Enable = void> +struct HeterogeneousAccessEqualTo; + +template <typename T, typename Enable = void> +struct HeterogeneousAccessHash; + +template <typename CharT> +struct TransparentStringEqualTo; + +template <typename CharT> +struct TransparentStringHash; + +} // namespace folly diff --git a/ios/Pods/Folly/folly/container/HeterogeneousAccess.h b/ios/Pods/Folly/folly/container/HeterogeneousAccess.h new file mode 100644 index 000000000..ffebe752e --- /dev/null +++ b/ios/Pods/Folly/folly/container/HeterogeneousAccess.h @@ -0,0 +1,164 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <functional> +#include <string> + +#include <folly/Range.h> +#include <folly/Traits.h> +#include <folly/container/HeterogeneousAccess-fwd.h> +#include <folly/hash/Hash.h> + +namespace folly { + +// folly::HeterogeneousAccessEqualTo<T>, and +// folly::HeterogeneousAccessHash<T> are functors suitable as defaults +// for containers that support heterogeneous access. When possible, they +// will be marked as transparent. When no transparent implementation +// is available then they fall back to std::equal_to and std::hash +// respectively. Since the fallbacks are not marked as transparent, +// heterogeneous lookup won't be available in that case. A corresponding +// HeterogeneousAccessLess<T> could be easily added if desired. +// +// If T can be implicitly converted to a StringPiece or +// to a Range<T::value_type const*> that is hashable, then +// HeterogeneousAccess{EqualTo,Hash}<T> will be transparent without any +// additional work. In practice this is true for T that can be convered to +// StringPiece or Range<IntegralType const*>. This includes std::string, +// std::string_view (when available), std::array, folly::Range, +// std::vector, and folly::small_vector. +// +// Additional specializations of HeterogeneousAccess*<T> should go in +// the header that declares T. Don't forget to typedef is_transparent to +// void and folly_is_avalanching to std::true_type in the specializations. + +template <typename T, typename Enable> +struct HeterogeneousAccessEqualTo : std::equal_to<T> {}; + +template <typename T, typename Enable> +struct HeterogeneousAccessHash : std::hash<T> { + using folly_is_avalanching = IsAvalanchingHasher<std::hash<T>, T>; +}; + +//////// strings + +namespace detail { + +template <typename T, typename Enable = void> +struct ValueTypeForTransparentConversionToRange { + using type = char; +}; + +// We assume that folly::hasher<folly::Range<T const*>> won't be enabled +// when it would be lower quality than std::hash<U> for a U that is +// convertible to folly::Range<T const*>. +template <typename T> +struct ValueTypeForTransparentConversionToRange< + T, + void_t<decltype( + std::declval<hasher<Range<typename T::value_type const*>>>()( + std::declval<Range<typename T::value_type const*>>()))>> { + using type = std::remove_const_t<typename T::value_type>; +}; + +template <typename T> +using TransparentlyConvertibleToRange = std::is_convertible< + T, + Range<typename ValueTypeForTransparentConversionToRange<T>::type const*>>; + +template <typename T> +struct TransparentRangeEqualTo { + using is_transparent = void; + + template <typename U1, typename U2> + bool operator()(U1 const& lhs, U2 const& rhs) const { + return Range<T const*>{lhs} == Range<T const*>{rhs}; + } + + // This overload is not required for functionality, but + // guarantees that replacing std::equal_to<std::string> with + // HeterogeneousAccessEqualTo<std::string> is truly zero overhead + bool operator()(std::string const& lhs, std::string const& rhs) const { + return lhs == rhs; + } +}; + +template <typename T> +struct TransparentRangeHash { + using is_transparent = void; + using folly_is_avalanching = std::true_type; + + private: + template <typename U> + static std::size_t hashImpl(Range<U const*> piece) { + return hasher<Range<U const*>>{}(piece); + } + + static std::size_t hashImpl(StringPiece piece) { +#if defined(_GLIBCXX_STRING) + return std::_Hash_impl::hash(piece.begin(), piece.size()); +#elif defined(_LIBCPP_STRING) + return std::__do_string_hash(piece.begin(), piece.end()); +#else + return hasher<StringPiece>{}(piece); +#endif + } + + public: + template <typename U> + std::size_t operator()(U const& stringish) const { + return hashImpl(Range<T const*>{stringish}); + } + + // Neither this overload nor the platform-conditional compilation + // is required for functionality, but implementing it this + // way guarantees that replacing std::hash<std::string> with + // HeterogeneousAccessHash<std::string> is actually zero overhead + // in the case that the underlying implementations make different + // optimality tradeoffs (short versus long string performance, for + // example). If folly::hasher<StringPiece> dominated the performance + // of std::hash<std::string> then we should consider using it all of + // the time. + std::size_t operator()(std::string const& str) const { +#if defined(_GLIBCXX_STRING) || defined(_LIBCPP_STRING) + return std::hash<std::string>{}(str); +#else + return hasher<StringPiece>{}(str); +#endif + } +}; + +} // namespace detail + +template <typename T> +struct HeterogeneousAccessEqualTo< + T, + std::enable_if_t<detail::TransparentlyConvertibleToRange<T>::value>> + : detail::TransparentRangeEqualTo< + typename detail::ValueTypeForTransparentConversionToRange<T>::type> { +}; + +template <typename T> +struct HeterogeneousAccessHash< + T, + std::enable_if_t<detail::TransparentlyConvertibleToRange<T>::value>> + : detail::TransparentRangeHash< + typename detail::ValueTypeForTransparentConversionToRange<T>::type> { +}; + +} // namespace folly diff --git a/ios/Pods/Folly/folly/container/Iterator.h b/ios/Pods/Folly/folly/container/Iterator.h index 69500987d..294406fa8 100644 --- a/ios/Pods/Folly/folly/container/Iterator.h +++ b/ios/Pods/Folly/folly/container/Iterator.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -252,15 +252,16 @@ class emplace_iterator_base<Derived, EmplaceImpl, false> */ template <typename... Args> Derived& operator=(emplace_args<Args...>& args) { - return unpackAndEmplace(args, index_sequence_for<Args...>{}); + return unpackAndEmplace(args, std::index_sequence_for<Args...>{}); } template <typename... Args> Derived& operator=(const emplace_args<Args...>& args) { - return unpackAndEmplace(args, index_sequence_for<Args...>{}); + return unpackAndEmplace(args, std::index_sequence_for<Args...>{}); } template <typename... Args> Derived& operator=(emplace_args<Args...>&& args) { - return unpackAndEmplace(std::move(args), index_sequence_for<Args...>{}); + return unpackAndEmplace( + std::move(args), std::index_sequence_for<Args...>{}); } // No-ops. @@ -284,17 +285,17 @@ class emplace_iterator_base<Derived, EmplaceImpl, false> protected: template <typename Args, std::size_t... I> - Derived& unpackAndEmplace(Args& args, index_sequence<I...>) { + Derived& unpackAndEmplace(Args& args, std::index_sequence<I...>) { this->emplace(get_emplace_arg<I>(args)...); return static_cast<Derived&>(*this); } template <typename Args, std::size_t... I> - Derived& unpackAndEmplace(const Args& args, index_sequence<I...>) { + Derived& unpackAndEmplace(const Args& args, std::index_sequence<I...>) { this->emplace(get_emplace_arg<I>(args)...); return static_cast<Derived&>(*this); } template <typename Args, std::size_t... I> - Derived& unpackAndEmplace(Args&& args, index_sequence<I...>) { + Derived& unpackAndEmplace(Args&& args, std::index_sequence<I...>) { this->emplace(get_emplace_arg<I>(std::move(args))...); return static_cast<Derived&>(*this); } @@ -323,16 +324,16 @@ class emplace_iterator_base<Derived, EmplaceImpl, true> */ template <typename... Args> Derived& operator=(std::pair<Args...>& args) { - return this->unpackAndEmplace(args, index_sequence_for<Args...>{}); + return this->unpackAndEmplace(args, std::index_sequence_for<Args...>{}); } template <typename... Args> Derived& operator=(const std::pair<Args...>& args) { - return this->unpackAndEmplace(args, index_sequence_for<Args...>{}); + return this->unpackAndEmplace(args, std::index_sequence_for<Args...>{}); } template <typename... Args> Derived& operator=(std::pair<Args...>&& args) { return this->unpackAndEmplace( - std::move(args), index_sequence_for<Args...>{}); + std::move(args), std::index_sequence_for<Args...>{}); } /** @@ -341,16 +342,16 @@ class emplace_iterator_base<Derived, EmplaceImpl, true> */ template <typename... Args> Derived& operator=(std::tuple<Args...>& args) { - return this->unpackAndEmplace(args, index_sequence_for<Args...>{}); + return this->unpackAndEmplace(args, std::index_sequence_for<Args...>{}); } template <typename... Args> Derived& operator=(const std::tuple<Args...>& args) { - return this->unpackAndEmplace(args, index_sequence_for<Args...>{}); + return this->unpackAndEmplace(args, std::index_sequence_for<Args...>{}); } template <typename... Args> Derived& operator=(std::tuple<Args...>&& args) { return this->unpackAndEmplace( - std::move(args), index_sequence_for<Args...>{}); + std::move(args), std::index_sequence_for<Args...>{}); } // We need all of these explicit defaults because the custom operator= diff --git a/ios/Pods/Folly/folly/container/Merge.h b/ios/Pods/Folly/folly/container/Merge.h index 959ec0521..b10cda73f 100644 --- a/ios/Pods/Folly/folly/container/Merge.h +++ b/ios/Pods/Folly/folly/container/Merge.h @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/container/SparseByteSet.h b/ios/Pods/Folly/folly/container/SparseByteSet.h index 717fa2d33..7bf7a8a12 100644 --- a/ios/Pods/Folly/folly/container/SparseByteSet.h +++ b/ios/Pods/Folly/folly/container/SparseByteSet.h @@ -1,11 +1,11 @@ /* - * Copyright 2015-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/container/detail/BitIteratorDetail.h b/ios/Pods/Folly/folly/container/detail/BitIteratorDetail.h index 8eb9491af..8a5b4ee70 100644 --- a/ios/Pods/Folly/folly/container/detail/BitIteratorDetail.h +++ b/ios/Pods/Folly/folly/container/detail/BitIteratorDetail.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -80,7 +80,8 @@ struct BitIteratorBase { BitIterator<BaseIter>, // Derived BaseIter, // Base bool, // Value - boost::use_default, // CategoryOrTraversal + typename std::iterator_traits< + BaseIter>::iterator_category, // CategoryOrTraversal bititerator_detail::BitReference< typename std::iterator_traits<BaseIter>::reference, typename std::iterator_traits<BaseIter>::value_type>, // Reference diff --git a/ios/Pods/Folly/folly/container/detail/F14Defaults.h b/ios/Pods/Folly/folly/container/detail/F14Defaults.h index 46ebbe598..bfc5a2839 100644 --- a/ios/Pods/Folly/folly/container/detail/F14Defaults.h +++ b/ios/Pods/Folly/folly/container/detail/F14Defaults.h @@ -1,11 +1,11 @@ /* - * Copyright 2018-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -16,16 +16,17 @@ #pragma once -#include <functional> #include <memory> +#include <folly/container/HeterogeneousAccess-fwd.h> + namespace folly { namespace f14 { template <typename T> -using DefaultHasher = std::hash<T>; +using DefaultHasher = HeterogeneousAccessHash<T>; template <typename T> -using DefaultKeyEqual = std::equal_to<T>; +using DefaultKeyEqual = HeterogeneousAccessEqualTo<T>; template <typename T> using DefaultAlloc = std::allocator<T>; diff --git a/ios/Pods/Folly/folly/container/detail/F14IntrinsicsAvailability.h b/ios/Pods/Folly/folly/container/detail/F14IntrinsicsAvailability.h index e9bc63037..c917c5dba 100644 --- a/ios/Pods/Folly/folly/container/detail/F14IntrinsicsAvailability.h +++ b/ios/Pods/Folly/folly/container/detail/F14IntrinsicsAvailability.h @@ -1,11 +1,11 @@ /* - * Copyright 2018-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/container/detail/F14Mask.h b/ios/Pods/Folly/folly/container/detail/F14Mask.h new file mode 100644 index 000000000..ec301a8c1 --- /dev/null +++ b/ios/Pods/Folly/folly/container/detail/F14Mask.h @@ -0,0 +1,248 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <algorithm> +#include <cstdint> + +#include <folly/Bits.h> +#include <folly/ConstexprMath.h> +#include <folly/Likely.h> +#include <folly/Portability.h> +#include <folly/lang/Assume.h> +#include <folly/lang/SafeAssert.h> + +#if (FOLLY_SSE >= 2 || (FOLLY_NEON && FOLLY_AARCH64)) && !FOLLY_MOBILE + +namespace folly { +namespace f14 { +namespace detail { + +template <typename T> +FOLLY_ALWAYS_INLINE static unsigned findFirstSetNonZero(T mask) { + assume(mask != 0); + if (sizeof(mask) == sizeof(unsigned)) { + return __builtin_ctz(static_cast<unsigned>(mask)); + } else { + return __builtin_ctzll(mask); + } +} + +#if FOLLY_NEON +using MaskType = uint64_t; + +constexpr unsigned kMaskSpacing = 4; +#else // SSE2 +using MaskType = uint32_t; + +constexpr unsigned kMaskSpacing = 1; +#endif + +template <unsigned BitCount> +struct FullMask { + static constexpr MaskType value = + (FullMask<BitCount - 1>::value << kMaskSpacing) + 1; +}; + +template <> +struct FullMask<1> : std::integral_constant<MaskType, 1> {}; + +#if FOLLY_ARM +// Mask iteration is different for ARM because that is the only platform +// for which the mask is bigger than a register. + +// Iterates a mask, optimized for the case that only a few bits are set +class SparseMaskIter { + static_assert(kMaskSpacing == 4, ""); + + uint32_t interleavedMask_; + + public: + explicit SparseMaskIter(MaskType mask) + : interleavedMask_{static_cast<uint32_t>(((mask >> 32) << 2) | mask)} {} + + bool hasNext() { + return interleavedMask_ != 0; + } + + unsigned next() { + FOLLY_SAFE_DCHECK(hasNext(), ""); + unsigned i = findFirstSetNonZero(interleavedMask_); + interleavedMask_ &= (interleavedMask_ - 1); + return ((i >> 2) | (i << 2)) & 0xf; + } +}; + +// Iterates a mask, optimized for the case that most bits are set +class DenseMaskIter { + static_assert(kMaskSpacing == 4, ""); + + std::size_t count_; + unsigned index_; + uint8_t const* tags_; + + public: + explicit DenseMaskIter(uint8_t const* tags, MaskType mask) { + if (mask == 0) { + count_ = 0; + } else { + count_ = popcount(static_cast<uint32_t>(((mask >> 32) << 2) | mask)); + if (LIKELY((mask & 1) != 0)) { + index_ = 0; + } else { + index_ = findFirstSetNonZero(mask) / kMaskSpacing; + } + tags_ = tags; + } + } + + bool hasNext() { + return count_ > 0; + } + + unsigned next() { + auto rv = index_; + --count_; + if (count_ > 0) { + do { + ++index_; + } while ((tags_[index_] & 0x80) == 0); + } + FOLLY_SAFE_DCHECK(index_ < 16, ""); + return rv; + } +}; + +#else +// Iterates a mask, optimized for the case that only a few bits are set +class SparseMaskIter { + MaskType mask_; + + public: + explicit SparseMaskIter(MaskType mask) : mask_{mask} {} + + bool hasNext() { + return mask_ != 0; + } + + unsigned next() { + FOLLY_SAFE_DCHECK(hasNext(), ""); + unsigned i = findFirstSetNonZero(mask_); + mask_ &= (mask_ - 1); + return i / kMaskSpacing; + } +}; + +// Iterates a mask, optimized for the case that most bits are set +class DenseMaskIter { + MaskType mask_; + unsigned index_{0}; + + public: + explicit DenseMaskIter(uint8_t const*, MaskType mask) : mask_{mask} {} + + bool hasNext() { + return mask_ != 0; + } + + unsigned next() { + FOLLY_SAFE_DCHECK(hasNext(), ""); + if (LIKELY((mask_ & 1) != 0)) { + mask_ >>= kMaskSpacing; + return index_++; + } else { + unsigned s = findFirstSetNonZero(mask_); + unsigned rv = index_ + (s / kMaskSpacing); + mask_ >>= (s + kMaskSpacing); + index_ = rv + 1; + return rv; + } + } +}; +#endif + +// Iterates a mask, returning pairs of [begin,end) index covering blocks +// of set bits +class MaskRangeIter { + MaskType mask_; + unsigned shift_{0}; + + public: + explicit MaskRangeIter(MaskType mask) { + // If kMaskSpacing is > 1 then there will be empty bits even for + // contiguous ranges. Fill them in. + mask_ = mask * ((1 << kMaskSpacing) - 1); + } + + bool hasNext() { + return mask_ != 0; + } + + std::pair<unsigned, unsigned> next() { + FOLLY_SAFE_DCHECK(hasNext(), ""); + auto s = shift_; + unsigned b = findFirstSetNonZero(mask_); + unsigned e = findFirstSetNonZero(~(mask_ | (mask_ - 1))); + mask_ >>= e; + shift_ = s + e; + return std::make_pair((s + b) / kMaskSpacing, (s + e) / kMaskSpacing); + } +}; + +// Holds the result of an index query that has an optional result, +// interpreting a mask of 0 to be the empty answer and the index of the +// last set bit to be the non-empty answer +class LastOccupiedInMask { + MaskType mask_; + + public: + explicit LastOccupiedInMask(MaskType mask) : mask_{mask} {} + + bool hasIndex() const { + return mask_ != 0; + } + + unsigned index() const { + assume(mask_ != 0); + return (findLastSet(mask_) - 1) / kMaskSpacing; + } +}; + +// Holds the result of an index query that has an optional result, +// interpreting a mask of 0 to be the empty answer and the index of the +// first set bit to be the non-empty answer +class FirstEmptyInMask { + MaskType mask_; + + public: + explicit FirstEmptyInMask(MaskType mask) : mask_{mask} {} + + bool hasIndex() const { + return mask_ != 0; + } + + unsigned index() const { + FOLLY_SAFE_DCHECK(mask_ != 0, ""); + return findFirstSetNonZero(mask_) / kMaskSpacing; + } +}; + +} // namespace detail +} // namespace f14 +} // namespace folly + +#endif diff --git a/ios/Pods/Folly/folly/container/detail/F14Policy.h b/ios/Pods/Folly/folly/container/detail/F14Policy.h index 713732a01..fb55a49fe 100644 --- a/ios/Pods/Folly/folly/container/detail/F14Policy.h +++ b/ios/Pods/Folly/folly/container/detail/F14Policy.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -22,7 +22,9 @@ #include <folly/Memory.h> #include <folly/Portability.h> +#include <folly/Traits.h> #include <folly/Unit.h> +#include <folly/container/HeterogeneousAccess.h> #include <folly/container/detail/F14Table.h> #include <folly/hash/Hash.h> #include <folly/lang/Align.h> @@ -155,13 +157,6 @@ struct BasePolicy struct AllocIsAlwaysEqual<A, typename A::is_always_equal> : A::is_always_equal {}; - // emulate c++17 has std::is_nothrow_swappable - template <typename T> - static constexpr bool isNothrowSwap() { - using std::swap; - return noexcept(swap(std::declval<T&>(), std::declval<T&>())); - } - public: static constexpr bool kAllocIsAlwaysEqual = AllocIsAlwaysEqual<Alloc>::value; @@ -171,7 +166,7 @@ struct BasePolicy std::is_nothrow_default_constructible<Alloc>::value; static constexpr bool kSwapIsNoexcept = kAllocIsAlwaysEqual && - isNothrowSwap<Hasher>() && isNothrowSwap<KeyEqual>(); + IsNothrowSwappable<Hasher>{} && IsNothrowSwappable<KeyEqual>{}; static constexpr bool isAvalanchingHasher() { return IsAvalanchingHasher<Hasher, Key>::value; @@ -196,6 +191,10 @@ struct BasePolicy using MappedOrBool = std::conditional_t<kIsMap, Mapped, bool>; + // if true, bucket_count() after reserve(n) will be as close as possible + // to n for multi-chunk tables + static constexpr bool kContinuousCapacity = false; + //////// methods BasePolicy(Hasher const& hasher, KeyEqual const& keyEqual, Alloc const& alloc) @@ -222,21 +221,40 @@ struct BasePolicy KeyEqualHolder{std::move(rhs.keyEqual())}, AllocHolder{alloc} {} + private: + template <typename Src> + void maybeAssignAlloc(std::true_type, Src&& src) { + alloc() = std::forward<Src>(src); + } + + template <typename Src> + void maybeAssignAlloc(std::false_type, Src&&) {} + + template <typename A> + void maybeSwapAlloc(std::true_type, A& rhs) { + using std::swap; + swap(alloc(), rhs); + } + + template <typename A> + void maybeSwapAlloc(std::false_type, A&) {} + + public: BasePolicy& operator=(BasePolicy const& rhs) { hasher() = rhs.hasher(); keyEqual() = rhs.keyEqual(); - if (AllocTraits::propagate_on_container_copy_assignment::value) { - alloc() = rhs.alloc(); - } + maybeAssignAlloc( + typename AllocTraits::propagate_on_container_copy_assignment{}, + rhs.alloc()); return *this; } BasePolicy& operator=(BasePolicy&& rhs) noexcept { hasher() = std::move(rhs.hasher()); keyEqual() = std::move(rhs.keyEqual()); - if (AllocTraits::propagate_on_container_move_assignment::value) { - alloc() = std::move(rhs.alloc()); - } + maybeAssignAlloc( + typename AllocTraits::propagate_on_container_move_assignment{}, + std::move(rhs.alloc())); return *this; } @@ -244,9 +262,8 @@ struct BasePolicy using std::swap; swap(hasher(), rhs.hasher()); swap(keyEqual(), rhs.keyEqual()); - if (AllocTraits::propagate_on_container_swap::value) { - swap(alloc(), rhs.alloc()); - } + maybeSwapAlloc( + typename AllocTraits::propagate_on_container_swap{}, rhs.alloc()); } Hasher& hasher() { @@ -382,7 +399,7 @@ struct BasePolicy } void afterDestroyWithoutDeallocate(Value* addr, std::size_t n) { - if (kIsSanitizeAddress) { + if (kIsLibrarySanitizeAddress) { memset(static_cast<void*>(addr), 0x66, sizeof(Value) * n); } } @@ -571,13 +588,16 @@ class ValueContainerPolicy : public BasePolicy< return Super::moveValue(item); } + Value const& valueAtItem(Item const& item) const { + return item; + } + Value&& valueAtItemForExtract(Item& item) { return std::move(item); } - template <typename... Args> - void - constructValueAtItem(std::size_t /*size*/, Item* itemAddr, Args&&... args) { + template <typename Table, typename... Args> + void constructValueAtItem(Table&&, Item* itemAddr, Args&&... args) { Alloc& a = this->alloc(); // GCC < 6 doesn't use the fact that itemAddr came from a reference // to avoid a null-check in the placement new. folly::assume-ing it @@ -643,7 +663,7 @@ class ValueContainerPolicy : public BasePolicy< //////// F14BasicMap/Set policy - Iter makeIter(ItemIter const& underlying) const { + FOLLY_ALWAYS_INLINE Iter makeIter(ItemIter const& underlying) const { return Iter{underlying}; } ConstIter makeConstIter(ItemIter const& underlying) const { @@ -820,13 +840,16 @@ class NodeContainerPolicy return Super::moveValue(*item); } + Value const& valueAtItem(Item const& item) const { + return *item; + } + Value&& valueAtItemForExtract(Item& item) { return std::move(*item); } - template <typename... Args> - void - constructValueAtItem(std::size_t /*size*/, Item* itemAddr, Args&&... args) { + template <typename Table, typename... Args> + void constructValueAtItem(Table&&, Item* itemAddr, Args&&... args) { Alloc& a = this->alloc(); // TODO(T31574848): clean up assume-s used to optimize placement new assume(itemAddr != nullptr); @@ -834,7 +857,9 @@ class NodeContainerPolicy auto p = std::addressof(**itemAddr); // TODO(T31574848): clean up assume-s used to optimize placement new assume(p != nullptr); + auto rollback = makeGuard([&] { AllocTraits::deallocate(a, p, 1); }); AllocTraits::construct(a, p, std::forward<Args>(args)...); + rollback.dismiss(); } void moveItemDuringRehash(Item* itemAddr, Item& src) { @@ -879,7 +904,7 @@ class NodeContainerPolicy //////// F14BasicMap/Set policy - Iter makeIter(ItemIter const& underlying) const { + FOLLY_ALWAYS_INLINE Iter makeIter(ItemIter const& underlying) const { return Iter{underlying}; } ConstIter makeConstIter(ItemIter const& underlying) const { @@ -897,7 +922,8 @@ template < typename MappedTypeOrVoid, typename HasherOrVoid, typename KeyEqualOrVoid, - typename AllocOrVoid> + typename AllocOrVoid, + typename EligibleForPerturbedInsertionOrder> class VectorContainerPolicy; template <typename ValuePtr> @@ -962,7 +988,13 @@ class VectorContainerIterator : public BaseIter<ValuePtr, uint32_t> { return current_ - lowest_; } - template <typename K, typename M, typename H, typename E, typename A> + template < + typename K, + typename M, + typename H, + typename E, + typename A, + typename P> friend class VectorContainerPolicy; template <typename P> @@ -978,7 +1010,8 @@ template < typename MappedTypeOrVoid, typename HasherOrVoid, typename KeyEqualOrVoid, - typename AllocOrVoid> + typename AllocOrVoid, + typename EligibleForPerturbedInsertionOrder> class VectorContainerPolicy : public BasePolicy< Key, MappedTypeOrVoid, @@ -1013,6 +1046,8 @@ class VectorContainerPolicy : public BasePolicy< public: static constexpr bool kEnableItemIteration = false; + static constexpr bool kContinuousCapacity = true; + using InternalSizeType = Item; using ConstIter = @@ -1152,26 +1187,61 @@ class VectorContainerPolicy : public BasePolicy< return {item}; } + Value const& valueAtItem(Item const& item) const { + return values_[item]; + } + Value&& valueAtItemForExtract(Item& item) { return std::move(values_[item]); } + template <typename Table> void constructValueAtItem( - std::size_t /*size*/, + Table&&, Item* itemAddr, VectorContainerIndexSearch arg) { *itemAddr = arg.index_; } - template <typename... Args> - void constructValueAtItem(std::size_t size, Item* itemAddr, Args&&... args) { + template <typename Table, typename... Args> + void constructValueAtItem(Table&& table, Item* itemAddr, Args&&... args) { Alloc& a = this->alloc(); - FOLLY_SAFE_DCHECK(size < std::numeric_limits<InternalSizeType>::max(), ""); - *itemAddr = static_cast<InternalSizeType>(size); + auto size = static_cast<InternalSizeType>(table.size()); + FOLLY_SAFE_DCHECK( + table.size() < std::numeric_limits<InternalSizeType>::max(), ""); + *itemAddr = size; auto dst = std::addressof(values_[size]); // TODO(T31574848): clean up assume-s used to optimize placement new assume(dst != nullptr); AllocTraits::construct(a, dst, std::forward<Args>(args)...); + + constexpr bool perturb = FOLLY_F14_PERTURB_INSERTION_ORDER; + if (EligibleForPerturbedInsertionOrder::value && perturb && + !tlsPendingSafeInserts()) { + // Pick a random victim. We have to do this post-construction + // because the item and tag are already set in the table before + // calling constructValueAtItem, so if there is a tag collision + // find may evaluate values_[size] during the search. + auto i = static_cast<InternalSizeType>(tlsMinstdRand(size + 1)); + if (i != size) { + auto& lhsItem = *itemAddr; + auto rhsIter = table.find( + VectorContainerIndexSearch{static_cast<InternalSizeType>(i)}); + FOLLY_SAFE_DCHECK(!rhsIter.atEnd(), ""); + auto& rhsItem = rhsIter.item(); + FOLLY_SAFE_DCHECK(lhsItem == size, ""); + FOLLY_SAFE_DCHECK(rhsItem == i, ""); + + aligned_storage_for_t<Value> tmp; + Value* tmpValue = static_cast<Value*>(static_cast<void*>(&tmp)); + transfer(a, std::addressof(values_[i]), tmpValue, 1); + transfer( + a, std::addressof(values_[size]), std::addressof(values_[i]), 1); + transfer(a, tmpValue, std::addressof(values_[size]), 1); + lhsItem = i; + rhsItem = size; + } + } } void moveItemDuringRehash(Item* itemAddr, Item& src) { @@ -1200,7 +1270,10 @@ class VectorContainerPolicy : public BasePolicy< auto origSrc = src; if (valueIsTriviallyCopyable()) { - std::memcpy(static_cast<void*>(dst), src, n * sizeof(Value)); + std::memcpy( + static_cast<void*>(dst), + static_cast<void const*>(src), + n * sizeof(Value)); } else { for (std::size_t i = 0; i < n; ++i, ++src, ++dst) { // TODO(T31574848): clean up assume-s used to optimize placement new @@ -1226,7 +1299,10 @@ class VectorContainerPolicy : public BasePolicy< Value* dst = std::addressof(values_[0]); if (valueIsTriviallyCopyable()) { - std::memcpy(dst, src, size * sizeof(Value)); + std::memcpy( + static_cast<void*>(dst), + static_cast<void const*>(src), + size * sizeof(Value)); } else { for (std::size_t i = 0; i < size; ++i, ++src, ++dst) { try { @@ -1275,11 +1351,11 @@ class VectorContainerPolicy : public BasePolicy< private: // Returns the byte offset of the first Value in a unified allocation // that first holds prefixBytes of data, where prefixBytes comes from - // Chunk storage and hence must be at least 8-byte aligned (sub-Chunk - // allocations always have an even capacity and sizeof(Item) == 4). + // Chunk storage and may be only 4-byte aligned due to sub-chunk + // allocation. static std::size_t valuesOffset(std::size_t prefixBytes) { - FOLLY_SAFE_DCHECK((prefixBytes % 8) == 0, ""); - if (alignof(Value) > 8) { + FOLLY_SAFE_DCHECK((prefixBytes % alignof(Item)) == 0, ""); + if (alignof(Value) > alignof(Item)) { prefixBytes = -(-prefixBytes & ~(alignof(Value) - 1)); } FOLLY_SAFE_DCHECK((prefixBytes % alignof(Value)) == 0, ""); @@ -1317,7 +1393,7 @@ class VectorContainerPolicy : public BasePolicy< &*outChunkAllocation + valuesOffset(chunkAllocSize)))); if (size > 0) { - Alloc& a{this->alloc()}; + Alloc& a = this->alloc(); transfer(a, std::addressof(before[0]), std::addressof(after[0]), size); } @@ -1454,31 +1530,37 @@ class VectorContainerPolicy : public BasePolicy< }; template < - template <typename, typename, typename, typename, typename> class Policy, + template <typename, typename, typename, typename, typename, typename...> + class Policy, typename Key, typename Mapped, typename Hasher, typename KeyEqual, - typename Alloc> + typename Alloc, + typename... Args> using MapPolicyWithDefaults = Policy< Key, Mapped, VoidDefault<Hasher, DefaultHasher<Key>>, VoidDefault<KeyEqual, DefaultKeyEqual<Key>>, - VoidDefault<Alloc, DefaultAlloc<std::pair<Key const, Mapped>>>>; + VoidDefault<Alloc, DefaultAlloc<std::pair<Key const, Mapped>>>, + Args...>; template < - template <typename, typename, typename, typename, typename> class Policy, + template <typename, typename, typename, typename, typename, typename...> + class Policy, typename Key, typename Hasher, typename KeyEqual, - typename Alloc> + typename Alloc, + typename... Args> using SetPolicyWithDefaults = Policy< Key, void, VoidDefault<Hasher, DefaultHasher<Key>>, VoidDefault<KeyEqual, DefaultKeyEqual<Key>>, - VoidDefault<Alloc, DefaultAlloc<Key>>>; + VoidDefault<Alloc, DefaultAlloc<Key>>, + Args...>; } // namespace detail } // namespace f14 diff --git a/ios/Pods/Folly/folly/container/detail/F14Table.cpp b/ios/Pods/Folly/folly/container/detail/F14Table.cpp index fbc61f409..d26b7d743 100644 --- a/ios/Pods/Folly/folly/container/detail/F14Table.cpp +++ b/ios/Pods/Folly/folly/container/detail/F14Table.cpp @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -16,6 +16,9 @@ #include <folly/container/detail/F14Table.h> +#include <atomic> +#include <chrono> + namespace folly { namespace f14 { namespace detail { @@ -31,8 +34,42 @@ void F14LinkCheck<getF14IntrinsicsMode()>::check() noexcept {} EmptyTagVectorType kEmptyTagVector = {}; #endif -FOLLY_F14_TLS_IF_ASAN std::size_t asanPendingSafeInserts = 0; -FOLLY_F14_TLS_IF_ASAN std::size_t asanRehashState = 0; +//// Debug and ASAN stuff + +#if defined(FOLLY_TLS) && (!defined(NDEBUG) || FOLLY_LIBRARY_SANITIZE_ADDRESS) +#define FOLLY_F14_DETAIL_TLS_SIZE_T FOLLY_TLS std::size_t +#else +#define FOLLY_F14_DETAIL_TLS_SIZE_T std::atomic<std::size_t> +#endif + +bool tlsPendingSafeInserts(std::ptrdiff_t delta) { + static FOLLY_F14_DETAIL_TLS_SIZE_T value{0}; + + FOLLY_SAFE_DCHECK(delta >= -1, ""); + std::size_t v = value; + if (delta > 0 || (delta == -1 && v > 0)) { + v += delta; + v = std::min(std::numeric_limits<std::size_t>::max() / 2, v); + value = v; + } + return v != 0; +} + +std::size_t tlsMinstdRand(std::size_t n) { + FOLLY_SAFE_DCHECK(n > 0, ""); + + static FOLLY_F14_DETAIL_TLS_SIZE_T state{0}; + auto s = static_cast<uint32_t>(state); + if (s == 0) { + uint64_t seed = static_cast<uint64_t>( + std::chrono::steady_clock::now().time_since_epoch().count()); + s = hash::twang_32from64(seed); + } + + s = static_cast<uint32_t>((s * uint64_t{48271}) % uint64_t{2147483647}); + state = s; + return std::size_t{s} % n; +} } // namespace detail } // namespace f14 diff --git a/ios/Pods/Folly/folly/container/detail/F14Table.h b/ios/Pods/Folly/folly/container/detail/F14Table.h index 0c7cc5803..a4395924e 100644 --- a/ios/Pods/Folly/folly/container/detail/F14Table.h +++ b/ios/Pods/Folly/folly/container/detail/F14Table.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -29,25 +29,31 @@ #include <utility> #include <vector> +#if FOLLY_HAS_STRING_VIEW +#include <string_view> // @manual +#endif + #include <folly/Bits.h> #include <folly/ConstexprMath.h> #include <folly/Likely.h> #include <folly/Portability.h> #include <folly/ScopeGuard.h> #include <folly/Traits.h> -#include <folly/functional/ApplyTuple.h> #include <folly/functional/Invoke.h> #include <folly/lang/Align.h> #include <folly/lang/Assume.h> #include <folly/lang/Exception.h> #include <folly/lang/Launder.h> +#include <folly/lang/Pretty.h> #include <folly/lang/SafeAssert.h> #include <folly/portability/Builtins.h> +#include <folly/container/HeterogeneousAccess.h> #include <folly/container/detail/F14Defaults.h> #include <folly/container/detail/F14IntrinsicsAvailability.h> +#include <folly/container/detail/F14Mask.h> -#if FOLLY_ASAN_ENABLED && defined(FOLLY_TLS) +#if FOLLY_LIBRARY_SANITIZE_ADDRESS && defined(FOLLY_TLS) #define FOLLY_F14_TLS_IF_ASAN FOLLY_TLS #else #define FOLLY_F14_TLS_IF_ASAN @@ -70,12 +76,17 @@ #if FOLLY_NEON #include <arm_neon.h> // uint8x16t intrinsics #else // SSE2 +#include <emmintrin.h> // _mm_set1_epi8 #include <immintrin.h> // __m128i intrinsics #include <xmmintrin.h> // _mm_prefetch #endif #endif +#ifndef FOLLY_F14_PERTURB_INSERTION_ORDER +#define FOLLY_F14_PERTURB_INSERTION_ORDER folly::kIsDebug +#endif + namespace folly { struct F14TableStats { @@ -130,6 +141,9 @@ struct F14LinkCheck<getF14IntrinsicsMode()> { static void check() noexcept; }; +bool tlsPendingSafeInserts(std::ptrdiff_t delta = 0); +std::size_t tlsMinstdRand(std::size_t n); + #if defined(_LIBCPP_VERSION) template <typename K, typename V, typename H> @@ -148,8 +162,11 @@ struct StdIsFastHash<std::hash<long double>> : std::false_type {}; template <typename... Args> struct StdIsFastHash<std::hash<std::basic_string<Args...>>> : std::false_type { }; - -// TODO: add specialization for std::basic_string_view +#if FOLLY_HAS_STRING_VIEW +template <typename... Args> +struct StdIsFastHash<std::hash<std::basic_string_view<Args...>>> + : std::false_type {}; +#endif // mimic internal node of unordered containers in STL to estimate the size template <typename K, typename V, typename H, typename Enable = void> @@ -171,6 +188,16 @@ struct StdNodeReplica< #endif +template <class Container, class Predicate> +void erase_if_impl(Container& c, Predicate& predicate) { + for (auto i = c.begin(), last = c.end(); i != last;) { + auto prev = i++; + if (predicate(*prev)) { + c.erase(prev); + } + } +} + } // namespace detail } // namespace f14 @@ -202,36 +229,27 @@ class F14HashToken final { namespace f14 { namespace detail { -//// Defaults should be selected using void +//// Defaults should be selected using void template <typename Arg, typename Default> using VoidDefault = std::conditional_t<std::is_same<Arg, Default>::value, void, Arg>; template <typename Arg, typename Default> using Defaulted = - typename std::conditional_t<std::is_same<Arg, void>::value, Default, Arg>; - -template < - typename TableKey, - typename Hasher, - typename KeyEqual, - typename ArgKey, - typename Void = void> -struct EligibleForHeterogeneousFind : std::false_type {}; + std::conditional_t<std::is_same<Arg, void>::value, Default, Arg>; template < typename TableKey, typename Hasher, typename KeyEqual, typename ArgKey> -struct EligibleForHeterogeneousFind< - TableKey, - Hasher, - KeyEqual, - ArgKey, - void_t<typename Hasher::is_transparent, typename KeyEqual::is_transparent>> - : std::true_type {}; +struct EligibleForHeterogeneousFind + : Conjunction< + is_transparent<Hasher>, + is_transparent<KeyEqual>, + is_invocable<Hasher, ArgKey const&>, + is_invocable<KeyEqual, ArgKey const&, TableKey const&>> {}; template < typename TableKey, @@ -242,35 +260,6 @@ using EligibleForHeterogeneousInsert = Conjunction< EligibleForHeterogeneousFind<TableKey, Hasher, KeyEqual, ArgKey>, std::is_constructible<TableKey, ArgKey>>; -template < - typename TableKey, - typename Hasher, - typename KeyEqual, - typename KeyArg0OrBool, - typename... KeyArgs> -using KeyTypeForEmplaceHelper = std::conditional_t< - sizeof...(KeyArgs) == 1 && - (std::is_same<remove_cvref_t<KeyArg0OrBool>, TableKey>::value || - EligibleForHeterogeneousFind< - TableKey, - Hasher, - KeyEqual, - KeyArg0OrBool>::value), - KeyArg0OrBool&&, - TableKey>; - -template < - typename TableKey, - typename Hasher, - typename KeyEqual, - typename... KeyArgs> -using KeyTypeForEmplace = KeyTypeForEmplaceHelper< - TableKey, - Hasher, - KeyEqual, - std::tuple_element_t<0, std::tuple<KeyArgs..., bool>>, - KeyArgs...>; - //////////////// template <typename T> @@ -285,28 +274,10 @@ FOLLY_ALWAYS_INLINE static void prefetchAddr(T const* ptr) { #endif } -template <typename T> -FOLLY_ALWAYS_INLINE static unsigned findFirstSetNonZero(T mask) { - assume(mask != 0); - if (sizeof(mask) == sizeof(unsigned)) { - return __builtin_ctz(static_cast<unsigned>(mask)); - } else { - return __builtin_ctzll(mask); - } -} - #if FOLLY_NEON using TagVector = uint8x16_t; - -using MaskType = uint64_t; - -constexpr unsigned kMaskSpacing = 4; #else // SSE2 using TagVector = __m128i; - -using MaskType = uint32_t; - -constexpr unsigned kMaskSpacing = 1; #endif // We could use unaligned loads to relax this requirement, but that @@ -321,198 +292,6 @@ using EmptyTagVectorType = std::aligned_storage_t< extern EmptyTagVectorType kEmptyTagVector; -extern FOLLY_F14_TLS_IF_ASAN std::size_t asanPendingSafeInserts; -extern FOLLY_F14_TLS_IF_ASAN std::size_t asanRehashState; - -template <unsigned BitCount> -struct FullMask { - static constexpr MaskType value = - (FullMask<BitCount - 1>::value << kMaskSpacing) + 1; -}; - -template <> -struct FullMask<1> : std::integral_constant<MaskType, 1> {}; - -#if FOLLY_ARM -// Mask iteration is different for ARM because that is the only platform -// for which the mask is bigger than a register. - -// Iterates a mask, optimized for the case that only a few bits are set -class SparseMaskIter { - static_assert(kMaskSpacing == 4, ""); - - uint32_t interleavedMask_; - - public: - explicit SparseMaskIter(MaskType mask) - : interleavedMask_{static_cast<uint32_t>(((mask >> 32) << 2) | mask)} {} - - bool hasNext() { - return interleavedMask_ != 0; - } - - unsigned next() { - FOLLY_SAFE_DCHECK(hasNext(), ""); - unsigned i = findFirstSetNonZero(interleavedMask_); - interleavedMask_ &= (interleavedMask_ - 1); - return ((i >> 2) | (i << 2)) & 0xf; - } -}; - -// Iterates a mask, optimized for the case that most bits are set -class DenseMaskIter { - static_assert(kMaskSpacing == 4, ""); - - std::size_t count_; - unsigned index_; - uint8_t const* tags_; - - public: - explicit DenseMaskIter(uint8_t const* tags, MaskType mask) { - if (mask == 0) { - count_ = 0; - } else { - count_ = popcount(static_cast<uint32_t>(((mask >> 32) << 2) | mask)); - if (LIKELY((mask & 1) != 0)) { - index_ = 0; - } else { - index_ = findFirstSetNonZero(mask) / kMaskSpacing; - } - tags_ = tags; - } - } - - bool hasNext() { - return count_ > 0; - } - - unsigned next() { - auto rv = index_; - --count_; - if (count_ > 0) { - do { - ++index_; - } while ((tags_[index_] & 0x80) == 0); - } - FOLLY_SAFE_DCHECK(index_ < 16, ""); - return rv; - } -}; - -#else -// Iterates a mask, optimized for the case that only a few bits are set -class SparseMaskIter { - MaskType mask_; - - public: - explicit SparseMaskIter(MaskType mask) : mask_{mask} {} - - bool hasNext() { - return mask_ != 0; - } - - unsigned next() { - FOLLY_SAFE_DCHECK(hasNext(), ""); - unsigned i = findFirstSetNonZero(mask_); - mask_ &= (mask_ - 1); - return i / kMaskSpacing; - } -}; - -// Iterates a mask, optimized for the case that most bits are set -class DenseMaskIter { - MaskType mask_; - unsigned index_{0}; - - public: - explicit DenseMaskIter(uint8_t const*, MaskType mask) : mask_{mask} {} - - bool hasNext() { - return mask_ != 0; - } - - unsigned next() { - FOLLY_SAFE_DCHECK(hasNext(), ""); - if (LIKELY((mask_ & 1) != 0)) { - mask_ >>= kMaskSpacing; - return index_++; - } else { - unsigned s = findFirstSetNonZero(mask_); - unsigned rv = index_ + (s / kMaskSpacing); - mask_ >>= (s + kMaskSpacing); - index_ = rv + 1; - return rv; - } - } -}; -#endif - -// Iterates a mask, returning pairs of [begin,end) index covering blocks -// of set bits -class MaskRangeIter { - MaskType mask_; - unsigned shift_{0}; - - public: - explicit MaskRangeIter(MaskType mask) { - // If kMaskSpacing is > 1 then there will be empty bits even for - // contiguous ranges. Fill them in. - mask_ = mask * ((1 << kMaskSpacing) - 1); - } - - bool hasNext() { - return mask_ != 0; - } - - std::pair<unsigned, unsigned> next() { - FOLLY_SAFE_DCHECK(hasNext(), ""); - auto s = shift_; - unsigned b = findFirstSetNonZero(mask_); - unsigned e = findFirstSetNonZero(~(mask_ | (mask_ - 1))); - mask_ >>= e; - shift_ = s + e; - return std::make_pair((s + b) / kMaskSpacing, (s + e) / kMaskSpacing); - } -}; - -// Holds the result of an index query that has an optional result, -// interpreting a mask of 0 to be the empty answer and the index of the -// last set bit to be the non-empty answer -class LastOccupiedInMask { - MaskType mask_; - - public: - explicit LastOccupiedInMask(MaskType mask) : mask_{mask} {} - - bool hasIndex() const { - return mask_ != 0; - } - - unsigned index() const { - assume(mask_ != 0); - return (findLastSet(mask_) - 1) / kMaskSpacing; - } -}; - -// Holds the result of an index query that has an optional result, -// interpreting a mask of 0 to be the empty answer and the index of the -// first set bit to be the non-empty answer -class FirstEmptyInMask { - MaskType mask_; - - public: - explicit FirstEmptyInMask(MaskType mask) : mask_{mask} {} - - bool hasIndex() const { - return mask_ != 0; - } - - unsigned index() const { - FOLLY_SAFE_DCHECK(mask_ != 0, ""); - return findFirstSetNonZero(mask_) / kMaskSpacing; - } -}; - template <typename ItemType> struct alignas(kRequiredVectorAlignment) F14Chunk { using Item = ItemType; @@ -532,16 +311,21 @@ struct alignas(kRequiredVectorAlignment) F14Chunk { static constexpr unsigned kAllocatedCapacity = kCapacity + (sizeof(Item) == 16 ? 1 : 0); + // If kCapacity == 12 then we get 16 bits of capacityScale by using + // tag 12 and 13, otherwise we only get 4 bits of control_ + static constexpr std::size_t kCapacityScaleBits = kCapacity == 12 ? 16 : 4; + static constexpr std::size_t kCapacityScaleShift = kCapacityScaleBits - 4; + static constexpr MaskType kFullMask = FullMask<kCapacity>::value; // Non-empty tags have their top bit set. tags_ array might be bigger // than kCapacity to keep alignment of first item. std::array<uint8_t, 14> tags_; - // Bits 0..3 record the actual capacity of the chunk if this is chunk - // zero, or hold 0000 for other chunks. Bits 4-7 are a 4-bit counter - // of the number of values in this chunk that were placed because they - // overflowed their desired chunk (hostedOverflowCount). + // Bits 0..3 of chunk 0 record the scaling factor between the number of + // chunks and the max size without rehash. Bits 4-7 in any chunk are a + // 4-bit counter of the number of values in this chunk that were placed + // because they overflowed their desired chunk (hostedOverflowCount). uint8_t control_; // The number of values that would have been placed into this chunk if @@ -550,10 +334,7 @@ struct alignas(kRequiredVectorAlignment) F14Chunk { // increases nor decreases. uint8_t outboundOverflowCount_; - std::array< - std::aligned_storage_t<sizeof(Item), alignof(Item)>, - kAllocatedCapacity> - rawItems_; + std::array<aligned_storage_for_t<Item>, kAllocatedCapacity> rawItems_; static F14Chunk* emptyInstance() { auto raw = reinterpret_cast<char*>(&kEmptyTagVector); @@ -603,19 +384,35 @@ struct alignas(kRequiredVectorAlignment) F14Chunk { } bool eof() const { - return (control_ & 0xf) != 0; + return capacityScale() != 0; } - std::size_t chunk0Capacity() const { - return control_ & 0xf; + std::size_t capacityScale() const { + if (kCapacityScaleBits == 4) { + return control_ & 0xf; + } else { + uint16_t v; + std::memcpy(&v, &tags_[12], 2); + return v; + } } - void markEof(std::size_t c0c) { + void setCapacityScale(std::size_t scale) { FOLLY_SAFE_DCHECK( - this != emptyInstance() && control_ == 0 && c0c > 0 && c0c <= 0xf && - c0c <= kCapacity, + this != emptyInstance() && scale > 0 && + scale < (std::size_t{1} << kCapacityScaleBits), ""); - control_ = static_cast<uint8_t>(c0c); + if (kCapacityScaleBits == 4) { + control_ = (control_ & ~0xf) | static_cast<uint8_t>(scale); + } else { + uint16_t v = static_cast<uint16_t>(scale); + std::memcpy(&tags_[12], &v, 2); + } + } + + void markEof(std::size_t scale) { + folly::assume(control_ == 0); + setCapacityScale(scale); } unsigned outboundOverflowCount() const { @@ -641,10 +438,12 @@ struct alignas(kRequiredVectorAlignment) F14Chunk { void setTag(std::size_t index, std::size_t tag) { FOLLY_SAFE_DCHECK( this != emptyInstance() && tag >= 0x80 && tag <= 0xff, ""); + FOLLY_SAFE_CHECK(tags_[index] == 0, ""); tags_[index] = static_cast<uint8_t>(tag); } void clearTag(std::size_t index) { + FOLLY_SAFE_CHECK((tags_[index] & 0x80) != 0, ""); tags_[index] = 0; } @@ -1093,6 +892,7 @@ class F14Table : public Policy { using KeyEqual = typename Policy::KeyEqual; using Policy::kAllocIsAlwaysEqual; + using Policy::kContinuousCapacity; using Policy::kDefaultConstructIsNoexcept; using Policy::kEnableItemIteration; using Policy::kSwapIsNoexcept; @@ -1229,7 +1029,7 @@ class F14Table : public Policy { // Hash values are used to compute the desired position, which is the // chunk index at which we would like to place a value (if there is no - // overflow), and the tag, which is an additional 8 bits of entropy. + // overflow), and the tag, which is an additional 7 bits of entropy. // // The standard's definition of hash function quality only refers to // the probability of collisions of the entire hash value, not to the @@ -1240,7 +1040,7 @@ class F14Table : public Policy { // // If the user-supplied hasher is an avalanching one (each bit of the // hash value has a 50% chance of being the same for differing hash - // inputs), then we can just take 1 byte of the hash value for the tag + // inputs), then we can just take 7 bits of the hash value for the tag // and the rest for the desired position. Avalanching hashers also // let us map hash value to array index position with just a bitmask // without risking clumping. (Many hash tables just accept the risk @@ -1266,7 +1066,7 @@ class F14Table : public Policy { std::size_t tag; if (!isAvalanchingHasher()) { #if FOLLY_F14_CRC_INTRINSIC_AVAILABLE -#if FOLLY_SSE +#if FOLLY_SSE_PREREQ(4, 2) // SSE4.2 CRC std::size_t c = _mm_crc32_u64(0, hash); tag = (c >> 24) | 0x80; @@ -1317,7 +1117,7 @@ class F14Table : public Policy { uint8_t tag; if (!isAvalanchingHasher()) { #if FOLLY_F14_CRC_INTRINSIC_AVAILABLE -#if FOLLY_SSE +#if FOLLY_SSE_PREREQ(4, 2) // SSE4.2 CRC auto c = _mm_crc32_u32(0, hash); tag = static_cast<uint8_t>(~(c >> 25)); @@ -1344,13 +1144,81 @@ class F14Table : public Policy { //////// memory management helpers + static std::size_t computeCapacity( + std::size_t chunkCount, + std::size_t scale) { + FOLLY_SAFE_DCHECK(!(chunkCount > 1 && scale == 0), ""); + FOLLY_SAFE_DCHECK( + scale < (std::size_t{1} << Chunk::kCapacityScaleBits), ""); + FOLLY_SAFE_DCHECK((chunkCount & (chunkCount - 1)) == 0, ""); + return (((chunkCount - 1) >> Chunk::kCapacityScaleShift) + 1) * scale; + } + + std::pair<std::size_t, std::size_t> computeChunkCountAndScale( + std::size_t desiredCapacity, + bool continuousSingleChunkCapacity, + bool continuousMultiChunkCapacity) const { + if (desiredCapacity <= Chunk::kCapacity) { + // we can go to 100% capacity in a single chunk with no problem + if (!continuousSingleChunkCapacity) { + if (desiredCapacity <= 2) { + desiredCapacity = 2; + } else if (desiredCapacity <= 6) { + desiredCapacity = 6; + } else { + desiredCapacity = Chunk::kCapacity; + } + } + auto rv = std::make_pair(std::size_t{1}, desiredCapacity); + FOLLY_SAFE_DCHECK( + computeCapacity(rv.first, rv.second) == desiredCapacity, ""); + return rv; + } else { + std::size_t minChunks = + (desiredCapacity - 1) / Chunk::kDesiredCapacity + 1; + std::size_t chunkPow = findLastSet(minChunks - 1); + if (chunkPow == 8 * sizeof(std::size_t)) { + throw_exception<std::bad_alloc>(); + } + + std::size_t chunkCount = std::size_t{1} << chunkPow; + + // Let cc * scale be the actual capacity. + // cc = ((chunkCount - 1) >> kCapacityScaleShift) + 1. + // If chunkPow >= kCapacityScaleShift, then cc = chunkCount >> + // kCapacityScaleShift = 1 << (chunkPow - kCapacityScaleShift), + // otherwise it equals 1 = 1 << 0. Let cc = 1 << ss. + std::size_t ss = chunkPow >= Chunk::kCapacityScaleShift + ? chunkPow - Chunk::kCapacityScaleShift + : 0; + + std::size_t scale; + if (continuousMultiChunkCapacity) { + // (1 << ss) * scale >= desiredCapacity + scale = ((desiredCapacity - 1) >> ss) + 1; + } else { + // (1 << ss) * scale == chunkCount * kDesiredCapacity + scale = Chunk::kDesiredCapacity << (chunkPow - ss); + } + + std::size_t actualCapacity = computeCapacity(chunkCount, scale); + FOLLY_SAFE_DCHECK(actualCapacity >= desiredCapacity, ""); + if (actualCapacity > max_size()) { + throw_exception<std::bad_alloc>(); + } + + return std::make_pair(chunkCount, scale); + } + } + static std::size_t chunkAllocSize( std::size_t chunkCount, - std::size_t maxSizeWithoutRehash) { + std::size_t capacityScale) { + FOLLY_SAFE_DCHECK(chunkCount > 0, ""); + FOLLY_SAFE_DCHECK(!(chunkCount > 1 && capacityScale == 0), ""); if (chunkCount == 1) { - FOLLY_SAFE_DCHECK((maxSizeWithoutRehash % 2) == 0, ""); static_assert(offsetof(Chunk, rawItems_) == 16, ""); - return 16 + sizeof(Item) * maxSizeWithoutRehash; + return 16 + sizeof(Item) * computeCapacity(1, capacityScale); } else { return sizeof(Chunk) * chunkCount; } @@ -1359,16 +1227,24 @@ class F14Table : public Policy { ChunkPtr initializeChunks( BytePtr raw, std::size_t chunkCount, - std::size_t maxSizeWithoutRehash) { + std::size_t capacityScale) { static_assert(std::is_trivial<Chunk>::value, "F14Chunk should be POD"); auto chunks = static_cast<Chunk*>(static_cast<void*>(&*raw)); for (std::size_t i = 0; i < chunkCount; ++i) { chunks[i].clear(); } - chunks[0].markEof(chunkCount == 1 ? maxSizeWithoutRehash : 1); + chunks[0].markEof(capacityScale); return std::pointer_traits<ChunkPtr>::pointer_to(*chunks); } + std::size_t itemCount() const noexcept { + if (chunkMask_ == 0) { + return computeCapacity(1, chunks_->capacityScale()); + } else { + return (chunkMask_ + 1) * Chunk::kCapacity; + } + } + public: ItemIter begin() const noexcept { FOLLY_SAFE_DCHECK(kEnableItemIteration, ""); @@ -1395,14 +1271,7 @@ class F14Table : public Policy { } std::size_t bucket_count() const noexcept { - // bucket_count is just a synthetic construct for the outside world - // so that size, bucket_count, load_factor, and max_load_factor are - // all self-consistent. The only one of those that is real is size(). - if (chunkMask_ != 0) { - return (chunkMask_ + 1) * Chunk::kDesiredCapacity; - } else { - return chunks_->chunk0Capacity(); - } + return computeCapacity(chunkMask_ + 1, chunks_->capacityScale()); } std::size_t max_bucket_count() const noexcept { @@ -1536,6 +1405,36 @@ class F14Table : public Policy { return findImpl(static_cast<HashPair>(token), key); } + // Searches for a key using a key predicate that is a refinement + // of key equality. func(k) should return true only if k is equal + // to key according to key_eq(), but is allowed to apply additional + // constraints. + template <typename K, typename F> + FOLLY_ALWAYS_INLINE ItemIter findMatching(K const& key, F&& func) const { + auto hp = splitHash(this->computeKeyHash(key)); + std::size_t index = hp.first; + std::size_t step = probeDelta(hp); + for (std::size_t tries = 0; tries <= chunkMask_; ++tries) { + ChunkPtr chunk = chunks_ + (index & chunkMask_); + if (sizeof(Chunk) > 64) { + prefetchAddr(chunk->itemAddr(8)); + } + auto hits = chunk->tagMatchIter(hp.second); + while (hits.hasNext()) { + auto i = hits.next(); + if (LIKELY( + func(this->keyForValue(this->valueAtItem(chunk->item(i)))))) { + return ItemIter{chunk, i}; + } + } + if (LIKELY(chunk->outboundOverflowCount() == 0)) { + break; + } + index += step; + } + return ItemIter{}; + } + private: void adjustSizeAndBeginAfterInsert(ItemIter iter) { if (kEnableItemIteration) { @@ -1589,7 +1488,7 @@ class F14Table : public Policy { void insertAtBlank(ItemIter pos, HashPair hp, Args&&... args) { try { auto dst = pos.itemAddr(); - this->constructValueAtItem(size(), dst, std::forward<Args>(args)...); + this->constructValueAtItem(*this, dst, std::forward<Args>(args)...); } catch (...) { eraseBlank(pos, hp); throw; @@ -1656,9 +1555,13 @@ class F14Table : public Policy { // in the Policy API. if (is_trivially_copyable<Item>::value && !this->destroyItemOnClear() && - bucket_count() == src.bucket_count()) { + itemCount() == src.itemCount()) { + FOLLY_SAFE_DCHECK(chunkMask_ == src.chunkMask_, ""); + + auto scale = chunks_->capacityScale(); + // most happy path - auto n = chunkAllocSize(chunkMask_ + 1, bucket_count()); + auto n = chunkAllocSize(chunkMask_ + 1, scale); std::memcpy(&chunks_[0], &src.chunks_[0], n); sizeAndPackedBegin_.size_ = src.size(); if (kEnableItemIteration) { @@ -1668,13 +1571,17 @@ class F14Table : public Policy { srcBegin.index()} .pack(); } + if (kContinuousCapacity) { + // capacityScale might not match even if itemCount matches + chunks_->setCapacityScale(scale); + } } else { - std::size_t maxChunkIndex = src.lastOccupiedChunk() - src.chunks_; - - // happy path, no rehash but pack items toward bottom of chunk and - // use copy constructor - auto srcChunk = &src.chunks_[maxChunkIndex]; - Chunk* dstChunk = &chunks_[maxChunkIndex]; + // Happy path, no rehash but pack items toward bottom of chunk + // and use copy constructor. Don't try to optimize by using + // lastOccupiedChunk() because there may be higher unoccupied chunks + // with the overflow bit set. + auto srcChunk = &src.chunks_[chunkMask_]; + Chunk* dstChunk = &chunks_[chunkMask_]; do { dstChunk->copyOverflowInfoFrom(*srcChunk); @@ -1703,6 +1610,7 @@ class F14Table : public Policy { // reset doesn't care about packedBegin, so we don't fix it until the end if (kEnableItemIteration) { + std::size_t maxChunkIndex = src.lastOccupiedChunk() - src.chunks_; sizeAndPackedBegin_.packedBegin() = ItemIter{chunks_ + maxChunkIndex, chunks_[maxChunkIndex].lastOccupied().index()} @@ -1791,7 +1699,7 @@ class F14Table : public Policy { auto&& srcArg = std::forward<T>(src).buildArgForItem(srcItem); auto const& srcKey = src.keyForValue(srcArg); auto hp = splitHash(this->computeKeyHash(srcKey)); - FOLLY_SAFE_DCHECK(hp.second == srcChunk->tag(i), ""); + FOLLY_SAFE_CHECK(hp.second == srcChunk->tag(i), ""); insertAtBlank( allocateTag(fullness, hp), hp, @@ -1809,12 +1717,23 @@ class F14Table : public Policy { template <typename T> FOLLY_NOINLINE void buildFromF14Table(T&& src) { - FOLLY_SAFE_DCHECK(size() == 0, ""); + FOLLY_SAFE_DCHECK(bucket_count() == 0, ""); if (src.size() == 0) { return; } - reserveForInsert(src.size()); + // Use the source's capacity, unless it is oversized. + auto upperLimit = computeChunkCountAndScale(src.size(), false, false); + auto ccas = + std::make_pair(src.chunkMask_ + 1, src.chunks_->capacityScale()); + FOLLY_SAFE_DCHECK( + ccas.first >= upperLimit.first, + "rounded chunk count can't be bigger than actual"); + if (ccas.first > upperLimit.first || ccas.second > upperLimit.second) { + ccas = upperLimit; + } + rehashImpl(0, 1, 0, ccas.first, ccas.second); + try { if (chunkMask_ == src.chunkMask_) { directBuildFrom(std::forward<T>(src)); @@ -1828,60 +1747,95 @@ class F14Table : public Policy { } } - FOLLY_NOINLINE void reserveImpl( - std::size_t capacity, - std::size_t origChunkCount, - std::size_t origMaxSizeWithoutRehash) { - FOLLY_SAFE_DCHECK(capacity >= size(), ""); - - // compute new size - std::size_t const kInitialCapacity = 2; - std::size_t const kHalfChunkCapacity = - (Chunk::kDesiredCapacity / 2) & ~std::size_t{1}; - std::size_t newMaxSizeWithoutRehash; - std::size_t newChunkCount; - if (capacity <= kHalfChunkCapacity) { - newChunkCount = 1; - newMaxSizeWithoutRehash = - (capacity < kInitialCapacity) ? kInitialCapacity : kHalfChunkCapacity; - } else { - newChunkCount = nextPowTwo((capacity - 1) / Chunk::kDesiredCapacity + 1); - newMaxSizeWithoutRehash = newChunkCount * Chunk::kDesiredCapacity; - - constexpr std::size_t kMaxChunksWithoutCapacityOverflow = - (std::numeric_limits<std::size_t>::max)() / Chunk::kDesiredCapacity; - - if (newChunkCount > kMaxChunksWithoutCapacityOverflow || - newMaxSizeWithoutRehash > max_size()) { - throw_exception<std::bad_alloc>(); - } + void reserveImpl(std::size_t desiredCapacity) { + desiredCapacity = std::max<std::size_t>(desiredCapacity, size()); + if (desiredCapacity == 0) { + reset(); + return; } - if (origMaxSizeWithoutRehash != newMaxSizeWithoutRehash) { + auto origChunkCount = chunkMask_ + 1; + auto origCapacityScale = chunks_->capacityScale(); + auto origCapacity = computeCapacity(origChunkCount, origCapacityScale); + + // This came from an explicit reserve() or rehash() call, so there's + // a good chance the capacity is exactly right. To avoid O(n^2) + // behavior, we don't do rehashes that decrease the size by less + // than 1/8, and if we have a requested increase of less than 1/8 we + // instead go to the next power of two. + + if (desiredCapacity <= origCapacity && + desiredCapacity >= origCapacity - origCapacity / 8) { + return; + } + bool attemptExact = + !(desiredCapacity > origCapacity && + desiredCapacity < origCapacity + origCapacity / 8); + + std::size_t newChunkCount; + std::size_t newCapacityScale; + std::tie(newChunkCount, newCapacityScale) = computeChunkCountAndScale( + desiredCapacity, attemptExact, kContinuousCapacity && attemptExact); + auto newCapacity = computeCapacity(newChunkCount, newCapacityScale); + + if (origCapacity != newCapacity) { rehashImpl( + size(), origChunkCount, - origMaxSizeWithoutRehash, + origCapacityScale, newChunkCount, - newMaxSizeWithoutRehash); + newCapacityScale); } } - void rehashImpl( + FOLLY_NOINLINE void reserveForInsertImpl( + std::size_t capacityMinusOne, std::size_t origChunkCount, - std::size_t origMaxSizeWithoutRehash, + std::size_t origCapacityScale, + std::size_t origCapacity) { + FOLLY_SAFE_DCHECK(capacityMinusOne >= size(), ""); + std::size_t capacity = capacityMinusOne + 1; + + // we want to grow by between 2^0.5 and 2^1.5 ending at a "good" + // size, so we grow by 2^0.5 and then round up + + // 1.01101_2 = 1.40625 + std::size_t minGrowth = origCapacity + (origCapacity >> 2) + + (origCapacity >> 3) + (origCapacity >> 5); + capacity = std::max<std::size_t>(capacity, minGrowth); + + std::size_t newChunkCount; + std::size_t newCapacityScale; + std::tie(newChunkCount, newCapacityScale) = + computeChunkCountAndScale(capacity, false, false); + + FOLLY_SAFE_DCHECK( + computeCapacity(newChunkCount, newCapacityScale) > origCapacity, ""); + + rehashImpl( + size(), + origChunkCount, + origCapacityScale, + newChunkCount, + newCapacityScale); + } + + void rehashImpl( + std::size_t origSize, + std::size_t origChunkCount, + std::size_t origCapacityScale, std::size_t newChunkCount, - std::size_t newMaxSizeWithoutRehash) { + std::size_t newCapacityScale) { auto origChunks = chunks_; + auto origCapacity = computeCapacity(origChunkCount, origCapacityScale); + auto origAllocSize = chunkAllocSize(origChunkCount, origCapacityScale); + auto newCapacity = computeCapacity(newChunkCount, newCapacityScale); + auto newAllocSize = chunkAllocSize(newChunkCount, newCapacityScale); BytePtr rawAllocation; auto undoState = this->beforeRehash( - size(), - origMaxSizeWithoutRehash, - newMaxSizeWithoutRehash, - chunkAllocSize(newChunkCount, newMaxSizeWithoutRehash), - rawAllocation); - chunks_ = - initializeChunks(rawAllocation, newChunkCount, newMaxSizeWithoutRehash); + origSize, origCapacity, newCapacity, newAllocSize, rawAllocation); + chunks_ = initializeChunks(rawAllocation, newChunkCount, newCapacityScale); FOLLY_SAFE_DCHECK( newChunkCount < std::numeric_limits<InternalSizeType>::max(), ""); @@ -1893,16 +1847,14 @@ class F14Table : public Policy { BytePtr finishedRawAllocation = nullptr; std::size_t finishedAllocSize = 0; if (LIKELY(success)) { - if (origMaxSizeWithoutRehash > 0) { + if (origCapacity > 0) { finishedRawAllocation = std::pointer_traits<BytePtr>::pointer_to( *static_cast<uint8_t*>(static_cast<void*>(&*origChunks))); - finishedAllocSize = - chunkAllocSize(origChunkCount, origMaxSizeWithoutRehash); + finishedAllocSize = origAllocSize; } } else { finishedRawAllocation = rawAllocation; - finishedAllocSize = - chunkAllocSize(newChunkCount, newMaxSizeWithoutRehash); + finishedAllocSize = newAllocSize; chunks_ = origChunks; FOLLY_SAFE_DCHECK( origChunkCount < std::numeric_limits<InternalSizeType>::max(), ""); @@ -1913,14 +1865,14 @@ class F14Table : public Policy { this->afterRehash( std::move(undoState), success, - size(), - origMaxSizeWithoutRehash, - newMaxSizeWithoutRehash, + origSize, + origCapacity, + newCapacity, finishedRawAllocation, finishedAllocSize); }; - if (size() == 0) { + if (origSize == 0) { // nothing to do } else if (origChunkCount == 1 && newChunkCount == 1) { // no mask, no chunk scan, no hash computation, no probing @@ -1928,7 +1880,7 @@ class F14Table : public Policy { auto dstChunk = chunks_; std::size_t srcI = 0; std::size_t dstI = 0; - while (dstI < size()) { + while (dstI < origSize) { if (LIKELY(srcChunk->occupied(srcI))) { dstChunk->setTag(dstI, srcChunk->tag(srcI)); this->moveItemDuringRehash( @@ -1965,7 +1917,7 @@ class F14Table : public Policy { }; auto srcChunk = origChunks + origChunkCount - 1; - std::size_t remaining = size(); + std::size_t remaining = origSize; while (remaining > 0) { auto iter = srcChunk->occupiedIter(); if (prefetchBeforeRehash()) { @@ -1979,7 +1931,7 @@ class F14Table : public Policy { Item& srcItem = srcChunk->item(srcI); auto hp = splitHash( this->computeItemHash(const_cast<Item const&>(srcItem))); - FOLLY_SAFE_DCHECK(hp.second == srcChunk->tag(srcI), ""); + FOLLY_SAFE_CHECK(hp.second == srcChunk->tag(srcI), ""); auto dstIter = allocateTag(fullness, hp); this->moveItemDuringRehash(dstIter.itemAddr(), srcItem); @@ -2001,34 +1953,24 @@ class F14Table : public Policy { success = true; } - void asanOnReserve(std::size_t capacity) { - if (kIsSanitizeAddress && capacity > size()) { - asanPendingSafeInserts += capacity - size(); + // Randomization to help expose bugs when running tests in debug or + // sanitizer builds + + FOLLY_ALWAYS_INLINE void debugModeOnReserve(std::size_t capacity) { + if (kIsLibrarySanitizeAddress || kIsDebug) { + if (capacity > size()) { + tlsPendingSafeInserts(static_cast<std::ptrdiff_t>(capacity - size())); + } } } - bool asanShouldAddExtraRehash() { - if (!kIsSanitizeAddress) { - return false; - } else if (asanPendingSafeInserts > 0) { - --asanPendingSafeInserts; - return false; - } else if (size() <= 1) { - return size() > 0; - } else { - constexpr std::size_t kBigPrime = 4294967291U; - auto s = (asanRehashState += kBigPrime); - return (s % size()) == 0; - } - } - - void asanExtraRehash() { + void debugModeSpuriousRehash() { auto cc = chunkMask_ + 1; - auto bc = bucket_count(); - rehashImpl(cc, bc, cc, bc); + auto ss = chunks_->capacityScale(); + rehashImpl(size(), cc, ss, cc, ss); } - void asanOnInsert() { + FOLLY_ALWAYS_INLINE void debugModeBeforeInsert() { // When running under ASAN, we add a spurious rehash with 1/size() // probability before every insert. This means that finding reference // stability problems for F14Value and F14Vector is much more likely. @@ -2038,9 +1980,30 @@ class F14Table : public Policy { // // One way to fix this is to call map.reserve(N) before such a // sequence, where N is the number of keys that might be inserted - // within the section that retains references. - if (asanShouldAddExtraRehash()) { - asanExtraRehash(); + // within the section that retains references plus the existing size. + if (kIsLibrarySanitizeAddress && !tlsPendingSafeInserts() && size() > 0 && + tlsMinstdRand(size()) == 0) { + debugModeSpuriousRehash(); + } + } + + FOLLY_ALWAYS_INLINE void debugModeAfterInsert() { + if (kIsLibrarySanitizeAddress || kIsDebug) { + tlsPendingSafeInserts(-1); + } + } + + FOLLY_ALWAYS_INLINE void debugModePerturbSlotInsertOrder( + ChunkPtr chunk, + std::size_t& itemIndex) { + FOLLY_SAFE_DCHECK(!chunk->occupied(itemIndex), ""); + constexpr bool perturbSlot = FOLLY_F14_PERTURB_INSERTION_ORDER; + if (perturbSlot && !tlsPendingSafeInserts()) { + std::size_t e = chunkMask_ == 0 ? bucket_count() : Chunk::kCapacity; + std::size_t i = itemIndex + tlsMinstdRand(e - itemIndex); + if (!chunk->occupied(i)) { + itemIndex = i; + } } } @@ -2053,20 +2016,20 @@ class F14Table : public Policy { void reserve(std::size_t capacity) { // We want to support the pattern - // map.reserve(2); auto& r1 = map[k1]; auto& r2 = map[k2]; - asanOnReserve(capacity); - reserveImpl( - std::max<std::size_t>(capacity, size()), - chunkMask_ + 1, - bucket_count()); + // map.reserve(map.size() + 2); auto& r1 = map[k1]; auto& r2 = map[k2]; + debugModeOnReserve(capacity); + reserveImpl(capacity); } - // Returns true iff a rehash was performed void reserveForInsert(size_t incoming = 1) { - auto capacity = size() + incoming; - auto bc = bucket_count(); - if (capacity - 1 >= bc) { - reserveImpl(capacity, chunkMask_ + 1, bc); + FOLLY_SAFE_DCHECK(incoming > 0, ""); + + auto needed = size() + incoming; + auto chunkCount = chunkMask_ + 1; + auto scale = chunks_->capacityScale(); + auto existing = computeCapacity(chunkCount, scale); + if (needed - 1 >= existing) { + reserveForInsertImpl(needed - 1, chunkCount, scale, existing); } } @@ -2084,7 +2047,7 @@ class F14Table : public Policy { } } - asanOnInsert(); + debugModeBeforeInsert(); reserveForInsert(); @@ -2103,13 +2066,17 @@ class F14Table : public Policy { chunk->adjustHostedOverflowCount(Chunk::kIncrHostedOverflowCount); } std::size_t itemIndex = firstEmpty.index(); - FOLLY_SAFE_DCHECK(!chunk->occupied(itemIndex), ""); + + debugModePerturbSlotInsertOrder(chunk, itemIndex); chunk->setTag(itemIndex, hp.second); ItemIter iter{chunk, itemIndex}; // insertAtBlank will clear the tag if the constructor throws insertAtBlank(iter, hp, std::forward<Args>(args)...); + + debugModeAfterInsert(); + return std::make_pair(iter, true); } @@ -2152,11 +2119,11 @@ class F14Table : public Policy { // It's okay to do this in a separate loop because we only do it // when the chunk count is small. That avoids a branch when we // are promoting a clear to a reset for a large table. - auto c0c = chunks_[0].chunk0Capacity(); + auto scale = chunks_[0].capacityScale(); for (std::size_t ci = 0; ci <= chunkMask_; ++ci) { chunks_[ci].clear(); } - chunks_[0].markEof(c0c); + chunks_[0].markEof(scale); } if (kEnableItemIteration) { sizeAndPackedBegin_.packedBegin() = ItemIter{}.pack(); @@ -2167,7 +2134,8 @@ class F14Table : public Policy { if (willReset) { BytePtr rawAllocation = std::pointer_traits<BytePtr>::pointer_to( *static_cast<uint8_t*>(static_cast<void*>(&*chunks_))); - std::size_t rawSize = chunkAllocSize(chunkMask_ + 1, bucket_count()); + std::size_t rawSize = + chunkAllocSize(chunkMask_ + 1, chunks_->capacityScale()); chunks_ = Chunk::emptyInstance(); chunkMask_ = 0; @@ -2227,12 +2195,12 @@ class F14Table : public Policy { } void clear() noexcept { - if (kIsSanitizeAddress) { + if (kIsLibrarySanitizeAddress) { // force recycling of heap memory auto bc = bucket_count(); reset(); try { - reserveImpl(bc, 0, 0); + reserveImpl(bc); } catch (std::bad_alloc const&) { // ASAN mode only, keep going } @@ -2266,11 +2234,11 @@ class F14Table : public Policy { // be called with a zero allocationCount. template <typename V> void visitAllocationClasses(V&& visitor) const { - auto bc = bucket_count(); + auto scale = chunks_->capacityScale(); this->visitPolicyAllocationClasses( - (bc == 0 ? 0 : chunkAllocSize(chunkMask_ + 1, bc)), + scale == 0 ? 0 : chunkAllocSize(chunkMask_ + 1, scale), size(), - bc, + bucket_count(), visitor); } @@ -2408,9 +2376,7 @@ class F14Table : public Policy { FOLLY_SAFE_DCHECK(n1 == size(), ""); FOLLY_SAFE_DCHECK(n2 == size(), ""); -#if FOLLY_HAS_RTTI - stats.policy = typeid(Policy).name(); -#endif + stats.policy = pretty_name<Policy>(); stats.size = size(); stats.valueSize = sizeof(value_type); stats.bucketCount = bucket_count(); @@ -2427,4 +2393,14 @@ class F14Table : public Policy { #endif // FOLLY_F14_VECTOR_INTRINSICS_AVAILABLE +namespace f14 { +namespace test { +inline void disableInsertOrderRandomization() { + if (kIsLibrarySanitizeAddress || kIsDebug) { + detail::tlsPendingSafeInserts(static_cast<std::ptrdiff_t>( + (std::numeric_limits<std::size_t>::max)() / 2)); + } +} +} // namespace test +} // namespace f14 } // namespace folly diff --git a/ios/Pods/Folly/folly/container/detail/Util.h b/ios/Pods/Folly/folly/container/detail/Util.h new file mode 100644 index 000000000..10186ec18 --- /dev/null +++ b/ios/Pods/Folly/folly/container/detail/Util.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <memory> +#include <tuple> +#include <type_traits> +#include <utility> + +#include <folly/Traits.h> +#include <folly/functional/ApplyTuple.h> + +// Utility functions for container implementors + +namespace folly { +namespace detail { + +template <typename KeyType, typename Alloc> +struct TemporaryEmplaceKey { + TemporaryEmplaceKey(TemporaryEmplaceKey const&) = delete; + TemporaryEmplaceKey(TemporaryEmplaceKey&&) = delete; + + template <typename... Args> + TemporaryEmplaceKey(Alloc& a, std::tuple<Args...>&& args) : alloc_(a) { + auto p = &value(); + apply( + [&, p](auto&&... inner) { + std::allocator_traits<Alloc>::construct( + alloc_, p, std::forward<decltype(inner)>(inner)...); + }, + std::move(args)); + } + + ~TemporaryEmplaceKey() { + std::allocator_traits<Alloc>::destroy(alloc_, &value()); + } + + KeyType& value() { + return *static_cast<KeyType*>(static_cast<void*>(&raw_)); + } + + Alloc& alloc_; + std::aligned_storage_t<sizeof(KeyType), alignof(KeyType)> raw_; +}; + +// A map's emplace(args...) function takes arguments that can be used to +// construct a pair<key_type const, mapped_type>, but that construction +// only needs to take place if the key is not present in the container. +// callWithExtractedKey helps to handle this efficiently by looking for a +// reference to the key within the args list. If the search is successful +// then the search can be performed without constructing any temporaries. +// If the search is not successful then callWithExtractedKey constructs +// a temporary key_type and a new argument list suitable for constructing +// the entire value_type if necessary. +// +// callWithExtractedKey(a, f, args...) will call f(k, args'...), where +// k is the key and args'... is an argument list that can be used to +// construct a pair of key and mapped value. Note that this means f gets +// the key twice. +// +// In some cases a temporary key must be constructed. This is accomplished +// with std::allocator_traits<>::construct, and the temporary will be +// destroyed with std::allocator_traits<>::destroy. Using the allocator's +// construct method reduces unnecessary copies for pmr allocators. +// +// callWithExtractedKey supports heterogeneous lookup with the UsableAsKey +// template parameter. If a single key argument of type K is found in +// args... then it will be passed directly to f if it is either KeyType or +// if UsableAsKey<remove_cvref_t<K>>::value is true. If you don't care +// about heterogeneous lookup you can just pass a single-arg template +// that extends std::false_type. + +template < + typename KeyType, + template <typename> class UsableAsKey, + typename Alloc, + typename Func, + typename Arg1, + typename... Args2, + std::enable_if_t< + std::is_same<remove_cvref_t<Arg1>, KeyType>::value || + UsableAsKey<remove_cvref_t<Arg1>>::value, + int> = 0> +auto callWithExtractedKey( + Alloc&, + Func&& f, + std::piecewise_construct_t, + std::tuple<Arg1>&& first_args, + std::tuple<Args2...>&& second_args) { + // we found a usable key in the args :) + auto const& key = std::get<0>(first_args); + return f( + key, + std::piecewise_construct, + std::tuple<Arg1&&>(std::move(first_args)), + std::tuple<Args2&&...>(std::move(second_args))); +} + +template < + typename KeyType, + template <typename> class UsableAsKey, + typename Alloc, + typename Func, + typename... Args1, + typename... Args2> +auto callWithExtractedKey( + Alloc& a, + Func&& f, + std::piecewise_construct_t, + std::tuple<Args1...>&& first_args, + std::tuple<Args2...>&& second_args) { + // we will need to materialize a temporary key :( + TemporaryEmplaceKey<KeyType, Alloc> key( + a, std::tuple<Args1&&...>(std::move(first_args))); + return f( + const_cast<KeyType const&>(key.value()), + std::piecewise_construct, + std::forward_as_tuple(std::move(key.value())), + std::tuple<Args2&&...>(std::move(second_args))); +} + +template < + typename KeyType, + template <typename> class UsableAsKey, + typename Alloc, + typename Func> +auto callWithExtractedKey(Alloc& a, Func&& f) { + return callWithExtractedKey<KeyType, UsableAsKey>( + a, + std::forward<Func>(f), + std::piecewise_construct, + std::tuple<>{}, + std::tuple<>{}); +} + +template < + typename KeyType, + template <typename> class UsableAsKey, + typename Alloc, + typename Func, + typename U1, + typename U2> +auto callWithExtractedKey(Alloc& a, Func&& f, U1&& x, U2&& y) { + return callWithExtractedKey<KeyType, UsableAsKey>( + a, + std::forward<Func>(f), + std::piecewise_construct, + std::forward_as_tuple(std::forward<U1>(x)), + std::forward_as_tuple(std::forward<U2>(y))); +} + +template < + typename KeyType, + template <typename> class UsableAsKey, + typename Alloc, + typename Func, + typename U1, + typename U2> +auto callWithExtractedKey(Alloc& a, Func&& f, std::pair<U1, U2> const& p) { + return callWithExtractedKey<KeyType, UsableAsKey>( + a, + std::forward<Func>(f), + std::piecewise_construct, + std::forward_as_tuple(p.first), + std::forward_as_tuple(p.second)); +} + +template < + typename KeyType, + template <typename> class UsableAsKey, + typename Alloc, + typename Func, + typename U1, + typename U2> +auto callWithExtractedKey(Alloc& a, Func&& f, std::pair<U1, U2>&& p) { + return callWithExtractedKey<KeyType, UsableAsKey>( + a, + std::forward<Func>(f), + std::piecewise_construct, + std::forward_as_tuple(std::move(p.first)), + std::forward_as_tuple(std::move(p.second))); +} + +// callWithConstructedKey is the set container analogue of +// callWithExtractedKey + +template < + typename KeyType, + template <typename> class UsableAsKey, + typename Alloc, + typename Func, + typename Arg, + std::enable_if_t< + std::is_same<remove_cvref_t<Arg>, KeyType>::value || + UsableAsKey<remove_cvref_t<Arg>>::value, + int> = 0> +auto callWithConstructedKey(Alloc&, Func&& f, Arg&& arg) { + // we found a usable key in the args :) + auto const& key = arg; + return f(key, std::forward<Arg>(arg)); +} + +template < + typename KeyType, + template <typename> class UsableAsKey, + typename Alloc, + typename Func, + typename... Args> +auto callWithConstructedKey(Alloc& a, Func&& f, Args&&... args) { + // we will need to materialize a temporary key :( + TemporaryEmplaceKey<KeyType, Alloc> key( + a, std::forward_as_tuple(std::forward<Args>(args)...)); + return f(const_cast<KeyType const&>(key.value()), std::move(key.value())); +} + +} // namespace detail +} // namespace folly diff --git a/ios/Pods/Folly/folly/detail/AsyncTrace.h b/ios/Pods/Folly/folly/detail/AsyncTrace.h new file mode 100644 index 000000000..09907c73e --- /dev/null +++ b/ios/Pods/Folly/folly/detail/AsyncTrace.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once +#include <folly/Optional.h> + +namespace folly { +class Executor; +class IOExecutor; +namespace async_tracing { +void logSetGlobalCPUExecutor(Executor*) noexcept; +void logSetGlobalCPUExecutorToImmutable() noexcept; +void logGetGlobalCPUExecutor(Executor*) noexcept; +void logGetImmutableCPUExecutor(Executor*) noexcept; +void logSetGlobalIOExecutor(IOExecutor*) noexcept; +void logGetGlobalIOExecutor(IOExecutor*) noexcept; +void logGetImmutableIOExecutor(IOExecutor*) noexcept; +void logSemiFutureVia(Executor*, Executor*) noexcept; +void logFutureVia(Executor*, Executor*) noexcept; +} // namespace async_tracing +} // namespace folly diff --git a/ios/Pods/Folly/folly/detail/AtFork.h b/ios/Pods/Folly/folly/detail/AtFork.h index 3b76f8786..b47efe6e6 100644 --- a/ios/Pods/Folly/folly/detail/AtFork.h +++ b/ios/Pods/Folly/folly/detail/AtFork.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #pragma once #include <folly/Function.h> @@ -24,11 +25,11 @@ namespace detail { struct AtFork { static void init(); static void registerHandler( - void* object, + void const* handle, folly::Function<bool()> prepare, folly::Function<void()> parent, folly::Function<void()> child); - static void unregisterHandler(void* object); + static void unregisterHandler(void const* handle); }; } // namespace detail diff --git a/ios/Pods/Folly/folly/detail/AtomicHashUtils.h b/ios/Pods/Folly/folly/detail/AtomicHashUtils.h index b3fca4ef2..9ffce4c09 100644 --- a/ios/Pods/Folly/folly/detail/AtomicHashUtils.h +++ b/ios/Pods/Folly/folly/detail/AtomicHashUtils.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/detail/AtomicUnorderedMapUtils.h b/ios/Pods/Folly/folly/detail/AtomicUnorderedMapUtils.h index 94bf5117d..0958871e1 100644 --- a/ios/Pods/Folly/folly/detail/AtomicUnorderedMapUtils.h +++ b/ios/Pods/Folly/folly/detail/AtomicUnorderedMapUtils.h @@ -1,11 +1,11 @@ /* - * Copyright 2015-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/detail/Demangle.cpp b/ios/Pods/Folly/folly/detail/Demangle.cpp index 419656625..717d96e21 100644 --- a/ios/Pods/Folly/folly/detail/Demangle.cpp +++ b/ios/Pods/Folly/folly/detail/Demangle.cpp @@ -1,11 +1,11 @@ /* - * Copyright 2018-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -23,7 +23,7 @@ // So we extract the inclusion of `<demangle.h>` which includes `<libiberty.h>` // to here, isolating it. #if FOLLY_DETAIL_HAVE_DEMANGLE_H -#include <demangle.h> +#include <demangle.h> // @manual #endif namespace folly { @@ -37,6 +37,9 @@ int cplus_demangle_v3_callback_wrapper( auto const options = DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES; return cplus_demangle_v3_callback(mangled, options, cbref, opaque); #else + (void)mangled; + (void)cbref; + (void)opaque; return 0; #endif } diff --git a/ios/Pods/Folly/folly/detail/Demangle.h b/ios/Pods/Folly/folly/detail/Demangle.h index 1755880e7..b11ffc7d7 100644 --- a/ios/Pods/Folly/folly/detail/Demangle.h +++ b/ios/Pods/Folly/folly/detail/Demangle.h @@ -1,11 +1,11 @@ /* - * Copyright 2018-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/detail/DiscriminatedPtrDetail.h b/ios/Pods/Folly/folly/detail/DiscriminatedPtrDetail.h index c73f3ff8c..11a80a11e 100644 --- a/ios/Pods/Folly/folly/detail/DiscriminatedPtrDetail.h +++ b/ios/Pods/Folly/folly/detail/DiscriminatedPtrDetail.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/detail/FileUtilDetail.h b/ios/Pods/Folly/folly/detail/FileUtilDetail.h index 970a95cfb..24cc69fb8 100644 --- a/ios/Pods/Folly/folly/detail/FileUtilDetail.h +++ b/ios/Pods/Folly/folly/detail/FileUtilDetail.h @@ -1,11 +1,11 @@ /* - * Copyright 2013-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/detail/FingerprintPolynomial.h b/ios/Pods/Folly/folly/detail/FingerprintPolynomial.h index 0950b8ac1..38acdd579 100644 --- a/ios/Pods/Folly/folly/detail/FingerprintPolynomial.h +++ b/ios/Pods/Folly/folly/detail/FingerprintPolynomial.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -16,6 +16,7 @@ #pragma once +#include <stddef.h> #include <cstdint> namespace folly { diff --git a/ios/Pods/Folly/folly/detail/Futex-inl.h b/ios/Pods/Folly/folly/detail/Futex-inl.h index 43e106951..8d34ac6a2 100644 --- a/ios/Pods/Folly/folly/detail/Futex-inl.h +++ b/ios/Pods/Folly/folly/detail/Futex-inl.h @@ -1,11 +1,11 @@ /* - * Copyright 2013-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/detail/Futex.h b/ios/Pods/Folly/folly/detail/Futex.h index 71fa98024..f0edfbbc2 100644 --- a/ios/Pods/Folly/folly/detail/Futex.h +++ b/ios/Pods/Folly/folly/detail/Futex.h @@ -1,11 +1,11 @@ /* - * Copyright 2013-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -69,10 +69,7 @@ futexWait(const Futex* futex, uint32_t expected, uint32_t waitMask = -1); * * For any other clock type, now() will be invoked twice. */ -template < - typename Futex, - class Clock, - class Duration = typename Clock::duration> +template <typename Futex, class Clock, class Duration> FutexResult futexWaitUntil( const Futex* futex, uint32_t expected, diff --git a/ios/Pods/Folly/folly/detail/GroupVarintDetail.h b/ios/Pods/Folly/folly/detail/GroupVarintDetail.h index 61eb65673..b24af6f0a 100644 --- a/ios/Pods/Folly/folly/detail/GroupVarintDetail.h +++ b/ios/Pods/Folly/folly/detail/GroupVarintDetail.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/detail/IPAddress.h b/ios/Pods/Folly/folly/detail/IPAddress.h index b5f8adbed..c4fe2270e 100644 --- a/ios/Pods/Folly/folly/detail/IPAddress.h +++ b/ios/Pods/Folly/folly/detail/IPAddress.h @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/detail/IPAddressSource.h b/ios/Pods/Folly/folly/detail/IPAddressSource.h index b81d85473..e8cbb8777 100644 --- a/ios/Pods/Folly/folly/detail/IPAddressSource.h +++ b/ios/Pods/Folly/folly/detail/IPAddressSource.h @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/detail/Iterators.h b/ios/Pods/Folly/folly/detail/Iterators.h index fad73e130..a2e5e53b0 100644 --- a/ios/Pods/Folly/folly/detail/Iterators.h +++ b/ios/Pods/Folly/folly/detail/Iterators.h @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -50,10 +50,11 @@ namespace folly { namespace detail { /** - * Currently this only supports forward iteration. The derived class must - * must have definitions for these three methods: + * Currently this only supports forward and bidirectional iteration. The + * derived class must must have definitions for these methods: * * void increment(); + * void decrement(); // optional, to be used with bidirectional * reference dereference() const; * bool equal([appropriate iterator type] const& rhs) const; * @@ -63,15 +64,18 @@ namespace detail { * Template parameters: * D: the deriving class (CRTP) * V: value type + * Tag: the iterator category, one of: + * std::forward_iterator_tag + * std::bidirectional_iterator_tag */ -template <class D, class V> +template <class D, class V, class Tag> class IteratorFacade { public: using value_type = V; using reference = value_type&; using pointer = value_type*; using difference_type = ssize_t; - using iterator_category = std::forward_iterator_tag; + using iterator_category = Tag; bool operator==(D const& rhs) const { return asDerivedConst().equal(rhs); @@ -119,6 +123,17 @@ class IteratorFacade { return ret; } + D& operator--() { + asDerived().decrement(); + return asDerived(); + } + + D operator--(int) { + auto ret = asDerived(); // copy + asDerived().decrement(); + return ret; + } + private: D& asDerived() { return static_cast<D&>(*this); @@ -138,10 +153,10 @@ class IteratorFacade { * I: the wrapper iterator type * V: value type */ -template <class D, class I, class V> -class IteratorAdaptor : public IteratorFacade<D, V> { +template <class D, class I, class V, class Tag> +class IteratorAdaptor : public IteratorFacade<D, V, Tag> { public: - using Super = IteratorFacade<D, V>; + using Super = IteratorFacade<D, V, Tag>; using value_type = typename Super::value_type; using iterator_category = typename Super::iterator_category; using reference = typename Super::reference; @@ -149,10 +164,15 @@ class IteratorAdaptor : public IteratorFacade<D, V> { using difference_type = typename Super::difference_type; explicit IteratorAdaptor(I base) : base_(base) {} + void increment() { ++base_; } + void decrement() { + --base_; + } + V& dereference() const { return *base_; } diff --git a/ios/Pods/Folly/folly/detail/MPMCPipelineDetail.h b/ios/Pods/Folly/folly/detail/MPMCPipelineDetail.h index 4c874f670..e62e96e66 100644 --- a/ios/Pods/Folly/folly/detail/MPMCPipelineDetail.h +++ b/ios/Pods/Folly/folly/detail/MPMCPipelineDetail.h @@ -1,11 +1,11 @@ /* - * Copyright 2013-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/detail/MemoryIdler.h b/ios/Pods/Folly/folly/detail/MemoryIdler.h index 997f56f2c..4b4d797b0 100644 --- a/ios/Pods/Folly/folly/detail/MemoryIdler.h +++ b/ios/Pods/Folly/folly/detail/MemoryIdler.h @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/detail/PolyDetail.h b/ios/Pods/Folly/folly/detail/PolyDetail.h index aca2886e6..a5456a39a 100644 --- a/ios/Pods/Folly/folly/detail/PolyDetail.h +++ b/ios/Pods/Folly/folly/detail/PolyDetail.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -23,14 +23,23 @@ #include <typeinfo> #include <utility> +#include <folly/Portability.h> #include <folly/Traits.h> #include <folly/Utility.h> #include <folly/detail/TypeList.h> #include <folly/functional/Invoke.h> #include <folly/lang/Exception.h> +#include <folly/lang/StaticConst.h> #include <folly/PolyException.h> +#if defined(__cpp_template_auto) || \ + defined(__cpp_nontype_template_parameter_auto) +#define FOLLY_POLY_NTTP_AUTO 1 +#else +#define FOLLY_POLY_NTTP_AUTO 0 +#endif + namespace folly { /// \cond namespace detail { @@ -65,7 +74,7 @@ detail::AddCvrefOf<T, I>& poly_cast(detail::PolyRoot<I>&); template <class T, class I> detail::AddCvrefOf<T, I> const& poly_cast(detail::PolyRoot<I> const&); -#if !defined(__cpp_template_auto) +#if !FOLLY_POLY_NTTP_AUTO #define FOLLY_AUTO class template <class... Ts> using PolyMembers = detail::TypeList<Ts...>; @@ -180,26 +189,12 @@ itself, depending on the size of T and whether or not it has a noexcept move constructor. */ -template <class T> -using Uncvref = std::remove_cv_t<std::remove_reference_t<T>>; - template <class T, template <class...> class U> struct IsInstanceOf : std::false_type {}; template <class... Ts, template <class...> class U> struct IsInstanceOf<U<Ts...>, U> : std::true_type {}; -template <class T> -using Not = Bool<!T::value>; - -template <class T> -struct StaticConst { - static constexpr T value{}; -}; - -template <class T> -constexpr T StaticConst<T>::value; - template <class Then> decltype(auto) if_constexpr(std::true_type, Then then) { return then(Identity{}); @@ -233,20 +228,20 @@ struct PolyRef; struct PolyAccess; template <class T> -using IsPoly = IsInstanceOf<Uncvref<T>, Poly>; +using IsPoly = IsInstanceOf<remove_cvref_t<T>, Poly>; // Given an interface I and a concrete type T that satisfies the interface // I, create a list of member function bindings from members of T to members // of I. template <class I, class T> -using MembersOf = typename I::template Members<Uncvref<T>>; +using MembersOf = typename I::template Members<remove_cvref_t<T>>; // Given an interface I and a base type T, create a type that implements // the interface I in terms of the capabilities of T. template <class I, class T> using InterfaceOf = typename I::template Interface<T>; -#if !defined(__cpp_template_auto) +#if !FOLLY_POLY_NTTP_AUTO template <class T, T V> using Member = std::integral_constant<T, V>; @@ -387,13 +382,13 @@ struct Data { template <class U, class I> using Arg = - If<std::is_same<Uncvref<U>, Archetype<I>>::value, + If<std::is_same<remove_cvref_t<U>, Archetype<I>>::value, Poly<AddCvrefOf<I, U const&>>, U>; template <class U, class I> using Ret = - If<std::is_same<Uncvref<U>, Archetype<I>>::value, + If<std::is_same<remove_cvref_t<U>, Archetype<I>>::value, AddCvrefOf<Poly<I>, U>, U>; @@ -410,6 +405,19 @@ struct SignatureOf_<R (C::*)(As...) const, I> { using type = Ret<R, I> (*)(Data const&, Arg<As, I>...); }; +#if FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE +template <class R, class C, class... As, class I> +struct SignatureOf_<R (C::*)(As...) noexcept, I> { + using type = std::add_pointer_t<Ret<R, I>(Data&, Arg<As, I>...) noexcept>; +}; + +template <class R, class C, class... As, class I> +struct SignatureOf_<R (C::*)(As...) const noexcept, I> { + using type = + std::add_pointer_t<Ret<R, I>(Data const&, Arg<As, I>...) noexcept>; +}; +#endif + template <class R, class This, class... As, class I> struct SignatureOf_<R (*)(This&, As...), I> { using type = Ret<R, I> (*)(Data&, Arg<As, I>...); @@ -431,6 +439,13 @@ struct ArgTypes_<User, I, Ret (*)(Data, Args...)> { using type = TypeList<Args...>; }; +#if FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE +template <FOLLY_AUTO User, class I, class Ret, class Data, class... Args> +struct ArgTypes_<User, I, Ret (*)(Data, Args...) noexcept> { + using type = TypeList<Args...>; +}; +#endif + template <FOLLY_AUTO User, class I> using ArgTypes = _t<ArgTypes_<User, I>>; @@ -490,10 +505,10 @@ template <class Arg, class U> decltype(auto) convert(U&& u) { return detail::if_constexpr( StrictConjunction< - IsPolyRef<Uncvref<U>>, + IsPolyRef<remove_cvref_t<U>>, Negation<std::is_convertible<U, Arg>>>(), [&](auto id) -> decltype(auto) { - return poly_cast<Uncvref<Arg>>(id(u).get()); + return poly_cast<remove_cvref_t<Arg>>(id(u).get()); }, [&](auto id) -> U&& { return static_cast<U&&>(id(u)); }); } @@ -507,6 +522,14 @@ struct IsConstMember<R (C::*)(As...) const> : std::true_type {}; template <class R, class C, class... As> struct IsConstMember<R (*)(C const&, As...)> : std::true_type {}; +#if FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE +template <class R, class C, class... As> +struct IsConstMember<R (C::*)(As...) const noexcept> : std::true_type {}; + +template <class R, class C, class... As> +struct IsConstMember<R (*)(C const&, As...) noexcept> : std::true_type {}; +#endif + template < class T, FOLLY_AUTO User, @@ -602,7 +625,7 @@ void* execOnHeap(Op op, Data* from, void* to) { } throw_exception<BadPolyCast>(); case Op::eRefr: - return vtableForRef<I, Uncvref<T>>( + return vtableForRef<I, remove_cvref_t<T>>( static_cast<RefType>(reinterpret_cast<std::uintptr_t>(to))); } return nullptr; @@ -611,7 +634,7 @@ void* execOnHeap(Op op, Data* from, void* to) { template < class I, class T, - std::enable_if_t<Not<std::is_reference<T>>::value, int> = 0> + std::enable_if_t<Negation<std::is_reference<T>>::value, int> = 0> void* execOnHeap(Op op, Data* from, void* to) { switch (op) { case Op::eNuke: @@ -633,7 +656,7 @@ void* execOnHeap(Op op, Data* from, void* to) { } throw_exception<BadPolyCast>(); case Op::eRefr: - return vtableForRef<I, Uncvref<T>>( + return vtableForRef<I, remove_cvref_t<T>>( static_cast<RefType>(reinterpret_cast<std::uintptr_t>(to))); } return nullptr; @@ -664,7 +687,7 @@ void* execInSitu(Op op, Data* from, void* to) { } throw_exception<BadPolyCast>(); case Op::eRefr: - return vtableForRef<I, Uncvref<T>>( + return vtableForRef<I, remove_cvref_t<T>>( static_cast<RefType>(reinterpret_cast<std::uintptr_t>(to))); } return nullptr; @@ -681,16 +704,21 @@ struct BasePtr { VTable<I> const* vptr_; }; -template <class I, class T, std::enable_if_t<inSitu<T>(), int> = 0> -constexpr void* (*getOps() noexcept)(Op, Data*, void*) { +template <class I, class T> +constexpr void* (*getOpsImpl(std::true_type) noexcept)(Op, Data*, void*) { return &execInSitu<I, T>; } -template <class I, class T, std::enable_if_t<!inSitu<T>(), int> = 0> -constexpr void* (*getOps() noexcept)(Op, Data*, void*) { +template <class I, class T> +constexpr void* (*getOpsImpl(std::false_type) noexcept)(Op, Data*, void*) { return &execOnHeap<I, T>; } +template <class I, class T> +constexpr void* (*getOps() noexcept)(Op, Data*, void*) { + return getOpsImpl<I, T>(std::integral_constant<bool, inSitu<T>()>{}); +} + template <class I, FOLLY_AUTO... Arch, class... S> struct VTable<I, PolyMembers<Arch...>, TypeList<S...>> : BasePtr<S>..., std::tuple<SignatureOf<Arch, I>...> { @@ -743,10 +771,10 @@ struct PolyAccess { } template <class Poly> - using Iface = typename Uncvref<Poly>::_polyInterface_; + using Iface = typename remove_cvref_t<Poly>::_polyInterface_; template <class Node, class Tfx = MetaIdentity> - static typename Uncvref<Node>::template _polySelf_<Node, Tfx> self_(); + static typename remove_cvref_t<Node>::template _polySelf_<Node, Tfx> self_(); template <class T, class Poly, class I = Iface<Poly>> static decltype(auto) cast(Poly&& _this) { @@ -770,7 +798,8 @@ struct PolyAccess { } template <class I> - static VTable<Uncvref<I>> const* vtable(PolyRoot<I> const& _this) noexcept { + static VTable<remove_cvref_t<I>> const* vtable( + PolyRoot<I> const& _this) noexcept { return _this.vptr_; } @@ -839,8 +868,10 @@ struct PolyRoot : private PolyBase, private Data { }; template <class I> -using PolyImpl = - TypeFold<InclusiveSubsumptionsOf<Uncvref<I>>, PolyRoot<I>, MakePolyNode>; +using PolyImpl = TypeFold< + InclusiveSubsumptionsOf<remove_cvref_t<I>>, + PolyRoot<I>, + MakePolyNode>; // A const-qualified function type means the user is trying to disambiguate // a member function pointer. @@ -904,20 +935,31 @@ struct Sig<R(A&, As...)> : SigImpl<R, A&, As...> { } }; -template < - class T, - class I, - class U = std::decay_t<T>, - std::enable_if_t<Not<std::is_base_of<PolyBase, U>>::value, int> = 0, - std::enable_if_t<std::is_constructible<AddCvrefOf<U, I>, T>::value, int> = - 0, - class = MembersOf<std::decay_t<I>, U>> -std::true_type modelsInterface_(int); -template <class T, class I> -std::false_type modelsInterface_(long); +template <class T, class I, class = void> +struct ModelsInterface2_ : std::false_type {}; template <class T, class I> -struct ModelsInterface : decltype(modelsInterface_<T, I>(0)) {}; +struct ModelsInterface2_< + T, + I, + void_t< + std::enable_if_t< + std::is_constructible<AddCvrefOf<std::decay_t<T>, I>, T>::value>, + MembersOf<std::decay_t<I>, std::decay_t<T>>>> : std::true_type {}; + +template <class T, class I, class = void> +struct ModelsInterface_ : std::false_type {}; + +template <class T, class I> +struct ModelsInterface_< + T, + I, + std::enable_if_t< + Negation<std::is_base_of<PolyBase, std::decay_t<T>>>::value>> + : ModelsInterface2_<T, I> {}; + +template <class T, class I> +struct ModelsInterface : ModelsInterface_<T, I> {}; template <class I1, class I2> struct ValueCompatible : std::is_base_of<I1, I2> {}; diff --git a/ios/Pods/Folly/folly/detail/RangeCommon.h b/ios/Pods/Folly/folly/detail/RangeCommon.h index 6a4321337..9d0d2944c 100644 --- a/ios/Pods/Folly/folly/detail/RangeCommon.h +++ b/ios/Pods/Folly/folly/detail/RangeCommon.h @@ -1,11 +1,11 @@ /* - * Copyright 2015-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -17,10 +17,9 @@ #pragma once #include <algorithm> +#include <cassert> #include <string> -#include <glog/logging.h> - #include <folly/Likely.h> namespace folly { @@ -56,7 +55,7 @@ class StringPieceLite { return size() == 0; } const char& operator[](size_t i) const { - DCHECK_GT(size(), i); + assert(size() > i); return b_[i]; } template <typename Range> diff --git a/ios/Pods/Folly/folly/detail/RangeSse42.h b/ios/Pods/Folly/folly/detail/RangeSse42.h index d2a7d7d75..3f7c7e519 100644 --- a/ios/Pods/Folly/folly/detail/RangeSse42.h +++ b/ios/Pods/Folly/folly/detail/RangeSse42.h @@ -1,11 +1,11 @@ /* - * Copyright 2015-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/detail/Singleton.h b/ios/Pods/Folly/folly/detail/Singleton.h index 689451ddf..14bdec38f 100644 --- a/ios/Pods/Folly/folly/detail/Singleton.h +++ b/ios/Pods/Folly/folly/detail/Singleton.h @@ -1,11 +1,11 @@ /* - * Copyright 2018-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -16,6 +16,10 @@ #pragma once +#include <type_traits> + +#include <folly/Traits.h> + namespace folly { namespace detail { @@ -23,10 +27,21 @@ struct DefaultTag {}; template <typename T> struct DefaultMake { - // Required form until C++17, which permits returning objects of types which - // are neither copy-constructible nor move-constructible. - T* operator()(unsigned char (&buf)[sizeof(T)]) const { - return new (buf) T(); + struct Heap { + std::unique_ptr<T> ptr{std::make_unique<T>()}; + /* implicit */ operator T&() { + return *ptr; + } + }; + + using is_returnable = StrictDisjunction< + bool_constant<__cplusplus >= 201703ULL>, + std::is_copy_constructible<T>, + std::is_move_constructible<T>>; + using type = std::conditional_t<is_returnable::value, T, Heap>; + + type operator()() const { + return type(); } }; diff --git a/ios/Pods/Folly/folly/detail/SingletonStackTrace.h b/ios/Pods/Folly/folly/detail/SingletonStackTrace.h new file mode 100644 index 000000000..0f7f4ccbe --- /dev/null +++ b/ios/Pods/Folly/folly/detail/SingletonStackTrace.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <string> + +#include <folly/CPortability.h> + +namespace folly { +namespace detail { + +// empty-string indicates stack-trace functionality is not available +std::string getSingletonStackTrace(); + +} // namespace detail +} // namespace folly diff --git a/ios/Pods/Folly/folly/detail/SlowFingerprint.h b/ios/Pods/Folly/folly/detail/SlowFingerprint.h index 4a2b5fd15..8467fdba8 100644 --- a/ios/Pods/Folly/folly/detail/SlowFingerprint.h +++ b/ios/Pods/Folly/folly/detail/SlowFingerprint.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/detail/SocketFastOpen.h b/ios/Pods/Folly/folly/detail/SocketFastOpen.h index ccec07c1a..77a291423 100644 --- a/ios/Pods/Folly/folly/detail/SocketFastOpen.h +++ b/ios/Pods/Folly/folly/detail/SocketFastOpen.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -16,9 +16,11 @@ #pragma once -#include <folly/portability/Sockets.h> #include <sys/types.h> +#include <folly/net/NetworkSocket.h> +#include <folly/portability/Sockets.h> + #if !defined(FOLLY_ALLOW_TFO) #if defined(__linux__) || defined(__APPLE__) // only allow for linux right now @@ -28,21 +30,20 @@ namespace folly { namespace detail { - /** * tfo_sendto has the same semantics as sendmsg, but is used to * send with TFO data. */ -ssize_t tfo_sendmsg(int sockfd, const struct msghdr* msg, int flags); +ssize_t tfo_sendmsg(NetworkSocket sockfd, const struct msghdr* msg, int flags); /** * Enable TFO on a listening socket. */ -int tfo_enable(int sockfd, size_t max_queue_size); +int tfo_enable(NetworkSocket sockfd, size_t max_queue_size); /** * Check if TFO succeeded in being used. */ -bool tfo_succeeded(int sockfd); +bool tfo_succeeded(NetworkSocket sockfd); } // namespace detail } // namespace folly diff --git a/ios/Pods/Folly/folly/detail/Sse.h b/ios/Pods/Folly/folly/detail/Sse.h index dcf962136..5b85221ba 100644 --- a/ios/Pods/Folly/folly/detail/Sse.h +++ b/ios/Pods/Folly/folly/detail/Sse.h @@ -1,11 +1,11 @@ /* - * Copyright 2018-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -29,18 +29,14 @@ namespace detail { #if FOLLY_SSE_PREREQ(2, 0) -FOLLY_DISABLE_ADDRESS_SANITIZER __m128i -_mm_loadu_si128_noasan(__m128i const* const p); -FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN __m128i -_mm_loadu_si128_unchecked(__m128i const* const p) { - return kIsSanitizeAddress ? _mm_loadu_si128_noasan(p) : _mm_loadu_si128(p); +__m128i _mm_loadu_si128_nosan(__m128i const* const p); +FOLLY_ERASE __m128i _mm_loadu_si128_unchecked(__m128i const* const p) { + return kIsSanitize ? _mm_loadu_si128_nosan(p) : _mm_loadu_si128(p); } -FOLLY_DISABLE_ADDRESS_SANITIZER __m128i -_mm_load_si128_noasan(__m128i const* const p); -FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN __m128i -_mm_load_si128_unchecked(__m128i const* const p) { - return kIsSanitizeAddress ? _mm_load_si128_noasan(p) : _mm_load_si128(p); +__m128i _mm_load_si128_nosan(__m128i const* const p); +FOLLY_ERASE __m128i _mm_load_si128_unchecked(__m128i const* const p) { + return kIsSanitize ? _mm_load_si128_nosan(p) : _mm_load_si128(p); } #endif diff --git a/ios/Pods/Folly/folly/detail/StaticSingletonManager.h b/ios/Pods/Folly/folly/detail/StaticSingletonManager.h index 74ebc36cd..3e6ea3ef3 100644 --- a/ios/Pods/Folly/folly/detail/StaticSingletonManager.h +++ b/ios/Pods/Folly/folly/detail/StaticSingletonManager.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -16,64 +16,85 @@ #pragma once +#include <atomic> #include <typeinfo> #include <folly/CPortability.h> +#include <folly/Indestructible.h> +#include <folly/Likely.h> +#include <folly/detail/Singleton.h> +#include <folly/lang/TypeInfo.h> namespace folly { namespace detail { +// Does not support dynamic loading but works without rtti. +class StaticSingletonManagerSansRtti { + public: + template <typename T, typename Tag> + FOLLY_EXPORT FOLLY_ALWAYS_INLINE static T& create() { + static std::atomic<T*> cache{}; + auto const pointer = cache.load(std::memory_order_acquire); + return FOLLY_LIKELY(!!pointer) ? *pointer : create_<T, Tag>(cache); + } + + private: + template <typename T, typename Tag> + FOLLY_EXPORT FOLLY_NOINLINE static T& create_(std::atomic<T*>& cache) { + static Indestructible<T> instance; + cache.store(&*instance, std::memory_order_release); + return *instance; + } +}; + // This internal-use-only class is used to create all leaked Meyers singletons. // It guarantees that only one instance of every such singleton will ever be // created, even when requested from different compilation units linked // dynamically. -class StaticSingletonManager { +// +// Supports dynamic loading but requires rtti. +class StaticSingletonManagerWithRtti { public: - template <typename T, typename Tag, typename F> - FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN static T* create( - F&& creator) { - return static_cast<T*>(create_<T, Tag>(creator)); + template <typename T, typename Tag> + FOLLY_EXPORT FOLLY_ALWAYS_INLINE static T& create() { + // gcc and clang behave poorly if typeid is hidden behind a non-constexpr + // function, but typeid is not constexpr under msvc + static Arg arg{{nullptr}, FOLLY_TYPE_INFO_OF(tag_t<T, Tag>), make<T>}; + auto const v = arg.cache.load(std::memory_order_acquire); + auto const p = FOLLY_LIKELY(!!v) ? v : create_<noexcept(T())>(arg); + return *static_cast<T*>(p); } private: - template <typename A, typename B> - struct TypePair {}; - using Key = std::type_info; - using Make = void*(void*); - - template <typename F> - struct Creator { - static void* create(void* f) { - return static_cast<void*>((*static_cast<F*>(f))()); - } + using Make = void*(); + using Cache = std::atomic<void*>; + struct Arg { + Cache cache; // should be first field + Key const* key; + Make& make; }; - template <typename T, typename Tag, typename F> - FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN static void* create_( - F& creator) { - auto const& key = typeid(TypePair<T, Tag>); - return create_(key, &Creator<F>::create, &creator); + template <typename T> + static void* make() { + return new T(); } - template <typename T, typename Tag, typename F> - FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN static void* create_( - F const& creator) { - auto const& key = typeid(TypePair<T, Tag>); - return create_(key, &Creator<F const>::create, const_cast<F*>(&creator)); + template <bool Noexcept> + FOLLY_ERASE static void* create_(Arg& arg) noexcept(Noexcept) { + return create_(arg); } - - FOLLY_NOINLINE static void* create_(Key const& key, Make* make, void* ctx); + FOLLY_NOINLINE static void* create_(Arg& arg); }; -template <typename T, typename Tag, typename F> -FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN T* createGlobal(F&& creator) { - return StaticSingletonManager::create<T, Tag>(static_cast<F&&>(creator)); -} +using StaticSingletonManager = std::conditional_t< + kHasRtti, + StaticSingletonManagerWithRtti, + StaticSingletonManagerSansRtti>; template <typename T, typename Tag> -FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN T* createGlobal() { - return StaticSingletonManager::create<T, Tag>([]() { return new T(); }); +FOLLY_ERASE T& createGlobal() { + return StaticSingletonManager::create<T, Tag>(); } } // namespace detail diff --git a/ios/Pods/Folly/folly/detail/ThreadLocalDetail.h b/ios/Pods/Folly/folly/detail/ThreadLocalDetail.h index 67ee7dce2..39e0570c4 100644 --- a/ios/Pods/Folly/folly/detail/ThreadLocalDetail.h +++ b/ios/Pods/Folly/folly/detail/ThreadLocalDetail.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -22,6 +22,7 @@ #include <functional> #include <mutex> #include <string> +#include <thread> #include <vector> #include <glog/logging.h> @@ -36,6 +37,7 @@ #include <folly/memory/Malloc.h> #include <folly/portability/PThread.h> #include <folly/synchronization/MicroSpinLock.h> +#include <folly/system/ThreadId.h> #include <folly/detail/StaticSingletonManager.h> @@ -209,12 +211,12 @@ struct ThreadEntryList; struct ThreadEntry { ElementWrapper* elements{nullptr}; std::atomic<size_t> elementsCapacity{0}; - ThreadEntry* next{nullptr}; - ThreadEntry* prev{nullptr}; ThreadEntryList* list{nullptr}; ThreadEntry* listNext{nullptr}; StaticMetaBase* meta{nullptr}; bool removed_{false}; + uint64_t tid_os{}; + aligned_storage_for_t<std::thread::id> tid_data{}; size_t getElementsCapacity() const noexcept { return elementsCapacity.load(std::memory_order_relaxed); @@ -223,6 +225,10 @@ struct ThreadEntry { void setElementsCapacity(size_t capacity) noexcept { elementsCapacity.store(capacity, std::memory_order_relaxed); } + + std::thread::id& tid() { + return *reinterpret_cast<std::thread::id*>(&tid_data); + } }; struct ThreadEntryList { @@ -341,21 +347,10 @@ struct StaticMetaBase { StaticMetaBase(ThreadEntry* (*threadEntry)(), bool strict); - void push_back(ThreadEntry* t) { - t->next = &head_; - t->prev = head_.prev; - head_.prev->next = t; - head_.prev = t; - } - - void erase(ThreadEntry* t) { - t->next->prev = t->prev; - t->prev->next = t->next; - t->next = t->prev = t; - } - FOLLY_EXPORT static ThreadEntryList* getThreadEntryList(); + static bool dying(); + static void onThreadExit(void* ptr); // returns the elementsCapacity for the @@ -400,7 +395,9 @@ struct StaticMetaBase { bool strict_; protected: - ~StaticMetaBase() {} + [[noreturn]] ~StaticMetaBase() { + std::terminate(); + } }; // Held in a singleton to track our global instances. @@ -423,14 +420,10 @@ struct StaticMeta final : StaticMetaBase { /*child*/ &StaticMeta::onForkChild); } - ~StaticMeta() = delete; - static StaticMeta<Tag, AccessMode>& instance() { // Leak it on exit, there's only one per process and we don't have to // worry about synchronization with exiting threads. - /* library-local */ static auto instance = - detail::createGlobal<StaticMeta<Tag, AccessMode>, void>(); - return *instance; + return detail::createGlobal<StaticMeta<Tag, AccessMode>, void>(); } FOLLY_EXPORT FOLLY_ALWAYS_INLINE static ElementWrapper& get(EntryID* ent) { @@ -488,6 +481,9 @@ struct StaticMeta final : StaticMetaBase { threadEntryList->head = threadEntry; } + threadEntry->tid() = std::this_thread::get_id(); + threadEntry->tid_os = folly::getOSThreadID(); + // if we're adding a thread entry // we need to increment the list count // even if the entry is reused @@ -511,8 +507,6 @@ struct StaticMeta final : StaticMetaBase { static void onForkChild() { // only the current thread survives auto& head = instance().head_; - // init the head list - head.next = head.prev = &head; // init the circular lists auto elementsCapacity = head.getElementsCapacity(); for (size_t i = 0u; i < elementsCapacity; ++i) { @@ -529,10 +523,6 @@ struct StaticMeta final : StaticMetaBase { } } - // If this thread was in the list before the fork, add it back. - if (elementsCapacity != 0) { - instance().push_back(threadEntry); - } instance().lock_.unlock(); } }; diff --git a/ios/Pods/Folly/folly/detail/TurnSequencer.h b/ios/Pods/Folly/folly/detail/TurnSequencer.h index be011ede9..8fd0212af 100644 --- a/ios/Pods/Folly/folly/detail/TurnSequencer.h +++ b/ios/Pods/Folly/folly/detail/TurnSequencer.h @@ -1,11 +1,11 @@ /* - * Copyright 2015-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -19,6 +19,8 @@ #include <algorithm> #include <limits> +#include <folly/Portability.h> +#include <folly/chrono/Hardware.h> #include <folly/detail/Futex.h> #include <folly/portability/Asm.h> #include <folly/portability/Unistd.h> @@ -68,6 +70,12 @@ namespace detail { /// cutoffs for different operations (read versus write, for example). /// To avoid contention, the spin cutoff is only updated when requested /// by the caller. +/// +/// On x86 the latency of a spin loop varies dramatically across +/// architectures due to changes in the PAUSE instruction. Skylake +/// increases the latency by about a factor of 15 compared to previous +/// architectures. To work around this, on x86 we measure spins using +/// RDTSC rather than a loop counter. template <template <typename> class Atom> struct TurnSequencer { explicit TurnSequencer(const uint32_t firstTurn = 0) noexcept @@ -96,13 +104,13 @@ struct TurnSequencer { // the bottom to store the number of waiters. We call shifted turns // "sturns" inside this class. - /// Blocks the current thread until turn has arrived. If - /// updateSpinCutoff is true then this will spin for up to kMaxSpins tries - /// before blocking and will adjust spinCutoff based on the results, - /// otherwise it will spin for at most spinCutoff spins. - /// Returns SUCCESS if the wait succeeded, PAST if the turn is in the past - /// or TIMEDOUT if the absTime time value is not nullptr and is reached before - /// the turn arrives + /// Blocks the current thread until turn has arrived. + /// If updateSpinCutoff is true then this will spin for up to + /// kMaxSpinLimit before blocking and will adjust spinCutoff based + /// on the results, otherwise it will spin for at most spinCutoff. + /// Returns SUCCESS if the wait succeeded, PAST if the turn is in the + /// past or TIMEDOUT if the absTime time value is not nullptr and is + /// reached before the turn arrives template < class Clock = std::chrono::steady_clock, class Duration = typename Clock::duration> @@ -114,8 +122,9 @@ struct TurnSequencer { nullptr) noexcept { uint32_t prevThresh = spinCutoff.load(std::memory_order_relaxed); const uint32_t effectiveSpinCutoff = - updateSpinCutoff || prevThresh == 0 ? kMaxSpins : prevThresh; + updateSpinCutoff || prevThresh == 0 ? kMaxSpinLimit : prevThresh; + uint64_t begin; uint32_t tries; const uint32_t sturn = turn << kTurnShift; for (tries = 0;; ++tries) { @@ -133,9 +142,20 @@ struct TurnSequencer { // the first effectSpinCutoff tries are spins, after that we will // record ourself as a waiter and block with futexWait - if (tries < effectiveSpinCutoff) { - asm_volatile_pause(); - continue; + if (kSpinUsingHardwareClock) { + auto now = hardware_timestamp(); + if (tries == 0) { + begin = now; + } + if (tries == 0 || now < begin + effectiveSpinCutoff) { + asm_volatile_pause(); + continue; + } + } else { + if (tries < effectiveSpinCutoff) { + asm_volatile_pause(); + continue; + } } uint32_t current_max_waiter_delta = decodeMaxWaitersDelta(state); @@ -164,16 +184,21 @@ struct TurnSequencer { } if (updateSpinCutoff || prevThresh == 0) { - // if we hit kMaxSpins then spinning was pointless, so the right - // spinCutoff is kMinSpins + // if we hit kMaxSpinLimit then spinning was pointless, so the right + // spinCutoff is kMinSpinLimit uint32_t target; - if (tries >= kMaxSpins) { - target = kMinSpins; + uint64_t elapsed = !kSpinUsingHardwareClock || tries == 0 + ? tries + : hardware_timestamp() - begin; + if (tries >= kMaxSpinLimit) { + target = kMinSpinLimit; } else { // to account for variations, we allow ourself to spin 2*N when // we think that N is actually required in order to succeed - target = std::min<uint32_t>( - kMaxSpins, std::max<uint32_t>(kMinSpins, tries * 2)); + target = std::min( + uint32_t{kMaxSpinLimit}, + std::max( + uint32_t{kMinSpinLimit}, static_cast<uint32_t>(elapsed) * 2)); } if (prevThresh == 0) { @@ -219,25 +244,29 @@ struct TurnSequencer { } private: - enum : uint32_t { - /// kTurnShift counts the bits that are stolen to record the delta - /// between the current turn and the maximum waiter. It needs to be big - /// enough to record wait deltas of 0 to 32 inclusive. Waiters more - /// than 32 in the future will be woken up 32*n turns early (since - /// their BITSET will hit) and will adjust the waiter count again. - /// We go a bit beyond and let the waiter count go up to 63, which - /// is free and might save us a few CAS - kTurnShift = 6, - kWaitersMask = (1 << kTurnShift) - 1, + static constexpr bool kSpinUsingHardwareClock = kIsArchAmd64; + static constexpr uint32_t kCyclesPerSpinLimit = + kSpinUsingHardwareClock ? 1 : 10; - /// The minimum spin count that we will adaptively select - kMinSpins = 20, + /// kTurnShift counts the bits that are stolen to record the delta + /// between the current turn and the maximum waiter. It needs to be big + /// enough to record wait deltas of 0 to 32 inclusive. Waiters more + /// than 32 in the future will be woken up 32*n turns early (since + /// their BITSET will hit) and will adjust the waiter count again. + /// We go a bit beyond and let the waiter count go up to 63, which is + /// free and might save us a few CAS + static constexpr uint32_t kTurnShift = 6; + static constexpr uint32_t kWaitersMask = (1 << kTurnShift) - 1; - /// The maximum spin count that we will adaptively select, and the - /// spin count that will be used when probing to get a new data point - /// for the adaptation - kMaxSpins = 2000, - }; + /// The minimum spin duration that we will adaptively select. The value + /// here is cycles, adjusted to the way in which the limit will actually + /// be applied. + static constexpr uint32_t kMinSpinLimit = 200 / kCyclesPerSpinLimit; + + /// The maximum spin duration that we will adaptively select, and the + /// spin duration that will be used when probing to get a new data + /// point for the adaptation + static constexpr uint32_t kMaxSpinLimit = 20000 / kCyclesPerSpinLimit; /// This holds both the current turn, and the highest waiting turn, /// stored as (current_turn << 6) | min(63, max(waited_turn - current_turn)) diff --git a/ios/Pods/Folly/folly/detail/TypeList.h b/ios/Pods/Folly/folly/detail/TypeList.h index 11643ade7..be2ee3338 100644 --- a/ios/Pods/Folly/folly/detail/TypeList.h +++ b/ios/Pods/Folly/folly/detail/TypeList.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -168,8 +168,10 @@ using If = MetaApply<impl::If_<If_>, Then, Else>; */ template <template <class...> class C, class... Ts> class MetaDefer { - template <template <class...> class D = C, class = D<Ts...>> + template <template <class...> class D, class = D<Ts...>> static char (&try_(int))[1]; + + template <template <class...> class D, class = void> static char (&try_(long))[2]; struct Result { using type = C<Ts...>; @@ -177,7 +179,7 @@ class MetaDefer { public: template <class... Us> - using apply = _t<If<sizeof(try_(0)) - 1 || sizeof...(Us), Empty, Result>>; + using apply = _t<If<sizeof(try_<C>(0)) - 1 || sizeof...(Us), Empty, Result>>; }; /** @@ -496,7 +498,7 @@ struct AsTypeList_<T<Ts...>> { using type = TypeList<Ts...>; }; template <class T, T... Is> -struct AsTypeList_<folly::integer_sequence<T, Is...>> { +struct AsTypeList_<std::integer_sequence<T, Is...>> { using type = TypeList<std::integral_constant<T, Is>...>; }; } // namespace impl diff --git a/ios/Pods/Folly/folly/detail/UniqueInstance.cpp b/ios/Pods/Folly/folly/detail/UniqueInstance.cpp new file mode 100644 index 000000000..cd9e4df65 --- /dev/null +++ b/ios/Pods/Folly/folly/detail/UniqueInstance.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <folly/detail/UniqueInstance.h> + +#include <cstdlib> +#include <iostream> +#include <sstream> +#include <stdexcept> +#include <string> + +#include <folly/Demangle.h> +#include <folly/lang/Exception.h> + +namespace folly { +namespace detail { + +namespace { + +using Ptr = std::type_info const*; +struct PtrRange { + Ptr const* b; + Ptr const* e; +}; + +template <typename Value> +PtrRange ptr_range_key(Value value) { + auto const data = value.ptrs; + return {data, data + value.key_size}; +} + +template <typename Value> +PtrRange ptr_range_mapped(Value value) { + auto const data = value.ptrs + value.key_size; + return {data, data + value.mapped_size}; +} + +bool equal(PtrRange lhs, PtrRange rhs) { + auto const cmp = [](auto a, auto b) { return *a == *b; }; + return std::equal(lhs.b, lhs.e, rhs.b, rhs.e, cmp); +} + +std::string join(PtrRange types) { + std::ostringstream ret; + for (auto t = types.b; t != types.e; ++t) { + if (t != types.b) { + ret << ", "; + } + ret << demangle((*t)->name()); + } + return ret.str(); +} + +template <typename Value> +std::string render(Value value) { + auto const key_s = join(ptr_range_key(value)); + auto const mapped_s = join(ptr_range_mapped(value)); + std::ostringstream ret; + ret << value.tmpl << "<" << key_s << ", " << mapped_s << ">"; + return ret.str(); +} + +} // namespace + +void UniqueInstance::enforce( + char const* tmpl, + Ptr const* ptrs, + std::uint32_t key_size, + std::uint32_t mapped_size, + Value& global) noexcept { + Value const local{tmpl, ptrs, key_size, mapped_size}; + + if (!global.tmpl) { + global = local; + return; + } + if (!equal(ptr_range_key(global), ptr_range_key(local))) { + throw_exception<std::logic_error>("mismatched unique instance"); + } + if (std::strcmp(global.tmpl, local.tmpl) == 0 && + equal(ptr_range_mapped(global), ptr_range_mapped(local))) { + return; + } + + auto const key = ptr_range_key(local); + + std::ios_base::Init io_init; + std::cerr << "Overloaded unique instance over <" << join(key) << ", ...> " + << "with differing trailing arguments:\n" + << " " << render(global) << "\n" + << " " << render(local) << "\n"; + std::abort(); +} + +} // namespace detail +} // namespace folly diff --git a/ios/Pods/Folly/folly/detail/UniqueInstance.h b/ios/Pods/Folly/folly/detail/UniqueInstance.h new file mode 100644 index 000000000..fded57d6f --- /dev/null +++ b/ios/Pods/Folly/folly/detail/UniqueInstance.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <cstdint> +#include <typeinfo> + +#include <folly/detail/StaticSingletonManager.h> + +namespace folly { +namespace detail { + +class UniqueInstance { + public: + template <typename... Key, typename... Mapped> + FOLLY_EXPORT explicit UniqueInstance( + char const* tmpl, + tag_t<Key...>, + tag_t<Mapped...>) noexcept { + static Ptr const ptrs[] = {&typeid(Key)..., &typeid(Mapped)...}; + auto& global = createGlobal<Value, tag_t<Tag, Key...>>(); + enforce(tmpl, ptrs, sizeof...(Key), sizeof...(Mapped), global); + } + + UniqueInstance(UniqueInstance const&) = delete; + UniqueInstance(UniqueInstance&&) = delete; + UniqueInstance& operator=(UniqueInstance const&) = delete; + UniqueInstance& operator=(UniqueInstance&&) = delete; + + private: + struct Tag {}; + + using Ptr = std::type_info const*; + struct PtrRange { + Ptr const* b; + Ptr const* e; + }; + struct Value { + char const* tmpl; + Ptr const* ptrs; + std::uint32_t key_size; + std::uint32_t mapped_size; + }; + + // Under Clang, this call signature shrinks the aligned and padded size of + // call-sites, as compared to a call signature taking Value or Value const&. + static void enforce( + char const* tmpl, + Ptr const* ptrs, + std::uint32_t key_size, + std::uint32_t mapped_size, + Value& global) noexcept; +}; + +} // namespace detail +} // namespace folly diff --git a/ios/Pods/Folly/folly/dynamic-inl.h b/ios/Pods/Folly/folly/dynamic-inl.h index 1de293e1f..c3edb2a69 100644 --- a/ios/Pods/Folly/folly/dynamic-inl.h +++ b/ios/Pods/Folly/folly/dynamic-inl.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #pragma once #include <functional> @@ -119,7 +120,6 @@ struct hash<::folly::dynamic> { apply(std::string); \ break; \ default: \ - CHECK(0); \ abort(); \ } \ } while (0) @@ -134,17 +134,6 @@ struct FOLLY_EXPORT TypeError : std::runtime_error { const std::string& expected, dynamic::Type actual1, dynamic::Type actual2); - // TODO: noexcept calculation required through gcc-v4.9; remove once upgrading - // to gcc-v5. - TypeError(const TypeError&) noexcept( - std::is_nothrow_copy_constructible<std::runtime_error>::value); - TypeError& operator=(const TypeError&) noexcept( - std::is_nothrow_copy_assignable<std::runtime_error>::value); - TypeError(TypeError&&) noexcept( - std::is_nothrow_move_constructible<std::runtime_error>::value); - TypeError& operator=(TypeError&&) noexcept( - std::is_nothrow_move_assignable<std::runtime_error>::value); - ~TypeError() override; }; ////////////////////////////////////////////////////////////////////// @@ -170,12 +159,7 @@ dynamic numericOp(dynamic const& a, dynamic const& b) { if (!a.isNumber() || !b.isNumber()) { throw_exception<TypeError>("numeric", a.type(), b.type()); } - if (a.type() != b.type()) { - auto& integ = a.isInt() ? a : b; - auto& nonint = a.isInt() ? b : a; - return Op<double>()(to<double>(integ.asInt()), nonint.asDouble()); - } - if (a.isDouble()) { + if (a.isDouble() || b.isDouble()) { return Op<double>()(a.asDouble(), b.asDouble()); } return Op<int64_t>()(a.asInt(), b.asInt()); @@ -249,11 +233,13 @@ inline dynamic::ObjectMaker dynamic::object(dynamic a, dynamic b) { struct dynamic::item_iterator : detail::IteratorAdaptor< dynamic::item_iterator, dynamic::ObjectImpl::iterator, - std::pair<dynamic const, dynamic>> { + std::pair<dynamic const, dynamic>, + std::forward_iterator_tag> { using Super = detail::IteratorAdaptor< dynamic::item_iterator, dynamic::ObjectImpl::iterator, - std::pair<dynamic const, dynamic>>; + std::pair<dynamic const, dynamic>, + std::forward_iterator_tag>; /* implicit */ item_iterator(dynamic::ObjectImpl::iterator b) : Super(b) {} using object_type = dynamic::ObjectImpl; @@ -262,11 +248,13 @@ struct dynamic::item_iterator : detail::IteratorAdaptor< struct dynamic::value_iterator : detail::IteratorAdaptor< dynamic::value_iterator, dynamic::ObjectImpl::iterator, - dynamic> { + dynamic, + std::forward_iterator_tag> { using Super = detail::IteratorAdaptor< dynamic::value_iterator, dynamic::ObjectImpl::iterator, - dynamic>; + dynamic, + std::forward_iterator_tag>; /* implicit */ value_iterator(dynamic::ObjectImpl::iterator b) : Super(b) {} using object_type = dynamic::ObjectImpl; @@ -280,11 +268,13 @@ struct dynamic::const_item_iterator : detail::IteratorAdaptor< dynamic::const_item_iterator, dynamic::ObjectImpl::const_iterator, - std::pair<dynamic const, dynamic> const> { + std::pair<dynamic const, dynamic> const, + std::forward_iterator_tag> { using Super = detail::IteratorAdaptor< dynamic::const_item_iterator, dynamic::ObjectImpl::const_iterator, - std::pair<dynamic const, dynamic> const>; + std::pair<dynamic const, dynamic> const, + std::forward_iterator_tag>; /* implicit */ const_item_iterator(dynamic::ObjectImpl::const_iterator b) : Super(b) {} /* implicit */ const_item_iterator(const_item_iterator const& i) @@ -297,11 +287,13 @@ struct dynamic::const_item_iterator struct dynamic::const_key_iterator : detail::IteratorAdaptor< dynamic::const_key_iterator, dynamic::ObjectImpl::const_iterator, - dynamic const> { + dynamic const, + std::forward_iterator_tag> { using Super = detail::IteratorAdaptor< dynamic::const_key_iterator, dynamic::ObjectImpl::const_iterator, - dynamic const>; + dynamic const, + std::forward_iterator_tag>; /* implicit */ const_key_iterator(dynamic::ObjectImpl::const_iterator b) : Super(b) {} @@ -315,11 +307,13 @@ struct dynamic::const_key_iterator : detail::IteratorAdaptor< struct dynamic::const_value_iterator : detail::IteratorAdaptor< dynamic::const_value_iterator, dynamic::ObjectImpl::const_iterator, - dynamic const> { + dynamic const, + std::forward_iterator_tag> { using Super = detail::IteratorAdaptor< dynamic::const_value_iterator, dynamic::ObjectImpl::const_iterator, - dynamic const>; + dynamic const, + std::forward_iterator_tag>; /* implicit */ const_value_iterator(dynamic::ObjectImpl::const_iterator b) : Super(b) {} /* implicit */ const_value_iterator(value_iterator i) : Super(i.base()) {} @@ -773,6 +767,27 @@ inline dynamic* dynamic::get_ptr(StringPiece idx) & { return const_cast<dynamic*>(const_cast<dynamic const*>(this)->get_ptr(idx)); } +// clang-format off +inline +dynamic::resolved_json_pointer<dynamic> +dynamic::try_get_ptr(json_pointer const& jsonPtr) & { + auto ret = const_cast<dynamic const*>(this)->try_get_ptr(jsonPtr); + if (ret.hasValue()) { + return json_pointer_resolved_value<dynamic>{ + const_cast<dynamic*>(ret.value().parent), + const_cast<dynamic*>(ret.value().value), + ret.value().parent_key, ret.value().parent_index}; + } else { + return makeUnexpected( + json_pointer_resolution_error<dynamic>{ + ret.error().error_code, + ret.error().index, + const_cast<dynamic*>(ret.error().context)} + ); + } +} +// clang-format on + inline dynamic* dynamic::get_ptr(json_pointer const& jsonPtr) & { return const_cast<dynamic*>( const_cast<dynamic const*>(this)->get_ptr(jsonPtr)); @@ -840,11 +855,17 @@ inline std::size_t dynamic::count(StringPiece key) const { } template <class K, class V> -inline void dynamic::insert(K&& key, V&& val) { +inline dynamic::IfNotIterator<K, void> dynamic::insert(K&& key, V&& val) { auto& obj = get<ObjectImpl>(); obj[std::forward<K>(key)] = std::forward<V>(val); } +template <class T> +inline dynamic::iterator dynamic::insert(const_iterator pos, T&& value) { + auto& arr = get<Array>(); + return arr.insert(pos, std::forward<T>(value)); +} + inline void dynamic::update(const dynamic& mergeObj) { if (!isObject() || !mergeObj.isObject()) { throw_exception<TypeError>("object", type(), mergeObj.type()); @@ -971,6 +992,11 @@ inline void dynamic::pop_back() { arr.pop_back(); } +inline const dynamic& dynamic::back() const { + auto& arr = get<Array>(); + return arr.back(); +} + ////////////////////////////////////////////////////////////////////// inline dynamic::dynamic(Array&& r) : type_(ARRAY) { @@ -1006,6 +1032,9 @@ T dynamic::asImpl() const { return to<T>(*get_nothrow<bool>()); case STRING: return to<T>(*get_nothrow<std::string>()); + case NULLT: + case ARRAY: + case OBJECT: default: throw_exception<TypeError>("int/double/bool/string", type()); } diff --git a/ios/Pods/Folly/folly/dynamic.cpp b/ios/Pods/Folly/folly/dynamic.cpp index 2261322d3..48c8157a2 100644 --- a/ios/Pods/Folly/folly/dynamic.cpp +++ b/ios/Pods/Folly/folly/dynamic.cpp @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -14,11 +14,14 @@ * limitations under the License. */ -#include <numeric> - #include <folly/dynamic.h> +#include <numeric> + +#include <glog/logging.h> + #include <folly/Format.h> +#include <folly/container/Enumerate.h> #include <folly/hash/Hash.h> #include <folly/lang/Assume.h> #include <folly/lang/Exception.h> @@ -62,16 +65,6 @@ TypeError::TypeError( dynamic::typeName(actual1), dynamic::typeName(actual2))) {} -TypeError::TypeError(const TypeError&) noexcept( - std::is_nothrow_copy_constructible<std::runtime_error>::value) = default; -TypeError& TypeError::operator=(const TypeError&) noexcept( - std::is_nothrow_copy_assignable<std::runtime_error>::value) = default; -TypeError::TypeError(TypeError&&) noexcept( - std::is_nothrow_move_constructible<std::runtime_error>::value) = default; -TypeError& TypeError::operator=(TypeError&&) noexcept( - std::is_nothrow_move_assignable<std::runtime_error>::value) = default; -TypeError::~TypeError() = default; - // This is a higher-order preprocessor macro to aid going from runtime // types to the compile time type system. #define FB_DYNAMIC_APPLY(type, apply) \ @@ -299,12 +292,12 @@ std::size_t dynamic::hash() const { // Accumulate using addition instead of using hash_range (as in the ARRAY // case), as we need a commutative hash operation since unordered_map's // iteration order is unspecified. - auto h = std::hash<std::pair<dynamic, dynamic>>{}; + auto h = std::hash<std::pair<dynamic const, dynamic>>{}; return std::accumulate( items().begin(), items().end(), size_t{0x0B1EC7}, - [&](auto acc, auto item) { return acc + h(item); }); + [&](auto acc, auto const& item) { return acc + h(item); }); } case ARRAY: return folly::hash::hash_range(begin(), end()); @@ -368,46 +361,112 @@ dynamic dynamic::merge_diff(const dynamic& source, const dynamic& target) { return diff; } -const dynamic* dynamic::get_ptr(json_pointer const& jsonPtr) const& { +// clang-format off +dynamic::resolved_json_pointer<dynamic const> +// clang-format on +dynamic::try_get_ptr(json_pointer const& jsonPtr) const& { + using err_code = json_pointer_resolution_error_code; + using error = json_pointer_resolution_error<dynamic const>; + auto const& tokens = jsonPtr.tokens(); if (tokens.empty()) { - return this; + return json_pointer_resolved_value<dynamic const>{ + nullptr, this, {nullptr, nullptr}, 0}; } - dynamic const* dyn = this; - for (auto const& token : tokens) { - if (!dyn) { + + dynamic const* curr = this; + dynamic const* prev = nullptr; + + size_t curr_idx{0}; + StringPiece curr_key{}; + + for (auto it : enumerate(tokens)) { + // hit bottom but pointer not exhausted yet + if (!curr) { + return makeUnexpected( + error{err_code::json_pointer_out_of_bounds, it.index, prev}); + } + prev = curr; + // handle lookup in array + if (auto const* parray = curr->get_nothrow<dynamic::Array>()) { + if (it->size() > 1 && it->at(0) == '0') { + return makeUnexpected( + error{err_code::index_has_leading_zero, it.index, prev}); + } + // if last element of pointer is '-', this is an append operation + if (it->size() == 1 && it->at(0) == '-') { + // was '-' the last token in pointer? + if (it.index == tokens.size() - 1) { + return makeUnexpected( + error{err_code::append_requested, it.index, prev}); + } + // Cannot resolve past '-' in an array + curr = nullptr; + continue; + } + auto const idx = tryTo<size_t>(*it); + if (!idx.hasValue()) { + return makeUnexpected( + error{err_code::index_not_numeric, it.index, prev}); + } + if (idx.value() < parray->size()) { + curr = &(*parray)[idx.value()]; + curr_idx = idx.value(); + } else { + return makeUnexpected( + error{err_code::index_out_of_bounds, it.index, prev}); + } + continue; + } + // handle lookup in object + if (auto const* pobject = curr->get_nothrow<dynamic::ObjectImpl>()) { + auto const sub_it = pobject->find(*it); + if (sub_it == pobject->end()) { + return makeUnexpected(error{err_code::key_not_found, it.index, prev}); + } + curr = &sub_it->second; + curr_key = *it; + continue; + } + return makeUnexpected( + error{err_code::element_not_object_or_array, it.index, prev}); + } + return json_pointer_resolved_value<dynamic const>{ + prev, curr, curr_key, curr_idx}; +} + +const dynamic* dynamic::get_ptr(json_pointer const& jsonPtr) const& { + using err_code = json_pointer_resolution_error_code; + + auto ret = try_get_ptr(jsonPtr); + if (ret.hasValue()) { + return ret.value().value; + } + + auto const ctx = ret.error().context; + auto const objType = ctx ? ctx->type() : Type::NULLT; + + switch (ret.error().error_code) { + case err_code::key_not_found: + return nullptr; + case err_code::index_out_of_bounds: + return nullptr; + case err_code::append_requested: + return nullptr; + case err_code::index_not_numeric: + throw std::invalid_argument("array index is not numeric"); + case err_code::index_has_leading_zero: + throw std::invalid_argument( + "leading zero not allowed when indexing arrays"); + case err_code::element_not_object_or_array: + throw_exception<TypeError>("object/array", objType); + case err_code::json_pointer_out_of_bounds: + return nullptr; + case err_code::other: + default: return nullptr; - } - // special case of parsing "/": lookup key with empty name - if (token.empty()) { - if (dyn->isObject()) { - dyn = dyn->get_ptr(""); - continue; - } - throw_exception<TypeError>("object", dyn->type()); - } - if (auto* parray = dyn->get_nothrow<dynamic::Array>()) { - if (token.size() > 1 && token.at(0) == '0') { - throw std::invalid_argument( - "Leading zero not allowed when indexing arrays"); - } - // special case, always return non-existent - if (token.size() == 1 && token.at(0) == '-') { - dyn = nullptr; - continue; - } - auto const idx = folly::to<size_t>(token); - dyn = idx < parray->size() ? &(*parray)[idx] : nullptr; - continue; - } - if (auto* pobject = dyn->get_nothrow<dynamic::ObjectImpl>()) { - auto const it = pobject->find(token); - dyn = it != pobject->end() ? &it->second : nullptr; - continue; - } - throw_exception<TypeError>("object/array", dyn->type()); } - return dyn; + assume_unreachable(); } ////////////////////////////////////////////////////////////////////// diff --git a/ios/Pods/Folly/folly/dynamic.h b/ios/Pods/Folly/folly/dynamic.h index ae0f11666..bbca41099 100644 --- a/ios/Pods/Folly/folly/dynamic.h +++ b/ios/Pods/Folly/folly/dynamic.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -62,6 +62,7 @@ #include <boost/operators.hpp> +#include <folly/Expected.h> #include <folly/Range.h> #include <folly/Traits.h> #include <folly/container/F14Map.h> @@ -370,6 +371,10 @@ struct dynamic : private boost::operators<dynamic> { std::is_convertible<K, dynamic>::value, T>; + template <typename K, typename T> + using IfNotIterator = + std::enable_if_t<!std::is_convertible<K, iterator>::value, T>; + public: /* * You can iterate over the keys, values, or items (std::pair of key and @@ -429,9 +434,70 @@ struct dynamic : private boost::operators<dynamic> { dynamic&& at(StringPiece) &&; /* - * Locate element using JSON pointer, per RFC 6901. Returns nullptr if - * element could not be located. Throws if pointer does not match the - * shape of the document, e.g. uses string to index in array. + * Locate element using JSON pointer, per RFC 6901 + */ + + enum class json_pointer_resolution_error_code : uint8_t { + other = 0, + // key not found in object + key_not_found, + // array index out of bounds + index_out_of_bounds, + // special index "-" requesting append + append_requested, + // indexes in arrays must be numeric + index_not_numeric, + // indexes in arrays should not have leading zero + index_has_leading_zero, + // element not subscribable, i.e. neither object or array + element_not_object_or_array, + // hit document boundary, but pointer not exhausted yet + json_pointer_out_of_bounds, + }; + + template <typename Dynamic> + struct json_pointer_resolution_error { + // error code encountered while resolving JSON pointer + json_pointer_resolution_error_code error_code{}; + // index of the JSON pointer's token that caused the error + size_t index{0}; + // Last correctly resolved element in object. You can use it, + // for example, to add last element to the array + Dynamic* context{nullptr}; + }; + + template <typename Dynamic> + struct json_pointer_resolved_value { + // parent element of the value in dynamic, if exist + Dynamic* parent{nullptr}; + // pointer to the value itself + Dynamic* value{nullptr}; + // if parent isObject, this is the key in object to get value + StringPiece parent_key; + // if parent isArray, this is the index in array to get value + size_t parent_index{0}; + }; + + // clang-format off + template <typename Dynamic> + using resolved_json_pointer = Expected< + json_pointer_resolved_value<Dynamic>, + json_pointer_resolution_error<Dynamic>>; + + resolved_json_pointer<dynamic const> + try_get_ptr(json_pointer const&) const&; + resolved_json_pointer<dynamic> + try_get_ptr(json_pointer const&) &; + resolved_json_pointer<dynamic const> + try_get_ptr(json_pointer const&) const&& = delete; + resolved_json_pointer<dynamic const> + try_get_ptr(json_pointer const&) && = delete; + // clang-format on + + /* + * The following versions return nullptr if element could not be located. + * Throws if pointer does not match the shape of the document, e.g. uses + * string to index in array. */ const dynamic* get_ptr(json_pointer const&) const&; dynamic* get_ptr(json_pointer const&) &; @@ -553,7 +619,16 @@ struct dynamic : private boost::operators<dynamic> { * Invalidates iterators. */ template <class K, class V> - void insert(K&&, V&& val); + IfNotIterator<K, void> insert(K&&, V&& val); + + /* + * Inserts the supplied value into array, or throw if not array + * Shifts existing values in the array to the right + * + * Invalidates iterators. + */ + template <class T> + iterator insert(const_iterator pos, T&& value); /* * These functions merge two folly dynamic objects. @@ -635,6 +710,12 @@ struct dynamic : private boost::operators<dynamic> { */ void pop_back(); + /* + * Return reference to the last element in an array. If this is not + * an array, throws TypeError. + */ + const dynamic& back() const; + /* * Get a hash code. This function is called by a std::hash<> * specialization, also. @@ -704,9 +785,7 @@ struct dynamic : private boost::operators<dynamic> { * incomplete type right now). (Note that in contrast we know it * is ok to do this with fbvector because we own it.) */ - std::aligned_storage< - sizeof(F14NodeMap<int, int>), - alignof(F14NodeMap<int, int>)>::type objectBuffer; + aligned_storage_for_t<F14NodeMap<int, int>> objectBuffer; } u_; }; diff --git a/ios/Pods/Folly/folly/functional/ApplyTuple.h b/ios/Pods/Folly/folly/functional/ApplyTuple.h index a3224d181..f7901aeb6 100644 --- a/ios/Pods/Folly/folly/functional/ApplyTuple.h +++ b/ios/Pods/Folly/folly/functional/ApplyTuple.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -33,7 +33,7 @@ namespace folly { */ template <typename Tuple> using index_sequence_for_tuple = - make_index_sequence<std::tuple_size<Tuple>::value>; + std::make_index_sequence<std::tuple_size<Tuple>::value>; namespace detail { namespace apply_tuple { @@ -45,7 +45,8 @@ struct ApplyInvoke { using seq = index_sequence_for_tuple<std::remove_reference_t<T>>; template <typename F, typename T, std::size_t... I> - static constexpr auto invoke_(F&& f, T&& t, index_sequence<I...>) noexcept( + static constexpr auto + invoke_(F&& f, T&& t, std::index_sequence<I...>) noexcept( is_nothrow_invocable<F&&, decltype(get<I>(std::declval<T>()))...>::value) -> invoke_result_t<F&&, decltype(get<I>(std::declval<T>()))...> { return invoke(static_cast<F&&>(f), get<I>(static_cast<T&&>(t))...); @@ -57,7 +58,8 @@ template < std::size_t... Indices, typename ReturnTuple = std::tuple<decltype(get<Indices>(std::declval<Tuple>()))...>> -auto forward_tuple(Tuple&& tuple, index_sequence<Indices...>) -> ReturnTuple { +auto forward_tuple(Tuple&& tuple, std::index_sequence<Indices...>) + -> ReturnTuple { return ReturnTuple{get<Indices>(std::forward<Tuple>(tuple))...}; } } // namespace adl @@ -76,7 +78,13 @@ struct ApplyInvoke : private detail::apply_tuple::adl::ApplyInvoke { ////////////////////////////////////////////////////////////////////// -#if __cpp_lib_apply >= 201603 +// libc++ v3.9 has std::apply +// android ndk r15c libc++ claims to be v3.9 but is missing std::apply +#if __cpp_lib_apply >= 201603 || \ + (((__ANDROID__ && _LIBCPP_VERSION > 3900) || \ + (!__ANDROID__ && _LIBCPP_VERSION > 3800)) && \ + _LIBCPP_STD_VER > 14) || \ + (_MSC_VER && _HAS_CXX17) /* using override */ using std::apply; @@ -126,13 +134,25 @@ template <typename F, typename Tuple> using apply_result_t = invoke_result_t<ApplyInvoke, F, Tuple>; template <typename F, typename Tuple> struct is_applicable : is_invocable<ApplyInvoke, F, Tuple> {}; +template <typename F, typename Tuple> +FOLLY_INLINE_VARIABLE constexpr bool is_applicable_v = + is_applicable<F, Tuple>::value; template <typename R, typename F, typename Tuple> struct is_applicable_r : is_invocable_r<R, ApplyInvoke, F, Tuple> {}; +template <typename R, typename F, typename Tuple> +FOLLY_INLINE_VARIABLE constexpr bool is_applicable_r_v = + is_applicable_r<R, F, Tuple>::value; template <typename F, typename Tuple> struct is_nothrow_applicable : is_nothrow_invocable<ApplyInvoke, F, Tuple> {}; +template <typename F, typename Tuple> +FOLLY_INLINE_VARIABLE constexpr bool is_nothrow_applicable_v = + is_nothrow_applicable<F, Tuple>::value; template <typename R, typename F, typename Tuple> struct is_nothrow_applicable_r : is_nothrow_invocable_r<R, ApplyInvoke, F, Tuple> {}; +template <typename R, typename F, typename Tuple> +FOLLY_INLINE_VARIABLE constexpr bool is_nothrow_applicable_r_v = + is_nothrow_applicable_r<R, F, Tuple>::value; namespace detail { namespace apply_tuple { diff --git a/ios/Pods/Folly/folly/functional/Invoke.h b/ios/Pods/Folly/folly/functional/Invoke.h index a3dbe7369..beb887992 100644 --- a/ios/Pods/Folly/folly/functional/Invoke.h +++ b/ios/Pods/Folly/folly/functional/Invoke.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -19,6 +19,13 @@ #include <functional> #include <type_traits> +#include <boost/preprocessor/control/expr_iif.hpp> +#include <boost/preprocessor/facilities/is_empty_variadic.hpp> +#include <boost/preprocessor/list/for_each.hpp> +#include <boost/preprocessor/logical/not.hpp> +#include <boost/preprocessor/tuple/to_list.hpp> + +#include <folly/Portability.h> #include <folly/Preprocessor.h> #include <folly/Traits.h> @@ -28,9 +35,13 @@ * * std::invoke_result * * std::invoke_result_t * * std::is_invocable + * * std::is_invocable_v * * std::is_invocable_r + * * std::is_invocable_r_v * * std::is_nothrow_invocable + * * std::is_nothrow_invocable_v * * std::is_nothrow_invocable_r + * * std::is_nothrow_invocable_r_v */ #if __cpp_lib_invoke >= 201411 || _MSC_VER @@ -46,13 +57,13 @@ namespace folly { // mimic: std::invoke, C++17 template <typename F, typename... Args> -constexpr auto invoke(F&& f, Args&&... args) noexcept( +FOLLY_ERASE constexpr auto invoke(F&& f, Args&&... args) noexcept( noexcept(static_cast<F&&>(f)(static_cast<Args&&>(args)...))) -> decltype(static_cast<F&&>(f)(static_cast<Args&&>(args)...)) { return static_cast<F&&>(f)(static_cast<Args&&>(args)...); } template <typename M, typename C, typename... Args> -constexpr auto invoke(M(C::*d), Args&&... args) +FOLLY_ERASE constexpr auto invoke(M(C::*d), Args&&... args) -> decltype(std::mem_fn(d)(static_cast<Args&&>(args)...)) { return std::mem_fn(d)(static_cast<Args&&>(args)...); } @@ -71,8 +82,12 @@ namespace folly { /* using override */ using std::invoke_result_t; /* using override */ using std::is_invocable; /* using override */ using std::is_invocable_r; +/* using override */ using std::is_invocable_r_v; +/* using override */ using std::is_invocable_v; /* using override */ using std::is_nothrow_invocable; /* using override */ using std::is_nothrow_invocable_r; +/* using override */ using std::is_nothrow_invocable_r_v; +/* using override */ using std::is_nothrow_invocable_v; } // namespace folly @@ -145,91 +160,152 @@ using invoke_result_t = typename invoke_result<F, Args...>::type; template <typename F, typename... Args> struct is_invocable : invoke_detail::is_invocable<void, F, Args...> {}; +// mimic: std::is_invocable_v, C++17 +template <typename F, typename... Args> +FOLLY_INLINE_VARIABLE constexpr bool is_invocable_v = + is_invocable<F, Args...>::value; + // mimic: std::is_invocable_r, C++17 template <typename R, typename F, typename... Args> struct is_invocable_r : invoke_detail::is_invocable_r<void, R, F, Args...> {}; +// mimic: std::is_invocable_r_v, C++17 +template <typename R, typename F, typename... Args> +FOLLY_INLINE_VARIABLE constexpr bool is_invocable_r_v = + is_invocable_r<R, F, Args...>::value; + // mimic: std::is_nothrow_invocable, C++17 template <typename F, typename... Args> struct is_nothrow_invocable : invoke_detail::is_nothrow_invocable<void, F, Args...> {}; +// mimic: std::is_nothrow_invocable_v, C++17 +template <typename F, typename... Args> +FOLLY_INLINE_VARIABLE constexpr bool is_nothrow_invocable_v = + is_nothrow_invocable<F, Args...>::value; + // mimic: std::is_nothrow_invocable_r, C++17 template <typename R, typename F, typename... Args> struct is_nothrow_invocable_r : invoke_detail::is_nothrow_invocable_r<void, R, F, Args...> {}; +// mimic: std::is_nothrow_invocable_r_v, C++17 +template <typename R, typename F, typename... Args> +FOLLY_INLINE_VARIABLE constexpr bool is_nothrow_invocable_r_v = + is_nothrow_invocable_r<R, F, Args...>::value; + } // namespace folly #endif namespace folly { + namespace detail { struct invoke_private_overload; +template <bool, typename Invoke> +struct invoke_traits_base_ {}; template <typename Invoke> -struct free_invoke_proxy { +struct invoke_traits_base_<false, Invoke> {}; +template <typename Invoke> +struct invoke_traits_base_<true, Invoke> { + FOLLY_INLINE_VARIABLE static constexpr Invoke invoke{}; +}; +template <typename Invoke> +using invoke_traits_base = + invoke_traits_base_<is_constexpr_default_constructible_v<Invoke>, Invoke>; + +} // namespace detail + +// invoke_traits +// +// A traits container struct with the following member types, type aliases, and +// variables: +// +// * invoke_result +// * invoke_result_t +// * is_invocable +// * is_invocable_v +// * is_invocable_r +// * is_invocable_r_v +// * is_nothrow_invocable +// * is_nothrow_invocable_v +// * is_nothrow_invocable_r +// * is_nothrow_invocable_r_v +// +// These members have behavior matching the behavior of C++17's corresponding +// invocation traits types, type aliases, and variables, but using invoke_type +// as the invocable argument passed to the usual nivocation traits. +// +// The traits container struct also has a member type alias: +// +// * invoke_type +// +// And an invocable variable as a default-constructed instance of invoke_type, +// if the latter is constexpr default-constructible: +// +// * invoke +template <typename Invoke> +struct invoke_traits : detail::invoke_traits_base<Invoke> { public: + using invoke_type = Invoke; + + // If invoke_type is constexpr default-constructible: + // + // inline static constexpr invoke_type invoke{}; + template <typename... Args> struct invoke_result : folly::invoke_result<Invoke, Args...> {}; template <typename... Args> using invoke_result_t = folly::invoke_result_t<Invoke, Args...>; template <typename... Args> struct is_invocable : folly::is_invocable<Invoke, Args...> {}; + template <typename... Args> + FOLLY_INLINE_VARIABLE static constexpr bool is_invocable_v = + is_invocable<Args...>::value; template <typename R, typename... Args> struct is_invocable_r : folly::is_invocable_r<R, Invoke, Args...> {}; + template <typename R, typename... Args> + FOLLY_INLINE_VARIABLE static constexpr bool is_invocable_r_v = + is_invocable_r<R, Args...>::value; template <typename... Args> struct is_nothrow_invocable : folly::is_nothrow_invocable<Invoke, Args...> {}; + template <typename... Args> + FOLLY_INLINE_VARIABLE static constexpr bool is_nothrow_invocable_v = + is_nothrow_invocable<Args...>::value; template <typename R, typename... Args> struct is_nothrow_invocable_r : folly::is_nothrow_invocable_r<R, Invoke, Args...> {}; - - template <typename... Args> - static constexpr auto invoke(Args&&... args) noexcept( - noexcept(Invoke{}(static_cast<Args&&>(args)...))) - -> decltype(Invoke{}(static_cast<Args&&>(args)...)) { - return Invoke{}(static_cast<Args&&>(args)...); - } - - using invoke_type = Invoke; + template <typename R, typename... Args> + FOLLY_INLINE_VARIABLE static constexpr bool is_nothrow_invocable_r_v = + is_nothrow_invocable_r<R, Args...>::value; }; -} // namespace detail } // namespace folly +#define FOLLY_DETAIL_CREATE_FREE_INVOKE_TRAITS_USING_1(_, funcname, ns) \ + using ns::funcname; + +#define FOLLY_DETAIL_CREATE_FREE_INVOKE_TRAITS_USING(_, funcname, ...) \ + BOOST_PP_EXPR_IIF( \ + BOOST_PP_NOT(BOOST_PP_IS_EMPTY(__VA_ARGS__)), \ + BOOST_PP_LIST_FOR_EACH( \ + FOLLY_DETAIL_CREATE_FREE_INVOKE_TRAITS_USING_1, \ + funcname, \ + BOOST_PP_TUPLE_TO_LIST((__VA_ARGS__)))) + /*** - * FOLLY_CREATE_FREE_INVOKE_TRAITS + * FOLLY_CREATE_FREE_INVOKER * - * Used to create traits container, bound to a specific free-invocable name, - * with the following member traits types and aliases: - * - * * invoke_result - * * invoke_result_t - * * is_invocable - * * is_invocable_r - * * is_nothrow_invocable - * * is_nothrow_invocable_r - * - * The container also has a static member function: - * - * * invoke - * - * And a member type alias: - * - * * invoke_type - * - * These members have behavior matching the behavior of C++17's corresponding - * invocation traits types, aliases, and functions, but substituting canonical - * invocation with member invocation. + * Used to create an invoker type bound to a specific free-invocable name. * * Example: * - * FOLLY_CREATE_FREE_INVOKE_TRAITS(foo_invoke_traits, foo); + * FOLLY_CREATE_FREE_INVOKER(foo_invoker, foo); * - * The traits container type `foo_invoke_traits` is generated in the current - * namespace and has the listed member types and aliases. They may be used as - * follows: + * The type `foo_invoker` is generated in the current namespace and may be used + * as follows: * * namespace Deep { * struct CanFoo {}; @@ -237,7 +313,7 @@ struct free_invoke_proxy { * int foo(CanFoo&&, Car&&) noexcept { return 2; } * } * - * using traits = foo_invoke_traits; + * using traits = folly::invoke_traits<foo_invoker>; * * traits::invoke(Deep::CanFoo{}, Car{}) // 2 * @@ -246,25 +322,25 @@ struct free_invoke_proxy { * traits::invoke_result<Deep::CanFoo, Bar&&> // empty * traits::invoke_result_t<Deep::CanFoo, Bar&&> // error * - * traits::is_invocable<CanFoo, Bar&>::value // true - * traits::is_invocable<CanFoo, Bar&&>::value // false + * traits::is_invocable_v<CanFoo, Bar&> // true + * traits::is_invocable_v<CanFoo, Bar&&> // false * - * traits::is_invocable_r<int, CanFoo, Bar&>::value // true - * traits::is_invocable_r<char*, CanFoo, Bar&>::value // false + * traits::is_invocable_r_v<int, CanFoo, Bar&> // true + * traits::is_invocable_r_v<char*, CanFoo, Bar&> // false * - * traits::is_nothrow_invocable<CanFoo, Bar&>::value // false - * traits::is_nothrow_invocable<CanFoo, Car&&>::value // true + * traits::is_nothrow_invocable_v<CanFoo, Bar&> // false + * traits::is_nothrow_invocable_v<CanFoo, Car&&> // true * - * traits::is_nothrow_invocable<int, CanFoo, Bar&>::value // false - * traits::is_nothrow_invocable<char*, CanFoo, Bar&>::value // false - * traits::is_nothrow_invocable<int, CanFoo, Car&&>::value // true - * traits::is_nothrow_invocable<char*, CanFoo, Car&&>::value // false + * traits::is_nothrow_invocable_v<int, CanFoo, Bar&> // false + * traits::is_nothrow_invocable_v<char*, CanFoo, Bar&> // false + * traits::is_nothrow_invocable_v<int, CanFoo, Car&&> // true + * traits::is_nothrow_invocable_v<char*, CanFoo, Car&&> // false * - * When a name has a primary definition in a fixed namespace and alternate - * definitions in the namespaces of its arguments, the primary definition may - * automatically be found as follows: + * When a name has one or more primary definition in a fixed set of namespaces + * and alternate definitions in the namespaces of its arguments, the primary + * definitions may automatically be found as follows: * - * FOLLY_CREATE_FREE_INVOKE_TRAITS(swap_invoke_traits, swap, std); + * FOLLY_CREATE_FREE_INVOKER(swap_invoker, swap, std); * * In this case, `swap_invoke_traits::invoke(int&, int&)` will use the primary * definition found in `namespace std` relative to the current namespace, which @@ -275,108 +351,46 @@ struct free_invoke_proxy { * void swap(HasData&, HasData&) { throw 7; } * } * - * using traits = swap_invoke_traits; + * using traits = invoke_traits<swap_invoker>; * * HasData a, b; * traits::invoke(a, b); // throw 7 */ -#define FOLLY_CREATE_FREE_INVOKE_TRAITS(classname, funcname, ...) \ - namespace classname##__folly_detail_invoke_ns { \ - namespace classname##__folly_detail_invoke_ns_inline { \ - FOLLY_PUSH_WARNING \ - FOLLY_CLANG_DISABLE_WARNING("-Wunused-function") \ - void funcname(::folly::detail::invoke_private_overload&); \ - FOLLY_POP_WARNING \ - } \ - using FB_ARG_2_OR_1( \ - classname##__folly_detail_invoke_ns_inline \ - FOLLY_PP_DETAIL_APPEND_VA_ARG(__VA_ARGS__))::funcname; \ - struct classname##__folly_detail_invoke { \ - template <typename... Args> \ - constexpr auto operator()(Args&&... args) const \ - noexcept(noexcept(funcname(static_cast<Args&&>(args)...))) \ - -> decltype(funcname(static_cast<Args&&>(args)...)) { \ - return funcname(static_cast<Args&&>(args)...); \ - } \ - }; \ - } \ - struct classname : ::folly::detail::free_invoke_proxy< \ - classname##__folly_detail_invoke_ns:: \ - classname##__folly_detail_invoke> {} - -namespace folly { -namespace detail { - -template <typename Invoke> -struct member_invoke_proxy { - public: - template <typename O, typename... Args> - struct invoke_result : folly::invoke_result<Invoke, O, Args...> {}; - template <typename O, typename... Args> - using invoke_result_t = folly::invoke_result_t<Invoke, O, Args...>; - template <typename O, typename... Args> - struct is_invocable : folly::is_invocable<Invoke, O, Args...> {}; - template <typename R, typename O, typename... Args> - struct is_invocable_r : folly::is_invocable_r<R, Invoke, O, Args...> {}; - template <typename O, typename... Args> - struct is_nothrow_invocable - : folly::is_nothrow_invocable<Invoke, O, Args...> {}; - template <typename R, typename O, typename... Args> - struct is_nothrow_invocable_r - : folly::is_nothrow_invocable_r<R, Invoke, O, Args...> {}; - - template <typename O, typename... Args> - static constexpr auto invoke(O&& o, Args&&... args) noexcept( - noexcept(Invoke{}(static_cast<O&&>(o), static_cast<Args&&>(args)...))) - -> decltype(Invoke{}(static_cast<O&&>(o), static_cast<Args&&>(args)...)) { - return Invoke{}(static_cast<O&&>(o), static_cast<Args&&>(args)...); - } - - using invoke_type = Invoke; -}; - -} // namespace detail -} // namespace folly +#define FOLLY_CREATE_FREE_INVOKER(classname, funcname, ...) \ + namespace classname##__folly_detail_invoke_ns { \ + FOLLY_MAYBE_UNUSED void funcname( \ + ::folly::detail::invoke_private_overload&); \ + FOLLY_DETAIL_CREATE_FREE_INVOKE_TRAITS_USING(_, funcname, __VA_ARGS__) \ + struct __folly_detail_invoke_obj { \ + template <typename... Args> \ + FOLLY_ERASE_HACK_GCC constexpr auto operator()(Args&&... args) const \ + noexcept(noexcept(funcname(static_cast<Args&&>(args)...))) \ + -> decltype(funcname(static_cast<Args&&>(args)...)) { \ + return funcname(static_cast<Args&&>(args)...); \ + } \ + }; \ + } \ + struct classname \ + : classname##__folly_detail_invoke_ns::__folly_detail_invoke_obj {} /*** - * FOLLY_CREATE_MEMBER_INVOKE_TRAITS + * FOLLY_CREATE_MEMBER_INVOKER * - * Used to create traits container, bound to a specific member-invocable name, - * with the following member traits types and aliases: - * - * * invoke_result - * * invoke_result_t - * * is_invocable - * * is_invocable_r - * * is_nothrow_invocable - * * is_nothrow_invocable_r - * - * The container also has a static member function: - * - * * invoke - * - * And a member type alias: - * - * * invoke_type - * - * These members have behavior matching the behavior of C++17's corresponding - * invocation traits types, aliases, and functions, but substituting canonical - * invocation with member invocation. + * Used to create an invoker type bound to a specific member-invocable name. * * Example: * - * FOLLY_CREATE_MEMBER_INVOKE_TRAITS(foo_invoke_traits, foo); + * FOLLY_CREATE_MEMBER_INVOKER(foo_invoker, foo); * - * The traits container type `foo_invoke_traits` is generated in the current - * namespace and has the listed member types and aliases. They may be used as - * follows: + * The type `foo_invoker` is generated in the current namespace and may be used + * as follows: * * struct CanFoo { * int foo(Bar&) { return 1; } * int foo(Car&&) noexcept { return 2; } * }; * - * using traits = foo_invoke_traits; + * using traits = folly::invoke_traits<foo_invoker>; * * traits::invoke(CanFoo{}, Car{}) // 2 * @@ -385,29 +399,80 @@ struct member_invoke_proxy { * traits::invoke_result<CanFoo, Bar&&> // empty * traits::invoke_result_t<CanFoo, Bar&&> // error * - * traits::is_invocable<CanFoo, Bar&>::value // true - * traits::is_invocable<CanFoo, Bar&&>::value // false + * traits::is_invocable_v<CanFoo, Bar&> // true + * traits::is_invocable_v<CanFoo, Bar&&> // false * - * traits::is_invocable_r<int, CanFoo, Bar&>::value // true - * traits::is_invocable_r<char*, CanFoo, Bar&>::value // false + * traits::is_invocable_r_v<int, CanFoo, Bar&> // true + * traits::is_invocable_r_v<char*, CanFoo, Bar&> // false * - * traits::is_nothrow_invocable<CanFoo, Bar&>::value // false - * traits::is_nothrow_invocable<CanFoo, Car&&>::value // true + * traits::is_nothrow_invocable_v<CanFoo, Bar&> // false + * traits::is_nothrow_invocable_v<CanFoo, Car&&> // true * - * traits::is_nothrow_invocable<int, CanFoo, Bar&>::value // false - * traits::is_nothrow_invocable<char*, CanFoo, Bar&>::value // false - * traits::is_nothrow_invocable<int, CanFoo, Car&&>::value // true - * traits::is_nothrow_invocable<char*, CanFoo, Car&&>::value // false + * traits::is_nothrow_invocable_v<int, CanFoo, Bar&> // false + * traits::is_nothrow_invocable_v<char*, CanFoo, Bar&> // false + * traits::is_nothrow_invocable_v<int, CanFoo, Car&&> // true + * traits::is_nothrow_invocable_v<char*, CanFoo, Car&&> // false */ -#define FOLLY_CREATE_MEMBER_INVOKE_TRAITS(classname, membername) \ - struct classname##__folly_detail_member_invoke { \ - template <typename O, typename... Args> \ - constexpr auto operator()(O&& o, Args&&... args) const noexcept(noexcept( \ - static_cast<O&&>(o).membername(static_cast<Args&&>(args)...))) \ - -> decltype( \ - static_cast<O&&>(o).membername(static_cast<Args&&>(args)...)) { \ - return static_cast<O&&>(o).membername(static_cast<Args&&>(args)...); \ - } \ - }; \ - struct classname : ::folly::detail::member_invoke_proxy< \ - classname##__folly_detail_member_invoke> {} +#define FOLLY_CREATE_MEMBER_INVOKER(classname, membername) \ + struct classname { \ + template <typename O, typename... Args> \ + FOLLY_ERASE_HACK_GCC constexpr auto operator()(O&& o, Args&&... args) \ + const noexcept(noexcept( \ + static_cast<O&&>(o).membername(static_cast<Args&&>(args)...))) \ + -> decltype(static_cast<O&&>(o).membername( \ + static_cast<Args&&>(args)...)) { \ + return static_cast<O&&>(o).membername(static_cast<Args&&>(args)...); \ + } \ + } + +/*** + * FOLLY_CREATE_STATIC_MEMBER_INVOKER + * + * Used to create an invoker type template bound to a specific static-member- + * invocable name. + * + * Example: + * + * FOLLY_CREATE_STATIC_MEMBER_INVOKER(foo_invoker, foo); + * + * The type template `foo_invoker` is generated in the current namespace and + * may be used as follows: + * + * struct CanFoo { + * static int foo(Bar&) { return 1; } + * static int foo(Car&&) noexcept { return 2; } + * }; + * + * using traits = folly::invoke_traits<foo_invoker<CanFoo>>; + * + * traits::invoke(Car{}) // 2 + * + * traits::invoke_result<Bar&> // has member + * traits::invoke_result_t<Bar&> // int + * traits::invoke_result<Bar&&> // empty + * traits::invoke_result_t<Bar&&> // error + * + * traits::is_invocable_v<Bar&> // true + * traits::is_invocable_v<Bar&&> // false + * + * traits::is_invocable_r_v<int, Bar&> // true + * traits::is_invocable_r_v<char*, Bar&> // false + * + * traits::is_nothrow_invocable_v<Bar&> // false + * traits::is_nothrow_invocable_v<Car&&> // true + * + * traits::is_nothrow_invocable_v<int, Bar&> // false + * traits::is_nothrow_invocable_v<char*, Bar&> // false + * traits::is_nothrow_invocable_v<int, Car&&> // true + * traits::is_nothrow_invocable_v<char*, Car&&> // false + */ +#define FOLLY_CREATE_STATIC_MEMBER_INVOKER(classname, membername) \ + template <typename T> \ + struct classname { \ + template <typename... Args> \ + FOLLY_ERASE constexpr auto operator()(Args&&... args) const \ + noexcept(noexcept(T::membername(static_cast<Args&&>(args)...))) \ + -> decltype(T::membername(static_cast<Args&&>(args)...)) { \ + return T::membername(static_cast<Args&&>(args)...); \ + } \ + } diff --git a/ios/Pods/Folly/folly/functional/Partial.h b/ios/Pods/Folly/folly/functional/Partial.h index 720dce163..aedde87ea 100644 --- a/ios/Pods/Folly/folly/functional/Partial.h +++ b/ios/Pods/Folly/folly/functional/Partial.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -33,10 +33,11 @@ struct PartialConstructFromCallable {}; template <typename F, typename Tuple> class Partial { - using Indexes = make_index_sequence<std::tuple_size<Tuple>{}>; + using Indexes = std::make_index_sequence<std::tuple_size<Tuple>{}>; template <typename Self, std::size_t... I, typename... Args> - static auto invokeForward(Self&& self, index_sequence<I...>, Args&&... args) + static auto + invokeForward(Self&& self, std::index_sequence<I...>, Args&&... args) -> decltype(invoke( std::declval<Self>().f_, std::get<I>(std::declval<Self>().stored_args_)..., diff --git a/ios/Pods/Folly/folly/hash/Checksum.h b/ios/Pods/Folly/folly/hash/Checksum.h index 29790e87b..c0f96b9af 100644 --- a/ios/Pods/Folly/folly/hash/Checksum.h +++ b/ios/Pods/Folly/folly/hash/Checksum.h @@ -1,11 +1,11 @@ /* - * Copyright 2013-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/hash/FarmHash.h b/ios/Pods/Folly/folly/hash/FarmHash.h new file mode 100644 index 000000000..7f733dc99 --- /dev/null +++ b/ios/Pods/Folly/folly/hash/FarmHash.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <folly/external/farmhash/farmhash.h> + +namespace folly { +namespace hash { +namespace farmhash { + +// The values returned by Hash, Hash32, and Hash64 are only guaranteed to +// be the same within the same process. Fingerpring32 and Fingerprint64 +// are fixed algorithms that always give the same result. + +// std::size_t Hash(char const*, std::size_t) +using external::farmhash::Hash; + +// uint32_t Hash32(char const*, std::size_t) +using external::farmhash::Hash32; + +// uint64_t Hash64(char const*, std::size_t) +using external::farmhash::Hash64; + +// uint32_t Fingerprint32(char const*, std::size_t) +using external::farmhash::Fingerprint32; + +// uint64_t Fingerprint64(char const*, std::size_t) +using external::farmhash::Fingerprint64; + +} // namespace farmhash +} // namespace hash +} // namespace folly diff --git a/ios/Pods/Folly/folly/hash/Hash.h b/ios/Pods/Folly/folly/hash/Hash.h index 3177e9c43..a8a50e8e8 100644 --- a/ios/Pods/Folly/folly/hash/Hash.h +++ b/ios/Pods/Folly/folly/hash/Hash.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -19,11 +19,13 @@ #include <cstdint> #include <cstring> #include <limits> +#include <memory> #include <string> #include <tuple> #include <type_traits> #include <utility> +#include <folly/CPortability.h> #include <folly/Traits.h> #include <folly/Utility.h> #include <folly/functional/ApplyTuple.h> @@ -38,7 +40,22 @@ namespace folly { namespace hash { -uint64_t hash_128_to_64(const uint64_t upper, const uint64_t lower) noexcept; +// This is the Hash128to64 function from Google's cityhash (available +// under the MIT License). We use it to reduce multiple 64 bit hashes +// into a single hash. +FOLLY_DISABLE_UNDEFINED_BEHAVIOR_SANITIZER("unsigned-integer-overflow") +inline uint64_t hash_128_to_64( + const uint64_t upper, + const uint64_t lower) noexcept { + // Murmur-inspired hashing. + const uint64_t kMul = 0x9ddfea08eb382d69ULL; + uint64_t a = (lower ^ upper) * kMul; + a ^= (a >> 47); + uint64_t b = (upper ^ a) * kMul; + b ^= (b >> 47); + b *= kMul; + return b; +} ////////////////////////////////////////////////////////////////////// @@ -46,6 +63,7 @@ uint64_t hash_128_to_64(const uint64_t upper, const uint64_t lower) noexcept; * Thomas Wang 64 bit mix hash function */ +FOLLY_DISABLE_UNDEFINED_BEHAVIOR_SANITIZER("unsigned-integer-overflow") inline uint64_t twang_mix64(uint64_t key) noexcept { key = (~key) + (key << 21); // key *= (1 << 21) - 1; key -= 1; key = key ^ (key >> 24); @@ -367,6 +385,10 @@ struct Hash { size_t operator()(const T& t, const Ts&... ts) const { return hash::hash_128_to_64((*this)(t), (*this)(ts...)); } + + size_t operator()() const noexcept { + return 0; + } }; // IsAvalanchingHasher<H, K> extends std::integral_constant<bool, V>. @@ -506,7 +528,7 @@ struct IsAvalanchingHasher<hasher<std::string>, K> : std::true_type {}; template <typename T> struct hasher<T, std::enable_if_t<std::is_enum<T>::value>> { size_t operator()(T key) const noexcept { - return Hash()(static_cast<std::underlying_type_t<T>>(key)); + return Hash()(to_underlying(key)); } }; @@ -531,6 +553,33 @@ struct hasher<std::tuple<Ts...>> { } }; +template <typename T> +struct hasher<T*> { + using folly_is_avalanching = hasher<std::uintptr_t>::folly_is_avalanching; + + size_t operator()(T* key) const { + return Hash()(bit_cast<std::uintptr_t>(key)); + } +}; + +template <typename T> +struct hasher<std::unique_ptr<T>> { + using folly_is_avalanching = typename hasher<T*>::folly_is_avalanching; + + size_t operator()(const std::unique_ptr<T>& key) const { + return Hash()(key.get()); + } +}; + +template <typename T> +struct hasher<std::shared_ptr<T>> { + using folly_is_avalanching = typename hasher<T*>::folly_is_avalanching; + + size_t operator()(const std::shared_ptr<T>& key) const { + return Hash()(key.get()); + } +}; + // combiner for multi-arg tuple also mixes bits template <typename T, typename K> struct IsAvalanchingHasher<hasher<std::tuple<T>>, K> @@ -564,22 +613,6 @@ class StdHasher { // commutative_hash_combine_* hashes values but combines them in an // order-independent way to yield a new hash. -// This is the Hash128to64 function from Google's cityhash (available -// under the MIT License). We use it to reduce multiple 64 bit hashes -// into a single hash. -inline uint64_t hash_128_to_64( - const uint64_t upper, - const uint64_t lower) noexcept { - // Murmur-inspired hashing. - const uint64_t kMul = 0x9ddfea08eb382d69ULL; - uint64_t a = (lower ^ upper) * kMul; - a ^= (a >> 47); - uint64_t b = (upper ^ a) * kMul; - b ^= (b >> 47); - b *= kMul; - return b; -} - template <class Hash, class Value> uint64_t commutative_hash_combine_value_generic( uint64_t seed, diff --git a/ios/Pods/Folly/folly/hash/SpookyHashV1.h b/ios/Pods/Folly/folly/hash/SpookyHashV1.h index 184e077ec..fe052cc75 100644 --- a/ios/Pods/Folly/folly/hash/SpookyHashV1.h +++ b/ios/Pods/Folly/folly/hash/SpookyHashV1.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/hash/SpookyHashV2.cpp b/ios/Pods/Folly/folly/hash/SpookyHashV2.cpp index 8603d5038..05322c71a 100644 --- a/ios/Pods/Folly/folly/hash/SpookyHashV2.cpp +++ b/ios/Pods/Folly/folly/hash/SpookyHashV2.cpp @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/hash/SpookyHashV2.h b/ios/Pods/Folly/folly/hash/SpookyHashV2.h index f4431a6ef..8e9be8c5b 100644 --- a/ios/Pods/Folly/folly/hash/SpookyHashV2.h +++ b/ios/Pods/Folly/folly/hash/SpookyHashV2.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/json.cpp b/ios/Pods/Folly/folly/json.cpp index 2334a9c62..c3d0375ee 100644 --- a/ios/Pods/Folly/folly/json.cpp +++ b/ios/Pods/Folly/folly/json.cpp @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include <folly/json.h> #include <algorithm> @@ -21,6 +22,7 @@ #include <type_traits> #include <boost/algorithm/string.hpp> +#include <glog/logging.h> #include <folly/Conv.h> #include <folly/Portability.h> @@ -35,8 +37,21 @@ namespace folly { ////////////////////////////////////////////////////////////////////// namespace json { + namespace { +parse_error make_parse_error( + unsigned int line, + std::string const& context, + std::string const& expected) { + return parse_error(to<std::string>( + "json parse error on line ", + line, + !context.empty() ? to<std::string>(" near `", context, '\'') : "", + ": ", + expected)); +} + struct Printer { explicit Printer( std::string& out, @@ -49,7 +64,7 @@ struct Printer { case dynamic::DOUBLE: if (!opts_.allow_nan_inf && (std::isnan(v.asDouble()) || std::isinf(v.asDouble()))) { - throw std::runtime_error( + throw json::parse_error( "folly::toJson: JSON object value was a " "NaN or INF"); } @@ -89,7 +104,7 @@ struct Printer { private: void printKV(const std::pair<const dynamic, dynamic>& p) const { if (!opts_.allow_non_string_keys && !p.first.isString()) { - throw std::runtime_error( + throw json::parse_error( "folly::toJson: JSON object key was not a " "string"); } @@ -119,16 +134,18 @@ struct Printer { newline(); if (opts_.sort_keys || opts_.sort_keys_by) { using ref = std::reference_wrapper<decltype(o.items())::value_type const>; + auto sort_keys_by = [&](auto begin, auto end, const auto& comp) { + std::sort(begin, end, [&](ref a, ref b) { + // Only compare keys. No ordering among identical keys. + return comp(a.get().first, b.get().first); + }); + }; std::vector<ref> refs(o.items().begin(), o.items().end()); - - using SortByRef = FunctionRef<bool(dynamic const&, dynamic const&)>; - auto const& sort_keys_by = opts_.sort_keys_by - ? SortByRef(opts_.sort_keys_by) - : SortByRef(std::less<dynamic>()); - std::sort(refs.begin(), refs.end(), [&](ref a, ref b) { - // Only compare keys. No ordering among identical keys. - return sort_keys_by(a.get().first, b.get().first); - }); + if (opts_.sort_keys_by) { + sort_keys_by(refs.begin(), refs.end(), opts_.sort_keys_by); + } else { + sort_keys_by(refs.begin(), refs.end(), std::less<>()); + } printKVPairs(refs.cbegin(), refs.cend()); } else { printKVPairs(o.items().begin(), o.items().end()); @@ -189,19 +206,6 @@ struct Printer { ////////////////////////////////////////////////////////////////////// -struct FOLLY_EXPORT ParseError : std::runtime_error { - explicit ParseError( - unsigned int line, - std::string const& context, - std::string const& expected) - : std::runtime_error(to<std::string>( - "json parse error on line ", - line, - !context.empty() ? to<std::string>(" near `", context, '\'') : "", - ": ", - expected)) {} -}; - // Wraps our input buffer with some helper functions. struct Input { explicit Input(StringPiece range, json::serialization_opts const* opts) @@ -216,6 +220,10 @@ struct Input { return range_.begin(); } + unsigned getLineNum() const { + return lineNum_; + } + // Parse ahead for as long as the supplied predicate is satisfied, // returning a range of what was skipped. template <class Predicate> @@ -249,13 +257,31 @@ struct Input { } void skipWhitespace() { - range_ = folly::skipWhitespace(range_); + unsigned index = 0; + while (true) { + while (index < range_.size() && range_[index] == ' ') { + index++; + } + if (index < range_.size()) { + if (range_[index] == '\n') { + index++; + ++lineNum_; + continue; + } + if (range_[index] == '\t' || range_[index] == '\r') { + index++; + continue; + } + } + break; + } + range_.advance(index); storeCurrent(); } void expect(char c) { if (**this != c) { - throw ParseError( + throw json::make_parse_error( lineNum_, context(), to<std::string>("expected '", c, '\'')); } ++*this; @@ -297,7 +323,7 @@ struct Input { } dynamic error(char const* what) const { - throw ParseError(lineNum_, context(), what); + throw json::make_parse_error(lineNum_, context(), what); } json::serialization_opts const& getOpts() { @@ -342,11 +368,36 @@ class RecursionGuard { Input& in_; }; -dynamic parseValue(Input& in); +dynamic parseValue(Input& in, json::metadata_map* map); std::string parseString(Input& in); dynamic parseNumber(Input& in); -dynamic parseObject(Input& in) { +template <class K> +void parseObjectKeyValue( + Input& in, + dynamic& ret, + K&& key, + json::metadata_map* map) { + auto keyLineNumber = in.getLineNum(); + in.skipWhitespace(); + in.expect(':'); + in.skipWhitespace(); + K tmp; + if (map) { + tmp = K(key); + } + auto valueLineNumber = in.getLineNum(); + ret.insert(std::forward<K>(key), parseValue(in, map)); + if (map) { + auto val = ret.get_ptr(tmp); + // We just inserted it, so it should be there! + DCHECK(val != nullptr); + map->emplace( + val, json::parse_metadata{{{keyLineNumber}}, {{valueLineNumber}}}); + } +} + +dynamic parseObject(Input& in, json::metadata_map* map) { DCHECK_EQ(*in, '{'); ++in; @@ -364,18 +415,12 @@ dynamic parseObject(Input& in) { } if (*in == '\"') { // string auto key = parseString(in); - in.skipWhitespace(); - in.expect(':'); - in.skipWhitespace(); - ret.insert(std::move(key), parseValue(in)); + parseObjectKeyValue(in, ret, std::move(key), map); } else if (!in.getOpts().allow_non_string_keys) { in.error("expected string for object key name"); } else { - auto key = parseValue(in); - in.skipWhitespace(); - in.expect(':'); - in.skipWhitespace(); - ret.insert(std::move(key), parseValue(in)); + auto key = parseValue(in, map); + parseObjectKeyValue(in, ret, std::move(key), map); } in.skipWhitespace(); @@ -390,7 +435,7 @@ dynamic parseObject(Input& in) { return ret; } -dynamic parseArray(Input& in) { +dynamic parseArray(Input& in, json::metadata_map* map) { DCHECK_EQ(*in, '['); ++in; @@ -402,11 +447,15 @@ dynamic parseArray(Input& in) { return ret; } + std::vector<uint32_t> lineNumbers; for (;;) { if (in.getOpts().allow_trailing_comma && *in == ']') { break; } - ret.push_back(parseValue(in)); + ret.push_back(parseValue(in, map)); + if (map) { + lineNumbers.push_back(in.getLineNum()); + } in.skipWhitespace(); if (*in != ',') { break; @@ -414,6 +463,11 @@ dynamic parseArray(Input& in) { ++in; in.skipWhitespace(); } + if (map) { + for (size_t i = 0; i < ret.size(); i++) { + map->emplace(&ret[i], json::parse_metadata{{{0}}, {{lineNumbers[i]}}}); + } + } in.expect(']'); return ret; @@ -492,7 +546,7 @@ std::string decodeUnicodeEscape(Input& in) { in.error("expected 4 hex digits"); } - uint16_t ret = uint16_t(hexVal(*in) * 4096); + auto ret = uint16_t(hexVal(*in) * 4096); ++in; ret += hexVal(*in) * 256; ++in; @@ -581,14 +635,14 @@ std::string parseString(Input& in) { return ret; } -dynamic parseValue(Input& in) { +dynamic parseValue(Input& in, json::metadata_map* map) { RecursionGuard guard(in); in.skipWhitespace(); // clang-format off return - *in == '[' ? parseArray(in) : - *in == '{' ? parseObject(in) : + *in == '[' ? parseArray(in, map) : + *in == '{' ? parseObject(in, map) : *in == '\"' ? parseString(in) : (*in == '-' || (*in >= '0' && *in <= '9')) ? parseNumber(in) : in.consume("true") ? true : @@ -666,7 +720,7 @@ size_t firstEscapableInWord(T s, const serialization_opts& opts) { (i == 0 ? uint64_t(-1) << 32 : ~0UL); while (bitmap) { auto bit = folly::findFirstSet(bitmap); - needsEscape |= isChar(offset + bit - 1); + needsEscape |= isChar(static_cast<uint8_t>(offset + bit - 1)); bitmap &= bitmap - 1; } } @@ -747,7 +801,7 @@ void escapeStringImpl( // checking that utf8 encodings are valid char32_t v = utf8ToCodePoint(q, e, opts.skip_invalid_utf8); if (opts.skip_invalid_utf8 && v == U'\ufffd') { - out.append(u8"\ufffd"); + out.append(reinterpret_cast<const char*>(u8"\ufffd")); p = q; continue; } @@ -897,6 +951,29 @@ std::string stripComments(StringPiece jsonC) { ////////////////////////////////////////////////////////////////////// +dynamic parseJsonWithMetadata(StringPiece range, json::metadata_map* map) { + return parseJsonWithMetadata(range, json::serialization_opts(), map); +} + +dynamic parseJsonWithMetadata( + StringPiece range, + json::serialization_opts const& opts, + json::metadata_map* map) { + json::Input in(range, &opts); + + uint32_t n = in.getLineNum(); + auto ret = parseValue(in, map); + if (map) { + map->emplace(&ret, json::parse_metadata{{{0}}, {{n}}}); + } + + in.skipWhitespace(); + if (in.size() && *in != '\0') { + in.error("parsing didn't consume all input"); + } + return ret; +} + dynamic parseJson(StringPiece range) { return parseJson(range, json::serialization_opts()); } @@ -904,7 +981,7 @@ dynamic parseJson(StringPiece range) { dynamic parseJson(StringPiece range, json::serialization_opts const& opts) { json::Input in(range, &opts); - auto ret = parseValue(in); + auto ret = parseValue(in, nullptr); in.skipWhitespace(); if (in.size() && *in != '\0') { in.error("parsing didn't consume all input"); @@ -919,6 +996,7 @@ std::string toJson(dynamic const& dyn) { std::string toPrettyJson(dynamic const& dyn) { json::serialization_opts opts; opts.pretty_formatting = true; + opts.sort_keys = true; return json::serialize(dyn, opts); } diff --git a/ios/Pods/Folly/folly/json.h b/ios/Pods/Folly/folly/json.h index 2a34a05f2..264552cea 100644 --- a/ios/Pods/Folly/folly/json.h +++ b/ios/Pods/Folly/folly/json.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -166,6 +166,28 @@ void escapeString( */ std::string stripComments(StringPiece jsonC); +class FOLLY_EXPORT parse_error : public std::runtime_error { + public: + using std::runtime_error::runtime_error; +}; + +// may be extened in future to include offset, col, etc. +struct parse_location { + uint32_t line{}; // 0-indexed +}; + +// may be extended in future to include end location +struct parse_range { + parse_location begin; +}; + +struct parse_metadata { + parse_range key_range; + parse_range value_range; +}; + +using metadata_map = std::unordered_map<dynamic const*, parse_metadata>; + } // namespace json ////////////////////////////////////////////////////////////////////// @@ -177,6 +199,12 @@ std::string stripComments(StringPiece jsonC); dynamic parseJson(StringPiece, json::serialization_opts const&); dynamic parseJson(StringPiece); +dynamic parseJsonWithMetadata(StringPiece range, json::metadata_map* map); +dynamic parseJsonWithMetadata( + StringPiece range, + json::serialization_opts const& opts, + json::metadata_map* map); + /* * Serialize a dynamic into a json string. */ diff --git a/ios/Pods/Folly/folly/json_patch.h b/ios/Pods/Folly/folly/json_patch.h index 34d3cb562..655423809 100644 --- a/ios/Pods/Folly/folly/json_patch.h +++ b/ios/Pods/Folly/folly/json_patch.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -97,6 +97,28 @@ class json_patch { std::vector<patch_operation> const& ops() const; + enum class patch_application_error_code : uint8_t { + other, + // "from" pointer did not resolve + from_not_found, + // "path" pointer did not resolve + path_not_found, + // "test" condition failed + test_failed, + }; + + struct patch_application_error { + patch_application_error_code error_code{}; + // index of the patch element (in array) that caused error + size_t index{}; + }; + + /* + * Mutate supplied object in accordance with patch operations. Leaves + * object in partially modified state if one of the operations fails. + */ + Expected<Unit, patch_application_error> apply(folly::dynamic& obj); + private: std::vector<patch_operation> ops_; }; diff --git a/ios/Pods/Folly/folly/json_pointer.cpp b/ios/Pods/Folly/folly/json_pointer.cpp index 5809bb202..312ab48fb 100644 --- a/ios/Pods/Folly/folly/json_pointer.cpp +++ b/ios/Pods/Folly/folly/json_pointer.cpp @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/json_pointer.h b/ios/Pods/Folly/folly/json_pointer.h index 82e4ab4af..ad7061360 100644 --- a/ios/Pods/Folly/folly/json_pointer.h +++ b/ios/Pods/Folly/folly/json_pointer.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/lang/Align.h b/ios/Pods/Folly/folly/lang/Align.h index f750b8fc2..3f6004ae6 100644 --- a/ios/Pods/Folly/folly/lang/Align.h +++ b/ios/Pods/Folly/folly/lang/Align.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -17,25 +17,40 @@ #pragma once #include <cstddef> +#include <cstdint> #include <folly/Portability.h> namespace folly { +// has_extended_alignment +// +// True if it may be presumed that the platform has static extended alignment; +// false if it may not be so presumed, even when the platform might actually +// have it. Static extended alignment refers to extended alignment of objects +// with automatic, static, or thread storage. Whether the there is support for +// dynamic extended alignment is a property of the allocator which is used for +// each given dynamic allocation. +// +// Currently, very heuristical - only non-mobile 64-bit linux gets the extended +// alignment treatment. Theoretically, this could be tuned better. +constexpr bool has_extended_alignment = + kIsLinux && sizeof(void*) >= sizeof(std::uint64_t); + namespace detail { // Implemented this way because of a bug in Clang for ARMv7, which gives the // wrong result for `alignof` a `union` with a field of each scalar type. -constexpr size_t max_align_(std::size_t a) { - return a; -} -template <typename... Es> -constexpr std::size_t max_align_(std::size_t a, std::size_t e, Es... es) { - return !(a < e) ? a : max_align_(e, es...); -} template <typename... Ts> struct max_align_t_ { - static constexpr std::size_t value = max_align_(0u, alignof(Ts)...); + static constexpr std::size_t value() { + std::size_t const values[] = {0u, alignof(Ts)...}; + std::size_t r = 0u; + for (auto const v : values) { + r = r < v ? v : r; + } + return r; + } }; using max_align_v_ = max_align_t_< long double, @@ -87,7 +102,7 @@ using max_align_v_ = max_align_t_< // crashes on 32-bit iOS apps that use `double`. // // Apple's allocation reference: http://bit.ly/malloc-small -constexpr std::size_t max_align_v = detail::max_align_v_::value; +constexpr std::size_t max_align_v = detail::max_align_v_::value(); struct alignas(max_align_v) max_align_t {}; // Memory locations within the same cache line are subject to destructive @@ -118,4 +133,12 @@ static_assert(hardware_destructive_interference_size >= max_align_v, "math?"); constexpr std::size_t hardware_constructive_interference_size = 64; static_assert(hardware_constructive_interference_size >= max_align_v, "math?"); +// A value corresponding to hardware_constructive_interference_size but which +// may be used with alignas, since hardware_constructive_interference_size may +// be too large on some platforms to be used with alignas. +constexpr std::size_t cacheline_align_v = has_extended_alignment + ? hardware_constructive_interference_size + : max_align_v; +struct alignas(cacheline_align_v) cacheline_align_t {}; + } // namespace folly diff --git a/ios/Pods/Folly/folly/lang/Aligned.h b/ios/Pods/Folly/folly/lang/Aligned.h new file mode 100644 index 000000000..5d079f0a3 --- /dev/null +++ b/ios/Pods/Folly/folly/lang/Aligned.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <cstddef> +#include <type_traits> +#include <utility> + +#include <folly/Utility.h> +#include <folly/lang/Align.h> + +namespace folly { + +template <typename T, std::size_t Align> +class aligned { + static_assert(!(Align & (Align - 1)), "alignment not a power of two"); + static_assert(alignof(T) <= Align, "alignment too small"); + + public: + using alignment = index_constant<Align>; + using value_type = T; + + aligned() = default; + aligned(aligned const&) = default; + aligned(aligned&&) = default; + template < + typename S = T, + std::enable_if_t<std::is_copy_constructible<S>::value, int> = 0> + aligned(T const& value) noexcept(std::is_nothrow_copy_constructible<T>::value) + : value_(value) {} + template < + typename S = T, + std::enable_if_t<std::is_move_constructible<S>::value, int> = 0> + aligned(T&& value) noexcept(std::is_nothrow_move_constructible<T>::value) + : value_(static_cast<T&&>(value)) {} + template < + typename... A, + std::enable_if_t<std::is_constructible<T, A...>::value, int> = 0> + explicit aligned(in_place_t, A&&... a) noexcept( + std::is_nothrow_constructible<T, A...>::value) + : value_(static_cast<A&&>(a)...) {} + + aligned& operator=(aligned const&) = default; + aligned& operator=(aligned&&) = default; + template < + typename S = T, + std::enable_if_t<std::is_copy_assignable<S>::value, int> = 0> + aligned& operator=(T const& value) noexcept( + std::is_nothrow_copy_assignable<T>::value) { + value_ = value; + return *this; + } + template < + typename S = T, + std::enable_if_t<std::is_move_assignable<S>::value, int> = 0> + aligned& operator=(T&& value) noexcept( + std::is_nothrow_move_assignable<T>::value) { + value_ = std::move(value); + return *this; + } + + T* get() noexcept { + return &value_; + } + T const* get() const noexcept { + return &value_; + } + T* operator->() noexcept { + return &value_; + } + T const* operator->() const noexcept { + return &value_; + } + T& operator*() noexcept { + return value_; + } + T const& operator*() const noexcept { + return value_; + } + + private: + alignas(Align) T value_; +}; + +template <typename T> +using cacheline_aligned = aligned< + T, + (cacheline_align_v < alignof(T) ? alignof(T) : cacheline_align_v)>; + +} // namespace folly diff --git a/ios/Pods/Folly/folly/lang/Assume.cpp b/ios/Pods/Folly/folly/lang/Assume.cpp index b2126ec5c..07de169d4 100644 --- a/ios/Pods/Folly/folly/lang/Assume.cpp +++ b/ios/Pods/Folly/folly/lang/Assume.cpp @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/lang/Assume.h b/ios/Pods/Folly/folly/lang/Assume.h index c2a4b447e..69033a15a 100644 --- a/ios/Pods/Folly/folly/lang/Assume.h +++ b/ios/Pods/Folly/folly/lang/Assume.h @@ -1,11 +1,11 @@ /* - * Copyright 2015-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/lang/Bits.h b/ios/Pods/Folly/folly/lang/Bits.h index 779705ff1..f0beb5baf 100644 --- a/ios/Pods/Folly/folly/lang/Bits.h +++ b/ios/Pods/Folly/folly/lang/Bits.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -26,6 +26,10 @@ * 1-based. 0 = no bits are set (x == 0) * for x != 0, findLastSet(x) == 1 + floor(log2(x)) * + * extractFirstSet(x) [constexpr] + * extract first (least significant) bit set in a value of an integral + * type, 0 = no bits are set (x == 0) + * * nextPowTwo(x) [constexpr] * Finds the next power of two >= x. * @@ -55,12 +59,35 @@ #include <folly/ConstexprMath.h> #include <folly/Portability.h> +#include <folly/Traits.h> #include <folly/Utility.h> #include <folly/lang/Assume.h> #include <folly/portability/Builtins.h> namespace folly { +#if __cpp_lib_bit_cast + +using std::bit_cast; + +#else + +// mimic: std::bit_cast, C++20 +template < + typename To, + typename From, + std::enable_if_t< + sizeof(From) == sizeof(To) && is_trivially_copyable<To>::value && + is_trivially_copyable<From>::value, + int> = 0> +To bit_cast(const From& src) noexcept { + aligned_storage_for_t<To> storage; + std::memcpy(&storage, &src, sizeof(From)); + return reinterpret_cast<To&>(storage); +} + +#endif + namespace detail { template <typename Dst, typename Src> constexpr std::make_signed_t<Dst> bits_to_signed(Src const s) { @@ -123,6 +150,18 @@ inline constexpr unsigned int findLastSet(T const v) { // clang-format on } +/// extractFirstSet +/// +/// Return a value where all the bits but the least significant are cleared. +template <typename T> +inline constexpr T extractFirstSet(T const v) { + static_assert(std::is_integral<T>::value, "non-integral type"); + static_assert(std::is_unsigned<T>::value, "signed type"); + static_assert(!std::is_same<T, bool>::value, "bool type"); + + return v & -v; +} + /// popcount /// /// Returns the number of bits which are set. @@ -202,15 +241,11 @@ struct EndianInt { std::is_floating_point<T>::value, "template type parameter must be non-bool integral or floating point"); static T swap(T x) { - // we implement this with memcpy because that is defined behavior in C++ - // we rely on compilers to optimize away the memcpy calls + // we implement this with bit_cast because that is defined behavior in C++ + // we rely on compilers to optimize away the bit_cast calls constexpr auto s = sizeof(T); using B = typename uint_types_by_size<s>::type; - B b; - std::memcpy(&b, &x, s); - b = byteswap_gen(b); - std::memcpy(&x, &b, s); - return x; + return bit_cast<T>(byteswap_gen(bit_cast<B>(x))); } static T big(T x) { return kIsLittleEndian ? EndianInt::swap(x) : x; diff --git a/ios/Pods/Folly/folly/lang/CString.cpp b/ios/Pods/Folly/folly/lang/CString.cpp new file mode 100644 index 000000000..ed78deeae --- /dev/null +++ b/ios/Pods/Folly/folly/lang/CString.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <folly/lang/CString.h> + +#include <algorithm> + +namespace folly { + +std::size_t +strlcpy(char* const dest, char const* const src, std::size_t const size) { + std::size_t const len = std::strlen(src); + if (size != 0) { + std::size_t const n = std::min(len, size - 1); // always null terminate! + std::memcpy(dest, src, n); + dest[n] = '\0'; + } + return len; +} + +} // namespace folly diff --git a/ios/Pods/Folly/folly/lang/CString.h b/ios/Pods/Folly/folly/lang/CString.h new file mode 100644 index 000000000..ced6aaead --- /dev/null +++ b/ios/Pods/Folly/folly/lang/CString.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <cstddef> +#include <cstring> + +namespace folly { + +// strlcpy +// +// mimic: strlcpy, libbsd +std::size_t strlcpy(char* dest, char const* src, std::size_t size); + +} // namespace folly diff --git a/ios/Pods/Folly/folly/lang/Cast.h b/ios/Pods/Folly/folly/lang/Cast.h new file mode 100644 index 000000000..709f17ef1 --- /dev/null +++ b/ios/Pods/Folly/folly/lang/Cast.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <memory> +#include <type_traits> + +#include <folly/Portability.h> +#include <folly/Traits.h> +#include <folly/lang/SafeAssert.h> + +namespace folly { + +// down_cast +// +// Unchecked polymorphic down-cast using static_cast. Only works for pairs of +// types where the cvref-unqualified source type is polymorphic and a base of +// the target type. The target type, which is passed as an explicit template +// param, must be cvref-unqualified. The return type is the target type with +// the same cvref-qualifiers or cvptr-qualifiers as the source type. +// +// Checked with an assertion in debug builds. +template <typename T, typename S> +FOLLY_ERASE like_t<S, T>* down_cast(S* ptr) noexcept { + using Q = std::remove_cv_t<S>; + static_assert(std::is_polymorphic<Q>::value, "not polymorphic"); + static_assert(std::is_base_of<Q, T>::value, "not down-castable"); + using R = like_t<S, T>; + FOLLY_SAFE_DCHECK(dynamic_cast<R*>(ptr), "not a runtime down-cast"); + return static_cast<R*>(ptr); +} +template <typename T, typename S> +FOLLY_ERASE like_t<S&&, T> down_cast(S&& ref) noexcept { + return static_cast<like_t<S&&, T>>(*down_cast<T>(std::addressof(ref))); +} + +} // namespace folly diff --git a/ios/Pods/Folly/folly/lang/CheckedMath.h b/ios/Pods/Folly/folly/lang/CheckedMath.h new file mode 100644 index 000000000..e474a3382 --- /dev/null +++ b/ios/Pods/Folly/folly/lang/CheckedMath.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <cassert> +#include <limits> +#include <type_traits> + +#include <folly/Likely.h> + +namespace folly { +template <typename T, typename = std::enable_if_t<std::is_unsigned<T>::value>> +bool checked_add(T* result, T a, T b) { + assert(result != nullptr); + if (FOLLY_LIKELY(a < std::numeric_limits<T>::max() - b)) { + *result = a + b; + return true; + } else { + *result = {}; + return false; + } +} +} // namespace folly diff --git a/ios/Pods/Folly/folly/lang/ColdClass.h b/ios/Pods/Folly/folly/lang/ColdClass.h deleted file mode 100644 index 3b21ef6c0..000000000 --- a/ios/Pods/Folly/folly/lang/ColdClass.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2017-present Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* Tag any class as `cold` by inheriting from folly::cold::ColdClass - * - * Intended use: things like folly::Unexpected which are designed to only be - * instantiated on error paths. - */ -#pragma once - -#include <folly/CppAttributes.h> - -namespace folly { -// ColdClass should be in its own namespace: inheriting from any class adds its -// innermost namespace to the namespaces inspected during -// argument-dependent-lookoup. We want people to be able to derive from this -// without implicitly picking up the folly namespace for ADL on their classes. -namespace cold_detail { -struct ColdClass { - FOLLY_COLD ColdClass() noexcept; -}; -} // namespace cold_detail - -/* using override */ using cold_detail::ColdClass; -} // namespace folly diff --git a/ios/Pods/Folly/folly/lang/CustomizationPoint.h b/ios/Pods/Folly/folly/lang/CustomizationPoint.h new file mode 100644 index 000000000..79ce3f560 --- /dev/null +++ b/ios/Pods/Folly/folly/lang/CustomizationPoint.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <folly/Portability.h> +#include <folly/lang/StaticConst.h> + +// FOLLY_DEFINE_CPO +// +// Helper for portably defining customization-point objects (CPOs). +// +// The customization-point object must be placed in a nested namespace to avoid +// potential conflicts with customizations defined as friend-functions of types +// defined in the same namespace as the CPO. +// +// In C++17 and later the object may be defined using 'inline constexpr' to +// avoid ODR issues. However, prior to that a helper template is required to +// ensure that there is only a single instance of the CPO created and then a +// named reference in an anonymous namespace is required to avoid duplicate +// symbol definitions. +#if FOLLY_HAS_INLINE_VARIABLES +#define FOLLY_DEFINE_CPO(Type, Name) \ + namespace folly_cpo__ { \ + inline constexpr Type Name{}; \ + } \ + using namespace folly_cpo__; +#else +#define FOLLY_DEFINE_CPO(Type, Name) \ + namespace { \ + constexpr auto& Name = ::folly::StaticConst<Type>::value; \ + } +#endif diff --git a/ios/Pods/Folly/folly/lang/Exception.h b/ios/Pods/Folly/folly/lang/Exception.h index b57ee8fec..e1cdfd067 100644 --- a/ios/Pods/Folly/folly/lang/Exception.h +++ b/ios/Pods/Folly/folly/lang/Exception.h @@ -1,11 +1,11 @@ /* - * Copyright 2018-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -17,6 +17,8 @@ #pragma once #include <exception> +#include <type_traits> +#include <utility> #include <folly/CPortability.h> #include <folly/CppAttributes.h> @@ -49,11 +51,11 @@ template <typename Ex> // clang-format off namespace detail { template <typename T> -FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN T&& to_exception_arg_(T&& t) { +FOLLY_ERASE T&& to_exception_arg_(T&& t) { return static_cast<T&&>(t); } template <std::size_t N> -FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN char const* to_exception_arg_( +FOLLY_ERASE char const* to_exception_arg_( char const (&array)[N]) { return static_cast<char const*>(array); } @@ -76,8 +78,7 @@ template <typename Ex, typename... Args> /// /// Converts any arguments of type `char const[N]` to `char const*`. template <typename Ex, typename... Args> -[[noreturn]] FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN void -throw_exception(Args&&... args) { +[[noreturn]] FOLLY_ERASE void throw_exception(Args&&... args) { detail::throw_exception_<Ex>( detail::to_exception_arg_(static_cast<Args&&>(args))...); } @@ -87,13 +88,38 @@ throw_exception(Args&&... args) { /// Terminates as if by forwarding to throw_exception but in a noexcept context. // clang-format off template <typename Ex, typename... Args> -[[noreturn]] FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN void +[[noreturn]] FOLLY_ERASE void terminate_with(Args&&... args) noexcept { detail::terminate_with_<Ex>( detail::to_exception_arg_(static_cast<Args&&>(args))...); } // clang-format on +/// invoke_cold +/// +/// Invoke the provided function with the provided arguments. +/// +/// Usage note: +/// Passing extra values as arguments rather than capturing them allows smaller +/// inlined native at the call-site. +/// +/// Example: +/// +/// if (i < 0) { +/// invoke_cold( +/// [](int j) { +/// std::string ret = doStepA(); +/// doStepB(ret); +/// doStepC(ret); +/// }, +/// i); +/// } +template <typename F, typename... A> +FOLLY_NOINLINE FOLLY_COLD auto invoke_cold(F&& f, A&&... a) + -> decltype(static_cast<F&&>(f)(static_cast<A&&>(a)...)) { + return static_cast<F&&>(f)(static_cast<A&&>(a)...); +} + /// invoke_noreturn_cold /// /// Invoke the provided function with the provided arguments. If the invocation @@ -107,7 +133,7 @@ terminate_with(Args&&... args) noexcept { /// /// Usage note: /// Passing extra values as arguments rather than capturing them allows smaller -/// bytecode at the call-site. +/// inlined native code at the call-site. /// /// Example: /// @@ -126,4 +152,89 @@ template <typename F, typename... A> std::terminate(); } +/// catch_exception +/// +/// Invokes t; if exceptions are enabled (if not compiled with -fno-exceptions), +/// catches a thrown exception e of type E and invokes c, forwarding e and any +/// trailing arguments. +/// +/// Usage note: +/// As a general rule, pass Ex const& rather than unqualified Ex as the explicit +/// template argument E. The catch statement catches E without qualifiers so +/// if E is Ex then that translates to catch (Ex), but if E is Ex const& then +/// that translates to catch (Ex const&). +/// +/// Usage note: +/// Passing extra values as arguments rather than capturing them allows smaller +/// inlined native code at the call-site. +/// +/// Example: +/// +/// int input = // ... +/// int def = 45; +/// auto result = catch_exception<std::runtime_error const&>( +/// [=] { +/// if (input < 0) throw std::runtime_error("foo"); +/// return input; +/// }, +/// [](auto&& e, int num) { return num; }, +/// def); +/// assert(result == input < 0 ? def : input); +template <typename E, typename Try, typename Catch, typename... CatchA> +FOLLY_ERASE_TRYCATCH auto catch_exception(Try&& t, Catch&& c, CatchA&&... a) -> + typename std::common_type< + decltype(static_cast<Try&&>(t)()), + decltype(static_cast<Catch&&>( + c)(std::declval<E>(), static_cast<CatchA&&>(a)...))>::type { +#if FOLLY_HAS_EXCEPTIONS + try { + return static_cast<Try&&>(t)(); + } catch (E e) { + return invoke_cold(static_cast<Catch&&>(c), e, static_cast<CatchA&&>(a)...); + } +#else + [](auto&&...) {}(c, a...); // ignore + return static_cast<Try&&>(t)(); +#endif +} + +/// catch_exception +/// +/// Invokes t; if exceptions are enabled (if not compiled with -fno-exceptions), +/// catches a thrown exception of any type and invokes c, forwarding any +/// trailing arguments. +// +/// Usage note: +/// Passing extra values as arguments rather than capturing them allows smaller +/// inlined native code at the call-site. +/// +/// Example: +/// +/// int input = // ... +/// int def = 45; +/// auto result = catch_exception( +/// [=] { +/// if (input < 0) throw 11; +/// return input; +/// }, +/// [](int num) { return num; }, +/// def); +/// assert(result == input < 0 ? def : input); +template <typename Try, typename Catch, typename... CatchA> +FOLLY_ERASE_TRYCATCH auto catch_exception(Try&& t, Catch&& c, CatchA&&... a) -> + typename std::common_type< + decltype(static_cast<Try&&>(t)()), + decltype(static_cast<Catch&&>(c)(static_cast<CatchA&&>(a)...))>::type { +#if FOLLY_HAS_EXCEPTIONS + try { + return static_cast<Try&&>(t)(); + } catch (...) { + return invoke_cold(static_cast<Catch&&>(c), static_cast<CatchA&&>(a)...); + } +#else + [](auto&&...) {}(c, a...); // ignore + return static_cast<Try&&>(t)(); +#endif +} + } // namespace folly diff --git a/ios/Pods/Folly/folly/lang/Launder.h b/ios/Pods/Folly/folly/lang/Launder.h index a2081fb5f..738305669 100644 --- a/ios/Pods/Folly/folly/lang/Launder.h +++ b/ios/Pods/Folly/folly/lang/Launder.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -28,7 +28,8 @@ // Note: libc++ 6+ adds std::launder but does not define __cpp_lib_launder #if __cpp_lib_launder >= 201606 || (_MSC_VER && _HAS_LAUNDER) || \ - (_LIBCPP_VERSION >= 6000 && __cplusplus >= 201703L) + ((_LIBCPP_VERSION >= (__ANDROID__ ? 7000 : 6000)) && \ + __cplusplus >= 201703L) namespace folly { diff --git a/ios/Pods/Folly/folly/lang/Ordering.h b/ios/Pods/Folly/folly/lang/Ordering.h index dbc9bb4de..f21a0e2fb 100644 --- a/ios/Pods/Folly/folly/lang/Ordering.h +++ b/ios/Pods/Folly/folly/lang/Ordering.h @@ -1,11 +1,11 @@ /* - * Copyright 2018-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/lang/Pretty.h b/ios/Pods/Folly/folly/lang/Pretty.h new file mode 100644 index 000000000..35ca3d5b0 --- /dev/null +++ b/ios/Pods/Folly/folly/lang/Pretty.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <cstddef> +#include <type_traits> + +#include <folly/Portability.h> + +namespace folly { + +namespace detail { + +template <std::size_t S> +struct pretty_carray { + char data[S]; +}; + +template <std::size_t S> +static constexpr pretty_carray<S> pretty_carray_from(char const (&in)[S]) { + pretty_carray<S> out{}; + for (std::size_t i = 0; i < S; ++i) { + out.data[i] = in[i]; + } + return out; +} + +struct pretty_info { + std::size_t b; + std::size_t e; +}; + +template <typename To, std::size_t S> +static constexpr To pretty_info_to(pretty_info info, char const (&name)[S]) { + return To(name + info.b, info.e - info.b); +} + +template <std::size_t S> +static constexpr std::size_t pretty_lfind( + char const (&haystack)[S], + char const needle) { + for (std::size_t i = 0; i < S - 1; ++i) { + if (haystack[i] == needle) { + return i; + } + } + return ~std::size_t(0); +} + +template <std::size_t S> +static constexpr std::size_t pretty_rfind( + char const (&haystack)[S], + char const needle) { + for (std::size_t i = S; i != 0; --i) { + if (haystack[i - 1] == needle) { + return i - 1; + } + } + return ~std::size_t(0); +} + +struct pretty_tag_msc {}; +struct pretty_tag_gcc {}; + +using pretty_default_tag = std::conditional_t< // + kMscVer && !kIsClang, + pretty_tag_msc, + pretty_tag_gcc>; + +template <typename T> +static constexpr auto pretty_raw(pretty_tag_msc) { +#if defined(_MSC_VER) + return pretty_carray_from(__FUNCSIG__); +#endif +} + +template <typename T> +static constexpr auto pretty_raw(pretty_tag_gcc) { +#if defined(__GNUC__) || defined(__clang__) + return pretty_carray_from(__PRETTY_FUNCTION__); +#endif +} + +template <std::size_t S> +static constexpr pretty_info pretty_parse( + pretty_tag_msc, + char const (&name)[S]) { + // void __cdecl folly::detail::pretty_raw<{...}>( + // folly::detail::pretty_tag_msc) + auto const la = pretty_lfind(name, '<'); + auto const rp = pretty_rfind(name, '>'); + return pretty_info{la + 1, rp}; +} + +template <std::size_t S> +static constexpr pretty_info pretty_parse( + pretty_tag_gcc, + char const (&name)[S]) { + // void folly::detail::pretty_raw( + // folly::detail::pretty_tag_gcc) [T = {...}] + auto const eq = pretty_lfind(name, '='); + auto const br = pretty_rfind(name, ']'); + return pretty_info{eq + 2, br}; +} + +template <typename T, typename Tag> +struct pretty_name_zarray { + static constexpr auto raw_() { + constexpr auto const raw_ = pretty_raw<T>(Tag{}); + return raw_; + } + static constexpr auto raw = raw_(); // indirection b/c of gcc-5.3 ice, gh#1105 + static constexpr auto info = pretty_parse(Tag{}, raw.data); + static constexpr auto size = info.e - info.b; + static constexpr auto zarray_() { + pretty_carray<size + 1> data{}; + for (std::size_t i = 0; i < size; ++i) { + data.data[i] = raw.data[info.b + i]; + } + data.data[size] = 0; + return data; + } + static constexpr pretty_carray<size + 1> zarray = zarray_(); +}; + +template <typename T, typename Tag> +constexpr pretty_carray<pretty_name_zarray<T, Tag>::size + 1> + pretty_name_zarray<T, Tag>::zarray; + +} // namespace detail + +// pretty_name +// +// Returns a statically-allocated C string containing the pretty name of T. +// +// The pretty name of a type varies by compiler, may include tokens which +// would not be present in the type name as it is spelled in the source code +// or as it would be symbolized, and may not include tokens which would be +// present in the type name as it would be symbolized. +template <typename T> +constexpr char const* pretty_name() { + return detail::pretty_name_zarray<T, detail::pretty_default_tag>::zarray.data; +} + +} // namespace folly diff --git a/ios/Pods/Folly/folly/lang/PropagateConst.h b/ios/Pods/Folly/folly/lang/PropagateConst.h index 71d88cbf6..a284df9ad 100644 --- a/ios/Pods/Folly/folly/lang/PropagateConst.h +++ b/ios/Pods/Folly/folly/lang/PropagateConst.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -39,12 +39,10 @@ constexpr Pointer const& get_underlying(propagate_const<Pointer> const& obj) { } namespace detail { -template <typename> -struct is_propagate_const : std::false_type {}; -template <typename Pointer> -struct is_propagate_const<propagate_const<Pointer>> : std::true_type {}; +template <class Pointer> +using is_propagate_const = is_instantiation_of<propagate_const, Pointer>; template <typename T> -using is_decay_propagate_const = is_propagate_const<_t<std::decay<T>>>; +using is_decay_propagate_const = is_propagate_const<std::decay_t<T>>; namespace propagate_const_adl { using std::swap; @@ -61,80 +59,79 @@ template <typename Pointer> class propagate_const { public: using element_type = - _t<std::remove_reference<decltype(*std::declval<Pointer&>())>>; + std::remove_reference_t<decltype(*std::declval<Pointer&>())>; constexpr propagate_const() = default; - FOLLY_CPP14_CONSTEXPR propagate_const(propagate_const&&) = default; + constexpr propagate_const(propagate_const&&) = default; propagate_const(propagate_const const&) = delete; template < typename OtherPointer, - _t<std::enable_if< + std::enable_if_t< std::is_constructible<Pointer, OtherPointer&&>::value && !std::is_convertible<OtherPointer&&, Pointer>::value, - int>> = 0> + int> = 0> constexpr explicit propagate_const(propagate_const<OtherPointer>&& other) : pointer_(static_cast<OtherPointer&&>(other.pointer_)) {} template < typename OtherPointer, - _t<std::enable_if< + std::enable_if_t< std::is_constructible<Pointer, OtherPointer&&>::value && std::is_convertible<OtherPointer&&, Pointer>::value, - int>> = 0> + int> = 0> constexpr propagate_const(propagate_const<OtherPointer>&& other) : pointer_(static_cast<OtherPointer&&>(other.pointer_)) {} template < typename OtherPointer, - _t<std::enable_if< + std::enable_if_t< !detail::is_decay_propagate_const<OtherPointer>::value && std::is_constructible<Pointer, OtherPointer&&>::value && !std::is_convertible<OtherPointer&&, Pointer>::value, - int>> = 0> + int> = 0> constexpr explicit propagate_const(OtherPointer&& other) : pointer_(static_cast<OtherPointer&&>(other)) {} template < typename OtherPointer, - _t<std::enable_if< + std::enable_if_t< !detail::is_decay_propagate_const<OtherPointer>::value && std::is_constructible<Pointer, OtherPointer&&>::value && std::is_convertible<OtherPointer&&, Pointer>::value, - int>> = 0> + int> = 0> constexpr propagate_const(OtherPointer&& other) : pointer_(static_cast<OtherPointer&&>(other)) {} - FOLLY_CPP14_CONSTEXPR propagate_const& operator=(propagate_const&&) = default; + constexpr propagate_const& operator=(propagate_const&&) = default; propagate_const& operator=(propagate_const const&) = delete; template < typename OtherPointer, - typename = _t< - std::enable_if<std::is_convertible<OtherPointer&&, Pointer>::value>>> - FOLLY_CPP14_CONSTEXPR propagate_const& operator=( - propagate_const<OtherPointer>&& other) { + typename = + std::enable_if_t<std::is_convertible<OtherPointer&&, Pointer>::value>> + constexpr propagate_const& operator=(propagate_const<OtherPointer>&& other) { pointer_ = static_cast<OtherPointer&&>(other.pointer_); } template < typename OtherPointer, - typename = _t<std::enable_if< + typename = std::enable_if_t< !detail::is_decay_propagate_const<OtherPointer>::value && - std::is_convertible<OtherPointer&&, Pointer>::value>>> - FOLLY_CPP14_CONSTEXPR propagate_const& operator=(OtherPointer&& other) { + std::is_convertible<OtherPointer&&, Pointer>::value>> + constexpr propagate_const& operator=(OtherPointer&& other) { pointer_ = static_cast<OtherPointer&&>(other); return *this; } - FOLLY_CPP14_CONSTEXPR void swap(propagate_const& other) noexcept( + constexpr void swap(propagate_const& other) noexcept( noexcept(detail::propagate_const_adl::adl_swap( std::declval<Pointer&>(), other.pointer_))) { detail::propagate_const_adl::adl_swap(pointer_, other.pointer_); } - FOLLY_CPP14_CONSTEXPR element_type* get() { + constexpr element_type* get() { return get_(pointer_); } @@ -146,7 +143,7 @@ class propagate_const { return static_cast<bool>(pointer_); } - FOLLY_CPP14_CONSTEXPR element_type& operator*() { + constexpr element_type& operator*() { return *get(); } @@ -154,7 +151,7 @@ class propagate_const { return *get(); } - FOLLY_CPP14_CONSTEXPR element_type* operator->() { + constexpr element_type* operator->() { return get(); } @@ -164,18 +161,18 @@ class propagate_const { template < typename OtherPointer = Pointer, - typename = _t<std::enable_if< + typename = std::enable_if_t< std::is_pointer<OtherPointer>::value || - std::is_convertible<OtherPointer, element_type*>::value>>> - FOLLY_CPP14_CONSTEXPR operator element_type*() { + std::is_convertible<OtherPointer, element_type*>::value>> + constexpr operator element_type*() { return get(); } template < typename OtherPointer = Pointer, - typename = _t<std::enable_if< + typename = std::enable_if_t< std::is_pointer<OtherPointer>::value || - std::is_convertible<OtherPointer, element_type const*>::value>>> + std::is_convertible<OtherPointer, element_type const*>::value>> constexpr operator element_type const*() const { return get(); } @@ -199,7 +196,7 @@ class propagate_const { }; template <typename Pointer> -FOLLY_CPP14_CONSTEXPR void swap( +constexpr void swap( propagate_const<Pointer>& a, propagate_const<Pointer>& b) noexcept(noexcept(a.swap(b))) { a.swap(b); diff --git a/ios/Pods/Folly/folly/lang/RValueReferenceWrapper.h b/ios/Pods/Folly/folly/lang/RValueReferenceWrapper.h index 2b66e4246..33fbb9b98 100644 --- a/ios/Pods/Folly/folly/lang/RValueReferenceWrapper.h +++ b/ios/Pods/Folly/folly/lang/RValueReferenceWrapper.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/lang/SafeAssert.cpp b/ios/Pods/Folly/folly/lang/SafeAssert.cpp new file mode 100644 index 000000000..edc1f50ce --- /dev/null +++ b/ios/Pods/Folly/folly/lang/SafeAssert.cpp @@ -0,0 +1,492 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <folly/lang/SafeAssert.h> + +#include <algorithm> + +#include <folly/Conv.h> +#include <folly/FileUtil.h> + +namespace folly { +namespace detail { + +namespace { + +// script (centos): +// +// for e in $( +// cat /usr/include/asm*/errno*.h | awk '{print $2}' | grep -P '^E' | sort +// ) ; do +// echo "#if defined($e)" +// echo " FOLLY_DETAIL_ERROR($e)," +// echo "#endif" +// done + +#define FOLLY_DETAIL_ERROR(name) \ + { name, #name } +constexpr std::pair<int, const char*> errors[] = { +#if defined(E2BIG) + FOLLY_DETAIL_ERROR(E2BIG), +#endif +#if defined(EACCES) + FOLLY_DETAIL_ERROR(EACCES), +#endif +#if defined(EADDRINUSE) + FOLLY_DETAIL_ERROR(EADDRINUSE), +#endif +#if defined(EADDRNOTAVAIL) + FOLLY_DETAIL_ERROR(EADDRNOTAVAIL), +#endif +#if defined(EADV) + FOLLY_DETAIL_ERROR(EADV), +#endif +#if defined(EAFNOSUPPORT) + FOLLY_DETAIL_ERROR(EAFNOSUPPORT), +#endif +#if defined(EAGAIN) + FOLLY_DETAIL_ERROR(EAGAIN), +#endif +#if defined(EALREADY) + FOLLY_DETAIL_ERROR(EALREADY), +#endif +#if defined(EBADE) + FOLLY_DETAIL_ERROR(EBADE), +#endif +#if defined(EBADF) + FOLLY_DETAIL_ERROR(EBADF), +#endif +#if defined(EBADFD) + FOLLY_DETAIL_ERROR(EBADFD), +#endif +#if defined(EBADMSG) + FOLLY_DETAIL_ERROR(EBADMSG), +#endif +#if defined(EBADR) + FOLLY_DETAIL_ERROR(EBADR), +#endif +#if defined(EBADRQC) + FOLLY_DETAIL_ERROR(EBADRQC), +#endif +#if defined(EBADSLT) + FOLLY_DETAIL_ERROR(EBADSLT), +#endif +#if defined(EBFONT) + FOLLY_DETAIL_ERROR(EBFONT), +#endif +#if defined(EBUSY) + FOLLY_DETAIL_ERROR(EBUSY), +#endif +#if defined(ECANCELED) + FOLLY_DETAIL_ERROR(ECANCELED), +#endif +#if defined(ECHILD) + FOLLY_DETAIL_ERROR(ECHILD), +#endif +#if defined(ECHRNG) + FOLLY_DETAIL_ERROR(ECHRNG), +#endif +#if defined(ECOMM) + FOLLY_DETAIL_ERROR(ECOMM), +#endif +#if defined(ECONNABORTED) + FOLLY_DETAIL_ERROR(ECONNABORTED), +#endif +#if defined(ECONNREFUSED) + FOLLY_DETAIL_ERROR(ECONNREFUSED), +#endif +#if defined(ECONNRESET) + FOLLY_DETAIL_ERROR(ECONNRESET), +#endif +#if defined(EDEADLK) + FOLLY_DETAIL_ERROR(EDEADLK), +#endif +#if defined(EDEADLOCK) + FOLLY_DETAIL_ERROR(EDEADLOCK), +#endif +#if defined(EDESTADDRREQ) + FOLLY_DETAIL_ERROR(EDESTADDRREQ), +#endif +#if defined(EDOM) + FOLLY_DETAIL_ERROR(EDOM), +#endif +#if defined(EDOTDOT) + FOLLY_DETAIL_ERROR(EDOTDOT), +#endif +#if defined(EDQUOT) + FOLLY_DETAIL_ERROR(EDQUOT), +#endif +#if defined(EEXIST) + FOLLY_DETAIL_ERROR(EEXIST), +#endif +#if defined(EFAULT) + FOLLY_DETAIL_ERROR(EFAULT), +#endif +#if defined(EFBIG) + FOLLY_DETAIL_ERROR(EFBIG), +#endif +#if defined(EHOSTDOWN) + FOLLY_DETAIL_ERROR(EHOSTDOWN), +#endif +#if defined(EHOSTUNREACH) + FOLLY_DETAIL_ERROR(EHOSTUNREACH), +#endif +#if defined(EHWPOISON) + FOLLY_DETAIL_ERROR(EHWPOISON), +#endif +#if defined(EIDRM) + FOLLY_DETAIL_ERROR(EIDRM), +#endif +#if defined(EILSEQ) + FOLLY_DETAIL_ERROR(EILSEQ), +#endif +#if defined(EINPROGRESS) + FOLLY_DETAIL_ERROR(EINPROGRESS), +#endif +#if defined(EINTR) + FOLLY_DETAIL_ERROR(EINTR), +#endif +#if defined(EINVAL) + FOLLY_DETAIL_ERROR(EINVAL), +#endif +#if defined(EIO) + FOLLY_DETAIL_ERROR(EIO), +#endif +#if defined(EISCONN) + FOLLY_DETAIL_ERROR(EISCONN), +#endif +#if defined(EISDIR) + FOLLY_DETAIL_ERROR(EISDIR), +#endif +#if defined(EISNAM) + FOLLY_DETAIL_ERROR(EISNAM), +#endif +#if defined(EKEYEXPIRED) + FOLLY_DETAIL_ERROR(EKEYEXPIRED), +#endif +#if defined(EKEYREJECTED) + FOLLY_DETAIL_ERROR(EKEYREJECTED), +#endif +#if defined(EKEYREVOKED) + FOLLY_DETAIL_ERROR(EKEYREVOKED), +#endif +#if defined(EL2HLT) + FOLLY_DETAIL_ERROR(EL2HLT), +#endif +#if defined(EL2NSYNC) + FOLLY_DETAIL_ERROR(EL2NSYNC), +#endif +#if defined(EL3HLT) + FOLLY_DETAIL_ERROR(EL3HLT), +#endif +#if defined(EL3RST) + FOLLY_DETAIL_ERROR(EL3RST), +#endif +#if defined(ELIBACC) + FOLLY_DETAIL_ERROR(ELIBACC), +#endif +#if defined(ELIBBAD) + FOLLY_DETAIL_ERROR(ELIBBAD), +#endif +#if defined(ELIBEXEC) + FOLLY_DETAIL_ERROR(ELIBEXEC), +#endif +#if defined(ELIBMAX) + FOLLY_DETAIL_ERROR(ELIBMAX), +#endif +#if defined(ELIBSCN) + FOLLY_DETAIL_ERROR(ELIBSCN), +#endif +#if defined(ELNRNG) + FOLLY_DETAIL_ERROR(ELNRNG), +#endif +#if defined(ELOOP) + FOLLY_DETAIL_ERROR(ELOOP), +#endif +#if defined(EMEDIUMTYPE) + FOLLY_DETAIL_ERROR(EMEDIUMTYPE), +#endif +#if defined(EMFILE) + FOLLY_DETAIL_ERROR(EMFILE), +#endif +#if defined(EMLINK) + FOLLY_DETAIL_ERROR(EMLINK), +#endif +#if defined(EMSGSIZE) + FOLLY_DETAIL_ERROR(EMSGSIZE), +#endif +#if defined(EMULTIHOP) + FOLLY_DETAIL_ERROR(EMULTIHOP), +#endif +#if defined(ENAMETOOLONG) + FOLLY_DETAIL_ERROR(ENAMETOOLONG), +#endif +#if defined(ENAVAIL) + FOLLY_DETAIL_ERROR(ENAVAIL), +#endif +#if defined(ENETDOWN) + FOLLY_DETAIL_ERROR(ENETDOWN), +#endif +#if defined(ENETRESET) + FOLLY_DETAIL_ERROR(ENETRESET), +#endif +#if defined(ENETUNREACH) + FOLLY_DETAIL_ERROR(ENETUNREACH), +#endif +#if defined(ENFILE) + FOLLY_DETAIL_ERROR(ENFILE), +#endif +#if defined(ENOANO) + FOLLY_DETAIL_ERROR(ENOANO), +#endif +#if defined(ENOBUFS) + FOLLY_DETAIL_ERROR(ENOBUFS), +#endif +#if defined(ENOCSI) + FOLLY_DETAIL_ERROR(ENOCSI), +#endif +#if defined(ENODATA) + FOLLY_DETAIL_ERROR(ENODATA), +#endif +#if defined(ENODEV) + FOLLY_DETAIL_ERROR(ENODEV), +#endif +#if defined(ENOENT) + FOLLY_DETAIL_ERROR(ENOENT), +#endif +#if defined(ENOEXEC) + FOLLY_DETAIL_ERROR(ENOEXEC), +#endif +#if defined(ENOKEY) + FOLLY_DETAIL_ERROR(ENOKEY), +#endif +#if defined(ENOLCK) + FOLLY_DETAIL_ERROR(ENOLCK), +#endif +#if defined(ENOLINK) + FOLLY_DETAIL_ERROR(ENOLINK), +#endif +#if defined(ENOMEDIUM) + FOLLY_DETAIL_ERROR(ENOMEDIUM), +#endif +#if defined(ENOMEM) + FOLLY_DETAIL_ERROR(ENOMEM), +#endif +#if defined(ENOMSG) + FOLLY_DETAIL_ERROR(ENOMSG), +#endif +#if defined(ENONET) + FOLLY_DETAIL_ERROR(ENONET), +#endif +#if defined(ENOPKG) + FOLLY_DETAIL_ERROR(ENOPKG), +#endif +#if defined(ENOPROTOOPT) + FOLLY_DETAIL_ERROR(ENOPROTOOPT), +#endif +#if defined(ENOSPC) + FOLLY_DETAIL_ERROR(ENOSPC), +#endif +#if defined(ENOSR) + FOLLY_DETAIL_ERROR(ENOSR), +#endif +#if defined(ENOSTR) + FOLLY_DETAIL_ERROR(ENOSTR), +#endif +#if defined(ENOSYS) + FOLLY_DETAIL_ERROR(ENOSYS), +#endif +#if defined(ENOTBLK) + FOLLY_DETAIL_ERROR(ENOTBLK), +#endif +#if defined(ENOTCONN) + FOLLY_DETAIL_ERROR(ENOTCONN), +#endif +#if defined(ENOTDIR) + FOLLY_DETAIL_ERROR(ENOTDIR), +#endif +#if defined(ENOTEMPTY) + FOLLY_DETAIL_ERROR(ENOTEMPTY), +#endif +#if defined(ENOTNAM) + FOLLY_DETAIL_ERROR(ENOTNAM), +#endif +#if defined(ENOTRECOVERABLE) + FOLLY_DETAIL_ERROR(ENOTRECOVERABLE), +#endif +#if defined(ENOTSOCK) + FOLLY_DETAIL_ERROR(ENOTSOCK), +#endif +#if defined(ENOTTY) + FOLLY_DETAIL_ERROR(ENOTTY), +#endif +#if defined(ENOTUNIQ) + FOLLY_DETAIL_ERROR(ENOTUNIQ), +#endif +#if defined(ENXIO) + FOLLY_DETAIL_ERROR(ENXIO), +#endif +#if defined(EOPNOTSUPP) + FOLLY_DETAIL_ERROR(EOPNOTSUPP), +#endif +#if defined(EOVERFLOW) + FOLLY_DETAIL_ERROR(EOVERFLOW), +#endif +#if defined(EOWNERDEAD) + FOLLY_DETAIL_ERROR(EOWNERDEAD), +#endif +#if defined(EPERM) + FOLLY_DETAIL_ERROR(EPERM), +#endif +#if defined(EPFNOSUPPORT) + FOLLY_DETAIL_ERROR(EPFNOSUPPORT), +#endif +#if defined(EPIPE) + FOLLY_DETAIL_ERROR(EPIPE), +#endif +#if defined(EPROTO) + FOLLY_DETAIL_ERROR(EPROTO), +#endif +#if defined(EPROTONOSUPPORT) + FOLLY_DETAIL_ERROR(EPROTONOSUPPORT), +#endif +#if defined(EPROTOTYPE) + FOLLY_DETAIL_ERROR(EPROTOTYPE), +#endif +#if defined(ERANGE) + FOLLY_DETAIL_ERROR(ERANGE), +#endif +#if defined(EREMCHG) + FOLLY_DETAIL_ERROR(EREMCHG), +#endif +#if defined(EREMOTE) + FOLLY_DETAIL_ERROR(EREMOTE), +#endif +#if defined(EREMOTEIO) + FOLLY_DETAIL_ERROR(EREMOTEIO), +#endif +#if defined(ERESTART) + FOLLY_DETAIL_ERROR(ERESTART), +#endif +#if defined(ERFKILL) + FOLLY_DETAIL_ERROR(ERFKILL), +#endif +#if defined(EROFS) + FOLLY_DETAIL_ERROR(EROFS), +#endif +#if defined(ESHUTDOWN) + FOLLY_DETAIL_ERROR(ESHUTDOWN), +#endif +#if defined(ESOCKTNOSUPPORT) + FOLLY_DETAIL_ERROR(ESOCKTNOSUPPORT), +#endif +#if defined(ESPIPE) + FOLLY_DETAIL_ERROR(ESPIPE), +#endif +#if defined(ESRCH) + FOLLY_DETAIL_ERROR(ESRCH), +#endif +#if defined(ESRMNT) + FOLLY_DETAIL_ERROR(ESRMNT), +#endif +#if defined(ESTALE) + FOLLY_DETAIL_ERROR(ESTALE), +#endif +#if defined(ESTRPIPE) + FOLLY_DETAIL_ERROR(ESTRPIPE), +#endif +#if defined(ETIME) + FOLLY_DETAIL_ERROR(ETIME), +#endif +#if defined(ETIMEDOUT) + FOLLY_DETAIL_ERROR(ETIMEDOUT), +#endif +#if defined(ETOOMANYREFS) + FOLLY_DETAIL_ERROR(ETOOMANYREFS), +#endif +#if defined(ETXTBSY) + FOLLY_DETAIL_ERROR(ETXTBSY), +#endif +#if defined(EUCLEAN) + FOLLY_DETAIL_ERROR(EUCLEAN), +#endif +#if defined(EUNATCH) + FOLLY_DETAIL_ERROR(EUNATCH), +#endif +#if defined(EUSERS) + FOLLY_DETAIL_ERROR(EUSERS), +#endif +#if defined(EWOULDBLOCK) + FOLLY_DETAIL_ERROR(EWOULDBLOCK), +#endif +#if defined(EXDEV) + FOLLY_DETAIL_ERROR(EXDEV), +#endif +#if defined(EXFULL) + FOLLY_DETAIL_ERROR(EXFULL), +#endif +}; +#undef FOLLY_DETAIL_ERROR + +void writeStderr(const char* s, size_t len) { + writeFull(STDERR_FILENO, s, len); +} +void writeStderr(const char* s) { + writeStderr(s, strlen(s)); +} + +} // namespace + +void assertionFailure( + const char* expr, + const char* msg, + const char* file, + unsigned int line, + const char* function, + int error) { + writeStderr("\n\nAssertion failure: "); + writeStderr(expr + 1, strlen(expr) - 2); + writeStderr("\nMessage: "); + writeStderr(msg); + writeStderr("\nFile: "); + writeStderr(file); + writeStderr("\nLine: "); + char buf[20]; + uint32_t n = uint64ToBufferUnsafe(line, buf); + writeFull(STDERR_FILENO, buf, n); + writeStderr("\nFunction: "); + writeStderr(function); + if (error) { + // if errno is set, print the number and the symbolic constant + // the symbolic constant is necessary since actual numbers may vary + // for simplicity, do not attempt to mimic strerror printing descriptions + writeStderr("\nError: "); + n = uint64ToBufferUnsafe(error, buf); + writeFull(STDERR_FILENO, buf, n); + writeStderr(" ("); + // the list is not required to be sorted; but the program is about to die + auto const pred = [=](auto const e) { return e.first == error; }; + auto const it = std::find_if(std::begin(errors), std::end(errors), pred); + writeStderr(it != std::end(errors) ? it->second : "<unknown>"); + writeStderr(")"); + } + writeStderr("\n"); + fsyncNoInt(STDERR_FILENO); + abort(); +} + +} // namespace detail +} // namespace folly diff --git a/ios/Pods/Folly/folly/lang/SafeAssert.h b/ios/Pods/Folly/folly/lang/SafeAssert.h index 9bf7a3e9d..ee1859983 100644 --- a/ios/Pods/Folly/folly/lang/SafeAssert.h +++ b/ios/Pods/Folly/folly/lang/SafeAssert.h @@ -1,11 +1,11 @@ /* - * Copyright 2013-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -16,23 +16,28 @@ #pragma once +#include <cerrno> + #include <folly/Portability.h> #include <folly/Preprocessor.h> +#define FOLLY_SAFE_CHECK_IMPL(expr, expr_s, msg, error) \ + ((expr) ? static_cast<void>(0) \ + : ::folly::detail::assertionFailure( \ + FOLLY_PP_STRINGIZE(expr_s), \ + (msg), \ + __FILE__, \ + __LINE__, \ + __PRETTY_FUNCTION__, \ + error)) + /** * Verify that the expression is true. If not, prints an error message * (containing msg) to stderr and abort()s. Just like CHECK(), but only * logs to stderr and only does async-signal-safe calls. */ -#define FOLLY_SAFE_CHECK_IMPL(expr, expr_s, msg) \ - ((expr) ? static_cast<void>(0) \ - : ::folly::detail::assertionFailure( \ - FB_STRINGIZE(expr_s), \ - (msg), \ - __FILE__, \ - __LINE__, \ - __PRETTY_FUNCTION__)) -#define FOLLY_SAFE_CHECK(expr, msg) FOLLY_SAFE_CHECK_IMPL((expr), (expr), (msg)) +#define FOLLY_SAFE_CHECK(expr, msg) \ + FOLLY_SAFE_CHECK_IMPL((expr), (expr), (msg), 0) /** * In debug mode, verify that the expression is true. Otherwise, do nothing @@ -40,7 +45,13 @@ * only does async-signal-safe calls. */ #define FOLLY_SAFE_DCHECK(expr, msg) \ - FOLLY_SAFE_CHECK_IMPL(!folly::kIsDebug || (expr), (expr), (msg)) + FOLLY_SAFE_CHECK_IMPL(!::folly::kIsDebug || (expr), (expr), (msg), 0) + +/** + * Like FOLLY_SAFE_CHECK, but also prints errno. + */ +#define FOLLY_SAFE_PCHECK(expr, msg) \ + FOLLY_SAFE_CHECK_IMPL((expr), (expr), (msg), errno) namespace folly { namespace detail { @@ -50,6 +61,7 @@ namespace detail { const char* msg, const char* file, unsigned int line, - const char* function); + const char* function, + int error); } // namespace detail } // namespace folly diff --git a/ios/Pods/Folly/folly/lang/StaticConst.h b/ios/Pods/Folly/folly/lang/StaticConst.h new file mode 100644 index 000000000..9479dfe2b --- /dev/null +++ b/ios/Pods/Folly/folly/lang/StaticConst.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +namespace folly { + +// StaticConst +// +// A template for defining ODR-usable constexpr instances. Safe from ODR +// violations and initialization-order problems. + +template <typename T> +struct StaticConst { + static constexpr T value{}; +}; + +template <typename T> +constexpr T StaticConst<T>::value; + +} // namespace folly diff --git a/ios/Pods/Folly/folly/lang/TypeInfo.h b/ios/Pods/Folly/folly/lang/TypeInfo.h new file mode 100644 index 000000000..daf7c47f6 --- /dev/null +++ b/ios/Pods/Folly/folly/lang/TypeInfo.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <typeinfo> + +#include <folly/Portability.h> + +// FOLLY_TYPE_INFO_OF +// +// Returns &typeid(...) if RTTI is available, nullptr otherwise. In either +// case, has type std::type_info const*. +#if FOLLY_HAS_RTTI +#define FOLLY_TYPE_INFO_OF(...) (&typeid(__VA_ARGS__)) +#else +#define FOLLY_TYPE_INFO_OF(...) (static_cast<std::type_info const*>(nullptr)) +#endif + +namespace folly { + +// type_info_of +// +// Returns &typeid(T) if RTTI is available, nullptr otherwise. +// +// This overload works on the static type of the template parameter. +template <typename T> +FOLLY_ALWAYS_INLINE static std::type_info const* type_info_of() { + return FOLLY_TYPE_INFO_OF(T); +} + +// type_info_of +// +// Returns &typeid(t) if RTTI is available, nullptr otherwise. +// +// This overload works on the dynamic type of the non-template parameter. +template <typename T> +FOLLY_ALWAYS_INLINE static std::type_info const* type_info_of(T const& t) { + return FOLLY_TYPE_INFO_OF(t); +} + +} // namespace folly diff --git a/ios/Pods/Folly/folly/lang/UncaughtExceptions.h b/ios/Pods/Folly/folly/lang/UncaughtExceptions.h index e5efa8557..a00c2575f 100644 --- a/ios/Pods/Folly/folly/lang/UncaughtExceptions.h +++ b/ios/Pods/Folly/folly/lang/UncaughtExceptions.h @@ -1,11 +1,11 @@ /* - * Copyright 2013-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -18,23 +18,20 @@ #include <exception> -#if !defined(FOLLY_FORCE_EXCEPTION_COUNT_USE_STD) && \ - (defined(__GNUG__) || defined(__clang__)) +#if !defined(FOLLY_FORCE_EXCEPTION_COUNT_USE_STD) && defined(__GNUG__) #define FOLLY_EXCEPTION_COUNT_USE_CXA_GET_GLOBALS namespace __cxxabiv1 { // forward declaration (originally defined in unwind-cxx.h from from libstdc++) struct __cxa_eh_globals; // declared in cxxabi.h from libstdc++-v3 +#if !defined(__FreeBSD__) extern "C" __cxa_eh_globals* __cxa_get_globals() noexcept; +#else +// Signature mismatch with FreeBSD case +extern "C" __cxa_eh_globals* __cxa_get_globals(void); +#endif } // namespace __cxxabiv1 -#elif defined(_MSC_VER) && (_MSC_VER >= 1400) && \ - (_MSC_VER < 1900) // MSVC++ 8.0 or greater -#define FOLLY_EXCEPTION_COUNT_USE_GETPTD -// forward declaration (originally defined in mtdll.h from MSVCRT) -struct _tiddata; -extern "C" _tiddata* _getptd(); // declared in mtdll.h from MSVCRT -#elif defined(FOLLY_FORCE_EXCEPTION_COUNT_USE_STD) || \ - (defined(_MSC_VER) && (_MSC_VER >= 1900)) // MSVC++ 2015 +#elif defined(FOLLY_FORCE_EXCEPTION_COUNT_USE_STD) || defined(_MSC_VER) #define FOLLY_EXCEPTION_COUNT_USE_STD #else // Raise an error when trying to use this on unsupported platforms. diff --git a/ios/Pods/Folly/folly/memory/Arena-inl.h b/ios/Pods/Folly/folly/memory/Arena-inl.h index d616c65b4..06cccdecc 100644 --- a/ios/Pods/Folly/folly/memory/Arena-inl.h +++ b/ios/Pods/Folly/folly/memory/Arena-inl.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -45,7 +45,10 @@ void* Arena<Alloc>::allocateSlow(size_t size) { std::pair<Block*, size_t> p; char* start; - size_t allocSize = std::max(size, minBlockSize()) + sizeof(Block); + size_t allocSize; + if (!checked_add(&allocSize, std::max(size, minBlockSize()), sizeof(Block))) { + throw_exception<std::bad_alloc>(); + } if (sizeLimit_ != kNoSizeLimit && allocSize > sizeLimit_ - totalAllocatedSize_) { throw_exception(std::bad_alloc()); diff --git a/ios/Pods/Folly/folly/memory/Arena.h b/ios/Pods/Folly/folly/memory/Arena.h index 14694b06e..1eb830a39 100644 --- a/ios/Pods/Folly/folly/memory/Arena.h +++ b/ios/Pods/Folly/folly/memory/Arena.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -28,6 +28,7 @@ #include <folly/Likely.h> #include <folly/Memory.h> #include <folly/lang/Align.h> +#include <folly/lang/CheckedMath.h> #include <folly/lang/Exception.h> #include <folly/memory/Malloc.h> @@ -165,7 +166,12 @@ class Arena { // Round up size so it's properly aligned size_t roundUp(size_t size) const { - return (size + maxAlign_ - 1) & ~(maxAlign_ - 1); + auto maxAl = maxAlign_ - 1; + size_t realSize; + if (!checked_add<size_t>(&realSize, size, maxAl)) { + throw_exception<std::bad_alloc>(); + } + return realSize & ~maxAl; } // cache_last<true> makes the list keep a pointer to the last element, so we diff --git a/ios/Pods/Folly/folly/memory/EnableSharedFromThis.h b/ios/Pods/Folly/folly/memory/EnableSharedFromThis.h index 1d33b877c..c8db6860a 100644 --- a/ios/Pods/Folly/folly/memory/EnableSharedFromThis.h +++ b/ios/Pods/Folly/folly/memory/EnableSharedFromThis.h @@ -1,11 +1,11 @@ /* - * Copyright 2013-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/memory/MallctlHelper.h b/ios/Pods/Folly/folly/memory/MallctlHelper.h index 41e4c7a8e..1d08b1eb8 100644 --- a/ios/Pods/Folly/folly/memory/MallctlHelper.h +++ b/ios/Pods/Folly/folly/memory/MallctlHelper.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/memory/Malloc.h b/ios/Pods/Folly/folly/memory/Malloc.h index d9c720a62..ac61c2ef2 100644 --- a/ios/Pods/Folly/folly/memory/Malloc.h +++ b/ios/Pods/Folly/folly/memory/Malloc.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -21,6 +21,7 @@ #include <folly/CPortability.h> #include <folly/portability/Config.h> +#include <folly/portability/Malloc.h> /** * Define various MALLOCX_* macros normally provided by jemalloc. We define @@ -29,7 +30,6 @@ */ #if (defined(USE_JEMALLOC) || defined(FOLLY_USE_JEMALLOC)) && !FOLLY_SANITIZE // We have JEMalloc, so use it. -#include <jemalloc/jemalloc.h> #else #ifndef MALLOCX_LG_ALIGN #define MALLOCX_LG_ALIGN(la) (la) @@ -37,83 +37,11 @@ #ifndef MALLOCX_ZERO #define MALLOCX_ZERO (static_cast<int>(0x40)) #endif -#ifndef MALLOCX_ARENA -#define MALLOCX_ARENA(_) (static_cast<int>(0)) #endif -#ifndef MALLOCX_LG_ALIGN -#define MALLOCX_LG_ALIGN(_) (static_cast<int>(0)) -#endif -#ifndef MALLCTL_ARENAS_ALL -#define MALLCTL_ARENAS_ALL (static_cast<int>(0)) -#endif -#ifndef MALLOCX_TCACHE_NONE -#define MALLOCX_TCACHE_NONE (static_cast<int>(0)) -#endif -#endif - -// If using fbstring from libstdc++ (see comment in FBString.h), then -// just define stub code here to typedef the fbstring type into the -// folly namespace. -// This provides backwards compatibility for code that explicitly -// includes and uses fbstring. -#if defined(_GLIBCXX_USE_FB) && !defined(_LIBSTDCXX_FBSTRING) - -#include <folly/lang/Exception.h> -#include <folly/memory/detail/MallocImpl.h> - -#include <string> - -namespace folly { -using std::checkedCalloc; -using std::checkedMalloc; -using std::checkedRealloc; -using std::goodMallocSize; -using std::jemallocMinInPlaceExpandable; -using std::smartRealloc; -using std::usingJEMalloc; -} // namespace folly - -#else // !defined(_GLIBCXX_USE_FB) || defined(_LIBSTDCXX_FBSTRING) - -#ifdef _LIBSTDCXX_FBSTRING -#pragma GCC system_header - -/** - * Declare *allocx() and mallctl*() as weak symbols. These will be provided by - * jemalloc if we are using jemalloc, or will be nullptr if we are using another - * malloc implementation. - */ -extern "C" void* mallocx(size_t, int) __attribute__((__weak__)); -extern "C" void* rallocx(void*, size_t, int) __attribute__((__weak__)); -extern "C" size_t xallocx(void*, size_t, size_t, int) __attribute__((__weak__)); -extern "C" size_t sallocx(const void*, int) __attribute__((__weak__)); -extern "C" void dallocx(void*, int) __attribute__((__weak__)); -extern "C" void sdallocx(void*, size_t, int) __attribute__((__weak__)); -extern "C" size_t nallocx(size_t, int) __attribute__((__weak__)); -extern "C" int mallctl(const char*, void*, size_t*, void*, size_t) - __attribute__((__weak__)); -extern "C" int mallctlnametomib(const char*, size_t*, size_t*) - __attribute__((__weak__)); -extern "C" int -mallctlbymib(const size_t*, size_t, void*, size_t*, void*, size_t) - __attribute__((__weak__)); - -#else // !defined(_LIBSTDCXX_FBSTRING) #include <folly/lang/Exception.h> /* nolint */ #include <folly/memory/detail/MallocImpl.h> /* nolint */ -#endif - -// for malloc_usable_size -// NOTE: FreeBSD 9 doesn't have malloc.h. Its definitions -// are found in stdlib.h. -#if __has_include(<malloc.h>) -#include <malloc.h> -#else -#include <stdlib.h> -#endif - #include <cassert> #include <cstddef> #include <cstdint> @@ -125,38 +53,30 @@ mallctlbymib(const size_t*, size_t, void*, size_t*, void*, size_t) // clang-format off -#ifdef _LIBSTDCXX_FBSTRING -namespace std _GLIBCXX_VISIBILITY(default) { - _GLIBCXX_BEGIN_NAMESPACE_VERSION -#else namespace folly { -#endif -// Cannot depend on Portability.h when _LIBSTDCXX_FBSTRING. #if defined(__GNUC__) -#define FOLLY_MALLOC_NOINLINE __attribute__((__noinline__)) -#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL) >= 40900 // This is for checked malloc-like functions (returns non-null pointer // which cannot alias any outstanding pointer). #define FOLLY_MALLOC_CHECKED_MALLOC \ __attribute__((__returns_nonnull__, __malloc__)) #else -#define FOLLY_MALLOC_CHECKED_MALLOC __attribute__((__malloc__)) -#endif -#else -#define FOLLY_MALLOC_NOINLINE #define FOLLY_MALLOC_CHECKED_MALLOC #endif /** * Determine if we are using jemalloc or not. */ -#if defined(USE_JEMALLOC) && !FOLLY_SANITIZE +#if defined(FOLLY_ASSUME_NO_JEMALLOC) + inline bool usingJEMalloc() noexcept { + return false; + } +#elif defined(USE_JEMALLOC) && !FOLLY_SANITIZE inline bool usingJEMalloc() noexcept { return true; } #else -FOLLY_MALLOC_NOINLINE inline bool usingJEMalloc() noexcept { +FOLLY_NOINLINE inline bool usingJEMalloc() noexcept { // Checking for rallocx != nullptr is not sufficient; we may be in a // dlopen()ed module that depends on libjemalloc, so rallocx is resolved, but // the main program might be using a different memory allocator. @@ -270,7 +190,7 @@ inline void* checkedRealloc(void* ptr, size_t size) { * jemalloc, realloc() almost always ends up doing a copy, because * there is little fragmentation / slack space to take advantage of. */ -FOLLY_MALLOC_CHECKED_MALLOC FOLLY_MALLOC_NOINLINE inline void* smartRealloc( +FOLLY_MALLOC_CHECKED_MALLOC FOLLY_NOINLINE inline void* smartRealloc( void* p, const size_t currentSize, const size_t currentCapacity, @@ -291,12 +211,6 @@ FOLLY_MALLOC_CHECKED_MALLOC FOLLY_MALLOC_NOINLINE inline void* smartRealloc( return checkedRealloc(p, newCapacity); } -#ifdef _LIBSTDCXX_FBSTRING - _GLIBCXX_END_NAMESPACE_VERSION -#endif - } // namespace folly // clang-format on - -#endif // !defined(_GLIBCXX_USE_FB) || defined(_LIBSTDCXX_FBSTRING) diff --git a/ios/Pods/Folly/folly/memory/MemoryResource.h b/ios/Pods/Folly/folly/memory/MemoryResource.h new file mode 100644 index 000000000..30abd66c6 --- /dev/null +++ b/ios/Pods/Folly/folly/memory/MemoryResource.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#if defined(__has_include) && __cplusplus >= 201703L + +#if __has_include(<memory_resource>) + +#define FOLLY_HAS_MEMORY_RESOURCE 1 +#include <memory_resource> // @manual +namespace folly { +namespace detail { +namespace std_pmr = ::std::pmr; +} // namespace detail +} // namespace folly + +// Ignore experimental/memory_resource for libc++ so that all programs +// don't need to explicitly link the c++experimental lib +#elif !defined(_LIBCPP_VERSION) && __has_include(<experimental/memory_resource>) + +#define FOLLY_HAS_MEMORY_RESOURCE 1 +#include <experimental/memory_resource> // @manual +namespace folly { +namespace detail { +namespace std_pmr = ::std::experimental::pmr; +} // namespace detail +} // namespace folly + +#else + +#define FOLLY_HAS_MEMORY_RESOURCE 0 + +#endif + +#else // __has_include + +#define FOLLY_HAS_MEMORY_RESOURCE 0 + +#endif // __has_include diff --git a/ios/Pods/Folly/folly/memory/SanitizeLeak.h b/ios/Pods/Folly/folly/memory/SanitizeLeak.h new file mode 100644 index 000000000..2d17286dd --- /dev/null +++ b/ios/Pods/Folly/folly/memory/SanitizeLeak.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <folly/Portability.h> + +namespace folly { + +namespace detail { +void annotate_object_leaked_impl(void const* ptr); +void annotate_object_collected_impl(void const* ptr); +} // namespace detail + +/** + * When the current compilation unit is being compiled with ASAN enabled this + * function will suppress an intentionally leaked pointer from the LSAN report. + * Otherwise, this function is an inlinable no-op. + * + * NOTE: This function will suppress LSAN leak reporting when the current + * compilation unit is being compiled with ASAN, independent of whether folly + * itself was compiled with ASAN enabled. + */ +FOLLY_ALWAYS_INLINE static void annotate_object_leaked(void const* ptr) { + if (kIsSanitizeAddress) { + detail::annotate_object_leaked_impl(static_cast<void const*>(ptr)); + } +} + +/** + * Annotate that an object previously passed to annotate_object_leaked() has + * been collected, so we should no longer suppress it from the LSAN report. + * This function is an inlinable no-op when ASAN is not enabled for the current + * compilation unit. + */ +FOLLY_ALWAYS_INLINE static void annotate_object_collected(void const* ptr) { + if (kIsSanitizeAddress) { + detail::annotate_object_collected_impl(static_cast<void const*>(ptr)); + } +} +} // namespace folly diff --git a/ios/Pods/Folly/folly/memory/ThreadCachedArena.h b/ios/Pods/Folly/folly/memory/ThreadCachedArena.h index e957d983a..870194d96 100644 --- a/ios/Pods/Folly/folly/memory/ThreadCachedArena.h +++ b/ios/Pods/Folly/folly/memory/ThreadCachedArena.h @@ -1,11 +1,11 @@ /* - * Copyright 2012-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/memory/UninitializedMemoryHacks.h b/ios/Pods/Folly/folly/memory/UninitializedMemoryHacks.h index c96203042..19236ed78 100644 --- a/ios/Pods/Folly/folly/memory/UninitializedMemoryHacks.h +++ b/ios/Pods/Folly/folly/memory/UninitializedMemoryHacks.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -160,24 +160,6 @@ template struct MakeUnsafeStringSetLargerSize< void (std::string::*)(std::size_t), &std::string::__set_size>; -#elif defined(_GLIBCXX_USE_FB) -// FBString - -template <typename Tag, typename T, typename A, A Ptrstore_> -struct MakeUnsafeStringSetLargerSize { - friend void unsafeStringSetLargerSize( - std::basic_string<T>& s, - std::size_t n) { - // s.store_.expandNoinit(n - s.size(), false); - (s.*Ptrstore_).expandNoinit(n - s.size(), false); - } -}; -template struct MakeUnsafeStringSetLargerSize< - FollyMemoryDetailTranslationUnitTag, - char, - std::fbstring_core<char>(std::string::*), - &std::string::store_>; - #elif defined(_GLIBCXX_STRING) && _GLIBCXX_USE_CXX11_ABI // libstdc++ new implementation with SSO @@ -264,7 +246,13 @@ inline void unsafeStringSetLargerSize(std::string& s, std::size_t n) { #if defined(_LIBCPP_VECTOR) // libc++ -template <typename Tag, typename T, typename A, A Ptr__end_> +template < + typename Tag, + typename T, + typename A, + A Ptr__end_, + typename B, + B Ptr__annotate_contiguous_container_> struct MakeUnsafeVectorSetLargerSize { friend void unsafeVectorSetLargerSizeImpl(std::vector<T>& v, std::size_t n) { // v.__end_ += (n - v.size()); @@ -273,16 +261,31 @@ struct MakeUnsafeVectorSetLargerSize { std::is_standard_layout<std::vector<T>>::value && sizeof(std::vector<T>) == sizeof(Base), "reinterpret_cast safety conditions not met"); + const auto old_size = v.size(); reinterpret_cast<Base&>(v).*Ptr__end_ += (n - v.size()); + + // libc++ contiguous containers use special annotation functions that help + // the address sanitizer to detect improper memory accesses. When ASAN is + // enabled we need to call the appropriate annotation functions in order to + // stop ASAN from reporting false positives. When ASAN is disabled, the + // annotation function is a no-op. + (v.*Ptr__annotate_contiguous_container_)( + v.data(), + v.data() + v.capacity(), + v.data() + old_size, + v.data() + v.size()); } }; -#define FOLLY_DECLARE_VECTOR_RESIZE_WITHOUT_INIT(TYPE) \ - template struct folly::detail::MakeUnsafeVectorSetLargerSize< \ - FollyMemoryDetailTranslationUnitTag, \ - TYPE, \ - TYPE*(std::__vector_base<TYPE, std::allocator<TYPE>>::*), \ - &std::vector<TYPE>::__end_>; \ +#define FOLLY_DECLARE_VECTOR_RESIZE_WITHOUT_INIT(TYPE) \ + template struct folly::detail::MakeUnsafeVectorSetLargerSize< \ + FollyMemoryDetailTranslationUnitTag, \ + TYPE, \ + TYPE*(std::__vector_base<TYPE, std::allocator<TYPE>>::*), \ + &std::vector<TYPE>::__end_, \ + void (std::vector<TYPE>::*)( \ + const void*, const void*, const void*, const void*) const, \ + &std::vector<TYPE>::__annotate_contiguous_container>; \ FOLLY_DECLARE_VECTOR_RESIZE_WITHOUT_INIT_IMPL(TYPE) #elif defined(_GLIBCXX_VECTOR) @@ -306,10 +309,9 @@ struct MakeUnsafeVectorSetLargerSize : std::vector<T> { template struct folly::detail::MakeUnsafeVectorSetLargerSize< \ FollyMemoryDetailTranslationUnitTag, \ TYPE, \ - std::vector<TYPE>::_Vector_impl( \ - std::_Vector_base<TYPE, std::allocator<TYPE>>::*), \ + decltype(&std::vector<TYPE>::_M_impl), \ &std::vector<TYPE>::_M_impl, \ - TYPE*(std::vector<TYPE>::_Vector_impl::*), \ + decltype(&std::vector<TYPE>::_Vector_impl::_M_finish), \ &std::vector<TYPE>::_Vector_impl::_M_finish>; \ FOLLY_DECLARE_VECTOR_RESIZE_WITHOUT_INIT_IMPL(TYPE) diff --git a/ios/Pods/Folly/folly/memory/detail/MallocImpl.cpp b/ios/Pods/Folly/folly/memory/detail/MallocImpl.cpp index c2b471917..5c015add2 100644 --- a/ios/Pods/Folly/folly/memory/detail/MallocImpl.cpp +++ b/ios/Pods/Folly/folly/memory/detail/MallocImpl.cpp @@ -1,11 +1,11 @@ /* - * Copyright 2014-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/memory/detail/MallocImpl.h b/ios/Pods/Folly/folly/memory/detail/MallocImpl.h index 2e84f4a89..e92b85539 100644 --- a/ios/Pods/Folly/folly/memory/detail/MallocImpl.h +++ b/ios/Pods/Folly/folly/memory/detail/MallocImpl.h @@ -1,11 +1,11 @@ /* - * Copyright 2013-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -23,18 +23,22 @@ extern "C" { #if FOLLY_HAVE_WEAK_SYMBOLS -void* mallocx(size_t, int) __attribute__((__weak__)); -void* rallocx(void*, size_t, int) __attribute__((__weak__)); -size_t xallocx(void*, size_t, size_t, int) __attribute__((__weak__)); -size_t sallocx(const void*, int) __attribute__((__weak__)); -void dallocx(void*, int) __attribute__((__weak__)); -void sdallocx(void*, size_t, int) __attribute__((__weak__)); -size_t nallocx(size_t, int) __attribute__((__weak__)); +#if !defined(__FreeBSD__) +void* mallocx(size_t, int) __attribute__((__nothrow__, __weak__)); +void* rallocx(void*, size_t, int) __attribute__((__nothrow__, __weak__)); +size_t xallocx(void*, size_t, size_t, int) + __attribute__((__nothrow__, __weak__)); +size_t sallocx(const void*, int) __attribute__((__nothrow__, __weak__)); +void dallocx(void*, int) __attribute__((__nothrow__, __weak__)); +void sdallocx(void*, size_t, int) __attribute__((__nothrow__, __weak__)); +size_t nallocx(size_t, int) __attribute__((__nothrow__, __weak__)); int mallctl(const char*, void*, size_t*, void*, size_t) - __attribute__((__weak__)); -int mallctlnametomib(const char*, size_t*, size_t*) __attribute__((__weak__)); + __attribute__((__nothrow__, __weak__)); +int mallctlnametomib(const char*, size_t*, size_t*) + __attribute__((__nothrow__, __weak__)); int mallctlbymib(const size_t*, size_t, void*, size_t*, void*, size_t) - __attribute__((__weak__)); + __attribute__((__nothrow__, __weak__)); +#endif #else extern void* (*mallocx)(size_t, int); extern void* (*rallocx)(void*, size_t, int); @@ -50,6 +54,19 @@ extern int ( #ifdef _MSC_VER // We emulate weak linkage for MSVC. The symbols we're // aliasing to are hiding in MallocImpl.cpp +#if defined(_M_IX86) +#pragma comment(linker, "/alternatename:_mallocx=_mallocxWeak") +#pragma comment(linker, "/alternatename:_rallocx=_rallocxWeak") +#pragma comment(linker, "/alternatename:_xallocx=_xallocxWeak") +#pragma comment(linker, "/alternatename:_sallocx=_sallocxWeak") +#pragma comment(linker, "/alternatename:_dallocx=_dallocxWeak") +#pragma comment(linker, "/alternatename:_sdallocx=_sdallocxWeak") +#pragma comment(linker, "/alternatename:_nallocx=_nallocxWeak") +#pragma comment(linker, "/alternatename:_mallctl=_mallctlWeak") +#pragma comment( \ + linker, "/alternatename:_mallctlnametomib=_mallctlnametomibWeak") +#pragma comment(linker, "/alternatename:_mallctlbymib=_mallctlbymibWeak") +#else #pragma comment(linker, "/alternatename:mallocx=mallocxWeak") #pragma comment(linker, "/alternatename:rallocx=rallocxWeak") #pragma comment(linker, "/alternatename:xallocx=xallocxWeak") @@ -62,4 +79,5 @@ extern int ( #pragma comment(linker, "/alternatename:mallctlbymib=mallctlbymibWeak") #endif #endif +#endif } diff --git a/ios/Pods/Folly/folly/net/NetOps.cpp b/ios/Pods/Folly/folly/net/NetOps.cpp new file mode 100644 index 000000000..f46e42db4 --- /dev/null +++ b/ios/Pods/Folly/folly/net/NetOps.cpp @@ -0,0 +1,492 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <folly/net/NetOps.h> + +#include <fcntl.h> +#include <cerrno> + +#include <cstddef> + +#include <folly/Portability.h> +#include <folly/net/detail/SocketFileDescriptorMap.h> + +#ifdef _WIN32 +#include <event2/util.h> // @manual + +#include <MSWSock.h> // @manual + +#include <folly/ScopeGuard.h> +#endif + +namespace folly { +namespace netops { + +namespace { +#ifdef _WIN32 +// WSA has to be explicitly initialized. +static struct WinSockInit { + WinSockInit() { + WSADATA dat; + WSAStartup(MAKEWORD(2, 2), &dat); + } + ~WinSockInit() { + WSACleanup(); + } +} winsockInit; + +int translate_wsa_error(int wsaErr) { + switch (wsaErr) { + case WSAEWOULDBLOCK: + return EAGAIN; + default: + return wsaErr; + } +} +#endif + +template <class R, class F, class... Args> +static R wrapSocketFunction(F f, NetworkSocket s, Args... args) { + R ret = f(s.data, args...); +#ifdef _WIN32 + errno = translate_wsa_error(WSAGetLastError()); +#endif + return ret; +} +} // namespace + +NetworkSocket accept(NetworkSocket s, sockaddr* addr, socklen_t* addrlen) { + return NetworkSocket(wrapSocketFunction<NetworkSocket::native_handle_type>( + ::accept, s, addr, addrlen)); +} + +int bind(NetworkSocket s, const sockaddr* name, socklen_t namelen) { + if (kIsWindows && name->sa_family == AF_UNIX) { + // Windows added support for AF_UNIX sockets, but didn't add + // support for autobind sockets, so detect requests for autobind + // sockets and treat them as invalid. (otherwise they don't trigger + // an error, but also don't actually work) + if (name->sa_data[0] == '\0') { + errno = EINVAL; + return -1; + } + } + return wrapSocketFunction<int>(::bind, s, name, namelen); +} + +int close(NetworkSocket s) { + return netops::detail::SocketFileDescriptorMap::close(s.data); +} + +int connect(NetworkSocket s, const sockaddr* name, socklen_t namelen) { + auto r = wrapSocketFunction<int>(::connect, s, name, namelen); +#ifdef _WIN32 + if (r == -1 && WSAGetLastError() == WSAEWOULDBLOCK) { + errno = EINPROGRESS; + } +#endif + return r; +} + +int getpeername(NetworkSocket s, sockaddr* name, socklen_t* namelen) { + return wrapSocketFunction<int>(::getpeername, s, name, namelen); +} + +int getsockname(NetworkSocket s, sockaddr* name, socklen_t* namelen) { + return wrapSocketFunction<int>(::getsockname, s, name, namelen); +} + +int getsockopt( + NetworkSocket s, + int level, + int optname, + void* optval, + socklen_t* optlen) { + auto ret = wrapSocketFunction<int>( + ::getsockopt, s, level, optname, (char*)optval, optlen); +#ifdef _WIN32 + if (optname == TCP_NODELAY && *optlen == 1) { + // Windows is weird about this value, and documents it as a + // BOOL (ie. int) but expects the variable to be bool (1-byte), + // so we get to adapt the interface to work that way. + *(int*)optval = *(uint8_t*)optval; + *optlen = sizeof(int); + } +#endif + return ret; +} + +int inet_aton(const char* cp, in_addr* inp) { + inp->s_addr = inet_addr(cp); + return inp->s_addr == INADDR_NONE ? 0 : 1; +} + +int listen(NetworkSocket s, int backlog) { + return wrapSocketFunction<int>(::listen, s, backlog); +} + +int poll(PollDescriptor fds[], nfds_t nfds, int timeout) { + // Make sure that PollDescriptor is byte-for-byte identical to pollfd, + // so we don't need extra allocations just for the safety of this shim. + static_assert( + alignof(PollDescriptor) == alignof(pollfd), + "PollDescriptor is misaligned"); + static_assert( + sizeof(PollDescriptor) == sizeof(pollfd), + "PollDescriptor is the wrong size"); + static_assert( + offsetof(PollDescriptor, fd) == offsetof(pollfd, fd), + "PollDescriptor.fd is at the wrong place"); + static_assert( + sizeof(decltype(PollDescriptor().fd)) == sizeof(decltype(pollfd().fd)), + "PollDescriptor.fd is the wrong size"); + static_assert( + offsetof(PollDescriptor, events) == offsetof(pollfd, events), + "PollDescriptor.events is at the wrong place"); + static_assert( + sizeof(decltype(PollDescriptor().events)) == + sizeof(decltype(pollfd().events)), + "PollDescriptor.events is the wrong size"); + static_assert( + offsetof(PollDescriptor, revents) == offsetof(pollfd, revents), + "PollDescriptor.revents is at the wrong place"); + static_assert( + sizeof(decltype(PollDescriptor().revents)) == + sizeof(decltype(pollfd().revents)), + "PollDescriptor.revents is the wrong size"); + + // Pun it through + auto files = reinterpret_cast<pollfd*>(reinterpret_cast<void*>(fds)); +#ifdef _WIN32 + return ::WSAPoll(files, (ULONG)nfds, timeout); +#else + return ::poll(files, nfds, timeout); +#endif +} + +ssize_t recv(NetworkSocket s, void* buf, size_t len, int flags) { +#ifdef _WIN32 + if ((flags & MSG_DONTWAIT) == MSG_DONTWAIT) { + flags &= ~MSG_DONTWAIT; + + u_long pendingRead = 0; + if (ioctlsocket(s.data, FIONREAD, &pendingRead)) { + errno = translate_wsa_error(WSAGetLastError()); + return -1; + } + + fd_set readSet; + FD_ZERO(&readSet); + FD_SET(s.data, &readSet); + timeval timeout{0, 0}; + auto ret = select(1, &readSet, nullptr, nullptr, &timeout); + if (ret == 0) { + errno = EWOULDBLOCK; + return -1; + } + } + return wrapSocketFunction<ssize_t>(::recv, s, (char*)buf, (int)len, flags); +#else + return wrapSocketFunction<ssize_t>(::recv, s, buf, len, flags); +#endif +} + +ssize_t recvfrom( + NetworkSocket s, + void* buf, + size_t len, + int flags, + sockaddr* from, + socklen_t* fromlen) { +#ifdef _WIN32 + if ((flags & MSG_TRUNC) == MSG_TRUNC) { + SOCKET h = s.data; + + WSABUF wBuf{}; + wBuf.buf = (CHAR*)buf; + wBuf.len = (ULONG)len; + WSAMSG wMsg{}; + wMsg.dwBufferCount = 1; + wMsg.lpBuffers = &wBuf; + wMsg.name = from; + if (fromlen != nullptr) { + wMsg.namelen = *fromlen; + } + + // WSARecvMsg is an extension, so we don't get + // the convenience of being able to call it directly, even though + // WSASendMsg is part of the normal API -_-... + LPFN_WSARECVMSG WSARecvMsg; + GUID WSARecgMsg_GUID = WSAID_WSARECVMSG; + DWORD recMsgBytes; + WSAIoctl( + h, + SIO_GET_EXTENSION_FUNCTION_POINTER, + &WSARecgMsg_GUID, + sizeof(WSARecgMsg_GUID), + &WSARecvMsg, + sizeof(WSARecvMsg), + &recMsgBytes, + nullptr, + nullptr); + + DWORD bytesReceived; + int res = WSARecvMsg(h, &wMsg, &bytesReceived, nullptr, nullptr); + errno = translate_wsa_error(WSAGetLastError()); + if (res == 0) { + return bytesReceived; + } + if (fromlen != nullptr) { + *fromlen = wMsg.namelen; + } + if ((wMsg.dwFlags & MSG_TRUNC) == MSG_TRUNC) { + return wBuf.len + 1; + } + return -1; + } + return wrapSocketFunction<ssize_t>( + ::recvfrom, s, (char*)buf, (int)len, flags, from, fromlen); +#else + return wrapSocketFunction<ssize_t>( + ::recvfrom, s, buf, len, flags, from, fromlen); +#endif +} + +ssize_t recvmsg(NetworkSocket s, msghdr* message, int flags) { +#ifdef _WIN32 + (void)flags; + SOCKET h = s.data; + + // Don't currently support the name translation. + if (message->msg_name != nullptr || message->msg_namelen != 0) { + return (ssize_t)-1; + } + WSAMSG msg; + msg.name = nullptr; + msg.namelen = 0; + msg.Control.buf = (CHAR*)message->msg_control; + msg.Control.len = (ULONG)message->msg_controllen; + msg.dwFlags = 0; + msg.dwBufferCount = (DWORD)message->msg_iovlen; + msg.lpBuffers = new WSABUF[message->msg_iovlen]; + SCOPE_EXIT { + delete[] msg.lpBuffers; + }; + for (size_t i = 0; i < message->msg_iovlen; i++) { + msg.lpBuffers[i].buf = (CHAR*)message->msg_iov[i].iov_base; + msg.lpBuffers[i].len = (ULONG)message->msg_iov[i].iov_len; + } + + // WSARecvMsg is an extension, so we don't get + // the convenience of being able to call it directly, even though + // WSASendMsg is part of the normal API -_-... + LPFN_WSARECVMSG WSARecvMsg; + GUID WSARecgMsg_GUID = WSAID_WSARECVMSG; + DWORD recMsgBytes; + WSAIoctl( + h, + SIO_GET_EXTENSION_FUNCTION_POINTER, + &WSARecgMsg_GUID, + sizeof(WSARecgMsg_GUID), + &WSARecvMsg, + sizeof(WSARecvMsg), + &recMsgBytes, + nullptr, + nullptr); + + DWORD bytesReceived; + int res = WSARecvMsg(h, &msg, &bytesReceived, nullptr, nullptr); + errno = translate_wsa_error(WSAGetLastError()); + return res == 0 ? (ssize_t)bytesReceived : -1; +#else + return wrapSocketFunction<ssize_t>(::recvmsg, s, message, flags); +#endif +} + +ssize_t send(NetworkSocket s, const void* buf, size_t len, int flags) { +#ifdef _WIN32 + return wrapSocketFunction<ssize_t>( + ::send, s, (const char*)buf, (int)len, flags); +#else + return wrapSocketFunction<ssize_t>(::send, s, buf, len, flags); +#endif +} + +ssize_t sendmsg(NetworkSocket socket, const msghdr* message, int flags) { +#ifdef _WIN32 + (void)flags; + SOCKET h = socket.data; + + // Unfortunately, WSASendMsg requires the socket to have been opened + // as either SOCK_DGRAM or SOCK_RAW, but sendmsg has no such requirement, + // so we have to implement it based on send instead :( + ssize_t bytesSent = 0; + for (size_t i = 0; i < message->msg_iovlen; i++) { + int r = -1; + if (message->msg_name != nullptr) { + r = ::sendto( + h, + (const char*)message->msg_iov[i].iov_base, + (int)message->msg_iov[i].iov_len, + message->msg_flags, + (const sockaddr*)message->msg_name, + (int)message->msg_namelen); + } else { + r = ::send( + h, + (const char*)message->msg_iov[i].iov_base, + (int)message->msg_iov[i].iov_len, + message->msg_flags); + } + if (r == -1 || size_t(r) != message->msg_iov[i].iov_len) { + errno = translate_wsa_error(WSAGetLastError()); + if (WSAGetLastError() == WSAEWOULDBLOCK && bytesSent > 0) { + return bytesSent; + } + return -1; + } + bytesSent += r; + } + return bytesSent; +#else + return wrapSocketFunction<ssize_t>(::sendmsg, socket, message, flags); +#endif +} + +int sendmmsg( + NetworkSocket socket, + mmsghdr* msgvec, + unsigned int vlen, + int flags) { +#if FOLLY_HAVE_SENDMMSG + return wrapSocketFunction<int>(::sendmmsg, socket, msgvec, vlen, flags); +#else + // implement via sendmsg + for (unsigned int i = 0; i < vlen; i++) { + ssize_t ret = sendmsg(socket, &msgvec[i].msg_hdr, flags); + // in case of an error + // we return the number of msgs sent if > 0 + // or an error if no msg was sent + if (ret < 0) { + if (i) { + return static_cast<int>(i); + } + + return static_cast<int>(ret); + } + } + + return static_cast<int>(vlen); +#endif +} + +ssize_t sendto( + NetworkSocket s, + const void* buf, + size_t len, + int flags, + const sockaddr* to, + socklen_t tolen) { +#ifdef _WIN32 + return wrapSocketFunction<ssize_t>( + ::sendto, s, (const char*)buf, (int)len, flags, to, (int)tolen); +#else + return wrapSocketFunction<ssize_t>(::sendto, s, buf, len, flags, to, tolen); +#endif +} + +int setsockopt( + NetworkSocket s, + int level, + int optname, + const void* optval, + socklen_t optlen) { +#ifdef _WIN32 + if (optname == SO_REUSEADDR) { + // We don't have an equivelent to the Linux & OSX meaning of this + // on Windows, so ignore it. + return 0; + } else if (optname == SO_REUSEPORT) { + // Windows's SO_REUSEADDR option is closer to SO_REUSEPORT than + // it is to the Linux & OSX meaning of SO_REUSEADDR. + return -1; + } + return wrapSocketFunction<int>( + ::setsockopt, s, level, optname, (char*)optval, optlen); +#else + return wrapSocketFunction<int>( + ::setsockopt, s, level, optname, optval, optlen); +#endif +} + +int shutdown(NetworkSocket s, int how) { + return wrapSocketFunction<int>(::shutdown, s, how); +} + +NetworkSocket socket(int af, int type, int protocol) { + return NetworkSocket(::socket(af, type, protocol)); +} + +int socketpair(int domain, int type, int protocol, NetworkSocket sv[2]) { +#ifdef _WIN32 + if (domain != PF_UNIX || type != SOCK_STREAM || protocol != 0) { + return -1; + } + intptr_t pair[2]; + auto r = evutil_socketpair(AF_INET, type, protocol, pair); + if (r == -1) { + return r; + } + sv[0] = NetworkSocket(static_cast<SOCKET>(pair[0])); + sv[1] = NetworkSocket(static_cast<SOCKET>(pair[1])); + return r; +#else + int pair[2]; + auto r = ::socketpair(domain, type, protocol, pair); + if (r == -1) { + return r; + } + sv[0] = NetworkSocket(pair[0]); + sv[1] = NetworkSocket(pair[1]); + return r; +#endif +} + +int set_socket_non_blocking(NetworkSocket s) { +#ifdef _WIN32 + u_long nonBlockingEnabled = 1; + return ioctlsocket(s.data, FIONBIO, &nonBlockingEnabled); +#else + int flags = fcntl(s.data, F_GETFL, 0); + if (flags == -1) { + return -1; + } + return fcntl(s.data, F_SETFL, flags | O_NONBLOCK); +#endif +} + +int set_socket_close_on_exec(NetworkSocket s) { +#ifdef _WIN32 + if (SetHandleInformation((HANDLE)s.data, HANDLE_FLAG_INHERIT, 0)) { + return 0; + } + return -1; +#else + return fcntl(s.data, F_SETFD, FD_CLOEXEC); +#endif +} +} // namespace netops +} // namespace folly diff --git a/ios/Pods/Folly/folly/net/NetOps.h b/ios/Pods/Folly/folly/net/NetOps.h new file mode 100644 index 000000000..4d0ff603f --- /dev/null +++ b/ios/Pods/Folly/folly/net/NetOps.h @@ -0,0 +1,205 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <cstdint> + +#include <folly/Portability.h> +#include <folly/net/NetworkSocket.h> +#include <folly/portability/IOVec.h> +#include <folly/portability/SysTypes.h> +#include <folly/portability/Windows.h> + +#ifndef _WIN32 +#include <netdb.h> +#include <poll.h> + +#include <arpa/inet.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <sys/socket.h> +#include <sys/un.h> + +#ifdef MSG_ERRQUEUE +#define FOLLY_HAVE_MSG_ERRQUEUE 1 +/* for struct sock_extended_err*/ +#include <linux/errqueue.h> +#endif + +#ifndef SO_EE_ORIGIN_ZEROCOPY +#define SO_EE_ORIGIN_ZEROCOPY 5 +#endif + +#ifndef SO_EE_CODE_ZEROCOPY_COPIED +#define SO_EE_CODE_ZEROCOPY_COPIED 1 +#endif + +#ifndef SO_ZEROCOPY +#define SO_ZEROCOPY 60 +#endif + +#ifndef MSG_ZEROCOPY +#define MSG_ZEROCOPY 0x4000000 +#endif + +#ifndef SOL_UDP +#define SOL_UDP 17 +#endif + +#ifndef ETH_MAX_MTU +#define ETH_MAX_MTU 0xFFFFU +#endif + +#ifndef UDP_SEGMENT +#define UDP_SEGMENT 103 +#endif + +#ifndef UDP_MAX_SEGMENTS +#define UDP_MAX_SEGMENTS (1 << 6UL) +#endif + +#if !defined(MSG_WAITFORONE) && !defined(__wasm32__) +struct mmsghdr { + struct msghdr msg_hdr; + unsigned int msg_len; +}; +#endif + +#ifndef IP_BIND_ADDRESS_NO_PORT +#define IP_BIND_ADDRESS_NO_PORT 24 +#endif + +#else +#include <WS2tcpip.h> // @manual + +using nfds_t = int; +using sa_family_t = ADDRESS_FAMILY; + +// these are not supported +#define SO_EE_ORIGIN_ZEROCOPY 0 +#define SO_ZEROCOPY 0 +#define MSG_ZEROCOPY 0x0 +#define SOL_UDP 0x0 +#define UDP_SEGMENT 0x0 +#define IP_BIND_ADDRESS_NO_PORT 0 + +// We don't actually support either of these flags +// currently. +#define MSG_DONTWAIT 0x1000 +#define MSG_EOR 0 +struct msghdr { + void* msg_name; + socklen_t msg_namelen; + struct iovec* msg_iov; + size_t msg_iovlen; + void* msg_control; + size_t msg_controllen; + int msg_flags; +}; + +struct mmsghdr { + struct msghdr msg_hdr; + unsigned int msg_len; +}; + +struct sockaddr_un { + sa_family_t sun_family; + char sun_path[108]; +}; + +#define SHUT_RD SD_RECEIVE +#define SHUT_WR SD_SEND +#define SHUT_RDWR SD_BOTH + +// These are the same, but PF_LOCAL +// isn't defined by WinSock. +#define AF_LOCAL PF_UNIX +#define PF_LOCAL PF_UNIX + +// This isn't defined by Windows, and we need to +// distinguish it from SO_REUSEADDR +#define SO_REUSEPORT 0x7001 + +// Someone thought it would be a good idea +// to define a field via a macro... +#undef s_host +#endif + +namespace folly { +namespace netops { +// Poll descriptor is intended to be byte-for-byte identical to pollfd, +// except that it is typed as containing a NetworkSocket for sane interactions. +struct PollDescriptor { + NetworkSocket fd; + int16_t events; + int16_t revents; +}; + +NetworkSocket accept(NetworkSocket s, sockaddr* addr, socklen_t* addrlen); +int bind(NetworkSocket s, const sockaddr* name, socklen_t namelen); +int close(NetworkSocket s); +int connect(NetworkSocket s, const sockaddr* name, socklen_t namelen); +int getpeername(NetworkSocket s, sockaddr* name, socklen_t* namelen); +int getsockname(NetworkSocket s, sockaddr* name, socklen_t* namelen); +int getsockopt( + NetworkSocket s, + int level, + int optname, + void* optval, + socklen_t* optlen); +int inet_aton(const char* cp, in_addr* inp); +int listen(NetworkSocket s, int backlog); +int poll(PollDescriptor fds[], nfds_t nfds, int timeout); +ssize_t recv(NetworkSocket s, void* buf, size_t len, int flags); +ssize_t recvfrom( + NetworkSocket s, + void* buf, + size_t len, + int flags, + sockaddr* from, + socklen_t* fromlen); +ssize_t recvmsg(NetworkSocket s, msghdr* message, int flags); +ssize_t send(NetworkSocket s, const void* buf, size_t len, int flags); +ssize_t sendto( + NetworkSocket s, + const void* buf, + size_t len, + int flags, + const sockaddr* to, + socklen_t tolen); +ssize_t sendmsg(NetworkSocket socket, const msghdr* message, int flags); +int sendmmsg( + NetworkSocket socket, + mmsghdr* msgvec, + unsigned int vlen, + int flags); +int setsockopt( + NetworkSocket s, + int level, + int optname, + const void* optval, + socklen_t optlen); +int shutdown(NetworkSocket s, int how); +NetworkSocket socket(int af, int type, int protocol); +int socketpair(int domain, int type, int protocol, NetworkSocket sv[2]); + +// And now we diverge from the Posix way of doing things and just do things +// our own way. +int set_socket_non_blocking(NetworkSocket s); +int set_socket_close_on_exec(NetworkSocket s); +} // namespace netops +} // namespace folly diff --git a/ios/Pods/Folly/folly/net/NetworkSocket.h b/ios/Pods/Folly/folly/net/NetworkSocket.h new file mode 100644 index 000000000..62ef82050 --- /dev/null +++ b/ios/Pods/Folly/folly/net/NetworkSocket.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <ostream> + +#include <folly/net/detail/SocketFileDescriptorMap.h> +#include <folly/portability/Windows.h> + +namespace folly { +/** + * This is just a very thin wrapper around either a file descriptor or + * a SOCKET depending on platform, along with a couple of helper methods + * for explicitly converting to/from file descriptors, even on Windows. + */ +struct NetworkSocket { +#ifdef _WIN32 + using native_handle_type = SOCKET; + static constexpr native_handle_type invalid_handle_value = INVALID_SOCKET; +#else + using native_handle_type = int; + static constexpr native_handle_type invalid_handle_value = -1; +#endif + + native_handle_type data; + + constexpr NetworkSocket() : data(invalid_handle_value) {} + constexpr explicit NetworkSocket(native_handle_type d) : data(d) {} + + template <typename T> + static NetworkSocket fromFd(T) = delete; + static NetworkSocket fromFd(int fd) { + return NetworkSocket( + netops::detail::SocketFileDescriptorMap::fdToSocket(fd)); + } + + int toFd() const { + return netops::detail::SocketFileDescriptorMap::socketToFd(data); + } + + friend constexpr bool operator==( + const NetworkSocket& a, + const NetworkSocket& b) noexcept { + return a.data == b.data; + } + + friend constexpr bool operator!=( + const NetworkSocket& a, + const NetworkSocket& b) noexcept { + return !(a == b); + } +}; + +template <class CharT, class Traits> +inline std::basic_ostream<CharT, Traits>& operator<<( + std::basic_ostream<CharT, Traits>& os, + const NetworkSocket& addr) { + os << "folly::NetworkSocket(" << addr.data << ")"; + return os; +} +} // namespace folly + +namespace std { +template <> +struct hash<folly::NetworkSocket> { + size_t operator()(const folly::NetworkSocket& s) const noexcept { + return std::hash<folly::NetworkSocket::native_handle_type>()(s.data); + } +}; +} // namespace std diff --git a/ios/Pods/Folly/folly/net/detail/SocketFileDescriptorMap.h b/ios/Pods/Folly/folly/net/detail/SocketFileDescriptorMap.h new file mode 100644 index 000000000..d6d8c22f6 --- /dev/null +++ b/ios/Pods/Folly/folly/net/detail/SocketFileDescriptorMap.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <folly/portability/Windows.h> + +#ifndef _WIN32 +// This can't go via the portability header, because +// the portability header depends on us. +#include <unistd.h> +#endif + +namespace folly { +namespace netops { +namespace detail { +struct SocketFileDescriptorMap { +#ifdef _WIN32 + static int close(int fd) noexcept; + static int close(SOCKET sock) noexcept; + + static SOCKET fdToSocket(int fd) noexcept; + static int socketToFd(SOCKET sock) noexcept; +#else + static int close(int fd) noexcept { + return ::close(fd); + } + + static int fdToSocket(int fd) noexcept { + return fd; + } + static int socketToFd(int sock) noexcept { + return sock; + } +#endif +}; +} // namespace detail +} // namespace netops +} // namespace folly diff --git a/ios/Pods/Folly/folly/portability/Asm.h b/ios/Pods/Folly/folly/portability/Asm.h index afa9308b4..83a50197e 100644 --- a/ios/Pods/Folly/folly/portability/Asm.h +++ b/ios/Pods/Folly/folly/portability/Asm.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -18,7 +18,6 @@ #include <folly/Portability.h> -#include <chrono> #include <cstdint> #ifdef _MSC_VER @@ -27,7 +26,7 @@ namespace folly { inline void asm_volatile_memory() { -#if defined(__clang__) || defined(__GNUC__) +#if defined(__GNUC__) asm volatile("" : : : "memory"); #elif defined(_MSC_VER) ::_ReadWriteBarrier(); @@ -37,28 +36,12 @@ inline void asm_volatile_memory() { inline void asm_volatile_pause() { #if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) ::_mm_pause(); -#elif defined(__i386__) || FOLLY_X64 +#elif defined(__i386__) || FOLLY_X64 || (__mips_isa_rev > 1) asm volatile("pause"); -#elif FOLLY_AARCH64 || defined(__arm__) +#elif FOLLY_AARCH64 || (defined(__arm__) && !(__ARM_ARCH < 7)) asm volatile("yield"); #elif FOLLY_PPC64 asm volatile("or 27,27,27"); #endif } - -inline std::uint64_t asm_rdtsc() { -#if _MSC_VER - return (uint64_t)__rdtsc(); -#elif defined(__i386__) || FOLLY_X64 - // read the timestamp counter on x86 - auto hi = std::uint32_t{}; - auto lo = std::uint32_t{}; - asm volatile("rdtsc" : "=a"(lo), "=d"(hi)); - return (((std::uint64_t)lo) + (((std::uint64_t)hi) << 32)); -#else - // use steady_clock::now() as an approximation for the timestamp counter on - // non-x86 systems - return std::chrono::steady_clock::now().time_since_epoch().count(); -#endif -} } // namespace folly diff --git a/ios/Pods/Folly/folly/portability/Atomic.h b/ios/Pods/Folly/folly/portability/Atomic.h index e904e8953..b5136c5fc 100644 --- a/ios/Pods/Folly/folly/portability/Atomic.h +++ b/ios/Pods/Folly/folly/portability/Atomic.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/portability/Builtins.h b/ios/Pods/Folly/folly/portability/Builtins.h index 8ad75f46d..971cb8819 100644 --- a/ios/Pods/Folly/folly/portability/Builtins.h +++ b/ios/Pods/Folly/folly/portability/Builtins.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -41,6 +41,7 @@ FOLLY_ALWAYS_INLINE void __builtin___clear_cache(char* begin, char* end) { } } +#if !defined(_MSC_VER) || (_MSC_VER < 1923) FOLLY_ALWAYS_INLINE int __builtin_clz(unsigned int x) { unsigned long index; return int(_BitScanReverse(&index, (unsigned long)x) ? 31 - index : 32); @@ -50,10 +51,21 @@ FOLLY_ALWAYS_INLINE int __builtin_clzl(unsigned long x) { return __builtin_clz((unsigned int)x); } +#if defined(_M_IX86) || defined(_M_ARM) || defined(_M_ARM64) +FOLLY_ALWAYS_INLINE int __builtin_clzll(unsigned long long x) { + if (x == 0) { + return 64; + } + unsigned int msb = (unsigned int)(x >> 32); + unsigned int lsb = (unsigned int)x; + return (msb != 0) ? __builtin_clz(msb) : 32 + __builtin_clz(lsb); +} +#else FOLLY_ALWAYS_INLINE int __builtin_clzll(unsigned long long x) { unsigned long index; return int(_BitScanReverse64(&index, x) ? 63 - index : 64); } +#endif FOLLY_ALWAYS_INLINE int __builtin_ctz(unsigned int x) { unsigned long index; @@ -64,10 +76,24 @@ FOLLY_ALWAYS_INLINE int __builtin_ctzl(unsigned long x) { return __builtin_ctz((unsigned int)x); } +#if defined(_M_IX86) || defined(_M_ARM) || defined(_M_ARM64) +FOLLY_ALWAYS_INLINE int __builtin_ctzll(unsigned long long x) { + unsigned long index; + unsigned int msb = (unsigned int)(x >> 32); + unsigned int lsb = (unsigned int)x; + if (lsb != 0) { + return (int)(_BitScanForward(&index, lsb) ? index : 64); + } else { + return (int)(_BitScanForward(&index, msb) ? index + 32 : 64); + } +} +#else FOLLY_ALWAYS_INLINE int __builtin_ctzll(unsigned long long x) { unsigned long index; return int(_BitScanForward64(&index, x) ? index : 64); } +#endif +#endif // !defined(_MSC_VER) || (_MSC_VER < 1923) FOLLY_ALWAYS_INLINE int __builtin_ffs(int x) { unsigned long index; @@ -78,6 +104,12 @@ FOLLY_ALWAYS_INLINE int __builtin_ffsl(long x) { return __builtin_ffs(int(x)); } +#if defined(_M_IX86) || defined(_M_ARM) || defined(_M_ARM64) +FOLLY_ALWAYS_INLINE int __builtin_ffsll(long long x) { + int ctzll = __builtin_ctzll((unsigned long long)x); + return ctzll != 64 ? ctzll + 1 : 0; +} +#else FOLLY_ALWAYS_INLINE int __builtin_ffsll(long long x) { unsigned long index; return int(_BitScanForward64(&index, (unsigned long long)x) ? index + 1 : 0); @@ -87,14 +119,26 @@ FOLLY_ALWAYS_INLINE int __builtin_popcount(unsigned int x) { return int(__popcnt(x)); } +#if !defined(_MSC_VER) || (_MSC_VER < 1923) FOLLY_ALWAYS_INLINE int __builtin_popcountl(unsigned long x) { static_assert(sizeof(x) == 4, ""); return int(__popcnt(x)); } +#endif // !defined(_MSC_VER) || (_MSC_VER < 1923) +#endif +#if !defined(_MSC_VER) || (_MSC_VER < 1923) +#if defined(_M_IX86) +FOLLY_ALWAYS_INLINE int __builtin_popcountll(unsigned long long x) { + return int(__popcnt((unsigned int)(x >> 32))) + + int(__popcnt((unsigned int)x)); +} +#elif defined(_M_X64) FOLLY_ALWAYS_INLINE int __builtin_popcountll(unsigned long long x) { return int(__popcnt64(x)); } +#endif +#endif // !defined(_MSC_VER) || (_MSC_VER < 1923) FOLLY_ALWAYS_INLINE void* __builtin_return_address(unsigned int frame) { // I really hope frame is zero... diff --git a/ios/Pods/Folly/folly/portability/Config.h b/ios/Pods/Folly/folly/portability/Config.h index f38135477..8d500cc21 100644 --- a/ios/Pods/Folly/folly/portability/Config.h +++ b/ios/Pods/Folly/folly/portability/Config.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -20,14 +20,14 @@ #include <folly/folly-config.h> #endif -#ifdef FOLLY_PLATFORM_CONFIG -#include FOLLY_PLATFORM_CONFIG -#endif - #if __has_include(<features.h>) #include <features.h> // @manual #endif +#if __has_include(<bits/c++config.h>) +#include <bits/c++config.h> // @manual +#endif + #ifdef __ANDROID__ #include <android/api-level.h> // @manual #endif diff --git a/ios/Pods/Folly/folly/portability/Constexpr.h b/ios/Pods/Folly/folly/portability/Constexpr.h index 1d338c117..c88210236 100644 --- a/ios/Pods/Folly/folly/portability/Constexpr.h +++ b/ios/Pods/Folly/folly/portability/Constexpr.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -63,7 +63,7 @@ constexpr size_t constexpr_strlen(const char* s) { #if FOLLY_HAS_FEATURE(cxx_constexpr_string_builtins) // clang provides a constexpr builtin return __builtin_strlen(s); -#elif defined(__GNUC__) && !defined(__clang__) +#elif defined(__GLIBCXX__) && !defined(__clang__) // strlen() happens to already be constexpr under gcc return std::strlen(s); #else @@ -81,7 +81,7 @@ constexpr int constexpr_strcmp(const char* s1, const char* s2) { #if FOLLY_HAS_FEATURE(cxx_constexpr_string_builtins) // clang provides a constexpr builtin return __builtin_strcmp(s1, s2); -#elif defined(__GNUC__) && !defined(__clang__) +#elif defined(__GLIBCXX__) && !defined(__clang__) // strcmp() happens to already be constexpr under gcc return std::strcmp(s1, s2); #else diff --git a/ios/Pods/Folly/folly/portability/Dirent.h b/ios/Pods/Folly/folly/portability/Dirent.h index 35bbd671d..9bb3fefab 100644 --- a/ios/Pods/Folly/folly/portability/Dirent.h +++ b/ios/Pods/Folly/folly/portability/Dirent.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/portability/Event.h b/ios/Pods/Folly/folly/portability/Event.h index ac828296a..460462d87 100644 --- a/ios/Pods/Folly/folly/portability/Event.h +++ b/ios/Pods/Folly/folly/portability/Event.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -28,39 +28,12 @@ #include <folly/portability/Fcntl.h> #endif +#include <folly/net/detail/SocketFileDescriptorMap.h> + namespace folly { #ifdef _MSC_VER using libevent_fd_t = evutil_socket_t; #else using libevent_fd_t = int; #endif - -inline libevent_fd_t getLibeventFd(int fd) { -#ifdef _MSC_VER - if (fd == -1) { - return (libevent_fd_t)INVALID_HANDLE_VALUE; - } - return _get_osfhandle(fd); -#else - return fd; -#endif -} - -inline int libeventFdToFd(libevent_fd_t fd) { -#ifdef _MSC_VER - if (fd == (libevent_fd_t)INVALID_HANDLE_VALUE) { - return -1; - } - return _open_osfhandle((intptr_t)fd, O_RDWR | O_BINARY); -#else - return fd; -#endif -} - -using EventSetCallback = void (*)(libevent_fd_t, short, void*); -inline void -folly_event_set(event* e, int fd, short s, EventSetCallback f, void* arg) { - auto lfd = getLibeventFd(fd); - event_set(e, lfd, s, f, arg); -} } // namespace folly diff --git a/ios/Pods/Folly/folly/portability/Fcntl.h b/ios/Pods/Folly/folly/portability/Fcntl.h index 678c3ee7c..6197554ad 100644 --- a/ios/Pods/Folly/folly/portability/Fcntl.h +++ b/ios/Pods/Folly/folly/portability/Fcntl.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/portability/GFlags.h b/ios/Pods/Folly/folly/portability/GFlags.h index f1327bf95..97df834ab 100644 --- a/ios/Pods/Folly/folly/portability/GFlags.h +++ b/ios/Pods/Folly/folly/portability/GFlags.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/portability/GMock.h b/ios/Pods/Folly/folly/portability/GMock.h index 8967ad73d..6147667a2 100644 --- a/ios/Pods/Folly/folly/portability/GMock.h +++ b/ios/Pods/Folly/folly/portability/GMock.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/portability/GTest.h b/ios/Pods/Folly/folly/portability/GTest.h index f35a2ff91..c834eb215 100644 --- a/ios/Pods/Folly/folly/portability/GTest.h +++ b/ios/Pods/Folly/folly/portability/GTest.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/portability/IOVec.h b/ios/Pods/Folly/folly/portability/IOVec.h index 0b6812db4..1e46c247f 100644 --- a/ios/Pods/Folly/folly/portability/IOVec.h +++ b/ios/Pods/Folly/folly/portability/IOVec.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/portability/Libgen.h b/ios/Pods/Folly/folly/portability/Libgen.h index b8865e10d..dd590f18b 100644 --- a/ios/Pods/Folly/folly/portability/Libgen.h +++ b/ios/Pods/Folly/folly/portability/Libgen.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/portability/Malloc.h b/ios/Pods/Folly/folly/portability/Malloc.h index 2a9693959..608dc5ff9 100644 --- a/ios/Pods/Folly/folly/portability/Malloc.h +++ b/ios/Pods/Folly/folly/portability/Malloc.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -22,13 +22,23 @@ #include <folly/portability/Config.h> #if (defined(USE_JEMALLOC) || defined(FOLLY_USE_JEMALLOC)) && !FOLLY_SANITIZE +#if defined(FOLLY_ASSUME_NO_JEMALLOC) +#error \ + "Both USE_JEMALLOC/FOLLY_USE_JEMALLOC and FOLLY_ASSUME_NO_JEMALLOC defined" +#endif // JEMalloc provides it's own implementation of // malloc_usable_size, and that's what we should be using. -#include <jemalloc/jemalloc.h> +#if defined(__FreeBSD__) +#include <malloc_np.h> #else -#ifndef __APPLE__ +#include <jemalloc/jemalloc.h> // @manual +#endif +#else +#if !defined(__FreeBSD__) +#if __has_include(<malloc.h>) #include <malloc.h> #endif +#endif #if defined(__APPLE__) && !defined(FOLLY_HAVE_MALLOC_USABLE_SIZE) // MacOS doesn't have malloc_usable_size() diff --git a/ios/Pods/Folly/folly/portability/Math.h b/ios/Pods/Folly/folly/portability/Math.h index 86b4a8af9..dfcaf03ed 100644 --- a/ios/Pods/Folly/folly/portability/Math.h +++ b/ios/Pods/Folly/folly/portability/Math.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -20,21 +20,22 @@ namespace folly { -#ifndef __ANDROID__ +#if !defined(__ANDROID__) && !defined(__UCLIBC__) /** - * Most platforms hopefully provide std::nextafter. + * Most platforms hopefully provide std::nextafter, std::remainder. */ /* using override */ using std::nextafter; +/* using override */ using std::remainder; -#else // !__ANDROID__ +#else // !__ANDROID__ && !__UCLIBC__ /** - * On Android, std::nextafter isn't implemented. However, the C functions and - * compiler builtins are still provided. Using the GCC builtin is actually - * slightly faster, as they're constexpr and the use cases within folly are in - * constexpr context. + * On Android and uclibc, std::nextafter or std::remainder isn't implemented. + * However, the C functions and compiler builtins are still provided. Using the + * GCC builtin is actually slightly faster, as they're constexpr and the use + * cases within folly are in constexpr context. */ #if defined(__GNUC__) && !defined(__clang__) @@ -67,5 +68,23 @@ inline long double nextafter(long double x, long double y) { #endif // __GNUC__ -#endif // __ANDROID__ +/** + * On uclibc, std::remainder isn't implemented. + * Implement it using builtin versions + */ +#ifdef __UCLIBC__ +constexpr float remainder(float x, float y) { + return __builtin_remainderf(x, y); +} + +constexpr double remainder(double x, double y) { + return __builtin_remainder(x, y); +} + +constexpr long double remainder(long double x, long double y) { + return __builtin_remainderl(x, y); +} +#endif // __UCLIBC__ + +#endif // !__ANDROID__ && !__UCLIBC__ } // namespace folly diff --git a/ios/Pods/Folly/folly/portability/Memory.h b/ios/Pods/Folly/folly/portability/Memory.h index 60e2e2ad9..8cd8ebc9f 100644 --- a/ios/Pods/Folly/folly/portability/Memory.h +++ b/ios/Pods/Folly/folly/portability/Memory.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/portability/OpenSSL.h b/ios/Pods/Folly/folly/portability/OpenSSL.h index 91b423c7e..b22b3c58f 100644 --- a/ios/Pods/Folly/folly/portability/OpenSSL.h +++ b/ios/Pods/Folly/folly/portability/OpenSSL.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -27,6 +27,7 @@ #include <openssl/asn1.h> #include <openssl/bio.h> +#include <openssl/bn.h> #include <openssl/crypto.h> #include <openssl/dh.h> #include <openssl/err.h> @@ -82,6 +83,31 @@ #define FOLLY_OPENSSL_HAS_ALPN 0 #endif +// OpenSSL 1.1.1 and above have TLS 1.3 support +#if OPENSSL_VERSION_NUMBER >= 0x1010100fL +#define FOLLY_OPENSSL_HAS_TLS13 1 +#else +#define FOLLY_OPENSSL_HAS_TLS13 0 +#endif + +#if FOLLY_OPENSSL_IS_110 && \ + (!defined(OPENSSL_NO_CHACHA) || !defined(OPENSSL_NO_POLY1305)) +#define FOLLY_OPENSSL_HAS_CHACHA 1 +#else +#define FOLLY_OPENSSL_HAS_CHACHA 0 +#endif + +#if !FOLLY_OPENSSL_IS_110 +#define OPENSSL_VERSION SSLEAY_VERSION +#define OpenSSL_version SSLeay_version +#define OpenSSL_version_num SSLeay +#endif + +#if !FOLLY_OPENSSL_IS_110 +#define X509_get0_notAfter X509_get_notAfter +#define X509_get0_notBefore X509_get_notBefore +#endif + // This attempts to "unify" the OpenSSL libcrypto/libssl APIs between // OpenSSL 1.0.2, 1.1.0 (and some earlier versions) and BoringSSL. The general // idea is to provide namespaced wrapper methods for versions which do not @@ -111,6 +137,9 @@ int SSL_CTX_up_ref(SSL_CTX* session); int SSL_SESSION_up_ref(SSL_SESSION* session); int X509_up_ref(X509* x); int X509_STORE_up_ref(X509_STORE* v); +void X509_STORE_CTX_set0_verified_chain( + X509_STORE_CTX* ctx, + STACK_OF(X509) * sk); int EVP_PKEY_up_ref(EVP_PKEY* evp); void RSA_get0_key( const RSA* r, @@ -160,6 +189,8 @@ void DH_get0_pqg( const BIGNUM** q, const BIGNUM** g); void DH_get0_key(const DH* dh, const BIGNUM** pub_key, const BIGNUM** priv_key); +long DH_get_length(const DH* dh); +int DH_set_length(DH* dh, long length); void DSA_get0_pqg( const DSA* dsa, diff --git a/ios/Pods/Folly/folly/portability/PThread.h b/ios/Pods/Folly/folly/portability/PThread.h index d1fa23b4b..46de6a795 100644 --- a/ios/Pods/Folly/folly/portability/PThread.h +++ b/ios/Pods/Folly/folly/portability/PThread.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -22,6 +22,10 @@ #include <pthread.h> +#if defined(__FreeBSD__) +#include <sys/thr.h> // @manual +#endif + #elif !FOLLY_HAVE_PTHREAD #include <cstdint> diff --git a/ios/Pods/Folly/folly/portability/Sched.h b/ios/Pods/Folly/folly/portability/Sched.h index 95389f93d..7db99a754 100644 --- a/ios/Pods/Folly/folly/portability/Sched.h +++ b/ios/Pods/Folly/folly/portability/Sched.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/portability/Semaphore.h b/ios/Pods/Folly/folly/portability/Semaphore.h index 142a52969..a57e5c6df 100644 --- a/ios/Pods/Folly/folly/portability/Semaphore.h +++ b/ios/Pods/Folly/folly/portability/Semaphore.h @@ -1,11 +1,11 @@ /* - * Copyright 2017-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/portability/Sockets.h b/ios/Pods/Folly/folly/portability/Sockets.h index d08479fee..d8099d988 100644 --- a/ios/Pods/Folly/folly/portability/Sockets.h +++ b/ios/Pods/Folly/folly/portability/Sockets.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -16,107 +16,7 @@ #pragma once -#ifndef _WIN32 -#include <netdb.h> -#include <poll.h> - -#include <arpa/inet.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <sys/socket.h> -#include <sys/un.h> - -#ifdef MSG_ERRQUEUE -#define FOLLY_HAVE_MSG_ERRQUEUE 1 -/* for struct sock_extended_err*/ -#include <linux/errqueue.h> -#endif - -#ifndef SO_EE_ORIGIN_ZEROCOPY -#define SO_EE_ORIGIN_ZEROCOPY 5 -#endif - -#ifndef SO_EE_CODE_ZEROCOPY_COPIED -#define SO_EE_CODE_ZEROCOPY_COPIED 1 -#endif - -#ifndef SO_ZEROCOPY -#define SO_ZEROCOPY 60 -#endif - -#ifndef MSG_ZEROCOPY -#define MSG_ZEROCOPY 0x4000000 -#endif - -#ifndef SOL_UDP -#define SOL_UDP 17 -#endif - -#ifndef ETH_MAX_MTU -#define ETH_MAX_MTU 0xFFFFU -#endif - -#ifndef UDP_SEGMENT -#define UDP_SEGMENT 103 -#endif - -#ifndef UDP_MAX_SEGMENTS -#define UDP_MAX_SEGMENTS (1 << 6UL) -#endif - -#else -#include <folly/portability/IOVec.h> -#include <folly/portability/SysTypes.h> -#include <folly/portability/Windows.h> - -#include <WS2tcpip.h> // @manual - -using nfds_t = int; -using sa_family_t = ADDRESS_FAMILY; - -// these are not supported -#define SO_EE_ORIGIN_ZEROCOPY 0 -#define SO_ZEROCOPY 0 -#define MSG_ZEROCOPY 0x0 -#define SOL_UDP 0x0 -#define UDP_SEGMENT 0x0 - -// We don't actually support either of these flags -// currently. -#define MSG_DONTWAIT 0x1000 -#define MSG_EOR 0 -struct msghdr { - void* msg_name; - socklen_t msg_namelen; - struct iovec* msg_iov; - size_t msg_iovlen; - void* msg_control; - size_t msg_controllen; - int msg_flags; -}; - -struct sockaddr_un { - sa_family_t sun_family; - char sun_path[108]; -}; - -#define SHUT_RD SD_RECEIVE -#define SHUT_WR SD_SEND -#define SHUT_RDWR SD_BOTH - -// These are the same, but PF_LOCAL -// isn't defined by WinSock. -#define AF_LOCAL PF_UNIX -#define PF_LOCAL PF_UNIX - -// This isn't defined by Windows, and we need to -// distinguish it from SO_REUSEADDR -#define SO_REUSEPORT 0x7001 - -// Someone thought it would be a good idea -// to define a field via a macro... -#undef s_host -#endif +#include <folly/net/NetOps.h> namespace folly { namespace portability { diff --git a/ios/Pods/Folly/folly/portability/Stdio.h b/ios/Pods/Folly/folly/portability/Stdio.h index b9651f57a..48b19aa85 100644 --- a/ios/Pods/Folly/folly/portability/Stdio.h +++ b/ios/Pods/Folly/folly/portability/Stdio.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/portability/Stdlib.h b/ios/Pods/Folly/folly/portability/Stdlib.h index c179a3e4f..bdf915413 100644 --- a/ios/Pods/Folly/folly/portability/Stdlib.h +++ b/ios/Pods/Folly/folly/portability/Stdlib.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -18,6 +18,8 @@ #include <cstdlib> +#include <folly/portability/Config.h> + #if defined(__APPLE__) #if __has_include(<crt_externs.h>) #include <crt_externs.h> // @manual @@ -48,6 +50,11 @@ char*** _NSGetEnviron(void); #define environ (*_NSGetEnviron()) #endif +#if defined(__FreeBSD__) +// Needed to resolve linkage +char** environ; +#endif + #if !__linux__ && !FOLLY_MOBILE int clearenv(); #endif diff --git a/ios/Pods/Folly/folly/portability/String.h b/ios/Pods/Folly/folly/portability/String.h index 83d58f1fb..966e09890 100644 --- a/ios/Pods/Folly/folly/portability/String.h +++ b/ios/Pods/Folly/folly/portability/String.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/portability/SysFile.h b/ios/Pods/Folly/folly/portability/SysFile.h index 1c7c0125f..8bad9432b 100644 --- a/ios/Pods/Folly/folly/portability/SysFile.h +++ b/ios/Pods/Folly/folly/portability/SysFile.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/portability/SysMembarrier.h b/ios/Pods/Folly/folly/portability/SysMembarrier.h index 4a8dd1ebc..c77c00073 100644 --- a/ios/Pods/Folly/folly/portability/SysMembarrier.h +++ b/ios/Pods/Folly/folly/portability/SysMembarrier.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/portability/SysMman.h b/ios/Pods/Folly/folly/portability/SysMman.h index 587bfa3cb..1b7c0a967 100644 --- a/ios/Pods/Folly/folly/portability/SysMman.h +++ b/ios/Pods/Folly/folly/portability/SysMman.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/portability/SysResource.h b/ios/Pods/Folly/folly/portability/SysResource.h index 8ee20ecd1..9a5e4d1df 100644 --- a/ios/Pods/Folly/folly/portability/SysResource.h +++ b/ios/Pods/Folly/folly/portability/SysResource.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/portability/SysStat.h b/ios/Pods/Folly/folly/portability/SysStat.h index b4e3a83fc..06c27f435 100644 --- a/ios/Pods/Folly/folly/portability/SysStat.h +++ b/ios/Pods/Folly/folly/portability/SysStat.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/portability/SysSyscall.h b/ios/Pods/Folly/folly/portability/SysSyscall.h index 620fee7ab..e7060fd4a 100644 --- a/ios/Pods/Folly/folly/portability/SysSyscall.h +++ b/ios/Pods/Folly/folly/portability/SysSyscall.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/portability/SysTime.h b/ios/Pods/Folly/folly/portability/SysTime.h index 1a1ef11a2..516aa7e9b 100644 --- a/ios/Pods/Folly/folly/portability/SysTime.h +++ b/ios/Pods/Folly/folly/portability/SysTime.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/portability/SysTypes.h b/ios/Pods/Folly/folly/portability/SysTypes.h index 0d9b59e75..af95183a5 100644 --- a/ios/Pods/Folly/folly/portability/SysTypes.h +++ b/ios/Pods/Folly/folly/portability/SysTypes.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/portability/SysUio.cpp b/ios/Pods/Folly/folly/portability/SysUio.cpp new file mode 100644 index 000000000..e516b4395 --- /dev/null +++ b/ios/Pods/Folly/folly/portability/SysUio.cpp @@ -0,0 +1,137 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <folly/portability/SysUio.h> + +#include <cerrno> +#include <cstdio> + +#include <folly/ScopeGuard.h> +#include <folly/portability/Sockets.h> +#include <folly/portability/SysFile.h> +#include <folly/portability/Unistd.h> + +template <class F, class... Args> +static int wrapPositional(F f, int fd, off_t offset, Args... args) { + off_t origLoc = lseek(fd, 0, SEEK_CUR); + if (origLoc == off_t(-1)) { + return -1; + } + if (lseek(fd, offset, SEEK_SET) == off_t(-1)) { + return -1; + } + + int res = (int)f(fd, args...); + + int curErrNo = errno; + if (lseek(fd, origLoc, SEEK_SET) == off_t(-1)) { + if (res == -1) { + errno = curErrNo; + } + return -1; + } + errno = curErrNo; + + return res; +} + +#if !FOLLY_HAVE_PREADV +extern "C" ssize_t preadv(int fd, const iovec* iov, int count, off_t offset) { + return wrapPositional(readv, fd, offset, iov, count); +} +#endif + +#if !FOLLY_HAVE_PWRITEV +extern "C" ssize_t pwritev(int fd, const iovec* iov, int count, off_t offset) { + return wrapPositional(writev, fd, offset, iov, count); +} +#endif + +#ifdef _WIN32 +template <bool isRead> +static ssize_t doVecOperation(int fd, const iovec* iov, int count) { + if (!count) { + return 0; + } + if (count < 0 || count > folly::kIovMax) { + errno = EINVAL; + return -1; + } + + // We only need to worry about locking if the file descriptor is + // not a socket. We have no way of locking sockets :( + // The correct way to do this for sockets is via sendmsg/recvmsg, + // but this is good enough for now. + bool shouldLock = !folly::portability::sockets::is_fh_socket(fd); + if (shouldLock && lockf(fd, F_LOCK, 0) == -1) { + return -1; + } + SCOPE_EXIT { + if (shouldLock) { + lockf(fd, F_ULOCK, 0); + } + }; + + ssize_t bytesProcessed = 0; + int curIov = 0; + void* curBase = iov[0].iov_base; + size_t curLen = iov[0].iov_len; + while (curIov < count) { + ssize_t res = 0; + if (isRead) { + res = read(fd, curBase, (unsigned int)curLen); + if (res == 0 && curLen != 0) { + break; // End of File + } + } else { + res = write(fd, curBase, (unsigned int)curLen); + // Write of zero bytes is fine. + } + + if (res == -1) { + return -1; + } + + if (size_t(res) == curLen) { + curIov++; + if (curIov < count) { + curBase = iov[curIov].iov_base; + curLen = iov[curIov].iov_len; + } + } else { + curBase = (void*)((char*)curBase + res); + curLen -= res; + } + + if (bytesProcessed + res < 0) { + // Overflow + errno = EINVAL; + return -1; + } + bytesProcessed += res; + } + + return bytesProcessed; +} + +extern "C" ssize_t readv(int fd, const iovec* iov, int count) { + return doVecOperation<true>(fd, iov, count); +} + +extern "C" ssize_t writev(int fd, const iovec* iov, int count) { + return doVecOperation<false>(fd, iov, count); +} +#endif diff --git a/ios/Pods/Folly/folly/portability/SysUio.h b/ios/Pods/Folly/folly/portability/SysUio.h index 9413a6994..2c9a7ec85 100644 --- a/ios/Pods/Folly/folly/portability/SysUio.h +++ b/ios/Pods/Folly/folly/portability/SysUio.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/portability/Syslog.h b/ios/Pods/Folly/folly/portability/Syslog.h index e242cef3b..b2d45ecd8 100644 --- a/ios/Pods/Folly/folly/portability/Syslog.h +++ b/ios/Pods/Folly/folly/portability/Syslog.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/portability/Time.h b/ios/Pods/Folly/folly/portability/Time.h index 0f024aab8..d8127d106 100644 --- a/ios/Pods/Folly/folly/portability/Time.h +++ b/ios/Pods/Folly/folly/portability/Time.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -66,5 +66,7 @@ char* strptime( const char* __restrict buf, const char* __restrict fmt, struct tm* __restrict tm); +time_t timelocal(tm* tm); +time_t timegm(tm* tm); } #endif diff --git a/ios/Pods/Folly/folly/portability/Unistd.h b/ios/Pods/Folly/folly/portability/Unistd.h index b6eabfb48..82212fa27 100644 --- a/ios/Pods/Folly/folly/portability/Unistd.h +++ b/ios/Pods/Folly/folly/portability/Unistd.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/Folly/folly/portability/Windows.h b/ios/Pods/Folly/folly/portability/Windows.h index f7990ca9a..aad589931 100644 --- a/ios/Pods/Folly/folly/portability/Windows.h +++ b/ios/Pods/Folly/folly/portability/Windows.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -29,9 +29,15 @@ #ifndef __STDC__ /* nolint */ #define __STDC__ 1 +#pragma push_macro("_CRT_DECLARE_NONSTDC_NAMES") +#ifdef _CRT_DECLARE_NONSTDC_NAMES +#undef _CRT_DECLARE_NONSTDC_NAMES +#endif +#define _CRT_DECLARE_NONSTDC_NAMES 0 #include <direct.h> // @manual nolint #include <io.h> // @manual nolint #undef __STDC__ +#pragma pop_macro("_CRT_DECLARE_NONSTDC_NAMES") #else #include <direct.h> // @manual nolint #include <io.h> // @manual nolint diff --git a/ios/Pods/Folly/folly/small_vector.h b/ios/Pods/Folly/folly/small_vector.h index 66ef10115..4c7611b67 100644 --- a/ios/Pods/Folly/folly/small_vector.h +++ b/ios/Pods/Folly/folly/small_vector.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -48,6 +48,7 @@ #include <folly/FormatTraits.h> #include <folly/Likely.h> #include <folly/Portability.h> +#include <folly/ScopeGuard.h> #include <folly/Traits.h> #include <folly/lang/Assume.h> #include <folly/lang/Exception.h> @@ -97,55 +98,84 @@ namespace detail { /* * Move objects in memory to the right into some uninitialized - * memory, where the region overlaps. This doesn't just use - * std::move_backward because move_backward only works if all the - * memory is initialized to type T already. + * memory, where the region overlaps. Then call create(size_t) for each + * "hole" passing it the offset of the hole from first. + * + * This doesn't just use std::move_backward because move_backward only works + * if all the memory is initialized to type T already. + * + * The create function should return a reference type, to avoid + * extra copies and moves for non-trivial types. */ -template <class T> -typename std::enable_if< - std::is_default_constructible<T>::value && - !folly::is_trivially_copyable<T>::value>::type -moveObjectsRight(T* first, T* lastConstructed, T* realLast) { +template <class T, class Create> +typename std::enable_if<!folly::is_trivially_copyable<T>::value>::type +moveObjectsRightAndCreate( + T* const first, + T* const lastConstructed, + T* const realLast, + Create&& create) { if (lastConstructed == realLast) { return; } - T* end = first - 1; // Past the end going backwards. - T* out = realLast - 1; - T* in = lastConstructed - 1; - try { - for (; in != end && out >= lastConstructed; --in, --out) { - new (out) T(std::move(*in)); + T* out = realLast; + T* in = lastConstructed; + { + auto rollback = makeGuard([&] { + // We want to make sure the same stuff is uninitialized memory + // if we exit via an exception (this is to make sure we provide + // the basic exception safety guarantee for insert functions). + if (out < lastConstructed) { + out = lastConstructed - 1; + } + for (auto it = out + 1; it != realLast; ++it) { + it->~T(); + } + }); + // Decrement the pointers only when it is known that the resulting pointer + // is within the boundaries of the object. Decrementing past the beginning + // of the object is UB. Note that this is asymmetric wrt forward iteration, + // as past-the-end pointers are explicitly allowed. + for (; in != first && out > lastConstructed;) { + // Out must be decremented before an exception can be thrown so that + // the rollback guard knows where to start. + --out; + new (out) T(std::move(*(--in))); } - for (; in != end; --in, --out) { - *out = std::move(*in); + for (; in != first;) { + --out; + *out = std::move(*(--in)); } - for (; out >= lastConstructed; --out) { - new (out) T(); + for (; out > lastConstructed;) { + --out; + new (out) T(create(out - first)); } - } catch (...) { - // We want to make sure the same stuff is uninitialized memory - // if we exit via an exception (this is to make sure we provide - // the basic exception safety guarantee for insert functions). - if (out < lastConstructed) { - out = lastConstructed - 1; + for (; out != first;) { + --out; + *out = create(out - first); } - for (auto it = out + 1; it != realLast; ++it) { - it->~T(); - } - throw; + rollback.dismiss(); } } // Specialization for trivially copyable types. The call to -// std::move_backward here will just turn into a memmove. (TODO: -// change to std::is_trivially_copyable when that works.) -template <class T> -typename std::enable_if< - !std::is_default_constructible<T>::value || - folly::is_trivially_copyable<T>::value>::type -moveObjectsRight(T* first, T* lastConstructed, T* realLast) { +// std::move_backward here will just turn into a memmove. +// This must only be used with trivially copyable types because some of the +// memory may be uninitialized, and std::move_backward() won't work when it +// can't memmove(). +template <class T, class Create> +typename std::enable_if<folly::is_trivially_copyable<T>::value>::type +moveObjectsRightAndCreate( + T* const first, + T* const lastConstructed, + T* const realLast, + Create&& create) { std::move_backward(first, lastConstructed, realLast); + T* const end = first - 1; + T* out = first + (realLast - lastConstructed) - 1; + for (; out != end; --out) { + *out = create(out - first); + } } /* @@ -155,16 +185,17 @@ moveObjectsRight(T* first, T* lastConstructed, T* realLast) { template <class T, class Function> void populateMemForward(T* mem, std::size_t n, Function const& op) { std::size_t idx = 0; - try { + { + auto rollback = makeGuard([&] { + for (std::size_t i = 0; i < idx; ++i) { + mem[i].~T(); + } + }); for (size_t i = 0; i < n; ++i) { op(&mem[idx]); ++idx; } - } catch (...) { - for (std::size_t i = 0; i < idx; ++i) { - mem[i].~T(); - } - throw; + rollback.dismiss(); } } @@ -229,20 +260,21 @@ struct IntegralSizePolicy<SizeType, true> typename std::enable_if<!folly::is_trivially_copyable<T>::value>::type moveToUninitialized(T* first, T* last, T* out) { std::size_t idx = 0; - try { + { + auto rollback = makeGuard([&] { + // Even for callers trying to give the strong guarantee + // (e.g. push_back) it's ok to assume here that we don't have to + // move things back and that it was a copy constructor that + // threw: if someone throws from a move constructor the effects + // are unspecified. + for (std::size_t i = 0; i < idx; ++i) { + out[i].~T(); + } + }); for (; first != last; ++first, ++idx) { new (&out[idx]) T(std::move(*first)); } - } catch (...) { - // Even for callers trying to give the strong guarantee - // (e.g. push_back) it's ok to assume here that we don't have to - // move things back and that it was a copy constructor that - // threw: if someone throws from a move constructor the effects - // are unspecified. - for (std::size_t i = 0; i < idx; ++i) { - out[i].~T(); - } - throw; + rollback.dismiss(); } } @@ -250,7 +282,10 @@ struct IntegralSizePolicy<SizeType, true> template <class T> typename std::enable_if<folly::is_trivially_copyable<T>::value>::type moveToUninitialized(T* first, T* last, T* out) { - std::memmove(out, first, (last - first) * sizeof *first); + std::memmove( + static_cast<void*>(out), + static_cast<void const*>(first), + (last - first) * sizeof *first); } /* @@ -270,22 +305,24 @@ struct IntegralSizePolicy<SizeType, true> // We have to support the strong exception guarantee for emplace_back(). emplaceFunc(out + pos); // move old elements to the left of the new one - try { + { + auto rollback = makeGuard([&] { // + out[pos].~T(); + }); this->moveToUninitialized(begin, begin + pos, out); - } catch (...) { - out[pos].~T(); - throw; + rollback.dismiss(); } // move old elements to the right of the new one - try { + { + auto rollback = makeGuard([&] { + for (SizeType i = 0; i <= pos; ++i) { + out[i].~T(); + } + }); if (begin + pos < end) { this->moveToUninitialized(begin + pos, end, out + pos + 1); } - } catch (...) { - for (SizeType i = 0; i <= pos; ++i) { - out[i].~T(); - } - throw; + rollback.dismiss(); } } }; @@ -422,11 +459,13 @@ class small_vector : public detail::small_vector_base< public: typedef std::size_t size_type; typedef Value value_type; + typedef std::allocator<Value> allocator_type; typedef value_type& reference; typedef value_type const& const_reference; typedef value_type* iterator; typedef value_type* pointer; typedef value_type const* const_iterator; + typedef value_type const* const_pointer; typedef std::ptrdiff_t difference_type; typedef std::reverse_iterator<iterator> reverse_iterator; @@ -440,13 +479,14 @@ class small_vector : public detail::small_vector_base< small_vector(small_vector const& o) { auto n = o.size(); makeSize(n); - try { + { + auto rollback = makeGuard([&] { + if (this->isExtern()) { + u.freeHeap(); + } + }); std::uninitialized_copy(o.begin(), o.end(), begin()); - } catch (...) { - if (this->isExtern()) { - u.freeHeap(); - } - throw; + rollback.dismiss(); } this->setSize(n); } @@ -523,6 +563,10 @@ class small_vector : public detail::small_vector_base< : BaseType::policyMaxSize(); } + allocator_type get_allocator() const { + return {}; + } + size_type size() const { return this->doSize(); } @@ -608,19 +652,20 @@ class small_vector : public detail::small_vector_base< size_type i = oldSmall.size(); const size_type ci = i; - try { + { + auto rollback = makeGuard([&] { + oldSmall.setSize(i); + for (; i < oldLarge.size(); ++i) { + oldLarge[i].~value_type(); + } + oldLarge.setSize(ci); + }); for (; i < oldLarge.size(); ++i) { auto addr = oldSmall.begin() + i; new (addr) value_type(std::move(oldLarge[i])); oldLarge[i].~value_type(); } - } catch (...) { - oldSmall.setSize(i); - for (; i < oldLarge.size(); ++i) { - oldLarge[i].~value_type(); - } - oldLarge.setSize(ci); - throw; + rollback.dismiss(); } oldSmall.setSize(i); oldLarge.setSize(ci); @@ -636,22 +681,23 @@ class small_vector : public detail::small_vector_base< auto buff = oldExtern.u.buffer(); size_type i = 0; - try { + { + auto rollback = makeGuard([&] { + for (size_type kill = 0; kill < i; ++kill) { + buff[kill].~value_type(); + } + for (; i < oldIntern.size(); ++i) { + oldIntern[i].~value_type(); + } + oldIntern.setSize(0); + oldExtern.u.pdata_.heap_ = oldExternHeap; + oldExtern.setCapacity(oldExternCapacity); + }); for (; i < oldIntern.size(); ++i) { new (&buff[i]) value_type(std::move(oldIntern[i])); oldIntern[i].~value_type(); } - } catch (...) { - for (size_type kill = 0; kill < i; ++kill) { - buff[kill].~value_type(); - } - for (; i < oldIntern.size(); ++i) { - oldIntern[i].~value_type(); - } - oldIntern.setSize(0); - oldExtern.u.pdata_.heap_ = oldExternHeap; - oldExtern.setCapacity(oldExternCapacity); - throw; + rollback.dismiss(); } oldIntern.u.pdata_.heap_ = oldExternHeap; this->swapSizePolicy(o); @@ -738,7 +784,7 @@ class small_vector : public detail::small_vector_base< } template <class... Args> - void emplace_back(Args&&... args) { + reference emplace_back(Args&&... args) { if (capacity() == size()) { // Any of args may be references into the vector. // When we are reallocating, we have to be careful to construct the new @@ -751,10 +797,11 @@ class small_vector : public detail::small_vector_base< new (end()) value_type(std::forward<Args>(args)...); } this->setSize(size() + 1); + return back(); } void push_back(value_type&& t) { - return emplace_back(std::move(t)); + emplace_back(std::move(t)); } void push_back(value_type const& t) { @@ -782,10 +829,16 @@ class small_vector : public detail::small_vector_base< offset); this->setSize(this->size() + 1); } else { - detail::moveObjectsRight( - data() + offset, data() + size(), data() + size() + 1); + detail::moveObjectsRightAndCreate( + data() + offset, + data() + size(), + data() + size() + 1, + [&](size_t i) -> value_type&& { + assert(i == 0); + (void)i; + return std::move(t); + }); this->setSize(size() + 1); - data()[offset] = std::move(t); } return begin() + offset; } @@ -799,10 +852,16 @@ class small_vector : public detail::small_vector_base< iterator insert(const_iterator pos, size_type n, value_type const& val) { auto offset = pos - begin(); makeSize(size() + n); - detail::moveObjectsRight( - data() + offset, data() + size(), data() + size() + n); + detail::moveObjectsRightAndCreate( + data() + offset, + data() + size(), + data() + size() + n, + [&](size_t i) -> value_type const& { + assert(i < n); + (void)i; + return val; + }); this->setSize(size() + n); - std::generate_n(begin() + offset, n, [&] { return val; }); return begin() + offset; } @@ -906,7 +965,8 @@ class small_vector : public detail::small_vector_base< // iterator insert functions from integral types (see insert().) template <class It> iterator insertImpl(iterator pos, It first, It last, std::false_type) { - typedef typename std::iterator_traits<It>::iterator_category categ; + using categ = typename std::iterator_traits<It>::iterator_category; + using it_ref = typename std::iterator_traits<It>::reference; if (std::is_same<categ, std::input_iterator_tag>::value) { auto offset = pos - begin(); while (first != last) { @@ -916,13 +976,20 @@ class small_vector : public detail::small_vector_base< return begin() + offset; } - auto distance = std::distance(first, last); - auto offset = pos - begin(); + auto const distance = std::distance(first, last); + auto const offset = pos - begin(); + assert(distance >= 0); + assert(offset >= 0); makeSize(size() + distance); - detail::moveObjectsRight( - data() + offset, data() + size(), data() + size() + distance); + detail::moveObjectsRightAndCreate( + data() + offset, + data() + size(), + data() + size() + distance, + [&](size_t i) -> it_ref { + assert(i < size_t(distance)); + return *(first + i); + }); this->setSize(size() + distance); - std::copy_n(first, distance, begin() + offset); return begin() + offset; } @@ -951,14 +1018,15 @@ class small_vector : public detail::small_vector_base< auto distance = std::distance(first, last); makeSize(distance); this->setSize(distance); - try { + { + auto rollback = makeGuard([&] { + if (this->isExtern()) { + u.freeHeap(); + } + }); detail::populateMemForward( data(), distance, [&](void* p) { new (p) value_type(*first++); }); - } catch (...) { - if (this->isExtern()) { - u.freeHeap(); - } - throw; + rollback.dismiss(); } } @@ -966,13 +1034,14 @@ class small_vector : public detail::small_vector_base< void doConstruct(size_type n, InitFunc&& func) { makeSize(n); this->setSize(n); - try { + { + auto rollback = makeGuard([&] { + if (this->isExtern()) { + u.freeHeap(); + } + }); detail::populateMemForward(data(), n, std::forward<InitFunc>(func)); - } catch (...) { - if (this->isExtern()) { - u.freeHeap(); - } - throw; + rollback.dismiss(); } } @@ -1017,7 +1086,7 @@ class small_vector : public detail::small_vector_base< EmplaceFunc&& emplaceFunc, size_type pos) { if (newSize > max_size()) { - throw std::length_error("max_size exceeded in small_vector"); + throw_exception<std::length_error>("max_size exceeded in small_vector"); } if (newSize <= capacity()) { assert(!insert); @@ -1053,7 +1122,10 @@ class small_vector : public detail::small_vector_base< heapifyCapacity ? detail::shiftPointer(newh, kHeapifyCapacitySize) : newh); - try { + { + auto rollback = makeGuard([&] { // + free(newh); + }); if (insert) { // move and insert the new element this->moveToUninitializedEmplace( @@ -1062,9 +1134,7 @@ class small_vector : public detail::small_vector_base< // move without inserting new element this->moveToUninitialized(begin(), end(), newp); } - } catch (...) { - free(newh); - throw; + rollback.dismiss(); } for (auto& val : *this) { val.~value_type(); @@ -1123,9 +1193,7 @@ class small_vector : public detail::small_vector_base< } } FOLLY_SV_PACK_ATTR; - typedef typename std::aligned_storage< - sizeof(value_type) * MaxInline, - alignof(value_type)>::type InlineStorageDataType; + typedef aligned_storage_for_t<value_type[MaxInline]> InlineStorageDataType; typedef typename std::conditional< sizeof(value_type) * MaxInline != 0, @@ -1204,6 +1272,22 @@ void swap( a.swap(b); } +template <class T, std::size_t MaxInline, class A, class B, class C, class U> +void erase(small_vector<T, MaxInline, A, B, C>& v, U value) { + v.erase(std::remove(v.begin(), v.end(), value), v.end()); +} + +template < + class T, + std::size_t MaxInline, + class A, + class B, + class C, + class Predicate> +void erase_if(small_vector<T, MaxInline, A, B, C>& v, Predicate predicate) { + v.erase(std::remove_if(v.begin(), v.end(), predicate), v.end()); +} + ////////////////////////////////////////////////////////////////////// namespace detail { diff --git a/ios/Pods/Folly/folly/sorted_vector_types.h b/ios/Pods/Folly/folly/sorted_vector_types.h index cc5de9c94..17bbddd8d 100644 --- a/ios/Pods/Folly/folly/sorted_vector_types.h +++ b/ios/Pods/Folly/folly/sorted_vector_types.h @@ -1,11 +1,11 @@ /* - * Copyright 2011-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -56,6 +56,9 @@ * - sorted_vector_map::value_type is pair<K,V>, not pair<const K,V>. * (This is basically because we want to store the value_type in * std::vector<>, which requires it to be Assignable.) + * - insert() single key variants, emplace(), and emplace_hint() only provide + * the strong exception guarantee (unchanged when exception is thrown) when + * std::is_nothrow_move_constructible<value_type>::value is true. */ #pragma once @@ -64,14 +67,17 @@ #include <cassert> #include <initializer_list> #include <iterator> +#include <memory> #include <stdexcept> #include <type_traits> #include <utility> #include <vector> +#include <folly/ScopeGuard.h> #include <folly/Traits.h> #include <folly/Utility.h> #include <folly/lang/Exception.h> +#include <folly/memory/MemoryResource.h> namespace folly { @@ -127,34 +133,34 @@ int distance_if_multipass(Iterator first, Iterator last) { return std::distance(first, last); } -template <class OurContainer, class Vector, class GrowthPolicy> +template <class OurContainer, class Vector, class GrowthPolicy, class Value> typename OurContainer::iterator insert_with_hint( OurContainer& sorted, Vector& cont, - typename OurContainer::iterator hint, - typename OurContainer::value_type&& value, + typename OurContainer::const_iterator hint, + Value&& value, GrowthPolicy& po) { const typename OurContainer::value_compare& cmp(sorted.value_comp()); if (hint == cont.end() || cmp(value, *hint)) { if (hint == cont.begin() || cmp(*(hint - 1), value)) { hint = po.increase_capacity(cont, hint); - return cont.insert(hint, std::move(value)); + return cont.insert(hint, std::forward<Value>(value)); } else { - return sorted.insert(std::move(value)).first; + return sorted.insert(std::forward<Value>(value)).first; } } if (cmp(*hint, value)) { if (hint + 1 == cont.end() || cmp(value, *(hint + 1))) { hint = po.increase_capacity(cont, hint + 1); - return cont.insert(hint, std::move(value)); + return cont.insert(hint, std::forward<Value>(value)); } else { - return sorted.insert(std::move(value)).first; + return sorted.insert(std::forward<Value>(value)).first; } } // Value and *hint did not compare, so they are equal keys. - return hint; + return sorted.begin() + std::distance(sorted.cbegin(), hint); } template <class OurContainer, class Vector, class InputIterator> @@ -196,9 +202,30 @@ void bulk_insert( } template <typename Container, typename Compare> -Container&& as_sorted(Container&& container, Compare const& comp) { - using namespace std; - std::sort(begin(container), end(container), comp); +bool is_sorted_unique(Container const& container, Compare const& comp) { + if (container.empty()) { + return true; + } + auto const e = container.end(); + for (auto a = container.begin(), b = std::next(a); b != e; ++a, ++b) { + if (!comp(*a, *b)) { + return false; + } + } + return true; +} + +template <typename Container, typename Compare> +Container&& as_sorted_unique(Container&& container, Compare const& comp) { + std::sort(container.begin(), container.end(), comp); + container.erase( + std::unique( + container.begin(), + container.end(), + [&](auto const& a, auto const& b) { + return !comp(a, b) && !comp(b, a); + }), + container.end()); return static_cast<Container&&>(container); } } // namespace detail @@ -234,11 +261,15 @@ class sorted_vector_set : detail::growth_policy_wrapper<GrowthPolicy> { using if_is_transparent = _t<detail::sorted_vector_enable_if_is_transparent<void, C, K, V>>; + struct EBO; + public: typedef T value_type; typedef T key_type; typedef Compare key_compare; typedef Compare value_compare; + typedef Allocator allocator_type; + typedef Container container_type; typedef typename Container::pointer pointer; typedef typename Container::reference reference; @@ -255,13 +286,28 @@ class sorted_vector_set : detail::growth_policy_wrapper<GrowthPolicy> { typedef typename Container::reverse_iterator reverse_iterator; typedef typename Container::const_reverse_iterator const_reverse_iterator; + sorted_vector_set() : m_(Compare(), Allocator()) {} + + sorted_vector_set(const sorted_vector_set&) = default; + + sorted_vector_set(const sorted_vector_set& other, const Allocator& alloc) + : m_(other.m_, alloc) {} + + sorted_vector_set(sorted_vector_set&&) = default; + + sorted_vector_set(sorted_vector_set&& other, const Allocator& alloc) noexcept( + std::is_nothrow_constructible<EBO, EBO&&, const Allocator&>::value) + : m_(std::move(other.m_), alloc) {} + + explicit sorted_vector_set(const Allocator& alloc) : m_(Compare(), alloc) {} + explicit sorted_vector_set( - const Compare& comp = Compare(), + const Compare& comp, const Allocator& alloc = Allocator()) : m_(comp, alloc) {} template <class InputIterator> - explicit sorted_vector_set( + sorted_vector_set( InputIterator first, InputIterator last, const Compare& comp = Compare(), @@ -272,6 +318,17 @@ class sorted_vector_set : detail::growth_policy_wrapper<GrowthPolicy> { insert(first, last); } + template <class InputIterator> + sorted_vector_set( + InputIterator first, + InputIterator last, + const Allocator& alloc) + : m_(Compare(), alloc) { + // This is linear if [first, last) is already sorted (and if we + // can figure out the distance between the two iterators). + insert(first, last); + } + /* implicit */ sorted_vector_set( std::initializer_list<value_type> list, const Compare& comp = Compare(), @@ -280,6 +337,13 @@ class sorted_vector_set : detail::growth_policy_wrapper<GrowthPolicy> { insert(list.begin(), list.end()); } + sorted_vector_set( + std::initializer_list<value_type> list, + const Allocator& alloc) + : m_(Compare(), alloc) { + insert(list.begin(), list.end()); + } + // Construct a sorted_vector_set by stealing the storage of a prefilled // container. The container need not be sorted already. This supports // bulk construction of sorted_vector_set with zero allocations, not counting @@ -292,28 +356,39 @@ class sorted_vector_set : detail::growth_policy_wrapper<GrowthPolicy> { Container&& container, const Compare& comp = Compare()) : sorted_vector_set( - presorted, - detail::as_sorted(std::move(container), comp), + sorted_unique, + detail::as_sorted_unique(std::move(container), comp), comp) {} // Construct a sorted_vector_set by stealing the storage of a prefilled - // container. The container must be sorted, as presorted_t hints. Supports - // bulk construction of sorted_vector_set with zero allocations, not counting - // those performed by the caller. (The iterator range constructor performs at - // least one allocation). + // container. Its elements must be sorted and unique, as sorted_unique_t + // hints. Supports bulk construction of sorted_vector_set with zero + // allocations, not counting those performed by the caller. (The iterator + // range constructor performs at least one allocation). // - // Note that `sorted_vector_set(presorted_t, const Container& container)` is - // not provided, since the purpose of this constructor is to avoid an extra + // Note that `sorted_vector_set(sorted_unique_t, const Container& container)` + // is not provided, since the purpose of this constructor is to avoid an extra // copy. sorted_vector_set( - presorted_t, + sorted_unique_t, Container&& container, - const Compare& comp = Compare()) - : m_(comp, container.get_allocator()) { - assert(std::is_sorted(container.begin(), container.end(), value_comp())); - m_.cont_.swap(container); + const Compare& comp = Compare()) noexcept(std:: + is_nothrow_constructible< + EBO, + const Compare&, + Container&&>::value) + : m_(comp, std::move(container)) { + assert(detail::is_sorted_unique(m_.cont_, value_comp())); } + Allocator get_allocator() const { + return m_.cont_.get_allocator(); + } + + sorted_vector_set& operator=(const sorted_vector_set& other) = default; + + sorted_vector_set& operator=(sorted_vector_set&& other) = default; + sorted_vector_set& operator=(std::initializer_list<value_type> ilist) { clear(); insert(ilist.begin(), ilist.end()); @@ -381,7 +456,12 @@ class sorted_vector_set : detail::growth_policy_wrapper<GrowthPolicy> { } std::pair<iterator, bool> insert(const value_type& value) { - return insert(std::move(value_type(value))); + iterator it = lower_bound(value); + if (it == end() || value_comp()(value, *it)) { + it = get_growth_policy().increase_capacity(m_.cont_, it); + return std::make_pair(m_.cont_.insert(it, value), true); + } + return std::make_pair(it, false); } std::pair<iterator, bool> insert(value_type&& value) { @@ -393,11 +473,12 @@ class sorted_vector_set : detail::growth_policy_wrapper<GrowthPolicy> { return std::make_pair(it, false); } - iterator insert(iterator hint, const value_type& value) { - return insert(hint, std::move(value_type(value))); + iterator insert(const_iterator hint, const value_type& value) { + return detail::insert_with_hint( + *this, m_.cont_, hint, value, get_growth_policy()); } - iterator insert(iterator hint, value_type&& value) { + iterator insert(const_iterator hint, value_type&& value) { return detail::insert_with_hint( *this, m_.cont_, hint, std::move(value), get_growth_policy()); } @@ -407,6 +488,54 @@ class sorted_vector_set : detail::growth_policy_wrapper<GrowthPolicy> { detail::bulk_insert(*this, m_.cont_, first, last); } + void insert(std::initializer_list<value_type> ilist) { + insert(ilist.begin(), ilist.end()); + } + + // emplace isn't better than insert for sorted_vector_set, but aids + // compatibility + template <typename... Args> + std::pair<iterator, bool> emplace(Args&&... args) { + std::aligned_storage_t<sizeof(value_type), alignof(value_type)> b; + value_type* p = static_cast<value_type*>(static_cast<void*>(&b)); + auto a = get_allocator(); + std::allocator_traits<allocator_type>::construct( + a, p, std::forward<Args>(args)...); + auto g = makeGuard( + [&]() { std::allocator_traits<allocator_type>::destroy(a, p); }); + return insert(std::move(*p)); + } + + std::pair<iterator, bool> emplace(const value_type& value) { + return insert(value); + } + + std::pair<iterator, bool> emplace(value_type&& value) { + return insert(std::move(value)); + } + + // emplace_hint isn't better than insert for sorted_vector_set, but aids + // compatibility + template <typename... Args> + iterator emplace_hint(const_iterator hint, Args&&... args) { + std::aligned_storage_t<sizeof(value_type), alignof(value_type)> b; + value_type* p = static_cast<value_type*>(static_cast<void*>(&b)); + auto a = get_allocator(); + std::allocator_traits<allocator_type>::construct( + a, p, std::forward<Args>(args)...); + auto g = makeGuard( + [&]() { std::allocator_traits<allocator_type>::destroy(a, p); }); + return insert(hint, std::move(*p)); + } + + iterator emplace_hint(const_iterator hint, const value_type& value) { + return insert(hint, value); + } + + iterator emplace_hint(const_iterator hint, value_type&& value) { + return insert(hint, std::move(value)); + } + size_type erase(const key_type& key) { iterator it = find(key); if (it == end()) { @@ -416,11 +545,11 @@ class sorted_vector_set : detail::growth_policy_wrapper<GrowthPolicy> { return 1; } - iterator erase(iterator it) { + iterator erase(const_iterator it) { return m_.cont_.erase(it); } - iterator erase(iterator first, iterator last) { + iterator erase(const_iterator first, const_iterator last) { return m_.cont_.erase(first, last); } @@ -554,8 +683,26 @@ class sorted_vector_set : detail::growth_policy_wrapper<GrowthPolicy> { * More info: http://www.cantrip.org/emptyopt.html */ struct EBO : Compare { - explicit EBO(const Compare& c, const Allocator& alloc) + explicit EBO(const Compare& c, const Allocator& alloc) noexcept( + std::is_nothrow_default_constructible<Container>::value) : Compare(c), cont_(alloc) {} + EBO(const EBO& other, const Allocator& alloc) + noexcept(std::is_nothrow_constructible< + Container, + const Container&, + const Allocator&>::value) + : Compare(static_cast<const Compare&>(other)), + cont_(other.cont_, alloc) {} + EBO(EBO&& other, const Allocator& alloc) + noexcept(std::is_nothrow_constructible< + Container, + Container&&, + const Allocator&>::value) + : Compare(static_cast<Compare&&>(other)), + cont_(std::move(other.cont_), alloc) {} + EBO(const Compare& c, Container&& cont) + noexcept(std::is_nothrow_move_constructible<Container>::value) + : Compare(c), cont_(std::move(cont)) {} Container cont_; } m_; @@ -582,6 +729,27 @@ inline void swap( return a.swap(b); } +#if FOLLY_HAS_MEMORY_RESOURCE + +namespace pmr { + +template < + class T, + class Compare = std::less<T>, + class GrowthPolicy = void, + class Container = + std::vector<T, folly::detail::std_pmr::polymorphic_allocator<T>>> +using sorted_vector_set = folly::sorted_vector_set< + T, + Compare, + folly::detail::std_pmr::polymorphic_allocator<T>, + GrowthPolicy, + Container>; + +} // namespace pmr + +#endif + ////////////////////////////////////////////////////////////////////// /** @@ -615,11 +783,15 @@ class sorted_vector_map : detail::growth_policy_wrapper<GrowthPolicy> { using if_is_transparent = _t<detail::sorted_vector_enable_if_is_transparent<void, C, K, V>>; + struct EBO; + public: typedef Key key_type; typedef Value mapped_type; typedef typename Container::value_type value_type; typedef Compare key_compare; + typedef Allocator allocator_type; + typedef Container container_type; struct value_compare : private Compare { bool operator()(const value_type& a, const value_type& b) const { @@ -641,8 +813,26 @@ class sorted_vector_map : detail::growth_policy_wrapper<GrowthPolicy> { typedef typename Container::reverse_iterator reverse_iterator; typedef typename Container::const_reverse_iterator const_reverse_iterator; + sorted_vector_map() noexcept( + std::is_nothrow_constructible<EBO, value_compare, Allocator>::value) + : m_(value_compare(Compare()), Allocator()) {} + + sorted_vector_map(const sorted_vector_map&) = default; + + sorted_vector_map(const sorted_vector_map& other, const Allocator& alloc) + : m_(other.m_, alloc) {} + + sorted_vector_map(sorted_vector_map&&) = default; + + sorted_vector_map(sorted_vector_map&& other, const Allocator& alloc) noexcept( + std::is_nothrow_constructible<EBO, EBO&&, const Allocator&>::value) + : m_(std::move(other.m_), alloc) {} + + explicit sorted_vector_map(const Allocator& alloc) + : m_(value_compare(Compare()), alloc) {} + explicit sorted_vector_map( - const Compare& comp = Compare(), + const Compare& comp, const Allocator& alloc = Allocator()) : m_(value_compare(comp), alloc) {} @@ -656,7 +846,16 @@ class sorted_vector_map : detail::growth_policy_wrapper<GrowthPolicy> { insert(first, last); } - explicit sorted_vector_map( + template <class InputIterator> + sorted_vector_map( + InputIterator first, + InputIterator last, + const Allocator& alloc) + : m_(value_compare(Compare()), alloc) { + insert(first, last); + } + + /* implicit */ sorted_vector_map( std::initializer_list<value_type> list, const Compare& comp = Compare(), const Allocator& alloc = Allocator()) @@ -664,6 +863,13 @@ class sorted_vector_map : detail::growth_policy_wrapper<GrowthPolicy> { insert(list.begin(), list.end()); } + sorted_vector_map( + std::initializer_list<value_type> list, + const Allocator& alloc) + : m_(value_compare(Compare()), alloc) { + insert(list.begin(), list.end()); + } + // Construct a sorted_vector_map by stealing the storage of a prefilled // container. The container need not be sorted already. This supports // bulk construction of sorted_vector_map with zero allocations, not counting @@ -676,28 +882,40 @@ class sorted_vector_map : detail::growth_policy_wrapper<GrowthPolicy> { Container&& container, const Compare& comp = Compare()) : sorted_vector_map( - presorted, - detail::as_sorted(std::move(container), value_compare(comp)), + sorted_unique, + detail::as_sorted_unique(std::move(container), value_compare(comp)), comp) {} // Construct a sorted_vector_map by stealing the storage of a prefilled - // container. The container must be sorted, as presorted_t hints. S supports - // bulk construction of sorted_vector_map with zero allocations, not counting - // those performed by the caller. (The iterator range constructor performs at - // least one allocation). + // container. Its elements must be sorted and unique, as sorted_unique_t + // hints. Supports bulk construction of sorted_vector_map with zero + // allocations, not counting those performed by the caller. (The iterator + // range constructor performs at least one allocation). // - // Note that `sorted_vector_map(presorted_t, const Container& container)` is - // not provided, since the purpose of this constructor is to avoid an extra + // Note that `sorted_vector_map(sorted_unique_t, const Container& container)` + // is not provided, since the purpose of this constructor is to avoid an extra // copy. sorted_vector_map( - presorted_t, + sorted_unique_t, Container&& container, - const Compare& comp = Compare()) - : m_(value_compare(comp), container.get_allocator()) { - assert(std::is_sorted(container.begin(), container.end(), value_comp())); - m_.cont_.swap(container); + const Compare& comp = Compare()) noexcept(std:: + is_nothrow_constructible< + EBO, + value_compare, + Container&&>::value) + : m_(value_compare(comp), std::move(container)) { + assert(std::is_sorted(m_.cont_.begin(), m_.cont_.end(), value_comp())); + assert(detail::is_sorted_unique(m_.cont_, value_comp())); } + Allocator get_allocator() const { + return m_.cont_.get_allocator(); + } + + sorted_vector_map& operator=(const sorted_vector_map& other) = default; + + sorted_vector_map& operator=(sorted_vector_map&& other) = default; + sorted_vector_map& operator=(std::initializer_list<value_type> ilist) { clear(); insert(ilist.begin(), ilist.end()); @@ -765,7 +983,12 @@ class sorted_vector_map : detail::growth_policy_wrapper<GrowthPolicy> { } std::pair<iterator, bool> insert(const value_type& value) { - return insert(std::move(value_type(value))); + iterator it = lower_bound(value.first); + if (it == end() || value_comp()(value, *it)) { + it = get_growth_policy().increase_capacity(m_.cont_, it); + return std::make_pair(m_.cont_.insert(it, value), true); + } + return std::make_pair(it, false); } std::pair<iterator, bool> insert(value_type&& value) { @@ -777,11 +1000,12 @@ class sorted_vector_map : detail::growth_policy_wrapper<GrowthPolicy> { return std::make_pair(it, false); } - iterator insert(iterator hint, const value_type& value) { - return insert(hint, std::move(value_type(value))); + iterator insert(const_iterator hint, const value_type& value) { + return detail::insert_with_hint( + *this, m_.cont_, hint, value, get_growth_policy()); } - iterator insert(iterator hint, value_type&& value) { + iterator insert(const_iterator hint, value_type&& value) { return detail::insert_with_hint( *this, m_.cont_, hint, std::move(value), get_growth_policy()); } @@ -791,6 +1015,54 @@ class sorted_vector_map : detail::growth_policy_wrapper<GrowthPolicy> { detail::bulk_insert(*this, m_.cont_, first, last); } + void insert(std::initializer_list<value_type> ilist) { + insert(ilist.begin(), ilist.end()); + } + + // emplace isn't better than insert for sorted_vector_map, but aids + // compatibility + template <typename... Args> + std::pair<iterator, bool> emplace(Args&&... args) { + std::aligned_storage_t<sizeof(value_type), alignof(value_type)> b; + value_type* p = static_cast<value_type*>(static_cast<void*>(&b)); + auto a = get_allocator(); + std::allocator_traits<allocator_type>::construct( + a, p, std::forward<Args>(args)...); + auto g = makeGuard( + [&]() { std::allocator_traits<allocator_type>::destroy(a, p); }); + return insert(std::move(*p)); + } + + std::pair<iterator, bool> emplace(const value_type& value) { + return insert(value); + } + + std::pair<iterator, bool> emplace(value_type&& value) { + return insert(std::move(value)); + } + + // emplace_hint isn't better than insert for sorted_vector_set, but aids + // compatibility + template <typename... Args> + iterator emplace_hint(const_iterator hint, Args&&... args) { + std::aligned_storage_t<sizeof(value_type), alignof(value_type)> b; + value_type* p = static_cast<value_type*>(static_cast<void*>(&b)); + auto a = get_allocator(); + std::allocator_traits<allocator_type>::construct( + a, p, std::forward<Args>(args)...); + auto g = makeGuard( + [&]() { std::allocator_traits<allocator_type>::destroy(a, p); }); + return insert(hint, std::move(*p)); + } + + iterator emplace_hint(const_iterator hint, const value_type& value) { + return insert(hint, value); + } + + iterator emplace_hint(const_iterator hint, value_type&& value) { + return insert(hint, std::move(value)); + } + size_type erase(const key_type& key) { iterator it = find(key); if (it == end()) { @@ -800,11 +1072,11 @@ class sorted_vector_map : detail::growth_policy_wrapper<GrowthPolicy> { return 1; } - iterator erase(iterator it) { + iterator erase(const_iterator it) { return m_.cont_.erase(it); } - iterator erase(iterator first, iterator last) { + iterator erase(const_iterator first, const_iterator last) { return m_.cont_.erase(first, last); } @@ -953,8 +1225,26 @@ class sorted_vector_map : detail::growth_policy_wrapper<GrowthPolicy> { // This is to get the empty base optimization; see the comment in // sorted_vector_set. struct EBO : value_compare { - explicit EBO(const value_compare& c, const Allocator& alloc) + explicit EBO(const value_compare& c, const Allocator& alloc) noexcept( + std::is_nothrow_default_constructible<Container>::value) : value_compare(c), cont_(alloc) {} + EBO(const EBO& other, const Allocator& alloc) + noexcept(std::is_nothrow_constructible< + Container, + const Container&, + const Allocator&>::value) + : value_compare(static_cast<const value_compare&>(other)), + cont_(other.cont_, alloc) {} + EBO(EBO&& other, const Allocator& alloc) + noexcept(std::is_nothrow_constructible< + Container, + Container&&, + const Allocator&>::value) + : value_compare(static_cast<value_compare&&>(other)), + cont_(std::move(other.cont_), alloc) {} + EBO(const Compare& c, Container&& cont) + noexcept(std::is_nothrow_move_constructible<Container>::value) + : value_compare(c), cont_(std::move(cont)) {} Container cont_; } m_; @@ -1007,6 +1297,30 @@ inline void swap( return a.swap(b); } +#if FOLLY_HAS_MEMORY_RESOURCE + +namespace pmr { + +template < + class Key, + class Value, + class Compare = std::less<Key>, + class GrowthPolicy = void, + class Container = std::vector< + std::pair<Key, Value>, + folly::detail::std_pmr::polymorphic_allocator<std::pair<Key, Value>>>> +using sorted_vector_map = folly::sorted_vector_map< + Key, + Value, + Compare, + folly::detail::std_pmr::polymorphic_allocator<std::pair<Key, Value>>, + GrowthPolicy, + Container>; + +} // namespace pmr + +#endif + ////////////////////////////////////////////////////////////////////// } // namespace folly diff --git a/ios/Pods/Folly/folly/stop_watch.h b/ios/Pods/Folly/folly/stop_watch.h index 61d956bed..3556c70ca 100644 --- a/ios/Pods/Folly/folly/stop_watch.h +++ b/ios/Pods/Folly/folly/stop_watch.h @@ -1,11 +1,11 @@ /* - * Copyright 2016-present Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ios/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/GoogleAppMeasurement b/ios/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/GoogleAppMeasurement index 3408766ca..9dc6d74b6 100755 Binary files a/ios/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/GoogleAppMeasurement and b/ios/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/GoogleAppMeasurement differ diff --git a/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCOREvent.m b/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCOREvent.m index 651431223..5c79a4bce 100644 --- a/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCOREvent.m +++ b/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCOREvent.m @@ -33,8 +33,8 @@ static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ eventIDQueue = dispatch_queue_create("com.google.GDTCOREventIDQueue", DISPATCH_QUEUE_SERIAL); - counterPath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0]; - counterPath = [NSString stringWithFormat:@"%@/google-sdks-events/count", counterPath]; + counterPath = GDTCORRootDirectory().path; + counterPath = [NSString stringWithFormat:@"%@/count", counterPath]; NSError *error; NSString *countText = [NSString stringWithContentsOfFile:counterPath encoding:NSUTF8StringEncoding @@ -56,7 +56,8 @@ atomically:YES encoding:NSUTF8StringEncoding error:&error]; - GDTCORAssert(error == nil, @"There was an error saving the new counter value to disk."); + GDTCORAssert(error == nil, @"There was an error saving the new counter value to disk: %@", + error); }); return result; } diff --git a/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORFlatFileStorage.m b/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORFlatFileStorage.m index 224fb5869..d50cf0aa3 100644 --- a/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORFlatFileStorage.m +++ b/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORFlatFileStorage.m @@ -51,6 +51,27 @@ return archivePath; } ++ (NSString *)libraryDataPath { + static NSString *libraryDataPath; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + libraryDataPath = + [GDTCORRootDirectory() URLByAppendingPathComponent:NSStringFromClass([self class]) + isDirectory:YES] + .path; + libraryDataPath = [libraryDataPath stringByAppendingPathComponent:@"gdt_library_data"]; + if (![[NSFileManager defaultManager] fileExistsAtPath:libraryDataPath isDirectory:NULL]) { + NSError *error; + [[NSFileManager defaultManager] createDirectoryAtPath:libraryDataPath + withIntermediateDirectories:YES + attributes:0 + error:&error]; + GDTCORAssert(error == nil, @"Creating the library data path failed: %@", error); + } + }); + return libraryDataPath; +} + + (instancetype)sharedInstance { static GDTCORFlatFileStorage *sharedStorage; static dispatch_once_t onceToken; @@ -187,6 +208,54 @@ }); } +#pragma mark - GDTCORStorageProtocol + +- (void)libraryDataForKey:(nonnull NSString *)key + onComplete: + (nonnull void (^)(NSData *_Nullable, NSError *_Nullable error))onComplete { + dispatch_async(_storageQueue, ^{ + NSString *dataPath = [[[self class] libraryDataPath] stringByAppendingPathComponent:key]; + NSError *error; + NSData *data = [NSData dataWithContentsOfFile:dataPath options:0 error:&error]; + if (onComplete) { + onComplete(data, error); + } + }); +} + +- (void)storeLibraryData:(NSData *)data + forKey:(nonnull NSString *)key + onComplete:(nonnull void (^)(NSError *_Nullable error))onComplete { + if (!data || data.length <= 0) { + if (onComplete) { + onComplete([NSError errorWithDomain:NSInternalInconsistencyException code:-1 userInfo:nil]); + } + return; + } + dispatch_async(_storageQueue, ^{ + NSError *error; + NSString *dataPath = [[[self class] libraryDataPath] stringByAppendingPathComponent:key]; + [data writeToFile:dataPath options:NSDataWritingAtomic error:&error]; + if (onComplete) { + onComplete(error); + } + }); +} + +- (void)removeLibraryDataForKey:(nonnull NSString *)key + onComplete:(nonnull void (^)(NSError *_Nullable error))onComplete { + dispatch_async(_storageQueue, ^{ + NSError *error; + NSString *dataPath = [[[self class] libraryDataPath] stringByAppendingPathComponent:key]; + if ([[NSFileManager defaultManager] fileExistsAtPath:dataPath]) { + [[NSFileManager defaultManager] removeItemAtPath:dataPath error:&error]; + if (onComplete) { + onComplete(error); + } + } + }); +} + #pragma mark - Private helper methods /** Saves the event's dataObject to a file using NSData mechanisms. diff --git a/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORRegistrar.m b/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORRegistrar.m index 536da66b3..8f7cacb96 100644 --- a/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORRegistrar.m +++ b/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORRegistrar.m @@ -19,6 +19,10 @@ #import "GDTCORLibrary/Public/GDTCORConsoleLogger.h" +id<GDTCORStorageProtocol> _Nullable GDTCORStorageInstanceForTarget(GDTCORTarget target) { + return [GDTCORRegistrar sharedInstance].targetToStorage[@(target)]; +} + @implementation GDTCORRegistrar { /** Backing ivar for targetToUploader property. */ NSMutableDictionary<NSNumber *, id<GDTCORUploader>> *_targetToUploader; diff --git a/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadCoordinator.m b/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadCoordinator.m index e2d2d2065..c712e5e66 100644 --- a/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadCoordinator.m +++ b/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadCoordinator.m @@ -63,7 +63,7 @@ * check the next-upload clocks of all targets to determine if an upload attempt can be made. */ - (void)startTimer { - dispatch_sync(_coordinationQueue, ^{ + dispatch_async(_coordinationQueue, ^{ self->_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self->_coordinationQueue); dispatch_source_set_timer(self->_timer, DISPATCH_TIME_NOW, self->_timerInterval, @@ -196,7 +196,7 @@ static NSString *const ktargetToInFlightPackagesKey = } - (void)appWillBackground:(GDTCORApplication *)app { - dispatch_sync(_coordinationQueue, ^{ + dispatch_async(_coordinationQueue, ^{ [self stopTimer]; }); } diff --git a/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORStorageProtocol.h b/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORStorageProtocol.h index 99e9344ca..3cc175e4e 100644 --- a/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORStorageProtocol.h +++ b/ios/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORStorageProtocol.h @@ -17,6 +17,7 @@ #import <Foundation/Foundation.h> #import <GoogleDataTransport/GDTCORLifecycle.h> +#import <GoogleDataTransport/GDTCORTargets.h> @class GDTCOREvent; @@ -25,6 +26,8 @@ NS_ASSUME_NONNULL_BEGIN /** Defines the interface a storage subsystem is expected to implement. */ @protocol GDTCORStorageProtocol <NSObject, GDTCORLifecycleProtocol> +@required + /** Stores an event and calls onComplete with a non-nil error if anything went wrong. * * @param event The event to store @@ -36,6 +39,40 @@ NS_ASSUME_NONNULL_BEGIN /** Removes the events from storage. */ - (void)removeEvents:(NSSet<NSNumber *> *)eventIDs; +/** Persists the given data with the given key. + * + * @param data The data to store. + * @param key The unique key to store it to. + * @param onComplete An block to be run when storage of the data is complete. + */ +- (void)storeLibraryData:(NSData *)data + forKey:(NSString *)key + onComplete:(void (^)(NSError *_Nullable error))onComplete; + +/** Retrieves the stored data for the given key. + * + * @param key The key corresponding to the desired data. + * @param onComplete The callback to invoke with the data once it's retrieved. + */ +- (void)libraryDataForKey:(NSString *)key + onComplete:(void (^)(NSData *_Nullable data, NSError *_Nullable error))onComplete; + +/** Removes data from storage and calls the callback when complete. + * + * @param key The key of the data to remove. + * @param onComplete The callback that will be invoked when removing the data is complete. + */ +- (void)removeLibraryDataForKey:(NSString *)key + onComplete:(void (^)(NSError *_Nullable error))onComplete; + @end +/** Retrieves the storage instance for the given target. + * + * @param target The target. + * * @return The storage instance registered for the target, or nil if there is none. + */ +FOUNDATION_EXPORT +id<GDTCORStorageProtocol> _Nullable GDTCORStorageInstanceForTarget(GDTCORTarget target); + NS_ASSUME_NONNULL_END diff --git a/ios/Pods/GoogleDataTransport/README.md b/ios/Pods/GoogleDataTransport/README.md index 1747cca7a..a396a214d 100644 --- a/ios/Pods/GoogleDataTransport/README.md +++ b/ios/Pods/GoogleDataTransport/README.md @@ -2,14 +2,20 @@ [![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) [![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![Actions Status][gh-abtesting-badge]][gh-actions] [![Actions Status][gh-auth-badge]][gh-actions] [![Actions Status][gh-core-badge]][gh-actions] +[![Actions Status][gh-crashlytics-badge]][gh-actions] +[![Actions Status][gh-database-badge]][gh-actions] [![Actions Status][gh-datatransport-badge]][gh-actions] [![Actions Status][gh-dynamiclinks-badge]][gh-actions] [![Actions Status][gh-firebasepod-badge]][gh-actions] [![Actions Status][gh-firestore-badge]][gh-actions] +[![Actions Status][gh-functions-badge]][gh-actions] +[![Actions Status][gh-inappmessaging-badge]][gh-actions] [![Actions Status][gh-interop-badge]][gh-actions] [![Actions Status][gh-messaging-badge]][gh-actions] +[![Actions Status][gh-remoteconfig-badge]][gh-actions] [![Actions Status][gh-storage-badge]][gh-actions] [![Actions Status][gh-symbolcollision-badge]][gh-actions] [![Actions Status][gh-zip-badge]][gh-actions] @@ -185,8 +191,16 @@ building and running the FirebaseAuth pod along with various samples and tests. ### Firebase Database -To run the Database Integration tests, make your database authentication rules -[public](https://firebase.google.com/docs/database/security/quickstart). +The Firebase Database Integration tests can be run against a locally running Database Emulator +or against a production instance. + +To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before +running the integration test. + +To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to +`Example/Database/App/GoogleService-Info.plist`. Your Security Rule must be set to +[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are +running. ### Firebase Storage @@ -274,14 +288,20 @@ Your use of Firebase is governed by the [Terms of Service for Firebase Services](https://firebase.google.com/terms/). [gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg [gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg [gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg +[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg [gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg [gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg [gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg [gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg +[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg +[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg [gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg [gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg +[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg [gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg [gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg [gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/ios/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTNanopbHelpers.m b/ios/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTNanopbHelpers.m index 4b63c6133..ba6591362 100644 --- a/ios/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTNanopbHelpers.m +++ b/ios/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTNanopbHelpers.m @@ -31,7 +31,7 @@ #import <nanopb/pb_decode.h> #import <nanopb/pb_encode.h> -#import "GDTCCTLibrary/Private/GDTCOREvent+NetworkConnectionInfo.h" +#import "GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h" #pragma mark - General purpose encoders @@ -145,6 +145,11 @@ gdt_cct_LogEvent GDTCCTConstructLogEvent(GDTCOREvent *event) { length:networkConnectionInfoData.length]; logEvent.has_network_connection_info = 1; } + NSNumber *eventCode = event.eventCode; + if (eventCode != nil) { + logEvent.has_event_code = 1; + logEvent.event_code = [eventCode intValue]; + } } NSError *error; NSData *extensionBytes; diff --git a/ios/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTPrioritizer.m b/ios/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTPrioritizer.m index 224e34cbf..d0382cc26 100644 --- a/ios/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTPrioritizer.m +++ b/ios/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTPrioritizer.m @@ -23,7 +23,7 @@ #import <GoogleDataTransport/GDTCORTargets.h> #import "GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h" -#import "GDTCCTLibrary/Private/GDTCOREvent+NetworkConnectionInfo.h" +#import "GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h" const static int64_t kMillisPerDay = 8.64e+7; diff --git a/ios/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCOREvent+GDTCCTSupport.m b/ios/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCOREvent+GDTCCTSupport.m new file mode 100644 index 000000000..1531e565a --- /dev/null +++ b/ios/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCOREvent+GDTCCTSupport.m @@ -0,0 +1,236 @@ +/* + * Copyright 2020 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h" + +#import <GoogleDataTransport/GDTCORConsoleLogger.h> + +NSString *const GDTCCTNeedsNetworkConnectionInfo = @"needs_network_connection_info"; + +NSString *const GDTCCTNetworkConnectionInfo = @"network_connection_info"; + +NSString *const GDTCCTEventCodeInfo = @"event_code_info"; + +@implementation GDTCOREvent (GDTCCTSupport) + +- (void)setNeedsNetworkConnectionInfoPopulated:(BOOL)needsNetworkConnectionInfoPopulated { + if (!needsNetworkConnectionInfoPopulated) { + if (!self.customBytes) { + return; + } + + // Make sure we don't destroy the eventCode data, if any is present. + @try { + NSError *error; + NSMutableDictionary *bytesDict = + [[NSJSONSerialization JSONObjectWithData:self.customBytes options:0 + error:&error] mutableCopy]; + if (error) { + GDTCORLogDebug(@"Error when setting an event's event_code: %@", error); + return; + } + NSNumber *eventCode = bytesDict[GDTCCTEventCodeInfo]; + if (eventCode != nil) { + self.customBytes = + [NSJSONSerialization dataWithJSONObject:@{GDTCCTEventCodeInfo : eventCode} + options:0 + error:&error]; + } + } @catch (NSException *exception) { + GDTCORLogDebug(@"Error when setting the event for needs_network_connection_info: %@", + exception); + } + } else { + @try { + NSError *error; + NSMutableDictionary *bytesDict; + if (self.customBytes) { + bytesDict = [[NSJSONSerialization JSONObjectWithData:self.customBytes + options:0 + error:&error] mutableCopy]; + if (error) { + GDTCORLogDebug(@"Error when setting an even'ts event_code: %@", error); + return; + } + } else { + bytesDict = [[NSMutableDictionary alloc] init]; + } + [bytesDict setObject:@YES forKey:GDTCCTNeedsNetworkConnectionInfo]; + self.customBytes = [NSJSONSerialization dataWithJSONObject:bytesDict options:0 error:&error]; + } @catch (NSException *exception) { + GDTCORLogDebug(@"Error when setting the event for needs_network_connection_info: %@", + exception); + } + } +} + +- (BOOL)needsNetworkConnectionInfoPopulated { + if (self.customBytes) { + @try { + NSError *error; + NSDictionary *bytesDict = [NSJSONSerialization JSONObjectWithData:self.customBytes + options:0 + error:&error]; + return bytesDict && !error && [bytesDict[GDTCCTNeedsNetworkConnectionInfo] boolValue]; + } @catch (NSException *exception) { + GDTCORLogDebug(@"Error when checking the event for needs_network_connection_info: %@", + exception); + } + } + return NO; +} + +- (void)setNetworkConnectionInfoData:(NSData *)networkConnectionInfoData { + @try { + NSError *error; + NSString *dataString = [networkConnectionInfoData base64EncodedStringWithOptions:0]; + if (dataString != nil) { + NSMutableDictionary *bytesDict; + if (self.customBytes) { + bytesDict = [[NSJSONSerialization JSONObjectWithData:self.customBytes + options:0 + error:&error] mutableCopy]; + if (error) { + GDTCORLogDebug(@"Error when setting an even'ts event_code: %@", error); + return; + } + } else { + bytesDict = [[NSMutableDictionary alloc] init]; + } + [bytesDict setObject:dataString forKey:GDTCCTNetworkConnectionInfo]; + self.customBytes = [NSJSONSerialization dataWithJSONObject:bytesDict options:0 error:&error]; + if (error) { + self.customBytes = nil; + GDTCORLogDebug(@"Error when setting an event's network_connection_info: %@", error); + } + } + } @catch (NSException *exception) { + GDTCORLogDebug(@"Error when setting an event's network_connection_info: %@", exception); + } +} + +- (nullable NSData *)networkConnectionInfoData { + if (self.customBytes) { + @try { + NSError *error; + NSDictionary *bytesDict = [NSJSONSerialization JSONObjectWithData:self.customBytes + options:0 + error:&error]; + NSString *base64Data = bytesDict[GDTCCTNetworkConnectionInfo]; + NSData *networkConnectionInfoData = [[NSData alloc] initWithBase64EncodedString:base64Data + options:0]; + if (error) { + GDTCORLogDebug(@"Error when getting an event's network_connection_info: %@", error); + return nil; + } else { + return networkConnectionInfoData; + } + } @catch (NSException *exception) { + GDTCORLogDebug(@"Error when getting an event's network_connection_info: %@", exception); + } + } + return nil; +} + +- (NSNumber *)eventCode { + if (self.customBytes) { + @try { + NSError *error; + NSDictionary *bytesDict = [NSJSONSerialization JSONObjectWithData:self.customBytes + options:0 + error:&error]; + NSString *eventCodeString = bytesDict[GDTCCTEventCodeInfo]; + + if (!eventCodeString) { + return nil; + } + + NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; + formatter.numberStyle = NSNumberFormatterDecimalStyle; + NSNumber *eventCode = [formatter numberFromString:eventCodeString]; + + if (error) { + GDTCORLogDebug(@"Error when getting an event's network_connection_info: %@", error); + return nil; + } else { + return eventCode; + } + } @catch (NSException *exception) { + GDTCORLogDebug(@"Error when getting an event's event_code: %@", exception); + } + } + return nil; +} + +- (void)setEventCode:(NSNumber *)eventCode { + if (eventCode == nil) { + if (!self.customBytes) { + return; + } + + NSError *error; + NSMutableDictionary *bytesDict = [[NSJSONSerialization JSONObjectWithData:self.customBytes + options:0 + error:&error] mutableCopy]; + if (error) { + GDTCORLogDebug(@"Error when setting an event's event_code: %@", error); + return; + } + + [bytesDict removeObjectForKey:GDTCCTEventCodeInfo]; + self.customBytes = [NSJSONSerialization dataWithJSONObject:bytesDict options:0 error:&error]; + if (error) { + self.customBytes = nil; + GDTCORLogDebug(@"Error when setting an event's event_code: %@", error); + return; + } + return; + } + + @try { + NSMutableDictionary *bytesDict; + NSError *error; + if (self.customBytes) { + bytesDict = [[NSJSONSerialization JSONObjectWithData:self.customBytes options:0 + error:&error] mutableCopy]; + if (error) { + GDTCORLogDebug(@"Error when setting an event's event_code: %@", error); + return; + } + } else { + bytesDict = [[NSMutableDictionary alloc] init]; + } + + NSString *eventCodeString = [eventCode stringValue]; + if (eventCodeString == nil) { + return; + } + + [bytesDict setObject:eventCodeString forKey:GDTCCTEventCodeInfo]; + + self.customBytes = [NSJSONSerialization dataWithJSONObject:bytesDict options:0 error:&error]; + if (error) { + self.customBytes = nil; + GDTCORLogDebug(@"Error when setting an event's network_connection_info: %@", error); + return; + } + + } @catch (NSException *exception) { + GDTCORLogDebug(@"Error when getting an event's network_connection_info: %@", exception); + } +} + +@end diff --git a/ios/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCOREvent+NetworkConnectionInfo.m b/ios/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCOREvent+NetworkConnectionInfo.m deleted file mode 100644 index 4337f43c8..000000000 --- a/ios/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCOREvent+NetworkConnectionInfo.m +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2020 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "GDTCCTLibrary/Private/GDTCOREvent+NetworkConnectionInfo.h" - -#import <GoogleDataTransport/GDTCORConsoleLogger.h> - -NSString *const GDTCCTNeedsNetworkConnectionInfo = @"needs_network_connection_info"; - -NSString *const GDTCCTNetworkConnectionInfo = @"network_connection_info"; - -@implementation GDTCOREvent (CCTNetworkConnectionInfo) - -- (void)setNeedsNetworkConnectionInfoPopulated:(BOOL)needsNetworkConnectionInfoPopulated { - if (!needsNetworkConnectionInfoPopulated) { - self.customBytes = nil; - } else { - @try { - NSError *error; - self.customBytes = - [NSJSONSerialization dataWithJSONObject:@{GDTCCTNeedsNetworkConnectionInfo : @YES} - options:0 - error:&error]; - } @catch (NSException *exception) { - GDTCORLogDebug(@"Error when setting the event for needs_network_connection_info: %@", - exception); - } - } -} - -- (BOOL)needsNetworkConnectionInfoPopulated { - if (self.customBytes) { - @try { - NSError *error; - NSDictionary *bytesDict = [NSJSONSerialization JSONObjectWithData:self.customBytes - options:0 - error:&error]; - return bytesDict && !error && [bytesDict[GDTCCTNeedsNetworkConnectionInfo] boolValue]; - } @catch (NSException *exception) { - GDTCORLogDebug(@"Error when checking the event for needs_network_connection_info: %@", - exception); - } - } - return NO; -} - -- (void)setNetworkConnectionInfoData:(NSData *)networkConnectionInfoData { - @try { - NSError *error; - NSString *dataString = [networkConnectionInfoData base64EncodedStringWithOptions:0]; - if (dataString) { - self.customBytes = - [NSJSONSerialization dataWithJSONObject:@{GDTCCTNetworkConnectionInfo : dataString} - options:0 - error:&error]; - if (error) { - self.customBytes = nil; - GDTCORLogDebug(@"Error when setting an event's network_connection_info: %@", error); - } - } - } @catch (NSException *exception) { - GDTCORLogDebug(@"Error when setting an event's network_connection_info: %@", exception); - } -} - -- (nullable NSData *)networkConnectionInfoData { - if (self.customBytes) { - @try { - NSError *error; - NSDictionary *bytesDict = [NSJSONSerialization JSONObjectWithData:self.customBytes - options:0 - error:&error]; - NSString *base64Data = bytesDict[GDTCCTNetworkConnectionInfo]; - NSData *networkConnectionInfoData = [[NSData alloc] initWithBase64EncodedString:base64Data - options:0]; - if (error) { - GDTCORLogDebug(@"Error when getting an event's network_connection_info: %@", error); - return nil; - } else { - return networkConnectionInfoData; - } - } @catch (NSException *exception) { - GDTCORLogDebug(@"Error when getting an event's network_connection_info: %@", exception); - } - } - return nil; -} - -@end diff --git a/ios/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCOREvent+NetworkConnectionInfo.h b/ios/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h similarity index 90% rename from ios/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCOREvent+NetworkConnectionInfo.h rename to ios/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h index 1c1512d50..e3a0b0ce4 100644 --- a/ios/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCOREvent+NetworkConnectionInfo.h +++ b/ios/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h @@ -30,7 +30,7 @@ FOUNDATION_EXPORT NSString *const GDTCCTNetworkConnectionInfo; /** A category that uses the customBytes property of a GDTCOREvent to store network connection info. */ -@interface GDTCOREvent (CCTNetworkConnectionInfo) +@interface GDTCOREvent (GDTCCTSupport) /** If YES, needs the network connection info field set during prioritization. * @note Uses the GDTCOREvent customBytes property. @@ -42,6 +42,10 @@ FOUNDATION_EXPORT NSString *const GDTCCTNetworkConnectionInfo; */ @property(nullable, nonatomic) NSData *networkConnectionInfoData; +/** Code that identifies the event to be sent to the CCT backend. + */ +@property(nullable, nonatomic) NSNumber *eventCode; + @end NS_ASSUME_NONNULL_END diff --git a/ios/Pods/GoogleDataTransportCCTSupport/README.md b/ios/Pods/GoogleDataTransportCCTSupport/README.md index 1747cca7a..d778205ff 100644 --- a/ios/Pods/GoogleDataTransportCCTSupport/README.md +++ b/ios/Pods/GoogleDataTransportCCTSupport/README.md @@ -2,14 +2,20 @@ [![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) [![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![Actions Status][gh-abtesting-badge]][gh-actions] [![Actions Status][gh-auth-badge]][gh-actions] [![Actions Status][gh-core-badge]][gh-actions] +[![Actions Status][gh-crashlytics-badge]][gh-actions] +[![Actions Status][gh-database-badge]][gh-actions] [![Actions Status][gh-datatransport-badge]][gh-actions] [![Actions Status][gh-dynamiclinks-badge]][gh-actions] [![Actions Status][gh-firebasepod-badge]][gh-actions] [![Actions Status][gh-firestore-badge]][gh-actions] +[![Actions Status][gh-functions-badge]][gh-actions] +[![Actions Status][gh-inappmessaging-badge]][gh-actions] [![Actions Status][gh-interop-badge]][gh-actions] [![Actions Status][gh-messaging-badge]][gh-actions] +[![Actions Status][gh-remoteconfig-badge]][gh-actions] [![Actions Status][gh-storage-badge]][gh-actions] [![Actions Status][gh-symbolcollision-badge]][gh-actions] [![Actions Status][gh-zip-badge]][gh-actions] @@ -92,7 +98,7 @@ Instructions for installing binary frameworks via To develop Firebase software in this repository, ensure that you have at least the following software: - * Xcode 10.1 (or later) + * Xcode 10.3 (or later) * CocoaPods 1.7.2 (or later) * [CocoaPods generate](https://github.com/square/cocoapods-generate) @@ -123,6 +129,10 @@ Firestore has a self contained Xcode project. See See [AddNewPod.md](AddNewPod.md). +### Managing Headers and Imports + +See [HeadersImports.md](HeadersImports.md). + ### Code Formatting To ensure that the code is formatted consistently, run the script @@ -185,8 +195,16 @@ building and running the FirebaseAuth pod along with various samples and tests. ### Firebase Database -To run the Database Integration tests, make your database authentication rules -[public](https://firebase.google.com/docs/database/security/quickstart). +The Firebase Database Integration tests can be run against a locally running Database Emulator +or against a production instance. + +To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before +running the integration test. + +To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to +`Example/Database/App/GoogleService-Info.plist`. Your Security Rule must be set to +[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are +running. ### Firebase Storage @@ -274,14 +292,20 @@ Your use of Firebase is governed by the [Terms of Service for Firebase Services](https://firebase.google.com/terms/). [gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg [gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg [gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg +[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg [gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg [gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg [gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg [gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg +[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg +[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg [gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg [gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg +[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg [gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg [gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg [gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m b/ios/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m index 173a776dc..ca551aca2 100644 --- a/ios/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m @@ -14,12 +14,12 @@ #import <TargetConditionals.h> -#import <GoogleUtilities/GULAppDelegateSwizzler.h> -#import <GoogleUtilities/GULAppEnvironmentUtil.h> -#import <GoogleUtilities/GULLogger.h> -#import <GoogleUtilities/GULMutableDictionary.h> #import "GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h" +#import "GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h" #import "GoogleUtilities/Common/GULLoggerCodes.h" +#import "GoogleUtilities/Environment/Private/GULAppEnvironmentUtil.h" +#import "GoogleUtilities/Logger/Private/GULLogger.h" +#import "GoogleUtilities/Network/Private/GULMutableDictionary.h" #import <objc/runtime.h> @@ -37,12 +37,8 @@ typedef void (*GULRealHandleEventsForBackgroundURLSessionIMP)( id, SEL, GULApplication *, NSString *, void (^)()); #pragma clang diagnostic pop -// This is needed to for the library to be warning free on iOS versions < 8. -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability" typedef BOOL (*GULRealContinueUserActivityIMP)( id, SEL, GULApplication *, NSUserActivity *, void (^)(NSArray *restorableObjects)); -#pragma clang diagnostic pop typedef void (*GULRealDidRegisterForRemoteNotificationsIMP)(id, SEL, GULApplication *, NSData *); @@ -53,14 +49,10 @@ typedef void (*GULRealDidFailToRegisterForRemoteNotificationsIMP)(id, typedef void (*GULRealDidReceiveRemoteNotificationIMP)(id, SEL, GULApplication *, NSDictionary *); -// TODO: Since we don't support iOS 7 anymore, see if we can remove the check below. -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability" +#if !TARGET_OS_WATCH && !TARGET_OS_OSX typedef void (*GULRealDidReceiveRemoteNotificationWithCompletionIMP)( id, SEL, GULApplication *, NSDictionary *, void (^)(UIBackgroundFetchResult)); -#pragma clang diagnostic pop -#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH +#endif // !TARGET_OS_WATCH && !TARGET_OS_OSX typedef void (^GULAppDelegateInterceptorCallback)(id<GULApplicationDelegate>); @@ -519,28 +511,26 @@ static dispatch_once_t sProxyAppDelegateRemoteNotificationOnceToken; storeDestinationImplementationTo:realImplementationsBySelector]; // For application:didReceiveRemoteNotification:fetchCompletionHandler: -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH - if ([GULAppEnvironmentUtil isIOS7OrHigher]) { - SEL didReceiveRemoteNotificationWithCompletionSEL = - NSSelectorFromString(kGULDidReceiveRemoteNotificationWithCompletionSEL); - SEL didReceiveRemoteNotificationWithCompletionDonorSEL = - @selector(application:donor_didReceiveRemoteNotification:fetchCompletionHandler:); - if ([appDelegate respondsToSelector:didReceiveRemoteNotificationWithCompletionSEL]) { - // Only add the application:didReceiveRemoteNotification:fetchCompletionHandler: method if - // the original AppDelegate implements it. - // This fixes a bug if an app only implements application:didReceiveRemoteNotification: - // (if we add the method with completion, iOS sees that one exists and does not call - // the method without the completion, which in this case is the only one the app implements). +#if !TARGET_OS_WATCH && !TARGET_OS_OSX + SEL didReceiveRemoteNotificationWithCompletionSEL = + NSSelectorFromString(kGULDidReceiveRemoteNotificationWithCompletionSEL); + SEL didReceiveRemoteNotificationWithCompletionDonorSEL = + @selector(application:donor_didReceiveRemoteNotification:fetchCompletionHandler:); + if ([appDelegate respondsToSelector:didReceiveRemoteNotificationWithCompletionSEL]) { + // Only add the application:didReceiveRemoteNotification:fetchCompletionHandler: method if + // the original AppDelegate implements it. + // This fixes a bug if an app only implements application:didReceiveRemoteNotification: + // (if we add the method with completion, iOS sees that one exists and does not call + // the method without the completion, which in this case is the only one the app implements). - [self proxyDestinationSelector:didReceiveRemoteNotificationWithCompletionSEL - implementationsFromSourceSelector:didReceiveRemoteNotificationWithCompletionDonorSEL - fromClass:[GULAppDelegateSwizzler class] - toClass:appDelegateSubClass - realClass:realClass - storeDestinationImplementationTo:realImplementationsBySelector]; - } + [self proxyDestinationSelector:didReceiveRemoteNotificationWithCompletionSEL + implementationsFromSourceSelector:didReceiveRemoteNotificationWithCompletionDonorSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; } -#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH +#endif // !TARGET_OS_WATCH && !TARGET_OS_OSX } /// We have to do this to invalidate the cache that caches the original respondsToSelector of @@ -799,9 +789,6 @@ static dispatch_once_t sProxyAppDelegateRemoteNotificationOnceToken; #pragma mark - [Donor Methods] User Activities overridden handler methods -// This is needed to for the library to be warning free on iOS versions < 8. -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability" - (BOOL)application:(GULApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler { @@ -828,7 +815,6 @@ static dispatch_once_t sProxyAppDelegateRemoteNotificationOnceToken; } return returnedValue; } -#pragma clang diagnostic pop #pragma mark - [Donor Methods] Remote Notifications @@ -885,9 +871,7 @@ static dispatch_once_t sProxyAppDelegateRemoteNotificationOnceToken; } } -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability" +#if !TARGET_OS_WATCH && !TARGET_OS_OSX - (void)application:(GULApplication *)application donor_didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { @@ -917,8 +901,7 @@ static dispatch_once_t sProxyAppDelegateRemoteNotificationOnceToken; completionHandler); } } -#pragma clang diagnostic pop -#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH +#endif // !TARGET_OS_WATCH && !TARGET_OS_OSX - (void)application:(GULApplication *)application donor_didReceiveRemoteNotification:(NSDictionary *)userInfo { diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h b/ios/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h index d7ebd8680..eb3abb1e7 100644 --- a/ios/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h @@ -15,8 +15,8 @@ */ #import <Foundation/Foundation.h> -#import <GoogleUtilities/GULAppDelegateSwizzler.h> -#import <GoogleUtilities/GULMutableDictionary.h> +#import "GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h" +#import "GoogleUtilities/Network/Private/GULMutableDictionary.h" @class GULApplication; diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h b/ios/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h index c1b2d6e1d..b15925f44 100644 --- a/ios/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h @@ -16,7 +16,11 @@ #import <Foundation/Foundation.h> +#if SWIFT_PACKAGE +#import "GoogleUtilities/AppDelegateSwizzler/Private/GULApplication.h" +#else #import <GoogleUtilities/GULApplication.h> +#endif NS_ASSUME_NONNULL_BEGIN diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/GULHeartbeatDateStorage.m b/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/GULHeartbeatDateStorage.m index 483c85903..b49dbf321 100644 --- a/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/GULHeartbeatDateStorage.m +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/GULHeartbeatDateStorage.m @@ -14,16 +14,20 @@ * limitations under the License. */ -#import <GoogleUtilities/GULHeartbeatDateStorage.h> -#import <GoogleUtilities/GULSecureCoding.h> +#import "GoogleUtilities/Environment/Private/GULHeartbeatDateStorage.h" +#import "GoogleUtilities/Environment/Private/GULSecureCoding.h" @interface GULHeartbeatDateStorage () /** The storage to store the date of the last sent heartbeat. */ @property(nonatomic, readonly) NSFileCoordinator *fileCoordinator; +/** The name of the file that stores heartbeat information. */ +@property(nonatomic, readonly) NSString *fileName; @end @implementation GULHeartbeatDateStorage +@synthesize fileURL = _fileURL; + - (instancetype)initWithFileName:(NSString *)fileName { if (fileName == nil) { return nil; @@ -32,13 +36,23 @@ self = [super init]; if (self) { _fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil]; - NSURL *directoryURL = [[self class] directoryPathURL]; - [[self class] checkAndCreateDirectory:directoryURL fileCoordinator:_fileCoordinator]; - _fileURL = [directoryURL URLByAppendingPathComponent:fileName]; + _fileName = fileName; } return self; } +/** Lazy getter for fileURL + * @return fileURL where heartbeat information is stored. + */ +- (NSURL *)fileURL { + if (!_fileURL) { + NSURL *directoryURL = [[self class] directoryPathURL]; + [[self class] checkAndCreateDirectory:directoryURL fileCoordinator:_fileCoordinator]; + _fileURL = [directoryURL URLByAppendingPathComponent:_fileName]; + } + return _fileURL; +} + /** Returns the URL path of the Application Support folder. * @return the URL path of Application Support. */ diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/GULSecureCoding.m b/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/GULSecureCoding.m index 25d5d1998..91c4495f4 100644 --- a/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/GULSecureCoding.m +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/GULSecureCoding.m @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#import "GoogleUtilities/Environment/Public/GULSecureCoding.h" +#import "GoogleUtilities/Environment/Private/GULSecureCoding.h" NSString *const kGULSecureCodingError = @"GULSecureCodingError"; diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/Private/GULAppEnvironmentUtil.h b/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/Private/GULAppEnvironmentUtil.h new file mode 100644 index 000000000..2fb162261 --- /dev/null +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/Private/GULAppEnvironmentUtil.h @@ -0,0 +1,47 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +@interface GULAppEnvironmentUtil : NSObject + +/// Indicates whether the app is from Apple Store or not. Returns NO if the app is on simulator, +/// development environment or sideloaded. ++ (BOOL)isFromAppStore; + +/// Indicates whether the app is a Testflight app. Returns YES if the app has sandbox receipt. +/// Returns NO otherwise. ++ (BOOL)isAppStoreReceiptSandbox; + +/// Indicates whether the app is on simulator or not at runtime depending on the device +/// architecture. ++ (BOOL)isSimulator; + +/// The current device model. Returns an empty string if device model cannot be retrieved. ++ (NSString *)deviceModel; + +/// The current operating system version. Returns an empty string if the system version cannot be +/// retrieved. ++ (NSString *)systemVersion; + +/// Indicates whether it is running inside an extension or an app. ++ (BOOL)isAppExtension; + +/// @return Returns @YES when is run on iOS version greater or equal to 7.0 ++ (BOOL)isIOS7OrHigher DEPRECATED_MSG_ATTRIBUTE( + "Always `YES` because only iOS 8 and higher supported. The method will be removed."); + +@end diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/Private/GULHeartbeatDateStorage.h b/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/Private/GULHeartbeatDateStorage.h new file mode 100644 index 000000000..9432dfc04 --- /dev/null +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/Private/GULHeartbeatDateStorage.h @@ -0,0 +1,49 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +/// Stores either a date or a dictionary to a specified file. +@interface GULHeartbeatDateStorage : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +@property(nonatomic, readonly) NSURL *fileURL; + +/** + * Default initializer. + * @param fileName The name of the file to store the date information. + * exist, it will be created if needed. + */ +- (instancetype)initWithFileName:(NSString *)fileName; + +/** + * Reads the date from the specified file for the given tag. + * @return Returns date if exists, otherwise `nil`. + */ +- (nullable NSDate *)heartbeatDateForTag:(NSString *)tag; + +/** + * Saves the date for the specified tag in the specified file. + * @return YES on success, NO otherwise. + */ +- (BOOL)setHearbeatDate:(NSDate *)date forTag:(NSString *)tag; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/Private/GULKeychainStorage.h b/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/Private/GULKeychainStorage.h new file mode 100644 index 000000000..dc01a8368 --- /dev/null +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/Private/GULKeychainStorage.h @@ -0,0 +1,79 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +@class FBLPromise<ValueType>; + +NS_ASSUME_NONNULL_BEGIN + +/// The class provides a convenient abstraction on top of the iOS Keychain API to save data. +@interface GULKeychainStorage : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +/** Initializes the keychain storage with Keychain Service name. + * @param service A Keychain Service name that will be used to store and retrieve objects. See also + * `kSecAttrService`. + */ +- (instancetype)initWithService:(NSString *)service; + +/** + * Get an object by key. + * @param key The key. + * @param objectClass The expected object class required by `NSSecureCoding`. + * @param accessGroup The Keychain Access Group. + * + * @return Returns a promise. It is resolved with an object stored by key if exists. It is resolved + * with `nil` when the object not found. It fails on a Keychain error. + */ +- (FBLPromise<id<NSSecureCoding>> *)getObjectForKey:(NSString *)key + objectClass:(Class)objectClass + accessGroup:(nullable NSString *)accessGroup; + +/** + * Saves the given object by the given key. + * @param object The object to store. + * @param key The key to store the object. If there is an existing object by the key, it will be + * overridden. + * @param accessGroup The Keychain Access Group. + * + * @return Returns which is resolved with `[NSNull null]` on success. + */ +- (FBLPromise<NSNull *> *)setObject:(id<NSSecureCoding>)object + forKey:(NSString *)key + accessGroup:(nullable NSString *)accessGroup; + +/** + * Removes the object by the given key. + * @param key The key to store the object. If there is an existing object by the key, it will be + * overridden. + * @param accessGroup The Keychain Access Group. + * + * @return Returns which is resolved with `[NSNull null]` on success. + */ +- (FBLPromise<NSNull *> *)removeObjectForKey:(NSString *)key + accessGroup:(nullable NSString *)accessGroup; + +#if TARGET_OS_OSX +/// If not `nil`, then only this keychain will be used to save and read data (see +/// `kSecMatchSearchList` and `kSecUseKeychain`. It is mostly intended to be used by unit tests. +@property(nonatomic, nullable) SecKeychainRef keychainRef; +#endif // TARGET_OSX + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/Private/GULKeychainUtils.h b/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/Private/GULKeychainUtils.h new file mode 100644 index 000000000..de4bef2fb --- /dev/null +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/Private/GULKeychainUtils.h @@ -0,0 +1,61 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +FOUNDATION_EXPORT NSString *const kGULKeychainUtilsErrorDomain; + +/// Helper functions to access Keychain. +@interface GULKeychainUtils : NSObject + +/** Fetches a keychain item data matching to the provided query. + * @param query A dictionary with Keychain query parameters. See docs for `SecItemCopyMatching` for + * details. + * @param outError A pointer to `NSError` instance or `NULL`. The instance at `outError` will be + * assigned with an error if there is. + * @returns Data for the first Keychain Item matching the provided query or `nil` if there is not + * such an item (`outError` will be `nil` in this case) or an error occurred. + */ ++ (nullable NSData *)getItemWithQuery:(NSDictionary *)query + error:(NSError *_Nullable *_Nullable)outError; + +/** Stores data to a Keychain Item matching to the provided query. An existing Keychain Item + * matching the query parameters will be updated or a new will be created. + * @param item A Keychain Item data to store. + * @param query A dictionary with Keychain query parameters. See docs for `SecItemAdd` and + * `SecItemUpdate` for details. + * @param outError A pointer to `NSError` instance or `NULL`. The instance at `outError` will be + * assigned with an error if there is. + * @returns `YES` when data was successfully stored, `NO` otherwise. + */ ++ (BOOL)setItem:(NSData *)item + withQuery:(NSDictionary *)query + error:(NSError *_Nullable *_Nullable)outError; + +/** Removes a Keychain Item matching to the provided query. + * @param query A dictionary with Keychain query parameters. See docs for `SecItemDelete` for + * details. + * @param outError A pointer to `NSError` instance or `NULL`. The instance at `outError` will be + * assigned with an error if there is. + * @returns `YES` if the item was removed successfully or doesn't exist, `NO` otherwise. + */ ++ (BOOL)removeItemWithQuery:(NSDictionary *)query error:(NSError *_Nullable *_Nullable)outError; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/Private/GULSecureCoding.h b/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/Private/GULSecureCoding.h new file mode 100644 index 000000000..8484b3953 --- /dev/null +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/Private/GULSecureCoding.h @@ -0,0 +1,36 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +/** The class wraps `NSKeyedArchiver` and `NSKeyedUnarchiver` API to provide a unified secure coding + * methods for iOS versions before and after 11. + */ +@interface GULSecureCoding : NSObject + ++ (nullable id)unarchivedObjectOfClasses:(NSSet<Class> *)classes + fromData:(NSData *)data + error:(NSError **)outError; + ++ (nullable id)unarchivedObjectOfClass:(Class)class + fromData:(NSData *)data + error:(NSError **)outError; + ++ (nullable NSData *)archivedDataWithRootObject:(id<NSCoding>)object error:(NSError **)outError; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/SecureStorage/GULKeychainStorage.m b/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/SecureStorage/GULKeychainStorage.m index 3777724bd..b6ef0cbd6 100644 --- a/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/SecureStorage/GULKeychainStorage.m +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/SecureStorage/GULKeychainStorage.m @@ -14,7 +14,7 @@ * limitations under the License. */ -#import <GoogleUtilities/GULKeychainStorage.h> +#import "GoogleUtilities/Environment/Private/GULKeychainStorage.h" #import <Security/Security.h> #if __has_include(<FBLPromises/FBLPromises.h>) @@ -23,8 +23,8 @@ #import "FBLPromises.h" #endif -#import <GoogleUtilities/GULKeychainUtils.h> -#import <GoogleUtilities/GULSecureCoding.h> +#import "GoogleUtilities/Environment/Private/GULKeychainUtils.h" +#import "GoogleUtilities/Environment/Private/GULSecureCoding.h" @interface GULKeychainStorage () @property(nonatomic, readonly) dispatch_queue_t keychainQueue; diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/SecureStorage/GULKeychainUtils.m b/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/SecureStorage/GULKeychainUtils.m index 673b6c4f9..ba8731a57 100644 --- a/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/SecureStorage/GULKeychainUtils.m +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/SecureStorage/GULKeychainUtils.m @@ -14,7 +14,7 @@ * limitations under the License. */ -#import <GoogleUtilities/GULKeychainUtils.h> +#import "GoogleUtilities/Environment/Private/GULKeychainUtils.h" NSString *const kGULKeychainUtilsErrorDomain = @"com.gul.keychain.ErrorDomain"; diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.m b/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.m index 8b1ac6ab0..924b642ac 100644 --- a/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.m +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.m @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#import "GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h" +#import "GoogleUtilities/Environment/Private/GULAppEnvironmentUtil.h" #import <Foundation/Foundation.h> #import <dlfcn.h> @@ -187,17 +187,10 @@ static BOOL HasEmbeddedMobileProvision() { ![enableSandboxCheck boolValue]) { return NO; } -// The #else is for pre Xcode 9 where @available is not yet implemented. -#if __has_builtin(__builtin_available) - if (@available(iOS 7.0, *)) { -#else - if ([[UIDevice currentDevice].systemVersion integerValue] >= 7) { -#endif - NSURL *appStoreReceiptURL = [NSBundle mainBundle].appStoreReceiptURL; - NSString *appStoreReceiptFileName = appStoreReceiptURL.lastPathComponent; - return [appStoreReceiptFileName isEqualToString:kFIRAIdentitySandboxReceiptFileName]; - } - return NO; + + NSURL *appStoreReceiptURL = [NSBundle mainBundle].appStoreReceiptURL; + NSString *appStoreReceiptFileName = appStoreReceiptURL.lastPathComponent; + return [appStoreReceiptFileName isEqualToString:kFIRAIdentitySandboxReceiptFileName]; } + (BOOL)isSimulator { @@ -253,15 +246,7 @@ static BOOL HasEmbeddedMobileProvision() { } + (BOOL)isIOS7OrHigher { -#if __has_builtin(__builtin_available) - if (@available(iOS 7.0, *)) { -#else - if ([[UIDevice currentDevice].systemVersion integerValue] >= 7) { -#endif - return YES; - } - - return NO; + return YES; } @end diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Logger/GULLogger.m b/ios/Pods/GoogleUtilities/GoogleUtilities/Logger/GULLogger.m index 0a512da60..832435352 100644 --- a/ios/Pods/GoogleUtilities/GoogleUtilities/Logger/GULLogger.m +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/Logger/GULLogger.m @@ -12,12 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. +#if SWIFT_PACKAGE +// Need to import the public header here, since the module won't exist yet. +// Restructure the GULLogger headers for Firebase 7. +#import "GoogleUtilities/Logger/Public/GULLoggerLevel.h" +#endif + #import "GoogleUtilities/Logger/Private/GULLogger.h" #include <asl.h> -#import <GoogleUtilities/GULAppEnvironmentUtil.h> -#import <GoogleUtilities/GULLoggerLevel.h> +#import "GoogleUtilities/Environment/Private/GULAppEnvironmentUtil.h" +#import "GoogleUtilities/Logger/Public/GULLoggerLevel.h" /// ASL client facility name used by GULLogger. const char *kGULLoggerASLClientFacilityName = "com.google.utilities.logger"; diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Logger/Private/GULLogger.h b/ios/Pods/GoogleUtilities/GoogleUtilities/Logger/Private/GULLogger.h index ff4257686..1146ee238 100644 --- a/ios/Pods/GoogleUtilities/GoogleUtilities/Logger/Private/GULLogger.h +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/Logger/Private/GULLogger.h @@ -16,7 +16,11 @@ #import <Foundation/Foundation.h> +#if SWIFT_PACKAGE +@import GoogleUtilities_Logger; +#else #import <GoogleUtilities/GULLoggerLevel.h> +#endif NS_ASSUME_NONNULL_BEGIN diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/GULSwizzler.m b/ios/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/GULSwizzler.m index 27d48bbf0..040da2688 100644 --- a/ios/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/GULSwizzler.m +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/GULSwizzler.m @@ -17,8 +17,8 @@ #import <objc/runtime.h> #ifdef DEBUG -#import <GoogleUtilities/GULLogger.h> #import "GoogleUtilities/Common/GULLoggerCodes.h" +#import "GoogleUtilities/Logger/Private/GULLogger.h" static GULLoggerService kGULLoggerSwizzler = @"[GoogleUtilities/MethodSwizzler]"; #endif diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.m b/ios/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.m index 5a77bb8f5..5eb638d6b 100644 --- a/ios/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.m +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.m @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#import "GoogleUtilities/NSData+zlib/GULNSData+zlib.h" +#import "GoogleUtilities/NSData+zlib/Public/GULNSData+zlib.h" #import <zlib.h> diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/Private/GULNSDataInternal.h b/ios/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/Private/GULNSDataInternal.h new file mode 100644 index 000000000..903589d5e --- /dev/null +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/Private/GULNSDataInternal.h @@ -0,0 +1,22 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// An umbrella header, for any other libraries in this repo to access Firebase Public and Private +// headers. Any package manager complexity should be handled here. + +#if SWIFT_PACKAGE +@import GoogleUtilities_NSData; +#else +#import <GoogleUtilities/GULNSData+zlib.h> +#endif diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.h b/ios/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/Public/GULNSData+zlib.h similarity index 100% rename from ios/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.h rename to ios/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/Public/GULNSData+zlib.h diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetwork.m b/ios/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetwork.m index 9d78e0ef7..5b7d7e37b 100644 --- a/ios/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetwork.m +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetwork.m @@ -15,11 +15,11 @@ #import "GoogleUtilities/Network/Private/GULNetwork.h" #import "GoogleUtilities/Network/Private/GULNetworkMessageCode.h" -#import <GoogleUtilities/GULLogger.h> -#import <GoogleUtilities/GULNSData+zlib.h> -#import <GoogleUtilities/GULReachabilityChecker.h> +#import "GoogleUtilities/Logger/Private/GULLogger.h" +#import "GoogleUtilities/NSData+zlib/Private/GULNSDataInternal.h" #import "GoogleUtilities/Network/Private/GULMutableDictionary.h" #import "GoogleUtilities/Network/Private/GULNetworkConstants.h" +#import "GoogleUtilities/Reachability/Private/GULReachabilityChecker.h" /// Constant string for request header Content-Encoding. static NSString *const kGULNetworkContentCompressionKey = @"Content-Encoding"; diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkURLSession.m b/ios/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkURLSession.m index df8bf4601..6cece0467 100644 --- a/ios/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkURLSession.m +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkURLSession.m @@ -16,7 +16,7 @@ #import "GoogleUtilities/Network/Private/GULNetworkURLSession.h" -#import <GoogleUtilities/GULLogger.h> +#import "GoogleUtilities/Logger/Private/GULLogger.h" #import "GoogleUtilities/Network/Private/GULMutableDictionary.h" #import "GoogleUtilities/Network/Private/GULNetworkConstants.h" #import "GoogleUtilities/Network/Private/GULNetworkMessageCode.h" diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetwork.h b/ios/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetwork.h index 0e75ae5d7..646cb4406 100644 --- a/ios/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetwork.h +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetwork.h @@ -16,9 +16,9 @@ #import <Foundation/Foundation.h> -#import "GULNetworkConstants.h" -#import "GULNetworkLoggerProtocol.h" -#import "GULNetworkURLSession.h" +#import "GoogleUtilities/Network/Private/GULNetworkConstants.h" +#import "GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h" +#import "GoogleUtilities/Network/Private/GULNetworkURLSession.h" /// Delegate protocol for GULNetwork events. @protocol GULNetworkReachabilityDelegate diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkConstants.h b/ios/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkConstants.h index 44d440b99..c73965f98 100644 --- a/ios/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkConstants.h +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkConstants.h @@ -15,7 +15,7 @@ */ #import <Foundation/Foundation.h> -#import <GoogleUtilities/GULLogger.h> +#import "GoogleUtilities/Logger/Private/GULLogger.h" /// Error codes in Firebase Network error domain. /// Note: these error codes should never change. It would make it harder to decode the errors if diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h b/ios/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h index f1be5906f..b713e4a8f 100644 --- a/ios/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h @@ -16,9 +16,9 @@ #import <Foundation/Foundation.h> -#import <GoogleUtilities/GULLoggerLevel.h> +#import "GoogleUtilities/Logger/Private/GULLogger.h" -#import "GULNetworkMessageCode.h" +#import "GoogleUtilities/Network/Private/GULNetworkMessageCode.h" /// The log levels used by GULNetworkLogger. typedef NS_ENUM(NSInteger, GULNetworkLogLevel) { diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkURLSession.h b/ios/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkURLSession.h index 3f9f7f9e1..b4fa97091 100644 --- a/ios/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkURLSession.h +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkURLSession.h @@ -16,7 +16,7 @@ #import <Foundation/Foundation.h> -#import "GULNetworkLoggerProtocol.h" +#import "GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h" NS_ASSUME_NONNULL_BEGIN diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h b/ios/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h index 8aabc8a12..5a54e4420 100644 --- a/ios/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h @@ -14,7 +14,7 @@ * limitations under the License. */ -#import <GoogleUtilities/GULReachabilityChecker.h> +#import "GoogleUtilities/Reachability/Private/GULReachabilityChecker.h" #if !TARGET_OS_WATCH typedef SCNetworkReachabilityRef (*GULReachabilityCreateWithNameFn)(CFAllocatorRef allocator, const char *host); diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker.m b/ios/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker.m index a334c1a0b..8cbe609de 100644 --- a/ios/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker.m +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker.m @@ -18,8 +18,8 @@ #import "GoogleUtilities/Reachability/Private/GULReachabilityChecker.h" #import "GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h" -#import <GoogleUtilities/GULLogger.h> -#import <GoogleUtilities/GULReachabilityChecker.h> +#import "GoogleUtilities/Logger/Private/GULLogger.h" +#import "GoogleUtilities/Reachability/Private/GULReachabilityChecker.h" static GULLoggerService kGULLoggerReachability = @"[GULReachability]"; #if !TARGET_OS_WATCH diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/GULSceneDelegateSwizzler.m b/ios/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/GULSceneDelegateSwizzler.m index b80e2aff1..134caa98d 100644 --- a/ios/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/GULSceneDelegateSwizzler.m +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/GULSceneDelegateSwizzler.m @@ -12,15 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -#import "TargetConditionals.h" +#import <TargetConditionals.h> -#import <GoogleUtilities/GULAppDelegateSwizzler.h> -#import <GoogleUtilities/GULAppEnvironmentUtil.h> -#import <GoogleUtilities/GULLogger.h> -#import <GoogleUtilities/GULMutableDictionary.h> -#import <GoogleUtilities/GULSceneDelegateSwizzler.h> +#import "GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h" #import "GoogleUtilities/Common/GULLoggerCodes.h" +#import "GoogleUtilities/Environment/Private/GULAppEnvironmentUtil.h" +#import "GoogleUtilities/Logger/Private/GULLogger.h" +#import "GoogleUtilities/Network/Private/GULMutableDictionary.h" #import "GoogleUtilities/SceneDelegateSwizzler/Internal/GULSceneDelegateSwizzler_Private.h" +#import "GoogleUtilities/SceneDelegateSwizzler/Private/GULSceneDelegateSwizzler.h" #import <objc/runtime.h> diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/Internal/GULSceneDelegateSwizzler_Private.h b/ios/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/Internal/GULSceneDelegateSwizzler_Private.h index a2439eb30..62f214ab4 100644 --- a/ios/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/Internal/GULSceneDelegateSwizzler_Private.h +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/Internal/GULSceneDelegateSwizzler_Private.h @@ -15,8 +15,8 @@ */ #import <Foundation/Foundation.h> -#import <GoogleUtilities/GULMutableDictionary.h> -#import <GoogleUtilities/GULSceneDelegateSwizzler.h> +#import "GoogleUtilities/Network/Private/GULMutableDictionary.h" +#import "GoogleUtilities/SceneDelegateSwizzler/Private/GULSceneDelegateSwizzler.h" NS_ASSUME_NONNULL_BEGIN diff --git a/ios/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/GULUserDefaults.m b/ios/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/GULUserDefaults.m index 47ac35d64..20fe8eed1 100644 --- a/ios/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/GULUserDefaults.m +++ b/ios/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/GULUserDefaults.m @@ -12,9 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -#import "Private/GULUserDefaults.h" +#import "GoogleUtilities/UserDefaults/Private/GULUserDefaults.h" -#import <GoogleUtilities/GULLogger.h> +#import "GoogleUtilities/Logger/Private/GULLogger.h" NS_ASSUME_NONNULL_BEGIN diff --git a/ios/Pods/GoogleUtilities/README.md b/ios/Pods/GoogleUtilities/README.md index b04a27099..1d9f0f678 100644 --- a/ios/Pods/GoogleUtilities/README.md +++ b/ios/Pods/GoogleUtilities/README.md @@ -1,18 +1,29 @@ -# Firebase iOS Open Source Development - [![Actions Status][gh-auth-badge]][gh-actions] - [![Actions Status][gh-core-badge]][gh-actions] - [![Actions Status][gh-datatransport-badge]][gh-actions] - [![Actions Status][gh-dynamiclinks-badge]][gh-actions] - [![Actions Status][gh-firebasepod-badge]][gh-actions] - [![Actions Status][gh-firestore-badge]][gh-actions] - [![Actions Status][gh-interop-badge]][gh-actions] - [![Actions Status][gh-messaging-badge]][gh-actions] - [![Actions Status][gh-storage-badge]][gh-actions] - [![Actions Status][gh-symbolcollision-badge]][gh-actions] - [![Actions Status][gh-zip-badge]][gh-actions] - [![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) +[![Version](https://img.shields.io/cocoapods/v/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) -This repository contains all Firebase iOS SDK source except FirebaseAnalytics, +[![Actions Status][gh-abtesting-badge]][gh-actions] +[![Actions Status][gh-auth-badge]][gh-actions] +[![Actions Status][gh-core-badge]][gh-actions] +[![Actions Status][gh-crashlytics-badge]][gh-actions] +[![Actions Status][gh-database-badge]][gh-actions] +[![Actions Status][gh-datatransport-badge]][gh-actions] +[![Actions Status][gh-dynamiclinks-badge]][gh-actions] +[![Actions Status][gh-firebasepod-badge]][gh-actions] +[![Actions Status][gh-firestore-badge]][gh-actions] +[![Actions Status][gh-functions-badge]][gh-actions] +[![Actions Status][gh-inappmessaging-badge]][gh-actions] +[![Actions Status][gh-interop-badge]][gh-actions] +[![Actions Status][gh-messaging-badge]][gh-actions] +[![Actions Status][gh-remoteconfig-badge]][gh-actions] +[![Actions Status][gh-storage-badge]][gh-actions] +[![Actions Status][gh-symbolcollision-badge]][gh-actions] +[![Actions Status][gh-zip-badge]][gh-actions] +[![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +# Firebase Apple Open Source Development + +This repository contains all Apple platform Firebase SDK source except FirebaseAnalytics, FirebasePerformance, and FirebaseML. The repository also includes GoogleUtilities source. The @@ -87,7 +98,7 @@ Instructions for installing binary frameworks via To develop Firebase software in this repository, ensure that you have at least the following software: - * Xcode 10.1 (or later) + * Xcode 10.3 (or later) * CocoaPods 1.7.2 (or later) * [CocoaPods generate](https://github.com/square/cocoapods-generate) @@ -118,6 +129,10 @@ Firestore has a self contained Xcode project. See See [AddNewPod.md](AddNewPod.md). +### Managing Headers and Imports + +See [HeadersImports.md](HeadersImports.md). + ### Code Formatting To ensure that the code is formatted consistently, run the script @@ -125,21 +140,13 @@ To ensure that the code is formatted consistently, run the script before creating a PR. Travis will verify that any code changes are done in a style compliant way. Install -`clang-format` and `swiftformat`. -These commands will get the right versions: +`clang-format` and `swiftformat`: ``` -brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c6f1cbd/Formula/clang-format.rb -brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c13eda8/Formula/swiftformat.rb +brew install clang-format +brew install swiftformat ``` -Note: if you already have a newer version of these installed you may need to -`brew switch` to this version. - -To update this section, find the versions of clang-format and swiftformat.rb to -match the versions in the CI failure logs -[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). - ### Running Unit Tests Select a scheme and press Command-u to build a component and run its unit tests. @@ -162,12 +169,7 @@ files without real values, but can be replaced with real plist files. To get you 2. Create a new Firebase project, if you don't already have one 3. For each sample app you want to test, create a new Firebase app with the sample app's bundle identifier (e.g. `com.google.Database-Example`) -4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file -(e.g. in [Example/Database/App/](Example/Database/App/)); - -Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require -special Apple capabilities, and you will have to change the sample app to use a unique bundle -identifier that you can control in your own Apple Developer account. +4. Download the resulting `GoogleService-Info.plist` and add it to the Xcode project. ## Specific Component Instructions See the sections below for any special instructions for those components. @@ -180,8 +182,16 @@ building and running the FirebaseAuth pod along with various samples and tests. ### Firebase Database -To run the Database Integration tests, make your database authentication rules -[public](https://firebase.google.com/docs/database/security/quickstart). +The Firebase Database Integration tests can be run against a locally running Database Emulator +or against a production instance. + +To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before +running the integration test. + +To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to +`FirebaseDatabase/Tests/Resources/GoogleService-Info.plist`. Your Security Rule must be set to +[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are +running. ### Firebase Storage @@ -269,14 +279,20 @@ Your use of Firebase is governed by the [Terms of Service for Firebase Services](https://firebase.google.com/terms/). [gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg [gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg [gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg +[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg [gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg [gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg [gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg [gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg +[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg +[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg [gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg [gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg +[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg [gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg [gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg [gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/ios/Pods/Headers/Private/BugsnagReactNative/BSG_KSMachHeaders.h b/ios/Pods/Headers/Private/BugsnagReactNative/BSG_KSMachHeaders.h new file mode 120000 index 000000000..a488182e4 --- /dev/null +++ b/ios/Pods/Headers/Private/BugsnagReactNative/BSG_KSMachHeaders.h @@ -0,0 +1 @@ +../../../../../node_modules/bugsnag-react-native/cocoa/vendor/bugsnag-cocoa/Source/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSMachHeaders.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/EXFileSystem/EXDownloadDelegate.h b/ios/Pods/Headers/Private/EXFileSystem/EXDownloadDelegate.h deleted file mode 120000 index 0590b2177..000000000 --- a/ios/Pods/Headers/Private/EXFileSystem/EXDownloadDelegate.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/expo-file-system/ios/EXFileSystem/EXDownloadDelegate.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/EXFileSystem/EXResumablesManager.h b/ios/Pods/Headers/Private/EXFileSystem/EXResumablesManager.h new file mode 120000 index 000000000..958b4705a --- /dev/null +++ b/ios/Pods/Headers/Private/EXFileSystem/EXResumablesManager.h @@ -0,0 +1 @@ +../../../../../node_modules/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXResumablesManager.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/EXFileSystem/EXSessionDownloadTaskDelegate.h b/ios/Pods/Headers/Private/EXFileSystem/EXSessionDownloadTaskDelegate.h new file mode 120000 index 000000000..be371eb88 --- /dev/null +++ b/ios/Pods/Headers/Private/EXFileSystem/EXSessionDownloadTaskDelegate.h @@ -0,0 +1 @@ +../../../../../node_modules/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionDownloadTaskDelegate.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/EXFileSystem/EXSessionResumableDownloadTaskDelegate.h b/ios/Pods/Headers/Private/EXFileSystem/EXSessionResumableDownloadTaskDelegate.h new file mode 120000 index 000000000..207a09ba5 --- /dev/null +++ b/ios/Pods/Headers/Private/EXFileSystem/EXSessionResumableDownloadTaskDelegate.h @@ -0,0 +1 @@ +../../../../../node_modules/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionResumableDownloadTaskDelegate.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/EXFileSystem/EXSessionTaskDelegate.h b/ios/Pods/Headers/Private/EXFileSystem/EXSessionTaskDelegate.h new file mode 120000 index 000000000..85cedea35 --- /dev/null +++ b/ios/Pods/Headers/Private/EXFileSystem/EXSessionTaskDelegate.h @@ -0,0 +1 @@ +../../../../../node_modules/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionTaskDelegate.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/EXFileSystem/EXSessionTaskDispatcher.h b/ios/Pods/Headers/Private/EXFileSystem/EXSessionTaskDispatcher.h new file mode 120000 index 000000000..5b5535e13 --- /dev/null +++ b/ios/Pods/Headers/Private/EXFileSystem/EXSessionTaskDispatcher.h @@ -0,0 +1 @@ +../../../../../node_modules/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionTaskDispatcher.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/EXFileSystem/EXSessionUploadTaskDelegate.h b/ios/Pods/Headers/Private/EXFileSystem/EXSessionUploadTaskDelegate.h new file mode 120000 index 000000000..44686858b --- /dev/null +++ b/ios/Pods/Headers/Private/EXFileSystem/EXSessionUploadTaskDelegate.h @@ -0,0 +1 @@ +../../../../../node_modules/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionUploadTaskDelegate.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/EXFileSystem/NSData+EXFileSystem.h b/ios/Pods/Headers/Private/EXFileSystem/NSData+EXFileSystem.h new file mode 120000 index 000000000..a91740920 --- /dev/null +++ b/ios/Pods/Headers/Private/EXFileSystem/NSData+EXFileSystem.h @@ -0,0 +1 @@ +../../../../../node_modules/expo-file-system/ios/EXFileSystem/NSData+EXFileSystem.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/EXPermissions/EXRemoteNotificationPermissionRequester.h b/ios/Pods/Headers/Private/EXPermissions/EXRemoteNotificationPermissionRequester.h deleted file mode 120000 index b78040b03..000000000 --- a/ios/Pods/Headers/Private/EXPermissions/EXRemoteNotificationPermissionRequester.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/expo-permissions/ios/EXPermissions/Requesters/RemoteNotification/EXRemoteNotificationPermissionRequester.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/EXPermissions/EXUserNotificationPermissionRequester.h b/ios/Pods/Headers/Private/EXPermissions/EXUserNotificationPermissionRequester.h deleted file mode 120000 index 0c452886b..000000000 --- a/ios/Pods/Headers/Private/EXPermissions/EXUserNotificationPermissionRequester.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/expo-permissions/ios/EXPermissions/Requesters/UserNotification/EXUserNotificationPermissionRequester.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCore/FIRAnalyticsConfiguration.h b/ios/Pods/Headers/Private/FirebaseCore/FIRAnalyticsConfiguration.h index 9a3893f7f..34a14ebc4 120000 --- a/ios/Pods/Headers/Private/FirebaseCore/FIRAnalyticsConfiguration.h +++ b/ios/Pods/Headers/Private/FirebaseCore/FIRAnalyticsConfiguration.h @@ -1 +1 @@ -../../../FirebaseCore/FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h \ No newline at end of file +../../../FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCore/FIRAppAssociationRegistration.h b/ios/Pods/Headers/Private/FirebaseCore/FIRAppAssociationRegistration.h index 75bf981a3..dba1d4d02 120000 --- a/ios/Pods/Headers/Private/FirebaseCore/FIRAppAssociationRegistration.h +++ b/ios/Pods/Headers/Private/FirebaseCore/FIRAppAssociationRegistration.h @@ -1 +1 @@ -../../../FirebaseCore/FirebaseCore/Sources/Private/FIRAppAssociationRegistration.h \ No newline at end of file +../../../FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCore/FIRComponentContainerInternal.h b/ios/Pods/Headers/Private/FirebaseCore/FIRComponentContainerInternal.h index 5df38379d..942ed8e7d 120000 --- a/ios/Pods/Headers/Private/FirebaseCore/FIRComponentContainerInternal.h +++ b/ios/Pods/Headers/Private/FirebaseCore/FIRComponentContainerInternal.h @@ -1 +1 @@ -../../../FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainerInternal.h \ No newline at end of file +../../../FirebaseCore/FirebaseCore/Sources/FIRComponentContainerInternal.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCore/FIRConfigurationInternal.h b/ios/Pods/Headers/Private/FirebaseCore/FIRConfigurationInternal.h index 7fc6c1df5..3f90fa584 120000 --- a/ios/Pods/Headers/Private/FirebaseCore/FIRConfigurationInternal.h +++ b/ios/Pods/Headers/Private/FirebaseCore/FIRConfigurationInternal.h @@ -1 +1 @@ -../../../FirebaseCore/FirebaseCore/Sources/Private/FIRConfigurationInternal.h \ No newline at end of file +../../../FirebaseCore/FirebaseCore/Sources/FIRConfigurationInternal.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCore/FIRCoreDiagnosticsData.h b/ios/Pods/Headers/Private/FirebaseCore/FIRCoreDiagnosticsData.h new file mode 120000 index 000000000..d4d5527c8 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCore/FIRCoreDiagnosticsData.h @@ -0,0 +1 @@ +../../../FirebaseCore/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCore/FIRCoreDiagnosticsInterop.h b/ios/Pods/Headers/Private/FirebaseCore/FIRCoreDiagnosticsInterop.h new file mode 120000 index 000000000..0a26d95c1 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCore/FIRCoreDiagnosticsInterop.h @@ -0,0 +1 @@ +../../../FirebaseCore/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCore/FIRDiagnosticsData.h b/ios/Pods/Headers/Private/FirebaseCore/FIRDiagnosticsData.h index bd4b38b40..68feda1e2 120000 --- a/ios/Pods/Headers/Private/FirebaseCore/FIRDiagnosticsData.h +++ b/ios/Pods/Headers/Private/FirebaseCore/FIRDiagnosticsData.h @@ -1 +1 @@ -../../../FirebaseCore/FirebaseCore/Sources/Private/FIRDiagnosticsData.h \ No newline at end of file +../../../FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCore/FirebaseCoreInternal.h b/ios/Pods/Headers/Private/FirebaseCore/FirebaseCoreInternal.h new file mode 120000 index 000000000..06b0648ed --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCore/FirebaseCoreInternal.h @@ -0,0 +1 @@ +../../../FirebaseCore/FirebaseCore/Sources/Private/FirebaseCoreInternal.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCoreDiagnostics/FIRCoreDiagnosticsData.h b/ios/Pods/Headers/Private/FirebaseCoreDiagnostics/FIRCoreDiagnosticsData.h new file mode 120000 index 000000000..83f0dd892 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCoreDiagnostics/FIRCoreDiagnosticsData.h @@ -0,0 +1 @@ +../../../FirebaseCoreDiagnostics/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCoreDiagnostics/FIRCoreDiagnosticsInterop.h b/ios/Pods/Headers/Private/FirebaseCoreDiagnostics/FIRCoreDiagnosticsInterop.h new file mode 120000 index 000000000..ed200e50e --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCoreDiagnostics/FIRCoreDiagnosticsInterop.h @@ -0,0 +1 @@ +../../../FirebaseCoreDiagnostics/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsData.h b/ios/Pods/Headers/Private/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsData.h deleted file mode 120000 index ce646ecf1..000000000 --- a/ios/Pods/Headers/Private/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsData.h +++ /dev/null @@ -1 +0,0 @@ -../../../FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsInterop.h b/ios/Pods/Headers/Private/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsInterop.h deleted file mode 120000 index 07d83d70f..000000000 --- a/ios/Pods/Headers/Private/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsInterop.h +++ /dev/null @@ -1 +0,0 @@ -../../../FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRAEvent+Internal.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRAEvent+Internal.h new file mode 120000 index 000000000..440805ba3 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRAEvent+Internal.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent+Internal.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRAEvent.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRAEvent.h new file mode 120000 index 000000000..817738eec --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRAEvent.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRAValue.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRAValue.h new file mode 120000 index 000000000..11fca850a --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRAValue.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAValue.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRAnalyticsInterop.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRAnalyticsInterop.h new file mode 120000 index 000000000..b24d8f41a --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRAnalyticsInterop.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Interop/Analytics/Public/FIRAnalyticsInterop.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRAnalyticsInteropListener.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRAnalyticsInteropListener.h new file mode 120000 index 000000000..5da7b2a26 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRAnalyticsInteropListener.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Interop/Analytics/Public/FIRAnalyticsInteropListener.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRAppInternal.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRAppInternal.h new file mode 120000 index 000000000..1348582ef --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRAppInternal.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRAppInternal.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSAllocate.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSAllocate.h new file mode 120000 index 000000000..21dbfbb55 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSAllocate.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSAllocate.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSApplication.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSApplication.h new file mode 120000 index 000000000..92dcbfdce --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSApplication.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSApplication.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSApplicationIdentifierModel.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSApplicationIdentifierModel.h new file mode 120000 index 000000000..80c3efe15 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSApplicationIdentifierModel.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Models/FIRCLSApplicationIdentifierModel.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSAsyncOperation.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSAsyncOperation.h new file mode 120000 index 000000000..1e41fc43f --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSAsyncOperation.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/FIRCLSAsyncOperation.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSAsyncOperation_Private.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSAsyncOperation_Private.h new file mode 120000 index 000000000..a8dfde8aa --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSAsyncOperation_Private.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/FIRCLSAsyncOperation_Private.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSBinaryImage.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSBinaryImage.h new file mode 120000 index 000000000..4a7c4394b --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSBinaryImage.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSBinaryImage.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSByteUtility.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSByteUtility.h new file mode 120000 index 000000000..393b9e7be --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSByteUtility.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Shared/FIRCLSByteUtility.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSCodeMapping.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSCodeMapping.h new file mode 120000 index 000000000..a74ad93ab --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSCodeMapping.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSCodeMapping.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSCompactUnwind.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSCompactUnwind.h new file mode 120000 index 000000000..5de2978ba --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSCompactUnwind.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSCompactUnwind_Private.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSCompactUnwind_Private.h new file mode 120000 index 000000000..61cfefc80 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSCompactUnwind_Private.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind_Private.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSCompoundOperation.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSCompoundOperation.h new file mode 120000 index 000000000..3a9832032 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSCompoundOperation.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSCompoundOperation.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSConstants.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSConstants.h new file mode 120000 index 000000000..d326f47bd --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSConstants.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Shared/FIRCLSConstants.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSContext.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSContext.h new file mode 120000 index 000000000..f6e348390 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSContext.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSContext.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSCrashedMarkerFile.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSCrashedMarkerFile.h new file mode 120000 index 000000000..e8040f63b --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSCrashedMarkerFile.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSCrashedMarkerFile.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDataCollectionArbiter.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDataCollectionArbiter.h new file mode 120000 index 000000000..45c13ad78 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDataCollectionArbiter.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionArbiter.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDataCollectionToken.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDataCollectionToken.h new file mode 120000 index 000000000..9f1a270d9 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDataCollectionToken.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDataParsing.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDataParsing.h new file mode 120000 index 000000000..7c83041c4 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDataParsing.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDataParsing.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDefines.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDefines.h new file mode 120000 index 000000000..f3a95c1cd --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDefines.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDemangleOperation.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDemangleOperation.h new file mode 120000 index 000000000..43575652b --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDemangleOperation.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSDemangleOperation.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDownloadAndSaveSettingsOperation.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDownloadAndSaveSettingsOperation.h new file mode 120000 index 000000000..1ecb6dcd0 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDownloadAndSaveSettingsOperation.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSDownloadAndSaveSettingsOperation.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDwarfExpressionMachine.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDwarfExpressionMachine.h new file mode 120000 index 000000000..7b746b805 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDwarfExpressionMachine.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfExpressionMachine.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDwarfUnwind.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDwarfUnwind.h new file mode 120000 index 000000000..475bfed3d --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDwarfUnwind.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwind.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDwarfUnwindRegisters.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDwarfUnwindRegisters.h new file mode 120000 index 000000000..6e118b248 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSDwarfUnwindRegisters.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwindRegisters.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSException.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSException.h new file mode 120000 index 000000000..e7c3a306a --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSException.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSException.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSExecutionIdentifierModel.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSExecutionIdentifierModel.h new file mode 120000 index 000000000..6a777b2ef --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSExecutionIdentifierModel.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSExecutionIdentifierModel.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSFABAsyncOperation.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSFABAsyncOperation.h new file mode 120000 index 000000000..b824b303e --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSFABAsyncOperation.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSFABAsyncOperation_Private.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSFABAsyncOperation_Private.h new file mode 120000 index 000000000..4681e4135 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSFABAsyncOperation_Private.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation_Private.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSFABHost.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSFABHost.h new file mode 120000 index 000000000..b9b77207a --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSFABHost.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Shared/FIRCLSFABHost.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSFABNetworkClient.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSFABNetworkClient.h new file mode 120000 index 000000000..12c6b79ef --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSFABNetworkClient.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSFABNetworkClient.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSFCRAnalytics.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSFCRAnalytics.h new file mode 120000 index 000000000..f2e5c10bb --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSFCRAnalytics.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFCRAnalytics.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSFeatures.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSFeatures.h new file mode 120000 index 000000000..a2d164354 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSFeatures.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSFile.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSFile.h new file mode 120000 index 000000000..114a6cd72 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSFile.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFile.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSFileManager.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSFileManager.h new file mode 120000 index 000000000..cd2890935 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSFileManager.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSFileManager.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSGlobals.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSGlobals.h new file mode 120000 index 000000000..4246b7285 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSGlobals.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSGlobals.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSHandler.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSHandler.h new file mode 120000 index 000000000..e34385874 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSHandler.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSHandler.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSHost.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSHost.h new file mode 120000 index 000000000..debd7f026 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSHost.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSHost.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSInstallIdentifierModel.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSInstallIdentifierModel.h new file mode 120000 index 000000000..6bfa95edb --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSInstallIdentifierModel.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInstallIdentifierModel.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSInternalLogging.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSInternalLogging.h new file mode 120000 index 000000000..cd6f4c353 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSInternalLogging.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSInternalLogging.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSInternalReport.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSInternalReport.h new file mode 120000 index 000000000..8c34a46c1 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSInternalReport.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSLogger.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSLogger.h new file mode 120000 index 000000000..ae161bb82 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSLogger.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSMachException.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSMachException.h new file mode 120000 index 000000000..b8cec8c00 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSMachException.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSMachException.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSMachO.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSMachO.h new file mode 120000 index 000000000..66c0a3f22 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSMachO.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachO.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSMachOBinary.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSMachOBinary.h new file mode 120000 index 000000000..1ea3db8b5 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSMachOBinary.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOBinary.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSMachOSlice.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSMachOSlice.h new file mode 120000 index 000000000..041dfe461 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSMachOSlice.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOSlice.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSMultipartMimeStreamEncoder.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSMultipartMimeStreamEncoder.h new file mode 120000 index 000000000..0263fad15 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSMultipartMimeStreamEncoder.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSMultipartMimeStreamEncoder.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSNetworkClient.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSNetworkClient.h new file mode 120000 index 000000000..595ea6e7a --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSNetworkClient.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSNetworkClient.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSNetworkOperation.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSNetworkOperation.h new file mode 120000 index 000000000..ff087f76b --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSNetworkOperation.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSNetworkOperation.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSNetworkResponseHandler.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSNetworkResponseHandler.h new file mode 120000 index 000000000..7d49b3549 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSNetworkResponseHandler.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSNetworkResponseHandler.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSOnboardingOperation.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSOnboardingOperation.h new file mode 120000 index 000000000..2e24a4668 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSOnboardingOperation.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSOnboardingOperation.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSOperation.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSOperation.h new file mode 120000 index 000000000..22f800231 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSOperation.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSOperation.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSPackageReportOperation.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSPackageReportOperation.h new file mode 120000 index 000000000..06e846761 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSPackageReportOperation.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSPackageReportOperation.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSProcess.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSProcess.h new file mode 120000 index 000000000..fd795516e --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSProcess.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSProcess.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSProcessReportOperation.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSProcessReportOperation.h new file mode 120000 index 000000000..83c933ed5 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSProcessReportOperation.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSProcessReportOperation.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSProfiling.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSProfiling.h new file mode 120000 index 000000000..cb3b5cdfa --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSProfiling.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSProfiling.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSRecordApplication.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSRecordApplication.h new file mode 120000 index 000000000..aa07bacc3 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSRecordApplication.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordApplication.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSRecordBase.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSRecordBase.h new file mode 120000 index 000000000..00194c885 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSRecordBase.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordBase.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSRecordHost.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSRecordHost.h new file mode 120000 index 000000000..6362fdc92 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSRecordHost.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordHost.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSRecordIdentity.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSRecordIdentity.h new file mode 120000 index 000000000..07310b311 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSRecordIdentity.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordIdentity.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSReport.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSReport.h new file mode 120000 index 000000000..85608d750 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSReport.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSReport.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSReportAdapter.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSReportAdapter.h new file mode 120000 index 000000000..f43ef6625 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSReportAdapter.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSReportAdapter_Private.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSReportAdapter_Private.h new file mode 120000 index 000000000..484e317d9 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSReportAdapter_Private.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter_Private.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSReportManager.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSReportManager.h new file mode 120000 index 000000000..39320f660 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSReportManager.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSReportManager_Private.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSReportManager_Private.h new file mode 120000 index 000000000..d87bd4bae --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSReportManager_Private.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager_Private.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSReportUploader.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSReportUploader.h new file mode 120000 index 000000000..9e06fa642 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSReportUploader.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSReportUploader_Private.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSReportUploader_Private.h new file mode 120000 index 000000000..703b5f164 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSReportUploader_Private.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader_Private.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSReport_Private.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSReport_Private.h new file mode 120000 index 000000000..ba8b360bb --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSReport_Private.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSReport_Private.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSSerializeSymbolicatedFramesOperation.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSSerializeSymbolicatedFramesOperation.h new file mode 120000 index 000000000..beb5e4d81 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSSerializeSymbolicatedFramesOperation.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSerializeSymbolicatedFramesOperation.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSSettings.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSSettings.h new file mode 120000 index 000000000..eafc83aaa --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSSettings.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSettings.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSSettingsOnboardingManager.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSSettingsOnboardingManager.h new file mode 120000 index 000000000..6105933ca --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSSettingsOnboardingManager.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/FIRCLSSettingsOnboardingManager.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSSignal.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSSignal.h new file mode 120000 index 000000000..1eb2adc93 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSSignal.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSSignal.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSSymbolResolver.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSSymbolResolver.h new file mode 120000 index 000000000..5c073a408 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSSymbolResolver.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSymbolResolver.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSSymbolicationOperation.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSSymbolicationOperation.h new file mode 120000 index 000000000..481e6a574 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSSymbolicationOperation.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSymbolicationOperation.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSThreadArrayOperation.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSThreadArrayOperation.h new file mode 120000 index 000000000..eee254626 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSThreadArrayOperation.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSThreadArrayOperation.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSThreadState.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSThreadState.h new file mode 120000 index 000000000..b3867f0e6 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSThreadState.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSThreadState.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLBuilder.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLBuilder.h new file mode 120000 index 000000000..37e79288e --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLBuilder.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSURLBuilder.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSession.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSession.h new file mode 120000 index 000000000..a2367cc91 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSession.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionAvailability.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionAvailability.h new file mode 120000 index 000000000..d1bd25803 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionAvailability.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionConfiguration.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionConfiguration.h new file mode 120000 index 000000000..51dda9584 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionConfiguration.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionConfiguration.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionDataTask.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionDataTask.h new file mode 120000 index 000000000..b5b2b30de --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionDataTask.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionDataTask_PrivateMethods.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionDataTask_PrivateMethods.h new file mode 120000 index 000000000..57847609f --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionDataTask_PrivateMethods.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask_PrivateMethods.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionDownloadTask.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionDownloadTask.h new file mode 120000 index 000000000..0200991c4 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionDownloadTask.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionDownloadTask_PrivateMethods.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionDownloadTask_PrivateMethods.h new file mode 120000 index 000000000..04791981c --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionDownloadTask_PrivateMethods.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask_PrivateMethods.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionTask.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionTask.h new file mode 120000 index 000000000..04122c069 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionTask.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionTask_PrivateMethods.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionTask_PrivateMethods.h new file mode 120000 index 000000000..f8b536b72 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionTask_PrivateMethods.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask_PrivateMethods.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionUploadTask.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionUploadTask.h new file mode 120000 index 000000000..2656f94c9 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSessionUploadTask.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionUploadTask.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSession_PrivateMethods.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSession_PrivateMethods.h new file mode 120000 index 000000000..25a98d761 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSURLSession_PrivateMethods.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession_PrivateMethods.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSUUID.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSUUID.h new file mode 120000 index 000000000..2155797e9 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSUUID.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Shared/FIRCLSUUID.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSUnwind.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSUnwind.h new file mode 120000 index 000000000..e31c432f3 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSUnwind.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSUnwind_arch.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSUnwind_arch.h new file mode 120000 index 000000000..4571097a1 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSUnwind_arch.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_arch.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSUnwind_x86.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSUnwind_x86.h new file mode 120000 index 000000000..405293c49 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSUnwind_x86.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_x86.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSUserDefaults.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSUserDefaults.h new file mode 120000 index 000000000..cffc22d48 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSUserDefaults.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSUserDefaults_private.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSUserDefaults_private.h new file mode 120000 index 000000000..e4266545b --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSUserDefaults_private.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults_private.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSUserLogging.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSUserLogging.h new file mode 120000 index 000000000..94711a81c --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSUserLogging.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSUtility.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSUtility.h new file mode 120000 index 000000000..e84aff0a2 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSUtility.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSdSYM.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSdSYM.h new file mode 120000 index 000000000..872a9216b --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCLSdSYM.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSdSYM.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRComponent.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRComponent.h new file mode 120000 index 000000000..09123adb7 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRComponent.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRComponent.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRComponentContainer.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRComponentContainer.h new file mode 120000 index 000000000..2d5153c16 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRComponentContainer.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRComponentContainer.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRComponentType.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRComponentType.h new file mode 120000 index 000000000..5abcc1c88 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRComponentType.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRComponentType.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCoreDiagnosticsConnector.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCoreDiagnosticsConnector.h new file mode 120000 index 000000000..05dd046c5 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCoreDiagnosticsConnector.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCrashlytics.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCrashlytics.h new file mode 120000 index 000000000..c5678902e --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRCrashlytics.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FIRCrashlytics.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRDependency.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRDependency.h new file mode 120000 index 000000000..71aeae7f9 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRDependency.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRDependency.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRErrorCode.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRErrorCode.h new file mode 120000 index 000000000..120c1b6de --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRErrorCode.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRErrorCode.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRErrors.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRErrors.h new file mode 120000 index 000000000..c310f4767 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRErrors.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRErrors.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRExceptionModel.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRExceptionModel.h new file mode 120000 index 000000000..fc129ad84 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRExceptionModel.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FIRExceptionModel.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRExceptionModel_Private.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRExceptionModel_Private.h new file mode 120000 index 000000000..debb3fb9d --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRExceptionModel_Private.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Private/FIRExceptionModel_Private.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRHeartbeatInfo.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRHeartbeatInfo.h new file mode 120000 index 000000000..f24190c81 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRHeartbeatInfo.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRInteropEventNames.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRInteropEventNames.h new file mode 120000 index 000000000..c93fa7b98 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRInteropEventNames.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Interop/Analytics/Public/FIRInteropEventNames.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRInteropParameterNames.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRInteropParameterNames.h new file mode 120000 index 000000000..94b01ac64 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRInteropParameterNames.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Interop/Analytics/Public/FIRInteropParameterNames.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRLibrary.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRLibrary.h new file mode 120000 index 000000000..9a3caae11 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRLibrary.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRLibrary.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRLogger.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRLogger.h new file mode 120000 index 000000000..9751a067c --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRLogger.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRLogger.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIROptionsInternal.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIROptionsInternal.h new file mode 120000 index 000000000..b219cbe3a --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIROptionsInternal.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/FirebaseCore/Sources/Private/FIROptionsInternal.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRStackFrame.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRStackFrame.h new file mode 120000 index 000000000..9c127465e --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRStackFrame.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FIRStackFrame.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRStackFrame_Private.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRStackFrame_Private.h new file mode 120000 index 000000000..1f246b296 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FIRStackFrame_Private.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Private/FIRStackFrame_Private.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FirebaseCoreInternal.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FirebaseCoreInternal.h new file mode 120000 index 000000000..bf1b43387 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FirebaseCoreInternal.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/FirebaseCore/Sources/Private/FirebaseCoreInternal.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/FirebaseCrashlytics.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/FirebaseCrashlytics.h new file mode 120000 index 000000000..e69eff498 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/FirebaseCrashlytics.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FirebaseCrashlytics.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/crashlytics.nanopb.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/crashlytics.nanopb.h new file mode 120000 index 000000000..2efc6dce8 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/crashlytics.nanopb.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Protogen/nanopb/crashlytics.nanopb.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseCrashlytics/dwarf.h b/ios/Pods/Headers/Private/FirebaseCrashlytics/dwarf.h new file mode 120000 index 000000000..dced99280 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseCrashlytics/dwarf.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/third_party/libunwind/dwarf.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseInstallations/FIRAppInternal.h b/ios/Pods/Headers/Private/FirebaseInstallations/FIRAppInternal.h new file mode 120000 index 000000000..a1ce806c5 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseInstallations/FIRAppInternal.h @@ -0,0 +1 @@ +../../../FirebaseInstallations/FirebaseCore/Sources/Private/FIRAppInternal.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseInstallations/FIRComponent.h b/ios/Pods/Headers/Private/FirebaseInstallations/FIRComponent.h new file mode 120000 index 000000000..07f086937 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseInstallations/FIRComponent.h @@ -0,0 +1 @@ +../../../FirebaseInstallations/FirebaseCore/Sources/Private/FIRComponent.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseInstallations/FIRComponentContainer.h b/ios/Pods/Headers/Private/FirebaseInstallations/FIRComponentContainer.h new file mode 120000 index 000000000..6bd713e4b --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseInstallations/FIRComponentContainer.h @@ -0,0 +1 @@ +../../../FirebaseInstallations/FirebaseCore/Sources/Private/FIRComponentContainer.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseInstallations/FIRComponentType.h b/ios/Pods/Headers/Private/FirebaseInstallations/FIRComponentType.h new file mode 120000 index 000000000..2d893eab6 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseInstallations/FIRComponentType.h @@ -0,0 +1 @@ +../../../FirebaseInstallations/FirebaseCore/Sources/Private/FIRComponentType.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseInstallations/FIRCoreDiagnosticsConnector.h b/ios/Pods/Headers/Private/FirebaseInstallations/FIRCoreDiagnosticsConnector.h new file mode 120000 index 000000000..3acaab7a1 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseInstallations/FIRCoreDiagnosticsConnector.h @@ -0,0 +1 @@ +../../../FirebaseInstallations/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseInstallations/FIRDependency.h b/ios/Pods/Headers/Private/FirebaseInstallations/FIRDependency.h new file mode 120000 index 000000000..a258e8c48 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseInstallations/FIRDependency.h @@ -0,0 +1 @@ +../../../FirebaseInstallations/FirebaseCore/Sources/Private/FIRDependency.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseInstallations/FIRErrorCode.h b/ios/Pods/Headers/Private/FirebaseInstallations/FIRErrorCode.h new file mode 120000 index 000000000..f99c2ceaf --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseInstallations/FIRErrorCode.h @@ -0,0 +1 @@ +../../../FirebaseInstallations/FirebaseCore/Sources/Private/FIRErrorCode.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseInstallations/FIRErrors.h b/ios/Pods/Headers/Private/FirebaseInstallations/FIRErrors.h new file mode 120000 index 000000000..98bb2aca2 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseInstallations/FIRErrors.h @@ -0,0 +1 @@ +../../../FirebaseInstallations/FirebaseCore/Sources/Private/FIRErrors.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseInstallations/FIRHeartbeatInfo.h b/ios/Pods/Headers/Private/FirebaseInstallations/FIRHeartbeatInfo.h new file mode 120000 index 000000000..ca161487c --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseInstallations/FIRHeartbeatInfo.h @@ -0,0 +1 @@ +../../../FirebaseInstallations/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseInstallations/FIRLibrary.h b/ios/Pods/Headers/Private/FirebaseInstallations/FIRLibrary.h new file mode 120000 index 000000000..8162c9342 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseInstallations/FIRLibrary.h @@ -0,0 +1 @@ +../../../FirebaseInstallations/FirebaseCore/Sources/Private/FIRLibrary.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseInstallations/FIRLogger.h b/ios/Pods/Headers/Private/FirebaseInstallations/FIRLogger.h new file mode 120000 index 000000000..10891ee9e --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseInstallations/FIRLogger.h @@ -0,0 +1 @@ +../../../FirebaseInstallations/FirebaseCore/Sources/Private/FIRLogger.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseInstallations/FIROptionsInternal.h b/ios/Pods/Headers/Private/FirebaseInstallations/FIROptionsInternal.h new file mode 120000 index 000000000..3aadbeb39 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseInstallations/FIROptionsInternal.h @@ -0,0 +1 @@ +../../../FirebaseInstallations/FirebaseCore/Sources/Private/FIROptionsInternal.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseInstallations/FirebaseCoreInternal.h b/ios/Pods/Headers/Private/FirebaseInstallations/FirebaseCoreInternal.h new file mode 120000 index 000000000..b5fa72f98 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseInstallations/FirebaseCoreInternal.h @@ -0,0 +1 @@ +../../../FirebaseInstallations/FirebaseCore/Sources/Private/FirebaseCoreInternal.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseInstallations/FirebaseInstallationsInternal.h b/ios/Pods/Headers/Private/FirebaseInstallations/FirebaseInstallationsInternal.h new file mode 120000 index 000000000..f13a6794c --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseInstallations/FirebaseInstallationsInternal.h @@ -0,0 +1 @@ +../../../FirebaseInstallations/FirebaseInstallations/Source/Library/Private/FirebaseInstallationsInternal.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseInstallations/GULAppEnvironmentUtil.h b/ios/Pods/Headers/Private/FirebaseInstallations/GULAppEnvironmentUtil.h new file mode 120000 index 000000000..6197cda60 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseInstallations/GULAppEnvironmentUtil.h @@ -0,0 +1 @@ +../../../FirebaseInstallations/GoogleUtilities/Environment/Private/GULAppEnvironmentUtil.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseInstallations/GULHeartbeatDateStorage.h b/ios/Pods/Headers/Private/FirebaseInstallations/GULHeartbeatDateStorage.h new file mode 120000 index 000000000..48d4be762 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseInstallations/GULHeartbeatDateStorage.h @@ -0,0 +1 @@ +../../../FirebaseInstallations/GoogleUtilities/Environment/Private/GULHeartbeatDateStorage.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseInstallations/GULKeychainStorage.h b/ios/Pods/Headers/Private/FirebaseInstallations/GULKeychainStorage.h new file mode 120000 index 000000000..56718538c --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseInstallations/GULKeychainStorage.h @@ -0,0 +1 @@ +../../../FirebaseInstallations/GoogleUtilities/Environment/Private/GULKeychainStorage.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseInstallations/GULKeychainUtils.h b/ios/Pods/Headers/Private/FirebaseInstallations/GULKeychainUtils.h new file mode 120000 index 000000000..1cf9a3cb6 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseInstallations/GULKeychainUtils.h @@ -0,0 +1 @@ +../../../FirebaseInstallations/GoogleUtilities/Environment/Private/GULKeychainUtils.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseInstallations/GULSecureCoding.h b/ios/Pods/Headers/Private/FirebaseInstallations/GULSecureCoding.h new file mode 120000 index 000000000..5295f6c36 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseInstallations/GULSecureCoding.h @@ -0,0 +1 @@ +../../../FirebaseInstallations/GoogleUtilities/Environment/Private/GULSecureCoding.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/FirebaseInstallations/GULUserDefaults.h b/ios/Pods/Headers/Private/FirebaseInstallations/GULUserDefaults.h new file mode 120000 index 000000000..c55a49752 --- /dev/null +++ b/ios/Pods/Headers/Private/FirebaseInstallations/GULUserDefaults.h @@ -0,0 +1 @@ +../../../FirebaseInstallations/GoogleUtilities/UserDefaults/Private/GULUserDefaults.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/GoogleDataTransportCCTSupport/GDTCOREvent+GDTCCTSupport.h b/ios/Pods/Headers/Private/GoogleDataTransportCCTSupport/GDTCOREvent+GDTCCTSupport.h new file mode 120000 index 000000000..5604da60a --- /dev/null +++ b/ios/Pods/Headers/Private/GoogleDataTransportCCTSupport/GDTCOREvent+GDTCCTSupport.h @@ -0,0 +1 @@ +../../../GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/GoogleDataTransportCCTSupport/GDTCOREvent+NetworkConnectionInfo.h b/ios/Pods/Headers/Private/GoogleDataTransportCCTSupport/GDTCOREvent+NetworkConnectionInfo.h deleted file mode 120000 index ec1ad719c..000000000 --- a/ios/Pods/Headers/Private/GoogleDataTransportCCTSupport/GDTCOREvent+NetworkConnectionInfo.h +++ /dev/null @@ -1 +0,0 @@ -../../../GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCOREvent+NetworkConnectionInfo.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/GoogleUtilities/GULAppEnvironmentUtil.h b/ios/Pods/Headers/Private/GoogleUtilities/GULAppEnvironmentUtil.h index 87f403f09..5fb0b6f03 120000 --- a/ios/Pods/Headers/Private/GoogleUtilities/GULAppEnvironmentUtil.h +++ b/ios/Pods/Headers/Private/GoogleUtilities/GULAppEnvironmentUtil.h @@ -1 +1 @@ -../../../GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h \ No newline at end of file +../../../GoogleUtilities/GoogleUtilities/Environment/Private/GULAppEnvironmentUtil.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/GoogleUtilities/GULHeartbeatDateStorage.h b/ios/Pods/Headers/Private/GoogleUtilities/GULHeartbeatDateStorage.h index 4bd32cf7e..ab7e64ae5 120000 --- a/ios/Pods/Headers/Private/GoogleUtilities/GULHeartbeatDateStorage.h +++ b/ios/Pods/Headers/Private/GoogleUtilities/GULHeartbeatDateStorage.h @@ -1 +1 @@ -../../../GoogleUtilities/GoogleUtilities/Environment/Public/GULHeartbeatDateStorage.h \ No newline at end of file +../../../GoogleUtilities/GoogleUtilities/Environment/Private/GULHeartbeatDateStorage.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/GoogleUtilities/GULKeychainStorage.h b/ios/Pods/Headers/Private/GoogleUtilities/GULKeychainStorage.h index d0de71b6d..31418e459 120000 --- a/ios/Pods/Headers/Private/GoogleUtilities/GULKeychainStorage.h +++ b/ios/Pods/Headers/Private/GoogleUtilities/GULKeychainStorage.h @@ -1 +1 @@ -../../../GoogleUtilities/GoogleUtilities/Environment/Public/GULKeychainStorage.h \ No newline at end of file +../../../GoogleUtilities/GoogleUtilities/Environment/Private/GULKeychainStorage.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/GoogleUtilities/GULKeychainUtils.h b/ios/Pods/Headers/Private/GoogleUtilities/GULKeychainUtils.h index d69319346..a51f38dea 120000 --- a/ios/Pods/Headers/Private/GoogleUtilities/GULKeychainUtils.h +++ b/ios/Pods/Headers/Private/GoogleUtilities/GULKeychainUtils.h @@ -1 +1 @@ -../../../GoogleUtilities/GoogleUtilities/Environment/Public/GULKeychainUtils.h \ No newline at end of file +../../../GoogleUtilities/GoogleUtilities/Environment/Private/GULKeychainUtils.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/GoogleUtilities/GULNSData+zlib.h b/ios/Pods/Headers/Private/GoogleUtilities/GULNSData+zlib.h index ee84730c9..fa7721f67 120000 --- a/ios/Pods/Headers/Private/GoogleUtilities/GULNSData+zlib.h +++ b/ios/Pods/Headers/Private/GoogleUtilities/GULNSData+zlib.h @@ -1 +1 @@ -../../../GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.h \ No newline at end of file +../../../GoogleUtilities/GoogleUtilities/NSData+zlib/Public/GULNSData+zlib.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/GoogleUtilities/GULNSDataInternal.h b/ios/Pods/Headers/Private/GoogleUtilities/GULNSDataInternal.h new file mode 120000 index 000000000..532ce483d --- /dev/null +++ b/ios/Pods/Headers/Private/GoogleUtilities/GULNSDataInternal.h @@ -0,0 +1 @@ +../../../GoogleUtilities/GoogleUtilities/NSData+zlib/Private/GULNSDataInternal.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/GoogleUtilities/GULSecureCoding.h b/ios/Pods/Headers/Private/GoogleUtilities/GULSecureCoding.h index 9cc98ca53..e7508aaff 120000 --- a/ios/Pods/Headers/Private/GoogleUtilities/GULSecureCoding.h +++ b/ios/Pods/Headers/Private/GoogleUtilities/GULSecureCoding.h @@ -1 +1 @@ -../../../GoogleUtilities/GoogleUtilities/Environment/Public/GULSecureCoding.h \ No newline at end of file +../../../GoogleUtilities/GoogleUtilities/Environment/Private/GULSecureCoding.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFBAnalytics/RNFBAnalyticsModule.h b/ios/Pods/Headers/Private/RNFBAnalytics/RNFBAnalyticsModule.h new file mode 120000 index 000000000..0e94f7c05 --- /dev/null +++ b/ios/Pods/Headers/Private/RNFBAnalytics/RNFBAnalyticsModule.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/analytics/ios/RNFBAnalytics/RNFBAnalyticsModule.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFBApp/RCTConvert+FIRApp.h b/ios/Pods/Headers/Private/RNFBApp/RCTConvert+FIRApp.h new file mode 120000 index 000000000..7d72b0274 --- /dev/null +++ b/ios/Pods/Headers/Private/RNFBApp/RCTConvert+FIRApp.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/app/ios/RNFBApp/RCTConvert+FIRApp.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFBApp/RCTConvert+FIROptions.h b/ios/Pods/Headers/Private/RNFBApp/RCTConvert+FIROptions.h new file mode 120000 index 000000000..683731ece --- /dev/null +++ b/ios/Pods/Headers/Private/RNFBApp/RCTConvert+FIROptions.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/app/ios/RNFBApp/RCTConvert+FIROptions.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFBApp/RNFBAppModule.h b/ios/Pods/Headers/Private/RNFBApp/RNFBAppModule.h new file mode 120000 index 000000000..152b1db65 --- /dev/null +++ b/ios/Pods/Headers/Private/RNFBApp/RNFBAppModule.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/app/ios/RNFBApp/RNFBAppModule.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFBApp/RNFBJSON.h b/ios/Pods/Headers/Private/RNFBApp/RNFBJSON.h new file mode 120000 index 000000000..8eebb0cd8 --- /dev/null +++ b/ios/Pods/Headers/Private/RNFBApp/RNFBJSON.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/app/ios/RNFBApp/RNFBJSON.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFBApp/RNFBMeta.h b/ios/Pods/Headers/Private/RNFBApp/RNFBMeta.h new file mode 120000 index 000000000..adbdc7cb7 --- /dev/null +++ b/ios/Pods/Headers/Private/RNFBApp/RNFBMeta.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/app/ios/RNFBApp/RNFBMeta.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFBApp/RNFBPreferences.h b/ios/Pods/Headers/Private/RNFBApp/RNFBPreferences.h new file mode 120000 index 000000000..625a2ca0d --- /dev/null +++ b/ios/Pods/Headers/Private/RNFBApp/RNFBPreferences.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/app/ios/RNFBApp/RNFBPreferences.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFBApp/RNFBRCTEventEmitter.h b/ios/Pods/Headers/Private/RNFBApp/RNFBRCTEventEmitter.h new file mode 120000 index 000000000..f3c53ea24 --- /dev/null +++ b/ios/Pods/Headers/Private/RNFBApp/RNFBRCTEventEmitter.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/app/ios/RNFBApp/RNFBRCTEventEmitter.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFBApp/RNFBSharedUtils.h b/ios/Pods/Headers/Private/RNFBApp/RNFBSharedUtils.h new file mode 120000 index 000000000..dfd5278d8 --- /dev/null +++ b/ios/Pods/Headers/Private/RNFBApp/RNFBSharedUtils.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/app/ios/RNFBApp/RNFBSharedUtils.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFBApp/RNFBUtilsModule.h b/ios/Pods/Headers/Private/RNFBApp/RNFBUtilsModule.h new file mode 120000 index 000000000..fcbb4d40a --- /dev/null +++ b/ios/Pods/Headers/Private/RNFBApp/RNFBUtilsModule.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/app/ios/RNFBApp/RNFBUtilsModule.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFBApp/RNFBVersion.h b/ios/Pods/Headers/Private/RNFBApp/RNFBVersion.h new file mode 120000 index 000000000..fc130e5c4 --- /dev/null +++ b/ios/Pods/Headers/Private/RNFBApp/RNFBVersion.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/app/ios/RNFBApp/RNFBVersion.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFBCrashlytics/RNFBCrashlyticsInitProvider.h b/ios/Pods/Headers/Private/RNFBCrashlytics/RNFBCrashlyticsInitProvider.h new file mode 120000 index 000000000..efc5c1c73 --- /dev/null +++ b/ios/Pods/Headers/Private/RNFBCrashlytics/RNFBCrashlyticsInitProvider.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/crashlytics/ios/RNFBCrashlytics/RNFBCrashlyticsInitProvider.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFBCrashlytics/RNFBCrashlyticsModule.h b/ios/Pods/Headers/Private/RNFBCrashlytics/RNFBCrashlyticsModule.h new file mode 120000 index 000000000..f039889e1 --- /dev/null +++ b/ios/Pods/Headers/Private/RNFBCrashlytics/RNFBCrashlyticsModule.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/crashlytics/ios/RNFBCrashlytics/RNFBCrashlyticsModule.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFastImage/FFFastImageSource.h b/ios/Pods/Headers/Private/RNFastImage/FFFastImageSource.h index c4fc8c87d..477cdf605 120000 --- a/ios/Pods/Headers/Private/RNFastImage/FFFastImageSource.h +++ b/ios/Pods/Headers/Private/RNFastImage/FFFastImageSource.h @@ -1 +1 @@ -../../../../../node_modules/react-native-fast-image/ios/FastImage/FFFastImageSource.h \ No newline at end of file +../../../../../node_modules/@rocket.chat/react-native-fast-image/ios/FastImage/FFFastImageSource.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFastImage/FFFastImageView.h b/ios/Pods/Headers/Private/RNFastImage/FFFastImageView.h index 80b12ac98..12ba0a915 120000 --- a/ios/Pods/Headers/Private/RNFastImage/FFFastImageView.h +++ b/ios/Pods/Headers/Private/RNFastImage/FFFastImageView.h @@ -1 +1 @@ -../../../../../node_modules/react-native-fast-image/ios/FastImage/FFFastImageView.h \ No newline at end of file +../../../../../node_modules/@rocket.chat/react-native-fast-image/ios/FastImage/FFFastImageView.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFastImage/FFFastImageViewManager.h b/ios/Pods/Headers/Private/RNFastImage/FFFastImageViewManager.h index 85a9fcb30..494208669 120000 --- a/ios/Pods/Headers/Private/RNFastImage/FFFastImageViewManager.h +++ b/ios/Pods/Headers/Private/RNFastImage/FFFastImageViewManager.h @@ -1 +1 @@ -../../../../../node_modules/react-native-fast-image/ios/FastImage/FFFastImageViewManager.h \ No newline at end of file +../../../../../node_modules/@rocket.chat/react-native-fast-image/ios/FastImage/FFFastImageViewManager.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFastImage/RCTConvert+FFFastImage.h b/ios/Pods/Headers/Private/RNFastImage/RCTConvert+FFFastImage.h index ade4a7a83..6a7475b1a 120000 --- a/ios/Pods/Headers/Private/RNFastImage/RCTConvert+FFFastImage.h +++ b/ios/Pods/Headers/Private/RNFastImage/RCTConvert+FFFastImage.h @@ -1 +1 @@ -../../../../../node_modules/react-native-fast-image/ios/FastImage/RCTConvert+FFFastImage.h \ No newline at end of file +../../../../../node_modules/@rocket.chat/react-native-fast-image/ios/FastImage/RCTConvert+FFFastImage.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/BannerComponent.h b/ios/Pods/Headers/Private/RNFirebase/BannerComponent.h deleted file mode 120000 index 0a9e6ca4f..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/BannerComponent.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/admob/BannerComponent.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/NativeExpressComponent.h b/ios/Pods/Headers/Private/RNFirebase/NativeExpressComponent.h deleted file mode 120000 index 493a2cee2..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/NativeExpressComponent.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/admob/NativeExpressComponent.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RCTConvert+UIBackgroundFetchResult.h b/ios/Pods/Headers/Private/RNFirebase/RCTConvert+UIBackgroundFetchResult.h deleted file mode 120000 index b09201935..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RCTConvert+UIBackgroundFetchResult.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/converters/RCTConvert+UIBackgroundFetchResult.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RNFirebase.h b/ios/Pods/Headers/Private/RNFirebase/RNFirebase.h deleted file mode 120000 index 4e0c70f5d..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RNFirebase.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/RNFirebase.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseAdMob.h b/ios/Pods/Headers/Private/RNFirebase/RNFirebaseAdMob.h deleted file mode 120000 index 55729ef54..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseAdMob.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/admob/RNFirebaseAdMob.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseAdMobBannerManager.h b/ios/Pods/Headers/Private/RNFirebase/RNFirebaseAdMobBannerManager.h deleted file mode 120000 index d516fd3fa..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseAdMobBannerManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/admob/RNFirebaseAdMobBannerManager.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseAdMobInterstitial.h b/ios/Pods/Headers/Private/RNFirebase/RNFirebaseAdMobInterstitial.h deleted file mode 120000 index e2ddff242..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseAdMobInterstitial.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/admob/RNFirebaseAdMobInterstitial.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseAdMobNativeExpressManager.h b/ios/Pods/Headers/Private/RNFirebase/RNFirebaseAdMobNativeExpressManager.h deleted file mode 120000 index eebfefa26..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseAdMobNativeExpressManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/admob/RNFirebaseAdMobNativeExpressManager.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseAdMobRewardedVideo.h b/ios/Pods/Headers/Private/RNFirebase/RNFirebaseAdMobRewardedVideo.h deleted file mode 120000 index c67cd35b3..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseAdMobRewardedVideo.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/admob/RNFirebaseAdMobRewardedVideo.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseAnalytics.h b/ios/Pods/Headers/Private/RNFirebase/RNFirebaseAnalytics.h deleted file mode 120000 index 2a566d6bd..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseAnalytics.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/analytics/RNFirebaseAnalytics.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseAuth.h b/ios/Pods/Headers/Private/RNFirebase/RNFirebaseAuth.h deleted file mode 120000 index 26e5057e3..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseAuth.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/auth/RNFirebaseAuth.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseCrashlytics.h b/ios/Pods/Headers/Private/RNFirebase/RNFirebaseCrashlytics.h deleted file mode 120000 index 7d586ad25..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseCrashlytics.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/fabric/crashlytics/RNFirebaseCrashlytics.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseDatabase.h b/ios/Pods/Headers/Private/RNFirebase/RNFirebaseDatabase.h deleted file mode 120000 index c0527788a..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseDatabase.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/database/RNFirebaseDatabase.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseDatabaseReference.h b/ios/Pods/Headers/Private/RNFirebase/RNFirebaseDatabaseReference.h deleted file mode 120000 index 8e6f9c456..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseDatabaseReference.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/database/RNFirebaseDatabaseReference.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseEvents.h b/ios/Pods/Headers/Private/RNFirebase/RNFirebaseEvents.h deleted file mode 120000 index 212ce0fcf..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseEvents.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/RNFirebaseEvents.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseFirestore.h b/ios/Pods/Headers/Private/RNFirebase/RNFirebaseFirestore.h deleted file mode 120000 index 0d3c287bb..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseFirestore.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/firestore/RNFirebaseFirestore.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseFirestoreCollectionReference.h b/ios/Pods/Headers/Private/RNFirebase/RNFirebaseFirestoreCollectionReference.h deleted file mode 120000 index 88dc08333..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseFirestoreCollectionReference.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/firestore/RNFirebaseFirestoreCollectionReference.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseFirestoreDocumentReference.h b/ios/Pods/Headers/Private/RNFirebase/RNFirebaseFirestoreDocumentReference.h deleted file mode 120000 index 5a097f55a..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseFirestoreDocumentReference.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/firestore/RNFirebaseFirestoreDocumentReference.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseFunctions.h b/ios/Pods/Headers/Private/RNFirebase/RNFirebaseFunctions.h deleted file mode 120000 index 1ce027568..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseFunctions.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/functions/RNFirebaseFunctions.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseInstanceId.h b/ios/Pods/Headers/Private/RNFirebase/RNFirebaseInstanceId.h deleted file mode 120000 index 7962fdd0f..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseInstanceId.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/instanceid/RNFirebaseInstanceId.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseLinks.h b/ios/Pods/Headers/Private/RNFirebase/RNFirebaseLinks.h deleted file mode 120000 index eaf19ac0f..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseLinks.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/links/RNFirebaseLinks.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseMessaging.h b/ios/Pods/Headers/Private/RNFirebase/RNFirebaseMessaging.h deleted file mode 120000 index d82190756..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseMessaging.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/messaging/RNFirebaseMessaging.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseNotifications.h b/ios/Pods/Headers/Private/RNFirebase/RNFirebaseNotifications.h deleted file mode 120000 index 27f2b2248..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseNotifications.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/notifications/RNFirebaseNotifications.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RNFirebasePerformance.h b/ios/Pods/Headers/Private/RNFirebase/RNFirebasePerformance.h deleted file mode 120000 index 6d1ff9e03..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RNFirebasePerformance.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/perf/RNFirebasePerformance.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseRemoteConfig.h b/ios/Pods/Headers/Private/RNFirebase/RNFirebaseRemoteConfig.h deleted file mode 120000 index f70c1842e..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseRemoteConfig.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/config/RNFirebaseRemoteConfig.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseStorage.h b/ios/Pods/Headers/Private/RNFirebase/RNFirebaseStorage.h deleted file mode 120000 index bcf4895f7..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseStorage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/storage/RNFirebaseStorage.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseUtil.h b/ios/Pods/Headers/Private/RNFirebase/RNFirebaseUtil.h deleted file mode 120000 index 38f1676bd..000000000 --- a/ios/Pods/Headers/Private/RNFirebase/RNFirebaseUtil.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/RNFirebaseUtil.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/React-Core/React/RCTDevLoadingView.h b/ios/Pods/Headers/Private/React-Core/React/RCTDevLoadingView.h index 10124dbc9..90547e0d4 120000 --- a/ios/Pods/Headers/Private/React-Core/React/RCTDevLoadingView.h +++ b/ios/Pods/Headers/Private/React-Core/React/RCTDevLoadingView.h @@ -1 +1 @@ -../../../../../../node_modules/react-native/React/DevSupport/RCTDevLoadingView.h \ No newline at end of file +../../../../../../node_modules/react-native/React/CoreModules/RCTDevLoadingView.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/React-Core/React/RCTDevLoadingViewProtocol.h b/ios/Pods/Headers/Private/React-Core/React/RCTDevLoadingViewProtocol.h new file mode 120000 index 000000000..960628350 --- /dev/null +++ b/ios/Pods/Headers/Private/React-Core/React/RCTDevLoadingViewProtocol.h @@ -0,0 +1 @@ +../../../../../../node_modules/react-native/React/DevSupport/RCTDevLoadingViewProtocol.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/React-Core/React/RCTDevLoadingViewSetEnabled.h b/ios/Pods/Headers/Private/React-Core/React/RCTDevLoadingViewSetEnabled.h new file mode 120000 index 000000000..3a1ead6c6 --- /dev/null +++ b/ios/Pods/Headers/Private/React-Core/React/RCTDevLoadingViewSetEnabled.h @@ -0,0 +1 @@ +../../../../../../node_modules/react-native/React/DevSupport/RCTDevLoadingViewSetEnabled.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/React-Core/React/RCTDisplayWeakRefreshable.h b/ios/Pods/Headers/Private/React-Core/React/RCTDisplayWeakRefreshable.h new file mode 120000 index 000000000..06afd8579 --- /dev/null +++ b/ios/Pods/Headers/Private/React-Core/React/RCTDisplayWeakRefreshable.h @@ -0,0 +1 @@ +../../../../../../node_modules/react-native/Libraries/Image/RCTDisplayWeakRefreshable.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/React-Core/React/RCTJSInvokerModule.h b/ios/Pods/Headers/Private/React-Core/React/RCTJSInvokerModule.h new file mode 120000 index 000000000..51992c8cb --- /dev/null +++ b/ios/Pods/Headers/Private/React-Core/React/RCTJSInvokerModule.h @@ -0,0 +1 @@ +../../../../../../node_modules/react-native/React/Base/RCTJSInvokerModule.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/React-Core/React/RCTModalManager.h b/ios/Pods/Headers/Private/React-Core/React/RCTModalManager.h deleted file mode 120000 index a043e068b..000000000 --- a/ios/Pods/Headers/Private/React-Core/React/RCTModalManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../../node_modules/react-native/React/Views/RCTModalManager.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/ReactCommon/ReactCommon/CallInvoker.h b/ios/Pods/Headers/Private/React-callinvoker/ReactCommon/CallInvoker.h similarity index 100% rename from ios/Pods/Headers/Private/ReactCommon/ReactCommon/CallInvoker.h rename to ios/Pods/Headers/Private/React-callinvoker/ReactCommon/CallInvoker.h diff --git a/ios/Pods/Headers/Private/React-cxxreact/cxxreact/ReactNativeVersion.h b/ios/Pods/Headers/Private/React-cxxreact/cxxreact/ReactNativeVersion.h new file mode 120000 index 000000000..ace035949 --- /dev/null +++ b/ios/Pods/Headers/Private/React-cxxreact/cxxreact/ReactNativeVersion.h @@ -0,0 +1 @@ +../../../../../../node_modules/react-native/ReactCommon/cxxreact/ReactNativeVersion.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/ReactCommon/ReactCommon/BridgeJSCallInvoker.h b/ios/Pods/Headers/Private/ReactCommon/ReactCommon/BridgeJSCallInvoker.h deleted file mode 120000 index 08d71be32..000000000 --- a/ios/Pods/Headers/Private/ReactCommon/ReactCommon/BridgeJSCallInvoker.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../../node_modules/react-native/ReactCommon/callinvoker/ReactCommon/BridgeJSCallInvoker.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/ReactCommon/ReactCommon/MessageQueueThreadCallInvoker.h b/ios/Pods/Headers/Private/ReactCommon/ReactCommon/MessageQueueThreadCallInvoker.h deleted file mode 120000 index 0720dccb3..000000000 --- a/ios/Pods/Headers/Private/ReactCommon/ReactCommon/MessageQueueThreadCallInvoker.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../../node_modules/react-native/ReactCommon/callinvoker/ReactCommon/MessageQueueThreadCallInvoker.h \ No newline at end of file diff --git a/ios/Pods/Headers/Private/SDWebImage/SDWebImageTransitionInternal.h b/ios/Pods/Headers/Private/SDWebImage/SDWebImageTransitionInternal.h new file mode 120000 index 000000000..0f3ec14ae --- /dev/null +++ b/ios/Pods/Headers/Private/SDWebImage/SDWebImageTransitionInternal.h @@ -0,0 +1 @@ +../../../SDWebImage/SDWebImage/Private/SDWebImageTransitionInternal.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/BugsnagReactNative/BSG_KSMachHeaders.h b/ios/Pods/Headers/Public/BugsnagReactNative/BSG_KSMachHeaders.h new file mode 120000 index 000000000..a488182e4 --- /dev/null +++ b/ios/Pods/Headers/Public/BugsnagReactNative/BSG_KSMachHeaders.h @@ -0,0 +1 @@ +../../../../../node_modules/bugsnag-react-native/cocoa/vendor/bugsnag-cocoa/Source/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSMachHeaders.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/EXFileSystem/EXDownloadDelegate.h b/ios/Pods/Headers/Public/EXFileSystem/EXDownloadDelegate.h deleted file mode 120000 index 0590b2177..000000000 --- a/ios/Pods/Headers/Public/EXFileSystem/EXDownloadDelegate.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/expo-file-system/ios/EXFileSystem/EXDownloadDelegate.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/EXFileSystem/EXResumablesManager.h b/ios/Pods/Headers/Public/EXFileSystem/EXResumablesManager.h new file mode 120000 index 000000000..958b4705a --- /dev/null +++ b/ios/Pods/Headers/Public/EXFileSystem/EXResumablesManager.h @@ -0,0 +1 @@ +../../../../../node_modules/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXResumablesManager.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/EXFileSystem/EXSessionDownloadTaskDelegate.h b/ios/Pods/Headers/Public/EXFileSystem/EXSessionDownloadTaskDelegate.h new file mode 120000 index 000000000..be371eb88 --- /dev/null +++ b/ios/Pods/Headers/Public/EXFileSystem/EXSessionDownloadTaskDelegate.h @@ -0,0 +1 @@ +../../../../../node_modules/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionDownloadTaskDelegate.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/EXFileSystem/EXSessionResumableDownloadTaskDelegate.h b/ios/Pods/Headers/Public/EXFileSystem/EXSessionResumableDownloadTaskDelegate.h new file mode 120000 index 000000000..207a09ba5 --- /dev/null +++ b/ios/Pods/Headers/Public/EXFileSystem/EXSessionResumableDownloadTaskDelegate.h @@ -0,0 +1 @@ +../../../../../node_modules/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionResumableDownloadTaskDelegate.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/EXFileSystem/EXSessionTaskDelegate.h b/ios/Pods/Headers/Public/EXFileSystem/EXSessionTaskDelegate.h new file mode 120000 index 000000000..85cedea35 --- /dev/null +++ b/ios/Pods/Headers/Public/EXFileSystem/EXSessionTaskDelegate.h @@ -0,0 +1 @@ +../../../../../node_modules/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionTaskDelegate.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/EXFileSystem/EXSessionTaskDispatcher.h b/ios/Pods/Headers/Public/EXFileSystem/EXSessionTaskDispatcher.h new file mode 120000 index 000000000..5b5535e13 --- /dev/null +++ b/ios/Pods/Headers/Public/EXFileSystem/EXSessionTaskDispatcher.h @@ -0,0 +1 @@ +../../../../../node_modules/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionTaskDispatcher.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/EXFileSystem/EXSessionUploadTaskDelegate.h b/ios/Pods/Headers/Public/EXFileSystem/EXSessionUploadTaskDelegate.h new file mode 120000 index 000000000..44686858b --- /dev/null +++ b/ios/Pods/Headers/Public/EXFileSystem/EXSessionUploadTaskDelegate.h @@ -0,0 +1 @@ +../../../../../node_modules/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionUploadTaskDelegate.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/EXFileSystem/NSData+EXFileSystem.h b/ios/Pods/Headers/Public/EXFileSystem/NSData+EXFileSystem.h new file mode 120000 index 000000000..a91740920 --- /dev/null +++ b/ios/Pods/Headers/Public/EXFileSystem/NSData+EXFileSystem.h @@ -0,0 +1 @@ +../../../../../node_modules/expo-file-system/ios/EXFileSystem/NSData+EXFileSystem.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/EXPermissions/EXRemoteNotificationPermissionRequester.h b/ios/Pods/Headers/Public/EXPermissions/EXRemoteNotificationPermissionRequester.h deleted file mode 120000 index b78040b03..000000000 --- a/ios/Pods/Headers/Public/EXPermissions/EXRemoteNotificationPermissionRequester.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/expo-permissions/ios/EXPermissions/Requesters/RemoteNotification/EXRemoteNotificationPermissionRequester.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/EXPermissions/EXUserNotificationPermissionRequester.h b/ios/Pods/Headers/Public/EXPermissions/EXUserNotificationPermissionRequester.h deleted file mode 120000 index 0c452886b..000000000 --- a/ios/Pods/Headers/Public/EXPermissions/EXUserNotificationPermissionRequester.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/expo-permissions/ios/EXPermissions/Requesters/UserNotification/EXUserNotificationPermissionRequester.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/FirebaseCoreDiagnostics/FIRCoreDiagnosticsData.h b/ios/Pods/Headers/Public/FirebaseCoreDiagnostics/FIRCoreDiagnosticsData.h new file mode 120000 index 000000000..83f0dd892 --- /dev/null +++ b/ios/Pods/Headers/Public/FirebaseCoreDiagnostics/FIRCoreDiagnosticsData.h @@ -0,0 +1 @@ +../../../FirebaseCoreDiagnostics/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/FirebaseCoreDiagnostics/FIRCoreDiagnosticsInterop.h b/ios/Pods/Headers/Public/FirebaseCoreDiagnostics/FIRCoreDiagnosticsInterop.h new file mode 120000 index 000000000..ed200e50e --- /dev/null +++ b/ios/Pods/Headers/Public/FirebaseCoreDiagnostics/FIRCoreDiagnosticsInterop.h @@ -0,0 +1 @@ +../../../FirebaseCoreDiagnostics/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsData.h b/ios/Pods/Headers/Public/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsData.h deleted file mode 120000 index ce646ecf1..000000000 --- a/ios/Pods/Headers/Public/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsData.h +++ /dev/null @@ -1 +0,0 @@ -../../../FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsInterop.h b/ios/Pods/Headers/Public/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsInterop.h deleted file mode 120000 index 07d83d70f..000000000 --- a/ios/Pods/Headers/Public/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsInterop.h +++ /dev/null @@ -1 +0,0 @@ -../../../FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/FirebaseCrashlytics/FIRCrashlytics.h b/ios/Pods/Headers/Public/FirebaseCrashlytics/FIRCrashlytics.h new file mode 120000 index 000000000..c5678902e --- /dev/null +++ b/ios/Pods/Headers/Public/FirebaseCrashlytics/FIRCrashlytics.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FIRCrashlytics.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/FirebaseCrashlytics/FIRExceptionModel.h b/ios/Pods/Headers/Public/FirebaseCrashlytics/FIRExceptionModel.h new file mode 120000 index 000000000..fc129ad84 --- /dev/null +++ b/ios/Pods/Headers/Public/FirebaseCrashlytics/FIRExceptionModel.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FIRExceptionModel.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/FirebaseCrashlytics/FIRStackFrame.h b/ios/Pods/Headers/Public/FirebaseCrashlytics/FIRStackFrame.h new file mode 120000 index 000000000..9c127465e --- /dev/null +++ b/ios/Pods/Headers/Public/FirebaseCrashlytics/FIRStackFrame.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FIRStackFrame.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/FirebaseCrashlytics/FirebaseCrashlytics.h b/ios/Pods/Headers/Public/FirebaseCrashlytics/FirebaseCrashlytics.h new file mode 120000 index 000000000..e69eff498 --- /dev/null +++ b/ios/Pods/Headers/Public/FirebaseCrashlytics/FirebaseCrashlytics.h @@ -0,0 +1 @@ +../../../FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FirebaseCrashlytics.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/GoogleDataTransportCCTSupport/GDTCOREvent+GDTCCTSupport.h b/ios/Pods/Headers/Public/GoogleDataTransportCCTSupport/GDTCOREvent+GDTCCTSupport.h new file mode 120000 index 000000000..5604da60a --- /dev/null +++ b/ios/Pods/Headers/Public/GoogleDataTransportCCTSupport/GDTCOREvent+GDTCCTSupport.h @@ -0,0 +1 @@ +../../../GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/GoogleDataTransportCCTSupport/cct.nanopb.h b/ios/Pods/Headers/Public/GoogleDataTransportCCTSupport/cct.nanopb.h deleted file mode 120000 index bc740eb72..000000000 --- a/ios/Pods/Headers/Public/GoogleDataTransportCCTSupport/cct.nanopb.h +++ /dev/null @@ -1 +0,0 @@ -../../../GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/GoogleUtilities/GULNSData+zlib.h b/ios/Pods/Headers/Public/GoogleUtilities/GULNSData+zlib.h index ee84730c9..fa7721f67 120000 --- a/ios/Pods/Headers/Public/GoogleUtilities/GULNSData+zlib.h +++ b/ios/Pods/Headers/Public/GoogleUtilities/GULNSData+zlib.h @@ -1 +1 @@ -../../../GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.h \ No newline at end of file +../../../GoogleUtilities/GoogleUtilities/NSData+zlib/Public/GULNSData+zlib.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFBAnalytics/RNFBAnalyticsModule.h b/ios/Pods/Headers/Public/RNFBAnalytics/RNFBAnalyticsModule.h new file mode 120000 index 000000000..0e94f7c05 --- /dev/null +++ b/ios/Pods/Headers/Public/RNFBAnalytics/RNFBAnalyticsModule.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/analytics/ios/RNFBAnalytics/RNFBAnalyticsModule.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFBApp/RCTConvert+FIRApp.h b/ios/Pods/Headers/Public/RNFBApp/RCTConvert+FIRApp.h new file mode 120000 index 000000000..7d72b0274 --- /dev/null +++ b/ios/Pods/Headers/Public/RNFBApp/RCTConvert+FIRApp.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/app/ios/RNFBApp/RCTConvert+FIRApp.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFBApp/RCTConvert+FIROptions.h b/ios/Pods/Headers/Public/RNFBApp/RCTConvert+FIROptions.h new file mode 120000 index 000000000..683731ece --- /dev/null +++ b/ios/Pods/Headers/Public/RNFBApp/RCTConvert+FIROptions.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/app/ios/RNFBApp/RCTConvert+FIROptions.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFBApp/RNFBAppModule.h b/ios/Pods/Headers/Public/RNFBApp/RNFBAppModule.h new file mode 120000 index 000000000..152b1db65 --- /dev/null +++ b/ios/Pods/Headers/Public/RNFBApp/RNFBAppModule.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/app/ios/RNFBApp/RNFBAppModule.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFBApp/RNFBJSON.h b/ios/Pods/Headers/Public/RNFBApp/RNFBJSON.h new file mode 120000 index 000000000..8eebb0cd8 --- /dev/null +++ b/ios/Pods/Headers/Public/RNFBApp/RNFBJSON.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/app/ios/RNFBApp/RNFBJSON.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFBApp/RNFBMeta.h b/ios/Pods/Headers/Public/RNFBApp/RNFBMeta.h new file mode 120000 index 000000000..adbdc7cb7 --- /dev/null +++ b/ios/Pods/Headers/Public/RNFBApp/RNFBMeta.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/app/ios/RNFBApp/RNFBMeta.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFBApp/RNFBPreferences.h b/ios/Pods/Headers/Public/RNFBApp/RNFBPreferences.h new file mode 120000 index 000000000..625a2ca0d --- /dev/null +++ b/ios/Pods/Headers/Public/RNFBApp/RNFBPreferences.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/app/ios/RNFBApp/RNFBPreferences.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFBApp/RNFBRCTEventEmitter.h b/ios/Pods/Headers/Public/RNFBApp/RNFBRCTEventEmitter.h new file mode 120000 index 000000000..f3c53ea24 --- /dev/null +++ b/ios/Pods/Headers/Public/RNFBApp/RNFBRCTEventEmitter.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/app/ios/RNFBApp/RNFBRCTEventEmitter.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFBApp/RNFBSharedUtils.h b/ios/Pods/Headers/Public/RNFBApp/RNFBSharedUtils.h new file mode 120000 index 000000000..dfd5278d8 --- /dev/null +++ b/ios/Pods/Headers/Public/RNFBApp/RNFBSharedUtils.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/app/ios/RNFBApp/RNFBSharedUtils.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFBApp/RNFBUtilsModule.h b/ios/Pods/Headers/Public/RNFBApp/RNFBUtilsModule.h new file mode 120000 index 000000000..fcbb4d40a --- /dev/null +++ b/ios/Pods/Headers/Public/RNFBApp/RNFBUtilsModule.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/app/ios/RNFBApp/RNFBUtilsModule.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFBApp/RNFBVersion.h b/ios/Pods/Headers/Public/RNFBApp/RNFBVersion.h new file mode 120000 index 000000000..fc130e5c4 --- /dev/null +++ b/ios/Pods/Headers/Public/RNFBApp/RNFBVersion.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/app/ios/RNFBApp/RNFBVersion.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFBCrashlytics/RNFBCrashlyticsInitProvider.h b/ios/Pods/Headers/Public/RNFBCrashlytics/RNFBCrashlyticsInitProvider.h new file mode 120000 index 000000000..efc5c1c73 --- /dev/null +++ b/ios/Pods/Headers/Public/RNFBCrashlytics/RNFBCrashlyticsInitProvider.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/crashlytics/ios/RNFBCrashlytics/RNFBCrashlyticsInitProvider.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFBCrashlytics/RNFBCrashlyticsModule.h b/ios/Pods/Headers/Public/RNFBCrashlytics/RNFBCrashlyticsModule.h new file mode 120000 index 000000000..f039889e1 --- /dev/null +++ b/ios/Pods/Headers/Public/RNFBCrashlytics/RNFBCrashlyticsModule.h @@ -0,0 +1 @@ +../../../../../node_modules/@react-native-firebase/crashlytics/ios/RNFBCrashlytics/RNFBCrashlyticsModule.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFastImage/FFFastImageSource.h b/ios/Pods/Headers/Public/RNFastImage/FFFastImageSource.h index c4fc8c87d..477cdf605 120000 --- a/ios/Pods/Headers/Public/RNFastImage/FFFastImageSource.h +++ b/ios/Pods/Headers/Public/RNFastImage/FFFastImageSource.h @@ -1 +1 @@ -../../../../../node_modules/react-native-fast-image/ios/FastImage/FFFastImageSource.h \ No newline at end of file +../../../../../node_modules/@rocket.chat/react-native-fast-image/ios/FastImage/FFFastImageSource.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFastImage/FFFastImageView.h b/ios/Pods/Headers/Public/RNFastImage/FFFastImageView.h index 80b12ac98..12ba0a915 120000 --- a/ios/Pods/Headers/Public/RNFastImage/FFFastImageView.h +++ b/ios/Pods/Headers/Public/RNFastImage/FFFastImageView.h @@ -1 +1 @@ -../../../../../node_modules/react-native-fast-image/ios/FastImage/FFFastImageView.h \ No newline at end of file +../../../../../node_modules/@rocket.chat/react-native-fast-image/ios/FastImage/FFFastImageView.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFastImage/FFFastImageViewManager.h b/ios/Pods/Headers/Public/RNFastImage/FFFastImageViewManager.h index 85a9fcb30..494208669 120000 --- a/ios/Pods/Headers/Public/RNFastImage/FFFastImageViewManager.h +++ b/ios/Pods/Headers/Public/RNFastImage/FFFastImageViewManager.h @@ -1 +1 @@ -../../../../../node_modules/react-native-fast-image/ios/FastImage/FFFastImageViewManager.h \ No newline at end of file +../../../../../node_modules/@rocket.chat/react-native-fast-image/ios/FastImage/FFFastImageViewManager.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFastImage/RCTConvert+FFFastImage.h b/ios/Pods/Headers/Public/RNFastImage/RCTConvert+FFFastImage.h index ade4a7a83..6a7475b1a 120000 --- a/ios/Pods/Headers/Public/RNFastImage/RCTConvert+FFFastImage.h +++ b/ios/Pods/Headers/Public/RNFastImage/RCTConvert+FFFastImage.h @@ -1 +1 @@ -../../../../../node_modules/react-native-fast-image/ios/FastImage/RCTConvert+FFFastImage.h \ No newline at end of file +../../../../../node_modules/@rocket.chat/react-native-fast-image/ios/FastImage/RCTConvert+FFFastImage.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/BannerComponent.h b/ios/Pods/Headers/Public/RNFirebase/BannerComponent.h deleted file mode 120000 index 0a9e6ca4f..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/BannerComponent.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/admob/BannerComponent.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/NativeExpressComponent.h b/ios/Pods/Headers/Public/RNFirebase/NativeExpressComponent.h deleted file mode 120000 index 493a2cee2..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/NativeExpressComponent.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/admob/NativeExpressComponent.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RCTConvert+UIBackgroundFetchResult.h b/ios/Pods/Headers/Public/RNFirebase/RCTConvert+UIBackgroundFetchResult.h deleted file mode 120000 index b09201935..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RCTConvert+UIBackgroundFetchResult.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/converters/RCTConvert+UIBackgroundFetchResult.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RNFirebase.h b/ios/Pods/Headers/Public/RNFirebase/RNFirebase.h deleted file mode 120000 index 4e0c70f5d..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RNFirebase.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/RNFirebase.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseAdMob.h b/ios/Pods/Headers/Public/RNFirebase/RNFirebaseAdMob.h deleted file mode 120000 index 55729ef54..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseAdMob.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/admob/RNFirebaseAdMob.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseAdMobBannerManager.h b/ios/Pods/Headers/Public/RNFirebase/RNFirebaseAdMobBannerManager.h deleted file mode 120000 index d516fd3fa..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseAdMobBannerManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/admob/RNFirebaseAdMobBannerManager.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseAdMobInterstitial.h b/ios/Pods/Headers/Public/RNFirebase/RNFirebaseAdMobInterstitial.h deleted file mode 120000 index e2ddff242..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseAdMobInterstitial.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/admob/RNFirebaseAdMobInterstitial.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseAdMobNativeExpressManager.h b/ios/Pods/Headers/Public/RNFirebase/RNFirebaseAdMobNativeExpressManager.h deleted file mode 120000 index eebfefa26..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseAdMobNativeExpressManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/admob/RNFirebaseAdMobNativeExpressManager.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseAdMobRewardedVideo.h b/ios/Pods/Headers/Public/RNFirebase/RNFirebaseAdMobRewardedVideo.h deleted file mode 120000 index c67cd35b3..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseAdMobRewardedVideo.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/admob/RNFirebaseAdMobRewardedVideo.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseAnalytics.h b/ios/Pods/Headers/Public/RNFirebase/RNFirebaseAnalytics.h deleted file mode 120000 index 2a566d6bd..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseAnalytics.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/analytics/RNFirebaseAnalytics.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseAuth.h b/ios/Pods/Headers/Public/RNFirebase/RNFirebaseAuth.h deleted file mode 120000 index 26e5057e3..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseAuth.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/auth/RNFirebaseAuth.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseCrashlytics.h b/ios/Pods/Headers/Public/RNFirebase/RNFirebaseCrashlytics.h deleted file mode 120000 index 7d586ad25..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseCrashlytics.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/fabric/crashlytics/RNFirebaseCrashlytics.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseDatabase.h b/ios/Pods/Headers/Public/RNFirebase/RNFirebaseDatabase.h deleted file mode 120000 index c0527788a..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseDatabase.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/database/RNFirebaseDatabase.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseDatabaseReference.h b/ios/Pods/Headers/Public/RNFirebase/RNFirebaseDatabaseReference.h deleted file mode 120000 index 8e6f9c456..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseDatabaseReference.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/database/RNFirebaseDatabaseReference.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseEvents.h b/ios/Pods/Headers/Public/RNFirebase/RNFirebaseEvents.h deleted file mode 120000 index 212ce0fcf..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseEvents.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/RNFirebaseEvents.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseFirestore.h b/ios/Pods/Headers/Public/RNFirebase/RNFirebaseFirestore.h deleted file mode 120000 index 0d3c287bb..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseFirestore.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/firestore/RNFirebaseFirestore.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseFirestoreCollectionReference.h b/ios/Pods/Headers/Public/RNFirebase/RNFirebaseFirestoreCollectionReference.h deleted file mode 120000 index 88dc08333..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseFirestoreCollectionReference.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/firestore/RNFirebaseFirestoreCollectionReference.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseFirestoreDocumentReference.h b/ios/Pods/Headers/Public/RNFirebase/RNFirebaseFirestoreDocumentReference.h deleted file mode 120000 index 5a097f55a..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseFirestoreDocumentReference.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/firestore/RNFirebaseFirestoreDocumentReference.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseFunctions.h b/ios/Pods/Headers/Public/RNFirebase/RNFirebaseFunctions.h deleted file mode 120000 index 1ce027568..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseFunctions.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/functions/RNFirebaseFunctions.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseInstanceId.h b/ios/Pods/Headers/Public/RNFirebase/RNFirebaseInstanceId.h deleted file mode 120000 index 7962fdd0f..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseInstanceId.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/instanceid/RNFirebaseInstanceId.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseLinks.h b/ios/Pods/Headers/Public/RNFirebase/RNFirebaseLinks.h deleted file mode 120000 index eaf19ac0f..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseLinks.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/links/RNFirebaseLinks.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseMessaging.h b/ios/Pods/Headers/Public/RNFirebase/RNFirebaseMessaging.h deleted file mode 120000 index d82190756..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseMessaging.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/messaging/RNFirebaseMessaging.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseNotifications.h b/ios/Pods/Headers/Public/RNFirebase/RNFirebaseNotifications.h deleted file mode 120000 index 27f2b2248..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseNotifications.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/notifications/RNFirebaseNotifications.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RNFirebasePerformance.h b/ios/Pods/Headers/Public/RNFirebase/RNFirebasePerformance.h deleted file mode 120000 index 6d1ff9e03..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RNFirebasePerformance.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/perf/RNFirebasePerformance.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseRemoteConfig.h b/ios/Pods/Headers/Public/RNFirebase/RNFirebaseRemoteConfig.h deleted file mode 120000 index f70c1842e..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseRemoteConfig.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/config/RNFirebaseRemoteConfig.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseStorage.h b/ios/Pods/Headers/Public/RNFirebase/RNFirebaseStorage.h deleted file mode 120000 index bcf4895f7..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseStorage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/storage/RNFirebaseStorage.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseUtil.h b/ios/Pods/Headers/Public/RNFirebase/RNFirebaseUtil.h deleted file mode 120000 index 38f1676bd..000000000 --- a/ios/Pods/Headers/Public/RNFirebase/RNFirebaseUtil.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../node_modules/react-native-firebase/ios/RNFirebase/RNFirebaseUtil.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/React-Core/React/RCTDevLoadingView.h b/ios/Pods/Headers/Public/React-Core/React/RCTDevLoadingView.h index 10124dbc9..90547e0d4 120000 --- a/ios/Pods/Headers/Public/React-Core/React/RCTDevLoadingView.h +++ b/ios/Pods/Headers/Public/React-Core/React/RCTDevLoadingView.h @@ -1 +1 @@ -../../../../../../node_modules/react-native/React/DevSupport/RCTDevLoadingView.h \ No newline at end of file +../../../../../../node_modules/react-native/React/CoreModules/RCTDevLoadingView.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/React-Core/React/RCTDevLoadingViewProtocol.h b/ios/Pods/Headers/Public/React-Core/React/RCTDevLoadingViewProtocol.h new file mode 120000 index 000000000..960628350 --- /dev/null +++ b/ios/Pods/Headers/Public/React-Core/React/RCTDevLoadingViewProtocol.h @@ -0,0 +1 @@ +../../../../../../node_modules/react-native/React/DevSupport/RCTDevLoadingViewProtocol.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/React-Core/React/RCTDevLoadingViewSetEnabled.h b/ios/Pods/Headers/Public/React-Core/React/RCTDevLoadingViewSetEnabled.h new file mode 120000 index 000000000..3a1ead6c6 --- /dev/null +++ b/ios/Pods/Headers/Public/React-Core/React/RCTDevLoadingViewSetEnabled.h @@ -0,0 +1 @@ +../../../../../../node_modules/react-native/React/DevSupport/RCTDevLoadingViewSetEnabled.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/React-Core/React/RCTDisplayWeakRefreshable.h b/ios/Pods/Headers/Public/React-Core/React/RCTDisplayWeakRefreshable.h new file mode 120000 index 000000000..06afd8579 --- /dev/null +++ b/ios/Pods/Headers/Public/React-Core/React/RCTDisplayWeakRefreshable.h @@ -0,0 +1 @@ +../../../../../../node_modules/react-native/Libraries/Image/RCTDisplayWeakRefreshable.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/React-Core/React/RCTJSInvokerModule.h b/ios/Pods/Headers/Public/React-Core/React/RCTJSInvokerModule.h new file mode 120000 index 000000000..51992c8cb --- /dev/null +++ b/ios/Pods/Headers/Public/React-Core/React/RCTJSInvokerModule.h @@ -0,0 +1 @@ +../../../../../../node_modules/react-native/React/Base/RCTJSInvokerModule.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/React-Core/React/RCTModalManager.h b/ios/Pods/Headers/Public/React-Core/React/RCTModalManager.h deleted file mode 120000 index a043e068b..000000000 --- a/ios/Pods/Headers/Public/React-Core/React/RCTModalManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../../node_modules/react-native/React/Views/RCTModalManager.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/ReactCommon/ReactCommon/CallInvoker.h b/ios/Pods/Headers/Public/React-callinvoker/ReactCommon/CallInvoker.h similarity index 100% rename from ios/Pods/Headers/Public/ReactCommon/ReactCommon/CallInvoker.h rename to ios/Pods/Headers/Public/React-callinvoker/ReactCommon/CallInvoker.h diff --git a/ios/Pods/Headers/Public/React-cxxreact/cxxreact/ReactNativeVersion.h b/ios/Pods/Headers/Public/React-cxxreact/cxxreact/ReactNativeVersion.h new file mode 120000 index 000000000..ace035949 --- /dev/null +++ b/ios/Pods/Headers/Public/React-cxxreact/cxxreact/ReactNativeVersion.h @@ -0,0 +1 @@ +../../../../../../node_modules/react-native/ReactCommon/cxxreact/ReactNativeVersion.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/ReactCommon/ReactCommon/BridgeJSCallInvoker.h b/ios/Pods/Headers/Public/ReactCommon/ReactCommon/BridgeJSCallInvoker.h deleted file mode 120000 index 08d71be32..000000000 --- a/ios/Pods/Headers/Public/ReactCommon/ReactCommon/BridgeJSCallInvoker.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../../node_modules/react-native/ReactCommon/callinvoker/ReactCommon/BridgeJSCallInvoker.h \ No newline at end of file diff --git a/ios/Pods/Headers/Public/ReactCommon/ReactCommon/MessageQueueThreadCallInvoker.h b/ios/Pods/Headers/Public/ReactCommon/ReactCommon/MessageQueueThreadCallInvoker.h deleted file mode 120000 index 0720dccb3..000000000 --- a/ios/Pods/Headers/Public/ReactCommon/ReactCommon/MessageQueueThreadCallInvoker.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../../node_modules/react-native/ReactCommon/callinvoker/ReactCommon/MessageQueueThreadCallInvoker.h \ No newline at end of file diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Headers/InfoPlistUtil.h b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Headers/InfoPlistUtil.h deleted file mode 100644 index f7d5bb8f9..000000000 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Headers/InfoPlistUtil.h +++ /dev/null @@ -1,23 +0,0 @@ -/* -* Copyright @ 2019-present 8x8, Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#import <Foundation/Foundation.h> - -@interface InfoPlistUtil : NSObject - -+ (BOOL)containsRealServiceInfoPlistInBundle:(NSBundle *)bundle; - -@end diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Headers/JitsiMeet.h b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Headers/JitsiMeet.h index 8db09854d..a268222de 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Headers/JitsiMeet.h +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Headers/JitsiMeet.h @@ -20,7 +20,6 @@ #import <JitsiMeet/JitsiMeetConferenceOptions.h> #import <JitsiMeet/JitsiMeetLogger.h> #import <JitsiMeet/JitsiMeetBaseLogHandler.h> -#import <JitsiMeet/InfoPlistUtil.h> @interface JitsiMeet : NSObject @@ -65,6 +64,4 @@ - (JitsiMeetConferenceOptions *_Nonnull)getInitialConferenceOptions; -- (BOOL)isCrashReportingDisabled; - @end diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/JitsiMeet b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/JitsiMeet index 5c09324b3..95d2ad08e 100755 Binary files a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/JitsiMeet and b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/JitsiMeet differ diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Modules/JitsiMeet.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Modules/JitsiMeet.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo index 26010b723..bc9168e74 100644 Binary files a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Modules/JitsiMeet.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo and b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Modules/JitsiMeet.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo differ diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Modules/JitsiMeet.swiftmodule/Project/x86_64.swiftsourceinfo b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Modules/JitsiMeet.swiftmodule/Project/x86_64.swiftsourceinfo index 26010b723..bc9168e74 100644 Binary files a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Modules/JitsiMeet.swiftmodule/Project/x86_64.swiftsourceinfo and b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Modules/JitsiMeet.swiftmodule/Project/x86_64.swiftsourceinfo differ diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Modules/JitsiMeet.swiftmodule/arm64-apple-ios.swiftmodule b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Modules/JitsiMeet.swiftmodule/arm64-apple-ios.swiftmodule index 45f17a283..b7db71631 100644 Binary files a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Modules/JitsiMeet.swiftmodule/arm64-apple-ios.swiftmodule and b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Modules/JitsiMeet.swiftmodule/arm64-apple-ios.swiftmodule differ diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Modules/JitsiMeet.swiftmodule/arm64.swiftmodule b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Modules/JitsiMeet.swiftmodule/arm64.swiftmodule index 45f17a283..b7db71631 100644 Binary files a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Modules/JitsiMeet.swiftmodule/arm64.swiftmodule and b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Modules/JitsiMeet.swiftmodule/arm64.swiftmodule differ diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Modules/JitsiMeet.swiftmodule/x86_64-apple-ios-simulator.swiftmodule b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Modules/JitsiMeet.swiftmodule/x86_64-apple-ios-simulator.swiftmodule index 39e068449..a2d7bde1b 100644 Binary files a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Modules/JitsiMeet.swiftmodule/x86_64-apple-ios-simulator.swiftmodule and b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Modules/JitsiMeet.swiftmodule/x86_64-apple-ios-simulator.swiftmodule differ diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Modules/JitsiMeet.swiftmodule/x86_64.swiftmodule b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Modules/JitsiMeet.swiftmodule/x86_64.swiftmodule index 39e068449..a2d7bde1b 100644 Binary files a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Modules/JitsiMeet.swiftmodule/x86_64.swiftmodule and b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/Modules/JitsiMeet.swiftmodule/x86_64.swiftmodule differ diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-ca.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-ca.json deleted file mode 100644 index 7b8e02384..000000000 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-ca.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "en": "Anglès", - "af": "Afrikaans", - "bg": "Búlgar", - "ca": "Català", - "cs": "Txec", - "da": "Danès", - "de": "Alemany", - "el": "Grec", - "enGB": "Anglès (Regne Unit)", - "eo": "Esperanto", - "es": "Espanyol", - "esUS": "Espanyol (Amèrica llatina)", - "fi": "Finès", - "fr": "Francès", - "frCA": "Francès (Canadà)", - "hr": "Croat", - "hu": "Hongarès", - "hy": "Armeni", - "it": "Italià", - "ja": "Japonès", - "ko": "Coreà", - "nl": "Neerlandès", - "oc": "Occità", - "pl": "Polonès", - "ptBR": "Portuguès (Brasil)", - "ru": "Rus", - "sv": "Suec", - "tr": "Turc", - "vi": "Vietnamita", - "zhCN": "Xinès (Xina)", - "zhTW": "Xinès (Taiwan)", - "et": "Estonià" -} diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-de.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-de.json index d35a7652b..c2c4b3e73 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-de.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-de.json @@ -23,16 +23,5 @@ "sv": "Schwedisch", "tr": "Türkisch", "vi": "Vietnamesisch", - "zhCN": "Chinesisch (China)", - "zhTW": "Chinesisch (Taiwan)", - "nl": "Niederländisch", - "hu": "Ungarisch", - "hr": "Kroatisch", - "frCA": "Französisch (Kanada)", - "fi": "Finnisch", - "et": "Estnisch", - "esUS": "Spanisch (Lateinamerika)", - "enGB": "Englisch (Vereinigtes Königreich)", - "da": "Dänisch", - "ca": "Katalanisch" + "zhCN": "Chinesisch (China)" } diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-enGB.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-enGB.json index f59913fa9..89fb1ac95 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-enGB.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-enGB.json @@ -1,38 +1,27 @@ { - "en": "English", - "af": "Afrikaans", + "en": "", + "af": "", "az": "", - "bg": "Bulgarian", - "cs": "Czech", - "de": "German", - "el": "Greek", - "eo": "Esperanto", - "es": "Spanish", - "fr": "French", - "hy": "Armenian", - "it": "Italian", - "ja": "Japanese", - "ko": "Korean", + "bg": "", + "cs": "", + "de": "", + "el": "", + "eo": "", + "es": "", + "fr": "", + "hy": "", + "it": "", + "ja": "", + "ko": "", "nb": "", - "oc": "Occitan", - "pl": "Polish", - "ptBR": "Portuguese (Brazil)", - "ru": "Russian", + "oc": "", + "pl": "", + "ptBR": "", + "ru": "", "sk": "", "sl": "", - "sv": "Swedish", - "tr": "Turkish", - "vi": "Vietnamese", - "zhCN": "Chinese (China)", - "zhTW": "Chinese (Taiwan)", - "nl": "Dutch", - "hu": "Hungarian", - "hr": "Croatian", - "frCA": "French (Canadian)", - "fi": "Finnish", - "et": "Estonian", - "esUS": "Spanish (Latin America)", - "enGB": "English (United Kingdom)", - "da": "Danish", - "ca": "Catalan" -} + "sv": "", + "tr": "", + "vi": "", + "zhCN": "" +} \ No newline at end of file diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-eo.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-eo.json index 8b28ed3d7..265118421 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-eo.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-eo.json @@ -1,18 +1,18 @@ { "en": "Angla", - "af": "Afrikansa", - "az": "Azera", + "af": "", + "az": "", "bg": "Bulgara", - "cs": "Ĉeĥa", + "cs": "", "de": "Germana", - "el": "Greka", + "el": "", "eo": "Esperanto", "es": "Hispana", "fr": "Franca", "hy": "Armena", "it": "Itala", - "ja": "Japana", - "ko": "Korea", + "ja": "", + "ko": "", "nb": "Norvega (Bukmola)", "oc": "Okcitana", "pl": "Pola", @@ -22,6 +22,6 @@ "sl": "Slovena", "sv": "Sveda", "tr": "Turka", - "vi": "Vjetnama", + "vi": "", "zhCN": "Ĉina (Ĉinuja)" -} +} \ No newline at end of file diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-es.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-es.json index cdecbad87..353a4a95a 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-es.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-es.json @@ -1,6 +1,6 @@ { "en": "Inglés", - "af": "Afrikáans", + "af": "Africano", "bg": "Búlgaro", "ca": "Catalán", "cs": "Checo", @@ -12,7 +12,7 @@ "esUS": "Español (América Latina)", "fi": "Finlandés", "fr": "Francés", - "frCA": "Francés (Canadiense)", + "frCA": "Franco (Canadiense)", "he": "Hebreo", "hr": "Croata", "hu": "Húngaro", @@ -30,7 +30,5 @@ "tr": "Turco", "vi": "Vietnamita", "zhCN": "Chino (China)", - "zhTW": "Chino (Taiwán)", - "et": "Estonio", - "da": "Danés" + "zhTW": "Chino (Taiwan)" } diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-fi.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-fi.json index 75c29e231..89fb1ac95 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-fi.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-fi.json @@ -1,38 +1,27 @@ { - "en": "englanti", - "af": "afrikaans", + "en": "", + "af": "", "az": "", - "bg": "bulgaria", - "cs": "tšekki", - "de": "saksa", - "el": "kreikka", - "eo": "esperanto", - "es": "espanja", - "fr": "ranska", - "hy": "armenia", - "it": "italia", - "ja": "japani", - "ko": "korea", + "bg": "", + "cs": "", + "de": "", + "el": "", + "eo": "", + "es": "", + "fr": "", + "hy": "", + "it": "", + "ja": "", + "ko": "", "nb": "", - "oc": "oksitaani", - "pl": "puola", - "ptBR": "portugali (Brasilia)", - "ru": "venäjä", + "oc": "", + "pl": "", + "ptBR": "", + "ru": "", "sk": "", "sl": "", - "sv": "ruotsi", - "tr": "turkki", - "vi": "vietnam", - "zhCN": "kiina (Kiina)", - "zhTW": "kiina (Taiwan)", - "nl": "hollanti", - "hu": "unkari", - "hr": "kroaatti", - "frCA": "ranska (Kanada)", - "fi": "suomi", - "et": "viro", - "esUS": "espanja (Latinalainen Amerikka)", - "enGB": "englanti (Yhdistynyt kuningaskunta)", - "da": "tanska", - "ca": "katalaani" -} + "sv": "", + "tr": "", + "vi": "", + "zhCN": "" +} \ No newline at end of file diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-fr.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-fr.json index 9624c7f4b..bdd3634b6 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-fr.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-fr.json @@ -6,13 +6,13 @@ "cs": "Tchèque", "de": "Allemand", "el": "Grec", - "enGB": "Anglais (Royaume-Uni)", + "enGB": "Anglais (Royaume-Uni) ", "eo": "Espéranto", "es": "Espagnol", "esUS": "Espagnol (Amérique latine)", - "fi": "Finnois", + "fi": "Finlandais", "fr": "Français", - "frCA": "Français (Canada)", + "frCA": "Français (Canadien)", "hr": "Croate", "hu": "Hongrois", "hy": "Arménien", @@ -29,7 +29,5 @@ "tr": "Turc", "vi": "Vietnamien", "zhCN": "Chinois (Chine)", - "zhTW": "Chinois (Taiwan)", - "et": "Estonien", - "da": "Danois" -} + "zhTW": "Chinois (Taiwan)" +} \ No newline at end of file diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-frCA.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-frCA.json index f0a3960fd..f721c9284 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-frCA.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-frCA.json @@ -6,11 +6,11 @@ "cs": "Tchèque", "de": "Allemand", "el": "Grec", - "enGB": "Anglais (Royaume-Uni)", + "enGB": "Anglais (Royaume-Uni) ", "eo": "Espéranto", "es": "Espagnol", "esUS": "Espagnol (Amérique latine)", - "fi": "Finnois", + "fi": "Finlandais", "fr": "Français", "frCA": "Français (Canadien)", "hr": "Croate", @@ -29,7 +29,5 @@ "tr": "Turc", "vi": "Vietnamien", "zhCN": "Chinois (Chine)", - "zhTW": "Chinois (Taiwan)", - "et": "Estonien", - "da": "Danois" -} + "zhTW": "Chinois (Taiwan)" +} \ No newline at end of file diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-hu.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-hu.json index d40d1dfb8..1d5f7208b 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-hu.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-hu.json @@ -29,7 +29,5 @@ "tr": "Török", "vi": "Vietnámi", "zhCN": "Kínai (Kína)", - "zhTW": "Kínai (Tajvan)", - "et": "Észt", - "da": "Dán" -} + "zhTW": "Kínai (Tajvan)" +} \ No newline at end of file diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-it.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-it.json index 218e97a66..87544b281 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-it.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-it.json @@ -23,16 +23,5 @@ "sv": "Svedese", "tr": "Turco", "vi": "Vietnamita", - "zhCN": "Cinese (Cina)", - "enGB": "Inglese (Regno Unito)", - "da": "Danese", - "ca": "Catalano", - "zhTW": "", - "nl": "", - "hu": "", - "hr": "", - "frCA": "", - "fi": "", - "et": "", - "esUS": "" + "zhCN": "Cinese (Cina)" } diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-oc.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-oc.json index 1c343a6d7..052500bda 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-oc.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-oc.json @@ -28,7 +28,5 @@ "tr": "Turc", "vi": "Vietnamian", "zhCN": "Chinés (China)", - "zhTW": "Chinés (Taiwan)", - "et": "Estonian", - "da": "Danés" -} + "zhTW": "Chinés (Taiwan)" +} \ No newline at end of file diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-ru.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-ru.json index 0e7266fb1..a02c8c060 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-ru.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-ru.json @@ -28,7 +28,5 @@ "tr": "Турецкий", "vi": "Вьетнамский", "zhCN": "Китайский (Китай)", - "zhTW": "Китайский (Тайвань)", - "et": "Эстонский", - "da": "Датский" -} + "zhTW": "Китайский (Тайвань)" +} \ No newline at end of file diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-sc.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-sc.json deleted file mode 100644 index 641d95721..000000000 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-sc.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "en": "Inglesu", - "af": "Afrikaans", - "bg": "Bùlgaru", - "ca": "Catalanu", - "cs": "Tzecu", - "da": "Danesu", - "de": "Tedescu", - "el": "Gregu", - "enGB": "Inglesu (Rennu Unidu)", - "eo": "Esperanto", - "es": "Castillianu", - "esUS": "Castillianu (Amèrica de su Sud)", - "fi": "Finlandesu", - "fr": "Frantzesu", - "frCA": "Frantzesu (Canadesu)", - "hr": "Croatu", - "hu": "Ungheresu", - "hy": "Armenu", - "it": "Italianu", - "ja": "Giaponesu", - "ko": "Coreanu", - "nl": "Olandesu", - "oc": "Otzitanu", - "pl": "Polacu", - "ptBR": "Portughesu (Brasile)", - "ru": "Russu", - "sc": "Sardu", - "sv": "Isvedesu", - "tr": "Turcu", - "vi": "Vietnamita", - "zhCN": "Tzinesu (Tzina)", - "zhTW": "Tzinesu (Taiwan)" -} diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-sk.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-sk.json deleted file mode 100644 index 59ac50b17..000000000 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-sk.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "en": "Angličtina", - "af": "", - "bg": "Bulharština", - "ca": "Katalánština", - "cs": "Čeština", - "da": "Dánština", - "de": "Nemčina", - "el": "Gréčtina", - "enGB": "Angličtina (Spojené kráľovstvo)", - "eo": "Esperanto", - "es": "Španielčina", - "esUS": "Angličtina (Spojené štáty americké)", - "et": "Estónčina", - "fi": "Fínčina", - "fr": "Francúžtina", - "frCA": "Francúžtina (Kanada)", - "hr": "Chorvátčina", - "hu": "Maďarčina", - "hy": "Arménčina", - "it": "Taliančina", - "ja": "Japončina", - "ko": "Kórejčina", - "nl": "Holandčina", - "oc": "Okcitánština", - "pl": "Polština", - "ptBR": "Portugalčina", - "ru": "Ruština", - "sk": "Slovenčina", - "sv": "Švédčina", - "tr": "Turečtina", - "vi": "Vietnamčina", - "zhCN": "Čínština (Čína)", - "zhTW": "Čínština (Taiwan)" -} \ No newline at end of file diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-sv.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-sv.json index 685ed2532..9908c438a 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-sv.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-sv.json @@ -1,18 +1,18 @@ { "en": "Engelska", - "af": "Afrikaans", + "af": "", "az": "", "bg": "Bulgariska", - "cs": "Tjeckiska", + "cs": "", "de": "Tyska", - "el": "Grekiska", + "el": "", "eo": "Esperanto", "es": "Spanska", "fr": "Franska", "hy": "Armeniska", "it": "Italienska", - "ja": "Japanska", - "ko": "Koreanska", + "ja": "", + "ko": "", "nb": "Norska (Bokmål)", "oc": "Occitanska", "pl": "Polska", @@ -22,17 +22,6 @@ "sl": "Slovenska", "sv": "Svenska", "tr": "Turkiska", - "vi": "Vietnamesiska", - "zhCN": "Kinesiska (Kina)", - "zhTW": "Kinesiska (Taiwan)", - "nl": "Nederländska", - "hu": "Ungerska", - "hr": "Kroatiska", - "frCA": "Franska (Kanada)", - "fi": "Finska", - "et": "Estniska", - "esUS": "Spanska (Latinamerika)", - "enGB": "Engelska (Storbritannien)", - "da": "Danska", - "ca": "Katalanska" -} + "vi": "", + "zhCN": "Kinesiska (Kina)" +} \ No newline at end of file diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-tr.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-tr.json deleted file mode 100644 index f0fe0e529..000000000 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages-tr.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "en": "İngilizce", - "af": "Afrikanca", - "az": "", - "bg": "Bulgarca", - "cs": "Çekçe", - "de": "Almanca", - "el": "Yunanca", - "eo": "Esperanto", - "es": "İspanyolca", - "fr": "Fransızca", - "hy": "Ermenice", - "it": "İtalyanca", - "ja": "Japonca", - "ko": "Korece", - "nb": "Norveççe Bokmal", - "oc": "Oksitan dili", - "pl": "Lehçe", - "ptBR": "Portekizce (Brezilya)", - "ru": "Rusça", - "sk": "Slovakça", - "sl": "Slovence", - "sv": "Isveççe", - "tr": "Türkçe", - "vi": "Vietnamca", - "zhCN": "Çince (Çin)", - "zhTW": "Çince (Tayvan)", - "nl": "Flemenkçe", - "hu": "Macarca", - "hr": "Hırvatça", - "frCA": "Fransızca (Kanada)", - "fi": "Fince", - "et": "Estonca", - "esUS": "İspanyolca (Latin Amerika)", - "enGB": "İngilizce (Birleşik Krallık)", - "da": "Danca", - "ca": "Katalanca" -} diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages.json index 805a796ea..fe0cff36d 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/languages.json @@ -12,7 +12,6 @@ "es": "Spanish", "esUS": "Spanish (Latin America)", "et": "Estonian", - "eu": "Basque", "fi": "Finnish", "fr": "French", "frCA": "French (Canadian)", @@ -20,7 +19,6 @@ "hr": "Croatian", "hu": "Hungarian", "hy": "Armenian", - "id": "Indonesian", "it": "Italian", "ja": "Japanese", "ko": "Korean", @@ -33,9 +31,7 @@ "sc": "Sardinian", "sk": "Slovak", "sv": "Swedish", - "th": "Thailand", "tr": "Turkish", - "uk": "Ukrainian", "vi": "Vietnamese", "zhCN": "Chinese (China)", "zhTW": "Chinese (Taiwan)" diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-af.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-af.json index cf12f8603..439b29cd9 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-af.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-af.json @@ -145,9 +145,9 @@ "cameraUnsupportedResolutionError": "Die kamera ondersteun nie die nodige videoresolusie nie.", "Cancel": "Kanselleer", "close": "Sluit", - "conferenceDisconnectMsg": "Kontroleer dalk die netwerkverbinding. Gaan oor {{seconds}} sekondes weer koppel…", + "conferenceDisconnectMsg": "Kontroleer dalk die netwerkverbinding. Gaan oor {{seconds}} sekondes weer koppel...", "conferenceDisconnectTitle": "Die verbinding is verbreek.", - "conferenceReloadMsg": "Ons probeer om dit reg te stel. Gaan herkoppel oor {{seconds}} sekondes…", + "conferenceReloadMsg": "Ons probeer om dit reg te stel. Gaan herkoppel oor {{seconds}} sekondes...", "conferenceReloadTitle": "Iets het ongelukkig skeefgeloop.", "confirm": "Bevestig", "confirmNo": "Nee", @@ -254,7 +254,7 @@ "userPassword": "gebruikerwagwoord", "WaitForHostMsg": "", "WaitForHostMsgWOk": "", - "WaitingForHost": "Wag tans vir die gasheer …", + "WaitingForHost": "Wag tans vir die gasheer ...", "Yes": "Ja", "yourEntireScreen": "U hele skerm" }, @@ -349,13 +349,13 @@ "errorLiveStreamNotEnabled": "Regstreekse stroom is nie geaktiveer op {{email}} nie. Aktiveer asb. regstreekse strome of meld aan met ’n rekening met regstreekse strome geaktiveer.", "expandedOff": "Die regstreekse stroom het gestop", "expandedOn": "Die vergadering word tans gestroom na YouTube.", - "expandedPending": "Die regstreekse stroom begin tans…", + "expandedPending": "Die regstreekse stroom begin tans...", "failedToStart": "Regstreekse stroom kon nie begin nie", "getStreamKeyManually": "", "invalidStreamKey": "", "off": "Regstreekse stroom het gestop", "on": "Regstreekse stroom", - "pending": "Begin tans regstreekse stroom…", + "pending": "Begin tans regstreekse stroom...", "serviceName": "Regstreekse stroomdiens", "signedInAs": "U is tans aangemeld as:", "signIn": "Meld aan met Google", @@ -433,22 +433,22 @@ "poweredby": "aangedryf deur", "presenceStatus": { "busy": "Besig", - "calling": "Bel tans…", + "calling": "Bel tans...", "connected": "Gekoppel", - "connecting": "Koppel tans…", + "connecting": "Koppel tans...", "connecting2": "Koppel tans*...", "disconnected": "Ontkoppeld", "expired": "Verval", "ignored": "Geïgnoreer", - "initializingCall": "Inisialiseer tans oproep…", + "initializingCall": "Inisialiseer tans oproep...", "invited": "Uitgenooi", "rejected": "Geweier", - "ringing": "Lui tans…" + "ringing": "Lui tans..." }, "profile": { "setDisplayNameLabel": "Stel u vertoonnaam", "setEmailInput": "Gee e-posadres", - "setEmailLabel": "Stel u Gravatar-e-posadres", + "setEmailLabel": "Stel u gravatar-e-posadres", "title": "Profiel" }, "recording": { @@ -460,14 +460,14 @@ "error": "Opname het misluk. Probeer gerus weer.", "expandedOff": "Opname het gestop", "expandedOn": "Die vergadering word tans opgeneem.", - "expandedPending": "Opname word begin…", + "expandedPending": "Opname word begin...", "failedToStart": "Kon nie begin opneem nie", "fileSharingdescription": "", "live": "", "loggedIn": "Aangemeld as {{name}}", "off": "Opname gestop", "on": "Neem tans op", - "pending": "Berei voor om vergadering op te neem…", + "pending": "Berei voor om vergadering op te neem...", "rec": "", "serviceDescription": "", "serviceName": "Opneemdiens", @@ -563,7 +563,7 @@ "recording": "Wissel opname", "remoteMute": "", "Settings": "Wissel instellings", - "sharedvideo": "Wissel YouTube-videodeling", + "sharedvideo": "Wissel Youtube-videodeling", "shareRoom": "Nooi iemand", "shareYourScreen": "Wissel skermdeling", "shortcuts": "Wissel kortpaaie", @@ -625,7 +625,7 @@ "failedToStart": "", "labelToolTip": "Die vergadering word getranskribeer", "off": "", - "pending": "Berei tans voor om die vergadering te transkribeer…", + "pending": "Berei tans voor om die vergadering te transkribeer...", "start": "", "stop": "", "tr": "" @@ -709,4 +709,4 @@ "terms": "Voorwaardes", "title": "Veilige en volledig gratis videokonferensies propvol funksionaliteit" } -} +} \ No newline at end of file diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-bg.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-bg.json index 748569536..984eac1eb 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-bg.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-bg.json @@ -477,7 +477,7 @@ "profile": { "setDisplayNameLabel": "Задайте екранното си име", "setEmailInput": "Въведете е-поща", - "setEmailLabel": "Задайте е-пощата си в „Gravatar“", + "setEmailLabel": "Задайте е-пощата си в „gravatar“", "title": "Профил" }, "raisedHand": "Иска думата", diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-ca.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-ca.json deleted file mode 100644 index ea9f51e86..000000000 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-ca.json +++ /dev/null @@ -1,787 +0,0 @@ -{ - "addPeople": { - "add": "Convida", - "countryNotSupported": "Encara no és possible usar aquesta destinació.", - "countryReminder": "Truqueu des de fora els EUA? Assegureu-vos que comenceu b el codi de país!", - "disabled": "No podeu convidar-hi persones.", - "failedToAdd": "No s'han pogut afegir-hi participants", - "footerText": "La marcació està desactivada.", - "loading": "S'estan cercant persones i números de telèfon", - "loadingNumber": "S'està validant el número de telèfon", - "loadingPeople": "S'estan cercant les persones a convidar", - "noResults": "No s'ha trobat cap resultat coincident", - "noValidNumbers": "Introduïu un número de telèfon", - "searchNumbers": "Afegeix-hi números de telèfon", - "searchPeople": "Cerca-hi persones", - "searchPeopleAndNumbers": "Cerca persones o n'afegeix els números de telèfon", - "telephone": "Telèfon: {{number}}", - "title": "Convida persones a aquesta reunió" - }, - "audioDevices": { - "bluetooth": "Bluetooth", - "headphones": "Auriculars", - "phone": "Telèfon", - "speaker": "Altaveu", - "none": "No hi ha disponible cap aparell d'àudio" - }, - "audioOnly": { - "audioOnly": "Poc ample de banda" - }, - "calendarSync": { - "addMeetingURL": "Afegeix un enllaç de reunió", - "confirmAddLink": "Voleu afegir un enllaç Jitsi en aquest esdeveniment?", - "error": { - "appConfiguration": "La integració de l'agenda no està configurada correctament.", - "generic": "S'ha produït un error. Comproveu la configuració de l'agenda o intenteu d'actualitzar-la.", - "notSignedIn": "S'ha produït un error en l'autenticació per a visualitzar els esdeveniments del calendari. Reviseu la configuració de l'agenda i intenteu a iniciar la sessió més endavant." - }, - "join": "Afegeix-m'hi", - "joinTooltip": "Uniu-vos a la reunió", - "nextMeeting": "reunió següent", - "noEvents": "No hi ha cap esdeveniment previst a l'agenda.", - "ongoingMeeting": "reunió en curs", - "permissionButton": "Obre la configuració", - "permissionMessage": "Es requereix el permís d'agenda per a veure les reunions en l'aplicació.", - "refresh": "Actualitza l'agenda", - "today": "Avui" - }, - "chat": { - "error": "Error: no s'ha enviat el vostre missatge. Raó: {{error}}", - "fieldPlaceHolder": "Escriviu aquí el missatge", - "messagebox": "Escriviu un missatge", - "messageTo": "Missatge privat per a {{recipient}}", - "noMessagesMessage": "Encara no hi ha cap missatge en aquesta reunió. Comenceu una conversa aquí!", - "nickname": { - "popover": "Trieu un sobrenom", - "title": "Introduïu un sobrenom per a usar el xat" - }, - "privateNotice": "Missatge privat per a {{recipient}}", - "title": "Xat", - "you": "vós" - }, - "chromeExtensionBanner": { - "installExtensionText": "Instal·la l'extensió per a la integració amb Google Calendar i Office 365", - "buttonText": "Instal·la l'extensió de Chrome", - "dontShowAgain": "No m'ho mostris més" - }, - "connectingOverlay": { - "joiningRoom": "S'està connectat a la reunió…" - }, - "connection": { - "ATTACHED": "Adjunt", - "AUTHENTICATING": "S'està autenticant", - "AUTHFAIL": "L'autenticació ha fallat", - "CONNECTED": "Connectat", - "CONNECTING": "S'està connectant", - "CONNFAIL": "La connexió ha fallat", - "DISCONNECTED": "Desconnectat", - "DISCONNECTING": "S'està desconnectant", - "ERROR": "Error", - "FETCH_SESSION_ID": "S'està obtenint un identificador de sessió…", - "GET_SESSION_ID_ERROR": "S'ha produït un error en obtenir l'identificador de la sessió: {{code}}", - "GOT_SESSION_ID": "Obtenció d'identificador de sessió… Fet", - "LOW_BANDWIDTH": "S'ha apagat el vídeo de {{displayName}} per a estalviar ample de banda" - }, - "connectionindicator": { - "address": "Adreça:", - "bandwidth": "Ample de banda estimat:", - "bitrate": "Taxa de bits:", - "bridgeCount": "Nombre de servidors: ", - "connectedTo": "Connectat a:", - "e2e_rtt": "E2E RTT:", - "framerate": "Taxa de fotogrames:", - "less": "Menys informació", - "localaddress": "Adreça local:", - "localaddress_plural": "Adreces locals:", - "localport": "Port local:", - "localport_plural": "Ports locals:", - "more": "Més informació", - "packetloss": "Pèrdua de paquets:", - "quality": { - "good": "Bona", - "inactive": "Inactiva", - "lost": "Perduda", - "nonoptimal": "No òptima", - "poor": "Pobra" - }, - "remoteaddress": "Adreça remota:", - "remoteaddress_plural": "Adreces remotes:", - "remoteport": "Port remot:", - "remoteport_plural": "Ports remots:", - "resolution": "Resolució:", - "status": "Connexió:", - "transport": "Transport:", - "transport_plural": "Transports:" - }, - "dateUtils": { - "earlier": "Abans", - "today": "Avui", - "yesterday": "Ahir" - }, - "deepLinking": { - "appNotInstalled": "Us cal l'aplicació mòbil {{app}} per a unir-vos a aquesta reunió des del vostre telèfon.", - "description": "No ha passat res? Hem intentat iniciar la reunió en l'aplicació d'escriptori {{app}}. Torneu a intentar-ho en l'aplicació web {{app}}.", - "descriptionWithoutWeb": "No ha passat res? Hem intentat iniciar la reunió en l'aplicació d'escriptori {{app}}.", - "downloadApp": "Baixa l'aplicació", - "launchWebButton": "Inicia al web", - "openApp": "Continua en l'aplicació", - "title": "S'està iniciant la reunió en {{app}}…", - "tryAgainButton": "Torna-ho a intentar en l'escriptori" - }, - "defaultLink": "p. ex. {{url}}", - "defaultNickname": "p. ex. Pere Cullera", - "deviceError": { - "cameraError": "No s'ha pogut accedir a la càmera", - "cameraPermission": "S'ha produït un error en obtenir el permís de la càmera", - "microphoneError": "No s'ha pogut accedir al micròfon", - "microphonePermission": "S'ha produït un error en obtenir el permís del micròfon" - }, - "deviceSelection": { - "noPermission": "No s'ha concedit el permís", - "previewUnavailable": "La previsualització no és disponible", - "selectADevice": "Seleccioneu un aparell", - "testAudio": "Reprodueix un so de prova" - }, - "dialog": { - "accessibilityLabel": { - "liveStreaming": "Transmissió en directe" - }, - "allow": "Permet", - "alreadySharedVideoMsg": "Un altre participant està compartint un vídeo. Aquesta conferència només permet compartir un vídeo a la vegada.", - "alreadySharedVideoTitle": "Només es permet un vídeo compartit a la vegada", - "applicationWindow": "Finestra de l'aplicació", - "Back": "Enrere", - "cameraConstraintFailedError": "La càmera no satisfà algun dels requeriments.", - "cameraNotFoundError": "No s'ha trobat cap càmera.", - "cameraNotSendingData": "No podem accedir a la càmera. Comproveu si alguna una aplicació l'està usant, seleccioneu un altre aparell en el menú de configuració o intenteu de recarregar l'aplicació.", - "cameraNotSendingDataTitle": "No s'ha pogut accedir a la càmera", - "cameraPermissionDeniedError": "No heu concedit permís per a usar la càmera. Encara podeu unir-vos a la conferència però els altres participants no us veuran. Useu el botó de la càmera en la barra d'adreces per a corregir això.", - "cameraUnknownError": "Per algun motiu desconegut, no es pot usar la càmera.", - "cameraUnsupportedResolutionError": "La vostra càmera no permet la resolució de vídeo requerida.", - "Cancel": "Cancel·la", - "close": "Tanca", - "conferenceDisconnectMsg": "Potser vulgueu comprovar la connexió a la xarxa. Es tornarà a connecta en {{seconds}} segons…", - "conferenceDisconnectTitle": "Esteu desconnectat.", - "conferenceReloadMsg": "Estem intentat de corregir-ho. Tornem a connectar en {{seconds}} segons…", - "conferenceReloadTitle": "Malauradament, alguna cosa no ha anat bé.", - "confirm": "Confirmo", - "confirmNo": "No", - "confirmYes": "Sí", - "connectError": "Vaja! Alguna cosa no ha anat bé i no podem connectar a la conferència.", - "connectErrorWithMsg": "Vaja! Alguna cosa no ha anat bé i no podem connectar a la conferència: {{msg}}", - "connecting": "S'està connectant", - "contactSupport": "Contacte amb l'assistència", - "copy": "Copia", - "dismiss": "Descarta", - "displayNameRequired": "Hola! Com us dieu?", - "done": "Fet", - "enterDisplayName": "Introduïu aquí el vostre nom", - "error": "Error", - "externalInstallationMsg": "Cal que instal·leu l'extensió de compartició d'escriptori.", - "externalInstallationTitle": "Es requereix una extensió", - "goToStore": "Aneu a la botiga d'aplicacions web", - "gracefulShutdown": "El nostre servei ara mateix és en manteniment. Torneu-ho a intentar més tard.", - "IamHost": "Sóc l'amfitrió", - "incorrectRoomLockPassword": "La contrasenya no és correcta", - "incorrectPassword": "El nom o la contrasenya no són correctes", - "inlineInstallationMsg": "Cal que instal·leu l'extensió de compartició de l'extensió.", - "inlineInstallExtension": "Instal·la-ho ara", - "internalError": "Vaja! Alguna cosa no ha anat bé. S'ha produït l'error següent: {{error}}", - "internalErrorTitle": "Error intern", - "kickMessage": "Per a més detalls, podeu contactar amb {{participantDisplayName}}.", - "kickParticipantButton": "Expulsa", - "kickParticipantDialog": "Esteu segur que voleu expulsar aquest participant?", - "kickParticipantTitle": "Voleu expulsar aquest participant?", - "kickTitle": "Ep! {{participantDisplayName}} us ha expulsat de la reunió", - "liveStreaming": "Transmissió en directe", - "liveStreamingDisabledForGuestTooltip": "Els convidats no poden iniciar la transmissió en directe.", - "liveStreamingDisabledTooltip": "No es pot iniciar la transmissió en directe.", - "lockMessage": "No s'ha pogut blocar la conferència.", - "lockRoom": "Afegeix la reunió $t(lockRoomPasswordUppercase)", - "lockTitle": "El blocatge ha fallat", - "logoutQuestion": "Esteu segur de voler tancar la sessió i aturar la conferència?", - "logoutTitle": "Tanca la sessió", - "maxUsersLimitReached": "S'ha assolit el nombre màxim de participants. La conferència és plena. Contacteu amb el propietari de la reunió o torneu-ho a intentar més tard!", - "maxUsersLimitReachedTitle": "S'ha assolit el límit màxim de participants", - "micConstraintFailedError": "La càmera no satisfà algun dels requeriments.", - "micNotFoundError": "No s'ha trobat cap micròfon.", - "micNotSendingData": "Aneu a la configuració de l'ordinador per a activar el micròfon i ajusteu-ne el nivell", - "micNotSendingDataTitle": "El micròfon està silenciat en la configuració del sistema", - "micPermissionDeniedError": "No heu concedit permís per a usar el micròfon. Encara podeu unir-vos a la conferència però els altres participants no us sentiran. Useu el botó de micròfon en la barra d'adreces per a corregir això.", - "micUnknownError": "No es pot usar el micròfon per alguna raó desconeguda.", - "muteEveryoneElseDialog": "Una vegada silenciats, no podreu activar-ne els micròfons, però podran activar-lo ells mateixos en qualsevol moment.", - "muteEveryoneElseTitle": "Voleu silenciar tothom excepte {{whom}}?", - "muteEveryoneDialog": "Esteu segur que voleu silenciar tothom? No podreu activar-los el micròfon, però ells mateixos podran activar el micròfon respectiu en qualsevol moment.", - "muteEveryoneTitle": "Voleu silenciar tothom?", - "muteEveryoneSelf": "vós mateix", - "muteEveryoneStartMuted": "Tothom comença en silenci a partir d'ara", - "muteParticipantBody": "No podreu activar-ne els micròfons, però ells podran activar-ne el seu en qualsevol moment.", - "muteParticipantButton": "Silencia", - "muteParticipantDialog": "Esteu segur que voleu silenciar aquest participant? No podreu activar-li el micròfon, però sí que podrà fer-ho ell mateix en qualsevol moment.", - "muteParticipantTitle": "Voleu silenciar aquest participant?", - "Ok": "D'acord", - "passwordLabel": "Un participant ha blocat la reunió. Introduïu una $t(lockRoomPassword) per a unirvos-hi.", - "passwordNotSupported": "No és possible definir una $t(lockRoomPassword).", - "passwordNotSupportedTitle": "No se suporta la $t(lockRoomPassword)", - "passwordRequired": "Es requereix una $t(lockRoomPassword)", - "popupError": "El vostre navegador bloca les finestres emergents d'aquest lloc. Habiliteu les finestres emergents a la configuració de seguretat del navegador i torneu-ho a intentar.", - "popupErrorTitle": "Finestres emergents blocades", - "recording": "Enregistrament", - "recordingDisabledForGuestTooltip": "Els convidats no poden iniciar enregistraments.", - "recordingDisabledTooltip": "No es pot enregistrar.", - "rejoinNow": "Torna a entrar ara", - "remoteControlAllowedMessage": "{{user}} ha acceptat la petició de control remot!", - "remoteControlDeniedMessage": "{{user}} ha rebutjat la petició de control remot!", - "remoteControlErrorMessage": "S'ha produït un error en intentar sol·licitar a {{user}} permisos de control remot!", - "remoteControlRequestMessage": "Voleu permetre a {{user}} de controlar remotament el vostre escriptori?", - "remoteControlShareScreenWarning": "Tingueu present que si pitgeu \"Permet\" compartireu la vostra pantalla!", - "remoteControlStopMessage": "La sessió de control remot ha finalitzat!", - "remoteControlTitle": "Control d'escriptori remot", - "Remove": "Suprimeix", - "removePassword": "Suprimeix la $t(lockRoomPassword)", - "removeSharedVideoMsg": "Esteu segur que voleu suprimir el vídeo compartit?", - "removeSharedVideoTitle": "Suprimeix aquest vídeo compartit", - "reservationError": "S'ha produït un error de reserva de sistema", - "reservationErrorMsg": "Codi d'error: {{code}}, missatge: {{msg}}", - "retry": "Torna a intentar-ho", - "screenSharingFailedToInstall": "Vaja! No s'ha pogut instal·lar l'extensió de compartició de pantalla.", - "screenSharingFailedToInstallTitle": "No s'ha pogut instal·lar l'extensió de compartició de pantalla", - "screenSharingFirefoxPermissionDeniedError": "Alguna cosa no ha anat bé en intentar compartir la pantalla. Assegureu-vos que heu donat el permís per a fer-ho. ", - "screenSharingFirefoxPermissionDeniedTitle": "Vaja! No hem pogut iniciar la compartició de pantalla!", - "screenSharingPermissionDeniedError": "Vaja! Alguna cosa no ha anat bé amb els permisos de l'extensió de compartició de pantalla. Torneu a carregar i intenteu-ho una altra vegada.", - "sendPrivateMessage": "Fa poc que heu rebut un missatge privat. Voleu respondre'l de forma privada, o voleu enviar el missatge al grup?", - "sendPrivateMessageCancel": "Envia'l al grup", - "sendPrivateMessageOk": "Envia'l en privat", - "sendPrivateMessageTitle": "Voleu enviar-lo en privat?", - "serviceUnavailable": "El servei no és disponible", - "sessTerminated": "La trucada ha finalitzat", - "Share": "Comparteix", - "shareVideoLinkError": "Proporcioneu un enllaç de YouTube correcte.", - "shareVideoTitle": "Comparteix un vídeo", - "shareYourScreen": "Comparteix la pantalla", - "shareYourScreenDisabled": "S'ha inhabilitat la compartició de pantalla.", - "shareYourScreenDisabledForGuest": "Els convidats no poden compartir la pantalla.", - "startLiveStreaming": "Inicia la transmissió en directe", - "startRecording": "Inicia l'enregistrament", - "startRemoteControlErrorMessage": "S'ha produït un error en intentar iniciar la sessió de control remot!", - "stopLiveStreaming": "Atura la transmissió en directe", - "stopRecording": "Atura l'enregistrament", - "stopRecordingWarning": "Esteu segur de voler aturar l'enregistrament?", - "stopStreamingWarning": "Esteu segur de voler aturar la transmissió en directe?", - "streamKey": "Clau de transmissió en directe", - "Submit": "Tramet", - "thankYou": "Gràcies per emprar {{appName}}!", - "token": "identificador", - "tokenAuthFailed": "No esteu autoritzat a unir-vos a aquesta trucada.", - "tokenAuthFailedTitle": "L'autenticació ha fallat", - "transcribing": "Transcripció", - "unlockRoom": "Suprimeix la $t(lockRoomPassword) de la reunió", - "userPassword": "contrasenya d'usuari", - "WaitForHostMsg": "La conferència <b>{{room}}</b> encara no ha començat. Si en sou l'amfitrió autentiqueu-vos. Altrament, espereu que arribi l'amfitrió.", - "WaitForHostMsgWOk": "La conferència <b>{{room}}</b> encara no ha començat. Si sou l'amfitrió aleshores pitgeu «D'acord» per a autenticar-vos. Altrament, espereu que arribi l'amfitrió.", - "WaitingForHost": "S'està esperant l'amfitrió…", - "Yes": "Sí", - "yourEntireScreen": "La pantalla sencera", - "screenSharingAudio": "Comparteix l'àudio" - }, - "dialOut": { - "statusMessage": "ara és {{status}}" - }, - "documentSharing": { - "title": "Document compartit" - }, - "feedback": { - "average": "Mitjana", - "bad": "Dolenta", - "detailsLabel": "Expliqueu-nos més sobre això.", - "good": "Bona", - "rateExperience": "Valoreu l'experiència de reunió", - "veryBad": "Molt dolenta", - "veryGood": "Molt bona" - }, - "incomingCall": { - "answer": "Resposta", - "audioCallTitle": "Trucada entrant", - "decline": "Rebutja", - "productLabel": "de Jitsi Meet", - "videoCallTitle": "Videotrucada entrant" - }, - "info": { - "accessibilityLabel": "Mostra la informació", - "addPassword": "Afegeix una $t(lockRoomPassword)", - "cancelPassword": "Cancel·la $t(lockRoomPassword)", - "conferenceURL": "Enllaç:", - "country": "País", - "dialANumber": "Per a unir-vos a la reunió, marqueu un d'aquests números i aleshores introduïu el PIN.", - "dialInConferenceID": "PIN:", - "dialInNotSupported": "El marcatge ara mateix no és permés.", - "dialInNumber": "Marcatge:", - "dialInSummaryError": "S'ha produït un error en obtenir la informació de marcatge. Torneu-ho a intentar més tard.", - "dialInTollFree": "Sense peatges", - "genericError": "Vaja, alguna cosa no ha anat bé.", - "inviteLiveStream": "Per a veure la transmissió en directe d'aquesta reunió, feu clic en aquest enllaç: {{url}}", - "invitePhone": "Per a unir-vos per telèfon, toqueu això: {{number}},,{{conferenceID}}#\n", - "invitePhoneAlternatives": "Esteu cercant un número de marcatge diferent?\nVegeu els números de marcatge de la reunió: {{url}}\n\n\nSi també truqueu via un telèfon de reunió, uniu-vos-hi sense connectar l'àudio: {{silentUrl}}", - "inviteURLFirstPartGeneral": "Us han convidat a unir-vos a una reunió.", - "inviteURLFirstPartPersonal": "{{name}} us convida a una reunió.\n", - "inviteURLSecondPart": "\nUniu-vos a la reunió:\n{{url}}\n", - "liveStreamURL": "Transmissió en directe:", - "moreNumbers": "Més números", - "noNumbers": "Sense números de marcatge.", - "noPassword": "Cap", - "noRoom": "No s'ha indicat cap sala a què marcar.", - "numbers": "Números de marcatge", - "password": "$t(lockRoomPasswordUppercase):", - "title": "Comparteix", - "tooltip": "Comparteix l'enllaç i la informació de marcatge d'aquesta reunió", - "label": "Informació de la reunió" - }, - "inviteDialog": { - "alertText": "No s'ha pogut convidar alguns participants.", - "header": "Convida", - "searchCallOnlyPlaceholder": "Introduïu el número de telèfon", - "searchPeopleOnlyPlaceholder": "Cerca participants", - "searchPlaceholder": "Participant o número de telèfon", - "send": "Envia" - }, - "inlineDialogFailure": { - "msg": "Vam ensopegar una mica.", - "retry": "Torneu-ho a intentar", - "support": "Assistència", - "supportMsg": "Si segueix passant, feu-nos-ho saber" - }, - "keyboardShortcuts": { - "focusLocal": "Focus al vostre vídeo", - "focusRemote": "Focus en el vídeo d'una altra persona", - "fullScreen": "Entra o surt de la pantalla completa", - "keyboardShortcuts": "Dreceres de teclat", - "localRecording": "Mostra o amaga els controls d'enregistrament local", - "mute": "Silencia o activa el micròfon", - "pushToTalk": "Premeu per a parlar", - "raiseHand": "Aixeca o abaixa la mà", - "showSpeakerStats": "Mostra les estadístiques de l'interlocutor", - "toggleChat": "Obre o tanca el xat", - "toggleFilmstrip": "Mostra o amaga les miniatures de vídeo", - "toggleScreensharing": "Canvia entre la càmera i la compartició de pantalla", - "toggleShortcuts": "Mostra o amaga les dreceres de teclat", - "videoMute": "Inicia o atura la vostra càmara", - "videoQuality": "Gestiona la qualitat de la trucada" - }, - "liveStreaming": { - "busy": "Treballem per a alliberar recursos de transmissió. Torneu-ho a intentar en uns minuts.", - "busyTitle": "Ara mateix, tots els reproductors són ocupats", - "changeSignIn": "Canvia entre comptes.", - "choose": "Trieu una transmissió en directe", - "chooseCTA": "Trieu una opció de transmissió. Ara mateix teniu sessió iniciada com a {{email}}.", - "enterStreamKey": "Introduïu la clau YouTube de transmissió en directe aquí.", - "error": "La transmissió en directe ha fallat. Torneu-ho a intentar més tard.", - "errorAPI": "S'ha produït un error en accedir a les vostres emissions de Youtube. Torneu a iniciar sessió una altra vegada.", - "errorLiveStreamNotEnabled": "La transmissió en directe no està activada a ̣{{email}}. Activeu-la o inicieu sessió en un compte que tingui la transmissió en directe activada.", - "expandedOff": "S'ha aturat la transmissió en directe", - "expandedOn": "Ara mateix, la reunió s'està transmetent a Youtube.", - "expandedPending": "S'ha iniciat la transmissió en directe…", - "failedToStart": "No s'ha pogut iniciar la transmissió en directe", - "getStreamKeyManually": "No hem pogut obtenir cap transmissió en directe. Intenteu d'obtenir la clau de transmissió en directe del YouTube.", - "invalidStreamKey": "La clau de transmissió en directe pot ser incorrecta.", - "off": "S'ha aturat la transmissió en directe", - "offBy": "{{name}} ha aturat la transmissió en directe", - "on": "Transmissió en directe", - "onBy": "{{name}} ha iniciat la transmissió en directe", - "pending": "S'està iniciant la transmissió en directe…", - "serviceName": "Servei de transmissió en directe", - "signedInAs": "Teniu sessió iniciada com a:", - "signIn": "Inicia sessió amb Google", - "signInCTA": "Inicieu sessió o introduïu la clau de transmissió en directe de YouTube.", - "signOut": "Tanca la sessió", - "start": "Inicia la transmissió en directe", - "streamIdHelp": "Què és això?", - "unavailableTitle": "La transmissió en directe no és disponible", - "googlePrivacyPolicy": "Política de privadesa de Google", - "youtubeTerms": "Condicions de servei del Youtube" - }, - "localRecording": { - "clientState": { - "off": "Inactiu", - "on": "Actiu", - "unknown": "Desconegut" - }, - "dialogTitle": "Controls d'enregistrament local", - "duration": "Durada", - "durationNA": "N/D", - "encoding": "Codificació", - "label": "ENREG LOC", - "labelToolTip": "L'enregistrament local està funcionant", - "localRecording": "Enregistrament local", - "me": "Jo", - "messages": { - "engaged": "L'enregistrament local funciona.", - "finished": "La sessió d'enregistrament {{token}} ha finalitzat. Envieu el fitxer enregistrat al moderador.", - "finishedModerator": "La sessió d'enregistrament {{token}} ha finalitzat. L'enregistrament de la part local s'ha desat. Demaneu als altres participants que enviïn els seus enregistraments.", - "notModerator": "No sou el moderador. No podeu iniciar ni aturar un enregistrament local." - }, - "moderator": "Moderador", - "no": "No", - "participant": "Participant", - "participantStats": "Estadístiques del participant", - "sessionToken": "Identificador de la sessió", - "start": "Inicia l'enregistrament", - "stop": "Atura l'enregistrament", - "yes": "Sí" - }, - "lockRoomPassword": "contrasenya", - "lockRoomPasswordUppercase": "Contrasenya", - "me": "jo", - "notify": { - "connectedOneMember": "{{name}} s'ha unit a la reunió", - "connectedThreePlusMembers": "{{name}} i {{count}} persones més s'han unit a la reunió", - "connectedTwoMembers": "{{first}} i {{second}} s'han unit a la reunió", - "disconnected": "desconnectat", - "focus": "Focus de la conferència", - "focusFail": "{{component}} no és disponible, torneu a intentar en {{ms}} segons", - "grantedTo": "S'han concedit permisos de moderador a {{to}}!", - "invitedOneMember": "S'ha convidat {{name}}", - "invitedThreePlusMembers": "S'han convidat {{name}} i {{count}} participants més", - "invitedTwoMembers": "S'han convidat {{first}} i {{second}}", - "kickParticipant": "{{kicker}} ha expulsat {{kicked}}", - "me": "Jo", - "moderator": "S'han concedit permisos de moderador!", - "muted": "Heu iniciat una conversa silenciada.", - "mutedTitle": "Esteu silenciat!", - "mutedRemotelyTitle": "Heu estat silenciat per {{participantDisplayName}}!", - "mutedRemotelyDescription": "Sempre podeu activar el micròfon quan hàgiu de parlar. Torneu a silenciar-lo quan hàgiu acabat per a mantenir el soroll lluny de la reunió.", - "passwordRemovedRemotely": "Un altre participant ha suprimit $t(lockRoomPasswordUppercase)", - "passwordSetRemotely": "Un altre participant ha establert la $t(lockRoomPassword)", - "raisedHand": "{{name}} vol parlar.", - "somebody": "Algú", - "startSilentTitle": "Us hi heu unit sense cap sortida d'àudio!", - "startSilentDescription": "Torneu a entrar per a activar l'àudio", - "suboptimalBrowserWarning": "Ens sap greu que la vostra experiència de reunió aquí no serà gaire bona. Cerquem maneres per a millorar-la, però fins aleshores, proveu de fer servir algun dels <a href='static/recommendedBrowsers.html' target='_blank'>navegadors completament compatibles</a>.", - "suboptimalExperienceTitle": "Avís del navegador", - "unmute": "Activa el so", - "newDeviceCameraTitle": "S'ha detectat una càmera nova", - "newDeviceAudioTitle": "S'ha detectat un aparell d'àudio nou", - "newDeviceAction": "Usa" - }, - "passwordSetRemotely": "establerta per una altre participant", - "passwordDigitsOnly": "Fins a {{number}} dígits", - "poweredby": "funciona amb", - "presenceStatus": { - "busy": "Ocupat", - "calling": "S'està trucant…", - "connected": "Connectat", - "connecting": "Està connectant…", - "connecting2": "Està connectant*...", - "disconnected": "Desconnectat", - "expired": "Ha expirat", - "ignored": "Ignorat", - "initializingCall": "S'està inicialitzant la trucada...", - "invited": "Convidat", - "rejected": "Rebutjat", - "ringing": "Està sonat..." - }, - "profile": { - "setDisplayNameLabel": "Indiqueu el nom visible", - "setEmailInput": "Introduïu una adreça electrònica", - "setEmailLabel": "Indiqueu l'adreça electrònica de Gravatar", - "title": "Perfil" - }, - "raisedHand": "Vull parlar", - "recording": { - "authDropboxText": "Puja a Dropbox", - "availableSpace": "Espai disponible: {{spaceLeft}} MB (aproximadament {{duration}} minuts d'enregistrament)", - "beta": "BETA", - "busy": "Treballem per a alliberar recursos d'enregistrament. Torneu-ho a intentar en uns minuts.", - "busyTitle": "Tots els enregistradors estan ocupats", - "error": "L'enregistrament ha fallat. Torneu-ho a intentar més tard.", - "expandedOff": "S'ha aturat l'enregistrament", - "expandedOn": "S'està enregistrant la reunió.", - "expandedPending": "S'ha iniciat l'enregistrament...", - "failedToStart": "No s'ha pogut iniciar l'enregistrament", - "fileSharingdescription": "Comparteix l'enregistrament amb els participants de la reunió", - "live": "EN DIRECTE", - "loggedIn": "Sessió iniciada com a {{userName}}", - "off": "S'ha aturat l'enregistrament", - "offBy": "{{name}} ha aturat l'enregistrament", - "on": "Enregistrament", - "onBy": "{{name}} ha iniciat l'enregistrament", - "pending": "S'està preparant per a enregistrar la reunió...", - "rec": "ENREG", - "serviceDescription": "El servei d'enregistrament desarà el vostre enregistrament", - "serviceName": "Servei d'enregistrament", - "signIn": "Inicia la sessió", - "signOut": "Tanca la sessió", - "unavailable": "Vaja! El servei {{serviceName}} ara mateix no és disponible. Treballem per a resoldre el problema. Torneu-ho a intentar més tard.", - "unavailableTitle": "L'enregistrament no és disponible" - }, - "sectionList": { - "pullToRefresh": "Estireu per a actualitzar" - }, - "settings": { - "calendar": { - "about": "La integració de l'agenda {{appName}} s'usa per a accedir de forma segura a la vostra agenda perquè pugui llegir els esdeveniments propers.", - "disconnect": "Desconnectat", - "microsoftSignIn": "Inicia sessió amb Microsoft", - "signedIn": "Ara mateix s'està accedint els esdeveniments de l'agenda de {{email}}. Feu clic al botó «Desconnecta» per a deixar d'accedir als esdeveniments de l'agenda.", - "title": "Agenda" - }, - "devices": "Aparells", - "followMe": "Tothom em segueix", - "language": "Llengua", - "loggedIn": "Sessió iniciada com a {{name}}", - "moderator": "Moderador", - "more": "Més", - "name": "Nom", - "noDevice": "Cap", - "selectAudioOutput": "Sortida d'àudio", - "selectCamera": "Càmera", - "selectMic": "Micròfon", - "startAudioMuted": "Tothom comença silenciat", - "startVideoMuted": "Tothom comença amagat", - "title": "Configuració", - "speakers": "Altaveus", - "microphones": "Micròfons" - }, - "settingsView": { - "advanced": "Avançat", - "alertOk": "D'acord", - "alertTitle": "Avís", - "alertURLText": "L'URL introduït no és vàlid", - "buildInfoSection": "Informació de la construcció", - "conferenceSection": "Conferència", - "disableCallIntegration": "Desactiva la integració de trucades nativa", - "disableP2P": "Desactiva el mode d'igual a igual", - "displayName": "Nom visible", - "email": "Adreça electrònica", - "header": "Configuració", - "profileSection": "Perfil", - "serverURL": "URL del servidor", - "showAdvanced": "Mostra la configuració avançada", - "startWithAudioMuted": "Comença amb l'àudio silenciat", - "startWithVideoMuted": "Comença amb el vídeo desactivat", - "version": "Versió" - }, - "share": { - "dialInfoText": "\n\n=====\n\nNomés voleu marcar en el telèfon?\n\n{{defaultDialInNumber}}Feu clic en aquest enllaç per a veure el marcatge de números de telèfon per a aquesta reunió\n{{dialInfoPageUrl}}", - "mainText": "Feu clic a l'enllaç següent per a unir-vos a la reunió:\n{{roomUrl}}" - }, - "speaker": "Altaveu", - "speakerStats": { - "hours": "{{count}}h", - "minutes": "{{count}}m", - "name": "Nom", - "seconds": "{{count}}s", - "speakerStats": "Estadístiques de l'interlocutor", - "speakerTime": "Temps de l'interlocutor" - }, - "startupoverlay": { - "title": "{{app}} requereix usar el micròfon i la càmera.", - "policyText": " " - }, - "suspendedoverlay": { - "rejoinKeyTitle": "Torna a entrar", - "text": "Premeu el botó <i>Torna a entrar</i> per a tornar a connectar.", - "title": "La videotrucada s'ha interromput perquè l'ordinador ha entrat en mode repòs." - }, - "toolbar": { - "accessibilityLabel": { - "audioOnly": "Activa o desactiva només l'àudio", - "audioRoute": "Seleccioneu l'aparell de so", - "callQuality": "Gestiona la qualitat de la trucada", - "cc": "Activa o desactiva els subtítols", - "chat": "Activa o desactiva la finestra de xats", - "document": "Activa o desactiva el document compartit", - "download": "Baixeu les nostres aplicacions", - "feedback": "Deixa comentaris", - "fullScreen": "Activa o desactiva la pantalla completa", - "hangup": "Abandona la trucada", - "help": "Ajuda", - "invite": "Convida-hi persones", - "kick": "Expulsa el participant", - "localRecording": "Activa o desactiva les controls d'enregistrament local", - "lockRoom": "Activa o desactiva la contrasenya de la reunió", - "moreActions": "Activa o desactiva el menú d'accions addicionals", - "moreActionsMenu": "Menú d'accions addicionals", - "moreOptions": "Mostra més opcions", - "mute": "Activa o desactiva el silenci de l'àudio", - "muteEveryone": "Silencia tothom", - "pip": "Activa o desactiva el mode imatge en imatge", - "privateMessage": "Envia un missatge privat", - "profile": "Edita el perfil", - "raiseHand": "Aixeca o abaixa la mà", - "recording": "Activa o desactiva l'enregistrament", - "remoteMute": "Silencia el participant", - "Settings": "Activa o desactiva la configuració", - "sharedvideo": "Activa o desactiva la compartició de vídeo", - "shareRoom": "Convida-hi algú", - "shareYourScreen": "Activa o desactiva la compartició de pantalla", - "shortcuts": "Activa o desactiva les dreceres", - "show": "Mostra-ho en l'escena", - "speakerStats": "Activa o desactiva les estadístiques de l'interlocutor", - "tileView": "Activa o desactiva el mode mosaic", - "toggleCamera": "Activa o desactiva la càmera", - "videomute": "Activa o desactiva el vídeo", - "videoblur": "Activa o desactiva el difuminat", - "toggleFilmstrip": "Activa o desactiva la tira" - }, - "addPeople": "Afegeix persones a la trucada", - "audioOnlyOff": "Desactiva el mode de poc ample de banda", - "audioOnlyOn": "Activa el mode de poc ample de banda", - "audioRoute": "Seleccioneu l'aparell de so", - "authenticate": "Autentica", - "callQuality": "Gestiona la qualitat de la trucada", - "chat": "Obre o tanca el xat", - "closeChat": "Tanca el xat", - "documentClose": "Tanca el document compartit", - "documentOpen": "Obre el document compartit", - "download": "Baixeu les nostres aplicacions", - "enterFullScreen": "Mostra en pantalla completa", - "enterTileView": "Mostra en mode mosaic", - "exitFullScreen": "Surt de la pantalla completa", - "exitTileView": "Surt del mode mosaic", - "feedback": "Deixa comentaris", - "hangup": "Surt", - "help": "Ajuda", - "invite": "Convida-hi persones", - "login": "Inicia sessió", - "logout": "Tanca la sessió", - "lowerYourHand": "Abaixa la mà", - "moreActions": "Més accions", - "moreOptions": "Més opcions", - "mute": "Silencia o activa el so", - "muteEveryone": "Silencia tothom", - "noAudioSignalTitle": "No entra cap so pel vostre micròfon!", - "noAudioSignalDesc": "Si no l'heu silenciat intencionadament en la configuració del sistema o per maquinari, considereu canviar l'aparell.", - "noAudioSignalDescSuggestion": "Si no l'heu silenciat intencionadament en la configuració del sistema o per maquinari, considereu canviar a l'aparell suggerit.", - "noAudioSignalDialInDesc": "També podeu marcar usant:", - "noAudioSignalDialInLinkDesc": "Números de marcatge", - "noisyAudioInputTitle": "Sembla que el micròfon fa soroll!", - "noisyAudioInputDesc": "Sembla que el vostre micròfon fa soroll, considereu de silenciar-lo o canviar l'aparell.", - "openChat": "Obre el xat", - "pip": "Entra en el mode imatge en imatge", - "privateMessage": "Envia un missatge privat", - "profile": "Edita el perfil", - "raiseHand": "Aixeca o abaixa la mà", - "raiseYourHand": "Aixeca la mà", - "Settings": "Configuració", - "sharedvideo": "Comparteix un vídeo de YouTube", - "shareRoom": "Convida-hi algú", - "shortcuts": "Mostra les dreceres", - "speakerStats": "Estadístiques de l'interlocutor", - "startScreenSharing": "Atura la compartició de la pantalla", - "startSubtitles": "Inicia els subtítols", - "stopScreenSharing": "Atura la compartició de la pantalla", - "stopSubtitles": "Atura els subtítols", - "stopSharedVideo": "Atura el vídeo de YouTube", - "talkWhileMutedPopup": "Intenteu parlar? Esteu silenciat.", - "tileViewToggle": "Activa o desactiva el mode mosaic", - "toggleCamera": "Activa o desactiva la càmera", - "videomute": "Inicia o atura la càmera", - "startvideoblur": "Difumina el fons", - "stopvideoblur": "No difuminis el fons" - }, - "transcribing": { - "ccButtonTooltip": "Inicia o atura els subtítols", - "error": "La transcripció ha fallat. Torneu-ho a intentar més tard.", - "expandedLabel": "La transcripció està activada", - "failedToStart": "No s'ha pogut iniciar la transcripció", - "labelToolTip": "La reunió s'està transcrivint", - "off": "La transcripció s'ha aturat", - "pending": "S'està preparant per a enregistrar la reunió…", - "start": "Activa els subtítols", - "stop": "Desactiva els subtítols", - "tr": "TR" - }, - "userMedia": { - "androidGrantPermissions": "Seleccioneu <b><i>Permet</i></b> si el navegador us sol·licita permisos.", - "chromeGrantPermissions": "Seleccioneu <b><i>Permet</i></b> si el navegador us sol·licita permisos.", - "edgeGrantPermissions": "Seleccioneu <b><i>Sí</i></b> si el navegador us sol·licita permisos.", - "electronGrantPermissions": "Concediu permisos per a usar la càmera i el micròfon", - "firefoxGrantPermissions": "Seleccioneu <b><i>Comparteix l'apareix seleccionat</i></b> si el navegador us sol·licita permisos.", - "iexplorerGrantPermissions": "Seleccioneu <b><i>D'acord</i></b> si el navegador us sol·licita permisos.", - "nwjsGrantPermissions": "Concediu permisos per a usar la càmera i el micròfon", - "operaGrantPermissions": "Seleccioneu <b><i>Permet</i></b> si el navegador us sol·licita permisos.", - "react-nativeGrantPermissions": "Seleccioneu <b><i>Permet</i></b> si el navegador us sol·licita permisos.", - "safariGrantPermissions": "Seleccioneu <b><i>D'acord</i></b> si el navegador us sol·licita permisos." - }, - "videoSIPGW": { - "busy": "Treballem per a alliberar recursos. Torneu-ho a intentar en uns minuts.", - "busyTitle": "Ara mateix, el servei Room és ocupat", - "errorAlreadyInvited": "Ja s'ha convidat {{displayName}}", - "errorInvite": "Encara no s'ha establert la connexió. Torneu-ho a intentar més tard.", - "errorInviteFailed": "Treballem per a resoldre el problema. Torneu-ho a intentar més tard.", - "errorInviteFailedTitle": "No s'ha pogut convidar {{displayName}}", - "errorInviteTitle": "S'ha produït un error en la sala d'invitació", - "pending": "{{displayName}} us ha convidat" - }, - "videoStatus": { - "audioOnly": "AUD", - "audioOnlyExpanded": "Ara sou en el mode de poc ample de banda. En aquest mode només rebreu àudio i compartició de pantalla.", - "callQuality": "Qualitat de vídeo", - "hd": "HD", - "hdTooltip": "Vídeo en alta definició", - "highDefinition": "Alta definició", - "labelTooiltipNoVideo": "No hi ha vídeo", - "labelTooltipAudioOnly": "S'ha activat el mode de poc ample de banda", - "ld": "LD", - "ldTooltip": "Vídeo en baixa definició", - "lowDefinition": "Baixa definició", - "onlyAudioAvailable": "Només hi ha disponible l'àudio", - "onlyAudioSupported": "Només es permet àudio en aquest navegador.", - "p2pEnabled": "Mode d'igual a igual activat", - "p2pVideoQualityDescription": "En el mode d'igual a igual, la qualitat del vídeo rebut només es pot canviar entre alta i només àudio. La resta de configuracions no es compliran fins sortir del mode d'igual a igual.", - "recHighDefinitionOnly": "L'alta definició serà preferent.", - "sd": "SD", - "sdTooltip": "Vídeo en definició estàndard", - "standardDefinition": "Definició estàndard" - }, - "videothumbnail": { - "domute": "Silencia", - "domuteOthers": "Silencia a tots els altres participants", - "flip": "Capgira", - "kick": "Expulsa", - "moderator": "Moderador", - "mute": "El participant és silenciat", - "muted": "Silenciat", - "remoteControl": "Inicia o atura el control remot", - "show": "Mostra-ho en l'escena", - "videomute": "El participant ha aturat la càmera" - }, - "welcomepage": { - "accessibilityLabel": { - "join": "Toqueu per a unir-vos-hi", - "roomname": "Introduïu el nom de la sala" - }, - "appDescription": "Endavant, xat de vídeo amb tot l'equip. De fet, convideu tothom que conegueu. {{app}} és una solució de videoconferència de codi obert 100% completament xifrada que podeu utilitzar durant tot el dia, tots els dies, gratuïtament, sense necessitat de compte.", - "audioVideoSwitch": { - "audio": "Veu", - "video": "Vídeo" - }, - "calendar": "Agenda", - "connectCalendarButton": "Connecteu la vostra agenda", - "connectCalendarText": "Connecteu l'agenda per a veure totes les reunions en {{app}}. Més, afegiu les reunions {{provider}} a la vostra agenda i inicieu-les amb un clic.", - "enterRoomTitle": "Inicia una reunió nova", - "roomNameAllowedChars": "El nom de la reunió no hauria de contenir cap d'aquests caràcters: ?, &, :, ', \", % ni #.", - "go": "SOM-HI", - "goSmall": "SOM-HI", - "join": "CREA / ENTRA", - "info": "Informació", - "privacy": "Privadesa", - "recentList": "Recents", - "recentListDelete": "Suprimeix", - "recentListEmpty": "La llista de reunions recents ara mateix és buida. Feu xats amb el vostre equip i trobareu totes les reunions recents aquí.", - "reducedUIText": "Us donem la benvinguda a {{app}}!", - "roomname": "Introduïu el nom de la sala", - "roomnameHint": "Introduïu el nom o l'URL de la sala on voleu entrar. Podeu crear un nom, només cal que les persones amb qui us reuniu el coneguin i introdueixin el mateix nom.", - "sendFeedback": "Envia comentaris", - "terms": "Condicions", - "title": "Videoconferència segura, plena de funcionalitats i completament gratuïta i lliure", - "getHelp": "Ajuda" - }, - "lonelyMeetingExperience": { - "button": "Convideu altres persones", - "youAreAlone": "Sou l'únic participant de la reunió" - }, - "helpView": { - "header": "Centre d'ajuda" - } -} diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-de.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-de.json index 42d385165..55377d520 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-de.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-de.json @@ -121,7 +121,7 @@ "deepLinking": { "appNotInstalled": "Sie benötigen die „{{app}}“-App, um der Konferenz auf dem Smartphone beizutreten.", "description": "Nichts passiert? Wir haben versucht, die Konferenz in {{app}} zu öffnen. Versuchen Sie es erneut oder treten Sie der Konferenz in {{app}} im Web bei.", - "descriptionWithoutWeb": "Ist nichts passiert? Wir haben versucht, Ihre Besprechung in der „{{app}}“-Desktop-App zu starten.", + "descriptionWithoutWeb": "Ist nichts passiert? Wir haben versucht, Ihre Besprechung in der „{{{app}}}“-Desktop-App zu starten.", "downloadApp": "App herunterladen", "launchWebButton": "Im Web öffnen", "openApp": "In der App fortfahren", @@ -144,7 +144,7 @@ }, "dialog": { "accessibilityLabel": { - "liveStreaming": "Livestream" + "liveStreaming": "Livestream:" }, "allow": "Erlauben", "alreadySharedVideoMsg": "Ein anderer Teilnehmer gibt bereits ein Video weiter. Bei dieser Konferenz ist jeweils nur ein geteiltes Video möglich.", @@ -155,7 +155,7 @@ "cameraNotFoundError": "Kamera nicht gefunden.", "cameraNotSendingData": "Die Kamera ist nicht verfügbar. Bitte prüfen, ob eine andere Applikation die Kamera verwendet, eine andere Kamera vom Einstellungs-Menü auswählen oder die Applikation neu laden.", "cameraNotSendingDataTitle": "Zugriff auf Kamera nicht möglich", - "cameraPermissionDeniedError": "Die Berechtigung zur Verwendung der Kamera wurde nicht erteilt. Sie können trotzdem an der Konferenz teilnehmen, aber die anderen Teilnehmer können Sie nicht sehen. Verwenden Sie die Kamera-Schaltfläche in der Adressleiste, um die Berechtigungen zu erteilen.", + "cameraPermissionDeniedError": "Die Berechtigung zur Verwendung der Kamera wurde nicht erteilt. Sie können trotzdem an der Konferenz teilnehmen, aber die anderen Teilnehmer können Sie nicht sehen. Verwenden Sie die Kamera-Schaltfläche in der Adressleiste um die Berechtigungen zu erteilen.", "cameraUnknownError": "Die Kamera kann aus einem unbekannten Grund nicht verwendet werden.", "cameraUnsupportedResolutionError": "Die Kamera unterstützt die erforderliche Auflösung nicht.", "Cancel": "Abbrechen", @@ -192,7 +192,7 @@ "kickParticipantButton": "Entfernen", "kickParticipantDialog": "Wollen Sie diesen Teilnehmer wirklich entfernen?", "kickParticipantTitle": "Teilnehmer entfernen?", - "kickTitle": "Autsch! {{participantDisplayName}} hat Sie aus dem Meeting geworfen", + "kickTitle": "Autsch! {{participantDisplayName}} hat Sie aus dem Meeting geworfen.", "liveStreaming": "Livestreaming", "liveStreamingDisabledForGuestTooltip": "Gäste können kein Livestreaming starten.", "liveStreamingDisabledTooltip": "Starten des Livestreams deaktiviert.", @@ -205,9 +205,9 @@ "maxUsersLimitReachedTitle": "Maximales Teilnehmerlimit erreicht", "micConstraintFailedError": "Ihr Mikrofon erfüllt die notwendigen Anforderungen nicht.", "micNotFoundError": "Mikrofon nicht gefunden.", - "micNotSendingData": "Gehen Sie zu den Einstellungen Ihres Computers, um die Stummschaltung Ihres Mikrofons aufzuheben und seinen Pegel einzustellen", - "micNotSendingDataTitle": "Ihr Mikrofon ist durch Ihre Systemeinstellungen stumm geschaltet", - "micPermissionDeniedError": "Die Berechtigung zur Verwendung des Mikrofons wurde nicht erteilt. Sie können trotzdem an der Konferenz teilnehmen, aber die anderen Teilnehmer können Sie nicht hören. Verwenden Sie die Kamera-Schaltfläche in der Adressleiste, um die Berechtigungen zu erteilen.", + "micNotSendingData": "Gehen Sie zu den Einstellungen Ihres Computers, um die Stummschaltung Ihres Mikrofons aufzuheben und seinen Pegel einzustellen.", + "micNotSendingDataTitle": "Ihr Mikrofon ist durch Ihre Systemeinstellungen stumm geschaltet.", + "micPermissionDeniedError": "Die Berechtigung zur Verwendung des Mikrofons wurde nicht erteilt. Sie können trotzdem an der Konferenz teilnehmen, aber die anderen Teilnehmer können Sie nicht hören. Verwenden Sie die Kamera-Schaltfläche in der Adressleiste um die Berechtigungen zu erteilen.", "micUnknownError": "Das Mikrofon kann aus einem unbekannten Grund nicht verwendet werden.", "muteEveryoneElseDialog": "Einmal stummgeschaltet, können Sie deren Stummschaltung nicht mehr beenden, aber sie können ihre Stummschaltung jederzeit selbst beenden.", "muteEveryoneElseTitle": "Alle außer {{whom}} stummschaten?", @@ -220,8 +220,8 @@ "muteParticipantDialog": "Wollen Sie diesen Teilnehmer wirklich stummschalten? Sie können die Stummschaltung nicht wieder aufheben, der Teilnehmer kann dies aber jederzeit selbst tun.", "muteParticipantTitle": "Teilnehmer stummschalten?", "Ok": "OK", - "passwordLabel": "Das Treffen wurde von einem Teilnehmer geslerrt. Bitte geben Sie die $t(lockRoomPassword) zu verbinden.", - "passwordNotSupported": "Das Festlegen von einem $t(lockRoomPassword) für das Meeting wird nicht unterstützt.", + "passwordLabel": "$t(lockRoomPasswordUppercase)", + "passwordNotSupported": "Setzen eines Konferenz-Passworts ist nicht unterstützt", "passwordNotSupportedTitle": "$t(lockRoomPasswordUppercase) nicht unterstützt", "passwordRequired": "$t(lockRoomPasswordUppercase) erforderlich", "popupError": "Ihr Browser blockiert Pop-ups von dieser Website. Bitte aktivieren Sie Pop-ups in den Sicherheitseinstellungen des Browsers und versuchen Sie es erneut.", @@ -230,12 +230,12 @@ "recordingDisabledForGuestTooltip": "Gäste können keine Aufzeichnungen starten.", "recordingDisabledTooltip": "Start der Aufzeichnung deaktiviert.", "rejoinNow": "Jetzt erneut beitreten", - "remoteControlAllowedMessage": "{{user}} hat die Anfrage zur Fernsteuerung angenommen!", - "remoteControlDeniedMessage": "{{user}} hat die Anfrage zur Fernsteuerung verweigert!", - "remoteControlErrorMessage": "Beim Anfordern der Fernsteuerungsberechtigung von {{user}} ist ein Fehler aufgetreten!", + "remoteControlAllowedMessage": "{{user}} hat die Anfrage zur Fernsteuerung angenommen.", + "remoteControlDeniedMessage": "{{user}} hat die Anfrage zur Fernsteuerung verweigert.", + "remoteControlErrorMessage": "Beim Anfordern der Fernsteuerungsberechtigung von {{user}} ist ein Fehler aufgetreten.", "remoteControlRequestMessage": "Möchten Sie {{user}} erlauben, den Computer fernzusteuern?", "remoteControlShareScreenWarning": "Achtung, wenn Sie die Anfrage genehmigen, starten Sie die Bildschirmfreigabe!", - "remoteControlStopMessage": "Die Fernsteuerung wurde beendet!", + "remoteControlStopMessage": "Die Fernsteuerung wurde beendet.", "remoteControlTitle": "Fernsteuerung", "Remove": "Entfernen", "removePassword": "$t(lockRoomPassword) entfernen", @@ -246,8 +246,8 @@ "retry": "Wiederholen", "screenSharingFailedToInstall": "Oh! Die Erweiterung für die Bildschirmfreigabe konnte nicht installiert werden.", "screenSharingFailedToInstallTitle": "Bildschirmfreigabe-Erweiterung konnte nicht installiert werden", - "screenSharingFirefoxPermissionDeniedError": "Die Bildschirmfreigabe ist leider fehlgeschlagen. Bitte stellen Sie sicher, dass die Berechtigung für die Bildschirmfreigabe im Browser erteilt wurde. ", - "screenSharingFirefoxPermissionDeniedTitle": "Die Bildschirmfreigabe konnte nicht gestartet werden!", + "screenSharingFirefoxPermissionDeniedError": "Die Bildschirmfreigabe ist leider fehlgeschlagen. Bitte stellen Sie sicher, dass die Berechtigung für die Bildschirmfreigabe im Browser erteilt wurde.", + "screenSharingFirefoxPermissionDeniedTitle": "Die Bildschirmfreigabe konnte nicht gestartet werden.", "screenSharingPermissionDeniedError": "Oh! Beim Anfordern der Bildschirmfreigabe-Berechtigungen hat etwas nicht funktioniert. Bitte aktualisieren und erneut versuchen.", "sendPrivateMessage": "Sie haben kürzlich eine private Nachricht erhalten. Hatten Sie die Absicht, darauf privat zu antworten, oder wollen Sie Ihre Nachricht an die Gruppe senden?", "sendPrivateMessageCancel": "An die Gruppe senden", @@ -263,7 +263,7 @@ "shareYourScreenDisabledForGuest": "Gäste können den Bildschirm nicht freigeben.", "startLiveStreaming": "Einen Livestream starten", "startRecording": "Aufnahme starten", - "startRemoteControlErrorMessage": "Beim Versuch, die Fernsteuerung zu starten, ist ein Fehler aufgetreten!", + "startRemoteControlErrorMessage": "Beim Versuch die Fernsteuerung zu starten ist ein Fehler aufgetreten.", "stopLiveStreaming": "Livestreaming stoppen", "stopRecording": "Aufnahme stoppen", "stopRecordingWarning": "Sind Sie sicher, dass Sie die Aufnahme stoppen möchten?", @@ -281,8 +281,7 @@ "WaitForHostMsgWOk": "Die Konferenz <b>{{room}}</b> wurde noch nicht gestartet. Wenn Sie der Organisator sind, drücken Sie zum Authentifizieren auf OK. Warten Sie andernfalls, bis der Organisator erscheint.", "WaitingForHost": "Warten auf den Organisator...", "Yes": "Ja", - "yourEntireScreen": "Ganzer Bildschirm", - "screenSharingAudio": "Audio austauschen" + "yourEntireScreen": "Ganzer Bildschirm" }, "dialOut": { "statusMessage": "ist jetzt {{status}}" @@ -319,18 +318,18 @@ "dialInSummaryError": "Fehler beim Abrufen der Einwahlinformationen. Versuchen Sie es später erneut.", "dialInTollFree": "Gebührenfrei", "genericError": "Es ist leider etwas schiefgegangen.", - "inviteLiveStream": "Klicken Sie auf {{url}}, um den Livestream dieser Konferenz zu öffnen", + "inviteLiveStream": "Klicken Sie auf {{url}} um den Livestream dieser Konferenz zu öffnen", "invitePhone": "Wenn Sie stattdessen per Telefon beitreten möchten, tippen Sie hier: {{number}},,{{conferenceID}}#\n", - "invitePhoneAlternatives": "Suche nach einer anderen Einwahlnummer?\nMeetings-Einwahlnummern sehen: {{url}}\n\n\nWenn Sie sich auch über ein Raumtelefon einwählen, nehmen Sie teil, ohne sich mit dem Ton zu verbinden: {{silentUrl}}", + "invitePhoneAlternatives": "Suche nach einer anderen Einwahlnummer?\nMeetings-Einwahlnummern sehen: {{{url}}\n\n\n\nWenn Sie sich auch über ein Raumtelefon einwählen, nehmen Sie teil, ohne sich mit dem Ton zu verbinden: {{silentUrl}}", "inviteURLFirstPartGeneral": "Sie wurden zur Teilnahme an einem Meeting eingeladen.", "inviteURLFirstPartPersonal": "{{name}} lädt Sie zu einem Meeting ein.\n", "inviteURLSecondPart": "\nAm Meeting teilnehmen:\n{{url}}\n", "liveStreamURL": "Livestream:", "moreNumbers": "Weitere Telefonnummern", "noNumbers": "Keine Telefonnummern verfügbar.", - "noPassword": "Keines", + "noPassword": "Kein", "noRoom": "Keine Konferenz für die Einwahlinformationen angegeben.", - "numbers": "Einwahlnummern", + "numbers": "Einwählnummern", "password": "$t(lockRoomPasswordUppercase):", "title": "Teilen", "tooltip": "Freigabe-Link und Einwahlinformationen für dieses Meeting", @@ -395,9 +394,7 @@ "signOut": "Abmelden", "start": "Einen Livestream starten", "streamIdHelp": "Was ist das?", - "unavailableTitle": "Livestreaming nicht verfügbar", - "youtubeTerms": "YouTube-Nutzungsbedingungen", - "googlePrivacyPolicy": "Google-Datenschutzerklärung" + "unavailableTitle": "Livestreaming nicht verfügbar" }, "localRecording": { "clientState": { @@ -414,7 +411,7 @@ "localRecording": "Lokale Aufzeichnung", "me": "Ich", "messages": { - "engaged": "Lokale Aufzeichnung ist aktiviert.", + "engaged": "Lokale Aufzeichnung ist aktiviert", "finished": "Aufzeichnung der Sitzung {{token}} ist beendet. Senden Sie die aufgezeichnete Datei an den Moderator.", "finishedModerator": "Aufzeichnung der Sitzung {{token}} ist beendet. Die Aufzeichnung des lokalen Verlaufs wurde gespeichert. Bitten Sie die anderen Teilnehmer, ihre Aufzeichnungen zu übermitteln.", "notModerator": "Sie sind nicht der Moderator. Sie können die lokale Aufzeichnung nicht starten oder stoppen." @@ -438,17 +435,17 @@ "disconnected": "getrennt", "focus": "Konferenz-Organisator", "focusFail": "{{component}} ist im Moment nicht verfügbar - wiederholen in {{ms}} Sekunden", - "grantedTo": "Moderatorenrechte an {{to}} vergeben!", - "invitedOneMember": "{{name}} wurde eingeladen", + "grantedTo": "Moderatorenrechte an {{to}} vergeben.", + "invitedOneMember": "{{displayName}} wurde eingeladen", "invitedThreePlusMembers": "{{name}} und {{count}} andere wurden eingeladen", "invitedTwoMembers": "{{first}} und {{second}} wurden eingeladen", - "kickParticipant": "{{kicked}} wurde von {{kicker}} ausgewiesen", + "kickParticipant": "Sie können sich für mehr Details an {{participantDisplayName}} wenden.", "me": "Ich", - "moderator": "Moderatorenrechte vergeben!", + "moderator": "Moderatorenrechte vergeben", "muted": "Der Konferenz wurde stumm beigetreten.", "mutedTitle": "Stummschaltung aktiv!", "mutedRemotelyTitle": "Sie wurden von {{participantDisplayName}} stummgeschaltet!", - "mutedRemotelyDescription": "Sie können jederzeit die Stummschaltung aufheben, wenn Sie bereit sind zu sprechen. Wenn Sie fertig sind, können Sie sich wieder stummschalten, um Geräusche vom Meeting fernzuhalten.", + "mutedRemotelyDescription": "Sie können jederzeit die Stummschaltung aufheben, wenn Sie bereit sind zu sprechen. Wenn Sie fertig sind, können sich wieder stummschalten, um Geräusche vom Meeting fernzuhalten.", "passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) von einem anderen Teilnehmer entfernt", "passwordSetRemotely": "$t(lockRoomPasswordUppercase) von einem anderen Teilnehmer gesetzt", "raisedHand": "{{name}} möchte sprechen.", @@ -467,9 +464,9 @@ "poweredby": "Betrieben von", "presenceStatus": { "busy": "Beschäftigt", - "calling": "Wird angerufen …", + "calling": "Wird angerufen…", "connected": "Verbunden", - "connecting": "Verbindung wird hergestellt…", + "connecting": "Verbindung wird hergestellt", "connecting2": "Wird verbunden*…", "disconnected": "Getrennt", "expired": "Abgelaufen", @@ -477,7 +474,7 @@ "initializingCall": "Anruf wird initialisiert…", "invited": "Einladen", "rejected": "Abgelehnt", - "ringing": "Es klingelt …" + "ringing": "Es klingelt…" }, "profile": { "setDisplayNameLabel": "Anzeigename festlegen", @@ -528,7 +525,6 @@ "followMe": "Follow-me für alle Teilnehmer", "language": "Sprache", "loggedIn": "Als {{name}} angemeldet", - "microphones": "Mikrofon", "moderator": "Moderator", "more": "Mehr", "name": "Name", @@ -536,7 +532,6 @@ "selectAudioOutput": "Audioausgabe", "selectCamera": "Kamera", "selectMic": "Mikrofon", - "speakers": "Lautsprecher", "startAudioMuted": "Alle Teilnehmer treten stumm geschaltet bei", "startVideoMuted": "Alle Teilnehmer treten ohne Video bei", "title": "Einstellungen" @@ -561,7 +556,7 @@ "version": "Version" }, "share": { - "dialInfoText": "\n\n=====\n\nWollen Sie sich nur auf Ihrem Telefon einwählen?\n\n{{defaultDialInNumber}}Klicken Sie auf diesen Link, um die eingewählten Telefonnummern für dieses Meeting zu sehen\n{{dialInfoPageUrl}}", + "dialInfoText": "\n\n=====\n\nWollen Sie sich nur auf Ihrem Telefon einwählen?\n\n{{{defaultDialInNumber}}}Klicken Sie auf diesen Link, um die eingewählten Telefonnummern für dieses Meeting zu sehen\n{{dialInfoPageUrl}}", "mainText": "Klicken Sie auf den folgenden Link, um dem Meeting beizutreten:\n{{roomUrl}}" }, "speaker": "Sprecher", @@ -652,7 +647,7 @@ "noAudioSignalDesc": "Wenn Sie das Gerät nicht absichtlich über die Systemeinstellungen oder die Hardware stumm geschaltet haben, sollten Sie einen Wechsel des Geräts in Erwägung ziehen.", "noAudioSignalDescSuggestion": "Wenn Sie das Gerät nicht absichtlich über die Systemeinstellungen oder die Hardware stummgeschaltet haben, sollten Sie einen Wechsel auf das vorgeschlagene Gerät in Erwägung ziehen.", "noAudioSignalDialInDesc": "Sie können sich auch über die Einwahlnummer einwählen:", - "noAudioSignalDialInLinkDesc": "Einwahlnummern", + "noAudioSignalDialInLinkDesc" : "Einwahlnummern:", "noisyAudioInputTitle": "Ihr Mikrofon scheint lärmintensiv zu sein!", "noisyAudioInputDesc": "Es klingt, als ob Ihr Mikrofon Störgeräusche verursacht. Bitte überlegen Sie, ob Sie das Gerät stummschalten oder austauschen wollen.", "openChat": "Chat öffnen", diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-enGB.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-enGB.json index 92ac5b5a6..f0d670ff6 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-enGB.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-enGB.json @@ -21,8 +21,7 @@ "bluetooth": "Bluetooth", "headphones": "Headphones", "phone": "Phone", - "speaker": "Speaker", - "none": "" + "speaker": "Speaker" }, "audioOnly": { "audioOnly": "Audio only" @@ -52,15 +51,10 @@ "popover": "Choose a nickname", "title": "Enter a nickname to use chat" }, - "title": "Chat", - "you": "", - "privateNotice": "", - "noMessagesMessage": "", - "messageTo": "", - "fieldPlaceHolder": "" + "title": "Chat" }, "connectingOverlay": { - "joiningRoom": "Connecting you to your meeting…" + "joiningRoom": "Connecting you to your meeting..." }, "connection": { "ATTACHED": "Attached", @@ -72,11 +66,7 @@ "DISCONNECTED": "Disconnected", "DISCONNECTING": "Disconnecting", "ERROR": "Error", - "RECONNECTING": "A network problem occurred. Reconnecting...", - "LOW_BANDWIDTH": "", - "GOT_SESSION_ID": "", - "GET_SESSION_ID_ERROR": "", - "FETCH_SESSION_ID": "" + "RECONNECTING": "A network problem occurred. Reconnecting..." }, "connectionindicator": { "address": "Address:", @@ -107,8 +97,7 @@ "status": "Connection:", "transport": "Transport:", "transport_plural": "Transports:", - "turn": " (turn)", - "e2e_rtt": "" + "turn": " (turn)" }, "dateUtils": { "earlier": "Earlier", @@ -122,7 +111,7 @@ "downloadApp": "Download the app", "launchWebButton": "Launch in web", "openApp": "Continue to the app", - "title": "Launching your meeting in {{app}}…", + "title": "Launching your meeting in {{app}}...", "tryAgainButton": "Try again in desktop" }, "defaultLink": "e.g. {{url}}", @@ -156,9 +145,9 @@ "cameraUnsupportedResolutionError": "Your camera does not support required video resolution.", "Cancel": "Cancel", "close": "Close", - "conferenceDisconnectMsg": "You may want to check your network connection. Reconnecting in {{seconds}} sec…", + "conferenceDisconnectMsg": "You may want to check your network connection. Reconnecting in {{seconds}} sec...", "conferenceDisconnectTitle": "You have been disconnected.", - "conferenceReloadMsg": "We're trying to fix this. Reconnecting in {{seconds}} sec…", + "conferenceReloadMsg": "We're trying to fix this. Reconnecting in {{seconds}} sec...", "conferenceReloadTitle": "Unfortunately, something went wrong.", "confirm": "Confirm", "confirmNo": "No", @@ -265,20 +254,9 @@ "userPassword": "user password", "WaitForHostMsg": "The conference <b>{{room}}</b> has not yet started. If you are the host then please authenticate. Otherwise, please wait for the host to arrive.", "WaitForHostMsgWOk": "The conference <b>{{room}}</b> has not yet started. If you are the host then please press Ok to authenticate. Otherwise, please wait for the host to arrive.", - "WaitingForHost": "Waiting for the host …", + "WaitingForHost": "Waiting for the host ...", "Yes": "Yes", - "yourEntireScreen": "Your entire screen", - "sendPrivateMessageTitle": "", - "sendPrivateMessageOk": "", - "sendPrivateMessageCancel": "", - "sendPrivateMessage": "", - "screenSharingAudio": "", - "muteEveryoneStartMuted": "", - "muteEveryoneSelf": "", - "muteEveryoneTitle": "", - "muteEveryoneDialog": "", - "muteEveryoneElseTitle": "", - "muteEveryoneElseDialog": "" + "yourEntireScreen": "Your entire screen" }, "dialOut": { "statusMessage": "is now {{status}}" @@ -313,7 +291,7 @@ "dialInTollFree": "Toll Free", "genericError": "Whoops, something went wrong.", "inviteLiveStream": "To view the live stream of this meeting, click this link: {{url}}", - "invitePhone": "One tap audio Dial In: {{number}},,{{conferenceID}}#\n", + "invitePhone": "One tap audio Dial In: {{number}},,{{conferenceID}}#", "invitePhoneAlternatives": "", "inviteURLFirstPartGeneral": "You are invited to join a meeting.", "inviteURLFirstPartPersonal": "{{name}} is inviting you to a meeting.\n", @@ -350,15 +328,14 @@ "keyboardShortcuts": "Keyboard shortcuts", "localRecording": "Show or hide local recording controls", "mute": "Mute or unmute your microphone", - "pushToTalk": "Press to transmit", + "pushToTalk": "Push to talk", "raiseHand": "Raise or lower your hand", "showSpeakerStats": "Show speaker stats", "toggleChat": "Open or close the chat", "toggleFilmstrip": "Show or hide video thumbnails", "toggleScreensharing": "Switch between camera and screen sharing", "toggleShortcuts": "Show or hide keyboard shortcuts", - "videoMute": "Start or stop your camera", - "videoQuality": "" + "videoMute": "Start or stop your camera" }, "liveStreaming": { "busy": "We're working on freeing streaming resources. Please try again in a few minutes.", @@ -372,13 +349,13 @@ "errorLiveStreamNotEnabled": "Live Streaming is not enabled on {{email}}. Please enable live streaming or log into an account with live streaming enabled.", "expandedOff": "The live streaming has stopped", "expandedOn": "The meeting is currently being streamed to YouTube.", - "expandedPending": "The live streaming is being started…", + "expandedPending": "The live streaming is being started...", "failedToStart": "Live Streaming failed to start", "getStreamKeyManually": "We weren’t able to fetch any live streams. Try getting your live stream key from YouTube.", "invalidStreamKey": "Live stream key may be incorrect.", "off": "Live Streaming stopped", "on": "Live Streaming", - "pending": "Starting Live Stream…", + "pending": "Starting Live Stream...", "serviceName": "Live Streaming service", "signedInAs": "You are currently signed in as:", "signIn": "Sign in with Google", @@ -386,11 +363,7 @@ "signOut": "Sign out", "start": "Start a live stream", "streamIdHelp": "What's this?", - "unavailableTitle": "Live Streaming unavailable", - "onBy": "", - "offBy": "", - "googlePrivacyPolicy": "Google Privacy Policy", - "youtubeTerms": "YouTube terms of services" + "unavailableTitle": "Live Streaming unavailable" }, "localRecording": { "clientState": { @@ -441,42 +414,41 @@ "muted": "You have started the conversation muted.", "mutedTitle": "You're muted!", "mutedRemotelyTitle": "You have been muted by {{participantDisplayName}}!", - "mutedRemotelyDescription": "You can always unmute when you're ready to speak. Mute back when you're done to keep noise away from the meeting.", - "passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) removed by another participant", - "passwordSetRemotely": "$t(lockRoomPasswordUppercase) set by another participant", + "mutedRemotelyDescription": "", + "passwordRemovedRemotely": "", + "passwordSetRemotely": "", "raisedHand": "{{name}} would like to speak.", "somebody": "Somebody", - "startSilentTitle": "You joined with no audio output!", - "startSilentDescription": "Rejoin the meeting to enable audio", + "startSilentTitle": "", + "startSilentDescription": "", "suboptimalExperienceDescription": "Eer... we are afraid your experience with {{appName}} isn't going to be that great here. We are looking for ways to improve this but, until then, please try using one of the <a href='static/recommendedBrowsers.html' target='_blank'>fully supported browsers</a>.", "suboptimalExperienceTitle": "Browser Warning", - "unmute": "Unmute", + "unmute": "", "newDeviceCameraTitle": "New camera detected", "newDeviceAudioTitle": "New audio device detected", - "newDeviceAction": "Use", - "suboptimalBrowserWarning": "We are afraid your meeting experience isn't going to be that great here. We are looking for ways to improve this, but until then please try using one of the <a href='static/recommendedBrowsers.html' target='_blank'>fully supported browsers</a>." + "newDeviceAction": "Use" }, "passwordSetRemotely": "set by another member", "passwordDigitsOnly": "Up to {{number}} digits", "poweredby": "powered by", "presenceStatus": { "busy": "Busy", - "calling": "Calling…", + "calling": "Calling...", "connected": "Connected", - "connecting": "Connecting…", + "connecting": "Connecting...", "connecting2": "Connecting*...", "disconnected": "Disconnected", "expired": "Expired", "ignored": "Ignored", - "initializingCall": "Initialising Call…", + "initializingCall": "Initialising Call...", "invited": "Invited", "rejected": "Rejected", - "ringing": "Ringing…" + "ringing": "Ringing..." }, "profile": { "setDisplayNameLabel": "Set your display name", "setEmailInput": "Enter e-mail", - "setEmailLabel": "Set your Gravatar e-mail", + "setEmailLabel": "Set your gravatar email", "title": "Profile" }, "recording": { @@ -488,23 +460,21 @@ "error": "Recording failed. Please try again.", "expandedOff": "Recording has stopped", "expandedOn": "The meeting is currently being recorded.", - "expandedPending": "Recording is being started…", + "expandedPending": "Recording is being started...", "failedToStart": "Recording failed to start", "fileSharingdescription": "Share recording with meeting participants", "live": "LIVE", "loggedIn": "Logged in as {{userName}}", "off": "Recording stopped", "on": "Recording", - "pending": "Preparing to record the meeting…", + "pending": "Preparing to record the meeting...", "rec": "REC", "serviceDescription": "Your recording will be saved by the recording service", "serviceName": "Recording service", "signIn": "Sign in", "signOut": "Sign out", "unavailable": "Oops! The {{serviceName}} is currently unavailable. We're working on resolving the issue. Please try again later.", - "unavailableTitle": "Recording unavailable", - "onBy": "{{name}} started the recording", - "offBy": "{{name}} stopped the recording" + "unavailableTitle": "Recording unavailable" }, "sectionList": { "pullToRefresh": "Pull to refresh" @@ -530,9 +500,7 @@ "selectMic": "Microphone", "startAudioMuted": "Everyone starts muted", "startVideoMuted": "Everyone starts hidden", - "title": "Settings", - "speakers": "Speakers", - "microphones": "Microphones" + "title": "Settings" }, "settingsView": { "alertOk": "OK", @@ -547,11 +515,7 @@ "serverURL": "Server URL", "startWithAudioMuted": "Start with audio muted", "startWithVideoMuted": "Start with video muted", - "version": "Version", - "showAdvanced": "Show advanced settings", - "disableP2P": "Disable Peer-To-Peer mode", - "disableCallIntegration": "Disable native call integration", - "advanced": "Advanced" + "version": "Version" }, "share": { "dialInfoText": "\n\n=====\n\nJust want to dial in on your phone?\n\n{{defaultDialInNumber}}Click this link to see the dial in phone numbers for this meeting\n{{dialInfoPageUrl}}", @@ -599,21 +563,16 @@ "recording": "Toggle recording", "remoteMute": "Mute participant", "Settings": "Toggle settings", - "sharedvideo": "Toggle YouTube video sharing", + "sharedvideo": "Toggle Youtube video sharing", "shareRoom": "Invite someone", "shareYourScreen": "Toggle screenshare", "shortcuts": "Toggle shortcuts", - "show": "Show on stage", + "show": "", "speakerStats": "Toggle speaker statistics", "tileView": "Toggle tile view", "toggleCamera": "Toggle camera", "videomute": "Toggle mute video", - "videoblur": "", - "privateMessage": "Send private message", - "muteEveryone": "Mute everyone", - "moreOptions": "Show more options", - "help": "Help", - "download": "Download our apps" + "videoblur": "" }, "addPeople": "Add people to your call", "audioOnlyOff": "Disable audio only mode", @@ -666,7 +625,7 @@ "failedToStart": "Transcribing failed to start", "labelToolTip": "The meeting is being transcribed", "off": "Transcribing stopped", - "pending": "Preparing to transcribe the meeting…", + "pending": "Preparing to transcribe the meeting...", "start": "Start showing subtitles", "stop": "Stop showing subtitles", "tr": "TR" @@ -749,15 +708,5 @@ "sendFeedback": "Send feedback", "terms": "Terms", "title": "Secure, fully featured, and completely free video conferencing" - }, - "documentSharing": { - "title": "" - }, - "defaultNickname": "", - "chromeExtensionBanner": { - "dontShowAgain": "", - "buttonText": "", - "installExtensionText": "" - }, - "raisedHand": "Would like to speak" -} + } +} \ No newline at end of file diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-eo.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-eo.json index 52859f900..6ec8e1b17 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-eo.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-eo.json @@ -253,10 +253,13 @@ "userPassword": "uzantopasvorto", "WaitForHostMsg": "", "WaitForHostMsgWOk": "", - "WaitingForHost": "Atendanta la gastigan komputilon …", + "WaitingForHost": "Atendanta la gastigan komputilon ...", "Yes": "Jes", "yourEntireScreen": "Via tuta ekrano" }, + "\u0005dialog": { + "accessibilityLabel": {} + }, "dialOut": { "statusMessage": "nun estas {{status}}" }, @@ -269,6 +272,7 @@ "veryBad": "Tre malbona", "veryGood": "Tre bona" }, + "\u0005feedback": {}, "incomingCall": { "answer": "", "audioCallTitle": "", @@ -306,6 +310,7 @@ "tooltip": "", "label": "" }, + "\u0005info": {}, "inviteDialog": { "alertText": "", "header": "", @@ -336,6 +341,7 @@ "toggleShortcuts": "", "videoMute": "Ŝalti aŭ malŝalti vian kameraon" }, + "\u0005keyboardShortcuts": {}, "liveStreaming": { "busy": "Ni penas liberigi tujajn elsendilojn. Bonvolu reprovi post kelkaj minutoj.", "busyTitle": "Ĉiuj elsendiloj nun okupiĝas", @@ -354,7 +360,7 @@ "invalidStreamKey": "", "off": "Tuja elsendfluo finiĝis", "on": "Tuja Elsendfluo", - "pending": "Komencanta Tujan Elsendfluon…", + "pending": "Komencanta Tujan Elsendfluon...", "serviceName": "", "signedInAs": "", "signIn": "", @@ -364,6 +370,7 @@ "streamIdHelp": "", "unavailableTitle": "Tuja elsendfluo ne disponeblas" }, + "\u0005liveStreaming": {}, "localRecording": { "clientState": { "off": "", @@ -393,6 +400,7 @@ "stop": "Fini registradon", "yes": "Jes" }, + "\u0005localRecording": {}, "lockRoomPassword": "Pasvorto", "lockRoomPasswordUppercase": "Pasvorto", "me": "mi", @@ -444,6 +452,7 @@ "rejected": "", "ringing": "" }, + "\u0005presenceStatus": {}, "profile": { "setDisplayNameLabel": "Agordi vian videblan nomon", "setEmailInput": "Enigu retpoŝtadreson", @@ -475,6 +484,7 @@ "unavailable": "", "unavailableTitle": "Registrado ne disponeblas" }, + "\u0005recording": {}, "sectionList": { "pullToRefresh": "" }, @@ -501,6 +511,9 @@ "startVideoMuted": "Ĉiuj komenciĝas kaŝitaj", "title": "Agordoj" }, + "\u0005settings": { + "calendar": {} + }, "settingsView": { "alertOk": "", "alertTitle": "Averto", @@ -617,6 +630,9 @@ "startvideoblur": "", "stopvideoblur": "" }, + "\u0005toolbar": { + "accessibilityLabel": {} + }, "transcribing": { "ccButtonTooltip": "", "error": "Registrado malsukcesis. Bonvolu provi denove.", @@ -629,6 +645,7 @@ "stop": "", "tr": "" }, + "\u0005transcribing": {}, "userMedia": { "androidGrantPermissions": "Elektu <b><i>Permesi</i></b> kiam via foliumilo petos permesojn.", "chromeGrantPermissions": "Elektu <b><i>Permesi</i></b> kiam via foliumilo petos permesojn.", @@ -708,4 +725,4 @@ "terms": "Kondiĉoj", "title": "" } -} +} \ No newline at end of file diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-es.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-es.json index 24bad2dcf..39bb8a319 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-es.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-es.json @@ -77,11 +77,7 @@ "DISCONNECTED": "Desconectado", "DISCONNECTING": "Desconectando", "ERROR": "Error", - "RECONNECTING": "Ocurrió un problema en la red. Reconectando...", - "LOW_BANDWIDTH": "", - "GOT_SESSION_ID": "", - "GET_SESSION_ID_ERROR": "", - "FETCH_SESSION_ID": "" + "RECONNECTING": "Ocurrió un problema en la red. Reconectando..." }, "connectionindicator": { "address": "Dirección:", @@ -125,7 +121,7 @@ "downloadApp": "Descargar la app", "launchWebButton": "Iniciar en web", "openApp": "Continuar a la aplicación", - "title": "Iniciar su reunión en {{app}}…", + "title": "Iniciar su reunión en {{app}}...", "tryAgainButton": "Intentar de nuevo en el escritorio" }, "defaultLink": "ej. {{url}}", @@ -160,9 +156,9 @@ "cameraUnsupportedResolutionError": "Su cámara no soporta la resolución de video.", "Cancel": "Cancelar", "close": "Cerrar", - "conferenceDisconnectMsg": "Es posible que desee comprobar la conexión de red. Reconectando en {{seconds}} segundos…", + "conferenceDisconnectMsg": "Es posible que desee comprobar la conexión de red. Reconectando en {{seconds}} segundos...", "conferenceDisconnectTitle": "Ha sido desconectado.", - "conferenceReloadMsg": "Estamos tratando de arreglar esto. Reconectando en {{seconds}} segundos…", + "conferenceReloadMsg": "Estamos tratando de arreglar esto. Reconectando en {{seconds}} segundos...", "conferenceReloadTitle": "Desafortunadamente, algo salió mal.", "confirm": "Confirmar", "confirmNo": "No", @@ -188,7 +184,7 @@ "inlineInstallExtension": "Instalar ahora", "internalError": "¡Oops! Algo salió mal. El siguiente error ocurrió: {{error}}", "internalErrorTitle": "Error interno", - "kickMessage": "Puede ponerse en contacto con {{participantDisplayName}} para obtener más detalles.", + "kickMessage": "Puede ponerse en contacto con {{participantDisplayName}} para obtener más detalles.", "kickParticipantButton": "Expulsar", "kickParticipantDialog": "¿Seguro que quiere expulsar a este participante?", "kickParticipantTitle": "¿Expulsar a este participante?", @@ -208,15 +204,9 @@ "micNotSendingData": "Vaya a la configuración de su computadora para activar el micrófono y ajustar su nivel", "micNotSendingDataTitle": "Su micrófono está silenciado en la configuración de su sistema", "micPermissionDeniedError": "No ha otorgado permisos para usar su micrófono. Puede unirse a la conferencia, pero no lo podrán escuchar. Utilice el botón en la barra de dirección para solucionar esto.", - "micUnknownError": "No se puede usar el micrófono por motivos desconocidos.", - "muteEveryoneElseDialog": "Una vez silenciados, no podrás quitarles el modo silencio, pero ellos podrán hacerlo en cualquier momento.", - "muteEveryoneElseTitle": "¿Silenciar a todos los participantes excepto a {{whom}}?", - "muteEveryoneDialog": "¿Estás seguro de silenciar a todos los participantes? No podrás quitarles el modo en silencio, pero ellos podrán hacerlo en cualquier momento.", - "muteEveryoneTitle": "¿Silenciar a todos los participantes?", - "muteEveryoneSelf": "A ti mismo", - "muteEveryoneStartMuted": "Todos los participantes comienzan silenciados a partir de ahora", + "micUnknownError": "No se puede usar su micrófono por motivos desconocidos.", "muteParticipantBody": "No podrás quitarles el modo en silencio, pero ellos pueden quitárselo en cualquier momento.", - "muteParticipantButton": "Silenciar", + "muteParticipantButton": "Control de escritorio remoto", "muteParticipantDialog": "¿Seguro que quiere silenciar a este participante? No podrá revertir esta acción, pero el participante podrá hacerlo en cualquier momento", "muteParticipantTitle": "¿Silenciar a este participante?", "Ok": "Aceptar", @@ -279,13 +269,12 @@ "userPassword": "contraseña del usuario", "WaitForHostMsg": "La conferencia <b> {{room}} </b> aún no ha comenzado. Si usted es el anfitrión, por favor autentíquese. De lo contrario, espere a que llegue el anfitrión.", "WaitForHostMsgWOk": "La conferencia <b> {{room}} </b> aún no ha comenzado. Si usted es el anfitrión, presione Ok para autenticar. De lo contrario, espere a que llegue el anfitrión.", - "WaitingForHost": "Esperando al anfitrión …", + "WaitingForHost": "Esperando al anfitrión ...", "Yes": "Sí", - "yourEntireScreen": "Su pantalla completa", - "muteEveryoneDialog": "Silenciar a todos" + "yourEntireScreen": "Su pantalla completa" }, "dialOut": { - "statusMessage": "está {{status}}" + "statusMessage": "esta {{status}}" }, "documentSharing": { "title": "Compartir documento" @@ -379,7 +368,7 @@ "errorLiveStreamNotEnabled": "La transmisión en vivo no está activada en {{email}}. Por favor, active la transmisión en vivo o inicie sesión en una cuenta con transmisión en vivo activada.", "expandedOff": "La transmisión en vivo se ha detenido", "expandedOn": "La reunión se está transmitiendo a YouTube.", - "expandedPending": "La transmisión en vivo se está iniciando …", + "expandedPending": "La transmisión en vivo se está iniciando ...", "failedToStart": "La transmisión en vivo no se puso iniciar", "getStreamKeyManually": "No pudimos buscar ninguna transmisión en vivo. Trate de obtener su clave de transmisión en vivo de YouTube.", "invalidStreamKey": "Es posible que la clave de transmisión sea incorrecta", @@ -387,7 +376,7 @@ "offBy": "{{name}} transmisión en directo", "on": "Emisión en Directo", "onBy": "{{name}} transmisión en directo iniciada", - "pending": "Iniciando Emisión en Directo…", + "pending": "Iniciando Emisión en Directo...", "serviceName": "Servicio de streaming en vivo", "signedInAs": "Actualmente está conectado como:", "signIn": "Iniciar sesión con Google", @@ -465,22 +454,22 @@ "poweredby": "proporcionado por", "presenceStatus": { "busy": "Ocupado", - "calling": "Llamando…", + "calling": "Llamando...", "connected": "Conectado", "connecting": "Conectando…", "connecting2": "Conectando*…", "disconnected": "Desconectado", "expired": "Expirado", "ignored": "Ignorado", - "initializingCall": "Iniciando llamada…", + "initializingCall": "Iniciando llamada...", "invited": "Invitado", "rejected": "Rechazado", - "ringing": "Timbrando…" + "ringing": "Timbrando..." }, "profile": { "setDisplayNameLabel": "Establecer nombre a mostrar", "setEmailInput": "Introducir e-mail", - "setEmailLabel": "Establecer su Gravatar", + "setEmailLabel": "Establecer su gravatar", "title": "Perfil" }, "raisedHand": "Desea hablar", @@ -493,7 +482,7 @@ "error": "Falla de grabación. Vuelva a intentarlo.", "expandedOff": "Grabación detenida", "expandedOn": "La reunión está siendo grabada.", - "expandedPending": "La grabación se está inciando…", + "expandedPending": "La grabación se está inciando...", "failedToStart": "No se pudo iniciar la grabación", "fileSharingdescription": "Compartir la grabación con los participantes de la reunión", "live": "Directo", @@ -502,7 +491,7 @@ "offBy": "{{name}} detuvo la grabación", "on": "Grabando", "onBy": "{{name}} comenzó la grabación", - "pending": "Preparando para grabar la reunión…", + "pending": "Preparando para grabar la reunión...", "rec": "REC", "serviceDescription": "El servicio de grabación guardará la grabación", "serviceName": "Servicio de grabación", @@ -557,7 +546,7 @@ "version": "Versión" }, "share": { - "dialInfoText": "\n\n=====\n\n¿Solo quieres marcar en tu teléfono?\n\n{{defaultDialInNumber}} Haga clic en este enlace para ver el marcado en los números de teléfono de esta reunión\n{{dialInfoPageUrl}}", + "dialInfoText": "\n\n===== \\ n\n¿Solo quieres marcar en tu teléfono? \\ N\n{{defaultDialInNumber}} Haga clic en este enlace para ver el marcado en los números de teléfono de esta reunión\n{{dialInfoPageUrl}}", "mainText": "Presione en el siguiente enlace para unirse a la reunión:\n{{roomUrl}}" }, "speaker": "Participante", @@ -640,8 +629,7 @@ "lowerYourHand": "Bajar la mano", "moreActions": "Más acciones", "moreOptions": "Más opciones", - "mute": "Activar o silenciar el micrófono", - "muteEveryone": "Silenciar a todos", + "mute": "Activar / Desactivar Silencio", "noAudioSignalTitle": "¡No hay entrada proveniente de su micrófono!", "noAudioSignalDesc": "Si no lo silenció a propósito desde la configuración del sistema o el dispositivo, considere cambiar el dispositivo.", "noAudioSignalDescSuggestion": "Si no lo silenció a propósito desde la configuración del sistema o el dispositivo, considere usar el siguiente dispositivo:", @@ -677,7 +665,7 @@ "failedToStart": "No es posible iniciar la transcripción", "labelToolTip": "La reunión se esta transcribiendo", "off": "Transcripción detenida", - "pending": "Preparando la transcripción de la reunión…", + "pending": "Preparando la transcripción de la reunión...", "start": "Mostrar subtítulos", "stop": "Dejar de mostrar subtítulos", "tr": "TR" @@ -726,14 +714,13 @@ "standardDefinition": "Definición estándar" }, "videothumbnail": { - "domute": "Silenciar", - "domuteOthers": "Silenciar a todos", + "domute": "Silenciar", "flip": "Voltear", "kick": "Expulsar", "moderator": "Moderador", "mute": "Participante está silenciado", "muted": "Silenciado", - "remoteControl": "Control remoto", + "remoteControl": "", "show": "Mostrar en escena", "videomute": "El participante ha detenido la cámara." }, @@ -765,7 +752,7 @@ "roomnameHint": "Introduce el nombre o URL de la sala a la que quieres unirte. Puedes crear un nombre nuevo, sólo tienes que hacer llegar este nombre al resto de participantes para que puedan unirse a esta sala.", "sendFeedback": "Enviar comentarios", "terms": "Términos", - "title": "Videoconferencias seguras, con gran variedad de funcionalidades y completamente gratuitas" + "title": "Seguro, lleno de funcionalidades y videoconferencias completamente gratuitas" }, "lonelyMeetingExperience": { "button": "Invitar a otros", diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-esUS.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-esUS.json index 339dcfd12..76aeed9de 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-esUS.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-esUS.json @@ -65,7 +65,7 @@ "dontShowAgain": "No mostrar nuevamente" }, "connectingOverlay": { - "joiningRoom": "Conectando a su reunión…" + "joiningRoom": "Conectando a su reunión..." }, "connection": { "ATTACHED": "Adjunto", @@ -78,9 +78,9 @@ "DISCONNECTING": "Desconectando", "ERROR": "Error", "RECONNECTING": "Ocurrió un problema en la red. Reconectando...", - "FETCH_SESSION_ID": "Obteniendo session-ID…", + "FETCH_SESSION_ID": "Obteniendo session-id...", "GET_SESSION_ID_ERROR": "Obtener session-id error: {{code}}", - "GOT_SESSION_ID": "Obteniendo session-ID… Listo", + "GOT_SESSION_ID": "Obteniendo session-id... Listo", "LOW_BANDWIDTH": "Video para {{displayName}} ha sido deshabilitado para economizar ancho de banda" }, "connectionindicator": { @@ -125,7 +125,7 @@ "downloadApp": "Descargar la aplicación", "launchWebButton": "Iniciar en la Web", "openApp": "Continuar a la aplicación", - "title": "Iniciando la reunión en {{app}}…", + "title": "Iniciando la reunión en {{app}}...", "tryAgainButton": "Intentar de nuevo en el escritorio" }, "defaultLink": "p.ej. {{url}}", @@ -160,9 +160,9 @@ "cameraUnsupportedResolutionError": "La cámara no admite la resolución de video requerida.", "Cancel": "Cancelar", "close": "Cerrar", - "conferenceDisconnectMsg": "Se recomienda que compruebes la conexión de la red. Reconectando en {{seconds}} segundos…", + "conferenceDisconnectMsg": "Se recomienda que compruebes la conexión de la red. Reconectando en {{seconds}} segundos...", "conferenceDisconnectTitle": "Ha sido desconectado.", - "conferenceReloadMsg": "Estamos tratando de arreglar esto. Reconectando en {{seconds}} segundos…", + "conferenceReloadMsg": "Estamos tratando de arreglar esto. Reconectando en {{seconds}} segundos...", "conferenceReloadTitle": "Desafortunadamente, algo salió mal.", "confirm": "Confirmar", "confirmNo": "No", @@ -279,7 +279,7 @@ "userPassword": "contraseña de usuario", "WaitForHostMsg": "La conferencia <b>{{room}}</b> aún no ha comenzado. Si eres el anfitrión, inicia la autenticación. De lo contrario, espera a que llegue el anfitrión.", "WaitForHostMsgWOk": "La conferencia <b>{{room}}</b> aún no ha comenzado. Si eres el anfitrión, presiona Aceptar para autenticar. De lo contrario, espera a que llegue el anfitrión.", - "WaitingForHost": "Esperando al anfitrión…", + "WaitingForHost": "Esperando al anfitrión...", "Yes": "Sí", "yourEntireScreen": "Toda su pantalla" }, @@ -378,7 +378,7 @@ "errorLiveStreamNotEnabled": "La transmisión en vivo no está habilitada en {{email}}. Habilítala o inicia sesión en una cuenta con la transmisión en vivo habilitada.", "expandedOff": "La transmisión en vivo se ha detenido", "expandedOn": "La reunión se está transmitiendo actualmente a YouTube.", - "expandedPending": "La transmisión en vivo se está iniciando…", + "expandedPending": "La transmisión en vivo se está iniciando...", "failedToStart": "La transmisión en vivo no se pudo iniciar", "getStreamKeyManually": "No pudimos obtener ninguna transmisión en vivo. Intenta obtener la clave de transmisión en vivo de YouTube.", "invalidStreamKey": "Es posible que la clave de transmisión en vivo sea incorrecta.", @@ -386,7 +386,7 @@ "offBy": "{{name}} detuvo el streaming en directo", "on": "Transmisión en vivo", "onBy": "{{name}} inició el streaming en directo", - "pending": "Iniciando transmisión en vivo…", + "pending": "Iniciando transmisión en vivo...", "serviceName": "Servicio de transmisión en vivo", "signedInAs": "Actualmente, la sesión está iniciada como:", "signIn": "Iniciar sesión con Google", @@ -464,17 +464,17 @@ "poweredby": "con tecnología de", "presenceStatus": { "busy": "Ocupado", - "calling": "Llamando…", + "calling": "Llamando...", "connected": "Conectado", - "connecting": "Conectando…", + "connecting": "Conectando...", "connecting2": "Conectando*...", "disconnected": "Desconectado", "expired": "Vencido", "ignored": "Omitido", - "initializingCall": "Inicializando llamada…", + "initializingCall": "Inicializando llamada...", "invited": "Invitado", "rejected": "Rechazado", - "ringing": "Timbrando…" + "ringing": "Timbrando..." }, "profile": { "setDisplayNameLabel": "Configurar su nombre para mostrar", @@ -492,7 +492,7 @@ "error": "Error de grabación. Vuelve a intentarlo.", "expandedOff": "La grabación se ha detenido", "expandedOn": "La reunión se está grabando en este momento.", - "expandedPending": "La grabación se está iniciando…", + "expandedPending": "La grabación se está iniciando...", "failedToStart": "La grabación no se pudo iniciar", "fileSharingdescription": "Compartir grabación con participantes de la reunión", "live": "EN VIVO", @@ -501,7 +501,7 @@ "offBy": "{{name}} paró la grabación", "on": "Grabación", "onBy": "{{name}} inició la grabación", - "pending": "Preparando para grabar la reunión…", + "pending": "Preparando para grabar la reunión...", "rec": "REC", "serviceDescription": "El servicio de grabación guardará la grabación", "serviceName": "Servicio de grabación", @@ -647,7 +647,7 @@ "noAudioSignalDesc": "Si no lo silenció intencionalmente desde la configuración del sistema o el hardware, considere la posibilidad de cambiar el dispositivo.", "noAudioSignalDescSuggestion": "Si no lo silenció intencionalmente desde la configuración del sistema o el hardware, considere utilizar el siguiente dispositivo:", "noAudioSignalDialInDesc": "Usted puede además llamar usando:", - "noAudioSignalDialInLinkDesc": "Números de llamada", + "noAudioSignalDialInLinkDesc" : "Números de llamada", "noisyAudioInputTitle": "Su micrófono parece estar ruidoso", "noisyAudioInputDesc": "Parece que su micráfono está haciendo ruido, por favor considere silenciarlo o cambiar de dispositivo.", "openChat": "Abrir chat", @@ -680,7 +680,7 @@ "failedToStart": "La transcripción no se pudo iniciar", "labelToolTip": "La reunión se está transcribiendo", "off": "Transcripción detenida", - "pending": "Preparando para transcribir la reunión…", + "pending": "Preparando para transcribir la reunión...", "start": "Comenzar a mostrar subtítulos", "stop": "Dejar de mostrar subtítulos", "tr": "TR" diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-et.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-et.json index e3510b297..2ff8d2fcc 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-et.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-et.json @@ -1,777 +1,777 @@ { - "addPeople": { - "add": "Lisa", - "countryNotSupported": "Valitud riik ei ole toetatud.", - "countryReminder": "Veendu, et suunakood oleks lisatud.", - "disabled": "Uusi kontakte ei saa kõnesse lisada.", - "failedToAdd": "Uue kontakti kõnesse lisamine ebaõnnestus", - "footerText": "Numbri valimine on keelatud.", - "loading": "Kontaktide otsimine…", - "loadingNumber": "Telefoninumbri kontrollimine…", - "loadingPeople": "Kontaktide otsimine kõnesse lisamiseks…", - "noResults": "Vasteid ei leitud", - "noValidNumbers": "Sisesta telefoninumber", - "searchNumbers": "Lisa telefoninumber", - "searchPeople": "Kontaktide otsimine", - "searchPeopleAndNumbers": "Otsi kontakti või lisa telefoninumber", - "telephone": "Telefoninumber: {{number}}", - "title": "Lisa kontakte kõnesse" + "addPeople": { + "add": "Lisa", + "countryNotSupported": "Valitud riik ei ole toetatud.", + "countryReminder": "Veendu, et suunakood oleks lisatud.", + "disabled": "Uusi kontakte ei saa kõnesse lisada.", + "failedToAdd": "Uue kontakti kõnesse lisamine ebaõnnestus", + "footerText": "Numbri valimine on keelatud.", + "loading": "Kontaktide otsimine...", + "loadingNumber": "Telefoninumbri kontrollimine...", + "loadingPeople": "Kontaktide otsimine kõnesse lisamiseks...", + "noResults": "Vasteid ei leitud", + "noValidNumbers": "Sisesta telefoninumber", + "searchNumbers": "Lisa telefoninumber", + "searchPeople": "Kontaktide otsimine", + "searchPeopleAndNumbers": "Otsi kontakti või lisa telefoninumber", + "telephone": "Telefoninumber: {{number}}", + "title": "Lisa kontakte kõnesse" + }, + "audioDevices": { + "bluetooth": "Bluetooth", + "headphones": "Kõrvaklapid", + "phone": "Telefon", + "speaker": "Kõlar", + "none": "Heli vahendid pole kättesaadavad" + }, + "audioOnly": { + "audioOnly": "Ainult heli" + }, + "calendarSync": { + "addMeetingURL": "Lisa kõne link", + "confirmAddLink": "Kas soovid käesolevale kõnele lisada lingi?", + "error": { + "appConfiguration": "Ühendus kalendriga ei ole õigesti seadistatud.", + "generic": "Viga! Palun kontrolli kalendri seadistusi või värskenda kalendrit.", + "notSignedIn": "Viga kalendri autentimisel! Palun kontrolli kalendri seadistusi ja logi uuesti sisse." }, - "audioDevices": { - "bluetooth": "Bluetooth", - "headphones": "Kõrvaklapid", - "phone": "Telefon", - "speaker": "Kõlar", - "none": "Heli vahendid pole kättesaadavad" + "join": "Liitu", + "joinTooltip": "Liitu kõnega", + "nextMeeting": "järgmine kõne", + "noEvents": "Uusi kõnesid pole planeeritud..", + "ongoingMeeting": "aktiivne kõne", + "permissionButton": "Ava seadistused", + "permissionMessage": "Planeeritud kõne nägemiseks on vajalik kalendri ligipääsuõigus.", + "refresh": "Värskenda kalendrit", + "today": "Täna" + }, + "chat": { + "error": "Viga: sõnumi \"{{originalText}}\" saatmine ebaõnnestus. Põhjus: {{error}}", + "fieldPlaceHolder": "Sisesta oma sõnum siia", + "messagebox": "Sisesta sõnum", + "messageTo": "Privaatsõnum kasutajale {{recipient}}", + "noMessagesMessage": "Kirjavahetust pole veel alustatud. Alusta kirjavahetust siin!", + "nickname": { + "popover": "Sisesta nimi", + "title": "Sisesta nimi, et kõnega alustada" }, - "audioOnly": { - "audioOnly": "Ainult heli" + "privateNotice": "Privaatsõnum kasutajale {{recipient}}", + "title": "Kõne", + "you": "you" + }, + "chromeExtensionBanner": { + "installExtensionText": "Paigalda Google Kalendri laiendus ja Office 365 integratsioon", + "buttonText": "Paigalda Chrome'i laiendus", + "dontShowAgain": "Ära rohkem näita" + }, + "connectingOverlay": { + "joiningRoom": "Kõnega ühendamine..." + }, + "connection": { + "ATTACHED": "Ühendatud", + "AUTHENTICATING": "Autentimine...", + "AUTHFAIL": "Autentimine ebaõnnestus", + "CONNECTED": "Ühendatud", + "CONNECTING": "Ühendamine...", + "CONNFAIL": "Ühendamine ebaõnnestus", + "DISCONNECTED": "Ühendus katkestatud", + "DISCONNECTING": "Ühenduse katkestamine...", + "ERROR": "Viga", + "FETCH_SESSION_ID": "Sessiooni-ID püüdmine...", + "GET_SESSION_ID_ERROR": "Sessiooni-ID püüdmisel tekkis viga: {{code}}", + "GOT_SESSION_ID": "Sessiooni-ID püüdmine... Tehtud", + "LOW_BANDWIDTH": "Kasutaja {{displayName}} video on ülekandekiiruse parandamiseks välja lülitatud" + }, + "connectionindicator": { + "address": "Aadress:", + "bandwidth": "Eeldatav ülekandekiirus:", + "bitrate": "Andmeedastuskiirus:", + "bridgeCount": "Serverite arv: ", + "connectedTo": "Ühendatud:", + "e2e_rtt": "E2E RTT:", + "framerate": "Ekraani eraldusvõime:", + "less": "Näita vähem", + "localaddress": "Lokaalne aadress:", + "localaddress_plural": "Lokaalsed aadressid:", + "localport": "Lokaalne port:", + "localport_plural": "Lokaalsed pordid:", + "more": "Näita rohkem", + "packetloss": "Andmepaketi kaotus:", + "quality": { + "good": "Hea", + "inactive": "Mitteaktiivne", + "lost": "Kaotatud", + "nonoptimal": "Mitteoptimaalne", + "poor": "Nõrk" }, - "calendarSync": { - "addMeetingURL": "Lisa kõne link", - "confirmAddLink": "Kas soovid käesolevale kõnele lisada lingi?", - "error": { - "appConfiguration": "Ühendus kalendriga ei ole õigesti seadistatud.", - "generic": "Viga! Palun kontrolli kalendri seadistusi või värskenda kalendrit.", - "notSignedIn": "Viga kalendri autentimisel! Palun kontrolli kalendri seadistusi ja logi uuesti sisse." - }, - "join": "Liitu", - "joinTooltip": "Liitu kõnega", - "nextMeeting": "järgmine kõne", - "noEvents": "Uusi kõnesid pole planeeritud..", - "ongoingMeeting": "aktiivne kõne", - "permissionButton": "Ava seadistused", - "permissionMessage": "Planeeritud kõne nägemiseks on vajalik kalendri ligipääsuõigus.", - "refresh": "Värskenda kalendrit", - "today": "Täna" + "remoteaddress": "Kaugtöö aadress:", + "remoteaddress_plural": "Kaugtöö aadressid:", + "remoteport": "Kaugtöö port:", + "remoteport_plural": "Kaugtöö pordid:", + "resolution": "Resolutsioon:", + "status": "Ühendus:", + "transport": "Transport:", + "transport_plural": "Transpordid:" + }, + "dateUtils": { + "earlier": "Varem", + "today": "Täna", + "yesterday": "Eile" + }, + "deepLinking": { + "appNotInstalled": "Kõnega liitumiseks läbi mobiiltelefoni on vaja paigaldada {{app}} rakendus.", + "description": "Midagi ei juhtunud? Proovisime ühendust luua töölaua rakendusega. Proovi uuesti või käivita {{app}} rakendus.", + "descriptionWithoutWeb": "Midagi ei juhtunud? Televastuvõttu prooviti avada töölaua rakendusest {{app}}.", + "downloadApp": "Laadi rakendus alla", + "launchWebButton": "Käivita veebis", + "openApp": "Jätka töölaua rakendusega", + "title": "Kõne avamine rakenduses {{app}}...", + "tryAgainButton": "Proovi töölaua rakendusega uuesti " + }, + "defaultLink": "nt {{url}}", + "defaultNickname": "nt. Mari Maasikas", + "deviceError": { + "cameraError": "Ei saanud kaameraga ühendust", + "cameraPermission": "Puudub õigus kasutada kaamerat", + "microphoneError": "Ei saanud mikrofoniga ühendust", + "microphonePermission": "Puudub õigus kasutada mikrofoni" + }, + "deviceSelection": { + "noPermission": "Luba pole antud", + "previewUnavailable": "Eelvaade pole kättesaadav", + "selectADevice": "Vali seade", + "testAudio": "Mängi testimiseks heli" + }, + "dialog": { + "accessibilityLabel": { + "liveStreaming": "Otseülekanne" }, - "chat": { - "error": "Viga: sõnumi \"{{originalText}}\" saatmine ebaõnnestus. Põhjus: {{error}}", - "fieldPlaceHolder": "Sisesta oma sõnum siia", - "messagebox": "Sisesta sõnum", - "messageTo": "Privaatsõnum kasutajale {{recipient}}", - "noMessagesMessage": "Kirjavahetust pole veel alustatud. Alusta kirjavahetust siin!", - "nickname": { - "popover": "Sisesta nimi", - "title": "Sisesta nimi, et kõnega alustada" - }, - "privateNotice": "Privaatsõnum kasutajale {{recipient}}", - "title": "Kõne", - "you": "you" + "allow": "Luba", + "alreadySharedVideoMsg": "Teine kasutaja jagab videot. Selles kõnes on ainult ühe video jagamine korraga lubatud.", + "alreadySharedVideoTitle": "Korraga on lubatud ainult ühe video jagamine.", + "applicationWindow": "Rakenduse aken", + "Back": "Tagasi", + "cameraConstraintFailedError": "Kaamera ei vasta teatud piirangutele.", + "cameraNotFoundError": "Kaamerat ei leitud.", + "cameraNotSendingData": "Ei saa ühendust kaameraga. Kontrolli, kas vahend on mõne teise rakenduse poolt kasutusel, vali menüüst teine vahend või värskenda rakendust.", + "cameraNotSendingDataTitle": "Kaamera pole kättesaadav.", + "cameraPermissionDeniedError": "Kaamera kasutamine on keelatud. Kõnega on võimalik ühineda ilma kaamerata. Kaamera kasutamiseks vajuta aadressiribal kaamera nupule.", + "cameraUnknownError": "Kaamerat ei saa kasutada! Põhjus teadmata.", + "cameraUnsupportedResolutionError": "Kaamera ei toeta nõutud resolutsiooni.", + "Cancel": "Tühista", + "close": "Sulge", + "conferenceDisconnectMsg": "Kontrolli võrguühendust. Taasühendamine {{seconds}}...", + "conferenceDisconnectTitle": "Ühendus on katkenud.", + "conferenceReloadMsg": "Lahenduse otsime. Taasühendus {{seconds}} sek...", + "conferenceReloadTitle": "Midagi läks valesti!", + "confirm": "Kinnita", + "confirmNo": "Ei", + "confirmYes": "Kinnita", + "connectError": "Oih, midagi läks valesti! Kõnega ühendamine ebaõnnestus.", + "connectErrorWithMsg": "Oih, midagi läks valesti! Kõnega ühendamine ebaõnnestus. Põhjus: {{msg}}.", + "connecting": "Ühendamine.", + "contactSupport": "Võta ühendust kasutustoega", + "copy": "Kopeeri", + "dismiss": "Lõpeta", + "displayNameRequired": "Nimi on kohustuslik", + "done": "Valmis", + "enterDisplayName": "Sisesta nimi", + "error": "Viga", + "externalInstallationMsg": "Töölauale on vaja paigaldada jagamise laiendus.", + "externalInstallationTitle": "Laiendus on kohustuslik", + "goToStore": "Mine veebipoodi", + "gracefulShutdown": "Rakendus on hoolduseks ajutiselt maas. Proovi hiljem uuesti!", + "IamHost": "Mina olen võõrustaja", + "incorrectRoomLockPassword": "Vale parool", + "incorrectPassword": "Vale kasutajanimi või parool", + "inlineInstallationMsg": "Töölauale tuleb paigaldada jagamise laiendus.", + "inlineInstallExtension": "Paiglada kohe", + "internalError": "Oih, midagi läks valesti! Veateate: {{error}}.", + "internalErrorTitle": "Sisemine viga", + "kickMessage": "Oih, oled kõnest eemaldatud!", + "kickParticipantButton": "Eemalda kõnest", + "kickParticipantDialog": "Oled kindel, et tahad kasutaja kõnest eemaldada?", + "kickParticipantTitle": "Eemalda kasutaja kõnest?", + "kickTitle": "Kõnest eemaldatud", + "liveStreaming": "Otseülekanne", + "liveStreamingDisabledForGuestTooltip": "Külalised ei saa otseülekannet alustada.", + "liveStreamingDisabledTooltip": "Otseülekande alustamine on keelatud.", + "lockMessage": "Ebaõnnestunud lukustada kõnet.", + "lockRoom": "Lisa kõnele parool", + "lockTitle": "Lukustamine ebaõnnestus", + "logoutQuestion": "Oled kindel, et tahad kõne peatada ja välja logida?", + "logoutTitle": "Logi välja", + "maxUsersLimitReached": "Maksimaalne kõnes osalejate arv on täis. Võta ühendust kõne omanikuga või proovi hiljem uuesti!", + "maxUsersLimitReachedTitle": "Maksimaalne kõnes osalejate arv on täis", + "micConstraintFailedError": "Mikrofon ei vasta teatud piirangutele.", + "micNotFoundError": "Mikrofoni ei leitud.", + "micNotSendingData": "Ei saa ühendust mikrofoniga. Vali menüüst teine vahend või värskenda rakendust.", + "micNotSendingDataTitle": "Mikrofon pole kättesaadav.", + "micPermissionDeniedError": "Mikrofoni kasutamine on keelatud. Kõnega on võimalik ühineda, aga teised Sind ei kuule. Mikrofoni kasutamiseks vajuta aadressiribal mikrofoni nupule.", + "micUnknownError": "Mikrofoni ei saa kasutada. Põhjus teadmata.", + "muteEveryoneElseDialog": "Peale mikrofoni vaigistamist saab ainult kasutaja ise oma mikrofoni tagasi sisse lülitada.", + "muteEveryoneElseTitle": "Vaigista kõikide teiste mikrofonid, välja arvatud {{whom}}?", + "muteEveryoneDialog": "Oled kindel, et soovid kõikide teiste mikrofonid vaigistada? Neid saab tagasi sisse lülitada ainult kasutaja ise.", + "muteEveryoneTitle": "Vaigista kõik?", + "muteEveryoneSelf": "Sina ise", + "muteEveryoneStartMuted": "Edaspidi alustavad kõik välja lülitatud mikrofonidega", + "muteParticipantBody": "Teiste kasutajate mikrofoni ei saa sisse lülitada. Kasutaja saab ise otsutada, kas mikrofon on sees või väljas.", + "muteParticipantButton": "Lülita mikrofon välja", + "muteParticipantDialog": "Oled kindel, et soovid kasutaja mikrofoni välja lülitada? Seda saab ainult kasutaja ise sisse tagasi lülitada.", + "muteParticipantTitle": "Lülita kasutaja mikrofon välja?", + "Ok": "Jah", + "passwordLabel": "Parool", + "passwordNotSupported": "Kõnele ei saa parooli määrata.", + "passwordNotSupportedTitle": "Parooli lisamine pole toetatud", + "passwordRequired": "Parool on kohustuslik", + "popupError": "Modaalaknad on veebilehitsejas keelatud. Palun luba modaalakende kasutamine veebilehitseja turvalisuse seadistuses ning proovi uuesti.", + "popupErrorTitle": "Modaalaknad on keelatud", + "recording": "Salvetamine", + "recordingDisabledForGuestTooltip": "Külalised ei saa kõne salvestada.", + "recordingDisabledTooltip": "Kõne salvestamine on keelatud.", + "rejoinNow": "Ühine uuesti", + "remoteControlAllowedMessage": "{{user}} andis kaugjuhtimiseks loa!", + "remoteControlDeniedMessage": "{{user}} keelas kaugjuhtimise!", + "remoteControlErrorMessage": "Viga kaugjuhtimiseks loa küsimisel kasutajalt {{user}}!", + "remoteControlRequestMessage": "Kas lubad kasutajal {{user}} oma töölauda kaugjuhtida?", + "remoteControlShareScreenWarning": "Kui vajutad nupule \"Luba\", siis jagad oma ekraani.", + "remoteControlStopMessage": "Kaugjuhtimise sessioon on lõppenud!", + "remoteControlTitle": "Kaugjuhtimine", + "Remove": "Eemalda", + "removePassword": "Eemalda parool", + "removeSharedVideoMsg": "Oled kindel, et soovid oma jagatud video eemaldada?", + "removeSharedVideoTitle": "Eemalda jagatud video", + "reservationError": "Broneerimise süsteemi viga", + "reservationErrorMsg": "Veakood: {{code}}, sõnum: {{msg}}", + "retry": "Proovi uuesti", + "screenSharingFailedToInstall": "Oih, ekraanijagamise laienduse paigaldamine ebaõnnestus!", + "screenSharingFailedToInstallTitle": "Ekraanijagamise laienduse paigaldamine ebaõnnestus", + "screenSharingFirefoxPermissionDeniedError": "Ekraani jagamisega läks midagi valesti! Veendu, et oled ekraani jagamiseks loa andnud.", + "screenSharingFirefoxPermissionDeniedTitle": "Oih, ekraani jagamist ei saanud alustada!", + "screenSharingPermissionDeniedError": "Oih, midagi läks valesti ekraanijagamise laienduse õigustega! Värskenda ja proovi uuesti.", + "sendPrivateMessage": "Sulle saabus privaatsõnum. Kas soovid vastata privaatselt või avalikult?", + "sendPrivateMessageCancel": "Saada sõnum avalikult", + "sendPrivateMessageOk": "Saada sõnum privaatselt", + "sendPrivateMessageTitle": "Saada privaatselt?", + "serviceUnavailable": "Teenus pole kättesaadav", + "sessTerminated": "Kõne lõpetatud", + "Share": "Jaga", + "shareVideoLinkError": "Sisesta korrektne Youtube’i link.", + "shareVideoTitle": "Jaga videot", + "shareYourScreen": "Jaga ekraani", + "shareYourScreenDisabled": "Ekraani jagamine on keelatud.", + "shareYourScreenDisabledForGuest": "Külalised ei saa ekraani jagada.", + "startLiveStreaming": "Alusta otseülekannet", + "startRecording": "Alusta salvestamist", + "startRemoteControlErrorMessage": "Kaugjuhtimise sessiooni alustamisel tekkis viga!", + "stopLiveStreaming": "Lõpeta otseülekanne", + "stopRecording": "Lõpeta salvestamine", + "stopRecordingWarning": "Oled kindel, et soovid salvestamist lõpetada?", + "stopStreamingWarning": "Oled kindel, et soovid otseülekannet lõpetada?", + "streamKey": "Otseülekande võti", + "Submit": "Esita", + "thankYou": "Aitäh, et kasutasid rakendust {{appName}}!", + "token": "token", + "tokenAuthFailed": "Kahjuks ei ole kõnega ühinemine lubatud.", + "tokenAuthFailedTitle": "Autentimine ebaõnnestus", + "transcribing": "Transkribeerimine", + "unlockRoom": "Eemalda kõne parool", + "userPassword": "kasutaja parool", + "WaitForHostMsg": "Kõne <b>{{room}}</b> ei ole veel alanud. Autendi ennast, kui oled võõrustaja. Külalisena oota, kuni võõrustaja saabub.", + "WaitForHostMsgWOk": "Kõne <b>{{room}}</b> ei ole veel alanud. Kui oled võõrustaja, vajuta OK, et ennast autentida. Külalisena oota, kuni võõrustaja saabub.", + "WaitingForHost": "Võõrustaja ootamine...", + "Yes": "Jah", + "yourEntireScreen": "Täisekraan" + }, + "dialOut": { + "statusMessage": "on staatusega {{status}}" + }, + "documentSharing": { + "title": "Jagatud dokument" + }, + "feedback": { + "average": "Keskmine", + "bad": "Halb", + "detailsLabel": "Kirjelda täpsemalt.", + "good": "Hea", + "rateExperience": "Hinda kõne kvaliteeti", + "veryBad": "Väga halb", + "veryGood": "Väga hea" + }, + "incomingCall": { + "answer": "Vasta", + "audioCallTitle": "Sissetulev kõne", + "decline": "Lõpeta", + "productLabel": "Jitsi", + "videoCallTitle": "Sissetulev videokõne" + }, + "info": { + "accessibilityLabel": "Näita infot", + "addPassword": "Lisa parool", + "cancelPassword": "Tühista parool", + "conferenceURL": "Link:", + "country": "Riik", + "dialANumber": "Kõnega ühinemiseks vali number ja sisesta pin-kood.", + "dialInConferenceID": "PIN:", + "dialInNotSupported": "Oih, sissehelistamine ei ole toetatud!", + "dialInNumber": "Sissehelistamine:", + "dialInSummaryError": "Sissehelistamise info pole kättesaadav. Proovi hiljem uuesti!", + "dialInTollFree": "Maksuvaba", + "genericError": "Oih, midagi läks valesti!", + "inviteLiveStream": "Otseülekande nägemiseks vajuta lingile: {{url}}", + "invitePhone": "Üks klikk heliga sissehelistamiseks: {{number}},,{{conferenceID}}#", + "invitePhoneAlternatives": "Otsid teist sissehelistamise numbrit?\nVaata sissehelistamise numbreid: {{url}}\n\n\nKui helistad läbi ruumi, ühine kõnega väljalülitatud mikrofoni režiimis: {{silentUrl}}", + "inviteURLFirstPartGeneral": "Oled kõnesse kutsutud.", + "inviteURLFirstPartPersonal": "{{name}} kutsub Sind kõnesse.\n", + "inviteURLSecondPart": "\nÜhine kõnega:\n{{url}}\n", + "liveStreamURL": "Otseülekanne:", + "moreNumbers": "Rohkem numbreid", + "noNumbers": "Sissehelistamise numbrid puuduvad.", + "noPassword": "Andmed puuduvad", + "noRoom": "Sissehelistamise ruum pole täpsustatud.", + "numbers": "Sissehelistamise numbrid", + "password": "Parool:", + "title": "Jaga", + "tooltip": "Jaga linki ja helista, et kõnega ühineda", + "label": "Kõne info" + }, + "inviteDialog": { + "alertText": "Osade kasutajate kutsumine ebaõnnestus.", + "header": "Kutsu", + "searchCallOnlyPlaceholder": "Sisesta telefoninumber", + "searchPeopleOnlyPlaceholder": "Otsi kasutajaid", + "searchPlaceholder": "Kasutaja telefoninumber", + "send": "Saada" + }, + "inlineDialogFailure": { + "msg": "Midagi läks valesti.", + "retry": "Proovi uuesti", + "support": "Kasutajatugi", + "supportMsg": "Kui see juhtub uuesti, võta ühendust" + }, + "keyboardShortcuts": { + "focusLocal": "Keskendu videole", + "focusRemote": "Keskendu teise kasutaja videole", + "fullScreen": "Ava/sulge täisekraani vaade", + "keyboardShortcuts": "Klaviatuuri kiirvalikud", + "localRecording": "Näita/peida salvestamise võimalused", + "mute": "Lülita mikrofon sisse/välja", + "pushToTalk": "Vajuta, et rääkida", + "raiseHand": "Tõsta/langeta kätt", + "showSpeakerStats": "Näita kõnelejate statistikat", + "toggleChat": "Ava/sulge vestluse aken", + "toggleFilmstrip": "Näita/peida video eelvaade", + "toggleScreensharing": "Vaheta kaamera ja ekraanijagamise vahel", + "toggleShortcuts": "Näita/peida klaviatuuri kiirvalikud", + "videoMute": "Lülita kaamera sisse/välja", + "videoQuality": "Halda kõne kvaliteeti" + }, + "liveStreaming": { + "busy": "Toimub ülekande ressursi vabastamine. Proovi mõne minuti pärast uuesti.", + "busyTitle": "Kõik ülekandjad on hetkel hõivatud", + "changeSignIn": "Vaheta kontot.", + "choose": "Vali otseülekanne", + "chooseCTA": "Vali ülekande viis. Oled sisse logitud e-mailiga {{email}}.", + "enterStreamKey": "Sisesta siia oma YouTube’i ülekande võti.", + "error": "Otseülekanne ebaõnnestus. Proovi uuesti.", + "errorAPI": "YouTube’i kanaliga ühendumisel tekkis viga. Palun logi uuesti sisse.", + "errorLiveStreamNotEnabled": "Otseülekanne ei ole e-mailiga {{email}} sisse lülitatud. Luba kasutajaga otseülekanded või vaheta kontot.", + "expandedOff": "Otseülekanne on peatatud", + "expandedOn": "Kõnest tehakse otseülekanne YouTube’i.", + "expandedPending": "Otseülekanne algab...", + "failedToStart": "Otseülekandega alustamine ebaõnnestus.", + "getStreamKeyManually": "Ülekandjaid ei leitud. Leia YouTube’st otseülekande võti.", + "invalidStreamKey": "Otseülekande võti võib olla vale.", + "off": "Otseülekanne on peatatud", + "offBy": "{{name}} lõpetas otseülekande", + "on": "Otseülekanne", + "onBy": "{{name}} alustas otseülekandega", + "pending": "Otseülekande alustamine...", + "serviceName": "Otseülekande teenus", + "signedInAs": "Oled sisse logitud kasutajana:", + "signIn": "Google’ga sisselogimine", + "signInCTA": "Logi sisse või sisesta otseülekande võti YouTube’st.", + "signOut": "Logi välja", + "start": "Alusta otseülekannet.", + "streamIdHelp": "Mis see on?", + "unavailableTitle": "Otseülekanne pole kättesaadav." + }, + "localRecording": { + "clientState": { + "off": "Väljas", + "on": "Sees", + "unknown": "Teadmata" }, - "chromeExtensionBanner": { - "installExtensionText": "Paigalda Google Kalendri laiendus ja Office 365 integratsioon", - "buttonText": "Paigalda Chrome'i laiendus", - "dontShowAgain": "Ära rohkem näita" + "dialogTitle": "Kohalikud salvestamise nupud", + "duration": "Kestvus", + "durationNA": "N/A", + "encoding": "Kodeerimine", + "label": "LOR", + "labelToolTip": "Kohalik salvestamine on alustatud", + "localRecording": "Kohalik salvestamine", + "me": "Mina", + "messages": { + "engaged": "Local recording engaged.", + "finished": "Salvestamise sessioon {{token}} on lõppenud. Palun saada salvestatud fail moderaatorile.", + "finishedModerator": "Salvestamise sessioon {{token}} on lõppenud ja salvestatud. Küsi teistelt kontaktidelt nende koopiaid.", + "notModerator": "Sa ei ole moderaator. Sa ei saa alustada ega lõpetada kohalikku salvestamist." }, - "connectingOverlay": { - "joiningRoom": "Kõnega ühendamine…" + "moderator": "Moderaator", + "no": "Ei", + "participant": "Osaleja", + "participantStats": "Osaleja andmed", + "sessionToken": "Sessiooni token", + "start": "Alusta salvestamist", + "stop": "Lõpeta salvestamine", + "yes": "Jah" + }, + "lockRoomPassword": "parool", + "lockRoomPasswordUppercase": "Parool", + "me": "mina", + "notify": { + "connectedOneMember": "{{name}} ühines kõnega", + "connectedThreePlusMembers": "{{name}} ja {{count}} teist kasutajat ühines kõnega", + "connectedTwoMembers": "{{first}} ja {{second}} ühinesid kõnega", + "disconnected": "lahti ühendatud", + "focus": "Konverentsi fookus", + "focusFail": "{{component}} pole kättesaadav - proovi uuesti {{ms}} sekundi pärast.", + "grantedTo": "Moderaatori õigused on antud kasutajale {{to}}!", + "invitedOneMember": "{{name}} on kutsutud", + "invitedThreePlusMembers": "{{name}} ja {{count}} teist kasutajat on kutsutud", + "invitedTwoMembers": "{{first}} ja {{second}} on kutsutud", + "kickParticipant": "{{kicked}} eemaldati kõnest kasutaja {{kicker}} poolt", + "me": "Mina", + "moderator": "Moderaatori õigused jagatud!", + "muted": "Alustasid kõnet väljalülitatud mikrofoniga.", + "mutedTitle": "Mikrofon on välja lülitatud!", + "mutedRemotelyTitle": "Sinu mikrofon lülitati välja kasutaja {{participantDisplayName}} poolt!", + "mutedRemotelyDescription": "Saad alati oma mikrofoni sisse lülitada, kui soovid rääkida. Lülita mikrofon peale rääkimist uuesti välja liigse müra ja kaja vältimiseks.", + "passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) eemaldatud teise kasutaja poolt", + "passwordSetRemotely": "$t(lockRoomPasswordUppercase) lisatud teise kasutaja poolt", + "raisedHand": "{{name}} soovib rääkida.", + "somebody": "Keegi", + "startSilentTitle": "Ühinesid ilma mikrofonita!", + "startSilentDescription": "Mikrofoni kasutamiseks ühine kõnega uuesti", + "suboptimalExperienceDescription": "Rakenduse {{appName}} parima kvaliteedi tagamiseks palun kasuta <a href='static/recommendedBrowsers.html' target='_blank'>ühte nendest veebilehitsejatest</a>.", + "suboptimalExperienceTitle": "Veebilehitseja hoiatus", + "unmute": "Lülita mikrofon sisse", + "newDeviceCameraTitle": "Leitud uus kaamera", + "newDeviceAudioTitle": "Leitud uus heliseadeldis", + "newDeviceAction": "Kasuta" + }, + "passwordSetRemotely": "määratud teise kasutaja poolt", + "passwordDigitsOnly": "Kuni {{number}} tähemärki", + "poweredby": "teieni toodud", + "presenceStatus": { + "busy": "Hõivatud", + "calling": "Helistamine...", + "connected": "Ühendatud", + "connecting": "Ühendamine...", + "connecting2": "Ühendamine*...", + "disconnected": "Lahti ühendatud", + "expired": "Aegunud", + "ignored": "Eiratud", + "initializingCall": "Kõne alustamine...", + "invited": "Kutsutud", + "rejected": "Tagasi lükatud", + "ringing": "Kutsumine..." + }, + "profile": { + "setDisplayNameLabel": "Sisesta nimi", + "setEmailInput": "Sisesta e-mail", + "setEmailLabel": "Sisesta gravatar email", + "title": "Profiil" + }, + "raisedHand": "Soovin rääkida", + "recording": { + "authDropboxText": "Lisa Dropbox’i", + "availableSpace": "Vaba ruum: {{spaceLeft}} MB (ca {{duration}} minutit salvestamist)", + "beta": "BETA", + "busy": "Salvestamise ressursi vabastamine... Proovi mõne minuti pärast uuesti.", + "busyTitle": "Kõik salvestajad on praegu kinni", + "error": "Salvestamine ebaõnnestus. Proovi uuesti.", + "expandedOff": "Salvestamine peatatud", + "expandedOn": "Kõne salvestatakse.", + "expandedPending": "Salvestamine on alustatud...", + "failedToStart": "Salvestamine ebaõnnestus", + "fileSharingdescription": "Jaga salvestust kõnelejatega", + "live": "Otse", + "loggedIn": "Sisseloginud kasutajana {{userName}}", + "off": "Salvestamine on lõpetatud", + "offBy": "{{name}} lõpetas salvestamise", + "on": "Salvestatakse", + "onBy": "{{name}} alustas salvestamist", + "pending": "Kõne salvestamise ettevalmistus...", + "rec": "REC", + "serviceDescription": "Salvestus toimub teenuse kaudu", + "serviceName": "Salvestamise teenus", + "signIn": "Logi sisse", + "signOut": "Logi välja", + "unavailable": "Oih! {{serviceName}} ei ole hetkel kättesaadav! Proovi hiljem uuesti.", + "unavailableTitle": "Salvestamine ei ole võimalik." + }, + "sectionList": { + "pullToRefresh": "Tõmba uuendamiseks" + }, + "settings": { + "calendar": { + "about": "Rakenduse {{appName}} kalender kasutab turvalist ühendust ning näeb eesolevaid kõnesid.", + "disconnect": "Ühenda lahti", + "microsoftSignIn": "Logi sisse Microsoft’i kontoga", + "signedIn": "Hetkel nähakse kasutaja {{email}} kalendrit. Kalendrikutsete peitmiseks vajuta “Ühenda lahti” nupule.", + "title": "Kalender" }, - "connection": { - "ATTACHED": "Ühendatud", - "AUTHENTICATING": "Autentimine…", - "AUTHFAIL": "Autentimine ebaõnnestus", - "CONNECTED": "Ühendatud", - "CONNECTING": "Ühendamine…", - "CONNFAIL": "Ühendamine ebaõnnestus", - "DISCONNECTED": "Ühendus katkestatud", - "DISCONNECTING": "Ühenduse katkestamine…", - "ERROR": "Viga", - "FETCH_SESSION_ID": "Sessiooni-ID püüdmine…", - "GET_SESSION_ID_ERROR": "Sessiooni-ID püüdmisel tekkis viga: {{code}}", - "GOT_SESSION_ID": "Sessiooni-ID püüdmine… Tehtud", - "LOW_BANDWIDTH": "Kasutaja {{displayName}} video on ülekandekiiruse parandamiseks välja lülitatud" + "devices": "Seaded", + "followMe": "Kõik jälgivad mind", + "language": "Keel", + "loggedIn": "Logitud sisse nimega: {{name}}", + "moderator": "Moderaator", + "more": "Rohkem", + "name": "Nimi", + "noDevice": "Andmed puuduvad", + "selectAudioOutput": "Heli väljund", + "selectCamera": "Kaamera", + "selectMic": "Mikrofon", + "startAudioMuted": "Kõik alustavad väljalülitatud mikrofoniga", + "startVideoMuted": "Kõik alustavad väljalülitatud kaameraga", + "title": "Seaded" + }, + "settingsView": { + "advanced": "Täpsem", + "alertOk": "OK", + "alertTitle": "Hoiatus", + "alertURLText": "Sisestatud link ei ole õige", + "buildInfoSection": "Versioon", + "conferenceSection": "Kõne", + "disableCallIntegration": "Lülita kohaliku kõne integratsioon välja", + "disableP2P": "Lülita otseühendus välja", + "displayName": "Kasutatav nimi", + "email": "E-mail", + "header": "Seaded", + "profileSection": "Profiil", + "serverURL": "Serveri link", + "showAdvanced": "Näita täpsemaid seadistusi", + "startWithAudioMuted": "Alusta väljalülitatud heliga", + "startWithVideoMuted": "Alusta väljalülitatud videoga", + "version": "Versioon" + }, + "share": { + "dialInfoText": "\n\n=====\n\nSoovid sisse helistada oma telefonilt?\n\n{{defaultDialInNumber}}Vajuta lingile, et näha telefoninumbreid sisse helistamiseks\n{{dialInfoPageUrl}}", + "mainText": "Vajuta lingile, et kõnega ühineda:\n{{roomUrl}}" + }, + "speaker": "Kõneleja", + "speakerStats": { + "hours": "{{count}}t", + "minutes": "{{count}}m", + "name": "Nimi", + "seconds": "{{count}}s", + "speakerStats": "Kõneleja andmed", + "speakerTime": "Kõnelemise aeg" + }, + "startupoverlay": { + "policyText": " ", + "title": "{{app}} vajab ligipääsu mikrofonile ja kaamerale." + }, + "suspendedoverlay": { + "rejoinKeyTitle": "Ühine uuesti", + "text": "Vajuta <i>Ühine uuesti</i> nupule, et uuesti ühineda.", + "title": "Kõne katkestati, sest arvuti läks magama." + }, + "toolbar": { + "accessibilityLabel": { + "audioOnly": "Kasuta ainult heli", + "audioRoute": "Vali heli vahend", + "callQuality": "Halda kõne kvaliteeti", + "cc": "Kasuta subtiitreid", + "chat": "Kasuta vestluse akent", + "document": "Kasuta jagatud dokumente", + "download": "Laadi rakendus alla", + "feedback": "Jäta tagasiside", + "fullScreen": "Kasuta täisekraani", + "hangup": "Lahku kõnest", + "help": "Abi", + "invite": "Kutsu inimesi", + "kick": "Eemalda kõneleja", + "localRecording": "Näita salvestamise paneeli", + "lockRoom": "Kasuta kõne parooli", + "moreActions": "Kasuta toimingute menüüd", + "moreActionsMenu": "Toimingute menüü", + "moreOptions": "Näita rohkem valikuid", + "mute": "Lülita heli välja", + "muteEveryone": "Vaigista kõikide mikrofonid", + "pip": "Kasuta pilt-pildis vaadet", + "privateMessage": "Saada privaatsõnum", + "profile": "Muuda profiili", + "raiseHand": "Käe tõstmine", + "recording": "Salvestamine", + "remoteMute": "Lülita kasutaja mikrofon välja", + "Settings": "Seadistused", + "sharedvideo": "Kasuta Youtube’i video jagamist", + "shareRoom": "Kutsu", + "shareYourScreen": "Jaga ekraani", + "shortcuts": "Kasuta kiirvalikuid", + "show": "Näita laval", + "speakerStats": "Kõnelejate statistika", + "tileView": "Paneelvaade", + "toggleCamera": "Kasuta kaamerat", + "videomute": "Video väljalülitamine", + "videoblur": "Video hägustamine" }, - "connectionindicator": { - "address": "Aadress:", - "bandwidth": "Eeldatav ülekandekiirus:", - "bitrate": "Andmeedastuskiirus:", - "bridgeCount": "Serverite arv: ", - "connectedTo": "Ühendatud:", - "e2e_rtt": "E2E RTT:", - "framerate": "Ekraani eraldusvõime:", - "less": "Näita vähem", - "localaddress": "Lokaalne aadress:", - "localaddress_plural": "Lokaalsed aadressid:", - "localport": "Lokaalne port:", - "localport_plural": "Lokaalsed pordid:", - "more": "Näita rohkem", - "packetloss": "Andmepaketi kaotus:", - "quality": { - "good": "Hea", - "inactive": "Mitteaktiivne", - "lost": "Kaotatud", - "nonoptimal": "Mitteoptimaalne", - "poor": "Nõrk" - }, - "remoteaddress": "Kaugtöö aadress:", - "remoteaddress_plural": "Kaugtöö aadressid:", - "remoteport": "Kaugtöö port:", - "remoteport_plural": "Kaugtöö pordid:", - "resolution": "Resolutsioon:", - "status": "Ühendus:", - "transport": "Transport:", - "transport_plural": "Transpordid:" + "addPeople": "Lisa kõnesse inimesi", + "audioOnlyOff": "Lülita “ainult heli” valik välja", + "audioOnlyOn": "Lülita “ainult heli” valik sisse", + "audioRoute": "Vali heli vahend", + "authenticate": "Autendi", + "callQuality": "Halda kõne kvaliteeti", + "chat": "Ava/sulge vestlus", + "closeChat": "Sulge vestlus", + "documentClose": "Sulge jagatud dokument", + "documentOpen": "Ava jagatud dokument", + "download": "Laadi rakendus alla", + "enterFullScreen": "Vaata täisekraanil", + "enterTileView": "Vaata paneelvaates", + "exitFullScreen": "Välju täisekraani vaatest", + "exitTileView": "Välju paneelvaatest", + "feedback": "Jäta tagasiside", + "hangup": "Lahku", + "help": "Abi", + "invite": "Kutsu", + "login": "Logi sisse", + "logout": "Logi välja", + "lowerYourHand": "Langeta kätt", + "moreActions": "Rohkem tegevusi", + "moreOptions": "Rohkem valikuid", + "mute": "Mikrofon sisse/välja", + "muteEveryone": "Vaigista kõikide mikrofonid", + "noAudioSignalTitle": "Mikrofon ei püüa sisendit kinni!", + "noAudioSignalDesc": "Kui Sa ei lülitanud mikrofoni seadistustest tahtlikult välja, kaalu seadme vahetamist.", + "noAudioSignalDescSuggestion": "Kui Sa ei lülitanud mikrofoni seadistustest tahtlikult välja, kaalu seadme vahetamist.", + "noAudioSignalDialInDesc": "Võid sisse helistada valides:", + "noAudioSignalDialInLinkDesc" : "Sissehelistamise numbrid", + "noisyAudioInputTitle": "Mikrofonis on müra! Tundub, et läbi mikrofoni kostub palju helisid. Kaalu mikrofoni välja lülitamist või seadme vahetamist.", + "noisyAudioInputDesc": "Tundub, et läbi mikrofoni kostub palju helisid. Kaalu mikrofoni välja lülitamist või seadme vahetamist.", + "openChat": "Ava vestlus", + "pip": "Ava pilt-pildis vaade", + "privateMessage": "Saada privaatsõnum", + "profile": "Muuda profiili", + "raiseHand": "Tõsta/langeta kätt", + "raiseYourHand": "Tõsta kätt", + "Settings": "Seaded", + "sharedvideo": "Jaga YouTube’i videot", + "shareRoom": "Kutsu", + "shortcuts": "Vaata kiirvalikuid", + "speakerStats": "Kõneleja andmed", + "startScreenSharing": "Alust ekraani jagamist", + "startSubtitles": "Alusta subtiitrite näitamist", + "stopScreenSharing": "Lõpeta ekraani jagamine", + "stopSubtitles": "Lõpeta subtiitrite näitamine", + "stopSharedVideo": "Lõpeta YouTube’i video", + "talkWhileMutedPopup": "Soovid rääkida? Mikrofon on välja lülitatud.", + "tileViewToggle": "Näita paneelvaadet", + "toggleCamera": "Kasuta kaamerat", + "videomute": "Kaamera sisse/välja", + "startvideoblur": "Tausta hägustamine", + "stopvideoblur": "Lülita tausta hägustamine välja" + }, + "transcribing": { + "ccButtonTooltip": "Subtiitrid sisse/välja", + "error": "Transkribeerimine ebaõnnestus. Proovi uuesti.", + "expandedLabel": "Transkribeerimine on sisse lülitatud", + "failedToStart": "Transkribeerimise alustamine ebaõnnestus", + "labelToolTip": "Kõne transkribeeritakse", + "off": "Transkribeerimine peatatud", + "pending": "Transkribeerimise ettevalmistus...", + "start": "Alusta subtiitrite kuvamist", + "stop": "Lõpeta subtiitrite kuvamine", + "tr": "TR" + }, + "userMedia": { + "androidGrantPermissions": "Vali <b><i>Luba</i></b>, kui veebilehitseja küsib nõusolekut.", + "chromeGrantPermissions": "Vali <b><i>Luba</i></b>, kui veebilehitseja küsib nõusolekut.", + "edgeGrantPermissions": "Vali <b><i>Jah</i></b>, kui veebilehitseja küsib nõusolekut.", + "electronGrantPermissions": "Luba kasutada kaamerat ja mikrofoni", + "firefoxGrantPermissions": "Vali <b><i>Jaga valitud vahendit</i></b>, kui veebilehitseja küsib nõusolekut.", + "iexplorerGrantPermissions": "Vali <b><i>OK</i></b>, kui veebilehitseja küsib nõusolekut.", + "nwjsGrantPermissions": "Luba kasutada kaamerat ja mikrofoni", + "operaGrantPermissions": "Vali <b><i>Luba</i></b>, kui veebilehitseja küsib nõusolekut.", + "react-nativeGrantPermissions": "Vali <b><i>Luba</i></b>, kui veebilehitseja küsib nõusolekut.", + "safariGrantPermissions": "Vali <b><i>OK</i></b>, kui veebilehitseja küsib nõusolekut." + }, + "videoSIPGW": { + "busy": "Vabastatakse ressurssi... Proovi mõne minuti pärast uuesti.", + "busyTitle": "Ruumi teenus on hetkel hõivatud", + "errorAlreadyInvited": "{{displayName}} on juba kutsutud", + "errorInvite": "Ühendus ei ole veel saavutatud. Proovi hiljem uuesti.", + "errorInviteFailed": "Probleemi lahendatakse. Proovi hiljem uuesti.", + "errorInviteFailedTitle": "Kasutaja {{displayName}} kutsumine ebaõnnestus", + "errorInviteTitle": "Ruumi kutsumine ebaõnnestus", + "pending": "{{displayName}} on kutsutud" + }, + "videoStatus": { + "audioOnly": "AUD", + "audioOnlyExpanded": "Kasutad kõnes ainult heli. See hõivab ülekandekiirust vähem, aga video jagamine on välja lülitatud.", + "callQuality": "Kõne kvaliteet", + "hd": "HD", + "hdTooltip": "Video vaatamine kõrgkvaliteediga", + "highDefinition": "Kõrgresolutsioon", + "labelTooiltipNoVideo": "Video puudub", + "labelTooltipAudioOnly": "Valitud on “ainult heli” seadistus", + "ld": "LD", + "ldTooltip": "Video vaatamine madala kvaliteediga", + "lowDefinition": "Madal", + "onlyAudioAvailable": "Saab kasutada ainult heli", + "onlyAudioSupported": "Selles veebilehitsejas on toetatud ainult heli.", + "p2pEnabled": "Otseühendus on sisse lülitatud", + "p2pVideoQualityDescription": "Otseühenduse režiimis saab vastuvõetava kõne heli olla “ainult heli“, või kõrge. Teisi seadistusi ei saa valida.", + "recHighDefinitionOnly": "Eelistan kõrgresolutsiooni.", + "sd": "SD", + "sdTooltip": "Video vaatamine vaikekvaliteediga", + "standardDefinition": "Vaike resolutsioon" + }, + "videothumbnail": { + "domute": "Lülita mikrofon välja", + "domuteOthers": "Vaigista teiste mikrofonid", + "flip": "Pööra", + "kick": "Eemalda kõnest", + "moderator": "Moderaator", + "mute": "Kasutaja mikrofon välja lülitatud", + "muted": "Mikrofon välja lülitatud", + "remoteControl": "Kaugjuhtimine", + "show": "Näita laval", + "videomute": "Kasutaja on kaamera peatanud" + }, + "welcomepage": { + "accessibilityLabel": { + "join": "Vajuta, et ühineda", + "roomname": "Sisesta ruumi nimi" }, - "dateUtils": { - "earlier": "Varem", - "today": "Täna", - "yesterday": "Eile" + "appDescription": "Lase käia, tee videoülekanne kogu meeskonnaga! Kutsu kõik, keda soovid. Rakendus {{app}} on krüpteeritud. 100% vabavara ülekannete tegemiseks, mida saab kasutada iga päev tasuta - ilma konto loomiseta.", + "audioVideoSwitch": { + "audio": "Heli", + "video": "Video" }, - "deepLinking": { - "appNotInstalled": "Kõnega liitumiseks läbi mobiiltelefoni on vaja paigaldada {{app}} rakendus.", - "description": "Midagi ei juhtunud? Proovisime ühendust luua töölaua rakendusega. Proovi uuesti või käivita {{app}} rakendus.", - "descriptionWithoutWeb": "Midagi ei juhtunud? Televastuvõttu prooviti avada töölaua rakendusest {{app}}.", - "downloadApp": "Laadi rakendus alla", - "launchWebButton": "Käivita veebis", - "openApp": "Jätka töölaua rakendusega", - "title": "Kõne avamine rakenduses {{app}}…", - "tryAgainButton": "Proovi töölaua rakendusega uuesti " - }, - "defaultLink": "nt {{url}}", - "defaultNickname": "nt. Mari Maasikas", - "deviceError": { - "cameraError": "Ei saanud kaameraga ühendust", - "cameraPermission": "Puudub õigus kasutada kaamerat", - "microphoneError": "Ei saanud mikrofoniga ühendust", - "microphonePermission": "Puudub õigus kasutada mikrofoni" - }, - "deviceSelection": { - "noPermission": "Luba pole antud", - "previewUnavailable": "Eelvaade pole kättesaadav", - "selectADevice": "Vali seade", - "testAudio": "Mängi testimiseks heli" - }, - "dialog": { - "accessibilityLabel": { - "liveStreaming": "Otseülekanne" - }, - "allow": "Luba", - "alreadySharedVideoMsg": "Teine kasutaja jagab videot. Selles kõnes on ainult ühe video jagamine korraga lubatud.", - "alreadySharedVideoTitle": "Korraga on lubatud ainult ühe video jagamine.", - "applicationWindow": "Rakenduse aken", - "Back": "Tagasi", - "cameraConstraintFailedError": "Kaamera ei vasta teatud piirangutele.", - "cameraNotFoundError": "Kaamerat ei leitud.", - "cameraNotSendingData": "Ei saa ühendust kaameraga. Kontrolli, kas vahend on mõne teise rakenduse poolt kasutusel, vali menüüst teine vahend või värskenda rakendust.", - "cameraNotSendingDataTitle": "Kaamera pole kättesaadav.", - "cameraPermissionDeniedError": "Kaamera kasutamine on keelatud. Kõnega on võimalik ühineda ilma kaamerata. Kaamera kasutamiseks vajuta aadressiribal kaamera nupule.", - "cameraUnknownError": "Kaamerat ei saa kasutada! Põhjus teadmata.", - "cameraUnsupportedResolutionError": "Kaamera ei toeta nõutud resolutsiooni.", - "Cancel": "Tühista", - "close": "Sulge", - "conferenceDisconnectMsg": "Kontrolli võrguühendust. Taasühendamine {{seconds}}…", - "conferenceDisconnectTitle": "Ühendus on katkenud.", - "conferenceReloadMsg": "Lahenduse otsime. Taasühendus {{seconds}} sek…", - "conferenceReloadTitle": "Midagi läks valesti!", - "confirm": "Kinnita", - "confirmNo": "Ei", - "confirmYes": "Kinnita", - "connectError": "Oih, midagi läks valesti! Kõnega ühendamine ebaõnnestus.", - "connectErrorWithMsg": "Oih, midagi läks valesti! Kõnega ühendamine ebaõnnestus. Põhjus: {{msg}}.", - "connecting": "Ühendamine.", - "contactSupport": "Võta ühendust kasutustoega", - "copy": "Kopeeri", - "dismiss": "Lõpeta", - "displayNameRequired": "Nimi on kohustuslik", - "done": "Valmis", - "enterDisplayName": "Sisesta nimi", - "error": "Viga", - "externalInstallationMsg": "Töölauale on vaja paigaldada jagamise laiendus.", - "externalInstallationTitle": "Laiendus on kohustuslik", - "goToStore": "Mine veebipoodi", - "gracefulShutdown": "Rakendus on hoolduseks ajutiselt maas. Proovi hiljem uuesti!", - "IamHost": "Mina olen võõrustaja", - "incorrectRoomLockPassword": "Vale parool", - "incorrectPassword": "Vale kasutajanimi või parool", - "inlineInstallationMsg": "Töölauale tuleb paigaldada jagamise laiendus.", - "inlineInstallExtension": "Paiglada kohe", - "internalError": "Oih, midagi läks valesti! Veateate: {{error}}.", - "internalErrorTitle": "Sisemine viga", - "kickMessage": "Oih, oled kõnest eemaldatud!", - "kickParticipantButton": "Eemalda kõnest", - "kickParticipantDialog": "Oled kindel, et tahad kasutaja kõnest eemaldada?", - "kickParticipantTitle": "Eemalda kasutaja kõnest?", - "kickTitle": "Kõnest eemaldatud", - "liveStreaming": "Otseülekanne", - "liveStreamingDisabledForGuestTooltip": "Külalised ei saa otseülekannet alustada.", - "liveStreamingDisabledTooltip": "Otseülekande alustamine on keelatud.", - "lockMessage": "Ebaõnnestunud lukustada kõnet.", - "lockRoom": "Lisa kõnele parool", - "lockTitle": "Lukustamine ebaõnnestus", - "logoutQuestion": "Oled kindel, et tahad kõne peatada ja välja logida?", - "logoutTitle": "Logi välja", - "maxUsersLimitReached": "Maksimaalne kõnes osalejate arv on täis. Võta ühendust kõne omanikuga või proovi hiljem uuesti!", - "maxUsersLimitReachedTitle": "Maksimaalne kõnes osalejate arv on täis", - "micConstraintFailedError": "Mikrofon ei vasta teatud piirangutele.", - "micNotFoundError": "Mikrofoni ei leitud.", - "micNotSendingData": "Ei saa ühendust mikrofoniga. Vali menüüst teine vahend või värskenda rakendust.", - "micNotSendingDataTitle": "Mikrofon pole kättesaadav.", - "micPermissionDeniedError": "Mikrofoni kasutamine on keelatud. Kõnega on võimalik ühineda, aga teised Sind ei kuule. Mikrofoni kasutamiseks vajuta aadressiribal mikrofoni nupule.", - "micUnknownError": "Mikrofoni ei saa kasutada. Põhjus teadmata.", - "muteEveryoneElseDialog": "Peale mikrofoni vaigistamist saab ainult kasutaja ise oma mikrofoni tagasi sisse lülitada.", - "muteEveryoneElseTitle": "Vaigista kõikide teiste mikrofonid, välja arvatud {{whom}}?", - "muteEveryoneDialog": "Oled kindel, et soovid kõikide teiste mikrofonid vaigistada? Neid saab tagasi sisse lülitada ainult kasutaja ise.", - "muteEveryoneTitle": "Vaigista kõik?", - "muteEveryoneSelf": "Sina ise", - "muteEveryoneStartMuted": "Edaspidi alustavad kõik välja lülitatud mikrofonidega", - "muteParticipantBody": "Teiste kasutajate mikrofoni ei saa sisse lülitada. Kasutaja saab ise otsutada, kas mikrofon on sees või väljas.", - "muteParticipantButton": "Lülita mikrofon välja", - "muteParticipantDialog": "Oled kindel, et soovid kasutaja mikrofoni välja lülitada? Seda saab ainult kasutaja ise sisse tagasi lülitada.", - "muteParticipantTitle": "Lülita kasutaja mikrofon välja?", - "Ok": "Jah", - "passwordLabel": "Parool", - "passwordNotSupported": "Kõnele ei saa parooli määrata.", - "passwordNotSupportedTitle": "Parooli lisamine pole toetatud", - "passwordRequired": "Parool on kohustuslik", - "popupError": "Modaalaknad on veebilehitsejas keelatud. Palun luba modaalakende kasutamine veebilehitseja turvalisuse seadistuses ning proovi uuesti.", - "popupErrorTitle": "Modaalaknad on keelatud", - "recording": "Salvetamine", - "recordingDisabledForGuestTooltip": "Külalised ei saa kõne salvestada.", - "recordingDisabledTooltip": "Kõne salvestamine on keelatud.", - "rejoinNow": "Ühine uuesti", - "remoteControlAllowedMessage": "{{user}} andis kaugjuhtimiseks loa!", - "remoteControlDeniedMessage": "{{user}} keelas kaugjuhtimise!", - "remoteControlErrorMessage": "Viga kaugjuhtimiseks loa küsimisel kasutajalt {{user}}!", - "remoteControlRequestMessage": "Kas lubad kasutajal {{user}} oma töölauda kaugjuhtida?", - "remoteControlShareScreenWarning": "Kui vajutad nupule \"Luba\", siis jagad oma ekraani.", - "remoteControlStopMessage": "Kaugjuhtimise sessioon on lõppenud!", - "remoteControlTitle": "Kaugjuhtimine", - "Remove": "Eemalda", - "removePassword": "Eemalda parool", - "removeSharedVideoMsg": "Oled kindel, et soovid oma jagatud video eemaldada?", - "removeSharedVideoTitle": "Eemalda jagatud video", - "reservationError": "Broneerimise süsteemi viga", - "reservationErrorMsg": "Veakood: {{code}}, sõnum: {{msg}}", - "retry": "Proovi uuesti", - "screenSharingFailedToInstall": "Oih, ekraanijagamise laienduse paigaldamine ebaõnnestus!", - "screenSharingFailedToInstallTitle": "Ekraanijagamise laienduse paigaldamine ebaõnnestus", - "screenSharingFirefoxPermissionDeniedError": "Ekraani jagamisega läks midagi valesti! Veendu, et oled ekraani jagamiseks loa andnud.", - "screenSharingFirefoxPermissionDeniedTitle": "Oih, ekraani jagamist ei saanud alustada!", - "screenSharingPermissionDeniedError": "Oih, midagi läks valesti ekraanijagamise laienduse õigustega! Värskenda ja proovi uuesti.", - "sendPrivateMessage": "Sulle saabus privaatsõnum. Kas soovid vastata privaatselt või avalikult?", - "sendPrivateMessageCancel": "Saada sõnum avalikult", - "sendPrivateMessageOk": "Saada sõnum privaatselt", - "sendPrivateMessageTitle": "Saada privaatselt?", - "serviceUnavailable": "Teenus pole kättesaadav", - "sessTerminated": "Kõne lõpetatud", - "Share": "Jaga", - "shareVideoLinkError": "Sisesta korrektne Youtube’i link.", - "shareVideoTitle": "Jaga videot", - "shareYourScreen": "Jaga ekraani", - "shareYourScreenDisabled": "Ekraani jagamine on keelatud.", - "shareYourScreenDisabledForGuest": "Külalised ei saa ekraani jagada.", - "startLiveStreaming": "Alusta otseülekannet", - "startRecording": "Alusta salvestamist", - "startRemoteControlErrorMessage": "Kaugjuhtimise sessiooni alustamisel tekkis viga!", - "stopLiveStreaming": "Lõpeta otseülekanne", - "stopRecording": "Lõpeta salvestamine", - "stopRecordingWarning": "Oled kindel, et soovid salvestamist lõpetada?", - "stopStreamingWarning": "Oled kindel, et soovid otseülekannet lõpetada?", - "streamKey": "Otseülekande võti", - "Submit": "Esita", - "thankYou": "Aitäh, et kasutasid rakendust {{appName}}!", - "token": "token", - "tokenAuthFailed": "Kahjuks ei ole kõnega ühinemine lubatud.", - "tokenAuthFailedTitle": "Autentimine ebaõnnestus", - "transcribing": "Transkribeerimine", - "unlockRoom": "Eemalda kõne parool", - "userPassword": "kasutaja parool", - "WaitForHostMsg": "Kõne <b>{{room}}</b> ei ole veel alanud. Autendi ennast, kui oled võõrustaja. Külalisena oota, kuni võõrustaja saabub.", - "WaitForHostMsgWOk": "Kõne <b>{{room}}</b> ei ole veel alanud. Kui oled võõrustaja, vajuta OK, et ennast autentida. Külalisena oota, kuni võõrustaja saabub.", - "WaitingForHost": "Võõrustaja ootamine…", - "Yes": "Jah", - "yourEntireScreen": "Täisekraan" - }, - "dialOut": { - "statusMessage": "on staatusega {{status}}" - }, - "documentSharing": { - "title": "Jagatud dokument" - }, - "feedback": { - "average": "Keskmine", - "bad": "Halb", - "detailsLabel": "Kirjelda täpsemalt.", - "good": "Hea", - "rateExperience": "Hinda kõne kvaliteeti", - "veryBad": "Väga halb", - "veryGood": "Väga hea" - }, - "incomingCall": { - "answer": "Vasta", - "audioCallTitle": "Sissetulev kõne", - "decline": "Lõpeta", - "productLabel": "Jitsi", - "videoCallTitle": "Sissetulev videokõne" - }, - "info": { - "accessibilityLabel": "Näita infot", - "addPassword": "Lisa parool", - "cancelPassword": "Tühista parool", - "conferenceURL": "Link:", - "country": "Riik", - "dialANumber": "Kõnega ühinemiseks vali number ja sisesta pin-kood.", - "dialInConferenceID": "PIN:", - "dialInNotSupported": "Oih, sissehelistamine ei ole toetatud!", - "dialInNumber": "Sissehelistamine:", - "dialInSummaryError": "Sissehelistamise info pole kättesaadav. Proovi hiljem uuesti!", - "dialInTollFree": "Maksuvaba", - "genericError": "Oih, midagi läks valesti!", - "inviteLiveStream": "Otseülekande nägemiseks vajuta lingile: {{url}}", - "invitePhone": "Üks klikk heliga sissehelistamiseks: {{number}},,{{conferenceID}}#\n", - "invitePhoneAlternatives": "Otsid teist sissehelistamise numbrit?\nVaata sissehelistamise numbreid: {{url}}\n\n\nKui helistad läbi ruumi, ühine kõnega väljalülitatud mikrofoni režiimis: {{silentUrl}}", - "inviteURLFirstPartGeneral": "Oled kõnesse kutsutud.", - "inviteURLFirstPartPersonal": "{{name}} kutsub Sind kõnesse.\n", - "inviteURLSecondPart": "\nÜhine kõnega:\n{{url}}\n", - "liveStreamURL": "Otseülekanne:", - "moreNumbers": "Rohkem numbreid", - "noNumbers": "Sissehelistamise numbrid puuduvad.", - "noPassword": "Andmed puuduvad", - "noRoom": "Sissehelistamise ruum pole täpsustatud.", - "numbers": "Sissehelistamise numbrid", - "password": "Parool:", - "title": "Jaga", - "tooltip": "Jaga linki ja helista, et kõnega ühineda", - "label": "Kõne info" - }, - "inviteDialog": { - "alertText": "Osade kasutajate kutsumine ebaõnnestus.", - "header": "Kutsu", - "searchCallOnlyPlaceholder": "Sisesta telefoninumber", - "searchPeopleOnlyPlaceholder": "Otsi kasutajaid", - "searchPlaceholder": "Kasutaja telefoninumber", - "send": "Saada" - }, - "inlineDialogFailure": { - "msg": "Midagi läks valesti.", - "retry": "Proovi uuesti", - "support": "Kasutajatugi", - "supportMsg": "Kui see juhtub uuesti, võta ühendust" - }, - "keyboardShortcuts": { - "focusLocal": "Keskendu videole", - "focusRemote": "Keskendu teise kasutaja videole", - "fullScreen": "Ava/sulge täisekraani vaade", - "keyboardShortcuts": "Klaviatuuri kiirvalikud", - "localRecording": "Näita/peida salvestamise võimalused", - "mute": "Lülita mikrofon sisse/välja", - "pushToTalk": "Vajuta, et rääkida", - "raiseHand": "Tõsta/langeta kätt", - "showSpeakerStats": "Näita kõnelejate statistikat", - "toggleChat": "Ava/sulge vestluse aken", - "toggleFilmstrip": "Näita/peida video eelvaade", - "toggleScreensharing": "Vaheta kaamera ja ekraanijagamise vahel", - "toggleShortcuts": "Näita/peida klaviatuuri kiirvalikud", - "videoMute": "Lülita kaamera sisse/välja", - "videoQuality": "Halda kõne kvaliteeti" - }, - "liveStreaming": { - "busy": "Toimub ülekande ressursi vabastamine. Proovi mõne minuti pärast uuesti.", - "busyTitle": "Kõik ülekandjad on hetkel hõivatud", - "changeSignIn": "Vaheta kontot.", - "choose": "Vali otseülekanne", - "chooseCTA": "Vali ülekande viis. Oled sisse logitud e-mailiga {{email}}.", - "enterStreamKey": "Sisesta siia oma YouTube’i ülekande võti.", - "error": "Otseülekanne ebaõnnestus. Proovi uuesti.", - "errorAPI": "YouTube’i kanaliga ühendumisel tekkis viga. Palun logi uuesti sisse.", - "errorLiveStreamNotEnabled": "Otseülekanne ei ole e-mailiga {{email}} sisse lülitatud. Luba kasutajaga otseülekanded või vaheta kontot.", - "expandedOff": "Otseülekanne on peatatud", - "expandedOn": "Kõnest tehakse otseülekanne YouTube’i.", - "expandedPending": "Otseülekanne algab…", - "failedToStart": "Otseülekandega alustamine ebaõnnestus.", - "getStreamKeyManually": "Ülekandjaid ei leitud. Leia YouTube’st otseülekande võti.", - "invalidStreamKey": "Otseülekande võti võib olla vale.", - "off": "Otseülekanne on peatatud", - "offBy": "{{name}} lõpetas otseülekande", - "on": "Otseülekanne", - "onBy": "{{name}} alustas otseülekandega", - "pending": "Otseülekande alustamine…", - "serviceName": "Otseülekande teenus", - "signedInAs": "Oled sisse logitud kasutajana:", - "signIn": "Google’ga sisselogimine", - "signInCTA": "Logi sisse või sisesta otseülekande võti YouTube’st.", - "signOut": "Logi välja", - "start": "Alusta otseülekannet.", - "streamIdHelp": "Mis see on?", - "unavailableTitle": "Otseülekanne pole kättesaadav." - }, - "localRecording": { - "clientState": { - "off": "Väljas", - "on": "Sees", - "unknown": "Teadmata" - }, - "dialogTitle": "Kohalikud salvestamise nupud", - "duration": "Kestvus", - "durationNA": "N/A", - "encoding": "Kodeerimine", - "label": "LOR", - "labelToolTip": "Kohalik salvestamine on alustatud", - "localRecording": "Kohalik salvestamine", - "me": "Mina", - "messages": { - "engaged": "Local recording engaged.", - "finished": "Salvestamise sessioon {{token}} on lõppenud. Palun saada salvestatud fail moderaatorile.", - "finishedModerator": "Salvestamise sessioon {{token}} on lõppenud ja salvestatud. Küsi teistelt kontaktidelt nende koopiaid.", - "notModerator": "Sa ei ole moderaator. Sa ei saa alustada ega lõpetada kohalikku salvestamist." - }, - "moderator": "Moderaator", - "no": "Ei", - "participant": "Osaleja", - "participantStats": "Osaleja andmed", - "sessionToken": "Sessiooni token", - "start": "Alusta salvestamist", - "stop": "Lõpeta salvestamine", - "yes": "Jah" - }, - "lockRoomPassword": "parool", - "lockRoomPasswordUppercase": "Parool", - "me": "mina", - "notify": { - "connectedOneMember": "{{name}} ühines kõnega", - "connectedThreePlusMembers": "{{name}} ja {{count}} teist kasutajat ühines kõnega", - "connectedTwoMembers": "{{first}} ja {{second}} ühinesid kõnega", - "disconnected": "lahti ühendatud", - "focus": "Konverentsi fookus", - "focusFail": "{{component}} pole kättesaadav - proovi uuesti {{ms}} sekundi pärast.", - "grantedTo": "Moderaatori õigused on antud kasutajale {{to}}!", - "invitedOneMember": "{{name}} on kutsutud", - "invitedThreePlusMembers": "{{name}} ja {{count}} teist kasutajat on kutsutud", - "invitedTwoMembers": "{{first}} ja {{second}} on kutsutud", - "kickParticipant": "{{kicked}} eemaldati kõnest kasutaja {{kicker}} poolt", - "me": "Mina", - "moderator": "Moderaatori õigused jagatud!", - "muted": "Alustasid kõnet väljalülitatud mikrofoniga.", - "mutedTitle": "Mikrofon on välja lülitatud!", - "mutedRemotelyTitle": "Sinu mikrofon lülitati välja kasutaja {{participantDisplayName}} poolt!", - "mutedRemotelyDescription": "Saad alati oma mikrofoni sisse lülitada, kui soovid rääkida. Lülita mikrofon peale rääkimist uuesti välja liigse müra ja kaja vältimiseks.", - "passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) eemaldatud teise kasutaja poolt", - "passwordSetRemotely": "$t(lockRoomPasswordUppercase) lisatud teise kasutaja poolt", - "raisedHand": "{{name}} soovib rääkida.", - "somebody": "Keegi", - "startSilentTitle": "Ühinesid ilma mikrofonita!", - "startSilentDescription": "Mikrofoni kasutamiseks ühine kõnega uuesti", - "suboptimalExperienceDescription": "Rakenduse {{appName}} parima kvaliteedi tagamiseks palun kasuta <a href='static/recommendedBrowsers.html' target='_blank'>ühte nendest veebilehitsejatest</a>.", - "suboptimalExperienceTitle": "Veebilehitseja hoiatus", - "unmute": "Lülita mikrofon sisse", - "newDeviceCameraTitle": "Leitud uus kaamera", - "newDeviceAudioTitle": "Leitud uus heliseadeldis", - "newDeviceAction": "Kasuta" - }, - "passwordSetRemotely": "määratud teise kasutaja poolt", - "passwordDigitsOnly": "Kuni {{number}} tähemärki", - "poweredby": "teieni toodud", - "presenceStatus": { - "busy": "Hõivatud", - "calling": "Helistamine…", - "connected": "Ühendatud", - "connecting": "Ühendamine…", - "connecting2": "Ühendamine*...", - "disconnected": "Lahti ühendatud", - "expired": "Aegunud", - "ignored": "Eiratud", - "initializingCall": "Kõne alustamine…", - "invited": "Kutsutud", - "rejected": "Tagasi lükatud", - "ringing": "Kutsumine…" - }, - "profile": { - "setDisplayNameLabel": "Sisesta nimi", - "setEmailInput": "Sisesta e-mail", - "setEmailLabel": "Sisesta Gravatar e-kirja aadress", - "title": "Profiil" - }, - "raisedHand": "Soovin rääkida", - "recording": { - "authDropboxText": "Lisa Dropbox’i", - "availableSpace": "Vaba ruum: {{spaceLeft}} MB (ca {{duration}} minutit salvestamist)", - "beta": "BETA", - "busy": "Salvestamise ressursi vabastamine… Proovi mõne minuti pärast uuesti.", - "busyTitle": "Kõik salvestajad on praegu kinni", - "error": "Salvestamine ebaõnnestus. Proovi uuesti.", - "expandedOff": "Salvestamine peatatud", - "expandedOn": "Kõne salvestatakse.", - "expandedPending": "Salvestamine on alustatud…", - "failedToStart": "Salvestamine ebaõnnestus", - "fileSharingdescription": "Jaga salvestust kõnelejatega", - "live": "Otse", - "loggedIn": "Sisseloginud kasutajana {{userName}}", - "off": "Salvestamine on lõpetatud", - "offBy": "{{name}} lõpetas salvestamise", - "on": "Salvestatakse", - "onBy": "{{name}} alustas salvestamist", - "pending": "Kõne salvestamise ettevalmistus…", - "rec": "REC", - "serviceDescription": "Salvestus toimub teenuse kaudu", - "serviceName": "Salvestamise teenus", - "signIn": "Logi sisse", - "signOut": "Logi välja", - "unavailable": "Oih! {{serviceName}} ei ole hetkel kättesaadav! Proovi hiljem uuesti.", - "unavailableTitle": "Salvestamine ei ole võimalik." - }, - "sectionList": { - "pullToRefresh": "Tõmba uuendamiseks" - }, - "settings": { - "calendar": { - "about": "Rakenduse {{appName}} kalender kasutab turvalist ühendust ning näeb eesolevaid kõnesid.", - "disconnect": "Ühenda lahti", - "microsoftSignIn": "Logi sisse Microsoft’i kontoga", - "signedIn": "Hetkel nähakse kasutaja {{email}} kalendrit. Kalendrikutsete peitmiseks vajuta “Ühenda lahti” nupule.", - "title": "Kalender" - }, - "devices": "Seaded", - "followMe": "Kõik jälgivad mind", - "language": "Keel", - "loggedIn": "Logitud sisse nimega: {{name}}", - "moderator": "Moderaator", - "more": "Rohkem", - "name": "Nimi", - "noDevice": "Andmed puuduvad", - "selectAudioOutput": "Heli väljund", - "selectCamera": "Kaamera", - "selectMic": "Mikrofon", - "startAudioMuted": "Kõik alustavad väljalülitatud mikrofoniga", - "startVideoMuted": "Kõik alustavad väljalülitatud kaameraga", - "title": "Seaded" - }, - "settingsView": { - "advanced": "Täpsem", - "alertOk": "OK", - "alertTitle": "Hoiatus", - "alertURLText": "Sisestatud link ei ole õige", - "buildInfoSection": "Versioon", - "conferenceSection": "Kõne", - "disableCallIntegration": "Lülita kohaliku kõne integratsioon välja", - "disableP2P": "Lülita otseühendus välja", - "displayName": "Kasutatav nimi", - "email": "E-mail", - "header": "Seaded", - "profileSection": "Profiil", - "serverURL": "Serveri link", - "showAdvanced": "Näita täpsemaid seadistusi", - "startWithAudioMuted": "Alusta väljalülitatud heliga", - "startWithVideoMuted": "Alusta väljalülitatud videoga", - "version": "Versioon" - }, - "share": { - "dialInfoText": "\n\n=====\n\nSoovid sisse helistada oma telefonilt?\n\n{{defaultDialInNumber}}Vajuta lingile, et näha telefoninumbreid sisse helistamiseks\n{{dialInfoPageUrl}}", - "mainText": "Vajuta lingile, et kõnega ühineda:\n{{roomUrl}}" - }, - "speaker": "Kõneleja", - "speakerStats": { - "hours": "{{count}}t", - "minutes": "{{count}}m", - "name": "Nimi", - "seconds": "{{count}}s", - "speakerStats": "Kõneleja andmed", - "speakerTime": "Kõnelemise aeg" - }, - "startupoverlay": { - "policyText": " ", - "title": "{{app}} vajab ligipääsu mikrofonile ja kaamerale." - }, - "suspendedoverlay": { - "rejoinKeyTitle": "Ühine uuesti", - "text": "Vajuta <i>Ühine uuesti</i> nupule, et uuesti ühineda.", - "title": "Kõne katkestati, sest arvuti läks magama." - }, - "toolbar": { - "accessibilityLabel": { - "audioOnly": "Kasuta ainult heli", - "audioRoute": "Vali heli vahend", - "callQuality": "Halda kõne kvaliteeti", - "cc": "Kasuta subtiitreid", - "chat": "Kasuta vestluse akent", - "document": "Kasuta jagatud dokumente", - "download": "Laadi rakendus alla", - "feedback": "Jäta tagasiside", - "fullScreen": "Kasuta täisekraani", - "hangup": "Lahku kõnest", - "help": "Abi", - "invite": "Kutsu inimesi", - "kick": "Eemalda kõneleja", - "localRecording": "Näita salvestamise paneeli", - "lockRoom": "Kasuta kõne parooli", - "moreActions": "Kasuta toimingute menüüd", - "moreActionsMenu": "Toimingute menüü", - "moreOptions": "Näita rohkem valikuid", - "mute": "Lülita heli välja", - "muteEveryone": "Vaigista kõikide mikrofonid", - "pip": "Kasuta pilt-pildis vaadet", - "privateMessage": "Saada privaatsõnum", - "profile": "Muuda profiili", - "raiseHand": "Käe tõstmine", - "recording": "Salvestamine", - "remoteMute": "Lülita kasutaja mikrofon välja", - "Settings": "Seadistused", - "sharedvideo": "Kasuta YouTube’i video jagamist", - "shareRoom": "Kutsu", - "shareYourScreen": "Jaga ekraani", - "shortcuts": "Kasuta kiirvalikuid", - "show": "Näita laval", - "speakerStats": "Kõnelejate statistika", - "tileView": "Paneelvaade", - "toggleCamera": "Kasuta kaamerat", - "videomute": "Video väljalülitamine", - "videoblur": "Video hägustamine" - }, - "addPeople": "Lisa kõnesse inimesi", - "audioOnlyOff": "Lülita “ainult heli” valik välja", - "audioOnlyOn": "Lülita “ainult heli” valik sisse", - "audioRoute": "Vali heli vahend", - "authenticate": "Autendi", - "callQuality": "Halda kõne kvaliteeti", - "chat": "Ava/sulge vestlus", - "closeChat": "Sulge vestlus", - "documentClose": "Sulge jagatud dokument", - "documentOpen": "Ava jagatud dokument", - "download": "Laadi rakendus alla", - "enterFullScreen": "Vaata täisekraanil", - "enterTileView": "Vaata paneelvaates", - "exitFullScreen": "Välju täisekraani vaatest", - "exitTileView": "Välju paneelvaatest", - "feedback": "Jäta tagasiside", - "hangup": "Lahku", - "help": "Abi", - "invite": "Kutsu", - "login": "Logi sisse", - "logout": "Logi välja", - "lowerYourHand": "Langeta kätt", - "moreActions": "Rohkem tegevusi", - "moreOptions": "Rohkem valikuid", - "mute": "Mikrofon sisse/välja", - "muteEveryone": "Vaigista kõikide mikrofonid", - "noAudioSignalTitle": "Mikrofon ei püüa sisendit kinni!", - "noAudioSignalDesc": "Kui Sa ei lülitanud mikrofoni seadistustest tahtlikult välja, kaalu seadme vahetamist.", - "noAudioSignalDescSuggestion": "Kui Sa ei lülitanud mikrofoni seadistustest tahtlikult välja, kaalu seadme vahetamist.", - "noAudioSignalDialInDesc": "Võid sisse helistada valides:", - "noAudioSignalDialInLinkDesc": "Sissehelistamise numbrid", - "noisyAudioInputTitle": "Mikrofonis on müra! Tundub, et läbi mikrofoni kostub palju helisid. Kaalu mikrofoni välja lülitamist või seadme vahetamist.", - "noisyAudioInputDesc": "Tundub, et läbi mikrofoni kostub palju helisid. Kaalu mikrofoni välja lülitamist või seadme vahetamist.", - "openChat": "Ava vestlus", - "pip": "Ava pilt-pildis vaade", - "privateMessage": "Saada privaatsõnum", - "profile": "Muuda profiili", - "raiseHand": "Tõsta/langeta kätt", - "raiseYourHand": "Tõsta kätt", - "Settings": "Seaded", - "sharedvideo": "Jaga YouTube’i videot", - "shareRoom": "Kutsu", - "shortcuts": "Vaata kiirvalikuid", - "speakerStats": "Kõneleja andmed", - "startScreenSharing": "Alust ekraani jagamist", - "startSubtitles": "Alusta subtiitrite näitamist", - "stopScreenSharing": "Lõpeta ekraani jagamine", - "stopSubtitles": "Lõpeta subtiitrite näitamine", - "stopSharedVideo": "Lõpeta YouTube’i video", - "talkWhileMutedPopup": "Soovid rääkida? Mikrofon on välja lülitatud.", - "tileViewToggle": "Näita paneelvaadet", - "toggleCamera": "Kasuta kaamerat", - "videomute": "Kaamera sisse/välja", - "startvideoblur": "Tausta hägustamine", - "stopvideoblur": "Lülita tausta hägustamine välja" - }, - "transcribing": { - "ccButtonTooltip": "Subtiitrid sisse/välja", - "error": "Transkribeerimine ebaõnnestus. Proovi uuesti.", - "expandedLabel": "Transkribeerimine on sisse lülitatud", - "failedToStart": "Transkribeerimise alustamine ebaõnnestus", - "labelToolTip": "Kõne transkribeeritakse", - "off": "Transkribeerimine peatatud", - "pending": "Transkribeerimise ettevalmistus…", - "start": "Alusta subtiitrite kuvamist", - "stop": "Lõpeta subtiitrite kuvamine", - "tr": "TR" - }, - "userMedia": { - "androidGrantPermissions": "Vali <b><i>Luba</i></b>, kui veebilehitseja küsib nõusolekut.", - "chromeGrantPermissions": "Vali <b><i>Luba</i></b>, kui veebilehitseja küsib nõusolekut.", - "edgeGrantPermissions": "Vali <b><i>Jah</i></b>, kui veebilehitseja küsib nõusolekut.", - "electronGrantPermissions": "Luba kasutada kaamerat ja mikrofoni", - "firefoxGrantPermissions": "Vali <b><i>Jaga valitud vahendit</i></b>, kui veebilehitseja küsib nõusolekut.", - "iexplorerGrantPermissions": "Vali <b><i>OK</i></b>, kui veebilehitseja küsib nõusolekut.", - "nwjsGrantPermissions": "Luba kasutada kaamerat ja mikrofoni", - "operaGrantPermissions": "Vali <b><i>Luba</i></b>, kui veebilehitseja küsib nõusolekut.", - "react-nativeGrantPermissions": "Vali <b><i>Luba</i></b>, kui veebilehitseja küsib nõusolekut.", - "safariGrantPermissions": "Vali <b><i>OK</i></b>, kui veebilehitseja küsib nõusolekut." - }, - "videoSIPGW": { - "busy": "Vabastatakse ressurssi… Proovi mõne minuti pärast uuesti.", - "busyTitle": "Ruumi teenus on hetkel hõivatud", - "errorAlreadyInvited": "{{displayName}} on juba kutsutud", - "errorInvite": "Ühendus ei ole veel saavutatud. Proovi hiljem uuesti.", - "errorInviteFailed": "Probleemi lahendatakse. Proovi hiljem uuesti.", - "errorInviteFailedTitle": "Kasutaja {{displayName}} kutsumine ebaõnnestus", - "errorInviteTitle": "Ruumi kutsumine ebaõnnestus", - "pending": "{{displayName}} on kutsutud" - }, - "videoStatus": { - "audioOnly": "AUD", - "audioOnlyExpanded": "Kasutad kõnes ainult heli. See hõivab ülekandekiirust vähem, aga video jagamine on välja lülitatud.", - "callQuality": "Kõne kvaliteet", - "hd": "HD", - "hdTooltip": "Video vaatamine kõrgkvaliteediga", - "highDefinition": "Kõrgresolutsioon", - "labelTooiltipNoVideo": "Video puudub", - "labelTooltipAudioOnly": "Valitud on “ainult heli” seadistus", - "ld": "LD", - "ldTooltip": "Video vaatamine madala kvaliteediga", - "lowDefinition": "Madal", - "onlyAudioAvailable": "Saab kasutada ainult heli", - "onlyAudioSupported": "Selles veebilehitsejas on toetatud ainult heli.", - "p2pEnabled": "Otseühendus on sisse lülitatud", - "p2pVideoQualityDescription": "Otseühenduse režiimis saab vastuvõetava kõne heli olla “ainult heli“, või kõrge. Teisi seadistusi ei saa valida.", - "recHighDefinitionOnly": "Eelistan kõrgresolutsiooni.", - "sd": "SD", - "sdTooltip": "Video vaatamine vaikekvaliteediga", - "standardDefinition": "Vaike resolutsioon" - }, - "videothumbnail": { - "domute": "Lülita mikrofon välja", - "domuteOthers": "Vaigista teiste mikrofonid", - "flip": "Pööra", - "kick": "Eemalda kõnest", - "moderator": "Moderaator", - "mute": "Kasutaja mikrofon välja lülitatud", - "muted": "Mikrofon välja lülitatud", - "remoteControl": "Kaugjuhtimine", - "show": "Näita laval", - "videomute": "Kasutaja on kaamera peatanud" - }, - "welcomepage": { - "accessibilityLabel": { - "join": "Vajuta, et ühineda", - "roomname": "Sisesta ruumi nimi" - }, - "appDescription": "Lase käia, tee videoülekanne kogu meeskonnaga! Kutsu kõik, keda soovid. Rakendus {{app}} on krüpteeritud. 100% vabavara ülekannete tegemiseks, mida saab kasutada iga päev tasuta - ilma konto loomiseta.", - "audioVideoSwitch": { - "audio": "Heli", - "video": "Video" - }, - "calendar": "Kalender", - "connectCalendarButton": "Ühenda kalender", - "connectCalendarText": "Ühenda oma kalender, et kõiki kohtumisi näha rakenduses {{app}}. Lisa {{provider}} kohtumised kalendrisse ja alusta kõnesid ühe klikiga.", - "enterRoomTitle": "Alusta uut kõnet", - "roomNameAllowedChars": "Televastuvõtu nimi ei tohi sisaldada sümboleid: ?, &, :, ', \", %, #.", - "go": "Mine", - "goSmall": "Mine", - "join": "Ühine", - "info": "Info", - "privacy": "Privaatsus", - "recentList": "Hiljutised", - "recentListDelete": "Kustuta", - "recentListEmpty": "Hiljutiste valikute nimekiri on tühi. Vestle kasutajatega ja leia oma hiljutised kõned siit.", - "reducedUIText": "Tere tulemast rakendusse {{app}}!", - "roomname": "Sisesta ruumi nimi", - "roomnameHint": "Sisesta ruumi nimi või link, millega soovid ühinega. Võid nime välja mõelda, aga anna osalejatele sellest teada, et nad saaksid ruumiga ühineda.", - "sendFeedback": "Saada tagasiside", - "terms": "Tingimused", - "title": "Turvaline, võimalusi täis ja tasuta keskkond videokõnede jaoks." - }, - "lonelyMeetingExperience": { - "button": "Kutsu teisi", - "youAreAlone": "Asud hetkel ruumis üksi" - } + "calendar": "Kalender", + "connectCalendarButton": "Ühenda kalender", + "connectCalendarText": "Ühenda oma kalender, et kõiki kohtumisi näha rakenduses {{app}}. Lisa {{provider}} kohtumised kalendrisse ja alusta kõnesid ühe klikiga.", + "enterRoomTitle": "Alusta uut kõnet", + "roomNameAllowedChars": "Televastuvõtu nimi ei tohi sisaldada sümboleid: ?, &, :, ', \", %, #.", + "go": "Mine", + "goSmall": "Mine", + "join": "Ühine", + "info": "Info", + "privacy": "Privaatsus", + "recentList": "Hiljutised", + "recentListDelete": "Kustuta", + "recentListEmpty": "Hiljutiste valikute nimekiri on tühi. Vestle kasutajatega ja leia oma hiljutised kõned siit.", + "reducedUIText": "Tere tulemast rakendusse {{app}}!", + "roomname": "Sisesta ruumi nimi", + "roomnameHint": "Sisesta ruumi nimi või link, millega soovid ühinega. Võid nime välja mõelda, aga anna osalejatele sellest teada, et nad saaksid ruumiga ühineda.", + "sendFeedback": "Saada tagasiside", + "terms": "Tingimused", + "title": "Turvaline, võimalusi täis ja tasuta keskkond videokõnede jaoks." + }, + "lonelyMeetingExperience": { + "button": "Kutsu teisi", + "youAreAlone": "Asud hetkel ruumis üksi" + } } diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-fi.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-fi.json index 8d2922ab7..7ee0aed68 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-fi.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-fi.json @@ -54,7 +54,7 @@ "title": "Chatti" }, "connectingOverlay": { - "joiningRoom": "Yhdistetään kokoukseen…" + "joiningRoom": "Yhdistetään kokoukseen..." }, "connection": { "ATTACHED": "Liitteenä", @@ -111,7 +111,7 @@ "downloadApp": "Lataa sovellus", "launchWebButton": "Käynnistä verkossa", "openApp": "Jatka sovellukseen", - "title": "Käynnistetään kokousta sovelluksessa {{app}}…", + "title": "Käynnistetään kokousta sovelluksessa {{app}}...", "tryAgainButton": "Yritä uudelleen työpöytäsovelluksella" }, "defaultLink": "esim. {{url}}", @@ -145,9 +145,9 @@ "cameraUnsupportedResolutionError": "Kamerasi ei tue vaadittua videoresoluutiota.", "Cancel": "Peruuta", "close": "Sulje", - "conferenceDisconnectMsg": "Tarkista verkkoyhteys. Yhdistetään uudelleen {{seconds}} sekunnin kuluttua…", + "conferenceDisconnectMsg": "Tarkista verkkoyhteys. Yhdistetään uudelleen {{seconds}} sekunnin kuluttua...", "conferenceDisconnectTitle": "Yhteys on katkennut.", - "conferenceReloadMsg": "Yritämme korjata tilannetta. Yhdistetään uudelleen {{seconds}} sekunnin kuluttua…", + "conferenceReloadMsg": "Yritämme korjata tilannetta. Yhdistetään uudelleen {{seconds}} sekunnin kuluttua...", "conferenceReloadTitle": "Valitettavasti jokin meni vikaan.", "confirm": "Vahvista", "confirmNo": "Ei", @@ -254,7 +254,7 @@ "userPassword": "käyttäjän salasana", "WaitForHostMsg": "Kokous <b>{{room}}</b> ei ole vielä alkanut. Jos olet vetäjä, todenna henkilöllisyytesi. Muussa tapauksessa odota vetäjän saapumista.", "WaitForHostMsgWOk": "Kokous <b>{{room}}</b> ei ole vielä alkanut. Jos olet vetäjä, todenna henkilöllisyytesi OK-painikkeella. Muussa tapauksessa odota vetäjän saapumista.", - "WaitingForHost": "Odotetaan vetäjää…", + "WaitingForHost": "Odotetaan vetäjää...", "Yes": "Kyllä", "yourEntireScreen": "Koko näyttö" }, @@ -349,13 +349,13 @@ "errorLiveStreamNotEnabled": "Suoratoisto ei ole käytössä tilillä {{email}}. Ota suoratoisto käyttöön tai kirjaudu tiliin, jossa se on käytössä.", "expandedOff": "Suoratoisto on päättynyt", "expandedOn": "Kokous näkyy parhaillaan YouTubessa suoratoistolähetyksenä.", - "expandedPending": "Suoratoistolähetys on alkamassa…", + "expandedPending": "Suoratoistolähetys on alkamassa...", "failedToStart": "Suoratoiston aloitus ei onnistunut", "getStreamKeyManually": "Suoratoistolähetysten nouto epäonnistui. Hanki suoratoistokoodi YouTubesta.", "invalidStreamKey": "Suoratoistokoodi voi olla virheellinen.", "off": "Suoratoisto päättyi", "on": "Suoratoisto", - "pending": "Suoratoisto alkamassa…", + "pending": "Suoratoisto alkamassa...", "serviceName": "Suoratoistopalvelu", "signedInAs": "Sisäänkirjautunut käyttäjä:", "signIn": "Kirjaudu Googlella", @@ -433,17 +433,17 @@ "poweredby": "tukija:", "presenceStatus": { "busy": "Varattu", - "calling": "Soitetaan…", + "calling": "Soitetaan...", "connected": "Yhdistetty", - "connecting": "Yhdistetään…", + "connecting": "Yhdistetään...", "connecting2": "Yhdistetään*...", "disconnected": "Ei yhteyttä", "expired": "Vanhentunut", "ignored": "Sivuutettu", - "initializingCall": "Käynnistetään puhelua…", + "initializingCall": "Käynnistetään puhelua...", "invited": "Kutsuttu", "rejected": "Hylätty", - "ringing": "Soi…" + "ringing": "Soi..." }, "profile": { "setDisplayNameLabel": "Määritä näyttönimi", @@ -460,14 +460,14 @@ "error": "Nauhoitus epäonnistui. Yritä uudelleen.", "expandedOff": "Nauhoitus päättyi", "expandedOn": "Tätä kokousta nauhoitetaan.", - "expandedPending": "Nauhoitus on alkamassa…", + "expandedPending": "Nauhoitus on alkamassa...", "failedToStart": "Nauhoituksen aloitus epäonnistui", "fileSharingdescription": "Jaa nauhoitus kokouksen osanottajille", "live": "SUORA LÄHETYS", "loggedIn": "Kirjautunut käyttäjänä {{userName}}", "off": "Nauhoitus päättyi", "on": "Nauhoitetaan", - "pending": "Kokouksen nauhoitusta valmistellaan…", + "pending": "Kokouksen nauhoitusta valmistellaan...", "rec": "REC", "serviceDescription": "Nauhoituspalvelu tallentaa nauhoituksen", "serviceName": "Nauhoituspalvelu", @@ -625,7 +625,7 @@ "failedToStart": "Puhtaaksikirjoituksen aloitus epäonnistui", "labelToolTip": "Kokousta kirjoitetaan puhtaaksi", "off": "Puhtaaksikirjoitus päättyi", - "pending": "Kokouksen puhtaaksikirjoitusta valmistellaan…", + "pending": "Kokouksen puhtaaksikirjoitusta valmistellaan...", "start": "Aloita tekstitys", "stop": "Lopeta tekstitys", "tr": "TR" @@ -709,4 +709,4 @@ "terms": "Ehdot", "title": "Turvallinen, täysin varustettu ja maksuton videoneuvottelu" } -} +} \ No newline at end of file diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-fr.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-fr.json index 38b36d691..6057fc14a 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-fr.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-fr.json @@ -5,7 +5,7 @@ "countryReminder": "Appel hors des États-Unis ? Veuillez commencer avec le code du pays !", "disabled": "Vous ne pouvez pas inviter quelqu'un.", "failedToAdd": "Erreur lors de l'ajout des participants", - "footerText": "Appels sortants désactivés.", + "footerText": "Appels sortants désactivés", "loading": "Rechercher des personnes et des numéros de téléphone", "loadingNumber": "Validation du numéro de téléphone", "loadingPeople": "Recherche de personnes à inviter", @@ -14,7 +14,7 @@ "searchNumbers": "Ajouter des numéros de téléphone", "searchPeople": "Rechercher une personne", "searchPeopleAndNumbers": "Rechercher des personnes ou ajouter leurs numéros de téléphone", - "telephone": "Téléphone : {{number}}", + "telephone": "Téléphone: {{number}}", "title": "Inviter une personne à cette réunion" }, "audioDevices": { @@ -31,7 +31,7 @@ "addMeetingURL": "Ajouter un lien de conférence", "confirmAddLink": "Voulez-vous ajouter un lien Jitsi à cet événement ?", "error": { - "appConfiguration": "L'intégration du calendrier n'est pas correctement configurée.", + "appConfiguration": "l'intégration du calendrier n'est pas correctement configurée", "generic": "Une erreur s'est produite. Veuillez vérifier les paramètres de votre calendrier ou tenter de l'actualiser.", "notSignedIn": "Une erreur s'est produite lors de l'authentification permettant d'afficher les événements du calendrier. Veuillez vérifier les paramètres de votre calendrier et essayer de vous reconnecter." }, @@ -60,12 +60,12 @@ "you": "vous" }, "chromeExtensionBanner": { - "installExtensionText": "Installer l'extension pour l'intégration de Google Calendar et Office 365", - "buttonText": "Installer l'extension Chrome", - "dontShowAgain": "Ne plus me montrer ceci" + "installExtensionText": "", + "buttonText": "", + "dontShowAgain": "" }, "connectingOverlay": { - "joiningRoom": "Connexion à la réunion…" + "joiningRoom": "Connexion à la réunion..." }, "connection": { "ATTACHED": "Attachée", @@ -77,19 +77,15 @@ "DISCONNECTED": "Déconnecté", "DISCONNECTING": "Déconnexion en cours", "ERROR": "Erreur", - "RECONNECTING": "Un problème réseau est survenue. Reconnexion en cours...", - "FETCH_SESSION_ID": "Obtention d’un identifiant de session…", - "GET_SESSION_ID_ERROR": "Obtenir une erreur d’identifiant de session : {{code}}", - "GOT_SESSION_ID": "Obtention d’un identifiant de session… Terminée", - "LOW_BANDWIDTH": "La vidéo de {{displayName}} a été désactivée pour économiser de la ba de passante" + "RECONNECTING": "Un problème réseau est survenue. Reconnexion en cours..." }, "connectionindicator": { "address": "Adresse :", "bandwidth": "Bande passante estimée :", "bitrate": "Débit :", - "bridgeCount": "Nombre de serveurs : ", + "bridgeCount": "Nombre de serveurs :", "connectedTo": "Connecté à :", - "framerate": "Images par seconde :", + "framerate": "Images par seconde", "less": "Cacher le détail", "localaddress": "Adresse locale :", "localaddress_plural": "Adresses locales :", @@ -111,8 +107,7 @@ "resolution": "Résolution :", "status": "Connexion :", "transport": "Transport :", - "transport_plural": "Transports :", - "e2e_rtt": "E2E RTT :" + "transport_plural": "Transports :" }, "dateUtils": { "earlier": "Plus tôt", @@ -133,7 +128,7 @@ "defaultNickname": "ex. Jean Dupont", "deviceError": { "cameraError": "Impossible d'accéder à votre caméra", - "cameraPermission": "Erreur lors de l'obtention de la permission de la caméra", + "cameraPermission": "Erreur lors de l'obtention de la permission de la caméra ", "microphoneError": "Impossible d'accéder à votre microphone", "microphonePermission": "Erreur lors de l'obtention de la permission du microphone" }, @@ -153,8 +148,8 @@ "applicationWindow": "Fenêtre d'application", "Back": "Retour", "cameraConstraintFailedError": "Votre caméra ne satisfait pas certaines des contraintes nécessaires.", - "cameraNotFoundError": "La caméra n'a pas été trouvée.", - "cameraNotSendingData": "Nous sommes incapables d'accéder à votre caméra. Veuillez sélectionner un autre périphérique dans les paramètres ou rafraîchir la page.", + "cameraNotFoundError": "La caméra n'a pas été trouvée", + "cameraNotSendingData": "Nous sommes incapables d'accéder à votre caméra. Veuillez sélectionner un autre périphérique dans les paramètres ou rafraîchir la page", "cameraNotSendingDataTitle": "Impossible d'accéder à votre caméra", "cameraPermissionDeniedError": "Vous n'avez pas autorisé l'utilisation de votre caméra. Vous pouvez toujours participer à la conférence, mais les autres ne vont pas vous voir. Utilisez le bouton de la caméra dans la barre d'adresse pour résoudre ce problème.", "cameraUnknownError": "Vous ne pouvez pas utiliser la caméra pour une raison inconnue.", @@ -168,8 +163,8 @@ "confirm": "Confirmer", "confirmNo": "Non", "confirmYes": "Oui", - "connectError": "Oups ! Un problème est survenu et la connexion à la conférence est impossible.", - "connectErrorWithMsg": "Oups ! Un problème est survenu et la connexion à la conférence est impossible : {{msg}}", + "connectError": "Oups! Un problème est survenu et la connexion à la conférence est impossible.", + "connectErrorWithMsg": "Oups! Un problème est survenu et la connexion à la conférence est impossible: {{msg}}", "connecting": "Connexion en cours", "contactSupport": "Contacter le support", "copy": "Copier", @@ -179,7 +174,7 @@ "enterDisplayName": "Merci de saisir votre nom ici", "error": "Erreur", "externalInstallationMsg": "Vous devez installer notre extension de partage de bureau.", - "externalInstallationTitle": "Extension requise", + "externalInstallationTitle": "Extension requise : ", "goToStore": "Aller sur le webstore", "gracefulShutdown": "Le service est actuellement en maintenance. Réessayez plus tard.", "IamHost": "Je suis l’hôte", @@ -187,7 +182,7 @@ "incorrectPassword": "Nom d'utilisateur ou mot de passe incorrect", "inlineInstallationMsg": "Vous devez installer notre extension de partage de bureau.", "inlineInstallExtension": "Installer maintenant", - "internalError": "Oups ! Quelque chose s'est mal passée. L'erreur suivante s'est produite : {{error}}", + "internalError": "Oups! Quelque chose s'est mal passée. L'erreur suivante s'est produite: {{error}}", "internalErrorTitle": "Erreur interne", "kickMessage": "Vous pouvez contacter {{participantDisplayName}} pour plus de détails.", "kickParticipantButton": "Expulser", @@ -221,7 +216,7 @@ "muteParticipantDialog": "Êtes-vous sûr(e) de vouloir couper le micro de ce participant ? Seul le participant pourra ensuite réactiver son micro à tout moment.", "muteParticipantTitle": "Couper le micro de ce participant ?", "Ok": "Ok", - "passwordLabel": "La réunion a été verrouillée par un·e participant·e. Veuillez entrer le $t(lockRoomPassword) pour la rejoindre.", + "passwordLabel": "$t(lockRoomPasswordUppercase)", "passwordNotSupported": "La définition d'un $t(lockRoomPassword) de réunion n'est pas prise en charge.", "passwordNotSupportedTitle": "L'ajout d'un $t(lockRoomPassword) n'est pas supporté", "passwordRequired": "$t(lockRoomPasswordUppercase) requis", @@ -247,8 +242,8 @@ "retry": "Réessayer", "screenSharingFailedToInstall": "Oups! Votre extension de partage d'écran n'a pas pu être installée.", "screenSharingFailedToInstallTitle": "L'extension de partage d'écran n'a pas pu être installée", - "screenSharingFirefoxPermissionDeniedError": "Quelque chose s'est mal passé pendant que nous essayions de partager votre écran. S'il vous plaît assurez-vous que vous nous avez donné la permission de le faire. ", - "screenSharingFirefoxPermissionDeniedTitle": "Oups! Nous ne pouvions pas démarrer le partage d'écran !", + "screenSharingFirefoxPermissionDeniedError": "Quelque chose s'est mal passé pendant que nous essayions de partager votre écran. S'il vous plaît assurez-vous que vous nous avez donné la permission de le faire.", + "screenSharingFirefoxPermissionDeniedTitle": "Oups! Nous ne pouvions pas démarrer le partage d'écran!", "screenSharingPermissionDeniedError": "Oups! Une erreur s'est produite avec vos autorisations d'extension de partage d'écran. Veuillez rafraîchir et réessayer.", "sendPrivateMessage": "Vous avez récemment reçu un message privé. Aviez-vous l'intention d'y répondre en privé, ou vouliez-vous envoyer votre message au groupe ?", "sendPrivateMessageCancel": "Envoyer au groupe", @@ -282,8 +277,7 @@ "WaitForHostMsgWOk": "La conférence <b>{{room}}</b> n'a pas encore commencé. Si vous en êtes l'hôte, veuillez appuyer sur Ok pour vous authentifier. Sinon, veuillez attendre son arrivée.", "WaitingForHost": "En attente de l'hôte ...", "Yes": "Oui", - "yourEntireScreen": "Votre écran entier", - "screenSharingAudio": "Partager l’audio" + "yourEntireScreen": "Votre écran entier" }, "dialOut": { "statusMessage": "est maintenant {{status}}" @@ -296,7 +290,7 @@ "bad": "Mauvais", "detailsLabel": "Dites nous en plus à ce sujet.", "good": "Bien", - "rateExperience": "Veuillez évaluer votre expérience", + "rateExperience": "Veuillez évaluer votre expérience.", "veryBad": "Très mauvais", "veryGood": "Très bon" }, @@ -325,10 +319,10 @@ "invitePhoneAlternatives": "Vous cherchez un numéro d'appel différent ?\nAfficher les numéros d'appel de la réunion: {{url}}\n\n\nSi vous appelez également via un téléphone de salle, vous pouvez vous connecter sans audio: {{silentUrl}}", "inviteURLFirstPartGeneral": "Vous êtes invité(e) à participer à une réunion.", "inviteURLFirstPartPersonal": "{{name}} vous invite à une réunion.\n", - "inviteURLSecondPart": "\nRejoindre la réunion :\n{{url}}\n", + "inviteURLSecondPart": "\nRejoindre la réunion:\n{{url}}\n", "liveStreamURL": "Diffusion en direct :", - "moreNumbers": "Plus de numéros", - "noNumbers": "Aucun numéro à composer.", + "moreNumbers": "Plus de numéros ", + "noNumbers": "Numéros à composer non trouvés", "noPassword": "Aucun", "noRoom": "Aucune réunion n'a été spécifiée pour l'appel entrant.", "numbers": "Numéros d'appel", @@ -374,10 +368,10 @@ "changeSignIn": "Changer de compte.", "choose": "Choisir un flux live", "chooseCTA": "Choisissez une option de diffusion. Vous êtes actuellement connecté comme {{email}}.", - "enterStreamKey": "Entrez votre clé de flux direct YouTube ici.", + "enterStreamKey": "Entrez votre clé de flux live Youtube ici", "error": "Le Streaming a échoué. Veuillez réessayer.", "errorAPI": "Une erreur s'est produite lors de l'accès à vos diffusions YouTube. Veuillez réessayer de vous connecter.", - "errorLiveStreamNotEnabled": "La diffusion en direct n'est pas activée pour {{email}}. Merci de l'activer ou de vous connecter avec un compte où elle est déjà activée.", + "errorLiveStreamNotEnabled": "La diffusion en direct n'est pas activée pour {{email}}. Merci de l'activer ou de vous connecter avec un compte où elle est déjà activée.", "expandedOff": "La diffusion en direct a été arrêtée", "expandedOn": "La conférence est en cours de diffusion sur YouTube.", "expandedPending": "La diffusion en direct a commencé...", @@ -395,10 +389,8 @@ "signInCTA": "Connectez vous ou entrez votre clé de flux live provenant de Youtube.", "signOut": "Se déconnecter", "start": "Démarrer la diffusion en direct", - "streamIdHelp": "Qu'est-ce que c'est ?", - "unavailableTitle": "Le Streaming est indisponible", - "youtubeTerms": "Conditions d’utilisation des services YouTube", - "googlePrivacyPolicy": "Politique de confidentialité de Google" + "streamIdHelp": "Qu'est-ce que c'est ?", + "unavailableTitle": "Le Streaming est indisponible" }, "localRecording": { "clientState": { @@ -420,9 +412,9 @@ "finishedModerator": "L'enregistrement de la session {{token}} s'est terminé. La piste a bien été sauvegardée. Merci de demander aux autres participants de soumettre leurs enregistrements.", "notModerator": "Vous n'êtes pas le modérateur. Vous ne pouvez pas démarrer ou arrêter un enregistrement local." }, - "moderator": "Modérateur", + "moderator": "Moderateur", "no": "Non", - "participant": "Participant·e", + "participant": "Participant", "participantStats": "Statistiques du participant", "sessionToken": "Token de la session", "start": "Démarrer l'enregistrement", @@ -433,28 +425,28 @@ "lockRoomPasswordUppercase": "Mot de passe", "me": "moi", "notify": { - "connectedOneMember": "{{name}} a rejoint la réunion", - "connectedThreePlusMembers": "{{name}} et {{count}} autres personnes ont rejoint la réunion", - "connectedTwoMembers": "{{first}} et {{second}} ont rejoint la réunion", + "connectedOneMember": "{{name}} a rejoint la réunion.", + "connectedThreePlusMembers": "{{name}} et {{count}} autres personnes ont rejoint la réunion.", + "connectedTwoMembers": "{{first}} et {{second}} ont rejoint la réunion.", "disconnected": "déconnecté", "focus": "Focus de conférence", "focusFail": "{{component}} n'est pas disponible - réessayez dans {{ms}} sec", "grantedTo": "Droits modérateur accordés à {{to}} !", - "invitedOneMember": "{{name}} a été invité·e", + "invitedOneMember": "{{displayName}} a été invité(e)", "invitedThreePlusMembers": "{{name}} et {{count}} autres ont été invités", "invitedTwoMembers": "{{first}} et {{second}} ont été invités", "kickParticipant": "{{kicked}} a été expulsé par {{kicker}}", "me": "Moi", "moderator": "Droits modérateur accordés !", "muted": "Vous avez commencé la conversation en muet.", - "mutedTitle": "Vous êtes en muet !", - "mutedRemotelyTitle": "Votre micro a été coupé par {{participantDisplayName}} !", + "mutedTitle": "Vôtre micro est coupé !", + "mutedRemotelyTitle": "Votre micro a été coupé par {{participantDisplayName}}!", "mutedRemotelyDescription": "Vous pouvez toujours activer votre micro pour prendre la parole. Désactivez votre micro quand vous terminez pour éviter les bruits parasites.", "passwordRemovedRemotely": "Le $t(lockRoomPassword) a été supprimé par un autre participant", "passwordSetRemotely": "Un $t(lockRoomPassword) a été défini par un autre participant", "raisedHand": "{{name}} aimerait prendre la parole.", "somebody": "Quelqu'un", - "startSilentTitle": "Vous avez rejoint sans sortie audio !", + "startSilentTitle": "Vous avez rejoint sans sortie audio!", "startSilentDescription": "Rejoignez la réunion de nouveau pour activer l'audio", "suboptimalBrowserWarning": "Nous craignons que votre expérience de réunion en ligne ne soit bonne ici. Nous cherchons des moyens d’améliorer cela, mais d’ici-là, essayez d’utiliser l’un des <a href='static/recommendedBrowsers.html' target='_blank'>navigateurs supportés</a>.", "suboptimalExperienceTitle": "Avertissement du navigateur", @@ -465,7 +457,7 @@ }, "passwordSetRemotely": "défini par un autre participant", "passwordDigitsOnly": "Jusqu'à {{number}} chiffres", - "poweredby": "produit par", + "poweredby": "Produit par", "presenceStatus": { "busy": "Occupé", "calling": "Appel...", @@ -489,7 +481,7 @@ "raisedHand": "Aimerait prendre la parole", "recording": { "authDropboxText": "Téléchargement vers Dropbox", - "availableSpace": "Espace disponible : {{spaceLeft}} Mo (approximativement {{duration}} minutes d'enregistrement)", + "availableSpace": "Espace disponible: {{spaceLeft}} Mo (approximativement {{duration}} minutes d'enregistrement)", "beta": "BETA", "busy": "Nous sommes en train de libérer les ressources d'enregistrement. Réessayez dans quelques minutes.", "busyTitle": "Tous les enregistreurs sont actuellement occupés", @@ -507,11 +499,11 @@ "onBy": "{{name}} a démarré l'enregistrement", "pending": "Préparation de l'enregistrement de la réunion...", "rec": "REC", - "serviceDescription": "Votre enregistrement sera enregistré par le service dédié", + "serviceDescription": "Votre enregistrement sera enregistré par le service dédié.", "serviceName": "Service d'enregistrement", "signIn": "Se connecter", "signOut": "Se déconnecter", - "unavailable": "Oups ! Le {{serviceName}} est actuellement indisponible. Nous travaillons sur la résolution du problème. Veuillez réessayer plus tard.", + "unavailable": "Oups! Le {{serviceName}} est actuellement indisponible. Nous travaillons sur la résolution du problème. Veuillez réessayer plus tard.", "unavailableTitle": "Enregistrement indisponible" }, "sectionList": { @@ -529,7 +521,7 @@ "followMe": "Tout le monde me suit", "language": "Langue", "loggedIn": "Connecté en tant que {{name}}", - "moderator": "Modérateur", + "moderator": "Moderateur", "more": "Plus", "name": "Nom", "noDevice": "Aucun", @@ -538,9 +530,7 @@ "selectMic": "Microphone", "startAudioMuted": "Tout le monde commence en muet", "startVideoMuted": "Tout le monde commence sans vidéo", - "title": "Paramètres", - "microphones": "Microphones", - "speakers": "Intervenants" + "title": "Paramètres" }, "settingsView": { "advanced": "Avancé", @@ -576,7 +566,7 @@ }, "startupoverlay": { "policyText": " ", - "title": "{{app}} a besoin d'accéder à votre microphone et votre caméra." + "title": " {{app}} a besoin d'accéder à votre microphone et votre caméra." }, "suspendedoverlay": { "rejoinKeyTitle": "Rejoindre", @@ -610,7 +600,7 @@ "recording": "Activer/désactiver l'enregistrement", "remoteMute": "Désactiver le micro du participant", "Settings": "Afficher/masquer le menu des paramètres", - "sharedvideo": "Démarrer/arrêter le partage de vidéo YouTube", + "sharedvideo": "Démarrer/arrêter le partage de vidéo Youtube", "shareRoom": "Inviter quelqu'un", "shareYourScreen": "Activer/désactiver le partage d’écran", "shortcuts": "Afficher/masquer les raccourcis", @@ -619,10 +609,7 @@ "tileView": "Activer/désactiver la vue mosaïque", "toggleCamera": "Changer de caméra", "videomute": "Activer/désactiver la vidéo", - "videoblur": "Activer/désactiver le flou de la vidéo", - "muteEveryone": "Mettre tout le monde en sourdine", - "moreOptions": "Afficher plus d'options", - "toggleFilmstrip": "Basculer la bande de film" + "videoblur": "Activer/désactiver le flou de la vidéo" }, "addPeople": "Ajouter des personnes à votre appel", "audioOnlyOff": "Désactiver le mode bande passante réduite", @@ -648,13 +635,13 @@ "lowerYourHand": "Baisser la main", "moreActions": "Plus d'actions", "moreOptions": "Plus d'options", - "mute": "Activer / Désactiver le micro", + "mute": "Muet / Actif", "muteEveryone": "Couper le micro de tout le monde", "noAudioSignalTitle": "Il n'y a pas d'entrée provenant de votre micro !", "noAudioSignalDesc": "Si vous n'avez pas délibérément coupé le son des paramètres du système ou du matériel, envisagez de changer le périphérique.", - "noAudioSignalDescSuggestion": "Si vous n'avez pas délibérément coupé le son des paramètres du système ou du matériel, pensez à utiliser le périphérique suivant.", - "noisyAudioInputTitle": "Votre microphone semble être bruyant !", - "noisyAudioInputDesc": "Il semble que votre microphone fasse du bruit, pensez à le mettre en sourdine ou à changer d'appareil.", + "noAudioSignalDescSuggestion": "Si vous n'avez pas délibérément coupé le son des paramètres du système ou du matériel, pensez à utiliser le périphérique suivant :", + "noisyAudioInputTitle": "", + "noisyAudioInputDesc": "", "openChat": "Ouvrir le chat", "pip": "Entrer en mode Picture-in-Picture", "privateMessage": "Envoyer un message privé", @@ -676,10 +663,7 @@ "toggleCamera": "Changer de caméra", "videomute": "Démarrer / Arrêter la caméra", "startvideoblur": "Flouter mon arrière plan", - "stopvideoblur": "Désactiver le flou d'arrière-plan", - "muteEveryone": "Mettre tout le monde en sourdine", - "noAudioSignalDialInDesc": "Vous pouvez également composer un numéro en utilisant :", - "noAudioSignalDialInLinkDesc": "Numéros d'appel" + "stopvideoblur": "Désactiver le flou d'arrière-plan" }, "transcribing": { "ccButtonTooltip": "Activer/Désactiver les sous-titres", @@ -731,7 +715,7 @@ "onlyAudioSupported": "Nous ne supportons que l'audio sur ce navigateur.", "p2pEnabled": "Peer to Peer activé", "p2pVideoQualityDescription": "En mode peer to peer, la qualité vidéo reçue ne peut être basculée qu'entre haute et audio uniquement. Les autres paramètres ne seront pas pris en compte jusqu'à ce que vous quittiez le mode peer to peer.", - "recHighDefinitionOnly": "Va préférer la haute définition.", + "recHighDefinitionOnly": "Va préférer la haute définition", "sd": "MD", "sdTooltip": "Regardez la vidéo en définition standard", "standardDefinition": "Moyenne Définition" @@ -741,10 +725,10 @@ "domuteOthers": "Couper le micro de tous les autres", "flip": "Balancer", "kick": "Exclure", - "moderator": "Modérateur", + "moderator": "Moderateur", "mute": "Un participant a coupé son micro", "muted": "Muet", - "remoteControl": "Démarrer / Arrêter le contrôle à distance", + "remoteControl": "", "show": "Afficher en premier plan", "videomute": "Le participant a arrêté la caméra" }, @@ -771,13 +755,12 @@ "recentList": "Récent", "recentListDelete": "Supprimer", "recentListEmpty": "Votre liste récente est actuellement vide. Discuter avec votre équipe et vous trouverez toutes vos réunions récentes ici.", - "reducedUIText": "Bienvenue sur {{app}} !", + "reducedUIText": "Bienvenue sur {{app}}!", "roomname": "Saisissez un nom de salle", "roomnameHint": "Entrez le nom ou l'URL de la salle que vous souhaitez rejoindre. Vous pouvez faire un nom, laissez les gens que vous rencontrerez le savoir afin qu'ils entrent le même nom.", "sendFeedback": "Envoyer votre avis", "terms": "Termes", - "title": "Vidéoconférence Sécurisée, entièrement en vedette et gratuite", - "getHelp": "Obtenir de l'aide" + "title": "Vidéoconférence Sécurisée, entièrement en vedette et gratuite" }, "lonelyMeetingExperience": { "button": "Inviter d'autres personnes", diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-frCA.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-frCA.json index 6b9562afb..f79a94004 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-frCA.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-frCA.json @@ -60,7 +60,7 @@ "you": "vous" }, "connectingOverlay": { - "joiningRoom": "Connexion à la réunion en cours…" + "joiningRoom": "Connexion à la réunion en cours..." }, "connection": { "ATTACHED": "Joint", @@ -116,7 +116,7 @@ "downloadApp": "Télécharger l'application", "launchWebButton": "Démarrer dans l'application Web", "openApp": "Continuer vers l'application", - "title": "Démarrage de votre réunion dans {{app}} en cours…", + "title": "Démarrage de votre réunion dans {{app}} en cours...", "tryAgainButton": "Veuillez réessayer sur votre ordinateur" }, "defaultLink": "p. ex. {{url}}", @@ -151,9 +151,9 @@ "cameraUnsupportedResolutionError": "Votre caméra ne prend pas en charge la résolution vidéo nécessaire.", "Cancel": "Annuler", "close": "Fermer", - "conferenceDisconnectMsg": "Vous devriez vérifier votre connexion au réseau. Reconnexion dans {{seconds}} sec…", + "conferenceDisconnectMsg": "Vous devriez vérifier votre connexion au réseau. Reconnexion dans {{seconds}} sec...", "conferenceDisconnectTitle": "Vous avez été déconnecté.", - "conferenceReloadMsg": "Nous tentons de résoudre le problème. Reconnexion dans {{seconds}} sec…", + "conferenceReloadMsg": "Nous tentons de résoudre le problème. Reconnexion dans {{seconds}} sec...", "conferenceReloadTitle": "Malheureusement, une erreur s'est produite.", "confirm": "Confirmer", "confirmNo": "Non", @@ -264,7 +264,7 @@ "userPassword": "mot de passe d'utilisateur", "WaitForHostMsg": "La conférence <b>{{room}}</b> n'a pas encore démarré. Si vous êtes l'hôte, veuillez vous authentifier. Sinon, veuillez attendre que l'hôte arrive.", "WaitForHostMsgWOk": "La conférence <b>{{room}}</b> n'a pas encore démarré. Si vous êtes l'hôte, veuillez appuyer sur OK pour vous authentifier. Sinon, veuillez attendre que l'hôte arrive.", - "WaitingForHost": "En attente de l'hôte…", + "WaitingForHost": "En attente de l'hôte...", "Yes": "Oui", "yourEntireScreen": "Votre écran entier" }, @@ -326,7 +326,7 @@ "searchCallOnlyPlaceholder": "Entrer le numéro de téléphone", "searchPeopleOnlyPlaceholder": "Rechercher des participants", "searchPlaceholder": "Participant ou numéro de téléphone", - "send": "Envoyer…" + "send": "Envoyer..." }, "inlineDialogFailure": { "msg": "Nous avons rencontré un obstacle.", @@ -363,15 +363,15 @@ "errorLiveStreamNotEnabled": "La diffusion en direct n'est pas activée pour {{email}}. Veuillez activer la diffusion en direct ou vous connecter à un compte pour lequel la diffusion en direct est activée.", "expandedOff": "La diffusion en direct a été arrêtée", "expandedOn": "La réunion est actuellement diffusée sur YouTube.", - "expandedPending": "Le démarrage de la diffusion en direct est en cours…", + "expandedPending": "Le démarrage de la diffusion en direct est en cours...", "failedToStart": "Le démarrage de la diffusion en direct a échoué", "getStreamKeyManually": "La récupération de diffusions en direct a échoué. Essayez d'obtenir une clé de diffusion en direct sur YouTube.", "invalidStreamKey": "La clé de diffusion en direct peut être erronée.", "off": "La diffusion en direct s'est arrêtée", "offBy": "{{name}} a arrêté la diffusion en continu", "on": "Diffusion en direct", - "onBy": "{{name}} démarré la diffusion en continu", - "pending": "Démarrage de la diffusion en direct…", + "onBy": "{{name}} démarré la diffusion en continu", + "pending": "Démarrage de la diffusion en direct...", "serviceName": "Service de diffusion en direct", "signedInAs": "Vous êtes actuellement connecté en tant que :", "signIn": "Se connecter avec Google", @@ -449,14 +449,14 @@ "poweredby": "optimisé par", "presenceStatus": { "busy": "Occupé", - "calling": "Appel en cours…", + "calling": "Appel en cours...", "connected": "Connecté", - "connecting": "Connexion en cours…", + "connecting": "Connexion en cours...", "connecting2": "Connexion en cours*...", "disconnected": "Déconnecté", "expired": "Expiré", "ignored": "Ignoré", - "initializingCall": "Initialisation de l'appel…", + "initializingCall": "Initialisation de l'appel...", "invited": "Invité", "rejected": "Refusé", "ringing": "Sonnerie" @@ -464,7 +464,7 @@ "profile": { "setDisplayNameLabel": "Définir votre nom d'affichage", "setEmailInput": "Entrer votre adresse courriel", - "setEmailLabel": "Définir votre courriel Gravatar", + "setEmailLabel": "Définir votre courriel gravatar", "title": "Profil" }, "raisedHand": "Aimerait prendre la parole", @@ -477,7 +477,7 @@ "error": "L'enregistrement a échoué. Veuillez réessayer.", "expandedOff": "L'enregistrement a été arrêté.", "expandedOn": "La réunion est actuellement enregistrée.", - "expandedPending": "Démarrage de l'enregistrement en cours…", + "expandedPending": "Démarrage de l'enregistrement en cours...", "failedToStart": "Échec du démarrage de l'enregistrement", "fileSharingdescription": "Partager l'enregistrement avec les participants de la réunion", "live": "EN DIRECT", @@ -486,7 +486,7 @@ "offBy": "{{name}} a arrêté l'enregistrement", "on": "Enregistrement", "onBy": "{{name}} a démarré l'enregistrement", - "pending": "Enregistrement de la réunion en préparation…", + "pending": "Enregistrement de la réunion en préparation...", "rec": "REC", "serviceDescription": "Votre enregistrement sera sauvegardé par le service d'enregistrement", "serviceName": "Service d'enregistrement", @@ -657,7 +657,7 @@ "failedToStart": "Échec du démarrage de la transcription", "labelToolTip": "La réunion est transcrite", "off": "La transcription est arrêtée", - "pending": "Préparation de la transcription de la réunion en cours…", + "pending": "Préparation de la transcription de la réunion en cours...", "start": "Activer l'affichage des sous-titres", "stop": "Désactiver l'affichage des sous-titres", "tr": "PI" @@ -746,4 +746,4 @@ "terms": "Termes", "title": "Conférence vidéo sécurisée, pleinement fonctionnelle et entièrement gratuite" } -} +} \ No newline at end of file diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-hr.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-hr.json index 572acfae2..ab5774168 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-hr.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-hr.json @@ -116,7 +116,7 @@ "downloadApp": "Preuzmite aplikaciju", "launchWebButton": "Pokreni na webu", "openApp": "Nastavite do aplikacije", - "title": "Pokretanje sastanka u {{app}}…", + "title": "Pokretanje sastanka u {{app}}...", "tryAgainButton": "Pokušajte ponovo na radnoj površini" }, "defaultLink": "npr. {{url}}", @@ -150,9 +150,9 @@ "cameraUnsupportedResolutionError": "Fotoaparat ne podržava potrebnu razlučivost videozapisa.", "Cancel": "Odustani", "close": "Zatvori", - "conferenceDisconnectMsg": "Provjerite vašu mrežnu vezu. Ponovno spajanje za {{seconds}} sekundi…", + "conferenceDisconnectMsg": "Provjerite vašu mrežnu vezu. Ponovno spajanje za {{seconds}} sekundi...", "conferenceDisconnectTitle": "Odspojeni ste.", - "conferenceReloadMsg": "Pokušavamo popraviti. Ponovno spajanje za {{seconds}} sekundi…", + "conferenceReloadMsg": "Pokušavamo popraviti. Ponovno spajanje za {{seconds}} sekundi...", "conferenceReloadTitle": "Nažalost, nešto je pošlo po zlu.", "confirm": "Potvrdi", "confirmNo": "Ne", @@ -354,13 +354,13 @@ "errorLiveStreamNotEnabled": "Emitiranje uživo nije omogućeno na {{email}}. Omogućite prijenos uživo ili se prijavite na račun s omogućenim prijenosom uživo.", "expandedOff": "Emitiranje uživo je zaustavljeno", "expandedOn": "Ovaj sastanak se emitira uživo na YouTube.", - "expandedPending": "Emitiranje uživo se pokreće…", + "expandedPending": "Emitiranje uživo se pokreće...", "failedToStart": "Pokretanje emitiranja uživo nije uspjelo", "getStreamKeyManually": "Nismo mogli dohvatiti niti jedan prijenos uživo. Pokušajte dobiti ključ uživo iz usluge YouTube.", "invalidStreamKey": "Ključ za emitiranje uživo možda je pogrešan.", "off": "Emitiranje uživo je zaustavljeno", "on": "Emitiranje uživo", - "pending": "Pokretanje emitiranja uživo…", + "pending": "Pokretanje emitiranja uživo...", "serviceName": "Usluga emitiranja uživo", "signedInAs": "", "signIn": "", @@ -465,7 +465,7 @@ "error": "Emitiranje uživo nije uspjelo. Pokušajte ponovno.", "expandedOff": "", "expandedOn": "", - "expandedPending": "Snimanje se pokreće…", + "expandedPending": "Snimanje se pokreće...", "failedToStart": "", "fileSharingdescription": "", "live": "", @@ -714,4 +714,4 @@ "terms": "Uvjeti", "title": "Sigurna, potpuno opremljena i potpuno besplatna videokonferencija" } -} +} \ No newline at end of file diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-hu.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-hu.json index 90dbb4e5d..fa2026a92 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-hu.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-hu.json @@ -60,7 +60,7 @@ "you": "neked" }, "connectingOverlay": { - "joiningRoom": "Kapcsolódás az értekezlethez…" + "joiningRoom": "Kapcsolódás az értekezlethez..." }, "connection": { "ATTACHED": "Kapcsolódva", @@ -72,11 +72,7 @@ "DISCONNECTED": "Szétkapcsolva", "DISCONNECTING": "Szétkapcsolódás", "ERROR": "Hiba", - "RECONNECTING": "Hálózati hiba történt. Újracsatlakozás...", - "LOW_BANDWIDTH": "{{displayName}} videója le lett kapcsolva a sávszélesség csökkentése érdekében", - "GOT_SESSION_ID": "Munkamenet-azonosító beszerzése… Kész", - "GET_SESSION_ID_ERROR": "Hiba a munkamenet-azonosítása beszerzése közben: {{code}}", - "FETCH_SESSION_ID": "Munkamenet-azonosító beszerzése…" + "RECONNECTING": "Hálózati hiba történt. Újracsatlakozás..." }, "connectionindicator": { "address": "Cím:", @@ -106,8 +102,7 @@ "resolution": "Felbontás:", "status": "Kapcsolat:", "transport": "Átvitel:", - "transport_plural": "Átvitelek:", - "e2e_rtt": "E2E RTT:" + "transport_plural": "Átvitel:" }, "dateUtils": { "earlier": "Korábban", @@ -121,7 +116,7 @@ "downloadApp": "Applikáció letöltése", "launchWebButton": "Indítás weben", "openApp": "Továbblépés az applikációhoz", - "title": "Értekezlet indítása a {{app}} applikációban…", + "title": "Értekezlet indítása a {{app}} applikációban...", "tryAgainButton": "Újbóli próbálkozás az asztali változatban" }, "defaultLink": "pl.: {{url}}", @@ -143,7 +138,7 @@ "liveStreaming": "Élő közvetítés" }, "allow": "Engedélyez", - "alreadySharedVideoMsg": "Egy másik résztvevő is videót oszt meg. E konferencia számára csak egy videomegosztás engedélyezett.", + "alreadySharedVideoMsg": "Egy másik résztvevő is videot oszt meg. E konferencia számára csak egy videomegosztás engedélyezett.", "alreadySharedVideoTitle": "Egyszerre csak egy videomegosztás engedélyezése", "applicationWindow": "Alkalmazásablak", "Back": "Vissza", @@ -156,9 +151,9 @@ "cameraUnsupportedResolutionError": "A kamera nem támogatja a szükséges videofelbontást.", "Cancel": "Mégsem", "close": "Bezárás", - "conferenceDisconnectMsg": "Ellenőrizni kellene a hálózati kapcsolatokat. Újracsatlakozás {{seconds}} másodperc múlva…", + "conferenceDisconnectMsg": "Ellenőrizni kellene a hálózati kapcsolatokat. Újracsatlakozás {{seconds}} másodperc múlva...", "conferenceDisconnectTitle": "Lecsatlakozott.", - "conferenceReloadMsg": "Próbálkozás a hiba javítására. Újracsatlakozás {{seconds}} másodperc múlva…", + "conferenceReloadMsg": "Próbálkozás a hiba javítására. Újracsatlakozás {{seconds}} másodperc múlva...", "conferenceReloadTitle": "Sajnos valami félresikerült.", "confirm": "Megerősítés", "confirmNo": "Nem", @@ -207,10 +202,10 @@ "micUnknownError": "Ismeretlen ok miatt nem lehet a mikrofont használni.", "muteParticipantBody": "Nem fogja tudni visszahangosítani, de ő önmagát bármikor vissza tudja majd hangosítani.", "muteParticipantButton": "Némítás", - "muteParticipantDialog": "Valóban elnémítható ez a résztvevő? Nem fogja tudni visszahangosítani, de ő önmagát bármikor vissza tudja majd hangosítani.", - "muteParticipantTitle": "Elnémítható a résztvevő?", + "muteParticipantDialog": "Valóban lenémítható ez a résztvevő? Nem fogja tudni visszahangosítani, de ő önmagát bármikor vissza tudja majd hangosítani.", + "muteParticipantTitle": "Lenémítható a résztvevő?", "Ok": "Ok", - "passwordLabel": "Az értekezletet zárolta egy résztvevő. Csatlakozáshoz adja meg a $t(lockRoomPassword).", + "passwordLabel": "$t(lockRoomPasswordUppercase)", "passwordNotSupported": "Az értekezlet $t(lockRoomPassword) beállítása nem támogatott.", "passwordNotSupportedTitle": "$t(lockRoomPasswordUppercase) nem támogatott", "passwordRequired": "$t(lockRoomPasswordUppercase) szükséges", @@ -229,8 +224,8 @@ "remoteControlTitle": "Távoli asztal vezérlése", "Remove": "Eltávolítás", "removePassword": "$t(lockRoomPassword) eltávolítása", - "removeSharedVideoMsg": "Valóban eltávolítható a megosztott videó?", - "removeSharedVideoTitle": "Megosztott videó eltávolítása", + "removeSharedVideoMsg": "Valóban eltávolítható a megosztott video?", + "removeSharedVideoTitle": "Megosztott video eltávolítása", "reservationError": "Foglalási rendszerhiba", "reservationErrorMsg": "Hibakód: {{code}}, üzenet: {{msg}}", "retry": "Újra", @@ -247,7 +242,7 @@ "sessTerminated": "Hívás megszakadt", "Share": "Megosztás", "shareVideoLinkError": "Adjon meg egy helyes YouTube linket.", - "shareVideoTitle": "Videó megosztása", + "shareVideoTitle": "Video megosztása", "shareYourScreen": "Képernyő megosztása", "shareYourScreenDisabled": "Képernyőmegosztás letiltva.", "shareYourScreenDisabledForGuest": "Vendég nem végezhet képernyőmegosztást.", @@ -269,16 +264,9 @@ "userPassword": "felhasználói jelszó", "WaitForHostMsg": "A <b>{{room}}</b> konferencia még nem kezdődött meg. Ha Ön a házigazda, akkor hitelesítse magát. Ellenkező esetben, kérjük várjon a házigazda érkezésére.", "WaitForHostMsgWOk": "A <b>{{room}}</b> konferencia még nem kezdődött meg. Ha Ön a házigazda, kérjük az „OK” gombra kattintva hitelesítse magát. Ellenkező esetben, kérjük várjon a házigazda érkezésére.", - "WaitingForHost": "Várakozás a házigazdára…", + "WaitingForHost": "Várakozás a házigazdára ...", "Yes": "Igen", - "yourEntireScreen": "A teljes képernyő", - "screenSharingAudio": "Hang megosztása", - "muteEveryoneStartMuted": "Mindenki elnémítva kezd ezután", - "muteEveryoneSelf": "önmagamat", - "muteEveryoneTitle": "Mindenki elnémítása?", - "muteEveryoneDialog": "Valóban mindenki elnémítható? Nem fogja tudni visszahangosítani, de ő önmagát bármikor vissza tudja majd hangosítani.", - "muteEveryoneElseTitle": "Mindenki elnémítása, kivéve: {{whom}}?", - "muteEveryoneElseDialog": "Némítás után már nem fogja tudni visszahangosítani, de ő önmagát bármikor vissza tudja hangosítani." + "yourEntireScreen": "A teljes képernyő" }, "dialOut": { "statusMessage": "jelenleg {{status}}" @@ -347,17 +335,17 @@ "supportMsg": "Ismételt hiba esetén érdemes kapcsolatba lépnie" }, "keyboardShortcuts": { - "focusLocal": "Fókusz a saját videómra", - "focusRemote": "Fókusz egy másik személy videójára", + "focusLocal": "Fókusz a saját videomra", + "focusRemote": "Fókusz egy másik személy videojára", "fullScreen": "Belépés vagy kilépés a teljes képernyőből", "keyboardShortcuts": "Gyorsbillentyűk", "localRecording": "Helyi rögzítési vezérlőelemek megjelenítése vagy elrejtése", "mute": "Mikrofon némítása vagy visszahangosítása", - "pushToTalk": "Nyomd, hogy beszélj (adó-vevő)", + "pushToTalk": "Push to talk", "raiseHand": "Kéz felemelése vagy leengedése", "showSpeakerStats": "Beszéd statisztikák megjelenítése", "toggleChat": "Csevegés megnyitása vagy bezárása", - "toggleFilmstrip": "Videó bélyegképek megjelenítése vagy elrejtése", + "toggleFilmstrip": "Video bélyegképek megjelenítése vagy elrejtése", "toggleScreensharing": "Váltás kamera és képernyőmegosztás között", "toggleShortcuts": "Gyorsbillentyűk megjelenítése vagy elrejtése", "videoMute": "Kamera elindítása vagy leállítása", @@ -375,7 +363,7 @@ "errorLiveStreamNotEnabled": "Az élő közvetítés nincs engedélyezve ezzel az email címmel: {{email}}. Engedélyezze az élő közvetítést vagy lépjen be egy másik felhasználóval, ahol az engedélyezve van.", "expandedOff": "Az élő közvetítés leállt", "expandedOn": "Az értekezlet jelenleg közvetítve van a YouTube-on.", - "expandedPending": "Az élvő közvetítés elindult…", + "expandedPending": "Az élvő közvetítés elindult...", "failedToStart": "Az élvő közvetítés indítása meghiúsult", "getStreamKeyManually": "Nem lehet semmilyen élő közvetítést letölteni. Az élő közvetítéshez szükséges kulcsot a Youtube-tól lehet beszerezni.", "invalidStreamKey": "Az élő közvetítési kulcs valószínűleg hibás.", @@ -383,7 +371,7 @@ "offBy": "{{name}} leállította az élő közvetítést", "on": "Élő közvetítés", "onBy": "{{name}} elindította az élő közvetítést", - "pending": "Élő közvetítés kezdése…", + "pending": "Élő közvetítés kezdése...", "serviceName": "Élő közvetítési szolgáltatás", "signedInAs": "Jelenleg bejelentkezve mint:", "signIn": "Bejelentkezés a Google-lel", @@ -391,9 +379,7 @@ "signOut": "Kilépés", "start": "Élő közvetítés kezdése", "streamIdHelp": "Mi ez?", - "unavailableTitle": "Élő közvetítés elérhetetlen", - "googlePrivacyPolicy": "Google adatvédelmi irányelvek", - "youtubeTerms": "YouTube szolgáltatási feltételek" + "unavailableTitle": "Élő közvetítés elérhetetlen" }, "localRecording": { "clientState": { @@ -441,9 +427,9 @@ "kickParticipant": "{{kicked}} résztvevőt kirúgta {{kicker}}", "me": "Én", "moderator": "Moderátori jogok biztosítva!", - "muted": "A beszélgetést elnémítva kezdte meg.", + "muted": "A beszélgetést lenémítva kezdte meg.", "mutedTitle": "Le lett némítva!", - "mutedRemotelyTitle": "{{participantDisplayName}} elnémította Önt!", + "mutedRemotelyTitle": "{{participantDisplayName}} lenémította Önt!", "mutedRemotelyDescription": "Bármikor visszahangosíthatja magát, ha készen áll a beszédre. Némítsa le magát ismét, ha a felesleges zajoktól meg kívánja védeni az értekezletet.", "passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) egy másik résztvevő által eltávolítva", "passwordSetRemotely": "$t(lockRoomPasswordUppercase) egy másik résztvevő által beállítva", @@ -460,20 +446,20 @@ }, "passwordSetRemotely": "egy másik résztvevő által beállítva", "passwordDigitsOnly": "Legfeljebb {{number}} szám", - "poweredby": "Működteti a", + "poweredby": "Működteti:", "presenceStatus": { "busy": "Foglalt", - "calling": "Hívás…", + "calling": "Hívás...", "connected": "Kapcsolódva", - "connecting": "Kapcsolódás…", + "connecting": "Kapcsolódás...", "connecting2": "Kapcsolódás*...", "disconnected": "Szétkapcsolva", "expired": "Lejárt", "ignored": "Figyelmen kívül hagyva", - "initializingCall": "Hívás kezdeményezése…", + "initializingCall": "Hívás indítása...", "invited": "Meghívva", "rejected": "Elutasítva", - "ringing": "Csörgetés…" + "ringing": "Csörgetés..." }, "profile": { "setDisplayNameLabel": "Állítsa be a megjelenő nevet", @@ -491,7 +477,7 @@ "error": "A felvétel meghiúsult. Próbálja újra.", "expandedOff": "A felvétel leállt", "expandedOn": "Az értekezlet jelenleg rögzítés alatt áll.", - "expandedPending": "A felvétel elindult…", + "expandedPending": "A felvétel elindult...", "failedToStart": "A felvétel indítása meghiúsult", "fileSharingdescription": "Felvétel megosztása az értekezlet résztvevőivel", "live": "ÉLŐ", @@ -500,7 +486,7 @@ "offBy": "{{name}} leállította a felvételt", "on": "Felvétel", "onBy": "{{name}} elindította a felvételt", - "pending": "Értekezlet rögzítésének előkészítése…", + "pending": "Értekezlet rögzítésének előkészítése...", "rec": "REC", "serviceDescription": "A felvételt a rögzítési szolgáltatás veszi fel", "serviceName": "Felvétel szolgáltatás", @@ -525,17 +511,15 @@ "language": "Nyelv", "loggedIn": "Belépve mint {{name}}", "moderator": "Moderátor", - "more": "Továbbiak", + "more": "Több", "name": "Név", "noDevice": "Nincs", "selectAudioOutput": "Hangkimenet", "selectCamera": "Kamera", "selectMic": "Mikrofon", - "startAudioMuted": "Mindenki elnémítva kezd", - "startVideoMuted": "Mindenki videó nélkül kezd", - "title": "Beállítások", - "speakers": "Hangszórók", - "microphones": "Mikrofonok" + "startAudioMuted": "Mindenki lenémítva kezd", + "startVideoMuted": "Mindenki video nélkül kezd", + "title": "Beállítások" }, "settingsView": { "advanced": "Haladó", @@ -552,8 +536,8 @@ "profileSection": "Profil", "serverURL": "Kiszolgáló URL", "showAdvanced": "Speciális beállítások megjelenítése", - "startWithAudioMuted": "Kezdés a hang elnémításával", - "startWithVideoMuted": "Kezdés a videó letiltásával", + "startWithAudioMuted": "Kezdés a hang lenémításával", + "startWithVideoMuted": "Kezdés a video letiltásával", "version": "Verzió" }, "share": { @@ -605,7 +589,7 @@ "recording": "Felvétel átváltása", "remoteMute": "Résztvevők némítása", "Settings": "Beállítások átváltása", - "sharedvideo": "YouTube videó megosztásának átváltása", + "sharedvideo": "YouTube video megosztásának átváltása", "shareRoom": "Valaki meghívása", "shareYourScreen": "Képernyőmegosztás átváltása", "shortcuts": "Gyorsbillentyűk átváltása", @@ -613,11 +597,8 @@ "speakerStats": "Beszélő statisztika átváltása", "tileView": "Mozaikos nézet átváltása", "toggleCamera": "Kamera átváltása", - "videomute": "Videó letiltásának átváltása", - "videoblur": "Videoelmosás átváltása", - "toggleFilmstrip": "Filmszalag átváltása", - "muteEveryone": "Mindenki elnémítása", - "moreOptions": "További beállítások megjelenítése" + "videomute": "Video letiltásának átváltása", + "videoblur": "Videoelmosás átváltása" }, "addPeople": "Személy hozzáadása a híváshoz", "audioOnlyOff": "Alacsony sávszélességű mód letiltása", @@ -638,14 +619,14 @@ "hangup": "Kilépés", "help": "Súgó", "invite": "Személyek meghívása", - "login": "Bejelentkezés", - "logout": "Kijelentkezés", + "login": "Belépés", + "logout": "Kilépés", "lowerYourHand": "Kéz leengedése", "moreActions": "További műveltek", "mute": "Némítás / Visszahangosítás", "noAudioSignalTitle": "Nincs bemenet a mikrofonjáról!", "noAudioSignalDesc": "Ha nem szándékosan némította el a rendszerbeállításokban vagy az eszközön, akkor fontolja meg az eszköz cseréjét.", - "noAudioSignalDescSuggestion": "Ha nem szándékosan némította el a rendszerbeállításokban vagy az eszközön, akkor fontolja meg a következő eszköz használatát.", + "noAudioSignalDescSuggestion": "Ha nem szándékosan némította el a rendszerbeállításokban vagy az eszközön, akkor fontolja meg a következő eszköz használatát:", "openChat": "Csevegés megnyitása", "pip": "Belépés kép a képben módba", "privateMessage": "Privát üzenet küldése", @@ -653,7 +634,7 @@ "raiseHand": "Kéz felemelése / leengedése", "raiseYourHand": "Kéz felemelése", "Settings": "Beállítások", - "sharedvideo": "YouTube videó megosztása", + "sharedvideo": "YouTube video megosztása", "shareRoom": "Valaki meghívása", "shortcuts": "Gyorsbillentyűk megtekintése", "speakerStats": "Beszélő statisztika", @@ -661,19 +642,13 @@ "startSubtitles": "Feliratok kezdése", "stopScreenSharing": "Képernyőmegosztás leállítása", "stopSubtitles": "Felirat leállítása", - "stopSharedVideo": "YouTube videó leállítása", + "stopSharedVideo": "YouTube video leállítása", "talkWhileMutedPopup": "Úgy tűnik beszélni szeretne, de le van némítva.", "tileViewToggle": "Mozaikos nézet átváltása", "toggleCamera": "Kamera átváltása", "videomute": "Kamera indítása / leállítása", "startvideoblur": "Háttér elhomályosítása", - "stopvideoblur": "Háttér elhomályosításának letiltása", - "noisyAudioInputDesc": "Úgy tűnik, hogy ez a mikrofon zajos. Le kellene némítani vagy cserélni az eszközt.", - "noisyAudioInputTitle": "Zajosnak tűnik a mikrofonja!", - "noAudioSignalDialInLinkDesc": "Betárcsázási számok", - "noAudioSignalDialInDesc": "Be is tárcsázhat:", - "muteEveryone": "Mindenki elnémítása", - "moreOptions": "További beállítások" + "stopvideoblur": "Háttér elhomályosításának letiltása" }, "transcribing": { "ccButtonTooltip": "Feliratok indítása / leállítása", @@ -682,7 +657,7 @@ "failedToStart": "Meghiúsult az átirat kezdése", "labelToolTip": "Az értekezlet átirata elkezdődött", "off": "Az átirat készítése le lett állítva", - "pending": "Előkészület az értekezlet átiratának készítésére…", + "pending": "Előkészület az értekezlet átiratának készítésére...", "start": "Felirat megjelenítésének kezdése", "stop": "Felirat megjelenítésének befejezése", "tr": "Átirat" @@ -714,12 +689,12 @@ "audioOnlyExpanded": "Jelenleg az alacsony sávszélességű mód az aktív, vagyis csak hangot lehet fogadni és képernyőmegosztást.", "callQuality": "Videominőség", "hd": "MF", - "hdTooltip": "Magas felbontású videó megtekintése", + "hdTooltip": "Magas felbontású video megtekintése", "highDefinition": "Magas felbontású", - "labelTooiltipNoVideo": "Nincs videó", + "labelTooiltipNoVideo": "Nincs video", "labelTooltipAudioOnly": "Alacsony sávszélességű mód aktiválva", "ld": "AF", - "ldTooltip": "Alacsony felbontású videó", + "ldTooltip": "Alacsony felbontású video", "lowDefinition": "Alacsony felbontású", "onlyAudioAvailable": "„Csak hang” mód elérhető", "onlyAudioSupported": "Csak a hang támogatott ebben a böngészőben.", @@ -727,7 +702,7 @@ "p2pVideoQualityDescription": "Az egyenrangú (peer to peer) módban a kapott videominőség csak a magas felbontású és a „csak hang” mód között váltható. A további beállítások nem lesznek figyelembe véve az egyenrangú kapcsolat alatt.", "recHighDefinitionOnly": "Lehetőleg magas felbontású.", "sd": "SF", - "sdTooltip": "Szabványos felbontású videó megtekintése", + "sdTooltip": "Szabványos felbontású video megtekintése", "standardDefinition": "Szabványos felbontású" }, "videothumbnail": { @@ -739,18 +714,17 @@ "muted": "Némítva", "remoteControl": "Távoli vezérlés", "show": "Megjelenítés a színpadon", - "videomute": "A résztvevő leállította a kameráját", - "domuteOthers": "Mindenki más elnémítása" + "videomute": "A résztvevő leállította a kameráját" }, "welcomepage": { "accessibilityLabel": { "join": "Koppintson a csatlakozáshoz", "roomname": "Adja meg a terem nevét" }, - "appDescription": "Rajta, csevegjen az egész csapattal. Valóban hívjon meg mindenkit, akit ismer. A {{app}} teljesen titkosított, 100% -ban nyílt forráskódú videokonferencia-megoldás, amelyet egész nap, minden nap ingyenesen használhat – fiók nélkül.", + "appDescription": "Gyerünk,csevegjen az egész csapattal. Valóban hívjon meg mindenkit, akit ismer. A {{app}} teljesen titkosított, 100% -ban nyílt forráskódú videokonferencia-megoldás, amelyet egész nap, minden nap ingyenesen használhat - fiók nélkül.", "audioVideoSwitch": { - "audio": "Hang", - "video": "Videó" + "audio": "Gyerünk, csevegjen az egész csapattal. Valóban hívjon meg mindenkit akit ismer. A {{app}} teljesen titkosított, 100% -ban nyílt forráskódú videokonferencia-megoldás, amelyet egész nap, minden nap ingyenesen használhat - fiók nélkül.", + "video": "Video" }, "calendar": "Naptár", "connectCalendarButton": "Naptár csatolása", @@ -770,19 +744,6 @@ "roomnameHint": "Adja meg a kívánt nevet vagy URL-t, amelyhez csatlakozni szeretne. Bármiképp elnevezheti, csak ossza meg az értekezlet résztvevőivel, hogy ők ugyanezt a nevet tudják majd megadni.", "sendFeedback": "Visszajelzés küldése", "terms": "Feltételek", - "title": "Biztonságos, maradéktalanul felszerelt és teljesen ingyenes videokonferencia", - "getHelp": "Segítség kérése" - }, - "helpView": { - "header": "Súgó" - }, - "lonelyMeetingExperience": { - "youAreAlone": "Egyedül van ezen az értekezleten", - "button": "Mások meghívása" - }, - "chromeExtensionBanner": { - "dontShowAgain": "Ne jelenjen meg újra", - "buttonText": "Chrome kiterjesztés telepítése", - "installExtensionText": "Kiterjesztés telepítése a Google Calendar és az Office 365 integrációjához" + "title": "Biztonságos, maradéktalanul felszerelt és teljesen ingyenes videokonferencia" } -} +} \ No newline at end of file diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-it.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-it.json index d6ecc95c1..d424850ab 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-it.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-it.json @@ -4,7 +4,7 @@ "countryNotSupported": "Non supportiamo ancora questa destinazione.", "countryReminder": "Stai chiamando fuori dagli Stati Uniti? Assicurati d'inserire il prefisso internazionale!", "disabled": "Non puoi invitare persone.", - "failedToAdd": "L'aggiunta di nuove persone è fallita", + "failedToAdd": "L'aggiunta di nuovi membri è fallita", "footerText": "La chiamata all'esterno è disabilitata.", "loading": "Sto cercando persone e numeri di telefono", "loadingNumber": "Sto validando il numero di telefono", @@ -110,7 +110,7 @@ "downloadApp": "Scarica l'app", "launchWebButton": "Avvia sul web", "openApp": "Prosegui verso l'app", - "title": "Sto avviando la tua videoconferenza su {{app}}…", + "title": "Sto avviando la tua videoconferenza su {{app}}...", "tryAgainButton": "Prova di nuovo sul desktop" }, "defaultLink": "es. {{url}}", @@ -123,7 +123,7 @@ "deviceSelection": { "noPermission": "Permesso negato", "previewUnavailable": "Anteprima non disponibile", - "selectADevice": "Scegli un dispositivo", + "selectADevice": "Seleziona un dispositivo", "testAudio": "Riproduci un suono di prova" }, "dialog": { @@ -144,14 +144,14 @@ "cameraUnsupportedResolutionError": "La tua videocamera non supporta la risoluzione richiesta.", "Cancel": "Annulla", "close": "Chiudi", - "conferenceDisconnectMsg": "Controlla la tua connessione. Riconnessione in {{seconds}} secondi…", + "conferenceDisconnectMsg": "Controlla la tua connessione. Riconnessione in {{seconds}} secondi...", "conferenceDisconnectTitle": "Sei stato disconnesso.", - "conferenceReloadMsg": "Stiamo cercando di risolvere il problema. Riconnessione in {{seconds}} secondi…", + "conferenceReloadMsg": "Stiamo cercando di risolvere il problema. Riconnessione in {{seconds}} secondi...", "conferenceReloadTitle": "Purtroppo qualcosa è andato storto.", "confirm": "Conferma", "confirmNo": "No", "confirmYes": "Sì", - "connectError": "Oh! Qualcosa è andato storto e non ti puoi collegare alla conferenza.", + "connectError": "Oops! Qualcosa è andato storto e non ti puoi collegare alla conferenza.", "connectErrorWithMsg": "Oops! Qualcosa è andato storto e non ti puoi collegare alla conferenza: {{msg}}", "connecting": "Connessione", "contactSupport": "Contatta il supporto", @@ -185,7 +185,7 @@ "lockTitle": "Blocco fallito", "logoutQuestion": "Vuoi disconnetterti e interrompere la conferenza ?", "logoutTitle": "Logout", - "maxUsersLimitReached": "È stato raggiunto il numero massimo di partecipanti. La conferenza è al completo. Contatta l'organizzatore, o riprova più tardi!", + "maxUsersLimitReached": "E' stato raggiunto il numero massimo di partecipanti. La conferenza è al completo. Contatta l'organizzatore, o riprova più tardi!", "maxUsersLimitReachedTitle": "Raggiunto limite partecipanti", "micConstraintFailedError": "Il tuo microfono non soddisfa alcuni dei requisiti richiesti.", "micNotFoundError": "Microfono non trovato.", @@ -222,7 +222,7 @@ "reservationError": "Errore di sistema in prenotazione", "reservationErrorMsg": "Codice di errore: {{code}}, messaggio: {{msg}}", "retry": "Riprova", - "screenSharingFailedToInstall": "Oh! Non è stato possibile installare l'estensione per la condivisione schermo.", + "screenSharingFailedToInstall": "Oops! Non è stato possibile installare l'estensione per la condivisione schermo. ", "screenSharingFailedToInstallTitle": "Impossibile installare l'estensione per la condivisione schermo", "screenSharingFirefoxPermissionDeniedError": "Qualcosa è andato storto mentre cercavamo di condividere il tuo schermo. Assicurati di averci dato il premesso di condivisione.", "screenSharingFirefoxPermissionDeniedTitle": "Ops! Non siamo stati in grado di avviare la condivisione schermo!", @@ -301,7 +301,7 @@ "noPassword": "Nessuna", "noRoom": "Non è stata specificata nessuna stanza da chiamare.", "numbers": "Numeri da chiamare", - "password": "$t(lockRoomPasswordUppercase):", + "password": "Password", "title": "Condividi", "tooltip": "Invia il collegamento e i numeri telefonici di questa conferenza", "label": "Informazioni meeting" @@ -429,7 +429,7 @@ }, "passwordSetRemotely": "definita da altro utente", "passwordDigitsOnly": "Fino a {{number}} cifre", - "poweredby": "offerto da", + "poweredby": "powered by", "presenceStatus": { "busy": "Occupato", "calling": "Chiamata…", @@ -541,7 +541,7 @@ "toolbar": { "accessibilityLabel": { "audioOnly": "Attiva/disattiva solo audio", - "audioRoute": "Scegli l'uscita audio", + "audioRoute": "Seleziona la periferica audio", "callQuality": "Gestisci qualità della chiamata", "cc": "Attiva/disattiva sottotitoli", "chat": "Attiva/disattiva la chat", @@ -568,15 +568,15 @@ "shortcuts": "Attiva/disattiva scorciatoie", "show": "", "speakerStats": "Attiva/disattiva statistiche relatore", - "tileView": "Vedi tutti i partecipanti insieme, o uno solo", + "tileView": "Attiva/disattiva visualizzazione a tessere", "toggleCamera": "Cambia videocamera", "videomute": "Attiva/disattiva videocamera", "videoblur": "Attiva/disattiva offuscamento video" }, "addPeople": "Aggiungi persone alla chiamata", - "audioOnlyOff": "Anche video", - "audioOnlyOn": "Solo audio", - "audioRoute": "Scegli l'uscita audio", + "audioOnlyOff": "Disattiva modalità solo audio", + "audioOnlyOn": "Attiva modalità solo audio", + "audioRoute": "Seleziona la periferica audio", "authenticate": "Autenticazione", "callQuality": "Gestisci qualità della chiamata", "chat": "Apri / Chiudi chat", @@ -584,9 +584,9 @@ "documentClose": "Chiudi documento condiviso", "documentOpen": "Apri documento condiviso", "enterFullScreen": "Visualizza a schermo intero", - "enterTileView": "Vedi tutti i partecipanti", + "enterTileView": "Vista a tessere", "exitFullScreen": "Esci da schermo intero", - "exitTileView": "Vedi una persona sola", + "exitTileView": "Vista utente singolo", "feedback": "Lascia un feedback", "hangup": "Esci", "invite": "Invita persone", @@ -612,7 +612,7 @@ "stopSubtitles": "Ferma sottotitoli", "stopSharedVideo": "Ferma video YouTube", "talkWhileMutedPopup": "Stai provando a parlare? Il microfono è disattivato.", - "tileViewToggle": "Vedi tutti i partecipanti insieme, o uno solo", + "tileViewToggle": "Attiva/disattiva visualizzazione griglia", "toggleCamera": "Cambia videocamera", "videomute": "Attiva / Disattiva videocamera", "startvideoblur": "Offusca il video", @@ -654,12 +654,12 @@ }, "videoStatus": { "audioOnly": "AUD", - "audioOnlyExpanded": "Hai attivato la modalità solo audio. Questa modalità permette di rispamiare banda, ma non vedrai gli altri partecipanti.", + "audioOnlyExpanded": "Modalita' solo audio attiva. Questa modalità permette di rispamiare banda ma non vedrai gli altri partecipanti.", "callQuality": "Qualità video", "hd": "HD", "highDefinition": "Alta definizione", "labelTooiltipNoVideo": "Nessun video", - "labelTooltipAudioOnly": "Hai attivato la modalità solo audio", + "labelTooltipAudioOnly": "Modalità solo audio abilitata", "ld": "LD", "lowDefinition": "Bassa definizione", "onlyAudioAvailable": "È disponibile solo l'audio", diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-ja.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-ja.json index 495f244bb..c0b58e3a6 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-ja.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-ja.json @@ -5,7 +5,7 @@ "countryReminder": "米国外にコールしますか? 国コードで始まることを確認してください!", "disabled": "人を招待することはできません。", "failedToAdd": "", - "footerText": "ダイヤルアウトが無効です。", + "footerText": "ダイヤルアウトが無効しています。", "loading": "人と電話番号を検索する", "loadingNumber": "電話番号を検証しています", "loadingPeople": "招待する人を検索する", @@ -17,12 +17,14 @@ "telephone": "電話: {{number}}", "title": "この会議に人を招待する" }, + "\u0005addPeople": {}, "audioDevices": { "bluetooth": "Bluetooth", "headphones": "ヘッドフォン", "phone": "電話", "speaker": "スピーカー" }, + "\u0005audioDevices": {}, "audioOnly": { "audioOnly": "オーディオのみ" }, @@ -31,7 +33,7 @@ "confirmAddLink": "このイベントにビデオ会議リンクを張り付けますか。", "error": { "appConfiguration": "カレンダー機能が正しく設定されていない", - "generic": "エラーが発生しました。カレンダー機能設定を確認してください、もしくはカレンダーを更新してください", + "generic": "エラーが発生した。カレンダー機能設定を確認してください、もしくはカレンダーを更新してください", "notSignedIn": "認証中エラーが発生しました。カレンダーの設定を確認し、ログインし直してください。" }, "join": "参加", @@ -44,6 +46,7 @@ "refresh": "カレンダーを更新する", "today": "今日" }, + "\u0005calendarSync": {}, "chat": { "error": "エラー: \"{{originalText}}\" がまだ送信されていません. エラー: {{error}}", "messagebox": "メッセージを書いてください", @@ -70,7 +73,7 @@ }, "connectionindicator": { "address": "アドレス:", - "bandwidth": "推定帯域幅", + "bandwidth": "推定バンドワイズ", "bitrate": "ビットレート:", "bridgeCount": "サーバー数:", "connectedTo": "接続先:", @@ -83,7 +86,7 @@ "quality": { "good": "良い", "inactive": "休止中", - "lost": "接続ロスト", + "lost": "接続切れた", "nonoptimal": "最適ではない", "poor": "悪い" }, @@ -106,7 +109,7 @@ "downloadApp": "アプリをダウンロードする", "launchWebButton": "Webで起動する", "openApp": "アプリで続く", - "title": "{{app}} で会議を開始する…", + "title": "{{app}} で会議を開始する...", "tryAgainButton": "デスクトップでもう一度お試しください" }, "defaultLink": "例: {{url}}", @@ -136,19 +139,19 @@ "cameraNotSendingData": "あなたのカメラにアクセスすることができません。 他のアプリケーションがこのデバイスを使用しているかどうかを確認し、設定メニューから別のデバイスを選択するか、アプリケーションをリロードしてみてください。", "cameraNotSendingDataTitle": "カメラにアクセスできません", "cameraPermissionDeniedError": "あなたはカメラを使用する許可を与えていません。 あなたはまだ会議に参加することができますが、他の参加者はあなたを見ることはできません。 この問題を解決するには、アドレスバーのカメラボタンを使用します。", - "cameraUnknownError": "不明な理由でカメラが使用できません。", + "cameraUnknownError": "不明な理由でカメラを使用することはできません。", "cameraUnsupportedResolutionError": "お使いのカメラは、必要なビデオ解像度をサポートしていません。", "Cancel": "キャンセル", "close": "閉じる", - "conferenceDisconnectMsg": "ネットワーク接続を確認することができます。 {{seconds}} 秒で再接続します…", + "conferenceDisconnectMsg": "ネットワーク接続を確認することができます。 {{seconds}} 秒で再接続します...", "conferenceDisconnectTitle": "あなたは切断されました。", - "conferenceReloadMsg": "私たちはこれを解決しようとしています。 {{seconds}} 秒で再接続します…", - "conferenceReloadTitle": "残念ながら、何か問題が発生しています。", + "conferenceReloadMsg": "私たちはこれを解決しようとしています。 {{seconds}} 秒で再接続します...", + "conferenceReloadTitle": "残念ながら、何かが間違っていました。", "confirm": "確認", "confirmNo": "いいえ", "confirmYes": "はい", - "connectError": "おおっと! 何かがうまくいかず、会議に接続できませんでした。", - "connectErrorWithMsg": "おおっと! 何か問題が発生し、会議に接続できませんでした: {{msg}}", + "connectError": "Oops! 何かがうまくいかず、会議に接続できませんでした。", + "connectErrorWithMsg": "Oops! 何か問題が発生し、会議に接続できませんでした: {{msg}}", "connecting": "接続中", "contactSupport": "サポート問い合わせ先", "copy": "コピー", @@ -191,7 +194,7 @@ "micUnknownError": "不明な理由でマイクを使用することはできません。", "muteParticipantBody": "あなたはそのミュートを解除することはできませんが、彼らはいつでも自分自身のミュートを解除することができます。", "muteParticipantButton": "ミュート", - "muteParticipantDialog": "この参加者をミュートしますか。あなた解除できませんが、本人が自分でいつでも解除できます。", + "muteParticipantDialog": "この参加者をミュートしますか。あなたが取り戻せませんが、本人が自分でいつでも解除でいます。", "muteParticipantTitle": "", "Ok": "Ok", "passwordLabel": "", @@ -249,10 +252,13 @@ "userPassword": "ユーザーのパスワード", "WaitForHostMsg": "", "WaitForHostMsgWOk": "", - "WaitingForHost": "ホストを待っています…", + "WaitingForHost": "ホストを待っています...", "Yes": "はい", "yourEntireScreen": "あなたの画面全体" }, + "\u0005dialog": { + "accessibilityLabel": {} + }, "dialOut": { "statusMessage": "は現在 {{status}} です" }, @@ -302,6 +308,7 @@ "tooltip": "この会議のリンクとダイヤルイン情報を共有する", "label": "ミーティング情報" }, + "\u0005info": {}, "inviteDialog": { "alertText": "", "header": "招待", @@ -332,6 +339,7 @@ "toggleShortcuts": "キーボード ショートカットを表示", "videoMute": "カメラを有効/無効" }, + "\u0005keyboardShortcuts": {}, "liveStreaming": { "busy": "私たちはストリーミングリソースを解放するために取り組んでいます。 数分後にもう一度お試しください。", "busyTitle": "すべてのストリーマーは現在ビジー状態です", @@ -350,7 +358,7 @@ "invalidStreamKey": "ライブストリーミングキーが間に合いました。", "off": "ライブストリーミングが停止しました", "on": "ライブストリーミング", - "pending": "ライブストリームを開始しています…", + "pending": "ライブストリームを開始しています...", "serviceName": "ライブストリーミングサービス", "signedInAs": "", "signIn": "Googleでログイン", @@ -360,6 +368,7 @@ "streamIdHelp": "これは何ですか?", "unavailableTitle": "ライブストリーミングは利用できません" }, + "\u0005liveStreaming": {}, "localRecording": { "clientState": { "off": "オフ", @@ -389,6 +398,7 @@ "stop": "録画を停止する", "yes": "はい" }, + "\u0005localRecording": {}, "lockRoomPassword": "パスワード", "lockRoomPasswordUppercase": "パスワード", "me": "私", @@ -440,6 +450,7 @@ "rejected": "", "ringing": "着信している・・" }, + "\u0005presenceStatus": {}, "profile": { "setDisplayNameLabel": "表示名を設定してください", "setEmailInput": "メールアドレスを入力してください", @@ -471,6 +482,7 @@ "unavailable": "Oops! {{serviceName}} は現在使用できません。 私たちはこの問題の解決に取り組んでいます。 後でもう一度お試しください。", "unavailableTitle": "録画できません" }, + "\u0005recording": {}, "sectionList": { "pullToRefresh": "プルしてリフレッシュする" }, @@ -497,6 +509,9 @@ "startVideoMuted": "全員非表示にする", "title": "設定" }, + "\u0005settings": { + "calendar": {} + }, "settingsView": { "alertOk": "OK", "alertTitle": "Warning", @@ -525,10 +540,12 @@ "speakerStats": "話者の統計", "speakerTime": "話す時間" }, + "\u0005speakerStats": {}, "startupoverlay": { "policyText": " ", "title": "{{app}} を使用するには、マイクとカメラが必要です。" }, + "\u0005startupoverlay": {}, "suspendedoverlay": { "rejoinKeyTitle": "再参加", "text": "再接続するには、<i>再参加</i> ボタンを押してください。", @@ -558,7 +575,7 @@ "recording": "レコーディングに切り替える", "remoteMute": "参加者を追い出す", "Settings": "設定に切り替える", - "sharedvideo": "YouTubeビデオ共有に切り替える", + "sharedvideo": "Youtubeビデオ共有に切り替える", "shareRoom": "誰かを招待する", "shareYourScreen": "画面共有に切り替える", "shortcuts": "ショートカットに切り替える", @@ -613,6 +630,9 @@ "startvideoblur": "", "stopvideoblur": "" }, + "\u0005toolbar": { + "accessibilityLabel": {} + }, "transcribing": { "ccButtonTooltip": "字幕を表示・非表示する", "error": "録画に失敗しました。 もう一度お試しください。", @@ -625,6 +645,7 @@ "stop": "字幕を非表示する", "tr": "TR" }, + "\u0005transcribing": {}, "userMedia": { "androidGrantPermissions": "ブラウザーのポップアップで<b><i>許可する</i></b>を選択してください", "chromeGrantPermissions": "ブラウザーのポップアップで<b><i>許可する</i></b>を選択してください", @@ -643,7 +664,7 @@ "errorAlreadyInvited": "{{displayName}}さんがすでに招待されました", "errorInvite": "会議がまだ設定されていません。もう一度お試しください。", "errorInviteFailed": "問題を解決しています。しばらくしたらまたお試しください。", - "errorInviteFailedTitle": "{{displayName}}さんが招待できません。", + "errorInviteFailedTitle": " {{displayName}}さんが招待できません。", "errorInviteTitle": "招集エラー", "pending": "{{displayName}} が招待されました" }, @@ -703,5 +724,6 @@ "sendFeedback": "フィードバックを送信", "terms": "利用規約", "title": "安全で、機能豊富で、完全に無料のビデオ会議" - } -} + }, + "\u0005welcomepage": {} +} \ No newline at end of file diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-ko.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-ko.json index 4b80491af..ffea6c19e 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-ko.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-ko.json @@ -106,7 +106,7 @@ "downloadApp": "앱 다운로드", "launchWebButton": "웹에서 실행", "openApp": "방으로 이동하기", - "title": "{{app}}에서 회의 시작…", + "title": "{{app}}에서 회의 시작...", "tryAgainButton": "데스크톱에서 다시 시도하십시오" }, "defaultLink": "e.g. {{url}}", @@ -140,7 +140,7 @@ "cameraUnsupportedResolutionError": "카메라가 필요한 비디오 해상도를 지원하지 않습니다", "Cancel": "취소", "close": "닫기", - "conferenceDisconnectMsg": "네트워크 연결을 확인하고 있습니다. {{seconds}} 초 내에 다시 연결중입니다…", + "conferenceDisconnectMsg": "네트워크 연결을 확인하고 있습니다. {{seconds}} 초 내에 다시 연결중입니다...", "conferenceDisconnectTitle": "연결이 끊어졌습니다.", "conferenceReloadMsg": "문제를 해결하려고 노력하고 있습니다. {{seconds}} 초 안에 다시 연결중입니다.", "conferenceReloadTitle": "불행하게도 문제가 발생했습니다", @@ -249,10 +249,13 @@ "userPassword": "사용자 비밀번호", "WaitForHostMsg": "", "WaitForHostMsgWOk": "", - "WaitingForHost": "호스트를 기다리는 중입니다…", + "WaitingForHost": "호스트를 기다리는 중입니다...", "Yes": "", "yourEntireScreen": "전체 화면" }, + "\u0005dialog": { + "accessibilityLabel": {} + }, "dialOut": { "statusMessage": "지금은 {{status}}입니다" }, @@ -302,6 +305,7 @@ "tooltip": "링크 공유 및 회의에 대한 정보", "label": "" }, + "\u0005info": {}, "inviteDialog": { "alertText": "", "header": "초대", @@ -350,7 +354,7 @@ "invalidStreamKey": "", "off": "실시간 스트리밍이 중지됨", "on": "실시간 스트리밍", - "pending": "실시간 스트리밍 시작…", + "pending": "실시간 스트리밍 시작...", "serviceName": "실시간 스트리밍 서비스", "signedInAs": "", "signIn": "Google로 로그인", @@ -389,6 +393,7 @@ "stop": "레코딩 종료", "yes": "" }, + "\u0005localRecording": {}, "lockRoomPassword": "패스워드", "lockRoomPasswordUppercase": "패스워드", "me": "Me", @@ -462,7 +467,7 @@ "loggedIn": "", "off": "레코딩이 중지됨", "on": "레코딩", - "pending": "참석할 멤버를 기다리는 중입니다…", + "pending": "참석할 멤버를 기다리는 중입니다...", "rec": "REC", "serviceDescription": "", "serviceName": "레코딩 서비스", @@ -471,6 +476,7 @@ "unavailable": "죄송합니다. {{serviceName}}은 현재 사용할 수 없습니다. 저희는 문제를 해결하기 위해 노력하고 있습니다. 나중에 다시 시도 해주십시오.", "unavailableTitle": "레코딩을 사용할 수 없습니다" }, + "\u0005recording": {}, "sectionList": { "pullToRefresh": "당겨서 새로고침" }, @@ -497,6 +503,9 @@ "startVideoMuted": "모두가 비디오 비활성화로 시작합니다", "title": "세티" }, + "\u0005settings": { + "calendar": {} + }, "settingsView": { "alertOk": "확인", "alertTitle": "경고", @@ -613,6 +622,7 @@ "startvideoblur": "", "stopvideoblur": "" }, + "\u0005toolbar": {}, "transcribing": { "ccButtonTooltip": "", "error": "레코딩이 실패했습니다. 다시 시도하십시오.", @@ -620,11 +630,12 @@ "failedToStart": "", "labelToolTip": "", "off": "", - "pending": "참석할 멤버를 기다리는 중입니다…", + "pending": "참석할 멤버를 기다리는 중입니다...", "start": "", "stop": "", "tr": "" }, + "\u0005transcribing": {}, "userMedia": { "androidGrantPermissions": "브라우저에서 권한을 요청할 때 <b><i>허락</i></b>을 선택", "chromeGrantPermissions": "브라우저에서 권한을 요청할 때 <b><i>허락</i></b>을 선택", @@ -704,4 +715,4 @@ "terms": "이용약관", "title": "" } -} +} \ No newline at end of file diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-nl.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-nl.json index b560bb125..e13025046 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-nl.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-nl.json @@ -59,7 +59,7 @@ "you": "jij" }, "connectingOverlay": { - "joiningRoom": "Er wordt verbinding gemaakt met de vergadering…" + "joiningRoom": "Er wordt verbinding gemaakt met de vergadering..." }, "connection": { "ATTACHED": "Bijgesloten", @@ -116,7 +116,7 @@ "downloadApp": "De app downloaden", "launchWebButton": "Starten via web", "openApp": "Doorgaan naar de app", - "title": "Uw vergadering wordt gestart in {{app}}…", + "title": "Uw vergadering wordt gestart in {{app}}...", "tryAgainButton": "Opnieuw proberen op desktop" }, "defaultLink": "bijv. {{url}}", @@ -150,9 +150,9 @@ "cameraUnsupportedResolutionError": "De camera biedt geen ondersteuning voor de vereiste videoresolutie.", "Cancel": "Annuleren", "close": "Sluiten", - "conferenceDisconnectMsg": "Controleer de netwerkverbinding. Over {{seconds}} sec. wordt opnieuw geprobeerd verbinding te maken…", + "conferenceDisconnectMsg": "Controleer de netwerkverbinding. Over {{seconds}} sec. wordt opnieuw geprobeerd verbinding te maken...", "conferenceDisconnectTitle": "De verbinding is verbroken.", - "conferenceReloadMsg": "We proberen het probleem op te lossen. Over {{seconds}} sec. wordt opnieuw geprobeerd verbinding te maken…", + "conferenceReloadMsg": "We proberen het probleem op te lossen. Over {{seconds}} sec. wordt opnieuw geprobeerd verbinding te maken...", "conferenceReloadTitle": "Er is iets misgegaan.", "confirm": "Bevestigen", "confirmNo": "Nee", @@ -259,7 +259,7 @@ "userPassword": "gebruikerswachtwoord", "WaitForHostMsg": "De vergadering <b>{{room}}</b> is nog niet gestart. Verifieer de vergadering als u de host bent. Anders wacht u tot de host aanwezig is.", "WaitForHostMsgWOk": "De vergadering <b>{{room}}</b> is nog niet gestart. Als u de host bent, drukt u op OK om te verifiëren. Anders wacht u tot de host aanwezig is.", - "WaitingForHost": "Wachten op de host…", + "WaitingForHost": "Wachten op de host...", "Yes": "Ja", "yourEntireScreen": "Uw gehele scherm" }, @@ -354,13 +354,13 @@ "errorLiveStreamNotEnabled": "Livestreaming is niet ingeschakeld voor {{email}}. Schakel livestreaming in of meld u aan bij een account waarvoor livestreaming is ingeschakeld.", "expandedOff": "De livestream is gestopt", "expandedOn": "De vergadering wordt momenteel gestreamd naar YouTube.", - "expandedPending": "De livestream wordt gestart…", + "expandedPending": "De livestream wordt gestart...", "failedToStart": "Livestream niet gestart", "getStreamKeyManually": "Er zijn geen livestreams opgehaald. Haal de sleutel voor uw livestream op uit YouTube.", "invalidStreamKey": "De sleutel voor de livestream is mogelijk onjuist.", "off": "Livestream gestopt", "on": "Livestream", - "pending": "Livestream starten…", + "pending": "Livestream starten...", "serviceName": "Livestreamservice", "signedInAs": "U bent momenteel aangemeld als:", "signIn": "Aanmelden via Google", @@ -438,22 +438,22 @@ "poweredby": "mogelijk gemaakt door", "presenceStatus": { "busy": "Bezet", - "calling": "Bellen…", + "calling": "Bellen...", "connected": "Verbonden", - "connecting": "Verbinding maken…", + "connecting": "Verbinding maken...", "connecting2": "Verbinding maken*...", "disconnected": "Verbinding verbroken", "expired": "Verlopen", "ignored": "Genegeerd", - "initializingCall": "Gesprek starten…", + "initializingCall": "Gesprek starten...", "invited": "Uitgenodigd", "rejected": "Geweigerd", - "ringing": "Gaat over…" + "ringing": "Gaat over..." }, "profile": { "setDisplayNameLabel": "Uw weergavenaam instellen", "setEmailInput": "E-mailadres invoeren", - "setEmailLabel": "Uw Gravatar voor e-mail instellen", + "setEmailLabel": "Uw gravatar voor e-mail instellen", "title": "Profiel" }, "recording": { @@ -465,14 +465,14 @@ "error": "Opname is mislukt. Probeer het opnieuw.", "expandedOff": "Opname is gestopt", "expandedOn": "De vergadering wordt momenteel opgenomen.", - "expandedPending": "Opname wordt gestart…", + "expandedPending": "Opname wordt gestart...", "failedToStart": "Opname starten is mislukt", "fileSharingdescription": "Opname delen met deelnemers aan vergadering", "live": "LIVE", "loggedIn": "Aangemeld als {{userName}}", "off": "Opname gestopt", "on": "Opnemen", - "pending": "Voorbereiden op opname van vergadering…", + "pending": "Voorbereiden op opname van vergadering...", "rec": "OPN.", "serviceDescription": "Uw opname wordt opgeslagen door de opnameservice", "serviceName": "Opnameservice", @@ -604,7 +604,6 @@ "moreActions": "Meer acties", "moreOptions": "Meer opties", "mute": "Dempen/dempen opheffen", - "muteEveryone": "Iedereen dempen", "openChat": "Chat openen", "pip": "Beeld-in-beeld-modus activeren", "profile": "Uw profiel bewerken", @@ -634,7 +633,7 @@ "failedToStart": "Transcriberen starten is mislukt", "labelToolTip": "De vergadering wordt getranscribeerd", "off": "Transcriberen gestopt", - "pending": "Voorbereiden op transcriberen van vergadering…", + "pending": "Voorbereiden op transcriberen van vergadering...", "start": "Weergave van ondertiteling starten", "stop": "Weergave van ondertiteling stoppen", "tr": "TR" diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-oc.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-oc.json index 86491aef2..af4f9a81e 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-oc.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-oc.json @@ -72,11 +72,7 @@ "DISCONNECTED": "Desconnectat", "DISCONNECTING": "Desconnexion en cors", "ERROR": "Error", - "RECONNECTING": "Un problèma ret s'es produita. Reconnexion en cors...", - "LOW_BANDWIDTH": "", - "GOT_SESSION_ID": "", - "GET_SESSION_ID_ERROR": "", - "FETCH_SESSION_ID": "" + "RECONNECTING": "Un problèma ret s'es produita. Reconnexion en cors..." }, "connectionindicator": { "address": "Adreça :", @@ -105,9 +101,7 @@ "remoteport_plural": "Pòrts distants :", "resolution": "Resolucion :", "status": "Connexion :", - "transport": "Transpòrt :", - "transport_plural": "", - "e2e_rtt": "" + "transport": "Transpòrt :" }, "dateUtils": { "earlier": "Mai d’ora", @@ -121,7 +115,7 @@ "downloadApp": "Telecargar l’aplicacion", "launchWebButton": "Lançar del navigador", "openApp": "Telecargar l’aplicacion", - "title": "Aviada de vòstra conferéncia dins {{app}}…", + "title": "Aviada de vòstra conferéncia dins {{app}}...", "tryAgainButton": "Tornar ensajar del burèu" }, "defaultLink": "ex. {{url}}", @@ -156,9 +150,9 @@ "cameraUnsupportedResolutionError": "Vòstra camèra pren pas en carga la resolucion vidèo que cal.", "Cancel": "Anullar", "close": "Tampar", - "conferenceDisconnectMsg": "Vos cal benlèu verificar vòstra connexion al malhum. Nòva connexion dins {{seconds}} segondas…", + "conferenceDisconnectMsg": "Vos cal benlèu verificar vòstra connexion al malhum. Nòva connexion dins {{seconds}} segondas...", "conferenceDisconnectTitle": "Sètz estat desconnectat.", - "conferenceReloadMsg": "Sèm a reglar aquò ! Nòva connexion dins {{seconds}} segondas…", + "conferenceReloadMsg": "Sèm a reglar aquò ! Nòva connexion dins {{seconds}} segondas...", "conferenceReloadTitle": "Malurosament, quicòm truquèt.", "confirm": "Confirmar", "confirmNo": "Non", @@ -271,14 +265,7 @@ "WaitForHostMsgWOk": "La conferéncia <b>{{room}}</b> a pas encara començat. Se sètz l’òst volgatz ben clicar Ok per vos identificar. Autrament esperatz qu’arribe l’òste.", "WaitingForHost": "Òm pòt pas que partejar una vidèo a l'encòp", "Yes": "Òc", - "yourEntireScreen": "Vòstre ecran complet", - "screenSharingAudio": "", - "muteEveryoneStartMuted": "", - "muteEveryoneSelf": "", - "muteEveryoneTitle": "", - "muteEveryoneDialog": "", - "muteEveryoneElseTitle": "", - "muteEveryoneElseDialog": "" + "yourEntireScreen": "Vòstre ecran complet" }, "dialOut": { "statusMessage": "ara es {{status}}" @@ -375,7 +362,7 @@ "errorLiveStreamNotEnabled": "La difusion en dirècte es pas activada per {{email}}. Volgatz ben activar la difusion en dirècte o vos connectar amb un compte que l’a activada.", "expandedOff": "La difusion en dirècte es estada arrestada", "expandedOn": "La conferéncia es difusada sus YouTube.", - "expandedPending": "La difusion en dirècte comença…", + "expandedPending": "La difusion en dirècte comença...", "failedToStart": "La difusion en dirècte a pas capitat de s'aviar", "getStreamKeyManually": "Avèm pas pogut recuperar cap de flux en dirècte. Ensajatz d’obténer vòstre clau de difusion sus YouTube.", "invalidStreamKey": "La clau de difusion en dirècte es benlèu pas corrècta.", @@ -383,7 +370,7 @@ "offBy": "{{name}} a arrestat la difusion en dirècte", "on": "La difusion en dirècte es estada arrestada", "onBy": "{{name}} a començat la difusion en dirècte", - "pending": "Començar lo dirècte…", + "pending": "Començar lo dirècte...", "serviceName": "Servici de difusion en dirècte", "signedInAs": "Sètz connectat coma :", "signIn": "Se connectar amb Google", @@ -391,9 +378,7 @@ "signOut": "Se desconnectar", "start": "Aviar una difusion en dirècte", "streamIdHelp": "Qu’es aquò ?", - "unavailableTitle": "Difusion en dirècte indisponibla", - "googlePrivacyPolicy": "", - "youtubeTerms": "" + "unavailableTitle": "Difusion en dirècte indisponibla" }, "localRecording": { "clientState": { @@ -463,22 +448,22 @@ "poweredby": "produit per", "presenceStatus": { "busy": "Ocupat", - "calling": "Sonada…", + "calling": "Sonada...", "connected": "Connectat", - "connecting": "Connexion en cors…", + "connecting": "Connexion en cors...", "connecting2": "Connexion*...", "disconnected": "Desconnectat", "expired": "Expirat", "ignored": "Ignorat", - "initializingCall": "Començament de la sonada…", + "initializingCall": "Començament de la sonada...", "invited": "Convidat", "rejected": "Refusat", - "ringing": "A sonar…" + "ringing": "A sonar..." }, "profile": { "setDisplayNameLabel": "Causissètz vòstre escais", "setEmailInput": "Picatz lo corrièl", - "setEmailLabel": "Definissètz vòstre corrièl per Gravatar", + "setEmailLabel": "Definissètz vòstre corrièl per gravatar", "title": "Perfil" }, "raisedHand": "Volriá charrar", @@ -491,7 +476,7 @@ "error": "Fracàs de l'enregistrament. Mercés de tornar ensajar.", "expandedOff": "Enregistrament arrestat", "expandedOn": "La conferéncia es enregistrada.", - "expandedPending": "Aviada de l’enregistrament…", + "expandedPending": "Aviada de l’enregistrament...", "failedToStart": "L'enregistrament n'as pas réussi a démarrer", "fileSharingdescription": "Partejar l’enregistrament amb los participants de la reünion", "live": "DIRÈCTE", @@ -500,7 +485,7 @@ "offBy": "{{name}} a arrestat l’enregistrament", "on": "Enregistrament", "onBy": "{{name}} a començat l’enregistrament", - "pending": "Preparacion de l’enregistrament de la conferéncia…", + "pending": "Preparacion de l’enregistrament de la conferéncia...", "rec": "ENRG", "serviceDescription": "Vòstre enregistrament serà salvagardat pel servici dedicat.", "serviceName": "Servici d’enregistrament", @@ -533,9 +518,7 @@ "selectMic": "Microfòn", "startAudioMuted": "Començan totes sens son", "startVideoMuted": "Començan totes sens vidèo", - "title": "Paramètres", - "speakers": "", - "microphones": "" + "title": "Paramètres" }, "settingsView": { "advanced": "Avançat", @@ -605,7 +588,7 @@ "recording": "Passar al enregistraments", "remoteMute": "Copar lo son del participant", "Settings": "Passar als paramètres", - "sharedvideo": "Passar al partatge de vidèo YouTube", + "sharedvideo": "Passar al partatge de vidèo Youtube", "shareRoom": "Convidar qualqu’un", "shareYourScreen": "Passar a la captura d’ecran", "shortcuts": "Passar als acorchis", @@ -614,9 +597,7 @@ "tileView": "Activar/Desactivar la vista en mosaïc", "toggleCamera": "Passar a la camèra", "videomute": "Silenciar la vidèo", - "videoblur": "Enfoscar o non la vidèo", - "muteEveryone": "", - "moreOptions": "" + "videoblur": "Enfoscar o non la vidèo" }, "addPeople": "Ajustar de monde a vòstra sonada", "audioOnlyOff": "Desactivar lo mòde connexion febla", @@ -666,13 +647,7 @@ "toggleCamera": "Passar a la camèra", "videomute": "Aviar / Arrestar la camèra", "startvideoblur": "Trebolar mon rèire-plan", - "stopvideoblur": "Desactivar lo borrolatge del rèire-plan", - "noisyAudioInputDesc": "", - "noisyAudioInputTitle": "", - "noAudioSignalDialInLinkDesc": "", - "noAudioSignalDialInDesc": "", - "muteEveryone": "", - "moreOptions": "" + "stopvideoblur": "Desactivar lo borrolatge del rèire-plan" }, "transcribing": { "ccButtonTooltip": "Aviar / Arrestat los sostítols", @@ -681,7 +656,7 @@ "failedToStart": "Fracàs de l’aviada de la transcripcion", "labelToolTip": "La conferéncia es a èsser transcricha", "off": "Transcripcion arrestada", - "pending": "Preparacion de l’enregistrament de la conferéncia…", + "pending": "Preparacion de l’enregistrament de la conferéncia...", "start": "Mostrar los sostítols", "stop": "Levar los sostítols", "tr": "TR" @@ -738,8 +713,7 @@ "muted": "Mut", "remoteControl": "Contraròtle alonhat", "show": "Mostrar davant", - "videomute": "Lo participant a arrestat la camèra", - "domuteOthers": "" + "videomute": "Lo participant a arrestat la camèra" }, "welcomepage": { "accessibilityLabel": { @@ -769,19 +743,6 @@ "roomnameHint": "Picatz lo nom o l’URL de la sala que volètz jónher. Podètz inventar un nom, cal pas que lo monde que volètz convidar lo sàpian. ", "sendFeedback": "Mandar vòstra opinion", "terms": "Tèrmes", - "title": "Conferéncias vidèo securizadas amb plen de foncionalitats e complètament gratuitas", - "getHelp": "" - }, - "helpView": { - "header": "" - }, - "lonelyMeetingExperience": { - "youAreAlone": "", - "button": "" - }, - "chromeExtensionBanner": { - "dontShowAgain": "", - "buttonText": "", - "installExtensionText": "" + "title": "Conferéncias vidèo securizadas amb plen de foncionalitats e complètament gratuitas" } -} +} \ No newline at end of file diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-pl.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-pl.json index 0b99eeba7..44e22b676 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-pl.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-pl.json @@ -60,7 +60,7 @@ "you": "Ty" }, "connectingOverlay": { - "joiningRoom": "Łączenie z Twoim spotkaniem…" + "joiningRoom": "Łączenie z Twoim spotkaniem..." }, "connection": { "ATTACHED": "Załącznik", @@ -121,7 +121,7 @@ "downloadApp": "Pobierz aplikację", "launchWebButton": "Uruchom przez przeglądarkę", "openApp": "Kontynuuj w aplikacji", - "title": "Trwa uruchamianie Twojego spotkania w {{app}}…", + "title": "Trwa uruchamianie Twojego spotkania w {{app}}...", "tryAgainButton": "Spróbuj ponownie w aplikacji stacjonarnej" }, "defaultLink": "np. {{url}}", @@ -156,9 +156,9 @@ "cameraUnsupportedResolutionError": "Twoja kamera nie obsługuje wymaganej rozdzielczości.", "Cancel": "Anuluj", "close": "Zamknij", - "conferenceDisconnectMsg": "Być może należy sprawdzić połączenie sieciowe. Ponowne połączenie za {{seconds}} sekund…", + "conferenceDisconnectMsg": "Być może należy sprawdzić połączenie sieciowe. Ponowne połączenie za {{seconds}} sekund...", "conferenceDisconnectTitle": "Zostałeś rozłączony.", - "conferenceReloadMsg": "Staramy się to naprawić. Ponowne połączenie za {{seconds}} sekund…", + "conferenceReloadMsg": "Staramy się to naprawić. Ponowne połączenie za {{seconds}} sekund...", "conferenceReloadTitle": "Niestety, coś poszło nie tak.", "confirm": "Potwierdź", "confirmNo": "Nie", @@ -269,7 +269,7 @@ "userPassword": "hasło użytkownika", "WaitForHostMsg": "Konferencja <b>{{room}}</b> jeszcze się nie rozpoczęła. Jeśli jesteś gospodarzem, prosimy o uwierzytelnienie. Jeśli nie, prosimy czekać na przybycie gospodarza.", "WaitForHostMsgWOk": "Konferencja <b>{{room}}</b> jeszcze się nie zaczęła. Jeśli jesteś jej gospodarzem, wybierz Ok, aby się uwierzytelnić. Jeśli nie, prosimy czekać na przybycie gospodarza.", - "WaitingForHost": "Oczekiwanie na gospodarza…", + "WaitingForHost": "Oczekiwanie na gospodarza...", "Yes": "Tak", "yourEntireScreen": "Cały Twój ekran" }, @@ -368,7 +368,7 @@ "errorLiveStreamNotEnabled": "", "expandedOff": "Transmisja na żywo została zatrzymana", "expandedOn": "Spotkanie jest obecnie transmitowane na YouTube.", - "expandedPending": "Transmisja na żywo rozpoczyna się…", + "expandedPending": "Transmisja na żywo rozpoczyna się...", "failedToStart": "Transmitowanie na żywo nie uruchomiło się", "getStreamKeyManually": "Nie byliśmy w stanie pobrać żadnych transmisji na żywo. Spróbuj uzyskać klucz do transmisji na żywo z YouTube.", "invalidStreamKey": "Klucz transmisji na żywo może być nieprawidłowy.", @@ -376,7 +376,7 @@ "offBy": "{{name}} zatrzymał transmisję na żywo", "on": "Strumień live", "onBy": "{{name}} rozpoczął transmisję na żywo", - "pending": "Start strumieniowania live…", + "pending": "Start strumieniowania live...", "serviceName": "Usługa transmisji na żywo", "signedInAs": "Jesteś obecnie zalogowany jako:", "signIn": "Zaloguj się z Google", @@ -454,22 +454,22 @@ "poweredby": "napędzane dzięki", "presenceStatus": { "busy": "Zajęte", - "calling": "Dzwonienie…", + "calling": "Dzwonienie...", "connected": "Połączono", - "connecting": "Łączenie…", + "connecting": "Łączenie...", "connecting2": "Łączenie*...", "disconnected": "Rozłączony", "expired": "Wygasłe", "ignored": "Zignorowane", - "initializingCall": "Inicjalizacja połączenia…", + "initializingCall": "Inicjalizacja połączenia...", "invited": "Zaproszony", "rejected": "Odrzucony", - "ringing": "Dzwonek…" + "ringing": "Dzwonek..." }, "profile": { "setDisplayNameLabel": "Podaj swoją wyświetlaną nazwę", "setEmailInput": "Wprowadź adres e-mail", - "setEmailLabel": "Ustaw adres poczty elektronicznej swojego Gravatara", + "setEmailLabel": "Ustaw email swojego gravatara", "title": "Profil" }, "raisedHand": "Chcesz się odezwać ?", @@ -482,7 +482,7 @@ "error": "Nagranie się nie powiodło. Proszę spróbować ponownie.", "expandedOff": "Nagrywanie zostało zatrzymane", "expandedOn": "Spotkanie jest obecnie nagrywane.", - "expandedPending": "Nagrywanie się rozpoczyna…", + "expandedPending": "Nagrywanie się rozpoczyna...", "failedToStart": "Nagrywanie nie jest możliwe", "fileSharingdescription": "Współdziel nagranie z uczestnikami spotkania", "live": "NA ŻYWO", @@ -491,7 +491,7 @@ "offBy": "{{name}} zatrzymał nagrywanie", "on": "Nagrywanie", "onBy": "{{name}} rozpoczął nagrywanie", - "pending": "Przygotowanie do nagrania spotkania…", + "pending": "Przygotowanie do nagrania spotkania...", "rec": "NAGRYWANIE", "serviceDescription": "Twoje nagranie zostanie zapisane przez usługę nagrywania", "serviceName": "Usługa nagrywania", @@ -662,7 +662,7 @@ "failedToStart": "Błąd uruchomienia transkrypcji", "labelToolTip": "Spotkanie jest transkrybowane", "off": "Transkrypcja została zatrzymana", - "pending": "Przygotowanie do transkrypcji spotkania…", + "pending": "Przygotowanie do transkrypcji spotkania...", "start": "Rozpocznij wyświetlanie napisów", "stop": "Zatrzymaj wyświetlanie napisów", "tr": "TR" @@ -751,4 +751,4 @@ "terms": "Warunki korzystania", "title": "Bezpieczna, w pełni funkcjonalna i całkowicie bezpłatna wideokonferencja" } -} +} \ No newline at end of file diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-ptBR.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-ptBR.json index a53cea581..0b7be7112 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-ptBR.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-ptBR.json @@ -478,7 +478,7 @@ "profile": { "setDisplayNameLabel": "Definir seu nome de exibição", "setEmailInput": "Digite e-mail", - "setEmailLabel": "Definir seu e-mail de Gravatar", + "setEmailLabel": "Definir seu email de gravatar", "title": "Perfil" }, "raisedHand": "Gostaria de falar", @@ -605,7 +605,7 @@ "recording": "Alternar gravação", "remoteMute": "Silenciar participante", "Settings": "Alternar configurações", - "sharedvideo": "Alternar compartilhamento de vídeo do YouTube", + "sharedvideo": "Alternar compartilhamento de vídeo do Youtube", "shareRoom": "Convidar alguém", "shareYourScreen": "Alternar compartilhamento de tela", "shortcuts": "Alternar atalhos", diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-ru.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-ru.json index 63d9b7765..eebfc5c4b 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-ru.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-ru.json @@ -57,12 +57,12 @@ }, "privateNotice": "Личное сообщение пользователю {{recipient}}", "title": "Чат", - "you": "вы" + "you": "" }, "chromeExtensionBanner": { - "installExtensionText": "Установите расширение для интеграции с Google Календарь и Office 365", - "buttonText": "Установить расширение Chrome", - "dontShowAgain": "Не показывай мне это снова" + "installExtensionText": "", + "buttonText": "", + "dontShowAgain": "" }, "connectingOverlay": { "joiningRoom": "Пытаемся присоединиться к вашей конференции..." @@ -78,24 +78,22 @@ "DISCONNECTING": "Отключение", "ERROR": "Ошибка", "RECONNECTING": "Проблема с сетью. Переподключение...", - "LOW_BANDWIDTH": "Видео для {{displayName}} приостановлено из-за низкой пропускной способности", - "GOT_SESSION_ID": "Получение идентификатора сеанса … Готово", - "GET_SESSION_ID_ERROR": "Ошибка получения идентификатора сеанса: {{code}}" + "LOW_BANDWIDTH": "Видео для {{displayName}} приостановлено из-за низкой пропускной способности" }, "connectionindicator": { "address": "Адрес:", "bandwidth": "Средняя скорость:", "bitrate": "Битрейт:", - "bridgeCount": "Количество серверов: ", + "bridgeCount": "Количество серверов:", "connectedTo": "Подключен к:", "framerate": "Частота кадров:", "less": "Краткая информация", - "localaddress_0": "Локальный адрес:", - "localaddress_1": "Локальных адреса:", - "localaddress_2": "Локальных адресов:", - "localport_0": "Локальный порт:", - "localport_1": "Локальных порта:", - "localport_2": "Локальных портов:", + "localaddress_0": "Локальные адреса:", + "localaddress_1": "Локальные адреса:", + "localaddress_2": "Локальные адреса:", + "localport_0": "Локальные порты:", + "localport_1": "Локальные порты:", + "localport_2": "Локальные порты:", "more": "Подробная информация", "packetloss": "Потери пакетов:", "quality": { @@ -105,18 +103,17 @@ "nonoptimal": "не оптимально", "poor": "плохо" }, - "remoteaddress_0": "Удаленный адрес:", - "remoteaddress_1": "Удаленных адреса:", - "remoteaddress_2": "Удаленных адресов:", - "remoteport_0": "Удаленный порт:", - "remoteport_1": "Удаленных порта:", - "remoteport_2": "Удаленных портов:", + "remoteaddress_0": "Удаленные адреса:", + "remoteaddress_1": "Удаленные адреса:", + "remoteaddress_2": "Удаленные адреса:", + "remoteport_0": "Удаленные порты:", + "remoteport_1": "Удаленные порты:", + "remoteport_2": "Удаленные порты:", "resolution": "Разрешение:", "status": "Связь:", - "transport_0": "Метод отправки:", - "transport_1": "Метода отправки:", - "transport_2": "Методов отправки:", - "e2e_rtt": "" + "transport_0": "Методы отправки:", + "transport_1": "Методы отправки:", + "transport_2": "Методы отправки:" }, "dateUtils": { "earlier": "Ранее", @@ -195,7 +192,7 @@ "internalErrorTitle": "Внутренняя ошибка", "kickMessage": "Вы можете связаться с {{participantDisplayName}} для получения более подробной информации.", "kickParticipantButton": "Выгнать", - "kickParticipantDialog": "Вы уверены, что хотите выгнать этого участника?", + "kickParticipantDialog": "Вы уверены, что хотите выгнать этого участника?", "kickParticipantTitle": "Выгнать этого участника?", "kickTitle": "Ай! {{participantDisplayName}} выгнал вас из конференции.", "liveStreaming": "Трансляция", @@ -216,7 +213,7 @@ "micUnknownError": "Неизвестная ошибка использования микрофона.", "muteParticipantBody": "Вы не можете включить им звук, но они могут сделать это сами в любое время.", "muteParticipantButton": "Выключить звук", - "muteParticipantDialog": "Вы уверены, что хотите отключить микрофон у данного пользователя? Вы не сможете отменить это действие, однако он сможет сам снова включить микрофон в любое время.", + "muteParticipantDialog": "Вы уверены, что хотите отключить микрофон у данного пользователя? Вы не сможете отменить это действие, однако он сможет сам снова включить микрофон в любое время.", "muteParticipantTitle": "Приглушить этого участника?", "Ok": "Ok", "passwordLabel": "$t(lockRoomPasswordUppercase)", @@ -231,7 +228,7 @@ "rejoinNow": "Подключиться снова", "remoteControlAllowedMessage": "{{user}} принял ваш запрос на удаленное управление!", "remoteControlDeniedMessage": "{{user}} отклонил ваш запрос на удаленное управление!", - "remoteControlErrorMessage": "Произошла ошибка при попытке запросить разрешения удаленного управления от {{user}}!", + "remoteControlErrorMessage": "Произошла ошибка при попытке запросить разрешения удаленного управления от {{user}}.", "remoteControlRequestMessage": "Разрешить {{user}} удаленное управление вашим рабочим столом?", "remoteControlShareScreenWarning": "Если нажмете \"Разрешить\", то поделитесь своим экраном!", "remoteControlStopMessage": "Сессия удаленного управления завершена!", @@ -245,7 +242,7 @@ "retry": "Повторить", "screenSharingFailedToInstall": "Ошибка установки расширения для показа экрана.", "screenSharingFailedToInstallTitle": "Расширение для показа экрана не установлено", - "screenSharingFirefoxPermissionDeniedError": "Что-то пошло не так, когда мы пытались поделиться вашим экраном. Пожалуйста, убедитесь, что вы дали нам разрешение на это. ", + "screenSharingFirefoxPermissionDeniedError": "Что-то пошло не так, когда мы пытались поделиться вашим экраном. Пожалуйста, убедитесь, что вы дали нам разрешение на это.", "screenSharingFirefoxPermissionDeniedTitle": "Ошибка показа экрана!", "screenSharingPermissionDeniedError": "Ошибка доступа к вашему расширению для показа экрана. Пожалуйста, перезапустите браузер и попробуйте снова.", "sendPrivateMessage": "Вы недавно получили личное сообщение. Вы хотели ответить на него, или отправить свое сообщение группе?", @@ -280,10 +277,7 @@ "WaitForHostMsgWOk": "Конференция <b>{{room}}</b> еще не началась. Если вы организатор, пожалуйста, нажмите Ok для аутентификации. В противном случае, дождитесь организатора.", "WaitingForHost": "Ждем организатора...", "Yes": "Да", - "yourEntireScreen": "Весь экран", - "muteEveryoneElseTitle": "Заглушить всех, за исключением {{whom}}?", - "screenSharingAudio": "Поделиться аудио", - "muteEveryoneSelf": "себя" + "yourEntireScreen": "Весь экран" }, "dialOut": { "statusMessage": "сейчас {{status}}" @@ -354,7 +348,7 @@ "keyboardShortcuts": { "focusLocal": "Фокус на ваше видео", "focusRemote": "Фокус на видео другого участника", - "fullScreen": "Вкл/выкл полноэкранный режим", + "fullScreen": "Вкл/выкл полноэкранный режим ", "keyboardShortcuts": "Комбинации клавиш", "localRecording": "Отобразить или скрыть элементы управления локальной записи", "mute": "Микрофон (вкл./выкл.)", @@ -373,14 +367,14 @@ "busyTitle": "Все ресурсы для трансляции уже задействованы", "changeSignIn": "Переключить аккаунты.", "choose": "Выбрать трансляцию", - "chooseCTA": "Выберите трансляцию. Вы вошли в систему как {{email}}.", + "chooseCTA": "Выберите трансляцию. Вы вошли в систему как {{email}}. ", "enterStreamKey": "Введите ваш ключ трансляции YouTube.", "error": "Ошибка трансляции. Пожалуйста, попробуйте снова.", "errorAPI": "Произошла ошибка при доступе к вашим трансляциям на YouTube. Повторите попытку входа в систему.", "errorLiveStreamNotEnabled": "Трансляция не подключена на {{email}}. Пожалуйста подключите трансляцию или войдите в аккаунт с подключенной трансляцией.", "expandedOff": "Прямая трансляция остановлена", "expandedOn": "В настоящий момент конференция транслируется на YouTube.", - "expandedPending": "Начинается прямая трансляция...", + "expandedPending": "Начинается прямая трансляция..", "failedToStart": "Ошибка трансляции видео", "getStreamKeyManually": "Прямые трансляций не найдены. Попробуйте получить ключ прямой трансляции от YouTube.", "invalidStreamKey": "Похоже ключ прямой трансляции неверен.", @@ -396,9 +390,7 @@ "signOut": "Выход", "start": "Начать трансляцию", "streamIdHelp": "Что это?", - "unavailableTitle": "Трансляция недоступна", - "googlePrivacyPolicy": "Политика конфиденциальности Google", - "youtubeTerms": "Условия использования YouTube" + "unavailableTitle": "Трансляция недоступна" }, "localRecording": { "clientState": { @@ -440,10 +432,10 @@ "focus": "Фокус встречи", "focusFail": "{{component}} недоступен, повторите через {{ms}} с", "grantedTo": "{{to}} получил права модератора!", - "invitedOneMember": "{{name}} был приглашен", + "invitedOneMember": "{{displayName}} был приглашен", "invitedThreePlusMembers": "Приглашены {{name}} и {{count}} других пользователей(ля)", "invitedTwoMembers": "{{first}} и {{second}} присоединились к конференции", - "kickParticipant": "{{kicker}} выгнал {{kicked}}", + "kickParticipant": "{{kicker}} выгнал {{kicked}} ", "me": "Я", "moderator": "Получены права модератора!", "muted": "Вы начали разговор без звука.", @@ -457,7 +449,7 @@ "startSilentTitle": "У вас отсутствует звук!", "startSilentDescription": "Перезайдите в конференцию, чтобы включить звук", "suboptimalBrowserWarning": "К сожалению, ваш браузер не полностью поддерживает данную систему вэбконференций. Мы работаем над проблемой, однако, пока рекомендуем вам воспользоваться <a href='static/recommendedBrowsers.html' target='_blank'> следующими браузерами</a>.", - "suboptimalExperienceTitle": "Предупреждение браузера", + "suboptimalExperienceTitle": "К сожалению, этот браузер может не подойти для работы с {{appName}}. Мы работаем над проблемой, а пока попробуйте один из <a href='static/recommendedBrowsers.html 'target='_blank'>полностью поддерживаемых браузеров</a>.", "unmute": "Включить микрофон", "newDeviceCameraTitle": "Обнаружена новая камера", "newDeviceAudioTitle": "Обнаружено новое аудиоустройство", @@ -468,14 +460,14 @@ "poweredby": "работает на", "presenceStatus": { "busy": "Занят", - "calling": "Вызываю...", + "calling": "Вызываю . . .", "connected": "Подключено", - "connecting": "Подключение...", + "connecting": "Подключение. . .", "connecting2": "Подключение*...", "disconnected": "Отключено", "expired": "Истек", "ignored": "Проигнорирован", - "initializingCall": "Инициализация звонка...", + "initializingCall": "Инициализация звонка. . .", "invited": "Приглашенный", "rejected": "Отклонен", "ringing": "Звоню. . ." @@ -483,7 +475,7 @@ "profile": { "setDisplayNameLabel": "Отображаемое имя", "setEmailInput": "Введите e-mail", - "setEmailLabel": "E-mail для Gravatar", + "setEmailLabel": "E-mail для gravatar", "title": "Профиль" }, "raisedHand": "Хочет говорить", @@ -538,9 +530,7 @@ "selectMic": "Микрофон", "startAudioMuted": "Все начинают с выключенным звуком", "startVideoMuted": "Все начинают в скрытом режиме", - "title": "Настройки", - "speakers": "Динамики", - "microphones": "Микрофоны" + "title": "Настройки" }, "settingsView": { "advanced": "Дополнительные", @@ -683,7 +673,7 @@ "failedToStart": "Неудалось начать расшифровку", "labelToolTip": "Создается транскрипция конференции.", "off": "Расшифровка остановлена", - "pending": "Подготовка расшифровки конференции...", + "pending": "Подготовка расшифровки конференции. . .", "start": "Вкл/Выкл показ субтитров", "stop": "Вкл/Выкл показ субтитров", "tr": "" @@ -739,7 +729,7 @@ "moderator": "Модератор", "mute": "Без звука", "muted": "Звук выключен", - "remoteControl": "Начать / Остановить дистанционный контроль", + "remoteControl": "", "show": "Показать крупным планом", "videomute": "Участник отключил камеру" }, @@ -750,7 +740,7 @@ }, "appDescription": "Попробуйте видеочат со всей командой. Приглашайте знакомых! {{app}} — полностью зашифрованное решение для видеоконференций с открытым исходным кодом. Пользуйтесь каждый день, бесплатно и без регистрации.", "audioVideoSwitch": { - "audio": "Звук", + "audio": "Календарь", "video": "Видео" }, "calendar": "Календарь", @@ -775,8 +765,6 @@ }, "lonelyMeetingExperience": { "button": "Пригласить", - "youAreAlone": "Вы один в видеоконференции", - "title": "Защищенная, полнофункциональная и совершенно бесплатная система видеоконференций", - "getHelp": "Получить помощь" + "youAreAlone": "Вы один в видеоконференции" } } diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-sc.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-sc.json deleted file mode 100644 index 02e6fcb94..000000000 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-sc.json +++ /dev/null @@ -1,786 +0,0 @@ -{ - "addPeople": { - "add": "Invita", - "countryNotSupported": "No est ancora possìbile de impreare custa destinatzione.", - "countryReminder": "Ses mutende in foras de is Istados Unidos? Verìfica chi insertas su còdighe de istadu!", - "disabled": "Non podes invitare gente.", - "failedToAdd": "Faddina in s'agiunta de partetzipantes", - "footerText": "Is mutidas in essida sunt disativadas.", - "loading": "Chirchende gente e nùmeros de telèfonu", - "loadingNumber": "Verifichende su nùmeru de telèfonu", - "loadingPeople": "Chirchende gente de invitare", - "noResults": "Non cointzidet perunu resultadu", - "noValidNumbers": "Inserta·nche unu nùmeru de telèfonu", - "searchNumbers": "Agiunghe nùmeros de telèfonu", - "searchPeople": "Chirca gente", - "searchPeopleAndNumbers": "Chirca gente o agiunghe is nùmeros de telèfonu issoro", - "telephone": "Telèfonu: {{number}}", - "title": "Invita gente a custa riunione" - }, - "audioDevices": { - "bluetooth": "Bluetooth", - "headphones": "Auriculares", - "phone": "Telèfonu", - "speaker": "Altoparlante", - "none": "Perunu dispositivu de àudio a disponimentu" - }, - "audioOnly": { - "audioOnly": "Àmpiu de banda bàsciu" - }, - "calendarSync": { - "addMeetingURL": "Agiunghe unu ligàmene a s'addòbiu", - "confirmAddLink": "Boles agiùnghere unu ligàmene de Jitsi a custu addòbiu?", - "error": { - "appConfiguration": "S'integratzione de su calendàriu no est cunfigurada bene.", - "generic": "Faddina. Controlla sa cunfiguratzione de calendàriu o proa de atualizare su calendàriu.", - "notSignedIn": "Faddina in s'autenticatzione pro visualizare eventos de calendàriu. Controlla sa cunfiguratzione de calendàriu e proa de ti torrare a autenticare." - }, - "join": "Aderi", - "joinTooltip": "Aderi a sa riunione", - "nextMeeting": "riunione imbeniente", - "noEvents": "Perunu eventu programmadu in futuru.", - "ongoingMeeting": "riunione in cursu", - "permissionButton": "Aberi sa cunfiguratzione", - "permissionMessage": "Su permissu de su calendàriu est rechèdidu pro bìdere is riuniones tuss in s'aplicatzione.", - "refresh": "Atualiza su calendàriu", - "today": "Oe" - }, - "chat": { - "error": "Faddina: su messàgiu tuo no est istadu imbiadu. Resone: {{error}}", - "fieldPlaceHolder": "Iscrie su messàgiu inoghe", - "messagebox": "Iscrie unu messàgiu", - "messageTo": "Messàgiu privadu a {{recipient}}", - "noMessagesMessage": "Perunu messàgiu ancora in sa riunione. Cumintza una tzarrada inoghe!", - "nickname": { - "popover": "Sèbera unu nòmine", - "title": "Inserta su nòmine pro impreare sa tzarrada" - }, - "privateNotice": "Messàgiu privadu a {{recipient}}", - "title": "Tzarrada", - "you": "tue" - }, - "chromeExtensionBanner": { - "installExtensionText": "Installa s'estensione de integratzione cun Google Calendar e Office 365", - "buttonText": "Installa s'estensione de Google", - "dontShowAgain": "Non ddu torres a ammustrare" - }, - "connectingOverlay": { - "joiningRoom": "Connetende a sa riunione..." - }, - "connection": { - "ATTACHED": "Allegados", - "AUTHENTICATING": "Autenticatzione in cursu", - "AUTHFAIL": "Faddina in s'autenticatzione", - "CONNECTED": "Connessione istabilida", - "CONNECTING": "Connetende", - "CONNFAIL": "Faddina in sa connessione", - "DISCONNECTED": "Disconnètidu", - "DISCONNECTING": "Disconnetende", - "ERROR": "Faddina", - "FETCH_SESSION_ID": "Otenende id de sessione...", - "GET_SESSION_ID_ERROR": "Faddina in su ritzevimentu de s'ide de sessione: {{code}}", - "GOT_SESSION_ID": "Otenende id de sessione... Fatu", - "LOW_BANDWIDTH": "Vìdeu disativadu pro {{displayName}} pro istraviare àmpiu de banda" - }, - "connectionindicator": { - "address": "Indiritzu:", - "bandwidth": "Àmpiu de banda istimadu:", - "bitrate": "Velotzidade de bits:", - "bridgeCount": "Nùmeru de servidores: ", - "connectedTo": "Connessione cun:", - "e2e_rtt": "E2E RTT:", - "framerate": "Velotzidade de fotogrammas:", - "less": "Prus pagu informatziones", - "localaddress": "Indiritzu locale:", - "localaddress_plural": "Indiritzos locales:", - "localport": "Portu locale:", - "localport_plural": "Portos locales:", - "more": "Àteras informatziones", - "packetloss": "Pèrdida de pachetes:", - "quality": { - "good": "Bonu", - "inactive": "Inativa", - "lost": "Pèrdida", - "nonoptimal": "No òtima", - "poor": "Pòbera" - }, - "remoteaddress": "Indiritzu remotu:", - "remoteaddress_plural": "Indiritzos remotos:", - "remoteport": "Portu remotu:", - "remoteport_plural": "Portos remotos:", - "resolution": "Risolutzione:", - "status": "Connessione:", - "transport": "Trasportu:", - "transport_plural": "Trasportos:" - }, - "dateUtils": { - "earlier": "Prus antigu", - "today": "Oe", - "yesterday": "Eris" - }, - "deepLinking": { - "appNotInstalled": "Tenes bisòngiu de s'aplicatzione mòbile {{app}} pro aderire a custa tzarrada dae su telèfonu.", - "description": "No est sutzèdidu nudda? Amus chircadu de aviare sa riunione tua in s'aplicatzione de iscrivania {{app}}. Torra·bi a proare o avia·la dae s'aplicatzione web {{app}}.", - "descriptionWithoutWeb": "No est sutzèdidu nudda? Amus chircadu de aviare sa riunione tua in s'aplicatzione de iscrivania {{app}}.", - "downloadApp": "Iscàrriga s'aplicatzione", - "launchWebButton": "Avia in sa web", - "openApp": "Sighi in s'aplicatzione", - "title": "Aviende sa reunione in {{app}}...", - "tryAgainButton": "Torra·bi a proare in s'aplicatzione de iscrivania" - }, - "defaultLink": "p. es. {{url}}", - "defaultNickname": "es. Rosa Pink", - "deviceError": { - "cameraError": "Impossìbile atzèdere a sa càmera", - "cameraPermission": "Faddina in is permissos pro sa càmera", - "microphoneError": "Impossìbile atzèdere a su micròfonu", - "microphonePermission": "Faddina in is permissos pro su micròfonu" - }, - "deviceSelection": { - "noPermission": "No as cuntzèdidu permissos", - "previewUnavailable": "Sa pre-visualizatzione no est a disponimentu", - "selectADevice": "Sèbera unu dispositivu", - "testAudio": "Riprodue unu sonu de proa" - }, - "dialog": { - "accessibilityLabel": { - "liveStreaming": "Trasmissione in direta" - }, - "allow": "Permite", - "alreadySharedVideoMsg": "Un'àteru partetzipante est giai cumpartende unu vìdeu. Custa cunferèntzia permitit de cumpartzire isceti unu vìdeu in contemporànea.", - "alreadySharedVideoTitle": "Isceti unu vìdeu cumpartzidu in contemporànea", - "applicationWindow": "Ventana de s'aplicatzione", - "Back": "In segus", - "cameraConstraintFailedError": "La càmera no satisfà algun dels requeriments.", - "cameraNotFoundError": "Càmera no agatada.", - "cameraNotSendingData": "Impossìbile atzèdere a sa càmera tua. Controlla si un'àtera aplicatzione est impreende custu dispositivu, sèbera un'àteru dispositivu dae su menù de cunfiguratziones o torra a carrigare s'aplicatzione.", - "cameraNotSendingDataTitle": "Non si podet atzèdere a sa càmera", - "cameraPermissionDeniedError": "No as donadu permissos pro impreare sa càmera. Podes intrare in sa cunferèntzia su pròpiu, però s'àtera gente non ti at a bìdere. Imprea su butone de sa càmera in sa barra de indiritzos pro acontzare custu problema.", - "cameraUnknownError": "Non si podet impreare sa càmera (resone disconnota).", - "cameraUnsupportedResolutionError": "Sa càmera no est cumpatìbile cun sa risolutzione de vìdeu rechèdida.", - "Cancel": "Annulla", - "close": "Serra", - "conferenceDisconnectMsg": "Controlla sa cunfiguratzione de rete. Torrende a connètere in {{seconds}} segundos...", - "conferenceDisconnectTitle": "Mutida disconnètida.", - "conferenceReloadMsg": "Semus chirchende de acontzare custu problema. Torrende a connètere in {{seconds}} segundos...", - "conferenceReloadTitle": "B'est istada una faddina.", - "confirm": "Cunfirma", - "confirmNo": "Nono", - "confirmYes": "Eja", - "connectError": "B'àt àpidu una faddina e non podimus connètere cun sa cunferèntzia.", - "connectErrorWithMsg": "B'àt àpidu una faddina e non podimus connètere cun sa cunferèntzia: {{msg}}", - "connecting": "Connetende", - "contactSupport": "Cuntatu s'agiudu", - "copy": "Còpia", - "dismiss": "Iscarta", - "displayNameRequired": "Salude! Comente ti tzèrrias?", - "done": "Fatu", - "enterDisplayName": "Inserta su nòmine inoghe", - "error": "Faddina", - "externalInstallationMsg": "Installa s'estensione nostra pro sa cumpartzidura de iscrivania.", - "externalInstallationTitle": "Estensione rechèdida", - "goToStore": "Bae a sa butega", - "gracefulShutdown": "Su servìtziu nostru est in mantenimentu. Torra·bi a proare a pustis.", - "IamHost": "So mere", - "incorrectRoomLockPassword": "Sa crae no est curreta", - "incorrectPassword": "Su nòmine o sa crae no sunt curretos", - "inlineInstallationMsg": "Installa s'estensione nostra pro sa cumpartzidura de iscrivania.", - "inlineInstallExtension": "Installa immoe", - "internalError": "B'est istada una faddina: {{error}}", - "internalErrorTitle": "Faddina interna", - "kickMessage": "Podes cuntatare {{participantDisplayName}} pro àteras informatziones.", - "kickParticipantButton": "Boga", - "kickParticipantDialog": "Seguru chi boles bogare custa persone?", - "kickParticipantTitle": "Cheres bogare custa persone?", - "kickTitle": "{{participantDisplayName}} t'at bogadu de sa riunione", - "liveStreaming": "Trasmissione in direta", - "liveStreamingDisabledForGuestTooltip": "Is persones invitadas non podent aviare una trasmissione in direta.", - "liveStreamingDisabledTooltip": "Faddina in s'aviu de sa trasmissione in direta.", - "lockMessage": "Impossìbile blocare sa cunferèntzia.", - "lockRoom": "Agiunghe riunione $t(lockRoomPasswordUppercase)", - "lockTitle": "Faddina in su blocu", - "logoutQuestion": "Seguru chi boles essire e firmare sa cunferèntzia?", - "logoutTitle": "Essi", - "maxUsersLimitReached": "Lìmite de partetzipantes cròmpidu. Sa cunferèntzia est prena. Cuntata su mere de sa riunione o torra·bi a proare.", - "maxUsersLimitReachedTitle": "Lìmite de partetzipantes cròmpidu", - "micConstraintFailedError": "Su micròfonu no at soddisfatu is rechestas.", - "micNotFoundError": "Micròfonu no agatadu.", - "micNotSendingData": "Bae a sa cunfiguratzione de s'elaboradore tuo pro ativare su micròfonu tuo e acontzare su livellu", - "micNotSendingDataTitle": "Su micròfonu tuo est in silèntziu pro more de is cunfiguratziones de su sistema tuo", - "micPermissionDeniedError": "No as donadu permissos pro impreare su micròfonu. Podes intrare in sa cunferèntzia su pròpiu, però s'àtera gente non ti at a intèndere. Imprea su butone de sa càmera in sa barra de indiritzos pro acontzare custu problema.", - "micUnknownError": "Non si podet impreare su micròfonu (resone disconnota).", - "muteEveryoneElseDialog": "Una borta chi as postu calicunu a sa muda, no as a pòdere torrare a aviare s'àudio suo, però isse ddu at a pòdere fàghere in cale si siat momentu.", - "muteEveryoneElseTitle": "Boles pònnere totus a sa muda francu {{whom}}?", - "muteEveryoneDialog": "Seguru chi boles pònnere totus a sa muda? No as a pòdere torrare a ativare s'àudio issoro, però is utentes ddu ant a pòdere ativare in cale si siat momentu.", - "muteEveryoneTitle": "Boles pònnere totus a sa muda?", - "muteEveryoneSelf": "tue", - "muteEveryoneStartMuted": "Dae immoe, is tzarradas cumintzant cun is utentes a sa muda", - "muteParticipantBody": "No as a pòdere torrare a ativare s'àudio issoro, però is utentes ddu ant a pòdere ativare in cale si siat momentu.", - "muteParticipantButton": "A sa muda", - "muteParticipantDialog": "Seguru chi boles pònnere custa persone a sa muda? No as a pòdere torrare a ativare s'àudio issoro, però is utentes ddu ant a pòdere ativare in cale si siat momentu.", - "muteParticipantTitle": "Boles pònnere custa persone a sa muda?", - "Ok": "AB", - "passwordLabel": "Unu partetzipante at blocadu sa riunione. Inserta sa $t(lockRoomPassword) pro intrare.", - "passwordNotSupported": "No est possìbile istabilire una $t(lockRoomPassword).", - "passwordNotSupportedTitle": "$t(lockRoomPasswordUppercase) non suportadu", - "passwordRequired": "$t(lockRoomPasswordUppercase) rechèdida", - "popupError": "Su navigadore tuo est blochende is ventanas emergentes de custu situ. Ativa is ventanas emergentes dae sa cunfiguratzione de seguresa de su navigadore e torra·bi a proare.", - "popupErrorTitle": "Finestres emergents blocades", - "recording": "Registrende", - "recordingDisabledForGuestTooltip": "Is persones invitadas non podent registrare.", - "recordingDisabledTooltip": "S'aviu de registratziones est istadu disativadu.", - "rejoinNow": "Torra a intrare", - "remoteControlAllowedMessage": "{{user}} at atzetadu sa rechesta tua de controllu remotu.", - "remoteControlDeniedMessage": "{{user}} at refudadu sa rechesta tua de controllu remotu.", - "remoteControlErrorMessage": "Faddina in sa rechesta de permissos pro su controllu remotu de {{user}}.", - "remoteControlRequestMessage": "Permitis chi {{user}} controllet in remotu s'elaboradore tuo?", - "remoteControlShareScreenWarning": "Si incarcas \"Permite\" as a cumpartzire s'ischermu tuo.", - "remoteControlStopMessage": "Sessione de controllu remotu acabada.", - "remoteControlTitle": "Controllu remotu de elaboradore", - "Remove": "Boga", - "removePassword": "Boga $t(lockRoomPassword)", - "removeSharedVideoMsg": "Seguru chi boles bogare su vìdeu chi as cumpartzidu?", - "removeSharedVideoTitle": "Boga vìdeu cumpartzidu", - "reservationError": "Faddina de riserva de sistema", - "reservationErrorMsg": "Còdighe de faddina: {{code}}, messàgiu: {{msg}}", - "retry": "Torra·bi a proare", - "screenSharingFailedToInstall": "Faddina in s'installatzione de s'estensione de cumpartzidura de ischermu.", - "screenSharingFailedToInstallTitle": "Faddina installatzione estensione cumpartzidura ischermu", - "screenSharingFirefoxPermissionDeniedError": "B'àt àpidu una faddina proende de cumpartzire s'ischermu tuo. Verìfica chi si as donadu permissos pro ddu fàghere. ", - "screenSharingFirefoxPermissionDeniedTitle": "No amus pòdidu aviare sa cumpartzidura de ischermu.", - "screenSharingPermissionDeniedError": "B'àt àpidu una faddina cun is permissos de s'estensione pro sa cumpartzidura de ischermu. Torra a carrigare e torra·bi a proare.", - "sendPrivateMessage": "As retzidu de reghente unu messàgiu privadu. Boles rispòndere a custu messàgiu in privadu, o boles imbiare su messàgiu a su grupu?", - "sendPrivateMessageCancel": "Imbia a su grupu", - "sendPrivateMessageOk": "Imbia in privadu", - "sendPrivateMessageTitle": "Boles imbiare custu messàgiu in privadu?", - "serviceUnavailable": "Su servìtziu no est a disponimentu", - "sessTerminated": "Mutida acabada", - "Share": "Cumpartzi", - "shareVideoLinkError": "Fruni unu ligàmene de youtube curretu.", - "shareVideoTitle": "Cumpartzi unu vìdeu", - "shareYourScreen": "Cumpartzi s'ischermu", - "shareYourScreenDisabled": "Cumpartzidura de ischermu disativada.", - "shareYourScreenDisabledForGuest": "Is persones invitadas non podent cumpartzire s'ischermu.", - "startLiveStreaming": "Avia sa trasmissione in direta", - "startRecording": "Avia sa registratzione", - "startRemoteControlErrorMessage": "Faddina aviende sa sessione de controllu remotu.", - "stopLiveStreaming": "Firma sa trasmissione in direta", - "stopRecording": "Firma sa registratzione", - "stopRecordingWarning": "Seguru chi boles firmare sa registratzione?", - "stopStreamingWarning": "Seguru chi boles firmare sa trasmissione in direta?", - "streamKey": "Crae de sa trasmissione in direta", - "Submit": "Imbia", - "thankYou": "Gràtzias de àere impreadu {{appName}}.", - "token": "còdighe", - "tokenAuthFailed": "No tenes permissu pro intrare in custa mutida.", - "tokenAuthFailedTitle": "Faddina in s'autenticatzione", - "transcribing": "Trascritzione", - "unlockRoom": "Boga riunione $t(lockRoomPassword)", - "userPassword": "crae de utente", - "WaitForHostMsg": "Sa cunferèntzia <b>{{room}}</b> no est cumintzada. Si ses mere de custa cunferèntzia, autèntica·ti. Si nono, iseta chi arribet.", - "WaitForHostMsgWOk": "Sa cunferèntzia <b>{{room}}</b> no est cumintzada. Si ses mere, incarca AB pro ti autenticare. Si nono, iseta chi arribet.", - "WaitingForHost": "Isetende mere...", - "Yes": "Eja", - "yourEntireScreen": "S'ischermu intreu", - "screenSharingAudio": "Cumpartzi s'àudio" - }, - "dialOut": { - "statusMessage": "est immoe {{status}}" - }, - "documentSharing": { - "title": "Documentu cumpartzidu" - }, - "feedback": { - "average": "Mèdiu", - "bad": "Malu", - "detailsLabel": "Nara·si de prus.", - "good": "Bonu", - "rateExperience": "Vota s'esperièntzia tua in custa riunione", - "veryBad": "Mala meda", - "veryGood": "Bona meda" - }, - "incomingCall": { - "answer": "Risponde", - "audioCallTitle": "Mutida in intrada", - "decline": "Iscarta", - "productLabel": "dae Jitsi Meet", - "videoCallTitle": "Mutida de vìdeu in intrada" - }, - "info": { - "accessibilityLabel": "Ammustra informatziones", - "addPassword": "Agiunghe $t(lockRoomPassword)", - "cancelPassword": "Annulla $t(lockRoomPassword)", - "conferenceURL": "Ligàmene:", - "country": "Paisu", - "dialANumber": "Pro intrare in sa riunione, cumpone unu de custos nùmeros e inserta su PIN.", - "dialInConferenceID": "PIN:", - "dialInNotSupported": "Sa partetzipatzione telefònica ebbia no est suportada a oe.", - "dialInNumber": "Cumpone:", - "dialInSummaryError": "Faddina in su ritzevimentu de is nùmeros de telèfonu. Torra·bi a proare a pustis.", - "dialInTollFree": "Sena pedàgios", - "genericError": "Faddina.", - "inviteLiveStream": "Pro bìdere sa trasmissione in direta de custa riunione, incarca custu ligàmene: {{url}}", - "invitePhone": "Si boles fàghere una connessione telefònica, toca custu: {{number}},,{{conferenceID}}#\n", - "invitePhoneAlternatives": "Ses chirchende unu nùmeru diferente?\nControlla is nùmeros de telèfonu de sa riunione: {{url}}\n\n\nSi ses giai mutende tràmite unu telèfonu de sa riunione, intra sena ti connètere a s'àudio: {{silentUrl}}", - "inviteURLFirstPartGeneral": "Tenes un'invitu pro intrare in una riunione.", - "inviteURLFirstPartPersonal": "{{name}} t'at invitadu a sa riunione.\n", - "inviteURLSecondPart": "\nIntra in sa riunione:\n{{url}}\n", - "liveStreamURL": "Trasmissione in direta:", - "moreNumbers": "Àteros nùmeros", - "noNumbers": "Perunu nùmeru de mutire.", - "noPassword": "Perunu", - "noRoom": "No as ispetzificadu peruna sala de mutire.", - "numbers": "Nùmeros de mutire", - "password": "$t(lockRoomPasswordUppercase):", - "title": "Cumpartzi", - "tooltip": "Imbia su ligàmene e is nùmeros de telèfonu de custa riunione", - "label": "Informatziones de sa riunione" - }, - "inviteDialog": { - "alertText": "Faddina in s'invitu de àtera gente.", - "header": "Invita", - "searchCallOnlyPlaceholder": "Inserta·nche unu nùmeru de telèfonu", - "searchPeopleOnlyPlaceholder": "Chirca gente", - "searchPlaceholder": "Partetzipante o nùmeru de telèfonu", - "send": "Imbia" - }, - "inlineDialogFailure": { - "msg": "Bi amus postu unu pagu.", - "retry": "Torra·bi a proare", - "support": "Agiudu", - "supportMsg": "Si custu sighit a sutzèdere, nara·si·ddu a" - }, - "keyboardShortcuts": { - "focusLocal": "Ammustra su vìdeu tuo", - "focusRemote": "Ammustra su vìdeu de s'àtera persone", - "fullScreen": "Visualiza in mannària prena o essi", - "keyboardShortcuts": "Incurtzaduras de tecladu", - "localRecording": "Ammustra o cua controllos de registratzione locale", - "mute": "Pone su micròfonu a sa muda o torra·ddu a ativare", - "pushToTalk": "Incarca pro chistionare", - "raiseHand": "Àrtzia o abassa sa manu", - "showSpeakerStats": "Ammustra istatìsticas de partetzipantes", - "toggleChat": "Aberi o serra sa tzarrada", - "toggleFilmstrip": "Ammustra o cua miniaturas de vìdeu", - "toggleScreensharing": "Cuncàmbia intre càmera e cumpartzidura de ischermu", - "toggleShortcuts": "Ammustra o cua incurtzaduras de tecladu", - "videoMute": "Avia o firma sa càmera tua", - "videoQuality": "Gesti sa calidade de sa mutida" - }, - "liveStreaming": { - "busy": "Semus chirchende de liberare resursas de trasmissione. Torra·bi a proare dae immoe a carchi minutu.", - "busyTitle": "Is trasmitentes sunt ocupados immoe", - "changeSignIn": "Càmbia contos.", - "choose": "Sèbera una trasmissione in direta", - "chooseCTA": "Sèbera un'optzione pro sa trasmissione. Autenticatzione che a {{email}}.", - "enterStreamKey": "Inserta inoghe sa crae tua pro sa trasmissione in direta de YouTube.", - "error": "Faddina in sa trasmissione in direta. Torra·bi a proare.", - "errorAPI": "Faddina in s'atzessu a is trasmissiones tuas de Youtube. Torra·bi a proare.", - "errorLiveStreamNotEnabled": "Sa trasmissione in direta no est ativa in {{email}}. Ativa sa trasmissione in direta o autèntica·ti in unu contu chi tèngiat ativa sa trasmissione in direta.", - "expandedOff": "Trasmissione in direta firmada", - "expandedOn": "Custa riunione est trasmìtida in direta in YouTube.", - "expandedPending": "Trasmissione in direta aviada...", - "failedToStart": "Faddina in s'aviu de sa trasmissione in direta", - "getStreamKeyManually": "No amus pòdidu retzire peruna trasmissione in direta. Chirca de otènnere sa crae de YouTube tua pro is trasmissiones in idreta.", - "invalidStreamKey": "Sa crae pro is trasmissiones in direta podet èssere iscurreta.", - "off": "Trasmissione in direta firmada", - "offBy": "{{name}} at firmadu sa trasmissione in direta", - "on": "Trasmissione in direta", - "onBy": "{{name}} at aviadu sa trasmissione in direta", - "pending": "Aviende sa trasmissione in direta...", - "serviceName": "Servìtziu de trasmissione in direta", - "signedInAs": "Autenticatzione cun:", - "signIn": "Autèntica·ti cun Google", - "signInCTA": "Autèntica·ti o inserta sa crae tua pro sa trasmissione in direta de YouTube.", - "signOut": "Essi", - "start": "Avia sa trasmissione in direta", - "streamIdHelp": "It'est custu?", - "unavailableTitle": "Sa trasmissione in direta no est a disponimentu", - "googlePrivacyPolicy": "Polìtica de riservadesa de Google", - "youtubeTerms": "Cunditziones de servìtziu de YouTube" - }, - "localRecording": { - "clientState": { - "off": "Disativada", - "on": "Ativa", - "unknown": "Disconnota" - }, - "dialogTitle": "Controllos de registratzione locale", - "duration": "Durada", - "durationNA": "Non a disponimentu", - "encoding": "Codìfica", - "label": "Registr. locale", - "labelToolTip": "Sa registratzione in locale est funtzionende", - "localRecording": "Registratzione in locale", - "me": "Deo", - "messages": { - "engaged": "Sa registratzione in locale est funtzionende.", - "finished": "Acabada sa registratzione de sessione {{token}}. Imbia s'archìviu registradu a sa persone chi mòderat.", - "finishedModerator": "Acabada sa registratzione de sessione {{token}}. Registratzione locale sarvada. Dimanda a su restu de su grupu de imbiare is registratziones.", - "notModerator": "No ses moderadore. Non podes aviare o firmare registratziones in locale." - }, - "moderator": "Moderadore", - "no": "Nono", - "participant": "Partetzipante", - "participantStats": "Istatìsticas de partetzipantes", - "sessionToken": "Còdighe de sessione", - "start": "Avia sa registratzione", - "stop": "Firma sa registratzione", - "yes": "Eja" - }, - "lockRoomPassword": "crae", - "lockRoomPasswordUppercase": "Crae", - "me": "deo", - "notify": { - "connectedOneMember": "{{name}} at aderidu a sa riunione", - "connectedThreePlusMembers": "{{name}} è ateras {{count}} persones ant aderidu a sa riunione", - "connectedTwoMembers": "{{first}} e {{second}} ant aderidu a sa riunione", - "disconnected": "disconnètidu", - "focus": "Focus de sa cunferèntzia", - "focusFail": "{{component}} no est a disponimentu - torra·bi a proare in {{ms}} seg", - "grantedTo": "Permissos pro sa moderatzione cuntzèdidos a {{to}}.", - "invitedOneMember": "Invitu imbiadu a {{name}}", - "invitedThreePlusMembers": "Invitu imbiadu a {{name}} e àteras {{count}} persones", - "invitedTwoMembers": "Invitu imbiadu a {{first}} e {{second}}", - "kickParticipant": "{{kicker}} at bogadu a {{kicked}}", - "me": "Deo", - "moderator": "As donadu permissos pro sa moderatzione.", - "muted": "As cumintzadu una tzarrada a sa muda.", - "mutedTitle": "Ses a sa muda.", - "mutedRemotelyTitle": "{{participantDisplayName}} t'at postu a sa muda.", - "mutedRemotelyDescription": "Podes torrare a aviare s'àudio cando depas chistionare. Torra a sa muda cando as acabadu pro evitare remore in sa riunione.", - "passwordRemovedRemotely": "Un'utente at bogadu $t(lockRoomPasswordUppercase)", - "passwordSetRemotely": "Un'utente at cunfiguradu $t(lockRoomPasswordUppercase)", - "raisedHand": "{{name}} bolet chistionare.", - "somebody": "Calicunu", - "startSilentTitle": "Ses intradu sena àudio.", - "startSilentDescription": "Torra a intrare pro ativare s'àudio", - "suboptimalBrowserWarning": "Timimus chi s'esperièntzia tua de custa riunione no at a èssere bona meda. Semus chirchende de megiorare custu, però in su mentras proa de impreare unu de is <a href='static/recommendedBrowsers.html' target='_blank'>navigadores cumpatìbiles</a>.", - "suboptimalExperienceTitle": "Avisu subra de su navigadore", - "unmute": "Ativa su sonu", - "newDeviceCameraTitle": "Càmera noa rilevada", - "newDeviceAudioTitle": "Dispositivu de àudio nou rilevadu", - "newDeviceAction": "Imprea" - }, - "passwordSetRemotely": "cunfiguradu dae un'àtera persone", - "passwordDigitsOnly": "Finas a {{number}} tzifras", - "poweredby": "de", - "presenceStatus": { - "busy": "No a disponimentu", - "calling": "Mutende...", - "connected": "Connessione istabilida", - "connecting": "Connetende...", - "connecting2": "Connetende*...", - "disconnected": "Disconnètidu", - "expired": "Iscadidu", - "ignored": "Ignoradu", - "initializingCall": "Aviende sa mutida...", - "invited": "Invitadu", - "rejected": "Refudadu", - "ringing": "Sonende..." - }, - "profile": { - "setDisplayNameLabel": "Cunfigura su nòmine visìbile tuo", - "setEmailInput": "Inserta posta eletrònica", - "setEmailLabel": "Cunfigura indiritzu eletrònicu de Gravatar", - "title": "Profilu" - }, - "raisedHand": "Bògio chistionare", - "recording": { - "authDropboxText": "Càrriga a Dropbox", - "availableSpace": "Ispàtziu a disponimentu: {{spaceLeft}} MB (prus o mancu {{duration}} minutos de registratzione)", - "beta": "BETA", - "busy": "Semus traballende pro liberare resursas de registratzione. Torra·bi a proare dae immoe a carchi minutu.", - "busyTitle": "Totu is registradores sunt ocupados", - "error": "Faddina in sa registratzione. Torra·bi a proare.", - "expandedOff": "Registratzione firmada", - "expandedOn": "Registrende sa riunione.", - "expandedPending": "Aviende sa registratzione...", - "failedToStart": "Faddina in s'aviu de sa registratzione", - "fileSharingdescription": "Cumpartzi sa registratzione cun is partetzipantes de sa riunione", - "live": "IN DIRETA", - "loggedIn": "Autenticatzione: {{userName}}", - "off": "Registratzione firmada", - "offBy": "{{name}} at firmadu sa registratzione", - "on": "Registrende", - "onBy": "{{name}} at aviadu sa registratzione", - "pending": "Preparende pro registrare sa riunione...", - "rec": "REG", - "serviceDescription": "Sa registratzione at a èssere sarvada dae su servìtziu de registratzione", - "serviceName": "Servìtziu de registratzione", - "signIn": "Identìfica·ti", - "signOut": "Essi", - "unavailable": "{{serviceName}} no est a disponimentu. Semus traballende pro acontzare su problema. Torra·bi a proare a pustis.", - "unavailableTitle": "Sa registratzione no est a disponimentu" - }, - "sectionList": { - "pullToRefresh": "Ispinghe pro atualizare" - }, - "settings": { - "calendar": { - "about": "S'integratzione cun su calendàriu {{appName}} est impreada pro atzèdere in manera segura a su calendàriu tuo pro chi potzat lèghere is eventos imbenientes.", - "disconnect": "Disconnete", - "microsoftSignIn": "Autèntica·ti cun Microsoft", - "signedIn": "Ses atzedende a is eventos de calendàriu pro {{email}}. Incarca su butone Disconnete in bàsciu pro firmare s'atzessu a eventos de calendàriu.", - "title": "Calendàriu" - }, - "devices": "Dispositivos", - "followMe": "Totus mi sighint", - "language": "Limba", - "loggedIn": "Autenticatzione: {{name}}", - "moderator": "Moderadore", - "more": "Àteru", - "name": "Nòmine", - "noDevice": "Perunu", - "selectAudioOutput": "Essida de àudio", - "selectCamera": "Càmera", - "selectMic": "Micròfonu", - "startAudioMuted": "Totus cumintzant a sa muda", - "startVideoMuted": "Totus cumintzant a sa cua", - "title": "Cunfiguratzione", - "speakers": "Altoparlantes", - "microphones": "Micròfonos" - }, - "settingsView": { - "advanced": "Avantzadas", - "alertOk": "AB", - "alertTitle": "Atentzione", - "alertURLText": "Custu URL no est vàlidu", - "buildInfoSection": "Informatzione de sa versione", - "conferenceSection": "Cunferèntzia", - "disableCallIntegration": "Disativa s'integratzione de mutidas nativas", - "disableP2P": "Disativa sa modalidade a nodu terminale (p2p)", - "displayName": "Nòmine visìbile", - "email": "Indiritzu eletrònicu", - "header": "Cunfiguratzione", - "profileSection": "Profilu", - "serverURL": "URL de su servidore", - "showAdvanced": "Ammustra cunfiguratziones avantzadas", - "startWithAudioMuted": "Cumintza cun s'àudio a sa muda", - "startWithVideoMuted": "Cumintza cun su vìdeu disativadu", - "version": "Versione" - }, - "share": { - "dialInfoText": "\n\n=====\n\nBoles isceti ascurtare sa cunferèntzia dae su telèfonu?\n\n{{defaultDialInNumber}}Incarca custu ligàmene pro bìdere is nùmeros de telèfonu de custa riunione\n{{dialInfoPageUrl}}\"", - "mainText": "Incarca custu ligàmene pro intrare a sa riunione:\n{{roomUrl}}" - }, - "speaker": "Altoparlante", - "speakerStats": { - "hours": "{{count}} h", - "minutes": "{{count}} min", - "name": "Nòmine", - "seconds": "{{count}} seg", - "speakerStats": "Istatìsticas de partetzipante", - "speakerTime": "Tempus de partetzipante" - }, - "startupoverlay": { - "title": "{{app}} tenet bisòngiu de impreare sa càmera e su micròfonu tuos.", - "policyText": " " - }, - "suspendedoverlay": { - "rejoinKeyTitle": "Torra a intrare", - "text": "Incarca su butone <i>Torra a intrare</i> pro torrare a connètere.", - "title": "S'elaboradore est andadu a riposu e custu at firmadu sa mutida de vìdeu." - }, - "toolbar": { - "accessibilityLabel": { - "audioOnly": "Càmbia àudio isceti", - "audioRoute": "Sèbera su dispositivu de àudio", - "callQuality": "Gesti sa calidade de su vìdeu", - "cc": "Càmbia s'istadu de is sutatìtulos", - "chat": "Càmbia ventana de tzarrada", - "document": "Càmbia documentu cumpartzidu", - "download": "Iscàrriga is aplicatziones nostras", - "feedback": "Lassa cummentos", - "fullScreen": "Ativa o disativa ischermu in mannària prena", - "hangup": "Lassa sa mutida", - "help": "Agiudu", - "invite": "Invita gente", - "kick": "Boga partetzipante", - "localRecording": "Ativa o disativa is controllos de registratzione in locale", - "lockRoom": "Ativa o disativa crae de riunione", - "moreActions": "Càmbia su menù de atziones additzionales", - "moreActionsMenu": "Menù de atziones additzionales", - "moreOptions": "Ammustra àteras optziones", - "mute": "Ativa o disativa su silèntziu de s'àudio", - "muteEveryone": "Pone totus a sa muda", - "pip": "Ativa o disativa sa modalidade immàgine in immàgine", - "privateMessage": "Imbia messàgiu de testu privadu", - "profile": "Modìfica su profilu", - "raiseHand": "Àrtzia o abassa sa manu", - "recording": "Ativa o disativa sa registratzione", - "remoteMute": "Pone partetzipante a sa muda", - "Settings": "Càmbia sa cunfiguratzione", - "sharedvideo": "Ativa o disativa sa cumpartzidura de vìdeos de YouTube", - "shareRoom": "Invita una persone", - "shareYourScreen": "Ativa o disativa sa cumpartzidura de ischermu", - "shortcuts": "Ativa o disativa incurtzaduras", - "show": "Ammustra in s'iscena", - "speakerStats": "Càmbia istatìsticas de partetzipante", - "tileView": "Càmbia a visualizatzione in mosàicu", - "toggleCamera": "Càmbia càmera", - "videomute": "Ativa o disativa su vìdeu", - "videoblur": "Ativa o disativa isfocadu" - }, - "addPeople": "Agiunghe gente a sa mutida", - "audioOnlyOff": "Disativa modalidade de àmpiu de banda bàsciu", - "audioOnlyOn": "Ativa modalidade de àmpiu de banda bàsciu", - "audioRoute": "Sèbera su dispositivu de àudio", - "authenticate": "Autentica·ti", - "callQuality": "Gesti sa calidade de su vìdeu", - "chat": "Aberi o serra sa tzarrada", - "closeChat": "Serra sa tzarrada", - "documentClose": "Serra su documentu cumpartzidu", - "documentOpen": "Aberi su documentu cumpartzidu", - "download": "Iscàrriga is aplicatziones nostras", - "enterFullScreen": "Ammustra in mannària prena", - "enterTileView": "Intra in visualizatzione in mosàicu", - "exitFullScreen": "Essi de ischermu in mannària prena", - "exitTileView": "Essi de sa visualizatzione in mosàicu", - "feedback": "Lassa cummentos", - "hangup": "Essi", - "help": "Agiudu", - "invite": "Invita gente", - "login": "Intra", - "logout": "Essi", - "lowerYourHand": "Abassa sa manu", - "moreActions": "Àteras atziones", - "moreOptions": "Àteras optziones", - "mute": "Ativa o disativa s'àudio", - "muteEveryone": "Pone totus a sa muda", - "noAudioSignalTitle": "Perunu sinnale dae su micròfonu tuo.", - "noAudioSignalDesc": "Si no dd'as postu a sa muda dae sa cunfiguratzione de sistema o dae su dispositivu, forsis depes cambiare dispositivu.", - "noAudioSignalDescSuggestion": "Si no dd'as postu a sa muda dae sa cunfiguratzione de sistema o dae su dispositivu, forsis depes cambiare a su dispositivu cussigiadu.", - "noAudioSignalDialInDesc": "Podes fintzas intrare cun una mutida:", - "noAudioSignalDialInLinkDesc": "Nùmeros de mutida", - "noisyAudioInputTitle": "Su micròfonu tuo faghet remore.", - "noisyAudioInputDesc": "Su micròfonu tuo faghet remore, forsis ti depes pònnere a sa muda o depes cambiare dispositivu.", - "openChat": "Aberi sa tzarrada", - "pip": "Intra in modalidade immàgine in immàgine", - "privateMessage": "Imbia messàgiu de testu privadu", - "profile": "Modìfica su profilu", - "raiseHand": "Àrtzia o abassa sa manu", - "raiseYourHand": "Àrtzia sa manu", - "Settings": "Cunfiguratzione", - "sharedvideo": "Cumpartzi unu vìdeu de YouTube", - "shareRoom": "Invita una persone", - "shortcuts": "Ammustra incurtzaduras", - "speakerStats": "Istatìsticas de partetzipante", - "startScreenSharing": "Avia sa cumpartzidura de s'ischermu", - "startSubtitles": "Avia sutatìtulos", - "stopScreenSharing": "Firma sa cumpartzidura de s'ischermu", - "stopSubtitles": "Firma sutatìtulos", - "stopSharedVideo": "Firma vìdeu de YouTube", - "talkWhileMutedPopup": "Ses chirchende de chistionare? Ses a sa muda.", - "tileViewToggle": "Càmbia a visualizatzione in mosàicu", - "toggleCamera": "Càmbia càmera", - "videomute": "Avia o firma sa càmera", - "startvideoblur": "Isfoca s'isfundu meu", - "stopvideoblur": "Disativa s'isfocadu de s'isfundu" - }, - "transcribing": { - "ccButtonTooltip": "Avia o firma sutatìtulos", - "error": "Faddina in sa trascritzione. Torra·bi a proare.", - "expandedLabel": "Trascritzione ativada", - "failedToStart": "Faddina in s'aviu de sa trascritzione", - "labelToolTip": "Trascriende sa riunione", - "off": "Trascritzione firmada", - "pending": "Preparende pro trascrìere sa riunione...", - "start": "Cumintza a ammustrare sutatìtulos", - "stop": "No ammustres prus sutatìtluos", - "tr": "TR" - }, - "userMedia": { - "androidGrantPermissions": "Sèbera <b><i>Permite</i></b> cando su navigadore ti dimandet permissos.", - "chromeGrantPermissions": "Sèbera <b><i>Permite</i></b> cando su navigadore ti dimandet permissos.", - "edgeGrantPermissions": "Sèbera <b><i>Eja</i></b> cando su navigadore ti dimandet permissos.", - "electronGrantPermissions": "Cuntzede permissos pro atzèdere a sa càmera e a su micròfonu tuos", - "firefoxGrantPermissions": "Sèbera <b><i>Cumpartzi dispositivos seletzionados</i></b> cando su navigadore ti dimandet permissos.", - "iexplorerGrantPermissions": "Sèbera <b><i>AB</i></b> cando su navigadore ti dimandet permissos.", - "nwjsGrantPermissions": "Cuntzede permissos pro atzèdere a sa càmera e a su micròfonu tuos", - "operaGrantPermissions": "Sèbera <b><i>Permite</i></b> cando su navigadore ti dimandet permissos.", - "react-nativeGrantPermissions": "Sèbera <b><i>Permite</i></b> cando su navigadore ti dimandet permissos.", - "safariGrantPermissions": "Sèbera <b><i>AB</i></b> cando su navigadore ti dimandet permissos." - }, - "videoSIPGW": { - "busy": "Semus traballende pro liberare resursas. Torra·bi a proare dae immoe a carchi minutu.", - "busyTitle": "Su servìtziu Room est ocupadu", - "errorAlreadyInvited": "Invitu a {{displayName}} giai imbiadu", - "errorInvite": "Sa connessione no est istada istabilida. Torra·bi a proare a pustis.", - "errorInviteFailed": "Semus traballende pro acontzare su problema. Torra·bi a proare a pustis.", - "errorInviteFailedTitle": "Faddina in s'invitu de {{displayName}}", - "errorInviteTitle": "Faddina in s'aposentu de invitos", - "pending": "Invitu a {{displayName}} imbiadu" - }, - "videoStatus": { - "audioOnly": "AUD", - "audioOnlyExpanded": "Ses in modalidade de àmpiu de banda bàsciu. In custa modalidade isceti su ritzevimentu de àudio e de cumpartzidura de ischermu sunt a disponimentu.", - "callQuality": "Calidade de su vìdeu", - "hd": "HD", - "hdTooltip": "Vìdeu in arta definitzione (HD)", - "highDefinition": "Arta definitzione (HD)", - "labelTooiltipNoVideo": "Sena vìdeu", - "labelTooltipAudioOnly": "Modalidade de àmpiu de banda bàsciu ativada", - "ld": "LD", - "ldTooltip": "Vìdeu in definitzione bàscia (LD)", - "lowDefinition": "Definitzione bàscia (LD)", - "onlyAudioAvailable": "Isceti àudio a disponimentu", - "onlyAudioSupported": "Custu navigadore est isceti cumpatìbile cun s'àudio.", - "p2pEnabled": "Rete a nodu terminale (p2p) ativada", - "p2pVideoQualityDescription": "In sa modalidade a nodu terminale (p2p), sa calidade de vìdeu retzida podet èssere cambiada intre arta calidade e isceti àudio. Depes essire de sa modalidade a nodu terminale pro pòdere cunfigurare àteras optziones.", - "recHighDefinitionOnly": "S'arta definitzione (HD) at a èssere preferida.", - "sd": "SD", - "sdTooltip": "Vìdeu in definitzione istandard (SD)", - "standardDefinition": "Definitzione istàndard (SD)" - }, - "videothumbnail": { - "domute": "A sa muda", - "domuteOthers": "Pone totus a sa muda", - "flip": "Fùrria", - "kick": "Boga", - "moderator": "Moderadore", - "mute": "Partetzipante a sa muda", - "muted": "A sa muda", - "remoteControl": "Avia o firma su controllu remotu", - "show": "Ammustra in s'iscena", - "videomute": "Custa persone at firmadu sa càmera" - }, - "welcomepage": { - "accessibilityLabel": { - "join": "Toca pro intrare", - "roomname": "Inserta su nòmine de s'aposentu" - }, - "appDescription": "Bae, tzarrada de vìdeu cun totu s'iscuadra. Difatis, podes invitare totu sa gente chi connosches. {{app}} est un'aplicatzione de vìdeu-cunferèntzia de còdighe abertu 100% cun critografia cumpleta chi podes impreare cada die, totu sa die, de badas — sena perunu contu creadu.", - "audioVideoSwitch": { - "audio": "Boghe", - "video": "Vìdeu" - }, - "calendar": "Calendàriu", - "connectCalendarButton": "Connete a su calendàriu tuo", - "connectCalendarText": "Connete a su calendàriu tuo pro bìdere totu is riuniones tuas in {{app}}. In prus, agiunghe riuniones de {{provider}} a su calendàriu tuo e avia·ddas cun unu clic.", - "enterRoomTitle": "Cumintza una riunione noa", - "roomNameAllowedChars": "Su nòmine de sa riunione non podet inclùdere custos caràteres: ?, &, :, ', \", %, #.", - "go": "BAE", - "goSmall": "BAE", - "join": "CREA / INTRA", - "info": "Informatziones", - "privacy": "Riservadesa", - "recentList": "Reghentes", - "recentListDelete": "Cantzella", - "recentListEmpty": "Sa lista de reghentes est bòida. Tzarra cun s'iscuadra tua e as a agatare totu is riuniones reghentes tuas inoghe.", - "reducedUIText": "Ti donamus su benebènnidu a {{app}}!", - "roomname": "Inserta su nòmine de s'aposentu", - "roomnameHint": "Inserta su nòmine o s'URL de s'aposentu a su chi boles intrare. Ti podes imbentare unu nòmine, bastat chi ddu fatzas ischire a sa gente chi ses addobiende pro chi ddu potzant insertare su pròpiu.", - "sendFeedback": "Imbia cummentos", - "terms": "Cunditziones", - "title": "Vìdeu-cunferèntzia segura, prena de funtzionalidades, lìbera e de badas", - "getHelp": "Agiudu" - }, - "lonelyMeetingExperience": { - "button": "Invita gente", - "youAreAlone": "Ses a sa sola in custa riunione" - }, - "helpView": { - "header": "Tzentru de agiudu" - } -} diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-sk.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-sk.json deleted file mode 100644 index 1a53771dd..000000000 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-sk.json +++ /dev/null @@ -1,773 +0,0 @@ -{ - "addPeople": { - "add": "Pozvať", - "countryNotSupported": "Zatiaľ nepodporujeme túto krajinu.", - "countryReminder": "Medzinárodný hovor? Prosím skontrolujte, či telefónne číslo začína smerovým číslo krajiny.", - "disabled": "Nemôžete pozvať ďalších účastníkov.", - "failedToAdd": "Nepodarilo sa pridať účastníka.", - "footerText": "Odchádzajúce hovory sú zablokované.", - "loading": "Hľadanie účastníkov a telefónnych čísiel", - "loadingNumber": "Kontrola telefónneho čísla", - "loadingPeople": "Hľadanie účastníkov na pozvanie", - "noResults": "Žiadne výsledky hľadania", - "noValidNumbers": "Prosím zadajte telefónne číslo", - "searchNumbers": "Zadajte telefónne čísla", - "searchPeople": "Hľadanie účastníkov", - "searchPeopleAndNumbers": "Hľadanie účastníkov alebo pridávanie telefónny čísel", - "telephone": "Telefón: {{number}}", - "title": "Pozvať účastníkov do tejto konferencie" - }, - "audioDevices": { - "bluetooth": "Bluetooth", - "headphones": "Sluchátka", - "phone": "Telefón", - "speaker": "Rečník", - "none": "Žiadne zvukové zariadenia" - }, - "audioOnly": { - "audioOnly": "Iba zvuk" - }, - "calendarSync": { - "addMeetingURL": "Pridať odkaz na stretnutie", - "confirmAddLink": "Chcete pridal Jitsi odkaz do tejto udalosti?", - "error": { - "appConfiguration": "Integrácia s kalendárom nie je správne nastavená.", - "generic": "Stala sa chyba. Skontrolujte si nastavenia kalendáru a skúste aktualizovať kalendár. ", - "notSignedIn": "Stala sa chyba počas autentifikácie pre zobrazovanie kaledárových udalosti. Skontrolujte si nastavenia kalendáru a skúste sa znovu prihlásiť." - }, - "join": "Zúčastniť sa", - "joinTooltip": "Zúčastniť sa stretnutia", - "nextMeeting": "nasledujúce stretnutie", - "noEvents": "Niesú naplánované žiadne ďalšie udalosti.", - "ongoingMeeting": "prebiehajúce stretnutie", - "permissionButton": "Otvoriť nastavenia", - "permissionMessage": "Aplikácia potrebuje kalendárové oprávnenie pre zobranie termínov a stretnutí ", - "refresh": "Aktualizovať kalendár", - "today": "Dnes" - }, - "chat": { - "error": "Chyba: vaša správa \"{{originalText}}\" nebola poslaná. Dôvod: {{error}}", - "fieldPlaceHolder": "Zadajte sem vašu správu", - "messagebox": "Napíšte správu", - "messageTo": "Správa pre {{recipient}}", - "noMessagesMessage": "V tejto konferencií ešte nie je žiadna správa. Začnite tu vašu diskusiu!", - "nickname": { - "popover": "Zvoľte meno", - "title": "Zadajte sem vašu prezývku" - }, - "privateNotice": "Súkromná správa pre {{recipient}}", - "title": "Písanie", - "you": "Vy" - }, - "chromeExtensionBanner": { - "installExtensionText": "Nainštalujte rozšírenie pre integráciu s Google Calendar a Office 365", - "buttonText": "Inštalovať Chrome rozšírenie", - "dontShowAgain": "Upozornenie viac nezobrazovať" - }, - "connectingOverlay": { - "joiningRoom": "Vytvára sa spojenie do vašej konferencie…" - }, - "connection": { - "ATTACHED": "Priložený", - "AUTHENTICATING": "Overujem", - "AUTHFAIL": "Overenie zlyhalo", - "CONNECTED": "Pripojený", - "CONNECTING": "Pripájam", - "CONNFAIL": "Spojenie zlyhalo", - "DISCONNECTED": "Odpojený", - "DISCONNECTING": "Odpájam", - "ERROR": "Chyba", - "RECONNECTING": "Chyba siete. Skúšam sa znova pripojiť ...", - "LOW_BANDWIDTH": "Video pre {{displayName}} bolo vypnuté, aby sa ušetrila prenosová kapacita" - }, - "connectionindicator": { - "address": "Adresa:", - "bandwidth": "Predpokladaný dat. tok:", - "bitrate": "Prenos. rýchlosť", - "bridgeCount": "Počet serverov:", - "connectedTo": "Spojenie s:", - "e2e_rtt": "E2E RTT:", - "framerate": "Rýchlosť snímkovania:", - "less": "Zobraz menej", - "localaddress_0": "Lokálna adresa:", - "localaddress_1": "Lokálne adresy:", - "localaddress_2": "", - "localport_0": "Lokálny port:", - "localport_1": "Lokálne porty:", - "localport_2": "", - "more": "Zobraz viac", - "packetloss": "Strata packetov:", - "quality": { - "good": "Dobré", - "inactive": "Neaktívne", - "lost": "Stratené", - "nonoptimal": "Nie je optimálne", - "poor": "Slabé" - }, - "remoteaddress_0": "Vzdialená adresa:", - "remoteaddress_1": "Vzdialené adresy:", - "remoteaddress_2": "", - "remoteport_0": "Vzdialený port:", - "remoteport_1": "Vzdialené porty:", - "remoteport_2": "", - "resolution": "Rozlíšenie:", - "status": "Spojenie:", - "transport": "Prenos:" - }, - "dateUtils": { - "earlier": "Skôr", - "today": "Dnes", - "yesterday": "Včera" - }, - "deepLinking": { - "appNotInstalled": "Potrebujete aplikáciu {{app}}, aby ste sa mohli pripojiť do tejto konferencie na vašom telefóne.", - "description": "Nič sa nestalo? Snažili sme sa otvoriť konferenciu v {{app}}. Skúste to znovu, alebo sa pripojte na konferenciu v {{app}} cez Web.", - "descriptionWithoutWeb": "Nič sa nestalo? Snažili sme sa spustiť váš rozhovor v desktopovej aplikácií {{app}}.", - "downloadApp": "Stiahnutie aplikácie", - "launchWebButton": "Otvoriť na webe", - "openApp": "Pokračovať na aplikáciu", - "title": "Konferencia sa otvára v {{app}}...", - "tryAgainButton": "Skúsiť znova s natívnou aplikáciou" - }, - "defaultLink": "napr. {{url}}", - "defaultNickname": "napr. Jane Pink", - "deviceError": { - "cameraError": "Chyba pri prístupe ku kamere", - "cameraPermission": "Aplikácia nemá oprávnenie pristupovať ku kamere", - "microphoneError": "Chyba pri prístupe k mikrofónu", - "microphonePermission": "Aplikácia nemá oprávnenie pristupovať k mikrofónu" - }, - "deviceSelection": { - "noPermission": "Oprávnenie nie je poskytnuté", - "previewUnavailable": "Náhľad nie je dostupný", - "selectADevice": "Vyberte zvukové zariadenie", - "testAudio": "Vyskúšať zvuk" - }, - "dialog": { - "accessibilityLabel": { - "liveStreaming": "Živé vysielanie" - }, - "allow": "Povoliť", - "alreadySharedVideoMsg": "Iný účastník už poskytuje video. Pri tejto konferencií môže poskytovať súčasne iba jeden účastník.", - "alreadySharedVideoTitle": "Naraz sa dá poskytovať iba jedno video", - "applicationWindow": "Okno aplikácie", - "Back": "Späť", - "cameraConstraintFailedError": "Vaša kamera nespĺňa potrebné požiadavky.", - "cameraNotFoundError": "Kamera nebola nájdená.", - "cameraNotSendingData": "Kamera nie je dostupná. Skontrolujte či iná aplikácia používa kameru, vyberte inú kameru v nastaveniach ale znovu spustite aplikáciu.", - "cameraNotSendingDataTitle": "Prístup na kameru nie je možný.", - "cameraPermissionDeniedError": "Nebolo udelené oprávnenie používať kameru. Napriek tomu sa môže zúčastniť na konferencií, ale ostatný účastníci vás nebudu vidieť. Pre pridelenie oprávnenia môžete použiť ikonu kamery na adresnej lište.", - "cameraUnknownError": "Z neznámeho dôvodu sa kamera nedá použiť.", - "cameraUnsupportedResolutionError": "Táto kamera nepodporuje požadované rozlíšenie.", - "Cancel": "Zrušiť", - "close": "Zatvoriť", - "conferenceDisconnectMsg": "Skontrolujte prípadne vaše sieťové pripojenie. Pripájam znovu o {{seconds}} sekúnd...", - "conferenceDisconnectTitle": "Vaše spojenie bolo prerušené.", - "conferenceReloadMsg": "Snažíme sa to napraviť. Pripájam znovu o {{seconds}} sekund...", - "conferenceReloadTitle": "Žiaľ niečo sa nepodarilo.", - "confirm": "Potvrdiť", - "confirmNo": "Nie", - "confirmYes": "Áno", - "connectError": "Oops! Niečo je zle a nemôžem sa pripojiť do konferencie.", - "connectErrorWithMsg": "Oops! Niečo je zle a nemôžem sa pripojiť do konferencie. Správa: {{msg}}", - "connecting": "Pripájam", - "contactSupport": "Spojiť sa s podporou", - "copy": "Kopírovať", - "dismiss": "Zavrieť", - "displayNameRequired": "Ahoj! Ako sa voláš?", - "done": "Hotovo", - "enterDisplayName": "Prosím zadajte sem vaše meno", - "error": "Chyba", - "externalInstallationMsg": "Zlyhanie pri inštalácií rozšírenia pre zdieľanie prac. plochy", - "externalInstallationTitle": "Potrebné rozšírenie:", - "goToStore": "", - "gracefulShutdown": "Naša služba je momentálne vypnutá pre údržbu. Skúste to neskor.", - "IamHost": "Ja som hostiteľ", - "incorrectRoomLockPassword": "Nesprávne heslo", - "incorrectPassword": "Používateľské meno alebo heslo je nesprávne", - "inlineInstallationMsg": "Musí byť nainštalované rozšírenie pre zdieľanie pracovnej prochy.", - "inlineInstallExtension": "Teraz inštalovať", - "internalError": "Ups! Niečo nefunguje. Vyskytla sa nasledujúca chyba: {{error}}", - "internalErrorTitle": "Interná chyba", - "kickMessage": "Pre podrobnosti sa môžete spojiť s {{participantDisplayName}}.", - "kickParticipantButton": "Odstrániť", - "kickParticipantDialog": "Skutočne chcete odstrániť tohto účastnika?", - "kickParticipantTitle": "Odstrániť účastníka?", - "kickTitle": "Ouch! {{participantDisplayName}} vás odstránil zo stretnutia.", - "liveStreaming": "Živé vysielanie", - "liveStreamingDisabledForGuestTooltip": "Hostia nemôžu začať živé vysielanie.", - "liveStreamingDisabledTooltip": "Štartovanie živého vysielania je vypnuté.", - "lockMessage": "Zlyhanie pri pokuse o zabezpečenie konferencie.", - "lockRoom": "Pridať stretnutie $t(lockRoomPasswordUppercase)", - "lockTitle": "Zabezpečenie zlyhalo", - "logoutQuestion": "Ste si istý, že sa chcete odhlásiť a skončiť konferenciu?", - "logoutTitle": "Odhlásiť", - "maxUsersLimitReached": "Bol dosiahnutý maximálny počet účastníkov. Konferencia je plná. Spojte sa prosím s organizátorom stretnutia, alebo to skúste neskôr.", - "maxUsersLimitReachedTitle": "Dosiahnutý maximálny počet účastníkov", - "micConstraintFailedError": "Váš mikrofón nespĺňa potrebné požiadavky.", - "micNotFoundError": "Mikrofón nebol nájdený.", - "micNotSendingData": "Choďte do nastavení vašeho počítača, aby ste odblokovali stlmenie vášho mikrofónu a upravte jeho úroveň.", - "micNotSendingDataTitle": "Mikrofón je stlmený vašimi systémovými nastaveniami.", - "micPermissionDeniedError": "Nebolo udelené oprávnenie používať mikrofón. Napriek tomu sa môže zúčastniť na konferencií, ale ostatný účastníci vás nebudú počuť. Pre pridelenie oprávnenia môžete použiť ikonu kamery na adresnej lište.", - "micUnknownError": "Mikrofón sa nedá použiť z neznámeho dôvodu.", - "muteEveryoneElseDialog": "Keď všetkým vypnete mikrofón, nedokážete spať zapnuť mikrofóny. Účastníci si ale môžu zapnúť mikrofóny sami.", - "muteEveryoneElseTitle": "Vypnúť mikrofón všetkým okrem {{whom}}?", - "muteEveryoneDialog": "Chcete naozaj všetkým vypnúť mikrofón. Keď všetkým vypnete mikrofón, nedokážete spať zapnúť mikrofóny. Účastníci si ale môžu zapnúť mikrofóny sami.", - "muteEveryoneTitle": "Všetkým vypnúť mikrofón?", - "muteEveryoneSelf": "seba samého", - "muteEveryoneStartMuted": "Všetci odteraz začínajú s vypnutým mikrofónom", - "muteParticipantBody": "Nedokážete zapnúť vypnuté mikrofóny ostatných účastníkov, ale každý účastník si vie sám zapnúť mikrofón.", - "muteParticipantButton": "Vypnúť mikrofón", - "muteParticipantDialog": "Chcete naozaj tomuto účastníkovi vypnúť mikrofón? Keď vypnete mikrofón, nedokážete späť zapnúť mikrofón tohto účastníka. Účastníci si ale dokážu zapnúť mikrofóny sami.", - "muteParticipantTitle": "Vypnúť účastníkovi mikrofón?", - "Ok": "Ok", - "passwordLabel": "$t(lockRoomPasswordUppercase)", - "passwordNotSupported": "Nastavovanie $t(lockRoomPassword) nie je podporované.", - "passwordNotSupportedTitle": "$t(lockRoomPasswordUppercase) nie je podporované", - "passwordRequired": "$t(lockRoomPasswordUppercase) je potrebné", - "popupError": "Váš prehliadať blokuje vyskakovacie okná tejto stránky. Prosím aktivujte vyskakovacie okná v bezpečnostných nastaveniach vašeho prehliadača a skúste znovu.", - "popupErrorTitle": "Vyskakovacie okná sú zablokované", - "recording": "Nahrávanie", - "recordingDisabledForGuestTooltip": "Hostia nemôžu začať nahrávanie.", - "recordingDisabledTooltip": "Štartovanie nahrávania je vypnuté.", - "rejoinNow": "Teraz sa znovu pridať.", - "remoteControlAllowedMessage": "{{user}} prijal požiadavku o vzdialené ovládanie.", - "remoteControlDeniedMessage": "{{user}} odmietol prijal požiadavku o vzdialené ovládanie.", - "remoteControlErrorMessage": "Stala sa chyba počas žiadania o vzdialené ovládanie od {{user}}", - "remoteControlRequestMessage": "Povolíte {{user}} ovládať vášu pracovnú plochu?", - "remoteControlShareScreenWarning": "Pozor, keď povolíte požiadavku budete zdielať vašu obrazovku!", - "remoteControlStopMessage": "Vzdialené ovládanie bolo ukončené.", - "remoteControlTitle": "Vzdialené ovládanie", - "Remove": "Odstrániť", - "removePassword": "$t(lockRoomPassword) odstránené", - "removeSharedVideoMsg": "Ste si istý že chcete odstrániť zdielané video?", - "removeSharedVideoTitle": "Odstrániť zdielané video", - "reservationError": "Systémová chyba rezervácie", - "reservationErrorMsg": "Chyba: {{code}}, správa: {{msg}}", - "retry": "Skúsiť znovu", - "screenSharingFailedToInstall": "Ups! Nepodarilo sa nainštalovať rozšírenie pre zdieľanie obrazovky.", - "screenSharingFailedToInstallTitle": "Chyba v inštalácii rozšírenie pre zdieľanie obrazovky", - "screenSharingFirefoxPermissionDeniedError": "Niečo sa nepodarilo pri pokuse o zdielanie obrazovky. Skontrolujte prosím či ste dali oprávnenie v prehliadači.", - "screenSharingFirefoxPermissionDeniedTitle": "Nepodarilo sa zdielať obrazovku", - "screenSharingPermissionDeniedError": "Ups! Niečo sa nepodarilo pri žiadaní o oprávnenie zdielať obrazovku. Prosím aktualizovať a skúsiť znovu.", - "sendPrivateMessage": "Dostali ste súkromnú správu. Chceli ste na ňu odpovedať súkromne, alebo chcete poslať správu skupine?", - "sendPrivateMessageCancel": "Poslať skupine", - "sendPrivateMessageOk": "Poslať súkromne", - "sendPrivateMessageTitle": "Súkromne poslať?", - "serviceUnavailable": "Služba nedostupná", - "sessTerminated": "Volanie ukončené", - "Share": "Zdieľať", - "shareVideoLinkError": "Prosím, zadajte správny Youtube odkaz.", - "shareVideoTitle": "Zdielať video", - "shareYourScreen": "Zdielať obrazovku", - "shareYourScreenDisabled": "Zdieľanie obrazovky vypnuté.", - "shareYourScreenDisabledForGuest": "Hostia nemôžu zdielať obrazovku.", - "startLiveStreaming": "Spustiť priamy prenos", - "startRecording": "Začať záznam", - "startRemoteControlErrorMessage": "Chyba pri pokuse o začatie vzdialeného riadenia!", - "stopLiveStreaming": "Prerušiť priamy prenos", - "stopRecording": "Zastaviť záznam", - "stopRecordingWarning": "Chcete zastaviť záznam?", - "stopStreamingWarning": "Chcete prerušiť priamy prenos", - "streamKey": "Klúč živého vysielania", - "Submit": "OK", - "thankYou": "Ďakujeme vám za používanie {{appName}}!", - "token": "token", - "tokenAuthFailed": "Prepáčte, nie ste oprávnený zúčastniť tejto sa konferencie.", - "tokenAuthFailedTitle": "Overenie zlyhalo", - "transcribing": "", - "unlockRoom": "Odstrániť stretnutie $t(lockRoomPassword)", - "userPassword": "užívateľské heslo", - "WaitForHostMsg": "Konferencia <b>{{room}}</b> sa ešte nezačala. Autorizujte sa prosím ak ste hostiteľ. V opačnom prípade čakajte na hostiteľa.", - "WaitForHostMsgWOk": "Konferencia <b>{{room}}</b> sa ešte nezačala. Ak ste hostiteľ autorizujte sa stlačením Ok. V opačnom prípade čakajte na hostiteľa.", - "WaitingForHost": "Čakám na hostiteľa ...", - "Yes": "Áno", - "yourEntireScreen": "Celú obrazovku" - }, - "dialOut": { - "statusMessage": "je teraz {{status}}" - }, - "documentSharing": { - "title": "Zdielaný dokument" - }, - "feedback": { - "average": "Priemerný", - "bad": "Zlý", - "detailsLabel": "Povedzte nám viac.", - "good": "Dobrý", - "rateExperience": "Ohodnoťte dojem", - "veryBad": "Veľmi zlý", - "veryGood": "Veľmi dobrý" - }, - "incomingCall": { - "answer": "Odpovedať", - "audioCallTitle": "Prichádzajúci hovor", - "decline": "Odmietnuť", - "productLabel": "", - "videoCallTitle": "Prichádzajúci video-hovor" - }, - "info": { - "accessibilityLabel": "Zobraziť informácie", - "addPassword": "$t(lockRoomPassword) pridať", - "cancelPassword": "$t(lockRoomPassword) zmazať", - "conferenceURL": "Odkaz:", - "country": "Krajina", - "dialANumber": "Aby ste sa zúčastnili stretnutia, zavolajte jedno z týchto čísel a zadajte pin.", - "dialInConferenceID": "", - "dialInNotSupported": "Prepáčte, volanie nie je podporované.", - "dialInNumber": "Volanie:", - "dialInSummaryError": "Chyba pri získavaná informácií o volaniach. Skúste neskôr.", - "dialInTollFree": "Bezplatné", - "genericError": "Niečo sa nepodarilo.", - "inviteLiveStream": "Kliknite túto linku {{url}}, pre zobrazenie živého vysielania z tohto stretnutia.", - "invitePhone": "Keď sa chcete pripojiť cez telefón, klikni na: {{number}},,{{conferenceID}}#\n", - "invitePhoneAlternatives": "Hľadáte iné pripojovacie číslo? Pripojovacie čísla pre konferenciu: {{{url}}\n\n\n\nTaktiež pokiaľ sa telefonicky pripájate cez konferenčný celomiestnostný telefón pripojte sa bez prenosu zvuku {{silentUrl}}", - "inviteURLFirstPartGeneral": "Ste pozývaný pripojiť sa na stretnutie.", - "inviteURLFirstPartPersonal": "{{name}} vás pozýva na stretnutie.", - "inviteURLSecondPart": "\n Zúčastniť sa stretnutia:\n{{url}}\n", - "liveStreamURL": "Živý prenos:", - "moreNumbers": "Ďalšie telefónne čísla", - "noNumbers": "Žiadne pripojovacie telefónne čísla.", - "noPassword": "Žiadne", - "noRoom": "Nebola zadaná žiadna konferencia na pripojenie.", - "numbers": "Pripojovacie čísla", - "password": "$t(lockRoomPasswordUppercase):", - "title": "Zdieľať", - "tooltip": "Zdieľať odkaz a informácie o vytáčaní pre toto stretnutie", - "label": "Informácie o stretnutí" - }, - "inviteDialog": { - "alertText": "Nepodarilo sa pozvať niektorych účastníkov.", - "header": "Pozvať", - "searchCallOnlyPlaceholder": "Zadajte telefónne číslo", - "searchPeopleOnlyPlaceholder": "Hľadať účastníkov", - "searchPlaceholder": "Účastník alebo telefónne číslo", - "send": "Poslať" - }, - "inlineDialogFailure": { - "msg": "Vyskytla sa chyba.", - "retry": "Skúsiť znovu", - "support": "Podpora", - "supportMsg": "Pokiaľ sa chyba zopakuje, spojte sa s" - }, - "keyboardShortcuts": { - "focusLocal": "Zamerať sa na vaše video", - "focusRemote": "Zamerať sa na video iného účastníka", - "fullScreen": "Zapnúť / Vypnúť plnú obrazovku", - "keyboardShortcuts": "Klávesové skratky", - "localRecording": "Zobraziť, alebo skryť tlačítka pre lokálne nahrávanie", - "mute": "Vypnúť alebo zapnúť mikrofón", - "pushToTalk": "Stlačiť, pre hovorenie", - "raiseHand": "Zdvihnúť alebo dať dole ruku", - "showSpeakerStats": "Zobrať štatistiky rečníka", - "toggleChat": "Zobraziť alebo skryť textové správy", - "toggleFilmstrip": "Zobraziť alebo skryť video náhľady", - "toggleScreensharing": "Prepnúť medzi kamerou a zdieľaním obrazovky", - "toggleShortcuts": "Zobraziť alebo skryť klávesové skratky", - "videoMute": "Zapnúť alebo vypnúť kameru", - "videoQuality": "Nastavenie kvality volania" - }, - "liveStreaming": { - "busy": "Chystajú sa zdroje pre vysielanie. Skúste znova za pár minút.", - "busyTitle": "Všetky vysielacie inštancie sú obsadené", - "changeSignIn": "Prepnúť konto", - "choose": "Vyberte živé vysielanie", - "chooseCTA": "Vyberte vysielaciu možnosť. Ste prihlásený ako {{email}}", - "enterStreamKey": "Zadajte meno/heslo pre YouTube vysielanie.", - "error": "Živé vysielanie zlyhalo. Prosím skúste to znovu.", - "errorAPI": "Došlo chybe pri prístupe k vašemu YouTube vysielaniu. Prosím skúste sa znovu prihlásiť.", - "errorLiveStreamNotEnabled": "Živé vysielanie pre {{email}} nie je aktivované. Aktivujte živé vysielanie, alebo sa prihláste pomocou konta s aktivovaným živým vysielaním.", - "expandedOff": "Živé vysielanie bolo zastavené", - "expandedOn": "Stretnutie je momentálne vysielané na YouTube.", - "expandedPending": "Spúšťa živé vysielanie...", - "failedToStart": "Nepodarilo sa naštartovať živé vysielanie", - "getStreamKeyManually": "Nepodarilo sa získať žiadne živé vysielania. Skúste získať kľúč pre živé vysielanie z YouTube.", - "invalidStreamKey": "Kľúč pre živé vysielanie je nesprávny.", - "off": "Živé vysielanie ukončené", - "offBy": "{{name}} ukončil živé vysielanie", - "on": "Živé vysielanie", - "onBy": "{{name}} začal živé vysielanie", - "pending": "Štartuje sa živé vysielanie...", - "serviceName": "Služba pre živé vysielanie", - "signedInAs": "Ste prihlásený ako:", - "signIn": "Prihlásiť sa pomocou Google", - "signInCTA": "Prihláste sa, alebo zadajte váš YouTube klúč pre živé vysielanie.", - "signOut": "Odhlásiť", - "start": "Začať živé vysielanie", - "streamIdHelp": "Čo je to?", - "unavailableTitle": "Živé vysielanie nie je k dispozícií" - }, - "localRecording": { - "clientState": { - "off": "Vypnutý", - "on": "Zapnutý", - "unknown": "Neznámy" - }, - "dialogTitle": "Lokálne ovládacie prvky nahrávania", - "duration": "Dĺžka", - "durationNA": "neznáma", - "encoding": "Kódovanie", - "label": "", - "labelToolTip": "Lokálny nahrávanie je aktivovaný", - "localRecording": "Lokálne nahrávanie", - "me": "Ja", - "messages": { - "engaged": "Lokálne nahrávanie je spustené", - "finished": "Nahrávanie sedenia {{token}} je ukončené. Prosím pošlite nahratý súbor moderátorovi.", - "finishedModerator": "Nahrávanie sedenia {{token}} je ukončené. Bola uložená nahrávka lokálnej stopy. Poproste ostatných účastníkov, aby vám poslali ich nahrávky.", - "notModerator": "Nieste moderátor. Nemôže začať, alebo skončiť lokálne nahrávanie." - }, - "moderator": "Moderátor", - "no": "Nie", - "participant": "Účastník", - "participantStats": "Štatistiky účastníkov", - "sessionToken": "Token sedenia", - "start": "Zapnúť nahrávanie", - "stop": "Vypnúť nahrávanie", - "yes": "Áno" - }, - "lockRoomPassword": "heslo", - "lockRoomPasswordUppercase": "Heslo", - "me": "ja", - "notify": { - "connectedOneMember": "{{name}} sa pripojil", - "connectedThreePlusMembers": "{{name}} a {{count}} ďalších osôb sa pripojilo", - "connectedTwoMembers": "{{first}} a {{second}} sa pripojili", - "disconnected": "odpojený", - "focus": "Konferenčný focus", - "focusFail": "{{component}} je nedostupný - skúste znova za {{ms}} sek", - "grantedTo": "Práva moderátora boli udelené {{to}}!", - "invitedOneMember": "{{displayName}} bol pozvaný", - "invitedThreePlusMembers": "{{name}} a {{count}} ďalší boli pozvaný", - "invitedTwoMembers": "{{first}} a {{second}} boli pozvaný", - "kickParticipant": "Pre ďalšie podrobnosti sa môže obrátiť na {{participantDisplayName}}", - "me": "Ja", - "moderator": "Boli vám udelené práva moderátora!", - "muted": "Začali ste rozhovor s vypnutým mikrofónom.", - "mutedTitle": "Boli ste stíšený!", - "mutedRemotelyTitle": "{{participantDisplayName}} vás stíšil", - "mutedRemotelyDescription": "Kedykoľvek môžete stíšenie zrušiť, keď ste prichystaný rozprávať. Keď skončite môžete sa znova stíšiť, aby ste znížili hluk na stretnutí.", - "passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) bolo odstránené iným účastníkom", - "passwordSetRemotely": "$t(lockRoomPasswordUppercase) bolo nastavené iným účastníkom", - "raisedHand": "{{name}} chce hovoriť", - "somebody": "Niekto", - "startSilentTitle": "Pripojili ste sa bez zvukového výstupu!", - "startSilentDescription": "Pripojte sa k stretnutiu ešte raz, aby ste aktivovali zvuk.", - "suboptimalBrowserWarning": "Obávame sa, že dojem z tohto stretnutia nebude až taký dobrý. Hladáme spôsob ako to zlepšiť, ale dovtedy prosím skúste jeden z <a href='static/recommendedBrowsers.html' target='_blank'>plne podporovaných prehliadačov</a>.", - "suboptimalExperienceTitle": "Prehliadačové varovanie", - "unmute": "Zapnúť mikrofón", - "newDeviceCameraTitle": "Bola zistená nová kamera", - "newDeviceAudioTitle": "Bolo zistené nové audio zariadenie", - "newDeviceAction": "Použiť" - }, - "passwordSetRemotely": "nastavené iným účastníkom", - "passwordDigitsOnly": "až {{number}} číslic", - "poweredby": "založené na", - "presenceStatus": { - "busy": "Obsadený", - "calling": "Je volaný", - "connected": "Pripojený", - "connecting": "Pripájam", - "connecting2": "Pripájam", - "disconnected": "Odpojený", - "expired": "Vypršaní", - "ignored": "Ignorovaný", - "initializingCall": "Volanie je inicializované...", - "invited": "Pozvať", - "rejected": "Zložiť", - "ringing": "Zvoní..." - }, - "profile": { - "setDisplayNameLabel": "Nastavte si meno", - "setEmailInput": "Zadajte e-mail", - "setEmailLabel": "Nastavte si email vašeho gravataru", - "title": "Profil" - }, - "raisedHand": "Chcel by som hovoriť", - "recording": { - "authDropboxText": "Nahrať na Dropbox", - "availableSpace": "Dostupná kapacita {{spaceLeft}} MB (ca. {{duration}} minút nahrávania)", - "beta": "BETA", - "busy": "Pripravujú sa prostriedky na nahrávanie. Skúste znova o pár minút.", - "busyTitle": "Všetky nahrávacie inštancie sú obsadené", - "error": "Nahrávka sa nepodarila. Skúste prosím znovu.", - "expandedOff": "Nahrávanie bolo zastavené", - "expandedOn": "Stretnutie sa momentálne nahráva.", - "expandedPending": "Začína sa nahrávanie...", - "failedToStart": "Nepodarilo sa začať nahrávanie", - "fileSharingdescription": "Nahrávku zdielať s účastníkmi stretnutia", - "live": "LIVE", - "loggedIn": "Prihlásený ako {{userName}}", - "off": "Nahrávanie zastavené", - "offBy": "{{name}} zastavil nahrávanie", - "on": "Nahrávanie", - "onBy": "{{name}} začal nahrávanie", - "pending": "Pripravuje sa nahrávanie stretnutia...", - "rec": "REC", - "serviceDescription": "Vaša nahrávka sa ukladá nahrávacou službou", - "serviceName": "Nahrávacia služba", - "signIn": "Prihlásiť", - "signOut": "Odhlásiť", - "unavailable": "Oh! Služba {{serviceName}} nie je dostupná. Pracujeme na riešeni problému. Skúste prosím neskôr.", - "unavailableTitle": "Nahrávanie nie je dostupné" - }, - "sectionList": { - "pullToRefresh": "Potiahnuť pre aktualizáciu" - }, - "settings": { - "calendar": { - "about": "Používa sa kalendárová integrácia {{appName}} pre zabezpečený prístup ku vašemu kalendáru.", - "disconnect": "Odpojený", - "microsoftSignIn": "Prihlásiť pomocou Microsoft", - "signedIn": "Momentálne sa pristupuje na kalendárové udalosti pre {{email}}. Stlačte tlačidlo „Odpojiť“ pre prerušenie spojenia ku kalendárovým udalostiam.", - "title": "Kalendár" - }, - "devices": "Zariadenia", - "followMe": "Všetci sledujú mňa", - "language": "Jazyk", - "loggedIn": "Prihlásený ako {{name}}", - "moderator": "Moderátor", - "more": "Viac", - "name": "Meno", - "noDevice": "Žiadne zariadenie", - "selectAudioOutput": "Zvukový výstup", - "selectCamera": "Kamera", - "selectMic": "Mikrofón", - "startAudioMuted": "Pri pripojení všetkým stlmiť zvuk", - "startVideoMuted": "Pri pripojení všetkým vypnúť video", - "title": "Nastavenia" - }, - "settingsView": { - "advanced": "Rozšírené", - "alertOk": "OK", - "alertTitle": "Upozornenie", - "alertURLText": "Zadaná serverový URL je neplatná", - "buildInfoSection": "informácie o kompilácií", - "conferenceSection": "Konferencia", - "disableCallIntegration": "Deaktivovať integráciu s natívnymi volaniami", - "disableP2P": "Deaktivovať mód s koncovými zariadeniami", - "displayName": "Ukázať", - "email": "E-mail", - "header": "Nastavenia", - "profileSection": "Profil", - "serverURL": "Adresa URL servera", - "showAdvanced": "Ukázať rozšírené nastavenia", - "startWithAudioMuted": "Začať so stlmeným zvukom", - "startWithVideoMuted": "Začať so vypnutým videom", - "version": "Verzia" - }, - "share": { - "dialInfoText": "\n\n=====\n\n Chcete ma zavolať na Vašom telefóne?\n\n{{{defaultDialInNumber}}}Kliknite na nasledujúci odkaz, aby ste videli vybrané telefónne čislo na stretnutí\n{{dialInfoPageUrl}}", - "mainText": "Kliknite na nasledujúci odkaz, aby ste sa pripojili na stretnutie:\n{{roomUrl}}" - }, - "speaker": "Rečník", - "speakerStats": { - "hours": "", - "minutes": "", - "name": "Meno", - "seconds": "", - "speakerStats": "Štatistiky rečníka", - "speakerTime": "Čas rečníka" - }, - "startupoverlay": { - "policyText": "", - "title": "{{app}} potrebuje prístup k vašemu mikrofónu a kamere." - }, - "suspendedoverlay": { - "rejoinKeyTitle": "Znovu pripojiť", - "text": "Stlačte tlačidlo <i>Znovu pripojiť</i> na opätovné spojenie.", - "title": "Konferencia sa prerušila lebo váš počítač bol uspaní." - }, - "toolbar": { - "accessibilityLabel": { - "audioOnly": "Zapnúť/vypnúť iba zvukový prenos", - "audioRoute": "Vybrať zvukové zariadenie", - "callQuality": "Spravovať kvalitu videa", - "cc": "Zapnúť/vypnúť titulky", - "chat": "Zapnúť/vypnúť textovú diskusiu", - "document": "Zatvoriť zdielaný dokument", - "download": "Stiahnuť našu aplikáciu", - "feedback": "Zanechať spätnú väzbu", - "fullScreen": "Zapnúť/vypnúť zobrazenie na celú obrazovku", - "hangup": "Ukončiť volanie", - "help": "Pomoc", - "invite": "Pozvať účastníka", - "kick": "Odstrániť účastníka", - "localRecording": "Zapnúť/vypnúť ovládanie lokálneho nahrávania", - "lockRoom": "Zapnúť/vypnúť heslo pre stretnutie", - "moreActions": "Menu „Ďalšie akcie“ zapnúť/vypnúť", - "moreActionsMenu": "Menu „Ďalšie akcie“", - "moreOptions": "Zobraz viac možností", - "mute": "„mikrofón stlmiť“ zapnúť/vypnúť", - "muteEveryone": "Všetkých stlmiť", - "pip": "Zapnuť/vypnuť mód obraz-v-obraze", - "privateMessage": "Poslať súkromnú správu", - "profile": "Upraviť profil", - "raiseHand": "„Ohlásiť sa“ zapnúť/vypnúť", - "recording": "Nahrávanie zapnúť/vypnúť", - "remoteMute": "Účastníka stlmiť", - "Settings": "Nastavenia zapnúť/vypnúť", - "sharedvideo": "Zdieľanie YouTube videa zapnúť/vypnúť", - "shareRoom": "Pozvať osobu", - "shareYourScreen": "Zdieľanie obrazovky zapnúť/vypnúť", - "shortcuts": "Klávesové skratky zobraziť/skryť", - "show": "V popredí zobraziť", - "speakerStats": "Štatistiky rečníka zobraziť/skryť", - "tileView": "Prepnúť dlaždicové zobrazenie", - "toggleCamera": "Zmeniť kameru", - "videomute": "„Video odpojiť“ zapnúť/vypnúť", - "videoblur": "Rozmazanie pozadia zapnúť/vypnúť" - }, - "addPeople": "Pridať účastníka do konferencie", - "audioOnlyOff": "Mód „Iba zvuk“ deaktivovať", - "audioOnlyOn": "Mód „Iba zvuk“ aktivovať", - "audioRoute": "Vybrať zvukové zariadenie", - "authenticate": "Overiť", - "callQuality": "Spravovať kvalitu videa", - "chat": "Otvoriť / Zatvoriť chat", - "closeChat": "Chat zatvoriť", - "documentClose": "Zdielaný dokument zatvoriť", - "documentOpen": "Zdielaný dokument otvoriť", - "download": "Stiahnuť našu aplikáciu", - "enterFullScreen": "Zobraziť na celú obrazovku", - "enterTileView": "Kachličkové zobrazenie", - "exitFullScreen": "Opustiť celú obrazovku", - "exitTileView": "Kachličkové zobrazenie vypnúť", - "feedback": "Nechať spätnú väzbu", - "hangup": "Odísť", - "help": "Pomoc", - "invite": "Pozvať účastníkov", - "login": "Prihlásiť", - "logout": "Odhlásiť", - "lowerYourHand": "Dať dole ruku", - "moreActions": "Viac akcií", - "moreOptions": "Viac možností", - "mute": "Vypnúť / Zapnúť mikrofón", - "muteEveryone": "Všetkých stlmiť", - "noAudioSignalTitle": "Neprichádza žiaden vstup z vašeho mikrofónu!", - "noAudioSignalDesc": "Pokiaľ ste zámerne nestlmili váš mikrofón v systémových nastavenia alebo hardvery, pouvažujte nad prepnutím zariadenia.", - "noAudioSignalDescSuggestion": "Pokiaľ ste zámerne nestlmili váš mikrofón v systémových nastavenia alebo hardvery, pouvažujte nad prepnutím na odporúčané zariadenie.", - "noAudioSignalDialInDesc": "Môže zavolať pomocou:", - "noAudioSignalDialInLinkDesc" : "Pripojovacie telefónne čísla", - "noisyAudioInputTitle": "Váš mikrofón vyzerá byť zašumený!", - "noisyAudioInputDesc": "Vyzerá, že váš mikrofón je zašumený, skúste ho vypnuť, alebo zmeňte zariadenie.", - "openChat": "Otvoriť chat", - "pip": "Zapnuť obraz-v-obraze", - "privateMessage": "Poslať súkromnú správu", - "profile": "Úprava profilu", - "raiseHand": "Prihlásiť / Odhlásiť sa o slovo", - "raiseYourHand": "Prihlásiť sa o slovo", - "Settings": "Nastavenia", - "sharedvideo": "Zdielať YouTube video", - "shareRoom": "Pozvať niekoho", - "shortcuts": "Ukázať klávesové skratky", - "speakerStats": "Štatistiky rečníka", - "startScreenSharing": "Začať zdieľanie obrazovky", - "startSubtitles": "Začať titulky", - "stopScreenSharing": "Ukončiť zdieľanie obrazovky", - "stopSubtitles": "Ukončiť titulky", - "stopSharedVideo": "Ukončiť zdielané YouTube video", - "talkWhileMutedPopup": "Skúšate hovoriť? Ste stlmený.", - "tileViewToggle": "Prepnúť dlaždicové zobrazenie", - "toggleCamera": "Zmeniť kameru", - "videomute": "Vypnúť / Zapnúť kameru", - "startvideoblur": "Rozmazať pozadie", - "stopvideoblur": "Ukončiť rozmazanie pozadia" - }, - "transcribing": { - "ccButtonTooltip": "titulky vypnuť/zapnúť", - "error": "Prepisovanie zlyhalo. Skúsiť znovu.", - "expandedLabel": "Prepisovanie je zapnuté", - "failedToStart": "Prepisovanie sa nepodarilo naštartovať", - "labelToolTip": "Stretnutie je prepisované", - "off": "Prepisovanie sa skončilo", - "pending": "Pripravuje sa prepisovanie stretnutia...", - "start": "Začni zobrazovať titulky", - "stop": "Skonči zobrazovať titulky", - "tr": "" - }, - "userMedia": { - "androidGrantPermissions": "Vyberte <b><i>Povoliť</i></b> keď sa prehliadač bude pýtať na povolenie.", - "chromeGrantPermissions": "Vyberte <b><i>Povoliť</i></b> keď sa prehliadač bude pýtať na povolenie.", - "edgeGrantPermissions": "Vyberte <b><i>Áno</i></b> keď sa prehliadač bude pýtať na povolenie.", - "electronGrantPermissions": "Prosím povoľte prístup k vašemu mikrofónu a kamere.", - "firefoxGrantPermissions": "Vyberte <b><i>Zdieľaj vybrané zariadenie</i></b> keď sa prehliadač bude pýtať na povolenie.", - "iexplorerGrantPermissions": "Vyberte <b><i>Ok</i></b> keď sa prehliadač bude pýtať na povolenie.", - "nwjsGrantPermissions": "Prosím povoľte prístup k vašemu mikrofónu a kamere.", - "operaGrantPermissions": "Vyberte <b><i>Povoliť</i></b> keď sa prehliadač bude pýtať na povolenie.", - "react-nativeGrantPermissions": "Vyber <b><i>Povoliť</i></b> keď sa prehliadač bude pýtať na povolenie.", - "safariGrantPermissions": "Vyberte <b><i>OK</i></b> keď sa prehliadač bude pýtať na povolenie." - }, - "videoSIPGW": { - "busy": "", - "busyTitle": "", - "errorAlreadyInvited": "", - "errorInvite": "", - "errorInviteFailed": "", - "errorInviteFailedTitle": "", - "errorInviteTitle": "", - "pending": "" - }, - "videoStatus": { - "audioOnly": "AUD", - "audioOnlyExpanded": "Ste v móde s nízkou prenosovou kapacitou. V tomto móde budete prijímať iba zvuk a zdielanú obrazovku.", - "callQuality": "Nastavenie kvality hovoru", - "hd": "HD", - "hdTooltip": "Sledujete obraz vo vysokej kvalite", - "highDefinition": "Vysoká kvalita", - "labelTooiltipNoVideo": "Žiadne video", - "labelTooltipAudioOnly": "Mód s nízkou prenosovou kapacitou je zapnutý", - "ld": "LD", - "ldTooltip": "Sledujete obraz v nízkej kvalite", - "lowDefinition": "Nízka kvalita", - "onlyAudioAvailable": "Iba zvuk je k dispozícií", - "onlyAudioSupported": "Na vašom prehliadači podporujeme iba zvuk.", - "p2pEnabled": "Prenos medzi koncovými používateľmi", - "p2pVideoQualityDescription": "Pri prenose medzi koncovými používateľmi sa dá video kvalita nastaviť iba na vysokú alebo iba zvukový prenos. Ostatné nastavenia sa budú používať iba ak prenose medzi koncovými používateľmi bude ukončený", - "recHighDefinitionOnly": "Uprednostňovať vysokú kvalitu", - "sd": "SD", - "sdTooltip": "Sledujete obraz v štandardnej kvalite", - "standardDefinition": "Štandardná kvalita" - }, - "videothumbnail": { - "domute": "Vypnúť mikrofón", - "flip": "Prevrátiť", - "kick": "Vyhodiť", - "moderator": "Moderátor", - "mute": "Účastník s vypnutým mikrofónom", - "muted": "Vypnutý mikrofón", - "remoteControl": "Vzdialené ovládanie", - "show": "Ukázať v popredí", - "videomute": "Účastník vypol kameru" - }, - "welcomepage": { - "accessibilityLabel": { - "join": "Kliknúť pre pripojenie", - "roomname": "Zadajte názov miestnosti" - }, - "appDescription": "Poďte na to, videokonferencie v rámci celého tímu. Do konferencie môžete pozvať kohokoľvek. Všetka komunikácia cez aplikáciu {{app}} je plne šifrovaná, 100% open source zaisťuje, že aplikáciu môžete využívať bez obmedzenia a navyše sa nemusíte ani registrovať.", - "audioVideoSwitch": { - "audio": "Zvuk", - "video": "Video" - }, - "calendar": "Kalendár", - "connectCalendarButton": "Pripojte váš kalendár", - "connectCalendarText": "", - "enterRoomTitle": "Začať nové stretnutie", - "roomNameAllowedChars": "Meno stretnutia by nemalo obsahovať žiaden z týchto znakov: ?, &, :, ', \", %, #.", - "go": "Začať", - "goSmall": "Začať", - "join": "Pripojiť", - "info": "Info", - "privacy": "Súkromie", - "recentList": "Posledné", - "recentListDelete": "Vymazať", - "recentListEmpty": "Váš zoznam posledných hovorov je prázdny. Spojte sa s kolegami z Vášho tímu a potom tu nájdete všetky vaše stretnutia.", - "reducedUIText": "Vítajte v {{app}}!", - "roomname": "Zadajte názov miestnosti", - "roomnameHint": "Zadajte názov alebo URL odkaz miestnosti ku ktorej sa chcete pripojiť. Pokial ste miestnosť vytvorili, uistite sa, že ostatný účastníci schôdzky zadajú rovnaké meno ako vy.", - "sendFeedback": "Odoslať spätnú väzbu", - "terms": "Podmienky používania", - "title": "Zabezpečené, plnohodnotné a úplne bezplatné videokonferencie" - } -} diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-sv.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-sv.json index 954b83832..2ff76c851 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-sv.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-sv.json @@ -4,7 +4,7 @@ "countryNotSupported": "Vi stöder inte den här platsen ännu.", "countryReminder": "Ringer du till utlandsnummer? Börja alltid med landskoden.", "disabled": "Du kan inte bjuda in andra.", - "failedToAdd": "Kunde inte lägga till deltagare", + "failedToAdd": "", "footerText": "Utringningsfunktionen är avstängd.", "loading": "Söker efter personer och telefonnummer", "loadingNumber": "Bekräftar telefonnummer", @@ -21,8 +21,7 @@ "bluetooth": "Bluetooth", "headphones": "Hörlurar", "phone": "Telefon", - "speaker": "Talare", - "none": "Inga ljudenheter tillgängliga" + "speaker": "Talare" }, "audioOnly": { "audioOnly": "Enbart ljud" @@ -46,21 +45,16 @@ "today": "Idag" }, "chat": { - "error": "Fel: ditt meddelande skickades inte. Orsak: {{error}}", + "error": "", "messagebox": "Skriv ett meddelande", "nickname": { "popover": "Välj ett namn", "title": "Skriv in ett namn för att börja använda chatten" }, - "title": "Chatt", - "you": "du", - "privateNotice": "Privat meddelande till {{recipient}}", - "noMessagesMessage": "Det finns ännu inga meddelanden i mötet. Påbörja en konversation!", - "messageTo": "Privat meddelande till {{recipient}}", - "fieldPlaceHolder": "Skriv ditt meddelande här" + "title": "Chatt" }, "connectingOverlay": { - "joiningRoom": "Ansluter till mötet …" + "joiningRoom": "Ansluter till mötet ..." }, "connection": { "ATTACHED": "Ansluten", @@ -72,11 +66,7 @@ "DISCONNECTED": "Frånkopplad", "DISCONNECTING": "Kopplar från", "ERROR": "Fel", - "RECONNECTING": "Ett nätverksproblem uppstod. Återansluter...", - "LOW_BANDWIDTH": "Video för {{displayName}} har stängts av för att spara bandbredd", - "GOT_SESSION_ID": "Hämta sessions-id ... Klart", - "GET_SESSION_ID_ERROR": "Hämta sessions-id-fel: {{code}}", - "FETCH_SESSION_ID": "Hämtar sessions-id …" + "RECONNECTING": "Ett nätverksproblem uppstod. Återansluter..." }, "connectionindicator": { "address": "Adress:", @@ -106,9 +96,7 @@ "resolution": "Upplösning:", "status": "Anslutning:", "transport": "Transport:", - "transport_plural": "Transporter:", - "turn": " (turn)", - "e2e_rtt": "E2E RTT:" + "turn": " (turn)" }, "dateUtils": { "earlier": "Tidigare", @@ -118,11 +106,11 @@ "deepLinking": { "appNotInstalled": "Du behöver mobilappen {{app}} för att gå med i det här mötet från din telefon.", "description": "Hände inget? Vi försökte starta mötet i programmet {{app}} i din skrivbordsapp. Försök igen eller starta det i webbappen {{app}}.", - "descriptionWithoutWeb": "Händer inget? Vi försökte starta mötet i {{app}}-skrivbordsappen.", + "descriptionWithoutWeb": "", "downloadApp": "Hämta appen", "launchWebButton": "Starta på webben", "openApp": "Fortsätt till appen", - "title": "Startar ditt möte i {{app}} …", + "title": "Startar ditt möte i {{app}} ...", "tryAgainButton": "Försök igen på skrivbordet" }, "defaultLink": "t ex. {{url}}", @@ -143,7 +131,7 @@ "liveStreaming": "Livesändning" }, "allow": "Tillåt", - "alreadySharedVideoMsg": "En annan deltagare delar redan en video. Konferensen tillåter bara en video-delning åt gången.", + "alreadySharedVideoMsg": "", "alreadySharedVideoTitle": "Endast en delad video åt gången tillåts", "applicationWindow": "Applikationsfönster", "Back": "Tillbaka", @@ -156,9 +144,9 @@ "cameraUnsupportedResolutionError": "Din kamera stöder inte den krävda videoupplösningen.", "Cancel": "Avbryt", "close": "Stäng", - "conferenceDisconnectMsg": "Kolla din internetanslutning. Återansluter om {{seconds}} sekunder…", + "conferenceDisconnectMsg": "Kolla din internetanslutning. Återansluter om {{seconds}} sekunder...", "conferenceDisconnectTitle": "Du har kopplats ner.", - "conferenceReloadMsg": "Vi försöker fixa problemet. Återansluter om {{seconds}} sekunder…", + "conferenceReloadMsg": "Vi försöker fixa problemet. Återansluter om {{seconds}} sekunder...", "conferenceReloadTitle": "Något gick snett.", "confirm": "Bekräfta", "confirmNo": "Nej", @@ -169,40 +157,40 @@ "contactSupport": "Kontakta kundtjänst", "copy": "Kopiera", "dismiss": "Förkasta", - "displayNameRequired": "Hej, vilket är ditt namn?", + "displayNameRequired": "", "done": "Klar", - "enterDisplayName": "Ange namn", + "enterDisplayName": "", "error": "Fel", "externalInstallationMsg": "Misslyckades att installera skrivbordsdelnings-tillägget.", "externalInstallationTitle": "Tillägg krävs", "goToStore": "Gå till appbutiken", "gracefulShutdown": "Vår tjänst är för tillfället nedstängd för underhåll. Vänligen försök senare.", "IamHost": "Jag är värd", - "incorrectRoomLockPassword": "Felaktigt lösenord", + "incorrectRoomLockPassword": "", "incorrectPassword": "Fel användarnamn eller lösenord", "inlineInstallationMsg": "Misslyckades att installera skrivbordsdelnings-tillägget.", "inlineInstallExtension": "Installera nu", "internalError": "Ett fel uppstod. Fel: {{error}}", "internalErrorTitle": "Internt fel", - "kickMessage": "Du kan kontakta {{participantDisplayName}} för mer information.", + "kickMessage": "", "kickParticipantButton": "Sparka ut", "kickParticipantDialog": "Vill du sparka ut den här deltagaren?", "kickParticipantTitle": "Tysta deltagaren?", - "kickTitle": "Aj! {{participantDisplayName}} sparkade ut dig ur mötet", + "kickTitle": "", "liveStreaming": "Strömma", "liveStreamingDisabledForGuestTooltip": "Gäster kan inte starta en livesändning.", "liveStreamingDisabledTooltip": "Starta livesändning har inaktiverats.", "lockMessage": "Misslyckades att låsa konferensen.", - "lockRoom": "Lägg till möte $t(lockRoomPasswordUppercase)", + "lockRoom": "", "lockTitle": "Låsning misslyckades", "logoutQuestion": "Är du säker på att du vill logga ut och stoppa konferensen?", "logoutTitle": "Logga ut", "maxUsersLimitReached": "", - "maxUsersLimitReachedTitle": "Maximal deltagarantal uppnått", + "maxUsersLimitReachedTitle": "", "micConstraintFailedError": "Din mikrofon uppfyller inte kraven för användning.", "micNotFoundError": "Hittar ingen mikrofon.", "micNotSendingData": "", - "micNotSendingDataTitle": "Din mikrofon är tystad av dina systeminställningar", + "micNotSendingDataTitle": "", "micPermissionDeniedError": "Du har inte tillåtit användning av din mikrofon. Du kan gå med i mötet men de andra kan då inte höra dej. Om du vill tillåta användning av din mikrofon gör du det via mikrofonknappen i URL-fältet.", "micUnknownError": "Av okänd anledning kan inte din mikrofon användas.", "muteParticipantBody": "Du kan inte aktivera deras mikrofoner, men de kan göra det själva.", @@ -210,10 +198,10 @@ "muteParticipantDialog": "Vill du tysta den här deltagaren? Du kan inte aktivera mikrofonen igen, men deltagaren kan när som helst göra det själv.", "muteParticipantTitle": "Tysta deltagaren?", "Ok": "Ok", - "passwordLabel": "Mötet har låsts av en deltagare. Ange $t(lockRoomPassword) för att gå med.", - "passwordNotSupported": "Att sätta ett $t(lockRoomPassword) för mötesrummet stöds ej.", - "passwordNotSupportedTitle": "$t(lockRoomPasswordUppercase) stöds inte", - "passwordRequired": "$t(lockRoomPasswordUppercase) krävs", + "passwordLabel": "", + "passwordNotSupported": "Att sätta ett lösenord för konferensrummet stöds inte.", + "passwordNotSupportedTitle": "", + "passwordRequired": "", "popupError": "Din webbläsare blockerar pop-up-fönster från sajten. Tillåt pop-up-fönster från den här sajten i inställningarna och försök igen.", "popupErrorTitle": "Pop-up blockerad", "recording": "Inspelning", @@ -228,7 +216,7 @@ "remoteControlStopMessage": "Fjärrstyrningssessionen avslutades.", "remoteControlTitle": "Anslutning till fjärrskrivbord", "Remove": "Ta bort", - "removePassword": "Ta bort $t(lockRoomPassword)", + "removePassword": "", "removeSharedVideoMsg": "Är du säker på att du vill ta bort din delade video?", "removeSharedVideoTitle": "Ta bort den delade videon", "reservationError": "Fel i reservationssystemet", @@ -261,24 +249,15 @@ "tokenAuthFailed": "Du är inte behörig att delta i det här samtalet.", "tokenAuthFailedTitle": "Autentisering misslyckades", "transcribing": "Transkriberar", - "unlockRoom": "Ta bort möte $t(lockRoomPassword)", + "unlockRoom": "", "userPassword": "användarlösenord", - "WaitForHostMsg": "Konferensen <b>{{room}}</b> har inte börjat än. Autentisera konferensen om du är värd. Vänta annars på att värden startar konferensen.", - "WaitForHostMsgWOk": "Konferensen <b>{{room}}</b> har inte börjat än. Om du är värd, autentisera konferensen genom att trycka på Ok. Vänta annars på att värden startar konferensen.", - "WaitingForHost": "Väntar på värden …", + "WaitForHostMsg": "Konferensen <b>{{room}}<b> har inte börjat än. Autentisera konferensen om du är värd. Vänta annars på att värden startar konferensen.", + "WaitForHostMsgWOk": "Konferensen <b>{{room}}<b> har inte börjat än. Om du är värd, autentisera konferensen genom att trycka på Ok. Vänta annars på att värden startar konferensen.", + "WaitingForHost": "Väntar på värden ...", "Yes": "Ja", - "yourEntireScreen": "Helskärm", - "muteEveryoneElseDialog": "När någon tystats kan du inte slå på mikrofonen, men de kan själva slå på sin egen mikrofon när som helst.", - "muteEveryoneElseTitle": "Tysta alla utom {{whom}}?", - "muteEveryoneDialog": "Är du säker på att du vill tysta alla? Du kan inte slå på mikrofonen åt dem, men de kan själva slå på sin egen mikrofon när som helst.", - "muteEveryoneStartMuted": "Alla börjar tystade", - "muteEveryoneTitle": "Tysta alla?", - "sendPrivateMessage": "Du har fått ett privat meddelande. Tänkte du svara på det privat, eller vill du skicka ditt meddelande till alla deltagare?", - "screenSharingAudio": "", - "sendPrivateMessageCancel": "Skicka till alla deltagare", - "sendPrivateMessageTitle": "", - "sendPrivateMessageOk": "" + "yourEntireScreen": "Helskärm" }, + "\u0005dialog": {}, "dialOut": { "statusMessage": "är nu {{status}}" }, @@ -300,8 +279,8 @@ }, "info": { "accessibilityLabel": "Visa info", - "addPassword": "Lägg till $t(lockRoomPassword)", - "cancelPassword": "Avbryt $t(lockRoomPassword)", + "addPassword": "", + "cancelPassword": "", "conferenceURL": "Länk:", "country": "Land", "dialANumber": "Om du vill gå med i mötet ringer du något av dessa nummer och fyller sedan i PIN-koden.", @@ -312,18 +291,18 @@ "dialInTollFree": "Avgiftsfritt nummer", "genericError": "Oj då, något gick fel.", "inviteLiveStream": "Om du vill se livesändningen av mötet klickar du här: {{url}}", - "invitePhone": "För att gå med via telefon istället trycker du in: {{number}} ,, {{conferenceID}} #\n", + "invitePhone": "", "invitePhoneAlternatives": "", "inviteURLFirstPartGeneral": "Du är inbjuden till ett möte.", "inviteURLFirstPartPersonal": "", - "inviteURLSecondPart": "\nGå med i mötet:\n{{url}}\n", + "inviteURLSecondPart": "", "liveStreamURL": "Livesändning:", "moreNumbers": "Fler nummer", "noNumbers": "Inga inringningsnummer.", "noPassword": "Inga enheter", "noRoom": "Inget rum specificerades för inringning.", "numbers": "Inringningsnummer", - "password": "$t(lockRoomPasswordUppercase):", + "password": "", "title": "Dela", "tooltip": "Dela länk och information om inringning för mötet", "label": "Mötesinformation" @@ -356,8 +335,7 @@ "toggleFilmstrip": "Visa eller dölj videominiatyrer", "toggleScreensharing": "Växla mellan kamera och skärmdelning", "toggleShortcuts": "Visa eller dölj kortkommandon", - "videoMute": "Aktivera / avaktivera din kamera", - "videoQuality": "" + "videoMute": "Aktivera / avaktivera din kamera" }, "liveStreaming": { "busy": "Vi försöker frigöra fler strömningsresurser. Försök igen senare.", @@ -366,18 +344,18 @@ "choose": "Välj en ström", "chooseCTA": "Välj ett livesändningsalternativ. Du är nu inloggad som {{email}}.", "enterStreamKey": "Skriv in lösenordet till YouTube-livesändningen här.", - "error": "Direktströmning misslyckades. Försök igen.", + "error": "Strömning misslyckades. Försök igen.", "errorAPI": "Ett fel inträffade vid åtkomst till dina YouTube-sändningar. Försök att logga in igen.", "errorLiveStreamNotEnabled": "Livesändning är otillgänglig för {{email}}. Aktivera livesändning eller logga in på ett konto där det är aktiverat.", "expandedOff": "Livesändningen har avslutats", "expandedOn": "Mötet livesänds just nu på YouTube.", - "expandedPending": "Livesändningen startas …", + "expandedPending": "Livesändningen startas ...", "failedToStart": "Strömningen kunde inte påbörjas", - "getStreamKeyManually": "Vi kunde inte hämta några direktströmmar. Försök att få din direktströmningsnyckel från YouTube.", + "getStreamKeyManually": "", "invalidStreamKey": "Livesändningslösenordet kan vara felaktigt.", "off": "Strömning avslutad", "on": "Strömma", - "pending": "Börja strömma …", + "pending": "Börja strömma ...", "serviceName": "Livesändningstjänst", "signedInAs": "Du är nu inloggad som:", "signIn": "Logga in med Google", @@ -385,12 +363,9 @@ "signOut": "Logga ut", "start": "Starta en livesändning", "streamIdHelp": "Vad är det här?", - "unavailableTitle": "Livesändning otillgänglig", - "offBy": "{{name}} stoppade direktströmningen", - "onBy": "{{name}} startade direktströmningen", - "youtubeTerms": "Tjänstevillkor för YouTube", - "googlePrivacyPolicy": "" + "unavailableTitle": "Livesändning otillgänglig" }, + "\u0005liveStreaming": {}, "localRecording": { "clientState": { "off": "Av", @@ -434,43 +409,42 @@ "invitedOneMember": "", "invitedThreePlusMembers": "", "invitedTwoMembers": "", - "kickParticipant": "{{kicked}} sparkades ut av {{kicker}}", + "kickParticipant": "", "me": "Jag", "moderator": "Moderatorsrättigheter tilldelades!", "muted": "Du har startat konversationen utan mikrofon.", "mutedTitle": "Du har mikrofonen avstängd!", "mutedRemotelyTitle": "", - "mutedRemotelyDescription": "Du kan alltid slå på mikrofonen när du är redo att tala. Stäng av när du är klar för att hålla brus borta från mötet.", - "passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) togs bort av en annan deltagare", - "passwordSetRemotely": "$t(lockRoomPasswordUppercase) satt av en annan deltagare", + "mutedRemotelyDescription": "", + "passwordRemovedRemotely": "", + "passwordSetRemotely": "", "raisedHand": "{{name}} vill prata.", "somebody": "Någon", - "startSilentTitle": "Du gick med utan ljud aktiverat!", - "startSilentDescription": "Anslut till mötet igen för att aktivera ljud", + "startSilentTitle": "", + "startSilentDescription": "", "suboptimalExperienceDescription": "Hmm... din upplevelse med {{appName}} kommer inte att bli särskilt bra. Vi försöker hitta sätt att förbättra det, men till dess använd en av <a href='static/recommendedBrowsers.html' target='_blank'>de helt stödda webbläsarna</a>.", "suboptimalExperienceTitle": "Webbläsarvarning", - "unmute": "Slå på mikrofonen", + "unmute": "", "newDeviceCameraTitle": "Ny kamera hittad", "newDeviceAudioTitle": "Ny ljudenhet hittad", - "newDeviceAction": "Använd", - "suboptimalBrowserWarning": "Din mötesupplevelse kommer tyvärr inte att bli så bra. Vi letar efter sätt att förbättra detta, men fram till dess kan du försöka använda en av de <a href='static/recommendedBrowsers.html' target='_blank'> fullt stödda webbläsarna </a>." + "newDeviceAction": "Använd" }, "passwordSetRemotely": "satt av en annan deltagare", "passwordDigitsOnly": "", "poweredby": "drivs av", "presenceStatus": { "busy": "Upptagen", - "calling": "Ringer …", + "calling": "Ringer ...", "connected": "Ansluten", - "connecting": "Ansluter …", + "connecting": "Ansluter ...", "connecting2": "Ansluter* ...", "disconnected": "Frånkopplad", "expired": "Utgången", "ignored": "Ignorerad", - "initializingCall": "Startar samtal …", + "initializingCall": "Startar samtal ...", "invited": "Inbjuden", "rejected": "Avvisad", - "ringing": "Ringer …" + "ringing": "Ringer ..." }, "profile": { "setDisplayNameLabel": "Ange ditt visningsnamn", @@ -487,23 +461,21 @@ "error": "Inspelningen misslyckades. Försök igen.", "expandedOff": "Inspelningen har avslutats", "expandedOn": "Mötet spelas nu in.", - "expandedPending": "Inspelningen påbörjas …", + "expandedPending": "Inspelningen startar ...", "failedToStart": "Inspelningen kunde inte påbörjas", "fileSharingdescription": "Dela inspelningen med mötesdeltagare", "live": "LIVE", "loggedIn": "Inloggad som {{userName}}", "off": "Inspelningen avslutades", "on": "Inspelning", - "pending": "Förbereder inspelning av mötet …", + "pending": "Förbereder inspelning av mötet ...", "rec": "REC", "serviceDescription": "Din inspelning kommer att sparas av inspelningstjänsten", "serviceName": "Inspelningstjänst", "signIn": "Logga in", "signOut": "Logga ut", "unavailable": "{{serviceName}} är inte tillgänglig. Vi försöker åtgärda felet. Försök igen senare.", - "unavailableTitle": "Inspelning kan inte göras", - "onBy": "{{name}} påbörjade inspelningen", - "offBy": "{{name}} avslutade inspelningen" + "unavailableTitle": "Inspelning kan inte göras" }, "sectionList": { "pullToRefresh": "Dra för att uppdatera" @@ -529,9 +501,7 @@ "selectMic": "Mikrofon", "startAudioMuted": "Alla börjar tystade", "startVideoMuted": "Alla börjar osynliga", - "title": "Inställningar", - "speakers": "Talare", - "microphones": "" + "title": "Inställningar" }, "settingsView": { "alertOk": "OK", @@ -546,15 +516,11 @@ "serverURL": "Serverlänk", "startWithAudioMuted": "Starta med ljudet avstängt", "startWithVideoMuted": "Starta med videon avstängd", - "version": "Version", - "disableCallIntegration": "Tillåt inte deltagande via telefon", - "showAdvanced": "Visa avancerade inställningar", - "disableP2P": "", - "advanced": "" + "version": "Version" }, "share": { - "dialInfoText": "\n\n=====\n\nVill du istället ringa in via telefon?\n\n{{defaultDialInNumber}} Klicka på den här länken för att se telefonnumret för detta möte\n{{dialInfoPageUrl}}", - "mainText": "Klicka på länken för att delta i mötet:\n{{roomUrl}}" + "dialInfoText": "", + "mainText": "" }, "speaker": "Talare", "speakerStats": { @@ -598,7 +564,7 @@ "recording": "Slå av eller på inspelning", "remoteMute": "Tysta deltagare", "Settings": "Öppna eller stäng inställningar", - "sharedvideo": "Slå av eller på YouTube-videodelning", + "sharedvideo": "Slå av eller på Youtube-videodelning", "shareRoom": "Bjud in någon", "shareYourScreen": "Slå av eller på skärmdelning", "shortcuts": "Stäng eller öppna genvägar", @@ -607,13 +573,7 @@ "tileView": "Öppna eller stäng panelvyn", "toggleCamera": "Växla kamera", "videomute": "Sätt på eller stäng av mikrofonen", - "videoblur": "", - "muteEveryone": "Tysta alla", - "toggleFilmstrip": "", - "privateMessage": "", - "moreOptions": "", - "help": "", - "download": "" + "videoblur": "" }, "addPeople": "Lägg till personer i samtal", "audioOnlyOff": "Avsluta ljudläget", @@ -656,20 +616,8 @@ "tileViewToggle": "Öppna eller stäng panelvyn", "toggleCamera": "Byta kamera", "videomute": "Aktivera / avaktivera kameran", - "startvideoblur": "Blurra min bakgrund", - "stopvideoblur": "Inaktivera bakgrundsblurr", - "noisyAudioInputDesc": "Din mikrofon skapar brus, tysta din mikrofon eller byt ljudenhet.", - "noAudioSignalTitle": "Det kommer inget ljud från din mikrofon!", - "muteEveryone": "Tysta alla", - "privateMessage": "Skicka privat meddelande", - "noisyAudioInputTitle": "", - "noAudioSignalDialInLinkDesc": "", - "noAudioSignalDialInDesc": "", - "noAudioSignalDescSuggestion": "", - "noAudioSignalDesc": "", - "moreOptions": "", - "help": "", - "download": "" + "startvideoblur": "", + "stopvideoblur": "" }, "transcribing": { "ccButtonTooltip": "Starta / Avsluta undertexter", @@ -678,7 +626,7 @@ "failedToStart": "Det gick inte att starta transkribering", "labelToolTip": "Mötet transkriberas", "off": "Transkribering avslutades", - "pending": "Förbereder transkribering av mötet …", + "pending": "Förbereder transkribering av mötet ...", "start": "Börja visa undertexter", "stop": "Sluta visa undertexter", "tr": "TR" @@ -708,7 +656,7 @@ "videoStatus": { "audioOnly": "AUD", "audioOnlyExpanded": "Du använder ljudläget. Läget sparar bandbredd men du kan inte se andras videor.", - "callQuality": "Videokvalitet", + "callQuality": "", "hd": "HD", "highDefinition": "High definition", "labelTooiltipNoVideo": "Ingen video", @@ -716,14 +664,12 @@ "ld": "LD", "lowDefinition": "Low definition", "onlyAudioAvailable": "Enbart ljud tillgängligt", - "onlyAudioSupported": "Vi stöder bara ljud i denna webbläsare.", - "p2pEnabled": "Peer to peer-läget används", - "p2pVideoQualityDescription": "I peer to peer-läget kan mottagen videokvalitet bara växlas mellan hög kvalitet eller enbart ljud. Andra inställningar kommer inte att aktiveras förrän peer to peer-läget har avslutats.", + "onlyAudioSupported": "Vi stöder bara ljud i denna webbläsare", + "p2pEnabled": "Peer to peer används", + "p2pVideoQualityDescription": "", "recHighDefinitionOnly": "Föredrar high definition.", "sd": "SD", - "standardDefinition": "Standard definition", - "ldTooltip": "", - "hdTooltip": "" + "standardDefinition": "Standard definition" }, "videothumbnail": { "domute": "Tysta", @@ -734,7 +680,7 @@ "muted": "Tystad", "remoteControl": "Fjärrkontroll", "show": "", - "videomute": "Deltagaren har stäng av kameran" + "videomute": "" }, "welcomepage": { "accessibilityLabel": { @@ -762,23 +708,6 @@ "roomnameHint": "Ange namnet eller URL:en till mötesrummet du vill ansluta till. Du kan hitta på ett nytt namn, berätta då för de andra du tänker möta så de anger samma namn.", "sendFeedback": "Ge återkoppling", "terms": "Termer", - "title": "Säkra, välutrustade och helt kostnadsfria videokonferenser", - "roomNameAllowedChars": "Mötesnamn kan inte innehålla dessa tecken: ?, &,:, ', \",%, #.", - "getHelp": "", - "goSmall": "BÖRJA" - }, - "defaultNickname": "till exempel Julia Eriksson", - "chromeExtensionBanner": { - "dontShowAgain": "Visa inte det här igen", - "buttonText": "Installera Chrome-utökningen", - "installExtensionText": "Installera utökning för Google Kalender och integrationen av Office 365" - }, - "documentSharing": { - "title": "" - }, - "raisedHand": "Jag vill prata", - "lonelyMeetingExperience": { - "youAreAlone": "Du är ensam i mötet", - "button": "Bjud in andra" + "title": "Säkra, välutrustade och helt kostnadsfria videokonferenser" } } diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-tr.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-tr.json deleted file mode 100644 index 781f928ed..000000000 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-tr.json +++ /dev/null @@ -1,729 +0,0 @@ -{ - "addPeople": { - "add": "Davet et", - "countryNotSupported": "Ülke henüz desteklenmiyor", - "countryReminder": "Dış bir ülkeyi mi arıyorsunuz? Lütfen ülke koduyla başlayın!", - "disabled": "Kişi davet edemezsiniz.", - "failedToAdd": "Kişi eklenemedi", - "footerText": "Dış arama devre dışı.", - "loading": "Kişiler ve telefon numaraları aranıyor..", - "loadingNumber": "Telefon numarası doğrulanıyor", - "loadingPeople": "Davet edilecek kişi aranıyor", - "noResults": "Eşleşen sonuç bulunamadı", - "noValidNumbers": "Lütfen bir telefon numarası girin", - "searchNumbers": "Telefon numarası ekle", - "searchPeople": "Kişi ara", - "searchPeopleAndNumbers": "Kişi arayın veya telefon numarası ekleyin", - "telephone": "Telefon numarası: {{number}}", - "title": "Bu toplantıya kişi davet edin" - }, - "audioDevices": { - "bluetooth": "Bluetooth", - "headphones": "Kulaklık", - "phone": "Telefon", - "speaker": "Konuşmacı", - "none": "Ses cihazı yok" - }, - "audioOnly": { - "audioOnly": "Düşük bant genişliği" - }, - "calendarSync": { - "addMeetingURL": "Toplantı bağlantısı ekle", - "confirmAddLink": "Bu etkinliğe bir toplantı bağlantısı eklensin mi?", - "error": { - "appConfiguration": "Takvim entegrasyonu doğru yapılandırılmadı.", - "generic": "Bir hata oluştu. Lütfen takvim ayarlarını kontrol edin veya takvimi yenilemeyi deneyin.", - "notSignedIn": "Takvim etkinlikleri getirilirken bir hata meydana geldi. Lütfen takvim ayarlarını kontrol edin ve tekrar giriş yapın." - }, - "join": "Katıl", - "joinTooltip": "Toplantıya katıl", - "nextMeeting": "sonraki toplantı", - "noEvents": "Planlanmış bir etkinlik bulunmuyor.", - "ongoingMeeting": "devam eden toplantı", - "permissionButton": "Ayarları aç", - "permissionMessage": "Uygulama içinde toplantılarınızı görüntülemek için takvim erişim izni gereklidir.", - "refresh": "Takvimi yenile", - "today": "Bugün" - }, - "chat": { - "error": "Hata: mesajınız gönderilmedi. Gerekçe: {{error}}", - "messagebox": "Bir mesaj yazın", - "nickname": { - "popover": "Bir takma ad seçin", - "title": "Sohbette kullanmak için bir takma ad girin" - }, - "title": "Sohbet", - "you": "sen", - "privateNotice": "{{recipient}} için özel mesaj", - "noMessagesMessage": "Toplantıda henüz mesaj yok. Buradan bir konuşma başlatın!", - "messageTo": "{{recipient}} için özel mesaj", - "fieldPlaceHolder": "Mesajınızı buraya yazın" - }, - "connectingOverlay": { - "joiningRoom": "Toplantınıza bağlanılıyor.." - }, - "connection": { - "ATTACHED": "Eklenmiş", - "AUTHENTICATING": "Kimlik doğrulanıyor", - "AUTHFAIL": "Kimlik doğrulama başarısız", - "CONNECTED": "Bağlandı", - "CONNECTING": "Bağlanıyor", - "CONNFAIL": "Bağlantı başarısız", - "DISCONNECTED": "Bağlantı kesildi", - "DISCONNECTING": "Bağlantı kesildi", - "ERROR": "Hata", - "RECONNECTING": "Bir bağlantı hatası oluştu. Tekrar bağlanıyor...", - "LOW_BANDWIDTH": "Bant genişliğinden tasarruf etmek için {{displayName}} kişisinin videosu kapatıldı", - "GOT_SESSION_ID": "Oturum kimliği alınıyor… Tamam", - "GET_SESSION_ID_ERROR": "Oturum kimliği alma hatası: {{code}}", - "FETCH_SESSION_ID": "Oturum kimliği alınıyor…" - }, - "connectionindicator": { - "address": "Adres:", - "bandwidth": "Tahmini bant genişliği:", - "bitrate": "Bit hızı:", - "bridgeCount": "Sunucu sayısı: ", - "connectedTo": "Bağlandı:", - "framerate": "Çerçeve hızı:", - "less": "Daha az göster", - "localaddress": "Yerel adres:", - "localaddress_plural": "Yerel adresler:", - "localport": "Yerel port:", - "localport_plural": "Yerel portlar:", - "more": "Daha fazla göster", - "packetloss": "Paket kaybı:", - "quality": { - "good": "İyi", - "inactive": "Aktif değil", - "lost": "Kayıp", - "nonoptimal": "Optimal seviyede değil", - "poor": "Zayıf" - }, - "remoteaddress": "Uzak adres:", - "remoteaddress_plural": "Uzak adresler:", - "remoteport": "Uzak port:", - "remoteport_plural": "Uzak portlar:", - "resolution": "Çözünürlük:", - "status": "Bağlantı:", - "transport": "Transport:", - "transport_plural": "Transportlar:", - "turn": " (turn)" - }, - "dateUtils": { - "earlier": "Daha eski", - "today": "Bugün", - "yesterday": "Dün" - }, - "deepLinking": { - "appNotInstalled": "Bu toplantıya katılmak için {{app}} uygulamasına ihtiyacınız var.", - "description": "Hiçbir şey olmadı mı? Toplantınızı {{app}} masaüstü uygulamasında başlatmaya çalıştık. Tekrar deneyin veya {{app}} web uygulamasını açın.", - "descriptionWithoutWeb": "", - "downloadApp": "Uygulamayı indir", - "launchWebButton": "Web'de aç", - "openApp": "Uygulamaya devam et", - "title": "Toplantınız {{app}} uygulamasında açılıyor...", - "tryAgainButton": "Masaüstünde tekrar deneyin" - }, - "defaultLink": "örneğin {{url}}", - "deviceError": { - "cameraError": "Kameraya erişilemedi", - "cameraPermission": "Kameraya erişim izni alınamadı", - "microphoneError": "Mikrofona erişilemedi", - "microphonePermission": "Mikrofon erişim izni alınamadı" - }, - "deviceSelection": { - "noPermission": "İzin alınamadı", - "previewUnavailable": "Önizleme mevcut değil", - "selectADevice": "Cihaz seç", - "testAudio": "Bir test sesi çal" - }, - "dialog": { - "accessibilityLabel": { - "liveStreaming": "Canlı akış" - }, - "allow": "İzin ver", - "alreadySharedVideoMsg": "Başka zaten bir video paylaşıyor. Bu toplantı aynı anda yalnızca bir paylaşılan videoya izin veriyor.", - "alreadySharedVideoTitle": "Yalnızca bir paylaşılan videoya izin veriliyor", - "applicationWindow": "Uygulama penceresi", - "Back": "Geri", - "cameraConstraintFailedError": "Kameranız gerekli bazı özellikleri karşılayamıyor.", - "cameraNotFoundError": "Kamera bulunamadı", - "cameraNotSendingData": "Kameranıza erişemiyoruz. Lütfen başka bir uygulamanın bu cihazı kullanıp kullanmadığını kontrol edin, Ayarlar menüsünden başka bir cihaz seçin veya uygulamayı yeniden yüklemeyi deneyin.", - "cameraNotSendingDataTitle": "Kameraya erişilemiyor", - "cameraPermissionDeniedError": "Kamera kullanımına izin vermediniz. Yine de toplantıya katılabilirsiniz, ancak diğerleri sizi göremez. Bunu düzeltmek için kamera butonunu kullanın.", - "cameraUnknownError": "Bilinmeyen bir nedenden dolayı kamera kullanılamıyor.", - "cameraUnsupportedResolutionError": "Kameranız gerekli video çözünürlüğünü desteklemiyor.", - "Cancel": "İptal", - "close": "Kapat", - "conferenceDisconnectMsg": "Ağ bağlantınızı kontrol etmek isteyebilirsiniz. {{seconds}} saniye içinde yeniden bağlanıyor ...", - "conferenceDisconnectTitle": "Bağlantınız kesildi.", - "conferenceReloadMsg": "Bunu düzeltmeye çalışıyoruz. {{seconds}} saniye içinde yeniden bağlanıyor ...", - "conferenceReloadTitle": "Ne yazık ki bir şeyler ters gitti.", - "confirm": "Onayla", - "confirmNo": "Hayır", - "confirmYes": "Evet", - "connectError": "Hata! Bir şeyler ters gitti ve toplantıya bağlanamadık.", - "connectErrorWithMsg": "Hata! Bir şeyler ters gitti ve konferansa bağlanamadık: {{msg}}", - "connecting": "Bağlanıyor", - "contactSupport": "Destek ekibine erişin", - "copy": "Kopyala", - "dismiss": "Son ver", - "displayNameRequired": "Görünür ad gerekli", - "done": "Bitti", - "enterDisplayName": "Lütfen bir görünür ad girin", - "error": "Hata", - "externalInstallationMsg": "Masaüstü paylaşım uzantımızı yüklemeniz gerekmektedir.", - "externalInstallationTitle": "Uzantı gerekli", - "goToStore": "Mağazaya git", - "gracefulShutdown": "Hizmetimiz şu anda bakım için devre dışı. Lütfen daha sonra tekrar deneyiniz.", - "IamHost": "Toplantı sahibiyim", - "incorrectRoomLockPassword": "", - "incorrectPassword": "Kullanıcı adı veya parola hatalı", - "inlineInstallationMsg": "Masaüstü paylaşım uzantımızı yüklemeniz gerekmektedir.", - "inlineInstallExtension": "Şimdi yükle", - "internalError": "Hata! Bir şeyler ters gitti. Şu hata oluştu: {{error}}", - "internalErrorTitle": "İç hata", - "kickMessage": "Ah! Toplantıdan çıkarıldınız!", - "kickParticipantButton": "Çıkar", - "kickParticipantDialog": "Bu katılımcıyı çıkarmak istediğinizden emin misiniz?", - "kickParticipantTitle": "Bu katılımcı çıkarılsın mı?", - "kickTitle": "Toplantıdan çıkarıldı", - "liveStreaming": "Canlı akış", - "liveStreamingDisabledForGuestTooltip": "Konuklar canlı akışa başlayamaz.", - "liveStreamingDisabledTooltip": "Canlı akışı başlatma devre dışı.", - "lockMessage": "Toplantı kilitlenemedi.", - "lockRoom": "Toplantı parolası ekle", - "lockTitle": "Kilitlenemedi", - "logoutQuestion": "Oturumu kapatmak ve toplantıyı durdurmak istediğinizden emin misiniz?", - "logoutTitle": "Oturumu kapat", - "maxUsersLimitReached": "Maksimum katılımcı sayısı sınırına ulaşıldı. Toplantı dolu. Lütfen toplantı sahibiyle iletişime geçin veya daha sonra tekrar deneyin!", - "maxUsersLimitReachedTitle": "Maksimum katılımcı sınırına ulaşıldı", - "micConstraintFailedError": "Mikrofonunuz gerekli özelliklerin bazılarını karşılayamıyor.", - "micNotFoundError": "Mikrofon bulunamadı.", - "micNotSendingData": "Mikrofonunuza erişemiyoruz. Lütfen Ayarlar menüsünden başka bir cihaz seçin veya uygulamayı yeniden yüklemeyi deneyin.", - "micNotSendingDataTitle": "Mikrofona erişilemiyor", - "micPermissionDeniedError": "Mikrofon kullanımına izin vermediniz. Yine de toplantıya katılabilirsiniz, ancak diğerleri sizi duyamaz. Bunu düzeltmek için mikrofon butonunu kullanın.", - "micUnknownError": "Bilinmeyen bir nedenden dolayı mikrofon kullanılamıyor.", - "muteParticipantBody": "Bunların sesini açamazsınız, ancak istedikleri zaman kendileri seslerini açabilirler.", - "muteParticipantButton": "Sustur", - "muteParticipantDialog": "Bu katılımcının sesini kapatmak istediğinizden emin misiniz? Bunların sesini açamazsınız, ancak istedikleri zaman kendileri seslerini açabilirler.", - "muteParticipantTitle": "Bu katılımcı susturulsun mu?", - "Ok": "Tamam", - "passwordLabel": "Parola", - "passwordNotSupported": "Toplantı parolası ayarlama desteklenmiyor.", - "passwordNotSupportedTitle": "Parola desteklenmiyor", - "passwordRequired": "Parola gerekli", - "popupError": "Tarayıcınız bu siteden açılan pencereleri engelliyor. Lütfen tarayıcınızın güvenlik ayarlarından açılır pencereleri etkinleştirin ve tekrar deneyin.", - "popupErrorTitle": "Açılır pencere engellendi", - "recording": "Kaydediliyor", - "recordingDisabledForGuestTooltip": "Misafirler kayıt etmeye başlayamaz.", - "recordingDisabledTooltip": "Kaydetmeye başlama devre dışı.", - "rejoinNow": "Tekrar katıl", - "remoteControlAllowedMessage": "{{user}} uzaktan kontrol isteğinizi kabul etti!", - "remoteControlDeniedMessage": "{{user}} uzaktan kontrol isteğinizi reddetti!", - "remoteControlErrorMessage": "{{user}} katılımcısından uzaktan kontrol izinleri istenmeye çalışılırken bir hata oluştu!", - "remoteControlRequestMessage": "{{user}} katılımcısının masaüstünüzü uzaktan kontrol etmesine izin veriyor musunuz?", - "remoteControlShareScreenWarning": "\"Allow\" butonuna bastığınızda ekranınızı paylaşacağınızı unutmayın!", - "remoteControlStopMessage": "Uzaktan kontrol oturumu sona erdi!", - "remoteControlTitle": "Uzak masaüstü kontrolü", - "Remove": "Kaldır", - "removePassword": "Şifreyi kaldır", - "removeSharedVideoMsg": "Paylaşılan videonuzu kaldırmak istediğinizden emin misiniz?", - "removeSharedVideoTitle": "Paylaşılan videoyu kaldır", - "reservationError": "Rezervasyon sistemi hatası", - "reservationErrorMsg": "Hata kodu: {{code}}, mesaj: {{msg}}", - "retry": "Yeniden Dene", - "screenSharingFailedToInstall": "Hata! Ekran paylaşım uzantınız yüklenemedi.", - "screenSharingFailedToInstallTitle": "Ekran paylaşım uzantısı yüklenemedi", - "screenSharingFirefoxPermissionDeniedError": "Ekranınızı paylaşmaya çalışırken bir şeyler ters gitti. Lütfen bize izin verdiğinizden emin olun.", - "screenSharingFirefoxPermissionDeniedTitle": "Hata! Ekran paylaşımına başlayamadık!", - "screenSharingPermissionDeniedError": "Hata! Ekran paylaşma uzantısı izinlerinizle ilgili bir sorun oluştu. Lütfen yeniden yükleyin ve tekrar deneyin.", - "serviceUnavailable": "Hizmet kullanılamıyor", - "sessTerminated": "Arama sonlandırıldı", - "Share": "Paylaş", - "shareVideoLinkError": "Lütfen doğru bir Youtube bağlantısı sağlayın.", - "shareVideoTitle": "Bir video paylaş", - "shareYourScreen": "Ekranınızı paylaşın", - "shareYourScreenDisabled": "Ekran paylaşımı devre dışı.", - "shareYourScreenDisabledForGuest": "Konuklar ekran paylaşımı yapamaz.", - "startLiveStreaming": "Canlı akışı başlat", - "startRecording": "Kaydı başlat", - "startRemoteControlErrorMessage": "Uzaktan kontrol oturumunu başlatmaya çalışırken bir hata oluştu!", - "stopLiveStreaming": "Canlı akışı durdur", - "stopRecording": "Kaydı durdur", - "stopRecordingWarning": "Kaydı durdurmak istediğinizden emin misiniz?", - "stopStreamingWarning": "Canlı akışı durdurmak istediğinizden emin misiniz?", - "streamKey": "Canlı akış anahtarı", - "Submit": "Gönder", - "thankYou": "{{appName}} kullandığınız için teşekkürler!", - "token": "token", - "tokenAuthFailed": "Üzgünüz, bu görüşmeye katılmanıza izin verilmiyor.", - "tokenAuthFailedTitle": "Kimlik doğrulama başarısız", - "transcribing": "Deşifre ediliyor", - "unlockRoom": "Toplantı parolasını kaldır", - "userPassword": "kullancı parolası", - "WaitForHostMsg": "<b>{{room}}</b> toplantısı henüz başlamadı. Toplantı sahibi sizseniz, lütfen kimlik doğrulaması yapın. Değilseniz lütfen toplantı sahibinin gelmesini bekleyin.", - "WaitForHostMsgWOk": "<b>{{room}}</b> toplantısı henüz başlamadı. Toplantı sahibi sizseniz, kimlik doğrulaması için Tamam butonuna basın. Değilseniz lütfen toplantı sahibinin gelmesini bekleyin.", - "WaitingForHost": "Toplantı sahibi bekleniyor...", - "Yes": "Evet", - "yourEntireScreen": "Tüm ekranınız" - }, - "dialOut": { - "statusMessage": "şimdi {{status}}" - }, - "feedback": { - "average": "Orta", - "bad": "Kötü", - "detailsLabel": "Bize daha fazla bilgi verin.", - "good": "İyi", - "rateExperience": "Toplantı deneyiminizi derecelendirin", - "veryBad": "Çok kötü", - "veryGood": "Çok iyi" - }, - "incomingCall": { - "answer": "Cevapla", - "audioCallTitle": "Gelen sesli arama", - "decline": "Reddet", - "productLabel": "Jitsi Meet'den", - "videoCallTitle": "Gelen görüntülü arama" - }, - "info": { - "accessibilityLabel": "Bilgiyi göster", - "addPassword": "Şifre ekle", - "cancelPassword": "Şifreyi iptal et", - "conferenceURL": "Bağlantı:", - "country": "Ülke", - "dialANumber": "Toplantınıza katılmak için bu numaralardan birini çevirin ve ardından kodu girin.", - "dialInConferenceID": "KOD:", - "dialInNotSupported": "Maalesef arama şu anda desteklenmiyor.", - "dialInNumber": "Arama:", - "dialInSummaryError": "Arama bilgisi getirilirken hata oluştu. Lütfen daha sonra tekrar deneyin.", - "dialInTollFree": "Ücretsiz", - "genericError": "Ah! Bir şeyler ters gitti.", - "inviteLiveStream": "Bu toplantının canlı akışını görüntülemek için şu bağlantıyı tıklayın: {{url}}", - "invitePhone": "Tek dokunuşla sesli arama: {{number}},,{{conferenceID}}#", - "invitePhoneAlternatives": "", - "inviteURLFirstPartGeneral": "Bir toplantıya katılmaya davet edildiniz.", - "inviteURLFirstPartPersonal": "{{name}} sizi bir toplantıya davet ediyor.\n", - "inviteURLSecondPart": "\nToplantıya katıl:\n{{url}}\n", - "liveStreamURL": "Canlı akış:", - "moreNumbers": "Daha fazla numara", - "noNumbers": "Arama numarası yok", - "noPassword": "Yok", - "noRoom": "Aranacak oda belirtilmedi.", - "numbers": "Arama Numaraları", - "password": "Şifre:", - "title": "Paylaş", - "tooltip": "Bu toplantı için bağlantıyı ve arama bilgilerini paylaşın", - "label": "Toplantı bilgileri" - }, - "inviteDialog": { - "alertText": "Bazı katılımcılar davet edilemedi.", - "header": "Davet et", - "searchCallOnlyPlaceholder": "Telefon numarasını girin", - "searchPeopleOnlyPlaceholder": "Katılımcı ara", - "searchPlaceholder": "Katılımcı veya telefon numarası", - "send": "Gönder" - }, - "inlineDialogFailure": { - "msg": "Biraz tökezledik.", - "retry": "Tekrar dene", - "support": "Destek", - "supportMsg": "Bu olmaya devam ederse, ulaşın" - }, - "keyboardShortcuts": { - "focusLocal": "Videoma odaklan", - "focusRemote": "Başka bir kişinin videosuna odaklan", - "fullScreen": "Tam ekran görüntüle veya çık", - "keyboardShortcuts": "Klavye kısayolları", - "localRecording": "Kayıt denetimlerini göster veya gizle", - "mute": "Mikrofonu aç veya kapat", - "pushToTalk": "Konuşmak için bas", - "raiseHand": "Elinizi kaldırın veya indirin", - "showSpeakerStats": "Konuşmacı istatistiklerini göster", - "toggleChat": "Mesajlaşmayı aç veya kapat", - "toggleFilmstrip": "Video önizlemelerini göster veya gizle", - "toggleScreensharing": "Kamera ve ekran paylaşımı arasında geçiş yap", - "toggleShortcuts": "Klavye kısayollarını göster veya gizle", - "videoMute": "Kamerayı aç veya kapat" - }, - "liveStreaming": { - "busy": "Akış kaynaklarını serbest bırakmaya çalışıyoruz. Lütfen birkaç dakika içinde tekrar deneyin.", - "busyTitle": "Tüm yayıncılar şu anda meşgul", - "changeSignIn": "Hesap değiştir.", - "choose": "Canlı bir akış seçin", - "chooseCTA": "Bir akış seçeneği belirleyin. Şu anda {{email}} olarak giriş yaptınız.", - "enterStreamKey": "Youtube canlı akış anahtarınızı buraya girin.", - "error": "Canlı Akış başarısız oldu. Lütfen tekrar deneyin.", - "errorAPI": "Youtube yayınlarınıza erişirken bir hata oluştu. Lütfen tekrar giriş yapmayı deneyin.", - "errorLiveStreamNotEnabled": "{{email}} için Canlı Akış etkin değil. Lütfen canlı akışı etkinleştirin veya canlı akışın etkin olduğu bir hesaba giriş yapın.", - "expandedOff": "Canlı akış durdu", - "expandedOn": "Toplantı şu anda Youtube'da yayınlanıyor.", - "expandedPending": "Canlı akış başlatılıyor...", - "failedToStart": "Canlı Akış başlatılamadı", - "getStreamKeyManually": "Canlı akış alınamadı. Canlı akış anahtarınızı Youtube'dan almayı deneyin.", - "invalidStreamKey": "Canlı akış anahtarı yanlış olabilir.", - "off": "Canlı Akış durduruldu", - "on": "Canlı Akış", - "pending": "Canlı Akış başlatılıyor...", - "serviceName": "Canlı Akış hizmeti", - "signedInAs": "Şu anda oturum açmış durumdasınız:", - "signIn": "Google ile giriş yap", - "signInCTA": "Oturum açın veya Youtube'dan canlı akış anahtarınızı girin.", - "signOut": "Çıkış yap", - "start": "Bir canlı akış başlat", - "streamIdHelp": "Bu nedir?", - "unavailableTitle": "Canlı Akış kullanılamıyor" - }, - "localRecording": { - "clientState": { - "off": "Kapalı", - "on": "Açık", - "unknown": "Bilinmiyor" - }, - "dialogTitle": "Kayıt Kontrolleri", - "duration": "Süre", - "durationNA": "Kullanılamaz", - "encoding": "Kodlama", - "label": "KK", - "labelToolTip": "Kayıt meşgul", - "localRecording": "Kayıt", - "me": "Ben", - "messages": { - "engaged": "Kayıt meşgul", - "finished": "{{token}} kayıt oturumu tamamlandı. Lütfen kaydedilen dosyayı yöneticiye gönderin.", - "finishedModerator": "{{token}} kayıt oturumu tamamlandı. Parça kaydedildi. Lütfen diğer katılımcılardan kayıtlarını göndermelerini isteyin.", - "notModerator": "Yönetici değilsiniz. Kaydı başlatamaz veya durduramazsınız." - }, - "moderator": "Yönetici", - "no": "Hayır", - "participant": "Katılımcı", - "participantStats": "Katılımcı İstatistikleri", - "sessionToken": "Oturum Tokeni", - "start": "Kaydı başlat", - "stop": "Kaydı durdur", - "yes": "Evet" - }, - "lockRoomPassword": "parola", - "lockRoomPasswordUppercase": "Parola", - "me": "ben", - "notify": { - "connectedOneMember": "{{name}} toplantıya katıldı", - "connectedThreePlusMembers": "{{name}} ve {{count}} kişi daha toplantıya katıldı", - "connectedTwoMembers": "{{first}} ve {{second}} toplantıya katıldı", - "disconnected": "bağlantı kesildi", - "focus": "Toplantı odağı", - "focusFail": "{{component}} uygun değil - {{ms}} saniye içinde tekrar deneyin", - "grantedTo": "{{to}} kişisine yönetici hakları verildi!", - "invitedOneMember": "{{name}} davet edildi", - "invitedThreePlusMembers": "{{name}} ve {{count}} kişi daha davet edildi", - "invitedTwoMembers": "{{first}} ve {{second}} davet edildi", - "kickParticipant": "{{kicked}} kişisi {{kicker}} tarafından çıkarıldı", - "me": "Ben", - "moderator": "Yönetici hakları alındı!", - "muted": "Görüşmeye sesiniz kapalı olarak başladınız.", - "mutedTitle": "Sesiniz kapalı!", - "mutedRemotelyTitle": "{{participantDisplayName}} tarafından sessize alındınız!", - "mutedRemotelyDescription": "", - "passwordRemovedRemotely": "", - "passwordSetRemotely": "", - "raisedHand": "{{name}} konuşmak istiyor.", - "somebody": "Birisi", - "startSilentTitle": "", - "startSilentDescription": "", - "suboptimalExperienceDescription": "Mmm... {{appName}} ile olan deneyiminizin burada çok iyi olmayacağından korkuyoruz. Bunu iyileştirmenin yollarını arıyoruz, ancak o zamana kadar lütfen şunlardan birini deneyin: <a href='static/recommendedBrowsers.html' target='_blank'>fully supported browsers</a>.", - "suboptimalExperienceTitle": "Tarayıcı Uyarısı", - "unmute": "", - "newDeviceCameraTitle": "Yeni kamera algılandı", - "newDeviceAudioTitle": "Yeni ses aygıtı algılandı", - "newDeviceAction": "Kullan" - }, - "passwordSetRemotely": "başka katılımcı tarafından ayarlandı", - "passwordDigitsOnly": "{{number}} rakama kadar", - "poweredby": "gücünün kaynağı", - "presenceStatus": { - "busy": "Meşgul", - "calling": "Arıyor...", - "connected": "Bağlandı", - "connecting": "Bağlanıyor...", - "connecting2": "Bağlanıyor*...", - "disconnected": "Bağlantı kesildi", - "expired": "Süresi doldu", - "ignored": "Yok sayıldı", - "initializingCall": "Arama başlatılıyor...", - "invited": "Davet edildi", - "rejected": "Reddedildi", - "ringing": "Çalıyor..." - }, - "profile": { - "setDisplayNameLabel": "Görünür adınızı ayarlayın", - "setEmailInput": "E-posta adresinizi girin", - "setEmailLabel": "Gravatar e-postanızı ayarlayın", - "title": "Profil" - }, - "recording": { - "authDropboxText": "Dropbox'a yükle", - "availableSpace": "Kullanılabilir alan: {{spaceLeft}} MB (yaklaşık {{duration}} dakika kayıt)", - "beta": "BETA", - "busy": "Kayıt kaynaklarını boşaltmaya çalışıyoruz. Lütfen birkaç dakika içinde tekrar deneyin.", - "busyTitle": "Tüm kayıt cihazları şu anda meşgul", - "error": "Kayıt başarısız oldu. Lütfen tekrar deneyin.", - "expandedOff": "Kayıt durdu", - "expandedOn": "Toplantı şu anda kaydediliyor.", - "expandedPending": "Kayıt başlatılıyor ...", - "failedToStart": "Kayıt başlatılamadı", - "fileSharingdescription": "Toplantı katılımcılarıyla kaydı paylaş", - "live": "CANLI", - "loggedIn": "{{userName}} olarak giriş yapıldı", - "off": "Kayıt durdu", - "on": "Kaydediliyor", - "pending": "Toplantıyı kaydetmeye hazırlanıyor ...", - "rec": "KAYIT", - "serviceDescription": "Kaydınız kayıt hizmeti tarafından kaydedilecektir", - "serviceName": "Kayıt hizmeti", - "signIn": "Giriş yap", - "signOut": "Çıkış yap", - "unavailable": "Ah! {{serviceName}} şu anda kullanılamıyor. Sorunu çözmek için çalışıyoruz. Lütfen daha sonra tekrar deneyin.", - "unavailableTitle": "Kayıt yapılamıyor" - }, - "sectionList": { - "pullToRefresh": "Yenilemek için çekin" - }, - "settings": { - "calendar": { - "about": "{{appName}} takvim entegrasyonu, yaklaşan etkinlikleri okuyabilmesi için takviminize güvenli bir şekilde erişmek için kullanılır.", - "disconnect": "Bağlantıyı Kes", - "microsoftSignIn": "Microsoft ile oturum aç", - "signedIn": "Şu anda {{email}} için takvim etkinliklerine erişiliyor. Takvim etkinliklerine erişmeyi durdurmak için aşağıdaki Bağlantıyı Kes butonuna tıklayın.", - "title": "Takvim" - }, - "devices": "Cihazlar", - "followMe": "Beni takip edenler", - "language": "Dil", - "loggedIn": "{{name}} olarak giriş yapıldı", - "moderator": "Yönetici", - "more": "Daha fazla", - "name": "Ad", - "noDevice": "Yok", - "selectAudioOutput": "Ses çıkışı", - "selectCamera": "Kamera", - "selectMic": "Mikrofon", - "startAudioMuted": "Herkes ses kapalı başlasın", - "startVideoMuted": "Herkes görüntü kapalı başlasın", - "title": "Ayarlar" - }, - "settingsView": { - "alertOk": "Tamam", - "alertTitle": "Uyarı", - "alertURLText": "Girilen sunucu bağlantısı geçersiz", - "buildInfoSection": "Yapı Bilgisi", - "conferenceSection": "Toplantı", - "displayName": "Görünür ad", - "email": "E-posta", - "header": "Ayarlar", - "profileSection": "Profil", - "serverURL": "Sunucu Bağlantısı", - "startWithAudioMuted": "Ses kapalı başla", - "startWithVideoMuted": "Görüntü kapalı başla", - "version": "Versiyon" - }, - "share": { - "dialInfoText": "\n\n=====\n\nTelefonunuzdan mı aramak istiyorsunuz?\n\n{{defaultDialInNumber}}Bu toplantının telefon numaralarını aramak için bu bağlantıyı tıklayın\n{{dialInfoPageUrl}}", - "mainText": "Toplantıya katılmak için aşağıdaki bağlantıyı tıklayın:\n{{roomUrl}}" - }, - "speaker": "Konuşmacı", - "speakerStats": { - "hours": "{{count}}sa", - "minutes": "{{count}}dk", - "name": "Ad", - "seconds": "{{count}}sn", - "speakerStats": "Konuşmacı İstatistikleri", - "speakerTime": "Konuşmacı Süresi" - }, - "startupoverlay": { - "policyText": " ", - "title": "{{app}} kameranızı ve mikrofonunuzu kullanmaya ihtiyaç duyuyor." - }, - "suspendedoverlay": { - "rejoinKeyTitle": "Tekrar katıl", - "text": "Tekrar bağlanmak için <i>Tekrar katıl</i> butonuna basın.", - "title": "Bu bilgisayar uyku moduna geçtiği için görüntülü görüşmeniz kesildi." - }, - "toolbar": { - "accessibilityLabel": { - "audioOnly": "Yalnızca sesi aç/kapat", - "audioRoute": "Ses aygıtını seçin", - "callQuality": "Arama kalitesini yönetin", - "cc": "Altyazıları aç/kapat", - "chat": "Mesajlaşma penceresini aç/kapat", - "document": "Paylaşılan dokümanı aç/kapat", - "feedback": "Geri bildirim bırakın", - "fullScreen": "Tam ekranı aç/kapat", - "hangup": "Aramadan ayrıl", - "invite": "İnsanları davet et", - "kick": "Katılımcı çıkar", - "localRecording": "Kayıt denetimlerini aç/kapat", - "lockRoom": "Toplantı parolasını aç/kapat", - "moreActions": "Diğer işlemler menüsünü aç/kapat", - "moreActionsMenu": "Diğer işlemler menüsü", - "mute": "Sesi aç/kapat", - "pip": "Resim içinde Resim modunu aç/kapat", - "profile": "Profilinizi düzenleyin", - "raiseHand": "El kaldırmayı aç/kapat", - "recording": "Kaydetmeyi aç/kapat", - "remoteMute": "Katılımcının sesini kapat", - "Settings": "Ayarları aç/kapat", - "sharedvideo": "Youtube video paylaşmayı aç/kapat", - "shareRoom": "Birini davet et", - "shareYourScreen": "Ekran paylaşımını aç/kapat", - "shortcuts": "Kısayolları aç/kapat", - "show": "", - "speakerStats": "Konuşmacı istatistiklerini aç/kapat", - "tileView": "Döşeme görünümünü aç/kapat", - "toggleCamera": "Kamerayı aç/kapat", - "videomute": "Sessiz videoyu aç/kapat", - "videoblur": "" - }, - "addPeople": "Aramanıza kişi ekleyin", - "audioOnlyOff": "Yalnızca ses modunu devre dışı bırak", - "audioOnlyOn": "Yalnızca ses modunu etkinleştir", - "audioRoute": "Ses aygıtını seçin", - "authenticate": "Kimlik doğrula", - "callQuality": "Arama kalitesini yönetin", - "chat": "Mesajlaşmayı aç/kapat", - "closeChat": "Mesajlaşmayı kapat", - "documentClose": "Paylaşılan dokümanı kapat", - "documentOpen": "Paylaşılan dokümanı aç", - "enterFullScreen": "Tam ekran görüntüle", - "enterTileView": "Döşeme görünümüne geç", - "exitFullScreen": "Tam ekrandan çık", - "exitTileView": "Döşeme görünümünden çık", - "feedback": "Geri bildirim bırakın", - "hangup": "Ayrıl", - "invite": "Kişi davet et", - "login": "Oturum aç", - "logout": "Oturum kapat", - "lowerYourHand": "Elinizi indirin", - "moreActions": "Daha fazla işlem", - "mute": "Sessiz / Sesli", - "openChat": "Mesajlaşmayı aç", - "pip": "Resim içinde Resim moduna gir", - "profile": "Profilinizi düzenleyin", - "raiseHand": "Elinizi kaldırın/indirin", - "raiseYourHand": "Elinizi kaldırın", - "Settings": "Ayarlar", - "sharedvideo": "Bir Youtube videosu paylaş", - "shareRoom": "Birini davet et", - "shortcuts": "Kısayolları göster", - "speakerStats": "Konuşmacı istatistikleri", - "startScreenSharing": "Ekran paylaşımını başlat", - "startSubtitles": "Altyazıları başlat", - "stopScreenSharing": "Ekran paylaşımını durdur", - "stopSubtitles": "Altyazıları durdur", - "stopSharedVideo": "Youtube videosunu durdur", - "talkWhileMutedPopup": "Bir şey mi dediniz? Mikrofonunuz kapalı.", - "tileViewToggle": "Döşeme görünümünü aç/kapat", - "toggleCamera": "Kamerayı aç/kapat", - "videomute": "Kamera başlat / durdur", - "startvideoblur": "", - "stopvideoblur": "" - }, - "transcribing": { - "ccButtonTooltip": "Altyazılıar başlat / durdur", - "error": "Deşifre etme başarısız oldu. Lütfen tekrar deneyin.", - "expandedLabel": "Deşifre etme açık", - "failedToStart": "Deşifre etme başlatılamadı", - "labelToolTip": "Toplantı deşifre ediliyor", - "off": "Deşifre etme durdu", - "pending": "Toplantıyı deşifre etmeye hazırlanıyor...", - "start": "Altyazıları göstermeye başla", - "stop": "Altyazıları göstermeyi durdur", - "tr": "TR" - }, - "userMedia": { - "androidGrantPermissions": "Tarayıcınız izin istediğinde <b><i>İzin Ver</i></b> seçeneğini seçin.", - "chromeGrantPermissions": "Tarayıcınız izin istediğinde <b><i>İzin Ver</i></b> seçeneğini seçin.", - "edgeGrantPermissions": "Tarayıcınız izin istediğinde <b><i>Evet</i></b> seçeneğini seçin.", - "electronGrantPermissions": "Lütfen kameranızı ve mikrofonunuzu kullanmak için izin verin", - "firefoxGrantPermissions": "Tarayıcınız izin istediğinde <b><i>Seçilen Aygıtı Paylaş</i></b> seçeneğini seçin.", - "iexplorerGrantPermissions": "Tarayıcınız izin istediğinde <b><i>Tamam</i></b> seçeneğini seçin.", - "nwjsGrantPermissions": "Lütfen kameranızı ve mikrofonunuzu kullanmak için izin verin", - "operaGrantPermissions": "Tarayıcınız izin istediğinde <b><i>İzin Ver</i></b> seçeneğini seçin.", - "react-nativeGrantPermissions": "Tarayıcınız izin istediğinde <b><i>İzin Ver</i></b> seçeneğini seçin.", - "safariGrantPermissions": "Tarayıcınız izin istediğinde <b><i>Tamam</i></b> seçeneğini seçin." - }, - "videoSIPGW": { - "busy": "Kaynakları serbest bırakmaya çalışıyoruz. Lütfen birkaç dakika içinde tekrar deneyin.", - "busyTitle": "Oda hizmeti şu anda meşgul", - "errorAlreadyInvited": "{{displayName}} zaten davet edildi", - "errorInvite": "Toplantı henüz oluşturulmadı. Lütfen daha sonra tekrar deneyin.", - "errorInviteFailed": "Sorunu çözmek için çalışıyoruz. Lütfen daha sonra tekrar deneyin.", - "errorInviteFailedTitle": "{{displayName}} davet edilemedi", - "errorInviteTitle": "Odaya davet edilirken hata oluştu", - "pending": "{{displayName}} davet edildi" - }, - "videoStatus": { - "audioOnly": "SES", - "audioOnlyExpanded": "Yalnızca ses modundasınız. Bu mod bant genişliğinden tasarruf sağlar, ancak başkalarının videolarını göremezsiniz.", - "callQuality": "Arama Kalitesi", - "hd": "HD", - "highDefinition": "Yüksek çözünürlük", - "labelTooiltipNoVideo": "Görüntü yok", - "labelTooltipAudioOnly": "Yalnızca ses modu etkin", - "ld": "LD", - "lowDefinition": "Düşük çözünürlük", - "onlyAudioAvailable": "Yalnızca ses kullanılabilir", - "onlyAudioSupported": "Bu tarayıcıda yalnızca sesi destekliyoruz.", - "p2pEnabled": "Peer to peer Etkin", - "p2pVideoQualityDescription": "Peer to peer modunda, arama kalitesi yalnızca yüksek çözünürlük ve yalnızca ses arasında değiştirilebilir. Peer to peer modundan çıkılmadıkça diğer ayarlar kabul edilmez.", - "recHighDefinitionOnly": "Yalnızca yüksek çözünürlüğü tercih et.", - "sd": "SD", - "standardDefinition": "Standart çözünürlük" - }, - "videothumbnail": { - "domute": "Sustur", - "flip": "Döndür", - "kick": "Çıkarıldı", - "moderator": "Yönetici", - "mute": "Katılımcı sessiz", - "muted": "Sessiz", - "remoteControl": "Uzaktan kontrol", - "show": "", - "videomute": "Katılımcı kamerayı durdurdu" - }, - "welcomepage": { - "accessibilityLabel": { - "join": "Katılmak için dokunun", - "roomname": "Oda adı girin" - }, - "appDescription": "Durma ve tüm ekiple görüntülü sohbet et. Hatta tanıdığın herkesi davet et. {{app}} tüm gün, her gün ücretsiz olarak kullanabileceğiniz, hesap gerektirmeden kullanbilieceğiniz tamamen şifrelenmiş, % 100 özgür bir video konferans çözümüdür.", - "audioVideoSwitch": { - "audio": "Ses", - "video": "Görüntü" - }, - "calendar": "Takvim", - "connectCalendarButton": "Takviminizi bağlayın", - "connectCalendarText": "", - "enterRoomTitle": "Yeni bir toplantı başlat", - "go": "GİT", - "join": "KATIL", - "info": "Bilgi", - "privacy": "Gizlilik", - "recentList": "En son", - "recentListDelete": "Sil", - "recentListEmpty": "En son görüşülenler listeniz şu anda boş. Sohbet edin ve son toplantılarınızı burada görüntüleyin.", - "reducedUIText": "", - "roomname": "Oda adı girin", - "roomnameHint": "Katılmak istediğiniz odanın adını veya bağlantısını girin. İstediğiniz oda adını uydurabilirsiniz. Aynı odada buluşmak için görüşmek istediğiniz kişilere bunu iletmeniz yeterli.", - "sendFeedback": "Geri bildirim gönder", - "terms": "Kurallar", - "title": "Güvenli, tüm özelliklere erişimli ve tamamen ücretsiz görüntülü arama", - "getHelp": "Yardım alın" - }, - "defaultNickname": "örnek Jane Pink", - "chromeExtensionBanner": { - "dontShowAgain": "Bunu bir daha gösterme", - "buttonText": "Chrome Eklentisi'ni indirin", - "installExtensionText": "Google Takvim ve Office 365 entegrasyonu için uzantıyı yükleyin" - } -} diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-vi.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-vi.json index dac4b5984..17918ce46 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-vi.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-vi.json @@ -54,7 +54,7 @@ "title": "Chat" }, "connectingOverlay": { - "joiningRoom": "Đang kết nối tới cuộc họp của bạn…" + "joiningRoom": "Đang kết nối tới cuộc họp của bạn..." }, "connection": { "ATTACHED": "Đã đính kèm", @@ -111,7 +111,7 @@ "downloadApp": "Tải phần mềm", "launchWebButton": "Chạy trên web", "openApp": "Tiếp tục ứng dụng này", - "title": "Thực hiện cuộc họp trên {{app}}…", + "title": "Thực hiện cuộc họp trên {{app}}...", "tryAgainButton": "Thử lại trên desktop" }, "defaultLink": "ví dụ: {{url}}", @@ -145,9 +145,9 @@ "cameraUnsupportedResolutionError": "Camera của bạn không hỗ trợ độ phân giải video yêu cầu.", "Cancel": "Hủy", "close": "Đóng", - "conferenceDisconnectMsg": "Bạn có thể muốn kiểm tra kết nối mạng của mình. Đang kết nối lại trong {{seconds}} giây…", + "conferenceDisconnectMsg": "Bạn có thể muốn kiểm tra kết nối mạng của mình. Đang kết nối lại trong {{seconds}} giây...", "conferenceDisconnectTitle": "Bạn đã bị ngắt kết nối.", - "conferenceReloadMsg": "Chúng tôi đang cố gắng sửa lỗi này. Đang kết nối lại trong {{seconds}} giây…", + "conferenceReloadMsg": "Chúng tôi đang cố gắng sửa lỗi này. Đang kết nối lại trong {{seconds}} giây...", "conferenceReloadTitle": "Thật không may, có điều gì đó đã sai.", "confirm": "Xác nhận", "confirmNo": "Không", @@ -254,7 +254,7 @@ "userPassword": "mật khẩu người dùng", "WaitForHostMsg": "Cuộc họp <b>{{room}}</b> chưa được khởi tạo. Nếu bạn là chủ nghị vui lòng xác thực. Nếu không, vui lòng đợi chủ nghị.", "WaitForHostMsgWOk": "Cuộc họp <b>{{room}}</b> chưa được khởi tạo. Nếu bạn là chủ nghị vui lòng nhấn OK để xác thực. Nếu không, vui lòng đợi chủ nghị.", - "WaitingForHost": "Đang đợi chủ nghị …", + "WaitingForHost": "Đang đợi chủ nghị ...", "Yes": "Có", "yourEntireScreen": "Toàn bộ màn hình của bạn" }, @@ -290,7 +290,7 @@ "dialInSummaryError": "Lỗi nạp thông tin quay số. Vui lòng thử lại.", "dialInTollFree": "Miễn phí", "genericError": "Chà, có gì đó không ổn.", - "inviteLiveStream": "Để xem phát trực tuyến cuộc họp này, chọn liên kết: {{url}}", + "inviteLiveStream": "Để xem phát trực tuyến cuộc họp này, chọn liên kết: {{url}}", "invitePhone": "", "invitePhoneAlternatives": "", "inviteURLFirstPartGeneral": "Bạn được mời tham gia một cuộc họp.", @@ -346,16 +346,16 @@ "enterStreamKey": "Nhập key trực tuyến Youtube của bạn.", "error": "Phát trực tuyến thất bại. Xin vui lòng thử lại.", "errorAPI": "Lỗi xảy ra khi truy cập phát sóng Youtube của bạn. Vui lòng truy cập lại.", - "errorLiveStreamNotEnabled": "Phát trực tuyến không được bật với email {{email}}. Vui lòng bật phát trực tuyến hoặc truy cập một tài khoản đã bật phát trực tuyến.", + "errorLiveStreamNotEnabled": "Phát trực tuyến không được bật với email {{email}}. Vui lòng bật phát trực tuyến hoặc truy cập một tài khoản đã bật phát trực tuyến.", "expandedOff": "Phát trực tuyến đã dừng", "expandedOn": "Cuộc họp đang được phát trên Youtube.", - "expandedPending": "Phát trực tuyến đang bắt đầu…", + "expandedPending": "Phát trực tuyến đang bắt đầu...", "failedToStart": "Không thể bắt đầu phát trực tuyến", "getStreamKeyManually": "Không thể thu nhận phát trực tuyến nào. Thử lấy mã phát trực tuyến từ Youtube.", "invalidStreamKey": "Mã phát trực tuyến có thể sai.", "off": "Phát trực tuyến đã dừng", "on": "Phát trực tuyến", - "pending": "Đang bắt đầu phát trực tuyến…", + "pending": "Đang bắt đầu phát trực tuyến...", "serviceName": "Dịch vụ Phát trực tuyến", "signedInAs": "Bạn đang đăng nhập theo:", "signIn": "Đăng nhập với Google", @@ -398,7 +398,7 @@ "lockRoomPasswordUppercase": "Mật khẩu", "me": "Tôi", "notify": { - "connectedOneMember": "{{name}} đã tham gia cuộc họp", + "connectedOneMember": "{{name}} đã tham gia cuộc họp", "connectedThreePlusMembers": "{{name}} và{{count}} khác đã tham gia cuộc họp", "connectedTwoMembers": "{{first}} và{{second}} đã tham gia cuộc họp", "disconnected": "đã ngắt kết nối", @@ -433,22 +433,22 @@ "poweredby": "Được hỗ trợ bởi", "presenceStatus": { "busy": "Bận", - "calling": "Đang gọi…", + "calling": "Đang gọi...", "connected": "Đã kết nối", - "connecting": "Đang kết nối…", + "connecting": "Đang kết nối...", "connecting2": "Đang kết nối*...", "disconnected": "Đã ngắt kết nối", "expired": "Hết hạn", "ignored": "Đã bỏ qua", - "initializingCall": "Đang tạo cuộc gọi…", + "initializingCall": "Đang tạo cuộc gọi...", "invited": "Đã mời", "rejected": "Đã từ chối", - "ringing": "Đang đổ chuông…" + "ringing": "Đang đổ chuông..." }, "profile": { "setDisplayNameLabel": "Nhập tên hiển thị của bạn", "setEmailInput": "Nhập địa chỉ e-mail", - "setEmailLabel": "Nhập địa chỉ Gravatar thư điện tử của bạn", + "setEmailLabel": "Nhập địa chỉ gravatar email của bạn", "title": "Hồ sơ" }, "recording": { @@ -460,14 +460,14 @@ "error": "Ghi âm không thành công. Vui lòng thử lại.", "expandedOff": "Ghi hình đã dừng", "expandedOn": "Cuộc họp đang được ghi hình.", - "expandedPending": "Ghi hình đang khởi động…", + "expandedPending": "Ghi hình đang khởi động...", "failedToStart": "Khởi động ghi âm thất bại", "fileSharingdescription": "Chia sẻ ghi hình với người tham gia họp", "live": "Trực tuyến", "loggedIn": "Đã đăng nhập dưới tên {{userName}}", "off": "Đã ngừng ghi âm", "on": "Đang ghi âm", - "pending": "Đang chuẩn bị để ghi hình cuộc họp…", + "pending": "Đang chuẩn bị để ghi hình cuộc họp...", "rec": "REC", "serviceDescription": "Ghi hình của bạn sẽ được lưu bởi dịch vụ ghi hình", "serviceName": "Dịch vụ ghi hình", @@ -563,7 +563,7 @@ "recording": "Mở/Đóng Ghi hình", "remoteMute": "Tắt tiếng người tham gia", "Settings": "Mở/Đóng Cấu hình", - "sharedvideo": "Mở/Đóng Chia sẻ YouTube", + "sharedvideo": "Mở/Đóng Chia sẻ Youtube", "shareRoom": "Mời ai đó", "shareYourScreen": "Mở/Đóng Chia sẻ màn hình", "shortcuts": "Mở/Đóng Phím tắt", @@ -625,7 +625,7 @@ "failedToStart": "Khởi chạy phiên âm thất bại", "labelToolTip": "Cuộc họp đang được phiên âm", "off": "Phiên âm đã dừng", - "pending": "Đang chuẩn bị phiên âm cuộc họp…", + "pending": "Đang chuẩn bị phiên âm cuộc họp...", "start": "Bắt đầu hiển thị phụ đề", "stop": "Dừng hiển thị phụ đề", "tr": "TR" @@ -650,7 +650,7 @@ "errorInviteFailed": "Chúng tôi đang xử lý vấn đề. Vui lòng thử lại sau.", "errorInviteFailedTitle": "Mời {{displayName}} thất bại", "errorInviteTitle": "Lỗi mời họp", - "pending": "{{displayName}} đã được mời" + "pending": "{{displayName}} đã được mời" }, "videoStatus": { "audioOnly": "AUD", @@ -709,4 +709,4 @@ "terms": "Điều kiện", "title": "Bảo mật, đầy đủ tính năng và miễn phí hoàn toàn" } -} +} \ No newline at end of file diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-zhCN.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-zhCN.json index dffbd0751..ae86676ee 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-zhCN.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-zhCN.json @@ -1,21 +1,21 @@ { "addPeople": { - "add": "添加", - "countryNotSupported": "当前国家暂时未被支持。", + "add": "邀请", + "countryNotSupported": "目的国家暂时未被支持。", "countryReminder": "尝试在美国之外通话?请检查国家代码!", - "disabled": "关闭", - "failedToAdd": "添加失败", - "footerText": "底部文本", - "loading": "正在加载", - "loadingNumber": "正在加载号码", - "loadingPeople": "正在加载会议人员", - "noResults": "没有找到查询结果", - "noValidNumbers": "无效号码", - "searchNumbers": "查询号码", + "disabled": "您不能邀请成员", + "failedToAdd": "添加参与者失败", + "footerText": "禁止拨号。", + "loading": "查找联系人或者电话号码", + "loadingNumber": "验证电话号码", + "loadingPeople": "正在搜索需要邀请的成员", + "noResults": "没有符合要求的搜索结果", + "noValidNumbers": "请输入一个电话号码", + "searchNumbers": "添加电话成员", "searchPeople": "查找人员", "searchPeopleAndNumbers": "搜索成员或添加其电话号码", "telephone": "电话号码: {{number}}", - "title": "会议标题" + "title": "邀请成员与会" }, "audioDevices": { "bluetooth": "蓝牙", @@ -25,13 +25,13 @@ "none": "没有可用的音频设备" }, "audioOnly": { - "audioOnly": "仅语音支持" + "audioOnly": "低带宽" }, "calendarSync": { "addMeetingURL": "添加会议链接", "confirmAddLink": "是否在此事件中添加Jitsi链接", "error": { - "appConfiguration": "配置错误", + "appConfiguration": "日历集成配置不正确。", "generic": "发生错误。请检查日历设置或尝试刷新日历。", "notSignedIn": "查看日历事件验证出错。请检查日历设置,然后再次尝试登录。" }, @@ -56,7 +56,7 @@ "title": "输入一个昵称用于聊天" }, "privateNotice": "与 {{recipient}} 的私人聊天", - "title": "话题", + "title": "聊天", "you": "您" }, "chromeExtensionBanner": { @@ -65,13 +65,13 @@ "dontShowAgain": "" }, "connectingOverlay": { - "joiningRoom": "会议连接中…" + "joiningRoom": "会议连接中..." }, "connection": { "ATTACHED": "已接入", "AUTHENTICATING": "认证中", "AUTHFAIL": "认证失败", - "CONNECTED": "连接中…", + "CONNECTED": "连接中...", "CONNECTING": "连接中", "CONNFAIL": "连接失败", "DISCONNECTED": "已断开连接", @@ -116,7 +116,7 @@ "downloadApp": "下载应用", "launchWebButton": "在网页中启动", "openApp": "继续", - "title": "在 {{app}}中登录会议…", + "title": "在 {{app}}中登录会议...", "tryAgainButton": "请尝试重启桌面版应用程序" }, "defaultLink": "例如 {{url}}", @@ -284,7 +284,7 @@ "veryGood": "非常好" }, "incomingCall": { - "answer": "应答", + "answer": "回复", "audioCallTitle": "来电", "decline": "解除,离开", "productLabel": "来自Jitsi Meet", @@ -292,9 +292,9 @@ }, "info": { "accessibilityLabel": "显示信息", - "addPassword": "添加密码", - "cancelPassword": "取消密码", - "conferenceURL": "会议链接:", + "addPassword": "", + "cancelPassword": "", + "conferenceURL": "链接:", "country": "国家", "dialANumber": "若要加入会议,请拨打其中一个号码,然后输入pin码。", "dialInConferenceID": "PIN:", @@ -315,7 +315,7 @@ "noPassword": "未发现设备", "noRoom": "没有指定要呼入的房间。", "numbers": "呼入号码", - "password": "密码", + "password": "", "title": "分享", "tooltip": "共享此会议的链接和拨入信息", "label": "会议信息" @@ -377,7 +377,7 @@ "signIn": "使用谷歌登录", "signInCTA": "输入 YouTube 串流密钥或者登录 YouTube 帐号。", "signOut": "登出", - "start": "开始", + "start": "开始直播", "streamIdHelp": "这是什么?", "unavailableTitle": "流媒体直播不可用" }, @@ -416,10 +416,10 @@ "notify": { "connectedOneMember": "{{name}} 加入会议", "connectedThreePlusMembers": "{{name}} 和其他 {{count}} 人加入会议", - "connectedTwoMembers": "{{first}} 和 {{second}} 加入会议", + "connectedTwoMembers": "{{first}} 和 {{second}} 加入会议", "disconnected": "已断开连接", "focus": "会议聚焦", - "focusFail": "{{component}} 不可用 - 在{{ms}}秒后重试", + "focusFail": "{{component}} 不可用 - 在{{ms}}秒后重试", "grantedTo": "主持权限已授予{{to}}!", "invitedOneMember": "{{name}} 已被邀请", "invitedThreePlusMembers": "", @@ -449,17 +449,17 @@ "poweredby": "技术支持", "presenceStatus": { "busy": "忙碌", - "calling": "通话中…", - "connected": "连接中…", - "connecting": "连接中…", + "calling": "通话中...", + "connected": "连接中...", + "connecting": "连接中...", "connecting2": "连接中...", "disconnected": "已断开连接", "expired": "已过期", "ignored": "已忽略", - "initializingCall": "初始化呼叫…", + "initializingCall": "初始化呼叫...", "invited": "邀请", "rejected": "拒绝", - "ringing": "响铃…" + "ringing": "响铃..." }, "profile": { "setDisplayNameLabel": "设定您的显示名称", @@ -477,7 +477,7 @@ "error": "录制失败。请重新尝试。", "expandedOff": "录制已停止", "expandedOn": "此会议正在被录制。", - "expandedPending": "录制正在启动…", + "expandedPending": "录制正在启动...", "failedToStart": "录制启动失败", "fileSharingdescription": "跟与会者分享录制", "live": "直播", @@ -486,7 +486,7 @@ "offBy": "", "on": "录制中", "onBy": "", - "pending": "正在准备录制会议…", + "pending": "正在准备录制会议....", "rec": "REC录制", "serviceDescription": "录制服务将保存您的录制", "serviceName": "录制服务", @@ -504,10 +504,10 @@ "disconnect": "断开连接", "microsoftSignIn": "Microsoft帐号登录", "signedIn": "目前通过{{email}}获取日历事件。点击下方断开连接按钮停止访问。", - "title": "题目" + "title": "日历" }, "devices": "设备", - "followMe": "分机随行", + "followMe": "所有人跟随我", "language": "语言", "loggedIn": "以{{name}} 登录", "moderator": "管理员", @@ -519,10 +519,10 @@ "selectMic": "麦克风", "startAudioMuted": "所有人开始时静音", "startVideoMuted": "所有人开始时隐藏视频画面", - "title": "抬头" + "title": "设置" }, "settingsView": { - "advanced": "高级", + "advanced": "", "alertOk": "确认", "alertTitle": "警告", "alertURLText": "服务器 URL 无效", @@ -535,13 +535,13 @@ "header": "设置", "profileSection": "简介", "serverURL": "服务器 URL", - "showAdvanced": "显示高级设置", + "showAdvanced": "", "startWithAudioMuted": "启动并关闭音频", "startWithVideoMuted": "启动并关闭视频", "version": "版本" }, "share": { - "dialInfoText": "拨号文本", + "dialInfoText": "", "mainText": "点击以下链接加入会议:{{roomUrl}}\n" }, "speaker": "发言人", @@ -589,7 +589,7 @@ "recording": "开启 / 停止 视频录制", "remoteMute": "静音与会者", "Settings": "显示 / 隐藏 设置", - "sharedvideo": "开启 / 关闭 YouTube 影片分享", + "sharedvideo": "开启 / 关闭 Youtube 影片分享", "shareRoom": "邀请他人", "shareYourScreen": "开启 / 关闭 屏幕分享", "shortcuts": "切换快捷方式", @@ -659,7 +659,7 @@ "failedToStart": "开启转录失败", "labelToolTip": "会议正在转录", "off": "停止转录", - "pending": "正在准备转录会议…", + "pending": "正在准备转录会议...", "start": "开启显示字幕", "stop": "停止显示字幕", "tr": "TR" @@ -687,9 +687,9 @@ "pending": "{{displayName}} 已被邀请" }, "videoStatus": { - "audioOnly": "仅语音支持", + "audioOnly": "AUD声音", "audioOnlyExpanded": "", - "callQuality": "呼叫质量", + "callQuality": "", "hd": "高清", "hdTooltip": "观看高清视频", "highDefinition": "高清", diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-zhTW.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-zhTW.json index c3af672ab..192a61ac3 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-zhTW.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main-zhTW.json @@ -2,13 +2,13 @@ "addPeople": { "add": "邀請", "countryNotSupported": "此目標區域尚未支援。", - "countryReminder": "嘗試撥打到美國以外的地區嗎?請確認在開頭加入國家代碼!", + "countryReminder": "嘗試在美國以外地區通話?請確認開頭使用的國家代碼!", "disabled": "您不可以邀請人員。", "failedToAdd": "增加參與人失敗", "footerText": "對外播號已停用。", "loading": "尋找聯絡人及電話號碼", "loadingNumber": "驗證電話號碼", - "loadingPeople": "正在搜尋邀請的人員", + "loadingPeople": "正在尋搜人員進行邀請", "noResults": "沒有符合要求的搜尋結果", "noValidNumbers": "請輸入一組電話號碼", "searchNumbers": "新增電話號碼", @@ -18,7 +18,7 @@ "title": "邀請人員參加會議" }, "audioDevices": { - "bluetooth": "藍牙", + "bluetooth": "藍芽", "headphones": "耳機", "phone": "電話", "speaker": "發言者", @@ -37,11 +37,11 @@ }, "join": "參加", "joinTooltip": "參加會議", - "nextMeeting": "下一個會議", - "noEvents": "已經沒有排程的事件。", + "nextMeeting": "下次會議", + "noEvents": "沒有預定事件排入行程。", "ongoingMeeting": "正在進行的會議", "permissionButton": "開啟設定", - "permissionMessage": "必須先取得行事曆的存取權限才能查看您應用程式中的會議。", + "permissionMessage": "行事曆允許權限是必須的,以查看您在應用程式中的會議。", "refresh": "重新整理行事曆", "today": "今日" }, @@ -50,7 +50,7 @@ "fieldPlaceHolder": "在此輸入您的訊息", "messagebox": "輸入訊息", "messageTo": "私人訊息傳送至 {{recipient}}", - "noMessagesMessage": "此會議尚無訊息。在此開始對話交談!", + "noMessagesMessage": "會議中還沒有訊息。在此開始對話!", "nickname": { "popover": "選擇名稱", "title": "輸入名稱來使用交談" @@ -81,7 +81,7 @@ "connectionindicator": { "address": "位址:", "bandwidth": "估計頻寬:", - "bitrate": "位元率:", + "bitrate": "比特率:", "bridgeCount": "伺服器數量:", "connectedTo": "已連接至:", "framerate": "影格率:", @@ -93,7 +93,7 @@ "quality": { "good": "很好", "inactive": "未啟用", - "lost": "遺失", + "lost": "漏失", "nonoptimal": "不甚理想", "poor": "不好" }, @@ -116,21 +116,21 @@ }, "deepLinking": { "appNotInstalled": "在您的手機上需要 {{app}} 行動應用程式去加入這場會議。", - "description": "沒有發生作用嗎?我們嘗試在您的 {{app}} 桌面應用程式發起會議。請再試一次,或是在 {{app}} 網路應用程式發起會議。", + "description": "沒有發生作用嗎?我們嘗試發起您的會議於 {{app}} 桌面應用程式。請再試一次,或是在 {{app}} 網路應用程式發起會議。", "descriptionWithoutWeb": "毫無作用嗎?我們已試著將您的會議在桌機應用工具 {{app}} 中啟動。", "downloadApp": "下載應用 APP", "launchWebButton": "在網路上發起", "openApp": "繼續前往此應用程式", - "title": "正在 {{app}} 發起您的會議...", + "title": "發起您的會議於 {{app}}...", "tryAgainButton": "在桌面上再試一次" }, "defaultLink": "例如 {{url}}", "defaultNickname": "例如 春嬌 志明", "deviceError": { - "cameraError": "無法存取您的攝影裝置", - "cameraPermission": "無法獲得攝影裝置存取權限", - "microphoneError": "無法存取您的麥克風", - "microphonePermission": "無法獲得麥克風存取權限" + "cameraError": "無法取用您的攝影裝置", + "cameraPermission": "無法獲得攝影裝置取用權限", + "microphoneError": "無法取用您的麥克風", + "microphonePermission": "無法獲得麥克風取用權限" }, "deviceSelection": { "noPermission": "未取得權限", @@ -149,14 +149,14 @@ "Back": "返回", "cameraConstraintFailedError": "您的攝影裝置不符合要求。", "cameraNotFoundError": "未發現攝影裝置。", - "cameraNotSendingData": "我們無法存取您的攝影裝置。請檢查是否有其他應用程式正在使用這個裝置,否則請從裝置選單裡選擇其他設備或者重新裝載。", - "cameraNotSendingDataTitle": "無法存取攝影裝置", + "cameraNotSendingData": "我們無法取用您的攝影裝置。請檢查是否有其他程序正在使用這個設備,否則請從設置選單裡選擇其他設備或者重新裝載。", + "cameraNotSendingDataTitle": "無法取用攝影裝置", "cameraPermissionDeniedError": "您未取得權限使用攝影裝置。您仍可參加會議,但其他人無法看到。可以利用位址欄中的攝影裝置按鈕來修正。", "cameraUnknownError": "由於不明原因,無法使用攝影裝置。", "cameraUnsupportedResolutionError": "您的攝影裝置不支援所需的影像解析度。", "Cancel": "取消", "close": "關閉", - "conferenceDisconnectMsg": "請檢查一下網路連線。將在 {{seconds}} 秒後重新連接...", + "conferenceDisconnectMsg": "請檢查一下網路連接。將在 {{seconds}} 秒後重新連接...", "conferenceDisconnectTitle": "您已經被中斷連接。", "conferenceReloadMsg": "我們正試著修復狀況。重新連接於 {{seconds}} 秒內......", "conferenceReloadTitle": "很不幸,有點出錯了。", @@ -211,17 +211,17 @@ "muteParticipantTitle": "將這位參與者設為靜音?", "Ok": "確定", "passwordLabel": "會議已被參與者鎖定。請輸入 $t(lockRoomPassword) 以加入。", - "passwordNotSupported": "尚未支援設定會議密碼 $t(lockRoomPassword)。", - "passwordNotSupportedTitle": "尚未支援 $t(lockRoomPasswordUppercase)", - "passwordRequired": "必須要有 $t(lockRoomPasswordUppercase)", - "popupError": "您的瀏覽器在此網站上阻擋彈出視窗。請在瀏覽器的安全設定中啟用並再試一次。", + "passwordNotSupported": "設置會議密碼 $t(lockRoomPassword) 尚未支援 。", + "passwordNotSupportedTitle": "$t(lockRoomPasswordUppercase) 尚未支援", + "passwordRequired": "$t(lockRoomPasswordUppercase) 必須要有", + "popupError": "您的瀏覽器在此網站上阻擋彈出視窗。請在瀏覽器的安全設置中開啟並再試一次。", "popupErrorTitle": "彈出視窗遭到阻擋", "recording": "錄影中", "recordingDisabledForGuestTooltip": "訪客無法啟動錄影。", "recordingDisabledTooltip": "啟動錄影已停用。", "rejoinNow": "立即重新加入", - "remoteControlAllowedMessage": "{{user}} 接受您進行遠端控制的請求!", - "remoteControlDeniedMessage": "{{user}} 拒絕您進行遠端控制的請求!", + "remoteControlAllowedMessage": "{{user}} 接受您進行遠端控制的要求!", + "remoteControlDeniedMessage": "{{user}} 拒絕您進行遠端控制的要求!", "remoteControlErrorMessage": "在嘗試向 {{user}} 請求遠端控制權限時發生錯誤!", "remoteControlRequestMessage": "您要允許 {{user}} 遠端控制您的桌面嗎?", "remoteControlShareScreenWarning": "注意:如果按下 \"允許\" 您將會分享出自己的螢幕!", @@ -289,9 +289,9 @@ "feedback": { "average": "普通中等", "bad": "很差", - "detailsLabel": "告訴我們關於本次會議使用上更多回饋。", + "detailsLabel": "告訴我們關於本次會議使用上更多結果。", "good": "很好", - "rateExperience": "對本次會議的體驗評分", + "rateExperience": "請您評分本次會議的體驗效果", "veryBad": "極差", "veryGood": "極好" }, @@ -325,9 +325,9 @@ "moreNumbers": "更多成員", "noNumbers": "無撥入號碼。", "noPassword": "無", - "noRoom": "沒有會議室是指定要撥入。", + "noRoom": "沒有會議室是指定要播打進入。", "numbers": "撥入號碼", - "password": "$t(lockRoomPasswordUppercase):", + "password": "$t(lockRoomPasswordUppercase):", "title": "分享", "tooltip": "顯示此會議的連結及電話撥入號碼", "label": "會議資訊" @@ -371,7 +371,7 @@ "chooseCTA": "請選擇直播串流選項。您目前是以 {{email}} 身份登入。", "enterStreamKey": "在此輸入您的 YouTube 直播串流密鑰。", "error": "直播串流失敗。請重試。", - "errorAPI": "在存取您的 YouTube 直播串流時發生問題。請重新登入。", + "errorAPI": "在取用您的 YouTube 直播串流時發生問題。請重新登入。", "errorLiveStreamNotEnabled": "直播串流在 {{email}} 尚未啟用。請開啟直播串流或登入有啟用直播串流的帳戶。", "expandedOff": "直播串流已停止", "expandedOn": "會議串流目前送至 YouTube 。", @@ -470,7 +470,7 @@ "disconnected": "已經中斷連接", "expired": "逾時未接", "ignored": "忽略不接", - "initializingCall": "撥打電話...", + "initializingCall": "播打電話...", "invited": "受邀請的", "rejected": "拒接", "ringing": "鈴鈴鈴..." @@ -478,17 +478,17 @@ "profile": { "setDisplayNameLabel": "設定您的顯示名稱", "setEmailInput": "輸入您的電子信箱", - "setEmailLabel": "設定您的大頭人像電子信箱", + "setEmailLabel": "設置您的大頭人像電子信箱", "title": "簡介" }, "raisedHand": "請求發言", "recording": { "authDropboxText": "上傳至 Dropbox", - "availableSpace": "可用空間: {{spaceLeft}} MB (錄影時間大約 {{duration}} 分鐘)", + "availableSpace": "可用空間: {{spaceLeft}} MB (大約錄影時間 {{duration}} 分鐘)", "beta": "BETA", "busy": "我們正在釋放錄影資源。請過幾分鐘後再試。", "busyTitle": "全部錄影目前忙碌", - "error": "錄影失敗。請重試。", + "error": "錄影失敗。請再次重試。", "expandedOff": "錄影已經停止", "expandedOn": "此會議目前正在錄影。", "expandedPending": "錄影正在啟動...", @@ -533,7 +533,7 @@ "selectMic": "麥克風", "startAudioMuted": "全部人啟動時處於靜音", "startVideoMuted": "全部人啟動時處於隱藏", - "title": "設定", + "title": "設置", "speakers": "揚聲器", "microphones": "麥克風" }, @@ -548,7 +548,7 @@ "disableP2P": "停用端對端模式", "displayName": "顯示名稱", "email": "電子郵件", - "header": "設定", + "header": "設置", "profileSection": "簡介", "serverURL": "伺服器 URL", "showAdvanced": "顯示進階設定", @@ -605,7 +605,7 @@ "recording": "切換錄影", "remoteMute": "靜音參與者", "Settings": "切換設定", - "sharedvideo": "切換 YouTube 影片分享", + "sharedvideo": "切換 Youtube 影片分享", "shareRoom": "邀請某人", "shareYourScreen": "切換螢幕分享", "shortcuts": "切換快捷鍵", @@ -652,7 +652,7 @@ "profile": "編輯您的簡介", "raiseHand": "舉手/取消 請求發言", "raiseYourHand": "舉手發言", - "Settings": "設定", + "Settings": "設置", "sharedvideo": "分享 YouTube 影片", "shareRoom": "邀請某人", "shortcuts": "查看快捷鍵", diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main.json b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main.json index 267340cfb..f972bd6be 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main.json +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/assets/lang/main.json @@ -251,7 +251,7 @@ "screenSharingAudio": "Share audio", "screenSharingFailedToInstall": "Oops! Your screen sharing extension failed to install.", "screenSharingFailedToInstallTitle": "Screen sharing extension failed to install", - "screenSharingFirefoxPermissionDeniedError": "Something went wrong while we were trying to share your screen. Please make sure that you have given us permission to do so.", + "screenSharingFirefoxPermissionDeniedError": "Something went wrong while we were trying to share your screen. Please make sure that you have given us permission to do so. ", "screenSharingFirefoxPermissionDeniedTitle": "Oops! We weren’t able to start screen sharing!", "screenSharingPermissionDeniedError": "Oops! Something went wrong with your screen sharing extension permissions. Please reload and try again.", "sendPrivateMessage": "You recently received a private message. Did you intend to reply to that privately, or you want to send your message to the group?", @@ -469,40 +469,13 @@ "newDeviceAudioTitle": "New audio device detected", "newDeviceAction": "Use", "OldElectronAPPTitle": "Security vulnerability!", - "oldElectronClientDescription1": "You appear to be using an old version of the Jitsi Meet client which has known security vulnerabilities. Please make sure you update to our ", + "oldElectronClientDescription1": "You appear to be using an old verion of the Jitsi Meet client which has known security vulnerabilities. Please make sure you update to our ", "oldElectronClientDescription2": "latest build", "oldElectronClientDescription3": " now!" }, "passwordSetRemotely": "set by another participant", "passwordDigitsOnly": "Up to {{number}} digits", "poweredby": "powered by", - "prejoin": { - "audioAndVideoError": "Audio and video error:", - "audioOnlyError": "Audio error:", - "audioTrackError": "Could not create audio track.", - "callMe": "Call me", - "callMeAtNumber": "Call me at this number:", - "configuringDevices": "Configuring devices...", - "connectedWithAudioQ": "You’re connected with audio?", - "copyAndShare": "Copy & share meeting link", - "dialInMeeting": "Dial into the meeting", - "dialInPin": "Dial into the meeting and enter PIN code:", - "dialing": "Dialing", - "iWantToDialIn": "I want to dial in", - "joinAudioByPhone": "Join with phone audio", - "joinMeeting": "Join meeting", - "joinWithoutAudio": "Join without audio", - "initiated": "Call initiated", - "linkCopied": "Link copied to clipboard", - "lookGood": "Speaker and microphone look good", - "or": "or", - "calling": "Calling", - "startWithPhone": "Start with phone audio", - "screenSharingError": "Screen sharing error:", - "videoOnlyError": "Video error:", - "videoTrackError": "Could not create video track.", - "viewAllNumbers": "view all numbers" - }, "presenceStatus": { "busy": "Busy", "calling": "Calling...", @@ -582,15 +555,12 @@ "settingsView": { "advanced": "Advanced", "alertOk": "OK", - "alertCancel": "Cancel", "alertTitle": "Warning", "alertURLText": "The entered server URL is invalid", "buildInfoSection": "Build Information", "conferenceSection": "Conference", "disableCallIntegration": "Disable native call integration", "disableP2P": "Disable Peer-To-Peer mode", - "disableCrashReporting": "Disable crash reporting", - "disableCrashReportingWarning": "Are you sure you want to disable crash reporting? The setting will be applied after you restart the app.", "displayName": "Display name", "email": "Email", "header": "Settings", @@ -825,6 +795,6 @@ "youAreAlone": "You are the only one in the meeting" }, "helpView": { - "header": "Help center" + "header": "Help centre" } } diff --git a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/main.jsbundle b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/main.jsbundle index f5dbff96b..0b377d3e2 100644 --- a/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/main.jsbundle +++ b/ios/Pods/JitsiMeetSDK/Frameworks/JitsiMeet.framework/main.jsbundle @@ -4,7 +4,7 @@ var __BUNDLE_START_TIME__=this.nativePerformanceNow?nativePerformanceNow():Date. !(function(n){var r=0,t=function(n,r){throw n},l={setGlobalHandler:function(n){t=n},getGlobalHandler:function(){return t},reportError:function(n){t&&t(n,!1)},reportFatalError:function(n){t&&t(n,!0)},applyWithGuard:function(n,t,u,o,e){try{return r++,n.apply(t,u)}catch(n){l.reportError(n)}finally{r--}return null},applyWithGuardIfNeeded:function(n,r,t){return l.inGuard()?n.apply(r,t):(l.applyWithGuard(n,r,t),null)},inGuard:function(){return!!r},guard:function(n,r,t){var u,o;if('function'!=typeof n)return console.warn('A function must be passed to ErrorUtils.guard, got ',n),null;var e=null!=(u=null!=(o=r)?o:n.name)?u:'<generated guard>';return function(){for(var r,u=arguments.length,o=new Array(u),a=0;a<u;a++)o[a]=arguments[a];return l.applyWithGuard(n,null!=(r=t)?r:this,o,null,e)}}};n.ErrorUtils=l})('undefined'!=typeof globalThis?globalThis:'undefined'!=typeof global?global:'undefined'!=typeof window?window:this); 'undefined'!=typeof globalThis?globalThis:'undefined'!=typeof global?global:'undefined'!=typeof window&&window,(function(){'use strict';var e=Object.prototype.hasOwnProperty;'function'!=typeof Object.entries&&(Object.entries=function(n){if(null==n)throw new TypeError('Object.entries called on non-object');var o=[];for(var t in n)e.call(n,t)&&o.push([t,n[t]]);return o}),'function'!=typeof Object.values&&(Object.values=function(n){if(null==n)throw new TypeError('Object.values called on non-object');var o=[];for(var t in n)e.call(n,t)&&o.push(n[t]);return o})})(); __d(function(g,r,i,a,m,e,d){r(d[0])},0,[1]); -__d(function(g,r,i,a,m,e,d){var n=r(d[0]),t=r(d[1]),o=t(r(d[2])),p=t(r(d[3])),u=t(r(d[4])),l=t(r(d[5])),c=t(r(d[6]));r(d[7]);var f=n(r(d[8])),s=r(d[9]),A=r(d[10]),y=r(d[11]),v=r(d[12]),C=(function(n){function t(){return(0,o.default)(this,t),(0,u.default)(this,(0,l.default)(t).apply(this,arguments))}return(0,c.default)(t,n),(0,p.default)(t,[{key:"render",value:function(){return f.default.createElement(A.App,this.props)}}]),t})(f.PureComponent);(0,v._initLogging)();var h=console.log,R=s.AppRegistry.runApplication;s.AppRegistry.runApplication=function(){console.log=function(){},R.apply(void 0,arguments),console.log=h},s.AppRegistry.registerComponent('App',function(){return C}),s.AppRegistry.registerComponent('IncomingCallApp',function(){return y.IncomingCallApp})},1,[2,3,4,5,6,9,10,12,59,15,435,1689,453]); +__d(function(g,r,i,a,m,e,d){var n=r(d[0]),t=r(d[1]),o=t(r(d[2])),p=t(r(d[3])),u=t(r(d[4])),l=t(r(d[5])),c=t(r(d[6]));r(d[7]);var f=n(r(d[8])),s=r(d[9]),A=r(d[10]),y=r(d[11]),v=r(d[12]),C=(function(n){function t(){return(0,o.default)(this,t),(0,u.default)(this,(0,l.default)(t).apply(this,arguments))}return(0,c.default)(t,n),(0,p.default)(t,[{key:"render",value:function(){return f.default.createElement(A.App,this.props)}}]),t})(f.PureComponent);(0,v._initLogging)();var h=console.log,R=s.AppRegistry.runApplication;s.AppRegistry.runApplication=function(){console.log=function(){},R.apply(void 0,arguments),console.log=h},s.AppRegistry.registerComponent('App',function(){return C}),s.AppRegistry.registerComponent('IncomingCallApp',function(){return y.IncomingCallApp})},1,[2,3,4,5,6,9,10,12,13,17,381,1656,592]); __d(function(g,r,i,a,m,e,d){m.exports=function(t){if(t&&t.__esModule)return t;var o={};if(null!=t)for(var n in t)if(Object.prototype.hasOwnProperty.call(t,n)){var c=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(t,n):{};c.get||c.set?Object.defineProperty(o,n,c):o[n]=t[n]}return o.default=t,o}},2,[]); __d(function(g,r,i,a,m,e,d){m.exports=function(n){return n&&n.__esModule?n:{default:n}}},3,[]); __d(function(g,r,i,a,m,e,d){m.exports=function(n,o){if(!(n instanceof o))throw new TypeError("Cannot call a class as a function")}},4,[]); @@ -15,1693 +15,1660 @@ __d(function(g,r,i,a,m,e,d){m.exports=function(n){if(void 0===n)throw new Refere __d(function(g,r,i,a,m,e,d){function t(o){return m.exports=t=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)},t(o)}m.exports=t},9,[]); __d(function(g,r,i,a,m,e,d){var t=r(d[0]);m.exports=function(o,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function");o.prototype=Object.create(n&&n.prototype,{constructor:{value:o,writable:!0,configurable:!0}}),n&&t(o,n)}},10,[11]); __d(function(g,r,i,a,m,e,d){function t(o,n){return m.exports=t=Object.setPrototypeOf||function(t,o){return t.__proto__=o,t},t(o,n)}m.exports=t},11,[]); -__d(function(g,r,i,a,m,e,d){r(d[0]),r(d[1])},12,[13,14]); -__d(function(g,r,i,a,m,e,d){var _;void 0===(_=g||window||this).__filename&&(_.__filename='__filename')},13,[]); -__d(function(g,r,i,a,m,e,d){var t=r(d[0]),n=r(d[1]),o=t(r(d[2]));r(d[3]);var l=t(r(d[4]));function s(t,n){return t===n?t:(o=Object.getPrototypeOf(t))&&(o=s(n,o))||(o=Object.getPrototypeOf(n))&&(o=s(t,o))?o:void 0;var o}function f(t,n){var o=null;return t&&u(t,function(t){return 1===t.nodeType&&t.nodeName===n&&(o=t,!0)}),o}function u(t,n){if(n(t))return!0;if(t=t.firstChild)do{if(u(t,n))return!0}while(t=t.nextSibling);return!1}!(function(t){var u=r(d[5]).DOMParser;if(t.DOMParser=u,void 0===t.addEventListener&&(t.addEventListener=function(){}),void 0===t.removeEventListener&&(t.removeEventListener=function(){}),void 0===t.document){var c=(new u).parseFromString('<html><head></head><body></body></html>','text/xml');void 0===c.addEventListener&&(c.addEventListener=function(){}),void 0===c.cookie&&(c.cookie=''),void 0===c.implementation.createHTMLDocument&&(c.implementation.createHTMLDocument=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:'',n=(new u).parseFromString("<html>\n <head><title>"+t+"\n \n ",'text/xml');return Object.defineProperty(n,'body',{get:function(){return n.getElementsByTagName('body')[0]}}),n});var v=Object.getPrototypeOf(c.documentElement);v&&(void 0===v.querySelector&&(v.querySelector=function(t){return f(this,t)}),void 0===v.remove&&(v.remove=function(){null!==this.parentNode&&this.parentNode.removeChild(this)}),v.hasOwnProperty('innerHTML')||Object.defineProperty(v,'innerHTML',{get:function(){return this.childNodes.toString()},set:function(t){this.textContent='';for(var n,o=(new u).parseFromString("

"+t+"
",'text/xml').documentElement;n=o.firstChild;)this.appendChild(n)}}),v.hasOwnProperty('children')||Object.defineProperty(v,'children',{get:function(){for(var t=this.childNodes,n=[],o=0,l=t[o];l;)1===l.nodeType&&n.push(l),l=t[o+=1];return n}}));var h=s(Object.getPrototypeOf(c),v);if(h&&h!==Object.getPrototypeOf({})){var p=t.console;if(p){var y=r(d[6]).levels;Object.keys(y).forEach(function(t){var n=y[t],o=p[n];'function'==typeof o&&(p[n]=function(){for(var t=arguments.length,l=new Array(t),s=0;s1&&void 0!==arguments[1]?arguments[1]:0;return o.default.setTimeout(t,n)},void 0===t.localStorage&&(t.localStorage=new l.default('@jitsi-meet/')),void 0===t.sessionStorage&&(t.sessionStorage=new l.default)})(g||window||this)},14,[3,15,383,384,385,389,392,395,396,431,434]); -__d(function(g,r,i,a,m,e,d){'use strict';r(d[0]);var t=r(d[1]);m.exports={get AccessibilityInfo(){return r(d[2])},get ActivityIndicator(){return r(d[3])},get ART(){return t('art-moved',"React Native ART has been extracted from react-native core and will be removed in a future release. It can now be installed and imported from '@react-native-community/art' instead of 'react-native'. See https://github.com/react-native-community/art"),r(d[4])},get Button(){return r(d[5])},get CheckBox(){return t('checkBox-moved',"CheckBox has been extracted from react-native core and will be removed in a future release. It can now be installed and imported from '@react-native-community/checkbox' instead of 'react-native'. See https://github.com/react-native-community/react-native-checkbox"),r(d[6])},get DatePickerIOS(){return t('DatePickerIOS-merged',"DatePickerIOS has been merged with DatePickerAndroid and will be removed in a future release. It can now be installed and imported from '@react-native-community/datetimepicker' instead of 'react-native'. See https://github.com/react-native-community/react-native-datetimepicker"),r(d[7])},get DrawerLayoutAndroid(){return r(d[8])},get FlatList(){return r(d[9])},get Image(){return r(d[10])},get ImageBackground(){return r(d[11])},get InputAccessoryView(){return r(d[12])},get KeyboardAvoidingView(){return r(d[13])},get MaskedViewIOS(){return t('maskedviewios-moved',"MaskedViewIOS has been extracted from react-native core and will be removed in a future release. It can now be installed and imported from '@react-native-community/masked-view' instead of 'react-native'. See https://github.com/react-native-community/react-native-masked-view"),r(d[14])},get Modal(){return r(d[15])},get Picker(){return r(d[16])},get PickerIOS(){return r(d[17])},get ProgressBarAndroid(){return r(d[18])},get ProgressViewIOS(){return r(d[19])},get SafeAreaView(){return r(d[20])},get ScrollView(){return r(d[21])},get SectionList(){return r(d[22])},get SegmentedControlIOS(){return r(d[23])},get Slider(){return t('slider-moved',"Slider has been extracted from react-native core and will be removed in a future release. It can now be installed and imported from '@react-native-community/slider' instead of 'react-native'. See https://github.com/react-native-community/react-native-slider"),r(d[24])},get Switch(){return r(d[25])},get RefreshControl(){return r(d[26])},get StatusBar(){return r(d[27])},get Text(){return r(d[28])},get TextInput(){return r(d[29])},get Touchable(){return r(d[30])},get TouchableHighlight(){return r(d[31])},get TouchableNativeFeedback(){return r(d[32])},get TouchableOpacity(){return r(d[33])},get TouchableWithoutFeedback(){return r(d[34])},get View(){return r(d[35])},get VirtualizedList(){return r(d[36])},get VirtualizedSectionList(){return r(d[37])},get ActionSheetIOS(){return r(d[38])},get Alert(){return r(d[39])},get Animated(){return r(d[40])},get AppRegistry(){return r(d[41])},get AppState(){return r(d[42])},get AsyncStorage(){return t('async-storage-moved',"AsyncStorage has been extracted from react-native core and will be removed in a future release. It can now be installed and imported from '@react-native-community/async-storage' instead of 'react-native'. See https://github.com/react-native-community/react-native-async-storage"),r(d[43])},get BackHandler(){return r(d[44])},get Clipboard(){return r(d[45])},get DatePickerAndroid(){return t('DatePickerAndroid-merged',"DatePickerAndroid has been merged with DatePickerIOS and will be removed in a future release. It can now be installed and imported from '@react-native-community/datetimepicker' instead of 'react-native'. See https://github.com/react-native-community/react-native-datetimepicker"),r(d[46])},get DeviceInfo(){return r(d[47])},get Dimensions(){return r(d[48])},get Easing(){return r(d[49])},get findNodeHandle(){return r(d[50]).findNodeHandle},get I18nManager(){return r(d[51])},get ImagePickerIOS(){return t('imagePickerIOS-moved',"ImagePickerIOS has been extracted from react-native core and will be removed in a future release. Please upgrade to use either '@react-native-community/react-native-image-picker' or 'expo-image-picker'. If you cannot upgrade to a different library, please install the deprecated '@react-native-community/image-picker-ios' package. See https://github.com/react-native-community/react-native-image-picker-ios"),r(d[52])},get InteractionManager(){return r(d[53])},get Keyboard(){return r(d[54])},get LayoutAnimation(){return r(d[55])},get Linking(){return r(d[56])},get NativeDialogManagerAndroid(){return r(d[57]).default},get NativeEventEmitter(){return r(d[58])},get PanResponder(){return r(d[59])},get PermissionsAndroid(){return r(d[60])},get PixelRatio(){return r(d[61])},get PushNotificationIOS(){return t('pushNotificationIOS-moved',"PushNotificationIOS has been extracted from react-native core and will be removed in a future release. It can now be installed and imported from '@react-native-community/push-notification-ios' instead of 'react-native'. See https://github.com/react-native-community/react-native-push-notification-ios"),r(d[62])},get Settings(){return r(d[63])},get Share(){return r(d[64])},get StatusBarIOS(){return t('StatusBarIOS-merged','StatusBarIOS has been merged with StatusBar and will be removed in a future release. Use StatusBar for mutating the status bar'),r(d[65])},get StyleSheet(){return r(d[66])},get Systrace(){return r(d[67])},get TimePickerAndroid(){return t('TimePickerAndroid-merged',"TimePickerAndroid has been merged with DatePickerIOS and DatePickerAndroid and will be removed in a future release. It can now be installed and imported from '@react-native-community/datetimepicker' instead of 'react-native'. See https://github.com/react-native-community/react-native-datetimepicker"),r(d[68])},get ToastAndroid(){return r(d[69])},get TurboModuleRegistry(){return r(d[70])},get TVEventHandler(){return r(d[71])},get UIManager(){return r(d[72])},get unstable_batchedUpdates(){return r(d[50]).unstable_batchedUpdates},get useWindowDimensions(){return r(d[73]).default},get UTFSequence(){return r(d[74])},get Vibration(){return r(d[75])},get YellowBox(){return r(d[76])},get DeviceEventEmitter(){return r(d[77])},get NativeAppEventEmitter(){return r(d[78])},get NativeModules(){return r(d[79])},get Platform(){return r(d[80])},get processColor(){return r(d[81])},get requireNativeComponent(){return r(d[82])},get unstable_RootTagContext(){return r(d[83])},get ColorPropType(){return r(d[84])},get EdgeInsetsPropType(){return r(d[85])},get PointPropType(){return r(d[86])},get ViewPropTypes(){return r(d[87])}}},15,[16,17,20,52,188,198,288,290,292,248,269,293,294,296,297,299,306,308,310,311,313,255,276,315,317,319,252,322,199,324,205,333,214,215,281,90,249,277,334,142,216,336,350,353,347,355,357,358,64,244,92,304,359,225,259,261,361,143,125,363,365,63,367,369,371,373,62,36,374,376,22,209,77,377,378,379,381,45,153,23,57,84,184,303,68,201,382,326]); -__d(function(g,r,i,a,m,e,d){'use strict';m.exports=function(n,o,t,f,s,u,c,l){if(!n){var v;if(void 0===o)v=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var p=[t,f,s,u,c,l],h=0;(v=new Error(o.replace(/%s/g,function(){return p[h++]}))).name='Invariant Violation'}throw v.framesToPop=1,v}}},16,[]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n={};m.exports=function(c,o){n[c]||(t(!1,o),n[c]=!0)}},17,[18]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);m.exports=t},18,[19]); -__d(function(g,r,i,a,m,e,d){"use strict";function t(t){return function(){return t}}var n=function(){};n.thatReturns=t,n.thatReturnsFalse=t(!1),n.thatReturnsTrue=t(!0),n.thatReturnsNull=t(null),n.thatReturnsThis=function(){return this},n.thatReturnsArgument=function(t){return t},m.exports=n},19,[]); -__d(function(g,r,i,a,m,e,d){'use strict';var n=r(d[0])(r(d[1])),t=r(d[2]),u=r(d[3]),c={announcementFinished:'announcementFinished',boldTextChanged:'boldTextChanged',grayscaleChanged:'grayscaleChanged',invertColorsChanged:'invertColorsChanged',reduceMotionChanged:'reduceMotionChanged',reduceTransparencyChanged:'reduceTransparencyChanged',screenReaderChanged:'screenReaderChanged'},o=new Map,s={isBoldTextEnabled:function(){return new t(function(t,u){n.default?n.default.getCurrentBoldTextState(t,u):u(u)})},isGrayscaleEnabled:function(){return new t(function(t,u){n.default?n.default.getCurrentGrayscaleState(t,u):u(u)})},isInvertColorsEnabled:function(){return new t(function(t,u){n.default?n.default.getCurrentInvertColorsState(t,u):u(u)})},isReduceMotionEnabled:function(){return new t(function(t,u){n.default?n.default.getCurrentReduceMotionState(t,u):u(u)})},isReduceTransparencyEnabled:function(){return new t(function(t,u){n.default?n.default.getCurrentReduceTransparencyState(t,u):u(u)})},isScreenReaderEnabled:function(){return new t(function(t,u){n.default?n.default.getCurrentVoiceOverState(t,u):u(u)})},get fetch(){return this.isScreenReaderEnabled},addEventListener:function(n,t){var l;return'change'===n?l=u.addListener(c.screenReaderChanged,t):c[n]&&(l=u.addListener(n,t)),o.set(t,l),{remove:s.removeEventListener.bind(null,n,t)}},setAccessibilityFocus:function(t){n.default&&n.default.setAccessibilityFocus(t)},announceForAccessibility:function(t){n.default&&n.default.announceForAccessibility(t)},removeEventListener:function(n,t){var u=o.get(t);u&&(u.remove(),o.delete(t))}};m.exports=s},20,[3,21,40,45]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var u=t(r(d[1])).get('AccessibilityManager');e.default=u},21,[2,22]); -__d(function(g,r,i,a,m,e,d){'use strict';var n=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.get=o,e.getEnforcing=function(n){var u=o(n);return(0,t.default)(null!=u,"TurboModuleRegistry.getEnforcing(...): '"+n+"' could not be found. Verify that a module by this name is registered in the native binary."),u};var t=n(r(d[1])),u=r(d[2]),l=g.__turboModuleProxy;function o(n){if(!g.RN$Bridgeless){var t=u[n];if(null!=t)return t}return null!=l?l(n):null}},22,[3,16,23]); -__d(function(g,r,i,a,m,e,d){'use strict';var n=r(d[0]),t=r(d[1]),o=r(d[2]),u=r(d[3]);function l(o,l){if(!o)return null;var f=t(o,5),v=f[0],h=f[1],y=f[2],C=f[3],p=f[4];if(u(!v.startsWith('RCT')&&!v.startsWith('RK'),"Module name prefixes should've been stripped by the native side but wasn't for "+v),!h&&!y)return{name:v};var M={};return y&&y.forEach(function(n,t){var o=C&&c(C,t),f=p&&c(p,t);u(!o||!f,'Cannot have a method that is both async and a sync hook');var v=o?'promise':f?'sync':'async';M[n]=s(l,t,v)}),n(M,h),null==M.getConstants?M.getConstants=function(){return h||Object.freeze({})}:console.warn("Unable to define method 'getConstants()' on NativeModule '"+v+"'. NativeModule '"+v+"' already has a constant or method called 'getConstants'. Please remove it."),{name:v,module:M}}function f(n,t){u(g.nativeRequireModuleConfig,"Can't lazily create module without nativeRequireModuleConfig");var o=l(g.nativeRequireModuleConfig(n),t);return o&&o.module}function s(n,t,l){var f=null;return(f='promise'===l?function(){for(var u=arguments.length,l=new Array(u),f=0;f0?s[s.length-1]:null,h=s.length>1?s[s.length-2]:null,y='function'==typeof v,C='function'==typeof h;C&&u(y,'Cannot have a non-function arg after a function arg.');var p=y?v:null,M=C?h:null,b=y+C;if(s=s.slice(0,s.length-b),'sync'===l)return o.callNativeSyncHook(n,t,s,M,p);o.enqueueNativeCall(n,t,s,M,p)}).type=l,f}function c(n,t){return-1!==n.indexOf(t)}function v(t,o){return n(o,t||{})}g.__fbGenNativeModule=l;var h={};if(g.nativeModuleProxy)h=g.nativeModuleProxy;else if(!g.nativeExtensions){var y=g.__fbBatchedBridgeConfig;u(y,'__fbBatchedBridgeConfig is not set, cannot invoke native modules');var C=r(d[4]);(y.remoteModuleConfig||[]).forEach(function(n,t){var o=l(n,t);o&&(o.module?h[o.name]=o.module:C(h,o.name,{get:function(){return f(o.name,t)}}))})}m.exports=h},23,[24,25,29,16,39]); -__d(function(g,r,i,a,m,e,d){function t(){return m.exports=t=Object.assign||function(t){for(var n=1;n=5){var c=this._queue;this._queue=[[],[],[],this._callID],this._lastFlush=o,g.nativeFlushQueueImmediate(c)}n.counterEvent('pending_js_to_native_queue',this._queue[0].length),this.__spy&&this.__spy({type:1,module:t+'',method:l,args:u})}},{key:"createDebugLookup",value:function(t,l,u){}},{key:"setImmediatesCallback",value:function(t){this._immediatesCallback=t}},{key:"__guard",value:function(t){if(this.__shouldPauseOnThrow())t();else try{t()}catch(t){s.reportFatalError(t)}}},{key:"__shouldPauseOnThrow",value:function(){return'undefined'!=typeof DebuggerInternal&&!0===DebuggerInternal.shouldPauseOnThrow}},{key:"__callImmediates",value:function(){n.beginEvent('JSTimers.callImmediates()'),null!=this._immediatesCallback&&this._immediatesCallback(),n.endEvent()}},{key:"__callFunction",value:function(t,l,u){this._lastFlush=Date.now(),this._eventLoopStartTime=this._lastFlush,this.__spy?n.beginEvent(t+"."+l+"("+o(u)+")"):n.beginEvent(t+"."+l+"(...)"),this.__spy&&this.__spy({type:0,module:t,method:l,args:u});var s=this.getCallableModule(t);h(!!s,'Module %s is not a registered callable module (calling %s)',t,l),h(!!s[l],'Method %s does not exist on module %s',l,t);var c=s[l].apply(s,u);return n.endEvent(),c}},{key:"__invokeCallback",value:function(l,u){this._lastFlush=Date.now(),this._eventLoopStartTime=this._lastFlush;var s=l>>>1,n=1&l?this._successCallbacks.get(s):this._failureCallbacks.get(s);n&&(this._successCallbacks.delete(s),this._failureCallbacks.delete(s),n.apply(void 0,t(u)))}}],[{key:"spy",value:function(t){c.prototype.__spy=!0===t?function(t){console.log((0===t.type?'N->JS':'JS->N')+" : "+(t.module?t.module+'.':'')+t.method+"("+JSON.stringify(t.args)+")")}:!1===t?null:t}}]),c})());m.exports=c},30,[31,4,5,35,36,37,16,38,17]); -__d(function(g,r,i,a,m,e,d){var n=r(d[0]),t=r(d[1]),o=r(d[2]);m.exports=function(u){return n(u)||t(u)||o()}},31,[32,33,34]); -__d(function(g,r,i,a,m,e,d){m.exports=function(n){if(Array.isArray(n)){for(var t=0,f=new Array(n.length);t=0||Object.prototype.propertyIsEnumerable.call(n,l)&&(b[l]=n[l])}return b}},55,[56]); -__d(function(g,r,i,a,m,e,d){m.exports=function(n,t){if(null==n)return{};var f,u,o={},c=Object.keys(n);for(u=0;u=0||(o[f]=n[f]);return o}},56,[]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0])(r(d[1])),s={__constants:null,OS:'ios',get Version(){return this.constants.osVersion},get constants(){return null==this.__constants&&(this.__constants=t.default.getConstants()),this.__constants},get isPad(){return'pad'===this.constants.interfaceIdiom},get isTVOS(){return s.isTV},get isTV(){return'tv'===this.constants.interfaceIdiom},get isTesting(){return!1},select:function(t){return'ios'in t?t.ios:t.default}};m.exports=s},57,[3,58]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var n=t(r(d[1])).getEnforcing('PlatformConstants');e.default=n},58,[2,22]); -__d(function(g,r,i,a,m,e,d){'use strict';m.exports=r(d[0])},59,[60]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n="function"==typeof Symbol&&("function"==typeof Symbol?Symbol.for:"@@for"),o=n?("function"==typeof Symbol?Symbol.for:"@@for")("react.element"):60103,u=n?("function"==typeof Symbol?Symbol.for:"@@for")("react.portal"):60106,f=n?("function"==typeof Symbol?Symbol.for:"@@for")("react.fragment"):60107,l=n?("function"==typeof Symbol?Symbol.for:"@@for")("react.strict_mode"):60108,c=n?("function"==typeof Symbol?Symbol.for:"@@for")("react.profiler"):60114,s=n?("function"==typeof Symbol?Symbol.for:"@@for")("react.provider"):60109,y=n?("function"==typeof Symbol?Symbol.for:"@@for")("react.context"):60110,p=n?("function"==typeof Symbol?Symbol.for:"@@for")("react.forward_ref"):60112,b=n?("function"==typeof Symbol?Symbol.for:"@@for")("react.suspense"):60113,v=n?("function"==typeof Symbol?Symbol.for:"@@for")("react.suspense_list"):60120,S=n?("function"==typeof Symbol?Symbol.for:"@@for")("react.memo"):60115,h=n?("function"==typeof Symbol?Symbol.for:"@@for")("react.lazy"):60116;n&&("function"==typeof Symbol?Symbol.for:"@@for")("react.fundamental"),n&&("function"==typeof Symbol?Symbol.for:"@@for")("react.responder");var _="function"==typeof Symbol&&("function"==typeof Symbol?Symbol.iterator:"@@iterator");function k(t){for(var n=t.message,o="https://reactjs.org/docs/error-decoder.html?invariant="+n,u=1;uD.length&&D.push(t)}function N(t,n,f,l){var c=typeof t;"undefined"!==c&&"boolean"!==c||(t=null);var s=!1;if(null===t)s=!0;else switch(c){case"string":case"number":s=!0;break;case"object":switch(t.$$typeof){case o:case u:s=!0}}if(s)return f(l,t,""===n?"."+z(t,0):n),1;if(s=0,n=""===n?".":n+":",Array.isArray(t))for(var y=0;y1&&(t-=1),t<.16666666666666666?l+6*(n-l)*t:t<.5?n:t<.6666666666666666?l+(n-l)*(.6666666666666666-t)*6:l}function n(n,t,o){var u=o<.5?o*(1+t):o+t-o*t,s=2*o-u,h=l(s,u,n+.3333333333333333),c=l(s,u,n),b=l(s,u,n-.3333333333333333);return Math.round(255*h)<<24|Math.round(255*c)<<16|Math.round(255*b)<<8}var t,o='[-+]?\\d*\\.?\\d+',u="[-+]?\\d*\\.?\\d+%";function s(){for(var l=arguments.length,n=new Array(l),t=0;t255?255:n}function c(l){return(parseFloat(l)%360+360)%360/360}function b(l){var n=parseFloat(l);return n<0?0:n>1?255:Math.round(255*n)}function p(l){var n=parseFloat(l);return n<0?0:n>100?1:n/100}var y={transparent:0,aliceblue:4042850303,antiquewhite:4209760255,aqua:16777215,aquamarine:2147472639,azure:4043309055,beige:4126530815,bisque:4293182719,black:255,blanchedalmond:4293643775,blue:65535,blueviolet:2318131967,brown:2771004159,burlywood:3736635391,burntsienna:3934150143,cadetblue:1604231423,chartreuse:2147418367,chocolate:3530104575,coral:4286533887,cornflowerblue:1687547391,cornsilk:4294499583,crimson:3692313855,cyan:16777215,darkblue:35839,darkcyan:9145343,darkgoldenrod:3095792639,darkgray:2846468607,darkgreen:6553855,darkgrey:2846468607,darkkhaki:3182914559,darkmagenta:2332068863,darkolivegreen:1433087999,darkorange:4287365375,darkorchid:2570243327,darkred:2332033279,darksalmon:3918953215,darkseagreen:2411499519,darkslateblue:1211993087,darkslategray:793726975,darkslategrey:793726975,darkturquoise:13554175,darkviolet:2483082239,deeppink:4279538687,deepskyblue:12582911,dimgray:1768516095,dimgrey:1768516095,dodgerblue:512819199,firebrick:2988581631,floralwhite:4294635775,forestgreen:579543807,fuchsia:4278255615,gainsboro:3705462015,ghostwhite:4177068031,gold:4292280575,goldenrod:3668254975,gray:2155905279,green:8388863,greenyellow:2919182335,grey:2155905279,honeydew:4043305215,hotpink:4285117695,indianred:3445382399,indigo:1258324735,ivory:4294963455,khaki:4041641215,lavender:3873897215,lavenderblush:4293981695,lawngreen:2096890111,lemonchiffon:4294626815,lightblue:2916673279,lightcoral:4034953471,lightcyan:3774873599,lightgoldenrodyellow:4210742015,lightgray:3553874943,lightgreen:2431553791,lightgrey:3553874943,lightpink:4290167295,lightsalmon:4288707327,lightseagreen:548580095,lightskyblue:2278488831,lightslategray:2005441023,lightslategrey:2005441023,lightsteelblue:2965692159,lightyellow:4294959359,lime:16711935,limegreen:852308735,linen:4210091775,magenta:4278255615,maroon:2147483903,mediumaquamarine:1724754687,mediumblue:52735,mediumorchid:3126187007,mediumpurple:2473647103,mediumseagreen:1018393087,mediumslateblue:2070474495,mediumspringgreen:16423679,mediumturquoise:1221709055,mediumvioletred:3340076543,midnightblue:421097727,mintcream:4127193855,mistyrose:4293190143,moccasin:4293178879,navajowhite:4292783615,navy:33023,oldlace:4260751103,olive:2155872511,olivedrab:1804477439,orange:4289003775,orangered:4282712319,orchid:3664828159,palegoldenrod:4008225535,palegreen:2566625535,paleturquoise:2951671551,palevioletred:3681588223,papayawhip:4293907967,peachpuff:4292524543,peru:3448061951,pink:4290825215,plum:3718307327,powderblue:2967529215,purple:2147516671,rebeccapurple:1714657791,red:4278190335,rosybrown:3163525119,royalblue:1097458175,saddlebrown:2336560127,salmon:4202722047,sandybrown:4104413439,seagreen:780883967,seashell:4294307583,sienna:2689740287,silver:3233857791,skyblue:2278484991,slateblue:1784335871,slategray:1887473919,slategrey:1887473919,snow:4294638335,springgreen:16744447,steelblue:1182971135,tan:3535047935,teal:8421631,thistle:3636451583,tomato:4284696575,turquoise:1088475391,violet:4001558271,wheat:4125012991,white:4294967295,whitesmoke:4126537215,yellow:4294902015,yellowgreen:2597139199};m.exports=function(l){var k,f=(void 0===t&&(t={rgb:new RegExp('rgb'+s(o,o,o)),rgba:new RegExp('rgba'+s(o,o,o,o)),hsl:new RegExp('hsl'+s(o,u,u)),hsla:new RegExp('hsla'+s(o,u,u,o)),hex3:/^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex4:/^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^#([0-9a-fA-F]{6})$/,hex8:/^#([0-9a-fA-F]{8})$/}),t);return'number'==typeof l?l>>>0===l&&l>=0&&l<=4294967295?l:null:(k=f.hex6.exec(l))?parseInt(k[1]+'ff',16)>>>0:y.hasOwnProperty(l)?y[l]:(k=f.rgb.exec(l))?(h(k[1])<<24|h(k[2])<<16|h(k[3])<<8|255)>>>0:(k=f.rgba.exec(l))?(h(k[1])<<24|h(k[2])<<16|h(k[3])<<8|b(k[4]))>>>0:(k=f.hex3.exec(l))?parseInt(k[1]+k[1]+k[2]+k[2]+k[3]+k[3]+'ff',16)>>>0:(k=f.hex8.exec(l))?parseInt(k[1],16)>>>0:(k=f.hex4.exec(l))?parseInt(k[1]+k[1]+k[2]+k[2]+k[3]+k[3]+k[4]+k[4],16)>>>0:(k=f.hsl.exec(l))?(255|n(c(k[1]),p(k[2]),p(k[3])))>>>0:(k=f.hsla.exec(l))?(n(c(k[1]),p(k[2]),p(k[3]))|b(k[4]))>>>0:null}},69,[]); -__d(function(g,r,i,a,m,e,d){'use strict';var n=r(d[0]),t={display:n.oneOf(['none','flex']),width:n.oneOfType([n.number,n.string]),height:n.oneOfType([n.number,n.string]),start:n.oneOfType([n.number,n.string]),end:n.oneOfType([n.number,n.string]),top:n.oneOfType([n.number,n.string]),left:n.oneOfType([n.number,n.string]),right:n.oneOfType([n.number,n.string]),bottom:n.oneOfType([n.number,n.string]),minWidth:n.oneOfType([n.number,n.string]),maxWidth:n.oneOfType([n.number,n.string]),minHeight:n.oneOfType([n.number,n.string]),maxHeight:n.oneOfType([n.number,n.string]),margin:n.oneOfType([n.number,n.string]),marginVertical:n.oneOfType([n.number,n.string]),marginHorizontal:n.oneOfType([n.number,n.string]),marginTop:n.oneOfType([n.number,n.string]),marginBottom:n.oneOfType([n.number,n.string]),marginLeft:n.oneOfType([n.number,n.string]),marginRight:n.oneOfType([n.number,n.string]),marginStart:n.oneOfType([n.number,n.string]),marginEnd:n.oneOfType([n.number,n.string]),padding:n.oneOfType([n.number,n.string]),paddingVertical:n.oneOfType([n.number,n.string]),paddingHorizontal:n.oneOfType([n.number,n.string]),paddingTop:n.oneOfType([n.number,n.string]),paddingBottom:n.oneOfType([n.number,n.string]),paddingLeft:n.oneOfType([n.number,n.string]),paddingRight:n.oneOfType([n.number,n.string]),paddingStart:n.oneOfType([n.number,n.string]),paddingEnd:n.oneOfType([n.number,n.string]),borderWidth:n.number,borderTopWidth:n.number,borderStartWidth:n.number,borderEndWidth:n.number,borderRightWidth:n.number,borderBottomWidth:n.number,borderLeftWidth:n.number,position:n.oneOf(['absolute','relative']),flexDirection:n.oneOf(['row','row-reverse','column','column-reverse']),flexWrap:n.oneOf(['wrap','nowrap','wrap-reverse']),justifyContent:n.oneOf(['flex-start','flex-end','center','space-between','space-around','space-evenly']),alignItems:n.oneOf(['flex-start','flex-end','center','stretch','baseline']),alignSelf:n.oneOf(['auto','flex-start','flex-end','center','stretch','baseline']),alignContent:n.oneOf(['flex-start','flex-end','center','stretch','space-between','space-around']),overflow:n.oneOf(['visible','hidden','scroll']),flex:n.number,flexGrow:n.number,flexShrink:n.number,flexBasis:n.oneOfType([n.number,n.string]),aspectRatio:n.number,zIndex:n.number,direction:n.oneOf(['inherit','ltr','rtl'])};m.exports=t},70,[71]); -__d(function(g,r,i,a,m,e,d){m.exports=r(d[0])()},71,[72]); -__d(function(g,r,i,a,m,e,d){'use strict';var n=r(d[0]);function t(){}function o(){}o.resetWarningCache=t,m.exports=function(){function p(t,o,p,c,s,y){if(y!==n){var f=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw f.name='Invariant Violation',f}}function c(){return p}p.isRequired=p;var s={array:p,bool:p,func:p,number:p,object:p,string:p,symbol:p,any:p,arrayOf:c,element:p,elementType:p,instanceOf:c,node:p,objectOf:c,oneOf:c,oneOfType:c,shape:c,exact:c,checkPropTypes:o,resetWarningCache:t};return s.PropTypes=s,s}},72,[73]); -__d(function(g,r,i,a,m,e,d){'use strict';m.exports='SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED'},73,[]); -__d(function(g,r,i,a,m,e,d){'use strict';var s=r(d[0]),h=r(d[1]),o={shadowColor:s,shadowOffset:h.shape({width:h.number,height:h.number}),shadowOpacity:h.number,shadowRadius:h.number};m.exports=o},74,[68,71]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),s=r(d[1]),n={transform:t.arrayOf(t.oneOfType([t.shape({perspective:t.number}),t.shape({rotate:t.string}),t.shape({rotateX:t.string}),t.shape({rotateY:t.string}),t.shape({rotateZ:t.string}),t.shape({scale:t.number}),t.shape({scaleX:t.number}),t.shape({scaleY:t.number}),t.shape({translateX:t.number}),t.shape({translateY:t.number}),t.shape({skewX:t.string}),t.shape({skewY:t.string})])),transformMatrix:function(t,s,n){if(t[s])return new Error("The transformMatrix style property is deprecated. Use `transform: [{ matrix: ... }]` instead.")},decomposedMatrix:function(t,s,n){if(t[s])return new Error("The decomposedMatrix style property is deprecated. Use `transform: [...]` instead.")},scaleX:s(t.number,'Use the transform prop instead.'),scaleY:s(t.number,'Use the transform prop instead.'),rotation:s(t.number,'Use the transform prop instead.'),translateX:s(t.number,'Use the transform prop instead.'),translateY:s(t.number,'Use the transform prop instead.')};m.exports=n},75,[71,76]); -__d(function(g,r,i,a,m,e,d){'use strict';var n=r(d[0]);m.exports=function(t,o){return function(c,u,p){n.getViewManagerConfig(p)||void 0===c[u]||console.warn("`"+u+"` supplied to `"+p+"` has been deprecated. "+o);for(var s=arguments.length,f=new Array(s>3?s-3:0),l=3;l>>8)>>>0:void 0}},84,[57,69]); -__d(function(g,r,i,a,m,e,d){'use strict';r(d[0]),r(d[1]),r(d[2]),r(d[3]);m.exports=function(t){return t}},85,[86,57,16,38]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=r(d[1]),o={createIdentityMatrix:function(){return[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},createCopy:function(t){return[t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15]]},createOrthographic:function(t,n,o,u,s,c){return[2/(n-t),0,0,0,0,2/(u-o),0,0,0,0,-2/(c-s),0,-(n+t)/(n-t),-(u+o)/(u-o),-(c+s)/(c-s),1]},createFrustum:function(t,n,o,u,s,c){var v=1/(n-t),f=1/(u-o),h=1/(s-c);return[s*v*2,0,0,0,0,s*f*2,0,0,(n+t)*v,(u+o)*f,(c+s)*h,-1,0,0,c*s*h*2,0]},createPerspective:function(t,n,o,u){var s=1/Math.tan(t/2),c=1/(o-u);return[s/n,0,0,0,0,s,0,0,0,0,(u+o)*c,-1,0,0,u*o*c*2,0]},createTranslate2d:function(t,n){var u=o.createIdentityMatrix();return o.reuseTranslate2dCommand(u,t,n),u},reuseTranslate2dCommand:function(t,n,o){t[12]=n,t[13]=o},reuseTranslate3dCommand:function(t,n,o,u){t[12]=n,t[13]=o,t[14]=u},createScale:function(t){var n=o.createIdentityMatrix();return o.reuseScaleCommand(n,t),n},reuseScaleCommand:function(t,n){t[0]=n,t[5]=n},reuseScale3dCommand:function(t,n,o,u){t[0]=n,t[5]=o,t[10]=u},reusePerspectiveCommand:function(t,n){t[11]=-1/n},reuseScaleXCommand:function(t,n){t[0]=n},reuseScaleYCommand:function(t,n){t[5]=n},reuseScaleZCommand:function(t,n){t[10]=n},reuseRotateXCommand:function(t,n){t[5]=Math.cos(n),t[6]=Math.sin(n),t[9]=-Math.sin(n),t[10]=Math.cos(n)},reuseRotateYCommand:function(t,n){t[0]=Math.cos(n),t[2]=-Math.sin(n),t[8]=Math.sin(n),t[10]=Math.cos(n)},reuseRotateZCommand:function(t,n){t[0]=Math.cos(n),t[1]=Math.sin(n),t[4]=-Math.sin(n),t[5]=Math.cos(n)},createRotateZ:function(t){var n=o.createIdentityMatrix();return o.reuseRotateZCommand(n,t),n},reuseSkewXCommand:function(t,n){t[4]=Math.tan(n)},reuseSkewYCommand:function(t,n){t[1]=Math.tan(n)},multiplyInto:function(t,n,o){var u=n[0],s=n[1],c=n[2],v=n[3],f=n[4],h=n[5],M=n[6],l=n[7],C=n[8],p=n[9],x=n[10],T=n[11],y=n[12],S=n[13],D=n[14],P=n[15],q=o[0],X=o[1],Y=o[2],I=o[3];t[0]=q*u+X*f+Y*C+I*y,t[1]=q*s+X*h+Y*p+I*S,t[2]=q*c+X*M+Y*x+I*D,t[3]=q*v+X*l+Y*T+I*P,q=o[4],X=o[5],Y=o[6],I=o[7],t[4]=q*u+X*f+Y*C+I*y,t[5]=q*s+X*h+Y*p+I*S,t[6]=q*c+X*M+Y*x+I*D,t[7]=q*v+X*l+Y*T+I*P,q=o[8],X=o[9],Y=o[10],I=o[11],t[8]=q*u+X*f+Y*C+I*y,t[9]=q*s+X*h+Y*p+I*S,t[10]=q*c+X*M+Y*x+I*D,t[11]=q*v+X*l+Y*T+I*P,q=o[12],X=o[13],Y=o[14],I=o[15],t[12]=q*u+X*f+Y*C+I*y,t[13]=q*s+X*h+Y*p+I*S,t[14]=q*c+X*M+Y*x+I*D,t[15]=q*v+X*l+Y*T+I*P},determinant:function(n){var o=t(n,16),u=o[0],s=o[1],c=o[2],v=o[3],f=o[4],h=o[5],M=o[6],l=o[7],C=o[8],p=o[9],x=o[10],T=o[11],y=o[12],S=o[13],D=o[14],P=o[15];return v*M*p*y-c*l*p*y-v*h*x*y+s*l*x*y+c*h*T*y-s*M*T*y-v*M*C*S+c*l*C*S+v*f*x*S-u*l*x*S-c*f*T*S+u*M*T*S+v*h*C*D-s*l*C*D-v*f*p*D+u*l*p*D+s*f*T*D-u*h*T*D-c*h*C*P+s*M*C*P+c*f*p*P-u*M*p*P-s*f*x*P+u*h*x*P},inverse:function(n){var u=o.determinant(n);if(!u)return n;var s=t(n,16),c=s[0],v=s[1],f=s[2],h=s[3],M=s[4],l=s[5],C=s[6],p=s[7],x=s[8],T=s[9],y=s[10],S=s[11],D=s[12],P=s[13],q=s[14],X=s[15];return[(C*S*P-p*y*P+p*T*q-l*S*q-C*T*X+l*y*X)/u,(h*y*P-f*S*P-h*T*q+v*S*q+f*T*X-v*y*X)/u,(f*p*P-h*C*P+h*l*q-v*p*q-f*l*X+v*C*X)/u,(h*C*T-f*p*T-h*l*y+v*p*y+f*l*S-v*C*S)/u,(p*y*D-C*S*D-p*x*q+M*S*q+C*x*X-M*y*X)/u,(f*S*D-h*y*D+h*x*q-c*S*q-f*x*X+c*y*X)/u,(h*C*D-f*p*D-h*M*q+c*p*q+f*M*X-c*C*X)/u,(f*p*x-h*C*x+h*M*y-c*p*y-f*M*S+c*C*S)/u,(l*S*D-p*T*D+p*x*P-M*S*P-l*x*X+M*T*X)/u,(h*T*D-v*S*D-h*x*P+c*S*P+v*x*X-c*T*X)/u,(v*p*D-h*l*D+h*M*P-c*p*P-v*M*X+c*l*X)/u,(h*l*x-v*p*x-h*M*T+c*p*T+v*M*S-c*l*S)/u,(C*T*D-l*y*D-C*x*P+M*y*P+l*x*q-M*T*q)/u,(v*y*D-f*T*D+f*x*P-c*y*P-v*x*q+c*T*q)/u,(f*l*D-v*C*D-f*M*P+c*C*P+v*M*q-c*l*q)/u,(v*C*x-f*l*x+f*M*T-c*C*T-v*M*y+c*l*y)/u]},transpose:function(t){return[t[0],t[4],t[8],t[12],t[1],t[5],t[9],t[13],t[2],t[6],t[10],t[14],t[3],t[7],t[11],t[15]]},multiplyVectorByMatrix:function(n,o){var u=t(n,4),s=u[0],c=u[1],v=u[2],f=u[3];return[s*o[0]+c*o[4]+v*o[8]+f*o[12],s*o[1]+c*o[5]+v*o[9]+f*o[13],s*o[2]+c*o[6]+v*o[10]+f*o[14],s*o[3]+c*o[7]+v*o[11]+f*o[15]]},v3Length:function(t){return Math.sqrt(t[0]*t[0]+t[1]*t[1]+t[2]*t[2])},v3Normalize:function(t,n){var u=1/(n||o.v3Length(t));return[t[0]*u,t[1]*u,t[2]*u]},v3Dot:function(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]},v3Combine:function(t,n,o,u){return[o*t[0]+u*n[0],o*t[1]+u*n[1],o*t[2]+u*n[2]]},v3Cross:function(t,n){return[t[1]*n[2]-t[2]*n[1],t[2]*n[0]-t[0]*n[2],t[0]*n[1]-t[1]*n[0]]},quaternionToDegreesXYZ:function(n,u,s){var c=t(n,4),v=c[0],f=c[1],h=c[2],M=c[3],l=v*v,C=f*f,p=h*h,x=v*f+h*M,T=M*M+l+C+p,y=180/Math.PI;return x>.49999*T?[0,2*Math.atan2(v,M)*y,90]:x<-.49999*T?[0,-2*Math.atan2(v,M)*y,-90]:[o.roundTo3Places(Math.atan2(2*v*M-2*f*h,1-2*l-2*p)*y),o.roundTo3Places(Math.atan2(2*f*M-2*v*h,1-2*C-2*p)*y),o.roundTo3Places(Math.asin(2*v*f+2*h*M)*y)]},roundTo3Places:function(t){var n=t.toString().split('e');return.001*Math.round(n[0]+'e'+(n[1]?+n[1]-3:3))},decomposeMatrix:function(t){n(16===t.length,'Matrix decomposition needs a list of 3d matrix values, received %s',t);var u=[],s=[],c=[],v=[],f=[];if(t[15]){for(var h=[],M=[],l=0;l<4;l++){h.push([]);for(var C=0;C<4;C++){var p=t[4*l+C]/t[15];h[l].push(p),M.push(3===C?0:p)}}if(M[15]=1,o.determinant(M)){if(0!==h[0][3]||0!==h[1][3]||0!==h[2][3]){var x=[h[0][3],h[1][3],h[2][3],h[3][3]],T=o.inverse(M),y=o.transpose(T);u=o.multiplyVectorByMatrix(x,y)}else u[0]=u[1]=u[2]=0,u[3]=1;for(var S=0;S<3;S++)f[S]=h[3][S];for(var D=[],P=0;P<3;P++)D[P]=[h[P][0],h[P][1],h[P][2]];c[0]=o.v3Length(D[0]),D[0]=o.v3Normalize(D[0],c[0]),v[0]=o.v3Dot(D[0],D[1]),D[1]=o.v3Combine(D[1],D[0],1,-v[0]),v[0]=o.v3Dot(D[0],D[1]),D[1]=o.v3Combine(D[1],D[0],1,-v[0]),c[1]=o.v3Length(D[1]),D[1]=o.v3Normalize(D[1],c[1]),v[0]/=c[1],v[1]=o.v3Dot(D[0],D[2]),D[2]=o.v3Combine(D[2],D[0],1,-v[1]),v[2]=o.v3Dot(D[1],D[2]),D[2]=o.v3Combine(D[2],D[1],1,-v[2]),c[2]=o.v3Length(D[2]),D[2]=o.v3Normalize(D[2],c[2]),v[1]/=c[2],v[2]/=c[2];var q,X=o.v3Cross(D[1],D[2]);if(o.v3Dot(D[0],X)<0)for(var Y=0;Y<3;Y++)c[Y]*=-1,D[Y][0]*=-1,D[Y][1]*=-1,D[Y][2]*=-1;return s[0]=.5*Math.sqrt(Math.max(1+D[0][0]-D[1][1]-D[2][2],0)),s[1]=.5*Math.sqrt(Math.max(1-D[0][0]+D[1][1]-D[2][2],0)),s[2]=.5*Math.sqrt(Math.max(1-D[0][0]-D[1][1]+D[2][2],0)),s[3]=.5*Math.sqrt(Math.max(1+D[0][0]+D[1][1]+D[2][2],0)),D[2][1]>D[1][2]&&(s[0]=-s[0]),D[0][2]>D[2][0]&&(s[1]=-s[1]),D[1][0]>D[0][1]&&(s[2]=-s[2]),{rotationDegrees:q=s[0]<.001&&s[0]>=0&&s[1]<.001&&s[1]>=0?[0,0,o.roundTo3Places(180*Math.atan2(D[0][1],D[0][0])/Math.PI)]:o.quaternionToDegreesXYZ(s,h,D),perspective:u,quaternion:s,scale:c,skew:v,translation:f,rotate:q[2],rotateX:q[0],rotateY:q[1],scaleX:c[0],scaleY:c[1],translateX:f[0],translateY:f[1]}}}}};m.exports=o},86,[25,16]); -__d(function(g,r,i,a,m,e,d){'use strict';var t={width:void 0,height:void 0};m.exports=function(h,n){return(h=h||t)!==(n=n||t)&&(h.width!==n.width||h.height!==n.height)}},87,[]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=r(d[1]),u=(r(d[2]),r(d[3]),r(d[4]),r(d[5]),(function(){function u(){t(this,u)}return n(u,null,[{key:"validateStyleProp",value:function(t,n,u){}},{key:"validateStyle",value:function(t,n){}},{key:"addValidStylePropTypes",value:function(t){}}]),u})());m.exports=u},88,[4,5,67,82,83,16]); -__d(function(g,r,i,a,m,e,d){'use strict';m.exports=function t(n){if(null!==n&&'object'==typeof n){if(!Array.isArray(n))return n;for(var f={},o=0,u=n.length;othis.eventPool.length&&this.eventPool.push(e)}function G(e){e.eventPool=[],e.getPooled=q,e.release=$}o(X.prototype,{preventDefault:function(){this.defaultPrevented=!0;var e=this.nativeEvent;e&&(e.preventDefault?e.preventDefault():"unknown"!=typeof e.returnValue&&(e.returnValue=!1),this.isDefaultPrevented=L)},stopPropagation:function(){var e=this.nativeEvent;e&&(e.stopPropagation?e.stopPropagation():"unknown"!=typeof e.cancelBubble&&(e.cancelBubble=!0),this.isPropagationStopped=L)},persist:function(){this.isPersistent=L},isPersistent:Y,destructor:function(){var e,t=this.constructor.Interface;for(e in t)this[e]=null;this.nativeEvent=this._targetInst=this.dispatchConfig=null,this.isPropagationStopped=this.isDefaultPrevented=Y,this._dispatchInstances=this._dispatchListeners=null}}),X.Interface={type:null,target:null,currentTarget:function(){return null},eventPhase:null,bubbles:null,cancelable:null,timeStamp:function(e){return e.timeStamp||Date.now()},defaultPrevented:null,isTrusted:null},X.extend=function(e){function t(){}function n(){return r.apply(this,arguments)}var r=this;t.prototype=r.prototype;var i=new t;return o(i,n.prototype),n.prototype=i,n.prototype.constructor=n,n.Interface=o({},r.Interface,e),n.extend=r.extend,G(n),n},G(X);var J=X.extend({touchHistory:function(){return null}});function K(e){return"topTouchStart"===e}function Z(e){return"topTouchMove"===e}var ee=["topTouchStart"],te=["topTouchMove"],ne=["topTouchCancel","topTouchEnd"],re=[],ie={touchBank:re,numberActiveTouches:0,indexOfSingleActiveTouch:-1,mostRecentTimeStamp:0};function le(e){return e.timeStamp||e.timestamp}function ae(e){if(null==(e=e.identifier))throw f(Error("Touch object is missing identifier."));return e}function oe(e){var t=ae(e),n=re[t];n?(n.touchActive=!0,n.startPageX=e.pageX,n.startPageY=e.pageY,n.startTimeStamp=le(e),n.currentPageX=e.pageX,n.currentPageY=e.pageY,n.currentTimeStamp=le(e),n.previousPageX=e.pageX,n.previousPageY=e.pageY,n.previousTimeStamp=le(e)):(n={touchActive:!0,startPageX:e.pageX,startPageY:e.pageY,startTimeStamp:le(e),currentPageX:e.pageX,currentPageY:e.pageY,currentTimeStamp:le(e),previousPageX:e.pageX,previousPageY:e.pageY,previousTimeStamp:le(e)},re[t]=n),ie.mostRecentTimeStamp=le(e)}function ue(e){var t=re[ae(e)];t?(t.touchActive=!0,t.previousPageX=t.currentPageX,t.previousPageY=t.currentPageY,t.previousTimeStamp=t.currentTimeStamp,t.currentPageX=e.pageX,t.currentPageY=e.pageY,t.currentTimeStamp=le(e),ie.mostRecentTimeStamp=le(e)):console.warn("Cannot record touch move without a touch start.\nTouch Move: %s\n","Touch Bank: %s",se(e),fe())}function ce(e){var t=re[ae(e)];t?(t.touchActive=!1,t.previousPageX=t.currentPageX,t.previousPageY=t.currentPageY,t.previousTimeStamp=t.currentTimeStamp,t.currentPageX=e.pageX,t.currentPageY=e.pageY,t.currentTimeStamp=le(e),ie.mostRecentTimeStamp=le(e)):console.warn("Cannot record touch end without a touch start.\nTouch End: %s\n","Touch Bank: %s",se(e),fe())}function se(e){return JSON.stringify({identifier:e.identifier,pageX:e.pageX,pageY:e.pageY,timestamp:le(e)})}function fe(){var e=JSON.stringify(re.slice(0,20));return 20a||(l=a),Ue(l,e,i)}}}),_=function(e){return xe.get(e._nativeTag)||null},P=we,R=function(e){var t=e.stateNode._nativeTag;if(void 0===t&&(t=e.stateNode.canonical._nativeTag),!t)throw f(Error("All native instances should have a tag."));return t},ye.injection.injectGlobalResponderHandler({onChange:function(e,t,n){null!==t?u.UIManager.setJSResponder(t.stateNode._nativeTag,n):u.UIManager.clearJSResponder()}});var ze=c.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;ze.hasOwnProperty("ReactCurrentDispatcher")||(ze.ReactCurrentDispatcher={current:null}),ze.hasOwnProperty("ReactCurrentBatchConfig")||(ze.ReactCurrentBatchConfig={suspense:null});var Me="function"==typeof Symbol&&("function"==typeof Symbol?Symbol.for:"@@for"),Ae=Me?("function"==typeof Symbol?Symbol.for:"@@for")("react.element"):60103,De=Me?("function"==typeof Symbol?Symbol.for:"@@for")("react.portal"):60106,Fe=Me?("function"==typeof Symbol?Symbol.for:"@@for")("react.fragment"):60107,Oe=Me?("function"==typeof Symbol?Symbol.for:"@@for")("react.strict_mode"):60108,je=Me?("function"==typeof Symbol?Symbol.for:"@@for")("react.profiler"):60114,We=Me?("function"==typeof Symbol?Symbol.for:"@@for")("react.provider"):60109,He=Me?("function"==typeof Symbol?Symbol.for:"@@for")("react.context"):60110,Qe=Me?("function"==typeof Symbol?Symbol.for:"@@for")("react.concurrent_mode"):60111,Be=Me?("function"==typeof Symbol?Symbol.for:"@@for")("react.forward_ref"):60112,Ve=Me?("function"==typeof Symbol?Symbol.for:"@@for")("react.suspense"):60113,Le=Me?("function"==typeof Symbol?Symbol.for:"@@for")("react.suspense_list"):60120,Ye=Me?("function"==typeof Symbol?Symbol.for:"@@for")("react.memo"):60115,Xe=Me?("function"==typeof Symbol?Symbol.for:"@@for")("react.lazy"):60116;Me&&("function"==typeof Symbol?Symbol.for:"@@for")("react.fundamental"),Me&&("function"==typeof Symbol?Symbol.for:"@@for")("react.responder");var qe="function"==typeof Symbol&&("function"==typeof Symbol?Symbol.iterator:"@@iterator");function $e(e){return null===e||"object"!=typeof e?null:"function"==typeof(e=qe&&e[qe]||e["@@iterator"])?e:null}function Ge(e){if(null==e)return null;if("function"==typeof e)return e.displayName||e.name||null;if("string"==typeof e)return e;switch(e){case Fe:return"Fragment";case De:return"Portal";case je:return"Profiler";case Oe:return"StrictMode";case Ve:return"Suspense";case Le:return"SuspenseList"}if("object"==typeof e)switch(e.$$typeof){case He:return"Context.Consumer";case We:return"Context.Provider";case Be:var t=e.render;return t=t.displayName||t.name||"",e.displayName||(""!==t?"ForwardRef("+t+")":"ForwardRef");case Ye:return Ge(e.type);case Xe:if(e=1===e._status?e._result:null)return Ge(e)}return null}function Je(e){var t=e;if(e.alternate)for(;t.return;)t=t.return;else{if(0!=(2&t.effectTag))return 1;for(;t.return;)if(0!=(2&(t=t.return).effectTag))return 1}return 3===t.tag?2:3}function Ke(e){if(2!==Je(e))throw f(Error("Unable to find node on an unmounted component."))}function Ze(e){var t=e.alternate;if(!t){if(3===(t=Je(e)))throw f(Error("Unable to find node on an unmounted component."));return 1===t?null:e}for(var n=e,r=t;;){var i=n.return;if(null===i)break;var l=i.alternate;if(null===l){if(null!==(r=i.return)){n=r;continue}break}if(i.child===l.child){for(l=i.child;l;){if(l===n)return Ke(i),e;if(l===r)return Ke(i),t;l=l.sibling}throw f(Error("Unable to find node on an unmounted component."))}if(n.return!==r.return)n=i,r=l;else{for(var a=!1,o=i.child;o;){if(o===n){a=!0,n=i,r=l;break}if(o===r){a=!0,r=i,n=l;break}o=o.sibling}if(!a){for(o=l.child;o;){if(o===n){a=!0,n=l,r=i;break}if(o===r){a=!0,r=l,n=i;break}o=o.sibling}if(!a)throw f(Error("Child was not found in either parent set. This indicates a bug in React related to the return pointer. Please file an issue."))}}if(n.alternate!==r)throw f(Error("Return fibers should always be each others' alternates. This error is likely caused by a bug in React. Please file an issue."))}if(3!==n.tag)throw f(Error("Unable to find node on an unmounted component."));return n.stateNode.current===n?e:t}function et(e){if(!(e=Ze(e)))return null;for(var t=e;;){if(5===t.tag||6===t.tag)return t;if(t.child)t.child.return=t,t=t.child;else{if(t===e)break;for(;!t.sibling;){if(!t.return||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}}return null}var tt={},nt=null,rt=0;function it(e,t,n){if(Array.isArray(t))for(var r=t.length;r--&&0wt||(e.current=xt[wt],xt[wt]=null,wt--)}function kt(e,t){xt[++wt]=e.current,e.current=t}var Ct={},_t={current:Ct},Pt={current:!1},Rt=Ct;function Nt(e,t){var n=e.type.contextTypes;if(!n)return Ct;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var i,l={};for(i in n)l[i]=t[i];return r&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=l),l}function It(e){return null!==(e=e.childContextTypes)&&void 0!==e}function Ut(e){St(Pt),St(_t)}function zt(e){St(Pt),St(_t)}function Mt(e,t,n){if(_t.current!==Ct)throw f(Error("Unexpected context found on stack. This error is likely caused by a bug in React. Please file an issue."));kt(_t,t),kt(Pt,n)}function At(e,t,n){var r=e.stateNode;if(e=t.childContextTypes,"function"!=typeof r.getChildContext)return n;for(var i in r=r.getChildContext())if(!(i in e))throw f(Error((Ge(t)||"Unknown")+'.getChildContext(): key "'+i+'" is not defined in childContextTypes.'));return o({},n,r)}function Dt(e){var t=e.stateNode;return t=t&&t.__reactInternalMemoizedMergedChildContext||Ct,Rt=_t.current,kt(_t,t),kt(Pt,Pt.current),!0}function Ft(e,t,n){var r=e.stateNode;if(!r)throw f(Error("Expected to have an instance by this point. This error is likely caused by a bug in React. Please file an issue."));n?(t=At(e,t,Rt),r.__reactInternalMemoizedMergedChildContext=t,St(Pt),St(_t),kt(_t,t)):St(Pt),kt(Pt,n)}var Ot=s.unstable_runWithPriority,jt=s.unstable_scheduleCallback,Wt=s.unstable_cancelCallback,Ht=s.unstable_shouldYield,Qt=s.unstable_requestPaint,Bt=s.unstable_now,Vt=s.unstable_getCurrentPriorityLevel,Lt=s.unstable_ImmediatePriority,Yt=s.unstable_UserBlockingPriority,Xt=s.unstable_NormalPriority,qt=s.unstable_LowPriority,$t=s.unstable_IdlePriority,Gt={},Jt=void 0!==Qt?Qt:function(){},Kt=null,Zt=null,en=!1,tn=Bt(),nn=1e4>tn?Bt:function(){return Bt()-tn};function rn(){switch(Vt()){case Lt:return 99;case Yt:return 98;case Xt:return 97;case qt:return 96;case $t:return 95;default:throw f(Error("Unknown priority level."))}}function ln(e){switch(e){case 99:return Lt;case 98:return Yt;case 97:return Xt;case 96:return qt;case 95:return $t;default:throw f(Error("Unknown priority level."))}}function an(e,t){return e=ln(e),Ot(e,t)}function on(e,t,n){return e=ln(e),jt(e,t,n)}function un(e){return null===Kt?(Kt=[e],Zt=jt(Lt,sn)):Kt.push(e),Gt}function cn(){null!==Zt&&Wt(Zt),sn()}function sn(){if(!en&&null!==Kt){en=!0;var e=0;try{var t=Kt;an(99,function(){for(;e=(e=10*(1073741821-t)-10*(1073741821-e))?99:250>=e?98:5250>=e?97:95}function dn(e,t){return e===t&&(0!==e||1/e==1/t)||e!=e&&t!=t}var pn=Object.prototype.hasOwnProperty;function hn(e,t){if(dn(e,t))return!0;if("object"!=typeof e||null===e||"object"!=typeof t||null===t)return!1;var n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return!1;for(r=0;r=t&&(li=!0),e.firstContext=null)}function Cn(e,t){if(Tn!==e&&!1!==t&&0!==t)if("number"==typeof t&&1073741823!==t||(Tn=e,t=1073741823),t={context:e,observedBits:t,next:null},null===bn){if(null===yn)throw f(Error("Context can only be read while React is rendering. In classes, you can read it in the render method or getDerivedStateFromProps. In function components, you can read it directly in the function body, but not inside Hooks like useReducer() or useMemo()."));bn=t,yn.dependencies={expirationTime:0,firstContext:t,responders:null}}else bn=bn.next=t;return e._currentValue}var _n=!1;function Pn(e){return{baseState:e,firstUpdate:null,lastUpdate:null,firstCapturedUpdate:null,lastCapturedUpdate:null,firstEffect:null,lastEffect:null,firstCapturedEffect:null,lastCapturedEffect:null}}function Rn(e){return{baseState:e.baseState,firstUpdate:e.firstUpdate,lastUpdate:e.lastUpdate,firstCapturedUpdate:null,lastCapturedUpdate:null,firstEffect:null,lastEffect:null,firstCapturedEffect:null,lastCapturedEffect:null}}function Nn(e,t){return{expirationTime:e,suspenseConfig:t,tag:0,payload:null,callback:null,next:null,nextEffect:null}}function In(e,t){null===e.lastUpdate?e.firstUpdate=e.lastUpdate=t:(e.lastUpdate.next=t,e.lastUpdate=t)}function Un(e,t){var n=e.alternate;if(null===n){var r=e.updateQueue,i=null;null===r&&(r=e.updateQueue=Pn(e.memoizedState))}else r=e.updateQueue,i=n.updateQueue,null===r?null===i?(r=e.updateQueue=Pn(e.memoizedState),i=n.updateQueue=Pn(n.memoizedState)):r=e.updateQueue=Rn(i):null===i&&(i=n.updateQueue=Rn(r));null===i||r===i?In(r,t):null===r.lastUpdate||null===i.lastUpdate?(In(r,t),In(i,t)):(In(r,t),i.lastUpdate=t)}function zn(e,t){var n=e.updateQueue;null===(n=null===n?e.updateQueue=Pn(e.memoizedState):Mn(e,n)).lastCapturedUpdate?n.firstCapturedUpdate=n.lastCapturedUpdate=t:(n.lastCapturedUpdate.next=t,n.lastCapturedUpdate=t)}function Mn(e,t){var n=e.alternate;return null!==n&&t===n.updateQueue&&(t=e.updateQueue=Rn(t)),t}function An(e,t,n,r,i,l){switch(n.tag){case 1:return"function"==typeof(e=n.payload)?e.call(l,r,i):e;case 3:e.effectTag=-2049&e.effectTag|64;case 0:if(null===(i="function"==typeof(e=n.payload)?e.call(l,r,i):e)||void 0===i)break;return o({},r,i);case 2:_n=!0}return r}function Dn(e,t,n,r,i){_n=!1;for(var l=(t=Mn(e,t)).baseState,a=null,o=0,u=t.firstUpdate,c=l;null!==u;){var s=u.expirationTime;sm?(g=f,f=null):g=f.sibling;var v=p(i,f,o[m],u);if(null===v){null===f&&(f=g);break}e&&f&&null===v.alternate&&t(i,f),a=l(v,a,m),null===s?c=v:s.sibling=v,s=v,f=g}if(m===o.length)return n(i,f),c;if(null===f){for(;mg?(v=m,m=null):v=m.sibling;var b=p(i,m,y.value,u);if(null===b){null===m&&(m=v);break}e&&m&&null===b.alternate&&t(i,m),a=l(b,a,g),null===s?c=b:s.sibling=b,s=b,m=v}if(y.done)return n(i,m),c;if(null===m){for(;!y.done;g++,y=o.next())null!==(y=d(i,y.value,u))&&(a=l(y,a,g),null===s?c=y:s.sibling=y,s=y);return c}for(m=r(i,m);!y.done;g++,y=o.next())null!==(y=h(m,i,g,y.value,u))&&(e&&null!==y.alternate&&m.delete(null===y.key?g:y.key),a=l(y,a,g),null===s?c=y:s.sibling=y,s=y);return e&&m.forEach(function(e){return t(i,e)}),c}return function(e,r,l,o){var u="object"==typeof l&&null!==l&&l.type===Fe&&null===l.key;u&&(l=l.props.children);var c="object"==typeof l&&null!==l;if(c)switch(l.$$typeof){case Ae:e:{for(c=l.key,u=r;null!==u;){if(u.key===c){if(7===u.tag?l.type===Fe:u.elementType===l.type){n(e,u.sibling),(r=i(u,l.type===Fe?l.props.children:l.props)).ref=qn(e,u,l),r.return=e,e=r;break e}n(e,u);break}t(e,u),u=u.sibling}l.type===Fe?((r=ea(l.props.children,e.mode,o,l.key)).return=e,e=r):((o=Zl(l.type,l.key,l.props,null,e.mode,o)).ref=qn(e,r,l),o.return=e,e=o)}return a(e);case De:e:{for(u=l.key;null!==r;){if(r.key===u){if(4===r.tag&&r.stateNode.containerInfo===l.containerInfo&&r.stateNode.implementation===l.implementation){n(e,r.sibling),(r=i(r,l.children||[])).return=e,e=r;break e}n(e,r);break}t(e,r),r=r.sibling}(r=na(l,e.mode,o)).return=e,e=r}return a(e)}if("string"==typeof l||"number"==typeof l)return l=""+l,null!==r&&6===r.tag?(n(e,r.sibling),(r=i(r,l)).return=e,e=r):(n(e,r),(r=ta(l,e.mode,o)).return=e,e=r),a(e);if(Xn(l))return m(e,r,l,o);if($e(l))return g(e,r,l,o);if(c&&$n(e,l),void 0===l&&!u)switch(e.tag){case 1:case 0:throw e=e.type,f(Error((e.displayName||e.name||"Component")+"(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null."))}return n(e,r)}}var Jn=Gn(!0),Kn=Gn(!1),Zn={},er={current:Zn},tr={current:Zn},nr={current:Zn};function rr(e){if(e===Zn)throw f(Error("Expected host context to exist. This error is likely caused by a bug in React. Please file an issue."));return e}function ir(e,t){kt(nr,t),kt(tr,e),kt(er,Zn),St(er),kt(er,{isInAParentText:!1})}function lr(e){St(er),St(tr),St(nr)}function ar(e){rr(nr.current);var t=rr(er.current),n=e.type;n="AndroidTextInput"===n||"RCTMultilineTextInputView"===n||"RCTSinglelineTextInputView"===n||"RCTText"===n||"RCTVirtualText"===n,t!==(n=t.isInAParentText!==n?{isInAParentText:n}:t)&&(kt(tr,e),kt(er,n))}function or(e){tr.current===e&&(St(er),St(tr))}var ur=1,cr=1,sr=2,fr={current:0};function dr(e){for(var t=e;null!==t;){if(13===t.tag){if(null!==t.memoizedState)return t}else if(19===t.tag&&void 0!==t.memoizedProps.revealOrder){if(0!=(64&t.effectTag))return t}else if(null!==t.child){t.child.return=t,t=t.child;continue}if(t===e)break;for(;null===t.sibling;){if(null===t.return||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}return null}function pr(e,t){return{responder:e,props:t}}var hr=0,mr=2,gr=4,vr=8,yr=16,br=32,Tr=64,Er=128,xr=ze.ReactCurrentDispatcher,wr=0,Sr=null,kr=null,Cr=null,_r=null,Pr=null,Rr=null,Nr=0,Ir=null,Ur=0,zr=!1,Mr=null,Ar=0;function Dr(){throw f(Error("Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem."))}function Fr(e,t){if(null===t)return!1;for(var n=0;nNr&&(Nr=s)):(zl(s,u.suspenseConfig),l=u.eagerReducer===e?u.eagerState:e(l,u.action)),a=u,u=u.next}while(null!==u&&u!==r);c||(o=a,i=l),dn(l,t.memoizedState)||(li=!0),t.memoizedState=l,t.baseUpdate=o,t.baseState=i,n.lastRenderedState=l}return[t.memoizedState,n.dispatch]}function Vr(e,t,n,r){return e={tag:e,create:t,destroy:n,deps:r,next:null},null===Ir?(Ir={lastEffect:null}).lastEffect=e.next=e:null===(t=Ir.lastEffect)?Ir.lastEffect=e.next=e:(n=t.next,t.next=e,e.next=n,Ir.lastEffect=e),e}function Lr(e,t,n,r){var i=Wr();Ur|=e,i.memoizedState=Vr(t,n,void 0,void 0===r?null:r)}function Yr(e,t,n,r){var i=Hr();r=void 0===r?null:r;var l=void 0;if(null!==kr){var a=kr.memoizedState;if(l=a.destroy,null!==r&&Fr(r,a.deps))return void Vr(hr,n,l,r)}Ur|=e,i.memoizedState=Vr(t,n,l,r)}function Xr(e,t){return"function"==typeof t?(e=e(),t(e),function(){t(null)}):null!==t&&void 0!==t?(e=e(),t.current=e,function(){t.current=null}):void 0}function qr(){}function $r(e,t,n){if(!(25>Ar))throw f(Error("Too many re-renders. React limits the number of renders to prevent an infinite loop."));var r=e.alternate;if(e===Sr||null!==r&&r===Sr)if(zr=!0,e={expirationTime:wr,suspenseConfig:null,action:n,eagerReducer:null,eagerState:null,next:null},null===Mr&&(Mr=new Map),void 0===(n=Mr.get(t)))Mr.set(t,e);else{for(t=n;null!==t.next;)t=t.next;t.next=e}else{var i=wl(),l=jn.suspense;l={expirationTime:i=Sl(i,e,l),suspenseConfig:l,action:n,eagerReducer:null,eagerState:null,next:null};var a=t.last;if(null===a)l.next=l;else{var o=a.next;null!==o&&(l.next=o),a.next=l}if(t.last=l,0===e.expirationTime&&(null===r||0===r.expirationTime)&&null!==(r=t.lastRenderedReducer))try{var u=t.lastRenderedState,c=r(u,n);if(l.eagerReducer=r,l.eagerState=c,dn(c,u))return}catch(e){}kl(e,i)}}var Gr={readContext:Cn,useCallback:Dr,useContext:Dr,useEffect:Dr,useImperativeHandle:Dr,useLayoutEffect:Dr,useMemo:Dr,useReducer:Dr,useRef:Dr,useState:Dr,useDebugValue:Dr,useResponder:Dr},Jr={readContext:Cn,useCallback:function(e,t){return Wr().memoizedState=[e,void 0===t?null:t],e},useContext:Cn,useEffect:function(e,t){return Lr(516,192,e,t)},useImperativeHandle:function(e,t,n){return n=null!==n&&void 0!==n?n.concat([e]):null,Lr(4,36,Xr.bind(null,t,e),n)},useLayoutEffect:function(e,t){return Lr(4,36,e,t)},useMemo:function(e,t){var n=Wr();return t=void 0===t?null:t,e=e(),n.memoizedState=[e,t],e},useReducer:function(e,t,n){var r=Wr();return t=void 0!==n?n(t):t,r.memoizedState=r.baseState=t,e=(e=r.queue={last:null,dispatch:null,lastRenderedReducer:e,lastRenderedState:t}).dispatch=$r.bind(null,Sr,e),[r.memoizedState,e]},useRef:function(e){return e={current:e},Wr().memoizedState=e},useState:function(e){var t=Wr();return"function"==typeof e&&(e=e()),t.memoizedState=t.baseState=e,e=(e=t.queue={last:null,dispatch:null,lastRenderedReducer:Qr,lastRenderedState:e}).dispatch=$r.bind(null,Sr,e),[t.memoizedState,e]},useDebugValue:qr,useResponder:pr},Kr={readContext:Cn,useCallback:function(e,t){var n=Hr();t=void 0===t?null:t;var r=n.memoizedState;return null!==r&&null!==t&&Fr(t,r[1])?r[0]:(n.memoizedState=[e,t],e)},useContext:Cn,useEffect:function(e,t){return Yr(516,192,e,t)},useImperativeHandle:function(e,t,n){return n=null!==n&&void 0!==n?n.concat([e]):null,Yr(4,36,Xr.bind(null,t,e),n)},useLayoutEffect:function(e,t){return Yr(4,36,e,t)},useMemo:function(e,t){var n=Hr();t=void 0===t?null:t;var r=n.memoizedState;return null!==r&&null!==t&&Fr(t,r[1])?r[0]:(e=e(),n.memoizedState=[e,t],e)},useReducer:Br,useRef:function(){return Hr().memoizedState},useState:function(e){return Br(Qr)},useDebugValue:qr,useResponder:pr},Zr=null,ei=null,ti=!1;function ni(e,t){switch(e.tag){case 5:return null!==(t=ft(e.type,e.pendingProps))&&(e.stateNode=t,!0);case 6:return null!==(t=ft(e.pendingProps))&&(e.stateNode=t,!0);case 13:default:return!1}}function ri(e){if(ti){var t=ei;if(t){var n=t;if(!ni(e,t)){if(!(t=ft())||!ni(e,t))return e.effectTag|=2,ti=!1,void(Zr=e);var r=Zr,i=$l(5,null,null,0);i.elementType="DELETED",i.type="DELETED",i.stateNode=n,i.return=r,i.effectTag=8,null!==r.lastEffect?(r.lastEffect.nextEffect=i,r.lastEffect=i):r.firstEffect=r.lastEffect=i}Zr=e,ei=ft()}else e.effectTag|=2,ti=!1,Zr=e}}var ii=ze.ReactCurrentOwner,li=!1;function ai(e,t,n,r){t.child=null===e?Kn(t,null,n,r):Jn(t,e.child,n,r)}function oi(e,t,n,r,i){n=n.render;var l=t.ref;return kn(t,i),r=Or(e,t,n,r,l,i),null===e||li?(t.effectTag|=1,ai(e,t,r,i),t.child):(t.updateQueue=e.updateQueue,t.effectTag&=-517,e.expirationTime<=i&&(e.expirationTime=0),bi(e,t,i))}function ui(e,t,n,r,i,l){if(null===e){var a=n.type;return"function"!=typeof a||Gl(a)||void 0!==a.defaultProps||null!==n.compare||void 0!==n.defaultProps?((e=Zl(n.type,null,r,null,t.mode,l)).ref=t.ref,e.return=t,t.child=e):(t.tag=15,t.type=a,ci(e,t,a,r,i,l))}return a=e.child,it)&&bl.set(e,t))}}function Cl(e,t){e.expirationTimei.firstPendingTime&&(i.firstPendingTime=t),0===(e=i.lastPendingTime)||t=t)&&(on(97,function(){return n._onComplete(),null}),!0)}function Nl(){if(null!==bl){var e=bl;bl=null,e.forEach(function(e,t){un(Ul.bind(null,t,e))}),cn()}}function Il(e,t){e.finishedWork=null,e.finishedExpirationTime=0;var n=e.timeoutHandle;if(-1!==n&&(e.timeoutHandle=-1,bt(n)),null!==nl)for(n=nl.return;null!==n;){var r=n;switch(r.tag){case 1:var i=r.type.childContextTypes;null!==i&&void 0!==i&&Ut();break;case 3:lr(),zt();break;case 5:or(r);break;case 4:lr();break;case 13:case 19:St(fr);break;case 10:wn(r)}n=n.return}tl=e,nl=Kl(e.current,null),rl=t,il=$i,al=ll=1073741823,ol=null,ul=!1}function Ul(e,t,n){if((48&el)!==Li)throw f(Error("Should not already be working."));if(e.firstPendingTime component higher in the tree to provide a loading indicator or placeholder to display."+Et(u))}il!==Zi&&(il=Gi),c=Ci(c,u),u=o;do{switch(u.tag){case 3:u.effectTag|=2048,u.expirationTime=s,zn(u,s=Wi(u,c,s));break e;case 1:if(d=c,a=u.type,o=u.stateNode,0==(64&u.effectTag)&&("function"==typeof a.getDerivedStateFromError||null!==o&&"function"==typeof o.componentDidCatch&&(null===hl||!hl.has(o)))){u.effectTag|=2048,u.expirationTime=s,zn(u,s=Hi(u,d,s));break e}}u=u.return}while(null!==u)}nl=Al(l)}if(el=r,En(),Bi.current=i,null!==nl)return Ul.bind(null,e,t)}if(e.finishedWork=e.current.alternate,e.finishedExpirationTime=t,Rl(e,t))return null;switch(tl=null,il){case $i:throw f(Error("Should have a work-in-progress."));case Gi:return(r=e.lastPendingTime)(n=r-n)&&(n=0),t<(n=(120>n?120:480>n?480:1080>n?1080:1920>n?1920:3e3>n?3e3:4320>n?4320:1960*Qi(n/1960))-n)&&(n=t)),10=(t=0|(i=ol).busyMinDurationMs)?t=0:(n=0|i.busyDelayMs,t=(r=nn()-(10*(1073741821-r)-(0|i.timeoutMs||5e3)))<=n?0:n+t-r),10 component."));r=mt(),u.UIManager.createView(r,"RCTRawText",l,{text:i}),Ee.set(r,t),n.stateNode=r}break;case 11:break;case 13:if(St(fr),i=t.memoizedState,0!=(64&t.effectTag)){t.expirationTime=r;break e}i=null!==i,r=!1,null!==n&&(r=null!==(l=n.memoizedState),i||null===l||null!==(l=n.child.sibling)&&(null!==(o=t.firstEffect)?(t.firstEffect=l,l.nextEffect=o):(t.firstEffect=t.lastEffect=l,l.nextEffect=null),l.effectTag=8)),i&&!r&&0!=(2&t.mode)&&(null===n&&!0!==t.memoizedProps.unstable_avoidThisFallback||0!=(fr.current&cr)?il===$i&&(il=Ji):il!==$i&&il!==Ji||(il=Ki)),(i||r)&&(t.effectTag|=4);break;case 7:case 8:case 12:break;case 4:lr(),Ei(t);break;case 10:wn(t);break;case 9:case 14:break;case 17:It(t.type)&&Ut();break;case 18:break;case 19:if(St(fr),null===(i=t.memoizedState))break;if(l=0!=(64&t.effectTag),null===(o=i.rendering)){if(l)Si(i,!1);else if(il!==$i||null!==n&&0!=(64&n.effectTag))for(n=t.child;null!==n;){if(null!==(o=dr(n))){for(t.effectTag|=64,Si(i,!1),null!==(i=o.updateQueue)&&(t.updateQueue=i,t.effectTag|=4),t.firstEffect=t.lastEffect=null,i=r,n=t.child;null!==n;)l=i,(r=n).effectTag&=2,r.nextEffect=null,r.firstEffect=null,r.lastEffect=null,null===(o=r.alternate)?(r.childExpirationTime=0,r.expirationTime=l,r.child=null,r.memoizedProps=null,r.memoizedState=null,r.updateQueue=null,r.dependencies=null):(r.childExpirationTime=o.childExpirationTime,r.expirationTime=o.expirationTime,r.child=o.child,r.memoizedProps=o.memoizedProps,r.memoizedState=o.memoizedState,r.updateQueue=o.updateQueue,l=o.dependencies,r.dependencies=null===l?null:{expirationTime:l.expirationTime,firstContext:l.firstContext,responders:l.responders}),n=n.sibling;kt(fr,fr.current&ur|sr),t=t.child;break e}n=n.sibling}}else{if(!l)if(null!==(n=dr(o))){if(t.effectTag|=64,l=!0,Si(i,!0),null===i.tail&&"hidden"===i.tailMode){null!==(n=n.updateQueue)&&(t.updateQueue=n,t.effectTag|=4),null!==(t=t.lastEffect=i.lastEffect)&&(t.nextEffect=null);break}}else nn()>i.tailExpiration&&1n&&(n=l),o>n&&(n=o),r=r.sibling;i.childExpirationTime=n}if(null!==t)return t;null!==e&&0==(1024&e.effectTag)&&(null===e.firstEffect&&(e.firstEffect=nl.firstEffect),null!==nl.lastEffect&&(null!==e.lastEffect&&(e.lastEffect.nextEffect=nl.firstEffect),e.lastEffect=nl.lastEffect),1i?l:i,e.firstPendingTime=i,i=n?gi(e,t,n):(kt(fr,fr.current&ur),null!==(t=bi(e,t,n))?t.sibling:null);kt(fr,fr.current&ur);break;case 19:if(r=t.childExpirationTime>=n,0!=(64&e.effectTag)){if(r)return yi(e,t,n);t.effectTag|=64}var i=t.memoizedState;if(null!==i&&(i.rendering=null,i.tail=null),kt(fr,fr.current),!r)return null}return bi(e,t,n)}}else li=!1;switch(t.expirationTime=0,t.tag){case 2:if(r=t.type,null!==e&&(e.alternate=null,t.alternate=null,t.effectTag|=2),e=t.pendingProps,i=Nt(t,_t.current),kn(t,n),i=Or(null,t,r,e,i,n),t.effectTag|=1,"object"==typeof i&&null!==i&&"function"==typeof i.render&&void 0===i.$$typeof){if(t.tag=1,jr(),It(r)){var l=!0;Dt(t)}else l=!1;t.memoizedState=null!==i.state&&void 0!==i.state?i.state:null;var a=r.getDerivedStateFromProps;"function"==typeof a&&Hn(t,r,a,e),i.updater=Qn,t.stateNode=i,i._reactInternalFiber=t,Yn(t,r,e,n),t=pi(null,t,r,!0,l,n)}else t.tag=0,ai(null,t,i,n),t=t.child;return t;case 16:switch(i=t.elementType,null!==e&&(e.alternate=null,t.alternate=null,t.effectTag|=2),e=t.pendingProps,i=gn(i),t.type=i,l=t.tag=Jl(i),e=mn(i,e),l){case 0:t=fi(null,t,i,e,n);break;case 1:t=di(null,t,i,e,n);break;case 11:t=oi(null,t,i,e,n);break;case 14:t=ui(null,t,i,mn(i.type,e),r,n);break;default:throw f(Error("Element type is invalid. Received a promise that resolves to: "+i+". Lazy element type must resolve to a class or function."))}return t;case 0:return r=t.type,i=t.pendingProps,fi(e,t,r,i=t.elementType===r?i:mn(r,i),n);case 1:return r=t.type,i=t.pendingProps,di(e,t,r,i=t.elementType===r?i:mn(r,i),n);case 3:if(hi(t),null===(r=t.updateQueue))throw f(Error("If the root does not have an updateQueue, we should have already bailed out. This error is likely caused by a bug in React. Please file an issue."));return i=null!==(i=t.memoizedState)?i.element:null,Dn(t,r,t.pendingProps,null,n),(r=t.memoizedState.element)===i?t=bi(e,t,n):(ai(e,t,r,n),t=t.child),t;case 5:return ar(t),null===e&&ri(t),r=t.pendingProps.children,si(e,t),ai(e,t,r,n),t.child;case 6:return null===e&&ri(t),null;case 13:return gi(e,t,n);case 4:return ir(t,t.stateNode.containerInfo),r=t.pendingProps,null===e?t.child=Jn(t,null,r,n):ai(e,t,r,n),t.child;case 11:return r=t.type,i=t.pendingProps,oi(e,t,r,i=t.elementType===r?i:mn(r,i),n);case 7:return ai(e,t,t.pendingProps,n),t.child;case 8:case 12:return ai(e,t,t.pendingProps.children,n),t.child;case 10:e:{if(r=t.type._context,i=t.pendingProps,a=t.memoizedProps,xn(t,l=i.value),null!==a){var o=a.value;if(0===(l=dn(o,l)?0:0|("function"==typeof r._calculateChangedBits?r._calculateChangedBits(o,l):1073741823))){if(a.children===i.children&&!Pt.current){t=bi(e,t,n);break e}}else for(null!==(o=t.child)&&(o.return=t);null!==o;){var u=o.dependencies;if(null!==u){a=o.child;for(var c=u.firstContext;null!==c;){if(c.context===r&&0!=(c.observedBits&l)){1===o.tag&&((c=Nn(n,null)).tag=2,Un(o,c)),o.expirationTime|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i,t=/\((\S*)(?::(\d+))(?::(\d+))\)/;function o(n){var o=u.exec(n);if(!o)return null;var c=o[2]&&0===o[2].indexOf('native'),s=o[2]&&0===o[2].indexOf('eval'),f=t.exec(o[2]);return s&&null!=f&&(o[2]=f[1],o[3]=f[2],o[4]=f[3]),{file:c?null:o[2],methodName:o[1]||l,arguments:c?[o[2]]:[],lineNumber:o[3]?+o[3]:null,column:o[4]?+o[4]:null}}var c=/^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i;function s(n){var u=c.exec(n);return u?{file:u[2],methodName:u[1]||l,arguments:[],lineNumber:+u[3],column:u[4]?+u[4]:null}:null}var f=/^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|\[native).*?|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i,v=/(\S+) line (\d+)(?: > eval line \d+)* > eval/i;function b(n){var u=f.exec(n);if(!u)return null;var t=u[3]&&u[3].indexOf(' > eval')>-1,o=v.exec(u[3]);return t&&null!=o&&(u[3]=o[1],u[4]=o[2],u[5]=null),{file:u[3],methodName:u[1]||l,arguments:u[2]?u[2].split(','):[],lineNumber:u[4]?+u[4]:null,column:u[5]?+u[5]:null}}var p=/^\s*(?:([^@]*)(?:\((.*?)\))?@)?(\S.*?):(\d+)(?::(\d+))?\s*$/i;function x(n){var u=p.exec(n);return u?{file:u[3],methodName:u[1]||l,arguments:[],lineNumber:+u[4],column:u[5]?+u[5]:null}:null}var h=/^\s*at (?:((?:\[object object\])?[^\\/]+(?: \[as \S+\])?) )?\(?(.*?):(\d+)(?::(\d+))?\)?\s*$/i;function N(n){var u=h.exec(n);return u?{file:u[2],methodName:u[1]||l,arguments:[],lineNumber:+u[3],column:u[4]?+u[4]:null}:null}n.parse=function(n){return n.split('\n').reduce(function(n,l){var u=o(l)||s(l)||b(l)||N(l)||x(l);return u&&n.push(u),n},[])},Object.defineProperty(n,'__esModule',{value:!0})},'object'==typeof e&&void 0!==m?l(e):'function'==typeof define&&define.amd?define(['exports'],l):l((n=n||self).stackTraceParser={})},105,[]); -__d(function(g,r,i,a,m,e,d){'use strict';(0,r(d[0]).polyfillGlobal)('Promise',function(){return r(d[1])})},106,[107,40]); -__d(function(g,r,i,a,m,e,d){'use strict';var l=r(d[0]);function o(o,t,n){var c=Object.getOwnPropertyDescriptor(o,t),b=c||{},f=b.enumerable,u=b.writable,p=b.configurable;!c||p?l(o,t,{get:n,enumerable:!1!==f,writable:!1!==u}):console.error('Failed to set polyfill. '+t+' is not configurable.')}m.exports={polyfillObjectProperty:o,polyfillGlobal:function(l,t){o(g,l,t)}}},107,[39]); -__d(function(g,r,i,a,m,e,d){'use strict';(0,r(d[0]).polyfillGlobal)('regeneratorRuntime',function(){return delete g.regeneratorRuntime,r(d[1])})},108,[107,109]); -__d(function(g,r,i,a,m,e,d){var t=(function(t){"use strict";var n,o=Object.prototype,c=o.hasOwnProperty,u="function"==typeof Symbol?Symbol:{},h=u.iterator||"@@iterator",f=u.asyncIterator||"@@asyncIterator",s=u.toStringTag||"@@toStringTag";function l(t,n,o,c){var u=n&&n.prototype instanceof E?n:E,h=Object.create(u.prototype),f=new A(c||[]);return h._invoke=F(t,o,f),h}function p(t,n,o){try{return{type:"normal",arg:t.call(n,o)}}catch(t){return{type:"throw",arg:t}}}t.wrap=l;var y="suspendedStart",v="suspendedYield",w="executing",L="completed",x={};function E(){}function b(){}function _(){}var j={};j[h]=function(){return this};var O=Object.getPrototypeOf,k=O&&O(O(R([])));k&&k!==o&&c.call(k,h)&&(j=k);var G=_.prototype=E.prototype=Object.create(j);function N(t){["next","throw","return"].forEach(function(n){t[n]=function(t){return this._invoke(n,t)}})}function P(t){function n(o,u,h,f){var s=p(t[o],t,u);if("throw"!==s.type){var l=s.arg,y=l.value;return y&&"object"==typeof y&&c.call(y,"__await")?Promise.resolve(y.__await).then(function(t){n("next",t,h,f)},function(t){n("throw",t,h,f)}):Promise.resolve(y).then(function(t){l.value=t,h(l)},function(t){return n("throw",t,h,f)})}f(s.arg)}var o;this._invoke=function(t,c){function u(){return new Promise(function(o,u){n(t,c,o,u)})}return o=o?o.then(u,u):u()}}function F(t,n,o){var c=y;return function(u,h){if(c===w)throw new Error("Generator is already running");if(c===L){if("throw"===u)throw h;return Y()}for(o.method=u,o.arg=h;;){var f=o.delegate;if(f){var s=S(f,o);if(s){if(s===x)continue;return s}}if("next"===o.method)o.sent=o._sent=o.arg;else if("throw"===o.method){if(c===y)throw c=L,o.arg;o.dispatchException(o.arg)}else"return"===o.method&&o.abrupt("return",o.arg);c=w;var l=p(t,n,o);if("normal"===l.type){if(c=o.done?L:v,l.arg===x)continue;return{value:l.arg,done:o.done}}"throw"===l.type&&(c=L,o.method="throw",o.arg=l.arg)}}}function S(t,o){var c=t.iterator[o.method];if(c===n){if(o.delegate=null,"throw"===o.method){if(t.iterator.return&&(o.method="return",o.arg=n,S(t,o),"throw"===o.method))return x;o.method="throw",o.arg=new TypeError("The iterator does not provide a 'throw' method")}return x}var u=p(c,t.iterator,o.arg);if("throw"===u.type)return o.method="throw",o.arg=u.arg,o.delegate=null,x;var h=u.arg;return h?h.done?(o[t.resultName]=h.value,o.next=t.nextLoc,"return"!==o.method&&(o.method="next",o.arg=n),o.delegate=null,x):h:(o.method="throw",o.arg=new TypeError("iterator result is not an object"),o.delegate=null,x)}function T(t){var n={tryLoc:t[0]};1 in t&&(n.catchLoc=t[1]),2 in t&&(n.finallyLoc=t[2],n.afterLoc=t[3]),this.tryEntries.push(n)}function I(t){var n=t.completion||{};n.type="normal",delete n.arg,t.completion=n}function A(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(T,this),this.reset(!0)}function R(t){if(t){var o=t[h];if(o)return o.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var u=-1,f=function o(){for(;++u=0;--h){var f=this.tryEntries[h],s=f.completion;if("root"===f.tryLoc)return u("end");if(f.tryLoc<=this.prev){var l=c.call(f,"catchLoc"),p=c.call(f,"finallyLoc");if(l&&p){if(this.prev=0;--o){var u=this.tryEntries[o];if(u.tryLoc<=this.prev&&c.call(u,"finallyLoc")&&this.prev=0;--n){var o=this.tryEntries[n];if(o.finallyLoc===t)return this.complete(o.completion,o.afterLoc),I(o),x}},catch:function(t){for(var n=this.tryEntries.length-1;n>=0;--n){var o=this.tryEntries[n];if(o.tryLoc===t){var c=o.completion;if("throw"===c.type){var u=c.arg;I(o)}return u}}throw new Error("illegal catch attempt")},delegateYield:function(t,o,c){return this.delegate={iterator:R(t),resultName:o,nextLoc:c},"next"===this.method&&(this.arg=n),x}},t})("object"==typeof m?m.exports:{});try{regeneratorRuntime=t}catch(n){Function("r","regeneratorRuntime = r")(t)}},109,[]); -__d(function(g,r,i,a,m,e,d){'use strict';if(!g.RN$Bridgeless){var l=r(d[0]).polyfillGlobal,t=function(t){l(t,function(){return r(d[1])[t]})};t('setTimeout'),t('setInterval'),t('setImmediate'),t('clearTimeout'),t('clearInterval'),t('clearImmediate'),t('requestAnimationFrame'),t('cancelAnimationFrame'),t('requestIdleCallback'),t('cancelIdleCallback')}},110,[107,111]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0])(r(d[1])),n=r(d[2]),l=(r(d[3]),r(d[4]),r(d[5])),u=null;function o(){return u||(u=r(d[6])),u()}var c=16.666666666666668,f=[],s=[],v=[],h=[],I=[],T={},b=[],p=1,w=null,k=!1;function q(){var t=v.indexOf(null);return-1===t&&(t=v.length),t}function x(t,n){var l=p++,u=q();return v[u]=l,f[u]=t,s[u]=n,l}function y(t,n,l){r(d[7])(t<=p,'Tried to call timer with ID %s but no such timer exists.',t);var u=v.indexOf(t);if(-1!==u){var h=s[u],I=f[u];if(I&&h){'setTimeout'!==h&&'setImmediate'!==h&&'requestAnimationFrame'!==h&&'requestIdleCallback'!==h||A(u);try{'setTimeout'===h||'setInterval'===h||'setImmediate'===h?I():'requestAnimationFrame'===h?I(o()):'requestIdleCallback'===h?I({timeRemaining:function(){return Math.max(0,c-(o()-n))},didTimeout:!!l}):console.error('Tried to call a callback with invalid type: '+h)}catch(t){w?w.push(t):w=[t]}}else console.error('No callback found for timerID '+t)}}function C(){if(h.length>0){var t=h.slice();h=[];for(var n=0;n0}function A(t){v[t]=null,f[t]=null,s[t]=null,b[t]=null}function D(t){if(null!=t){var n=v.indexOf(t);if(-1!==n){A(n);var l=s[n];'setImmediate'!==l&&'requestIdleCallback'!==l&&E(t)}}}var O,F={setTimeout:function(t,n){for(var l=arguments.length,u=new Array(l>2?l-2:0),o=2;o2?l-2:0),o=2;o1?n-1:0),u=1;u-1&&(I.splice(t,1),y(u,o(),!0)),delete T[u],0===I.length&&_(!1)},l);T[u]=c}return u},cancelIdleCallback:function(t){D(t);var n=I.indexOf(t);-1!==n&&I.splice(n,1);var l=T[t];l&&(F.clearTimeout(l),delete T[t]),0===I.length&&_(!1)},clearTimeout:function(t){D(t)},clearInterval:function(t){D(t)},clearImmediate:function(t){D(t);var n=h.indexOf(t);-1!==n&&h.splice(n,1)},cancelAnimationFrame:function(t){D(t)},callTimers:function(t){l(0!==t.length,'Cannot call `callTimers` with an empty list of IDs.'),w=null;for(var n=0;n1)for(var o=1;o0){var n=I.slice();I=[];for(var l=0;l=0,loaded:s,total:n})}},{key:"__didCompleteResponse",value:function(t,s,n){t===this._requestId&&(s&&(''!==this._responseType&&'text'!==this._responseType||(this._response=s),this._hasError=!0,n&&(this._timedOut=!0)),this._clearSubscriptions(),this._requestId=null,this.setReadyState(this.DONE),s?S._interceptor&&S._interceptor.loadingFailed(t,s):S._interceptor&&S._interceptor.loadingFinished(t,this._response.length))}},{key:"_clearSubscriptions",value:function(){(this._subscriptions||[]).forEach(function(t){t&&t.remove()}),this._subscriptions=[]}},{key:"getAllResponseHeaders",value:function(){if(!this.responseHeaders)return null;var t=this.responseHeaders||{};return Object.keys(t).map(function(s){return s+': '+t[s]}).join('\r\n')}},{key:"getResponseHeader",value:function(t){var s=this._lowerCaseResponseHeaders[t.toLowerCase()];return void 0!==s?s:null}},{key:"setRequestHeader",value:function(t,s){if(this.readyState!==this.OPENED)throw new Error('Request has not been opened');this._headers[t.toLowerCase()]=String(s)}},{key:"setTrackingName",value:function(t){return this._trackingName=t,this}},{key:"open",value:function(t,s,n){if(this.readyState!==this.UNSENT)throw new Error('Cannot open, already sending');if(void 0!==n&&!n)throw new Error('Synchronous http requests are not supported');if(!s)throw new Error('Cannot load an empty url');this._method=t.toUpperCase(),this._url=s,this._aborted=!1,this.setReadyState(this.OPENED)}},{key:"send",value:function(s){var n=this;if(this.readyState!==this.OPENED)throw new Error('Request has not been opened');if(this._sent)throw new Error('Request has already been sent');this._sent=!0;var o=this._incrementalEvents||!!this.onreadystatechange||!!this.onprogress;this._subscriptions.push(l.addListener('didSendNetworkData',function(s){return n.__didUploadProgress.apply(n,t(s))})),this._subscriptions.push(l.addListener('didReceiveNetworkResponse',function(s){return n.__didReceiveResponse.apply(n,t(s))})),this._subscriptions.push(l.addListener('didReceiveNetworkData',function(s){return n.__didReceiveData.apply(n,t(s))})),this._subscriptions.push(l.addListener('didReceiveNetworkIncrementalData',function(s){return n.__didReceiveIncrementalData.apply(n,t(s))})),this._subscriptions.push(l.addListener('didReceiveNetworkDataProgress',function(s){return n.__didReceiveDataProgress.apply(n,t(s))})),this._subscriptions.push(l.addListener('didCompleteNetworkResponse',function(s){return n.__didCompleteResponse.apply(n,t(s))}));var h='text';'arraybuffer'===this._responseType&&(h='base64'),'blob'===this._responseType&&(h='blob'),v(this._method,'Request method needs to be defined.'),v(this._url,'Request URL needs to be defined.'),l.sendRequest(this._method,this._trackingName,this._url,this._headers,s,h,o,this.timeout,this.__didCreateRequest.bind(this),this.withCredentials)}},{key:"abort",value:function(){this._aborted=!0,this._requestId&&l.abortRequest(this._requestId),this.readyState===this.UNSENT||this.readyState===this.OPENED&&!this._sent||this.readyState===this.DONE||(this._reset(),this.setReadyState(this.DONE)),this._reset()}},{key:"setResponseHeaders",value:function(t){this.responseHeaders=t||null;var s=t||{};this._lowerCaseResponseHeaders=Object.keys(s).reduce(function(t,n){return t[n.toLowerCase()]=s[n],t},{})}},{key:"setReadyState",value:function(t){this.readyState=t,this.dispatchEvent({type:'readystatechange'}),t===this.DONE&&(this._aborted?this.dispatchEvent({type:'abort'}):this._hasError?this._timedOut?this.dispatchEvent({type:'timeout'}):this.dispatchEvent({type:'error'}):this.dispatchEvent({type:'load'}),this.dispatchEvent({type:'loadend'}))}},{key:"addEventListener",value:function(t,n){'readystatechange'!==t&&'progress'!==t||(this._incrementalEvents=!0),s(p(S.prototype),"addEventListener",this).call(this,t,n)}},{key:"responseType",get:function(){return this._responseType},set:function(t){if(this._sent)throw new Error("Failed to set the 'responseType' property on 'XMLHttpRequest': The response type cannot be set after the request has been sent.");w.hasOwnProperty(t)?(v(w[t]||'document'===t,"The provided value '"+t+"' is unsupported in this environment."),'blob'===t&&v(_.isAvailable,'Native module BlobModule is required for blob support'),this._responseType=t):f(!1,"The provided value '"+t+"' is not a valid 'responseType'.")}},{key:"responseText",get:function(){if(''!==this._responseType&&'text'!==this._responseType)throw new Error("The 'responseText' property is only available if 'responseType' is set to '' or 'text', but it is '"+this._responseType+"'.");return this.readyState0&&void 0!==arguments[0]?arguments[0]:[],o=arguments.length>1?arguments[1]:void 0;t(this,s);var u=r(d[2]);this.data=u.createFromParts(n,o).data}return n(s,[{key:"slice",value:function(t,n){var s=r(d[2]),o=this.data,u=o.offset,l=o.size;return'number'==typeof t&&(t>l&&(t=l),u+=t,l-=t,'number'==typeof n&&(n<0&&(n=this.size+n),l=n-t)),s.createFromOptions({blobId:this.data.blobId,offset:u,size:l})}},{key:"close",value:function(){r(d[2]).release(this.data.blobId),this.data=null}},{key:"data",set:function(t){this._data=t},get:function(){if(!this._data)throw new Error('Blob has been closed and is no longer available');return this._data}},{key:"size",get:function(){return this.data.size}},{key:"type",get:function(){return this.data.type||''}}]),s})();m.exports=s},120,[4,5,118]); -__d(function(g,r,i,a,m,e,d){var n={};m.exports={register:function(t){n[t]?n[t]++:n[t]=1},unregister:function(t){n[t]&&(n[t]--,n[t]<=0&&delete n[t])},has:function(t){return n[t]&&n[t]>0}}},121,[]); -__d(function(g,r,i,a,m,e,d){'use strict';Object.defineProperty(e,'__esModule',{value:!0});var t=new WeakMap,n=new WeakMap;function o(n){var o=t.get(n);return console.assert(null!=o,"'this' is expected an Event object, but got",n),o}function l(t){null==t.passiveListener?t.event.cancelable&&(t.canceled=!0,"function"==typeof t.event.preventDefault&&t.event.preventDefault()):"undefined"!=typeof console&&"function"==typeof console.error&&console.error("Unable to preventDefault inside passive event listener invocation.",t.passiveListener)}function u(n,o){t.set(this,{eventTarget:n,event:o,eventPhase:2,currentTarget:n,canceled:!1,stopped:!1,immediateStopped:!1,passiveListener:null,timeStamp:o.timeStamp||Date.now()}),Object.defineProperty(this,"isTrusted",{value:!1,enumerable:!0});for(var l=Object.keys(o),u=0;u0){for(var t=new Array(arguments.length),n=0;n0?y-4:y;var l=0;for(h=0;h>16&255,C[l++]=u>>8&255,C[l++]=255&u;2===f?(u=n[t.charCodeAt(h)]<<2|n[t.charCodeAt(h+1)]>>4,C[l++]=255&u):1===f&&(u=n[t.charCodeAt(h)]<<10|n[t.charCodeAt(h+1)]<<4|n[t.charCodeAt(h+2)]>>2,C[l++]=u>>8&255,C[l++]=255&u);return C},e.fromByteArray=function(n){for(var o,h=n.length,c=h%3,u='',A=[],C=0,y=h-c;Cy?y:C+16383));1===c?(o=n[h-1],u+=t[o>>2],u+=t[o<<4&63],u+='=='):2===c&&(o=(n[h-2]<<8)+n[h-1],u+=t[o>>10],u+=t[o>>4&63],u+=t[o<<2&63],u+='=');return A.push(u),A.join('')};for(var t=[],n=[],o='undefined'!=typeof Uint8Array?Uint8Array:Array,h='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',c=0,u=h.length;c0)throw new Error('Invalid string. Length must be a multiple of 4');return'='===t[n-2]?2:'='===t[n-1]?1:0}function f(n,o,h){for(var c,u,A=[],f=o;f>18&63]+t[u>>12&63]+t[u>>6&63]+t[63&u]);return A.join('')}n['-'.charCodeAt(0)]=62,n['_'.charCodeAt(0)]=63},128,[]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=r(d[1]),s=r(d[2]),o=r(d[3]),p=(function(){function p(){s(this,p),this._parts=[]}return o(p,[{key:"append",value:function(t,n){this._parts.push([t,n])}},{key:"getParts",value:function(){return this._parts.map(function(s){var o=n(s,2),p=o[0],f=o[1],u={'content-disposition':'form-data; name="'+p+'"'};return'object'==typeof f&&f?('string'==typeof f.name&&(u['content-disposition']+='; filename="'+f.name+'"'),'string'==typeof f.type&&(u['content-type']=f.type),t({},f,{headers:u,fieldName:p})):{string:String(f),headers:u,fieldName:p}})}}]),p})();m.exports=p},129,[53,25,4,5]); -__d(function(g,r,i,a,m,e,d){'use strict';r(d[0]),m.exports={fetch:fetch,Headers:Headers,Request:Request,Response:Response}},130,[131]); -__d(function(g,r,i,a,m,e,d){var t,o;t=this,o=function(t){'use strict';var o={searchParams:'URLSearchParams'in self,iterable:'Symbol'in self&&'iterator'in Symbol,blob:'FileReader'in self&&'Blob'in self&&(function(){try{return new Blob,!0}catch(t){return!1}})(),formData:'FormData'in self,arrayBuffer:'ArrayBuffer'in self};if(o.arrayBuffer)var n=['[object Int8Array]','[object Uint8Array]','[object Uint8ClampedArray]','[object Int16Array]','[object Uint16Array]','[object Int32Array]','[object Uint32Array]','[object Float32Array]','[object Float64Array]'],s=ArrayBuffer.isView||function(t){return t&&n.indexOf(Object.prototype.toString.call(t))>-1};function f(t){if('string'!=typeof t&&(t=String(t)),/[^a-z0-9\-#$%&'*+.^_`|~]/i.test(t))throw new TypeError('Invalid character in header field name');return t.toLowerCase()}function h(t){return'string'!=typeof t&&(t=String(t)),t}function u(t){var n={next:function(){var o=t.shift();return{done:void 0===o,value:o}}};return o.iterable&&(n["function"==typeof Symbol?Symbol.iterator:"@@iterator"]=function(){return n}),n}function c(t){this.map={},t instanceof c?t.forEach(function(t,o){this.append(o,t)},this):Array.isArray(t)?t.forEach(function(t){this.append(t[0],t[1])},this):t&&Object.getOwnPropertyNames(t).forEach(function(o){this.append(o,t[o])},this)}function y(t){if(t.bodyUsed)return Promise.reject(new TypeError('Already read'));t.bodyUsed=!0}function l(t){return new Promise(function(o,n){t.onload=function(){o(t.result)},t.onerror=function(){n(t.error)}})}function p(t){var o=new FileReader,n=l(o);return o.readAsArrayBuffer(t),n}function b(t){for(var o=new Uint8Array(t),n=new Array(o.length),s=0;s-1?s:n),this.mode=o.mode||this.mode||null,this.signal=o.signal||this.signal,this.referrer=null,('GET'===this.method||'HEAD'===this.method)&&f)throw new TypeError('Body not allowed for GET or HEAD requests');this._initBody(f)}function A(t){var o=new FormData;return t.trim().split('&').forEach(function(t){if(t){var n=t.split('='),s=n.shift().replace(/\+/g,' '),f=n.join('=').replace(/\+/g,' ');o.append(decodeURIComponent(s),decodeURIComponent(f))}}),o}function x(t,o){o||(o={}),this.type='default',this.status=void 0===o.status?200:o.status,this.ok=this.status>=200&&this.status<300,this.statusText='statusText'in o?o.statusText:'OK',this.headers=new c(o.headers),this.url=o.url||'',this._initBody(t)}_.prototype.clone=function(){return new _(this,{body:this._bodyInit})},v.call(_.prototype),v.call(x.prototype),x.prototype.clone=function(){return new x(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new c(this.headers),url:this.url})},x.error=function(){var t=new x(null,{status:0,statusText:''});return t.type='error',t};var B=[301,302,303,307,308];x.redirect=function(t,o){if(-1===B.indexOf(o))throw new RangeError('Invalid status code');return new x(null,{status:o,headers:{location:t}})},t.DOMException=self.DOMException;try{new t.DOMException}catch(o){t.DOMException=function(t,o){this.message=t,this.name=o;var n=Error(t);this.stack=n.stack},t.DOMException.prototype=Object.create(Error.prototype),t.DOMException.prototype.constructor=t.DOMException}function T(n,s){return new Promise(function(f,h){var u=new _(n,s);if(u.signal&&u.signal.aborted)return h(new t.DOMException('Aborted','AbortError'));var y=new XMLHttpRequest;function l(){y.abort()}y.onload=function(){var t,o,n={status:y.status,statusText:y.statusText,headers:(t=y.getAllResponseHeaders()||'',o=new c,t.replace(/\r?\n[\t ]+/g,' ').split(/\r?\n/).forEach(function(t){var n=t.split(':'),s=n.shift().trim();if(s){var f=n.join(':').trim();o.append(s,f)}}),o)};n.url='responseURL'in y?y.responseURL:n.headers.get('X-Request-URL');var s='response'in y?y.response:y.responseText;f(new x(s,n))},y.onerror=function(){h(new TypeError('Network request failed'))},y.ontimeout=function(){h(new TypeError('Network request failed'))},y.onabort=function(){h(new t.DOMException('Aborted','AbortError'))},y.open(u.method,u.url,!0),'include'===u.credentials?y.withCredentials=!0:'omit'===u.credentials&&(y.withCredentials=!1),'responseType'in y&&o.blob&&(y.responseType='blob'),u.headers.forEach(function(t,o){y.setRequestHeader(o,t)}),u.signal&&(u.signal.addEventListener('abort',l),y.onreadystatechange=function(){4===y.readyState&&u.signal.removeEventListener('abort',l)}),y.send(void 0===u._bodyInit?null:u._bodyInit)})}T.polyfill=!0,self.fetch||(self.fetch=T,self.Headers=c,self.Request=_,self.Response=x),t.Headers=c,t.Request=_,t.Response=x,t.fetch=T,Object.defineProperty(t,'__esModule',{value:!0})},'object'==typeof e&&void 0!==m?o(e):'function'==typeof define&&define.amd?define(['exports'],o):o(t.WHATWGFetch={})},131,[]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),s=t(r(d[1])),o=t(r(d[2])),n=t(r(d[3])),c=t(r(d[4])),u=t(r(d[5])),l=t(r(d[6])),f=t(r(d[7])),h=r(d[8]),b=r(d[9]),y=r(d[10]),p=r(d[11]),v=(r(d[12]),r(d[13])),_=r(d[14]),E=r(d[15]),k=r(d[16]),I=0,S=1,N=2,w=3,O=0,C=(function(t){function y(t,n,l){var h;(0,o.default)(this,y),(h=(0,c.default)(this,(0,u.default)(y).call(this))).CONNECTING=I,h.OPEN=S,h.CLOSING=N,h.CLOSED=w,h.readyState=I,'string'==typeof n&&(n=[n]);var b=l||{},v=b.headers,_=void 0===v?{}:v,E=(0,s.default)(b,["headers"]);return E&&'string'==typeof E.origin&&(console.warn('Specifying `origin` as a WebSocket connection option is deprecated. Include it under `headers` instead.'),_.origin=E.origin,delete E.origin),Object.keys(E).length>0&&console.warn('Unrecognized WebSocket connection option(s) `'+Object.keys(E).join('`, `')+"`. Did you mean to put these under `headers`?"),Array.isArray(n)||(n=null),h._eventEmitter=new p(f.default),h._socketId=O++,h._registerEvents(),f.default.connect(t,n,{headers:_},h._socketId),h}return(0,l.default)(y,t),(0,n.default)(y,[{key:"close",value:function(t,s){this.readyState!==this.CLOSING&&this.readyState!==this.CLOSED&&(this.readyState=this.CLOSING,this._close(t,s))}},{key:"send",value:function(t){if(this.readyState===this.CONNECTING)throw new Error('INVALID_STATE_ERR');if(t instanceof h)return k(b.isAvailable,'Native module BlobModule is required for blob support'),void b.sendOverSocket(t,this._socketId);if('string'!=typeof t){if(!(t instanceof ArrayBuffer||ArrayBuffer.isView(t)))throw new Error('Unsupported data type');f.default.sendBinary(E(t),this._socketId)}else f.default.send(t,this._socketId)}},{key:"ping",value:function(){if(this.readyState===this.CONNECTING)throw new Error('INVALID_STATE_ERR');f.default.ping(this._socketId)}},{key:"_close",value:function(t,s){var o='number'==typeof t?t:1e3,n='string'==typeof s?s:'';f.default.close(o,n,this._socketId),b.isAvailable&&'blob'===this._binaryType&&b.removeWebSocketHandler(this._socketId)}},{key:"_unregisterEvents",value:function(){this._subscriptions.forEach(function(t){return t.remove()}),this._subscriptions=[]}},{key:"_registerEvents",value:function(){var t=this;this._subscriptions=[this._eventEmitter.addListener('websocketMessage',function(s){if(s.id===t._socketId){var o=s.data;switch(s.type){case'binary':o=_.toByteArray(s.data).buffer;break;case'blob':o=b.createFromOptions(s.data)}t.dispatchEvent(new v('message',{data:o}))}}),this._eventEmitter.addListener('websocketOpen',function(s){s.id===t._socketId&&(t.readyState=t.OPEN,t.protocol=s.protocol,t.dispatchEvent(new v('open')))}),this._eventEmitter.addListener('websocketClosed',function(s){s.id===t._socketId&&(t.readyState=t.CLOSED,t.dispatchEvent(new v('close',{code:s.code,reason:s.reason})),t._unregisterEvents(),t.close())}),this._eventEmitter.addListener('websocketFailed',function(s){s.id===t._socketId&&(t.readyState=t.CLOSED,t.dispatchEvent(new v('error',{message:s.message})),t.dispatchEvent(new v('close',{message:s.message})),t._unregisterEvents(),t.close())})]}},{key:"binaryType",get:function(){return this._binaryType},set:function(t){if('blob'!==t&&'arraybuffer'!==t)throw new Error("binaryType must be either 'blob' or 'arraybuffer'");'blob'!==this._binaryType&&'blob'!==t||(k(b.isAvailable,'Native module BlobModule is required for blob support'),'blob'===t?b.addWebSocketHandler(this._socketId):b.removeWebSocketHandler(this._socketId)),this._binaryType=t}}]),y})(y.apply(void 0,['close','error','message','open']));C.CONNECTING=I,C.OPEN=S,C.CLOSING=N,C.CLOSED=w,m.exports=C},132,[3,55,4,5,6,9,10,133,120,118,122,125,57,134,128,127,16]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var o=t(r(d[1])).getEnforcing('WebSocketModule');e.default=o},133,[2,22]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),s=r(d[1]);m.exports=function n(o,c){s(this,n),this.type=o.toString(),t(this,c)}},134,[24,4]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=r(d[1]),s=r(d[2]),u=r(d[3]),l=r(d[4]),o=r(d[5]),c=r(d[6]),h=(function(h){function f(n,l,o){var h;return t(this,f),c(null!=n&&null!=l,'Failed to construct `File`: Must pass both `parts` and `name` arguments.'),(h=s(this,u(f).call(this,n,o))).data.name=l,h}return l(f,o),n(f,[{key:"name",get:function(){return c(null!=this.data.name,'Files must have a name set.'),this.data.name}},{key:"lastModified",get:function(){return this.data.lastModified||0}}]),f})();m.exports=h},135,[4,5,6,9,10,120,16]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),s=t(r(d[1])),n=t(r(d[2])),o=t(r(d[3])),u=t(r(d[4])),h=t(r(d[5])),_=t(r(d[6])),l=(r(d[7]),0),c=1,y=2,f=(function(t){function f(){var t;return(0,s.default)(this,f),(t=(0,o.default)(this,(0,u.default)(f).call(this))).EMPTY=l,t.LOADING=c,t.DONE=y,t._aborted=!1,t._subscriptions=[],t._reset(),t}return(0,h.default)(f,t),(0,n.default)(f,[{key:"_reset",value:function(){this._readyState=l,this._error=null,this._result=null}},{key:"_clearSubscriptions",value:function(){this._subscriptions.forEach(function(t){return t.remove()}),this._subscriptions=[]}},{key:"_setReadyState",value:function(t){this._readyState=t,this.dispatchEvent({type:'readystatechange'}),t===y&&(this._aborted?this.dispatchEvent({type:'abort'}):this._error?this.dispatchEvent({type:'error'}):this.dispatchEvent({type:'load'}),this.dispatchEvent({type:'loadend'}))}},{key:"readAsArrayBuffer",value:function(){throw new Error('FileReader.readAsArrayBuffer is not implemented')}},{key:"readAsDataURL",value:function(t){var s=this;this._aborted=!1,_.default.readAsDataURL(t.data).then(function(t){s._aborted||(s._result=t,s._setReadyState(y))},function(t){s._aborted||(s._error=t,s._setReadyState(y))})}},{key:"readAsText",value:function(t){var s=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:'UTF-8';this._aborted=!1,_.default.readAsText(t.data,n).then(function(t){s._aborted||(s._result=t,s._setReadyState(y))},function(t){s._aborted||(s._error=t,s._setReadyState(y))})}},{key:"abort",value:function(){this._aborted=!0,this._readyState!==l&&this._readyState!==y&&(this._reset(),this._setReadyState(y)),this._reset()}},{key:"readyState",get:function(){return this._readyState}},{key:"error",get:function(){return this._error}},{key:"result",get:function(){return this._result}}]),f})(r(d[8]).apply(void 0,['abort','error','load','loadstart','loadend','progress']));f.EMPTY=l,f.LOADING=c,f.DONE=y,m.exports=f},136,[3,4,5,6,9,10,137,120,122]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var u=t(r(d[1])).getEnforcing('FileReaderModule');e.default=u},137,[2,22]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.URL=e.URLSearchParams=void 0;var n=t(r(d[1])),o=t(r(d[2])),u=t(r(d[3])),s=(r(d[4]),null);if(u.default&&'string'==typeof u.default.getConstants().BLOB_URI_SCHEME){var f=u.default.getConstants();s=f.BLOB_URI_SCHEME+':','string'==typeof f.BLOB_URI_HOST&&(s+="//"+f.BLOB_URI_HOST+"/")}var l="function"==typeof Symbol?Symbol.iterator:"@@iterator",h=(function(){function t(o){var u=this;(0,n.default)(this,t),this._searchParams=[],'object'==typeof o&&Object.keys(o).forEach(function(t){return u.append(t,o[t])})}return(0,o.default)(t,[{key:"append",value:function(t,n){this._searchParams.push([t,n])}},{key:"delete",value:function(t){throw new Error('not implemented')}},{key:"get",value:function(t){throw new Error('not implemented')}},{key:"getAll",value:function(t){throw new Error('not implemented')}},{key:"has",value:function(t){throw new Error('not implemented')}},{key:"set",value:function(t,n){throw new Error('not implemented')}},{key:"sort",value:function(){throw new Error('not implemented')}},{key:l,value:function(){return this._searchParams["function"==typeof Symbol?Symbol.iterator:"@@iterator"]()}},{key:"toString",value:function(){if(0===this._searchParams.length)return'';var t=this._searchParams.length-1;return this._searchParams.reduce(function(n,o,u){return n+o.join('=')+(u===t?'':'&')},'')}}]),t})();function c(t){return/^(?:(?:(?:https?|ftp):)?\/\/)(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(t)}e.URLSearchParams=h;var y=(function(){function t(o,u){(0,n.default)(this,t),this._searchParamsInstance=null;var s=null;if(!u||c(o))this._url=o,this._url.endsWith('/')||(this._url+='/');else{if('string'==typeof u){if(!c(s=u))throw new TypeError("Invalid base URL: "+s)}else'object'==typeof u&&(s=u.toString());s.endsWith('/')&&o.startsWith('/')&&(s=s.slice(0,s.length-1)),s.endsWith(o)&&(o=''),this._url=""+s+o}}return(0,o.default)(t,null,[{key:"createObjectURL",value:function(t){if(null===s)throw new Error('Cannot create URL for blob!');return""+s+t.data.blobId+"?offset="+t.data.offset+"&size="+t.size}},{key:"revokeObjectURL",value:function(t){}}]),(0,o.default)(t,[{key:"toJSON",value:function(){return this.toString()}},{key:"toString",value:function(){if(null===this._searchParamsInstance)return this._url;var t=this._url.indexOf('?')>-1?'&':'?';return this._url+t+this._searchParamsInstance.toString()}},{key:"hash",get:function(){throw new Error('not implemented')}},{key:"host",get:function(){throw new Error('not implemented')}},{key:"hostname",get:function(){throw new Error('not implemented')}},{key:"href",get:function(){return this.toString()}},{key:"origin",get:function(){throw new Error('not implemented')}},{key:"password",get:function(){throw new Error('not implemented')}},{key:"pathname",get:function(){throw new Error('not implemented')}},{key:"port",get:function(){throw new Error('not implemented')}},{key:"protocol",get:function(){throw new Error('not implemented')}},{key:"search",get:function(){throw new Error('not implemented')}},{key:"searchParams",get:function(){return null==this._searchParamsInstance&&(this._searchParamsInstance=new h),this._searchParamsInstance}},{key:"username",get:function(){throw new Error('not implemented')}}]),t})();e.URL=y},138,[3,4,5,119,120]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),o=r(d[1]),n=r(d[2]),l=r(d[3]),b=r(d[4]);Object.defineProperty(e,'__esModule',{value:!0});var u=r(d[5]),p=(function(u){function p(){throw t(this,p),n(this,l(p).call(this)),new TypeError("AbortSignal cannot be constructed directly")}return b(p,u),o(p,[{key:"aborted",get:function(){var t=y.get(this);if("boolean"!=typeof t)throw new TypeError("Expected 'this' to be an 'AbortSignal' object, but got "+(null===this?"null":typeof this));return t}}]),p})(u.EventTarget);u.defineEventAttribute(p.prototype,"abort");var y=new WeakMap;Object.defineProperties(p.prototype,{aborted:{enumerable:!0}}),"function"==typeof Symbol&&"symbol"==typeof("function"==typeof Symbol?Symbol.toStringTag:"@@toStringTag")&&Object.defineProperty(p.prototype,"function"==typeof Symbol?Symbol.toStringTag:"@@toStringTag",{configurable:!0,value:"AbortSignal"});var f=(function(){function n(){var o;t(this,n),c.set(this,(o=Object.create(p.prototype),u.EventTarget.call(o),y.set(o,!1),o))}return o(n,[{key:"abort",value:function(){var t;t=s(this),!1===y.get(t)&&(y.set(t,!0),t.dispatchEvent({type:"abort"}))}},{key:"signal",get:function(){return s(this)}}]),n})(),c=new WeakMap;function s(t){var o=c.get(t);if(null==o)throw new TypeError("Expected 'this' to be an 'AbortController' object, but got "+(null===t?"null":typeof t));return o}Object.defineProperties(f.prototype,{signal:{enumerable:!0},abort:{enumerable:!0}}),"function"==typeof Symbol&&"symbol"==typeof("function"==typeof Symbol?Symbol.toStringTag:"@@toStringTag")&&Object.defineProperty(f.prototype,"function"==typeof Symbol?Symbol.toStringTag:"@@toStringTag",{configurable:!0,value:"AbortController"}),e.AbortController=f,e.AbortSignal=p,e.default=f,m.exports=f,m.exports.AbortController=m.exports.default=f,m.exports.AbortSignal=p},139,[4,5,6,9,10,140]); -__d(function(g,r,i,a,m,e,d){'use strict';Object.defineProperty(e,'__esModule',{value:!0});var t=new WeakMap,n=new WeakMap;function o(n){var o=t.get(n);return console.assert(null!=o,"'this' is expected an Event object, but got",n),o}function l(t){null==t.passiveListener?t.event.cancelable&&(t.canceled=!0,"function"==typeof t.event.preventDefault&&t.event.preventDefault()):"undefined"!=typeof console&&"function"==typeof console.error&&console.error("Unable to preventDefault inside passive event listener invocation.",t.passiveListener)}function u(n,o){t.set(this,{eventTarget:n,event:o,eventPhase:2,currentTarget:n,canceled:!1,stopped:!1,immediateStopped:!1,passiveListener:null,timeStamp:o.timeStamp||Date.now()}),Object.defineProperty(this,"isTrusted",{value:!1,enumerable:!0});for(var l=Object.keys(o),u=0;u0){for(var t=new Array(arguments.length),n=0;n3&&void 0!==arguments[3]?arguments[3]:'plain-text',c=arguments.length>4?arguments[4]:void 0,f=arguments.length>5?arguments[5]:void 0;if('ios'===l.default.OS){if('function'==typeof s){console.warn("You passed a callback function as the \"type\" argument to Alert.prompt(). React Native is assuming you want to use the deprecated Alert.prompt(title, defaultValue, buttons, callback) signature. The current signature is Alert.prompt(title, message, callbackOrButtons, type, defaultValue, keyboardType) and the old syntax will be removed in a future version.");var p=s;return void u.default.alertWithArgs({title:t||'',type:'plain-text',defaultValue:n||''},function(t,n){p(n)})}var v,y,b=[],h=[];'function'==typeof o?b=[o]:Array.isArray(o)&&o.forEach(function(t,n){if(b[n]=t.onPress,'cancel'===t.style?v=String(n):'destructive'===t.style&&(y=String(n)),t.text||n<(o||[]).length-1){var l={};l[n]=t.text||'',h.push(l)}}),u.default.alertWithArgs({title:t||'',message:n||void 0,buttons:h,type:s||void 0,defaultValue:c,cancelButtonKey:v,destructiveButtonKey:y,keyboardType:f},function(t,n){var o=b[t];o&&o(n)})}}}]),t})();m.exports=c},142,[3,4,5,57,143,144]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var o=t(r(d[1])).get('DialogManagerAndroid');e.default=o},143,[2,22]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0])(r(d[1]));m.exports={alertWithArgs:function(l,u){null!=t.default&&t.default.alertWithArgs(l,u)}}},144,[3,145]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var u=t(r(d[1])).get('AlertManager');e.default=u},145,[2,22]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]).polyfillObjectProperty,o=g.navigator;void 0===o&&(g.navigator=o={}),t(o,'product',function(){return'ReactNative'})},146,[107]); -__d(function(g,r,i,a,m,e,d){'use strict';if(!g.RN$Bridgeless){var l=r(d[0]);l.registerLazyCallableModule('Systrace',function(){return r(d[1])}),l.registerLazyCallableModule('JSTimers',function(){return r(d[2])}),l.registerLazyCallableModule('HeapCapture',function(){return r(d[3])}),l.registerLazyCallableModule('SamplingProfiler',function(){return r(d[4])}),l.registerLazyCallableModule('RCTLog',function(){return r(d[5])}),l.registerLazyCallableModule('RCTDeviceEventEmitter',function(){return r(d[6])}),l.registerLazyCallableModule('RCTNativeAppEventEmitter',function(){return r(d[7])}),l.registerLazyCallableModule('GlobalPerformanceLogger',function(){return r(d[8])}),l.registerLazyCallableModule('JSDevSupportModule',function(){return r(d[9])}),l.registerCallableModule('HMRClient',r(d[10]))}},147,[29,36,111,148,150,152,45,153,154,157,159]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0])(r(d[1])),p={captureHeap:function(p){var u=null;try{g.nativeCaptureHeap(p),console.log('HeapCapture.captureHeap succeeded: '+p)}catch(t){console.log('HeapCapture.captureHeap error: '+t.toString()),u=t.toString()}t.default&&t.default.captureComplete(p,u)}};m.exports=p},148,[3,149]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var u=t(r(d[1])).get('HeapCapture');e.default=u},149,[2,22]); -__d(function(g,r,i,a,m,e,d){'use strict';var o={poke:function(o){var l=null,n=null;try{null===(n=g.pokeSamplingProfiler())?console.log('The JSC Sampling Profiler has started'):console.log('The JSC Sampling Profiler has stopped')}catch(o){console.log('Error occurred when restarting Sampling Profiler: '+o.toString()),l=o.toString()}var t=r(d[0]).default;t&&t.operationComplete(o,n,l)}};m.exports=o},150,[151]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var l=t(r(d[1])).get('JSCSamplingProfiler');e.default=l},151,[2,22]); -__d(function(g,r,i,a,m,e,d){'use strict';var o=r(d[0]),n={log:'log',info:'info',warn:'warn',error:'error',fatal:'error'},l=null,t={logIfNoNativeHook:function(o){for(var n=arguments.length,f=new Array(n>1?n-1:0),c=1;c1?c-1:0),s=1;s2&&void 0!==arguments[2]?arguments[2]:-1;if(0===o)return!0;if(n===f)return!1;if('function'==typeof n&&'function'==typeof f)return!1;if('object'!=typeof n||null===n)return n!==f;if('object'!=typeof f||null===f)return!0;if(n.constructor!==f.constructor)return!0;if(Array.isArray(n)){var u=n.length;if(f.length!==u)return!0;for(var c=0;c=C},u=function(){},e.unstable_forceFrameRate=function(n){0>n||125(F=lc){if(s=f,null===E)E=o.next=o.previous=o;else{u=null;var p=E;do{if(s1&&(o[u]=c)}else o[u]=f}for(var l in n)f.includes(l)||(u?n.hasOwnProperty(l)&&c(n[l],u[l],l):o[l]={});return o},e.getConfigWithoutViewProps=function(t,f){if(!t[f])return{};return Object.keys(t[f]).filter(function(t){return!n.default[f][t]}).reduce(function(n,u){return n[u]=t[f][u],n},{})},e.stringifyViewConfig=function(t){return JSON.stringify(t,function(t,n){return'function'==typeof n?"\u0192 "+n.name:n},2)},e.default=void 0;var n=t(r(d[1])),f=(r(d[2]),['transform','hitSlop']);var u=function(t,n){};e.default=u},172,[3,173,176]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),o=t(r(d[1])),s=t(r(d[2])),n={uiViewClassName:'RCTView',baseModuleName:null,Manager:'ViewManager',Commands:{},Constants:{},bubblingEventTypes:(0,o.default)({},s.default.bubblingEventTypes,{topBlur:{phasedRegistrationNames:{bubbled:'onBlur',captured:'onBlurCapture'}},topChange:{phasedRegistrationNames:{bubbled:'onChange',captured:'onChangeCapture'}},topEndEditing:{phasedRegistrationNames:{bubbled:'onEndEditing',captured:'onEndEditingCapture'}},topFocus:{phasedRegistrationNames:{bubbled:'onFocus',captured:'onFocusCapture'}},topKeyPress:{phasedRegistrationNames:{bubbled:'onKeyPress',captured:'onKeyPressCapture'}},topPress:{phasedRegistrationNames:{bubbled:'onPress',captured:'onPressCapture'}},topSubmitEditing:{phasedRegistrationNames:{bubbled:'onSubmitEditing',captured:'onSubmitEditingCapture'}},topTouchCancel:{phasedRegistrationNames:{bubbled:'onTouchCancel',captured:'onTouchCancelCapture'}},topTouchEnd:{phasedRegistrationNames:{bubbled:'onTouchEnd',captured:'onTouchEndCapture'}},topTouchMove:{phasedRegistrationNames:{bubbled:'onTouchMove',captured:'onTouchMoveCapture'}},topTouchStart:{phasedRegistrationNames:{bubbled:'onTouchStart',captured:'onTouchStartCapture'}}}),directEventTypes:(0,o.default)({},s.default.directEventTypes,{topAccessibilityAction:{registrationName:'onAccessibilityAction'},topAccessibilityEscape:{registrationName:'onAccessibilityEscape'},topAccessibilityTap:{registrationName:'onAccessibilityTap'},topLayout:{registrationName:'onLayout'},topMagicTap:{registrationName:'onMagicTap'},onGestureHandlerEvent:{registrationName:'onGestureHandlerEvent'},onGestureHandlerStateChange:{registrationName:'onGestureHandlerStateChange'}}),validAttributes:(0,o.default)({},s.default.validAttributes,{accessibilityActions:!0,accessibilityElementsHidden:!0,accessibilityHint:!0,accessibilityIgnoresInvertColors:!0,accessibilityLabel:!0,accessibilityLiveRegion:!0,accessibilityRole:!0,accessibilityStates:!0,accessibilityState:!0,accessibilityViewIsModal:!0,accessible:!0,alignContent:!0,alignItems:!0,alignSelf:!0,aspectRatio:!0,backfaceVisibility:!0,backgroundColor:{process:r(d[3])},borderBottomColor:{process:r(d[3])},borderBottomEndRadius:!0,borderBottomLeftRadius:!0,borderBottomRightRadius:!0,borderBottomStartRadius:!0,borderBottomWidth:!0,borderColor:{process:r(d[3])},borderEndColor:{process:r(d[3])},borderEndWidth:!0,borderLeftColor:{process:r(d[3])},borderLeftWidth:!0,borderRadius:!0,borderRightColor:{process:r(d[3])},borderRightWidth:!0,borderStartColor:{process:r(d[3])},borderStartWidth:!0,borderStyle:!0,borderTopColor:{process:r(d[3])},borderTopEndRadius:!0,borderTopLeftRadius:!0,borderTopRightRadius:!0,borderTopStartRadius:!0,borderTopWidth:!0,borderWidth:!0,bottom:!0,clickable:!0,collapsable:!0,direction:!0,display:!0,elevation:!0,end:!0,flex:!0,flexBasis:!0,flexDirection:!0,flexGrow:!0,flexShrink:!0,flexWrap:!0,height:!0,hitSlop:{diff:r(d[4])},importantForAccessibility:!0,justifyContent:!0,left:!0,margin:!0,marginBottom:!0,marginEnd:!0,marginHorizontal:!0,marginLeft:!0,marginRight:!0,marginStart:!0,marginTop:!0,marginVertical:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,nativeID:!0,needsOffscreenAlphaCompositing:!0,onAccessibilityAction:!0,onAccessibilityEscape:!0,onAccessibilityTap:!0,onLayout:!0,onMagicTap:!0,opacity:!0,overflow:!0,padding:!0,paddingBottom:!0,paddingEnd:!0,paddingHorizontal:!0,paddingLeft:!0,paddingRight:!0,paddingStart:!0,paddingTop:!0,paddingVertical:!0,pointerEvents:!0,position:!0,removeClippedSubviews:!0,renderToHardwareTextureAndroid:!0,right:!0,rotation:!0,scaleX:!0,scaleY:!0,shadowColor:{process:r(d[3])},shadowOffset:{diff:r(d[5])},shadowOpacity:!0,shadowRadius:!0,shouldRasterizeIOS:!0,start:!0,style:{alignContent:!0,alignItems:!0,alignSelf:!0,aspectRatio:!0,backfaceVisibility:!0,backgroundColor:{process:r(d[3])},borderBottomColor:{process:r(d[3])},borderBottomEndRadius:!0,borderBottomLeftRadius:!0,borderBottomRightRadius:!0,borderBottomStartRadius:!0,borderBottomWidth:!0,borderColor:{process:r(d[3])},borderEndColor:{process:r(d[3])},borderEndWidth:!0,borderLeftColor:{process:r(d[3])},borderLeftWidth:!0,borderRadius:!0,borderRightColor:{process:r(d[3])},borderRightWidth:!0,borderStartColor:{process:r(d[3])},borderStartWidth:!0,borderStyle:!0,borderTopColor:{process:r(d[3])},borderTopEndRadius:!0,borderTopLeftRadius:!0,borderTopRightRadius:!0,borderTopStartRadius:!0,borderTopWidth:!0,borderWidth:!0,bottom:!0,color:{process:r(d[3])},decomposedMatrix:!0,direction:!0,display:!0,elevation:!0,end:!0,flex:!0,flexBasis:!0,flexDirection:!0,flexGrow:!0,flexShrink:!0,flexWrap:!0,fontFamily:!0,fontSize:!0,fontStyle:!0,fontVariant:!0,fontWeight:!0,height:!0,includeFontPadding:!0,justifyContent:!0,left:!0,letterSpacing:!0,lineHeight:!0,margin:!0,marginBottom:!0,marginEnd:!0,marginHorizontal:!0,marginLeft:!0,marginRight:!0,marginStart:!0,marginTop:!0,marginVertical:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,opacity:!0,overflow:!0,overlayColor:{process:r(d[3])},padding:!0,paddingBottom:!0,paddingEnd:!0,paddingHorizontal:!0,paddingLeft:!0,paddingRight:!0,paddingStart:!0,paddingTop:!0,paddingVertical:!0,position:!0,resizeMode:!0,right:!0,rotation:!0,scaleX:!0,scaleY:!0,shadowColor:{process:r(d[3])},shadowOffset:{diff:r(d[5])},shadowOpacity:!0,shadowRadius:!0,start:!0,textAlign:!0,textAlignVertical:!0,textDecorationColor:{process:r(d[3])},textDecorationLine:!0,textDecorationStyle:!0,textShadowColor:{process:r(d[3])},textShadowOffset:!0,textShadowRadius:!0,textTransform:!0,tintColor:{process:r(d[3])},top:!0,transform:{diff:r(d[6])},transformMatrix:!0,translateX:!0,translateY:!0,width:!0,writingDirection:!0,zIndex:!0},testID:!0,top:!0,transform:{diff:r(d[6])},translateX:!0,translateY:!0,width:!0,zIndex:!0})};m.exports=n},173,[3,53,170,84,174,87,175]); -__d(function(g,r,i,a,m,e,d){'use strict';var t={top:void 0,left:void 0,right:void 0,bottom:void 0};m.exports=function(o,f){return(o=o||t)!==(f=f||t)&&(o.top!==f.top||o.left!==f.left||o.right!==f.right||o.bottom!==f.bottom)}},174,[]); -__d(function(g,r,i,a,m,e,d){'use strict';m.exports=function(t,n){return!(t===n||t&&n&&t[12]===n[12]&&t[13]===n[13]&&t[14]===n[14]&&t[5]===n[5]&&t[10]===n[10]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[6]===n[6]&&t[7]===n[7]&&t[8]===n[8]&&t[9]===n[9]&&t[11]===n[11]&&t[15]===n[15])}},175,[]); -__d(function(g,r,i,a,m,e,d){'use strict';var n=r(d[0]),t=r(d[1]),s=r(d[2]),o=r(d[3]),u=r(d[4]),c=r(d[5]),l=r(d[6]),v=r(d[7]),b=r(d[8]),p=r(d[9]),f=r(d[10]),y=r(d[11]),C=r(d[12]);var E=!1;function T(n){var t=o.getConstants();t.ViewManagerNames||t.LazyViewManagersEnabled?n=w(n,o.getDefaultEventTypes()):(n.bubblingEventTypes=w(n.bubblingEventTypes,t.genericBubblingEventTypes),n.directEventTypes=w(n.directEventTypes,t.genericDirectEventTypes))}function w(n,t){if(!t)return n;if(!n)return t;for(var s in t)if(t.hasOwnProperty(s)){var o=t[s];if(n.hasOwnProperty(s)){var u=n[s];'object'==typeof o&&'object'==typeof u&&(o=w(u,o))}n[s]=o}return n}function I(n){switch(n){case'CATransform3D':return l;case'CGPoint':return v;case'CGSize':return y;case'UIEdgeInsets':return u}return null}function N(n){switch(n){case'CGColor':case'UIColor':return b;case'CGColorArray':case'UIColorArray':return p;case'CGImage':case'UIImage':case'RCTImageSource':return f;case'Color':return b;case'ColorArray':return p}return null}m.exports=function(u){var l=o.getViewManagerConfig(u);c(null!=l&&null!=l.NativeProps,'requireNativeComponent: "%s" was not found in the UIManager.',u);for(var v=l.baseModuleName,b=l.bubblingEventTypes,p=l.directEventTypes,f=l.NativeProps;v;){var y=o.getViewManagerConfig(v);y?(b=t({},y.bubblingEventTypes,b),p=t({},y.directEventTypes,p),f=t({},y.NativeProps,f),v=y.baseModuleName):(C(!1,'Base module "%s" does not exist',v),v=null)}var w={};for(var M in f){var P=f[M],h=I(P),A=N(P);w[M]=null==h&&null==A||{diff:h,process:A}}return w.style=s,n(l,{uiViewClassName:u,validAttributes:w,bubblingEventTypes:b,directEventTypes:p}),E||(T(l),E=!0),l}},176,[24,53,66,77,174,16,175,177,84,178,179,87,18]); -__d(function(g,r,i,a,m,e,d){'use strict';var t={x:void 0,y:void 0};m.exports=function(n,o){return(n=n||t)!==(o=o||t)&&(n.x!==o.x||n.y!==o.y)}},177,[]); -__d(function(g,r,i,a,m,e,d){'use strict';var n=r(d[0]);m.exports=function(t){return null==t?null:t.map(n)}},178,[84]); -__d(function(g,r,i,a,m,e,d){'use strict';var t,n,s,u,o=r(d[0]),f=r(d[1]);function c(){if(u)return u;var t=g.nativeExtensions&&g.nativeExtensions.SourceCode;return t||(t=r(d[2]).default),u=t.getConstants().scriptURL}function l(){if(void 0===n){var t=c(),s=t&&t.match(/^https?:\/\/.*?\//);n=s?s[0]:null}return n}function v(t){if(t){if(t.startsWith('assets://'))return null;(t=t.substring(0,t.lastIndexOf('/')+1)).includes('://')||(t='file://'+t)}return t}m.exports=function(n){if('object'==typeof n)return n;var u=o.getAssetByID(n);if(!u)return null;var p=new f(l(),(void 0===s&&(s=v(c())),s),u);return t?t(p):p.defaultAsset()},m.exports.pickScale=f.pickScale,m.exports.setCustomSourceTransformer=function(n){t=n}},179,[180,181,183]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=[];m.exports={registerAsset:function(s){return t.push(s)},getAssetByID:function(s){return t[s-1]}}},180,[]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),s=r(d[1]),n=r(d[2]),u=(r(d[3]),r(d[4])),o=r(d[5]);function l(t){var s=h.pickScale(t.scales,n.get()),o=1===s?'':'@'+s+'x';return u.getBasePath(t)+'/'+t.name+o+'.'+t.type}function c(t){var s=h.pickScale(t.scales,n.get());return u.getAndroidResourceFolderName(t,s)+'/'+u.getAndroidResourceIdentifier(t)+'.'+t.type}var h=(function(){function h(s,n,u){t(this,h),this.serverUrl=s,this.jsbundleUrl=n,this.asset=u}return s(h,[{key:"isLoadedFromServer",value:function(){return!!this.serverUrl}},{key:"isLoadedFromFileSystem",value:function(){return!(!this.jsbundleUrl||!this.jsbundleUrl.startsWith('file://'))}},{key:"defaultAsset",value:function(){return this.isLoadedFromServer()?this.assetServerURL():this.scaledAssetURLNearBundle()}},{key:"assetServerURL",value:function(){return o(!!this.serverUrl,'need server to load from'),this.fromSource(this.serverUrl+l(this.asset)+"?platform=ios&hash="+this.asset.hash)}},{key:"scaledAssetPath",value:function(){return this.fromSource(l(this.asset))}},{key:"scaledAssetURLNearBundle",value:function(){var t=this.jsbundleUrl||'file://';return this.fromSource(t+l(this.asset))}},{key:"resourceIdentifierWithoutScale",value:function(){return o(!1,'resource identifiers work on Android'),this.fromSource(u.getAndroidResourceIdentifier(this.asset))}},{key:"drawableFolderInBundle",value:function(){var t=this.jsbundleUrl||'file://';return this.fromSource(t+c(this.asset))}},{key:"fromSource",value:function(t){return{__packager_asset:!0,width:this.asset.width,height:this.asset.height,uri:t,scale:h.pickScale(this.asset.scales,n.get())}}}],[{key:"pickScale",value:function(t,s){for(var n=0;n=s)return t[n];return t[t.length-1]||1}}]),h})();m.exports=h},181,[4,5,63,57,182,16]); -__d(function(g,r,i,a,m,e,d){'use strict';var t={.75:'ldpi',1:'mdpi',1.5:'hdpi',2:'xhdpi',3:'xxhdpi',4:'xxxhdpi'};function n(n){if(n.toString()in t)return t[n.toString()];throw new Error('no such scale '+n.toString())}var o=new Set(['gif','jpeg','jpg','png','svg','webp','xml']);function s(t){var n=t.httpServerLocation;return'/'===n[0]&&(n=n.substr(1)),n}m.exports={getAndroidAssetSuffix:n,getAndroidResourceFolderName:function(s,u){if(!o.has(s.type))return'raw';var c=n(u);if(!c)throw new Error("Don't know which android drawable suffix to use for scale: "+u+'\nAsset: '+JSON.stringify(s,null,'\t')+'\nPossible scales are:'+JSON.stringify(t,null,'\t'));return'drawable-'+c},getAndroidResourceIdentifier:function(t){return(s(t)+'/'+t.name).toLowerCase().replace(/\//g,'_').replace(/([^a-z0-9_])/g,'').replace(/^assets_/,'')},getBasePath:s}},182,[]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var o=t(r(d[1])).getEnforcing('SourceCode');e.default=o},183,[2,22]); -__d(function(g,r,i,a,m,e,d){'use strict';var n=r(d[0]),t=r(d[1]);m.exports=function(u){return n(u,function(){return t(u)})}},184,[185,176]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]).ReactNativeViewConfigRegistry.register;m.exports=function(n,s){return t(n,s)}},185,[162]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var o=(0,t(r(d[1])).default)('ActivityIndicatorView',{paperComponentName:'RCTActivityIndicatorView'});e.default=o},186,[3,187]); -__d(function(g,r,i,a,m,e,d){'use strict';var n=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var o=n(r(d[1])),t=r(d[2]);var p=function(n,p){var f=p&&p.paperComponentName?p.paperComponentName:n;if(null!=p&&null!=p.paperComponentNameDeprecated)if(t.UIManager.getViewManagerConfig(n))f=n;else{if(null==p.paperComponentNameDeprecated||!t.UIManager.getViewManagerConfig(p.paperComponentNameDeprecated))throw new Error("Failed to find native component for either "+n+" or "+(p.paperComponentNameDeprecated||'(unknown)'));f=p.paperComponentNameDeprecated}return(0,o.default)(f)};e.default=p},187,[3,184,15]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=r(d[1]),o=r(d[2]),l=r(d[3]),u=r(d[4]),s=r(d[5]),f=r(d[6]),c=r(d[7]),h=r(d[8]),p=r(d[9]),v=r(d[10]),y=r(d[11]),b=r(d[12]),k=r(d[13]);function S(t,n){if(null==t||null==n)return!0;if(t.length!==n.length)return!0;for(var o=0;o must be a child of a '),h.createElement(W,{opacity:E(t),transform:D(t)},this.props.children)}}]),f})(h.Component);F.contextTypes={isInSurface:p.bool.isRequired};var M=(function(s){function f(){return t(this,f),o(this,l(f).apply(this,arguments))}return u(f,s),n(f,[{key:"render",value:function(){var t=this.props,n=[N(t.x,0),N(t.y,0),N(t.width,0),N(t.height,0)],o=b(t);return delete o.x,delete o.y,h.createElement(W,{clipping:n,opacity:E(t),transform:D(o)},this.props.children)}}]),f})(h.Component),P=0,X=1,Y=2,O=3;function q(t,n,o){var l=new s(t);n[o+0]=l.red/255,n[o+1]=l.green/255,n[o+2]=l.blue/255,n[o+3]=l.alpha}function j(t,n,o){var l=0;if('length'in t)for(;lT?(X-=M,Y-=b):f>0&&0!=T&&(X-=f/T*M,Y-=f/T*b),l=X*X+Y*Y,(f=(X=o-t)*M+(Y=u-n)*b)>T?(X-=M,Y-=b):f>0&&0!=T&&(X-=f/T*M,Y-=f/T*b),v=X*X+Y*Y,l<.01&&v<.01)this.onLine(t,n,p,c);else{if(isNaN(l)||isNaN(v))throw new Error('Bad input');var k=.5*(s+o),w=.5*(h+u),_=.5*(s+t),D=.5*(h+n),z=.5*(_+k),C=.5*(D+w),B=.5*(p+o),A=.5*(c+u),L=.5*(B+k),I=.5*(A+w),P=.5*(z+L),N=.5*(C+I);this.onBezierCurve(t,n,_,D,z,C,P,N),this.onBezierCurve(P,N,L,I,B,A,p,c)}},onArc:function(t,n,s,h,o,u,p,c,l,v,X,Y){var f=Y?Y*Math.PI/180:0,M=Math.cos(f),b=Math.sin(f),T=M*p,k=-b*c,w=b*p,_=M*c,D=v-l;D<0&&!X?D+=2*Math.PI:D>0&&X&&(D-=2*Math.PI);for(var z=Math.ceil(Math.abs(D/(Math.PI/2))),C=D/z,B=1.3333333333333333*Math.tan(C/4),A=Math.cos(l),L=Math.sin(l),I=0;Ithis.yy/this.xy?-1:1;return(this.xx<0?this.xy>=0:this.xy<0)&&(x=-x),this.rotate(t-180*Math.atan2(x*this.yx,x*this.xx)/Math.PI,s,h)},scaleTo:function(t,s){var h=Math.sqrt(this.xx*this.xx+this.yx*this.yx);return this.xx/=h,this.yx/=h,h=Math.sqrt(this.yy*this.yy+this.xy*this.xy),this.yy/=h,this.xy/=h,this.scale(t,s)},resizeTo:function(t,s){var h=this.width,x=this.height;return h&&x?this.scaleTo(t/h,s/x):this},inversePoint:function(t,s){var h=this.xx,x=this.yx,y=this.xy,n=this.yy,o=this.x,u=this.y,f=x*y-h*n;return 0==f?null:{x:(n*(o-t)+y*(s-u))/f,y:(h*(u-s)+x*(t-o))/f}},point:function(t,s){return{x:this.xx*t+this.xy*s+this.x,y:this.yx*t+this.yy*s+this.y}}})},193,[191]); -__d(function(g,r,i,a,m,e,d){'use strict';var s=r(d[0]),t={pointerEvents:!0,accessible:!0,accessibilityActions:!0,accessibilityLabel:!0,accessibilityLiveRegion:!0,accessibilityRole:!0,accessibilityStates:!0,accessibilityState:!0,accessibilityHint:!0,importantForAccessibility:!0,nativeID:!0,testID:!0,renderToHardwareTextureAndroid:!0,shouldRasterizeIOS:!0,onLayout:!0,onAccessibilityAction:!0,onAccessibilityTap:!0,onMagicTap:!0,onAccessibilityEscape:!0,collapsable:!0,needsOffscreenAlphaCompositing:!0,style:r(d[1])},c={UIView:t,RCTView:s({},t,{removeClippedSubviews:!0})};m.exports=c},194,[53,66]); -__d(function(g,r,i,a,m,e,d){"use strict";var t=r(d[0]);m.exports=function(n,u){var c={};return t(c,n),t(c,u),c}},195,[196]); -__d(function(g,r,i,a,m,e,d){"use strict";var t=r(d[0]),c=t.checkMergeObjectArg,n=t.checkMergeIntoObjectArg;m.exports=function(t,o){if(n(t),null!=o)for(var f in c(o),o)Object.prototype.hasOwnProperty.call(o,f)&&(t[f]=o[f])}},196,[197]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=function(t){return'object'!=typeof t||t instanceof Date||null===t},c={MAX_MERGE_DEPTH:36,isTerminal:n,normalizeMergeArg:function(t){return void 0===t||null===t?{}:t},checkMergeArrayArgs:function(n,c){t(Array.isArray(n)&&Array.isArray(c),'Tried to merge arrays, instead got %s and %s.',n,c)},checkMergeObjectArgs:function(t,n){c.checkMergeObjectArg(t),c.checkMergeObjectArg(n)},checkMergeObjectArg:function(c){t(!n(c)&&!Array.isArray(c),'Tried to merge an object, instead got %s.',c)},checkMergeIntoObjectArg:function(c){t(!(n(c)&&'function'!=typeof c||Array.isArray(c)),'Tried to merge into an object, instead got %s.',c)},checkMergeLevel:function(n){t(n<36,"Maximum deep merge depth exceeded. You may be attempting to merge circular structures in an unsupported way.")},checkArrayStrategy:function(n){t(void 0===n||n in c.ArrayStrategies,"You must provide an array strategy to deep merge functions to instruct the deep merge how to resolve merging two arrays.")},ArrayStrategies:{Clobber:'Clobber',Concat:'Concat',IndexByIndex:'IndexByIndex'}};m.exports=c},197,[16]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),s=r(d[1]),o=r(d[2]),n=r(d[3]),c=r(d[4]),u=r(d[5]),l=(r(d[6]),r(d[7])),b=r(d[8]),p=r(d[9]),x=(r(d[10]),r(d[11])),F=r(d[12]),h=r(d[13]),f=(function(t){function b(){return s(this,b),n(this,c(b).apply(this,arguments))}return u(b,t),o(b,[{key:"render",value:function(){var t=this.props,s=t.accessibilityLabel,o=t.color,n=t.onPress,c=t.touchSoundDisabled,u=t.title,b=t.hasTVPreferredFocus,f=t.nextFocusDown,y=t.nextFocusForward,v=t.nextFocusLeft,w=t.nextFocusRight,L=t.nextFocusUp,P=t.disabled,S=t.testID,E=[D.button],R=[D.text];o&&R.push({color:o});var T=[];P&&(E.push(D.buttonDisabled),R.push(D.textDisabled),T.push('disabled')),h('string'==typeof u,'The title prop of a Button must be a string');var A=u,I=x;return l.createElement(I,{accessibilityLabel:s,accessibilityRole:"button",accessibilityStates:T,hasTVPreferredFocus:b,nextFocusDown:f,nextFocusForward:y,nextFocusLeft:v,nextFocusRight:w,nextFocusUp:L,testID:S,disabled:P,onPress:n,touchSoundDisabled:c},l.createElement(F,{style:E},l.createElement(p,{style:R,disabled:P},A)))}}]),b})(l.Component),D=b.create({button:{},text:t({textAlign:'center',padding:8},{color:'#007AFF',fontSize:18}),buttonDisabled:{},textDisabled:{color:'#cdcdcd'}});m.exports=f},198,[53,4,5,6,9,10,57,59,62,199,214,215,90,16]); -__d(function(g,r,i,a,m,e,d){'use strict';var n=r(d[0]),t=r(d[1]),o=r(d[2]),s=r(d[3]),l=r(d[4]),u=r(d[5]),p=r(d[6]),c=r(d[7]),h=r(d[8]),f=r(d[9]),R=r(d[10]),H=r(d[11]),v=r(d[12]),T=r(d[13]),b=r(d[14]),S=r(d[15]),y=r(d[16]),w={top:20,left:20,right:20,bottom:30},x={validAttributes:c({},R.UIView,{isHighlighted:!0,numberOfLines:!0,ellipsizeMode:!0,allowFontScaling:!0,maxFontSizeMultiplier:!0,disabled:!0,selectable:!0,selectionColor:!0,adjustsFontSizeToFit:!0,minimumFontScale:!0,textBreakStrategy:!0,onTextLayout:!0,onInlineViewLayout:!0,dataDetectorType:!0}),directEventTypes:{topTextLayout:{registrationName:'onTextLayout'},topInlineViewLayout:{registrationName:'onInlineViewLayout'}},uiViewClassName:'RCTText'},C=(function(h){function R(){var n,o;t(this,R);for(var u=arguments.length,h=new Array(u),f=0;f4?p-4:0),l=4;l5?b-5:0),k=5;k4?s-4:0),p=4;p0,s=R&&R.length>0;return!_&&s?R[0]:_?t[0]:E}),T=N({NOT_RESPONDER:null,RESPONDER_INACTIVE_PRESS_IN:null,RESPONDER_INACTIVE_PRESS_OUT:null,RESPONDER_ACTIVE_PRESS_IN:null,RESPONDER_ACTIVE_PRESS_OUT:null,RESPONDER_ACTIVE_LONG_PRESS_IN:null,RESPONDER_ACTIVE_LONG_PRESS_OUT:null,ERROR:null}),u={NOT_RESPONDER:!1,RESPONDER_INACTIVE_PRESS_IN:!1,RESPONDER_INACTIVE_PRESS_OUT:!1,RESPONDER_ACTIVE_PRESS_IN:!1,RESPONDER_ACTIVE_PRESS_OUT:!1,RESPONDER_ACTIVE_LONG_PRESS_IN:!1,RESPONDER_ACTIVE_LONG_PRESS_OUT:!1,ERROR:!1},P=t({},u,{RESPONDER_ACTIVE_PRESS_OUT:!0,RESPONDER_ACTIVE_PRESS_IN:!0}),O=t({},u,{RESPONDER_INACTIVE_PRESS_IN:!0,RESPONDER_ACTIVE_PRESS_IN:!0,RESPONDER_ACTIVE_LONG_PRESS_IN:!0}),D=t({},u,{RESPONDER_ACTIVE_LONG_PRESS_IN:!0}),c=N({DELAY:null,RESPONDER_GRANT:null,RESPONDER_RELEASE:null,RESPONDER_TERMINATED:null,ENTER_PRESS_RECT:null,LEAVE_PRESS_RECT:null,LONG_PRESS_DETECTED:null}),A={NOT_RESPONDER:{DELAY:T.ERROR,RESPONDER_GRANT:T.RESPONDER_INACTIVE_PRESS_IN,RESPONDER_RELEASE:T.ERROR,RESPONDER_TERMINATED:T.ERROR,ENTER_PRESS_RECT:T.ERROR,LEAVE_PRESS_RECT:T.ERROR,LONG_PRESS_DETECTED:T.ERROR},RESPONDER_INACTIVE_PRESS_IN:{DELAY:T.RESPONDER_ACTIVE_PRESS_IN,RESPONDER_GRANT:T.ERROR,RESPONDER_RELEASE:T.NOT_RESPONDER,RESPONDER_TERMINATED:T.NOT_RESPONDER,ENTER_PRESS_RECT:T.RESPONDER_INACTIVE_PRESS_IN,LEAVE_PRESS_RECT:T.RESPONDER_INACTIVE_PRESS_OUT,LONG_PRESS_DETECTED:T.ERROR},RESPONDER_INACTIVE_PRESS_OUT:{DELAY:T.RESPONDER_ACTIVE_PRESS_OUT,RESPONDER_GRANT:T.ERROR,RESPONDER_RELEASE:T.NOT_RESPONDER,RESPONDER_TERMINATED:T.NOT_RESPONDER,ENTER_PRESS_RECT:T.RESPONDER_INACTIVE_PRESS_IN,LEAVE_PRESS_RECT:T.RESPONDER_INACTIVE_PRESS_OUT,LONG_PRESS_DETECTED:T.ERROR},RESPONDER_ACTIVE_PRESS_IN:{DELAY:T.ERROR,RESPONDER_GRANT:T.ERROR,RESPONDER_RELEASE:T.NOT_RESPONDER,RESPONDER_TERMINATED:T.NOT_RESPONDER,ENTER_PRESS_RECT:T.RESPONDER_ACTIVE_PRESS_IN,LEAVE_PRESS_RECT:T.RESPONDER_ACTIVE_PRESS_OUT,LONG_PRESS_DETECTED:T.RESPONDER_ACTIVE_LONG_PRESS_IN},RESPONDER_ACTIVE_PRESS_OUT:{DELAY:T.ERROR,RESPONDER_GRANT:T.ERROR,RESPONDER_RELEASE:T.NOT_RESPONDER,RESPONDER_TERMINATED:T.NOT_RESPONDER,ENTER_PRESS_RECT:T.RESPONDER_ACTIVE_PRESS_IN,LEAVE_PRESS_RECT:T.RESPONDER_ACTIVE_PRESS_OUT,LONG_PRESS_DETECTED:T.ERROR},RESPONDER_ACTIVE_LONG_PRESS_IN:{DELAY:T.ERROR,RESPONDER_GRANT:T.ERROR,RESPONDER_RELEASE:T.NOT_RESPONDER,RESPONDER_TERMINATED:T.NOT_RESPONDER,ENTER_PRESS_RECT:T.RESPONDER_ACTIVE_LONG_PRESS_IN,LEAVE_PRESS_RECT:T.RESPONDER_ACTIVE_LONG_PRESS_OUT,LONG_PRESS_DETECTED:T.RESPONDER_ACTIVE_LONG_PRESS_IN},RESPONDER_ACTIVE_LONG_PRESS_OUT:{DELAY:T.ERROR,RESPONDER_GRANT:T.ERROR,RESPONDER_RELEASE:T.NOT_RESPONDER,RESPONDER_TERMINATED:T.NOT_RESPONDER,ENTER_PRESS_RECT:T.RESPONDER_ACTIVE_LONG_PRESS_IN,LEAVE_PRESS_RECT:T.RESPONDER_ACTIVE_LONG_PRESS_OUT,LONG_PRESS_DETECTED:T.ERROR},error:{DELAY:T.NOT_RESPONDER,RESPONDER_GRANT:T.RESPONDER_INACTIVE_PRESS_IN,RESPONDER_RELEASE:T.NOT_RESPONDER,RESPONDER_TERMINATED:T.NOT_RESPONDER,ENTER_PRESS_RECT:T.NOT_RESPONDER,LEAVE_PRESS_RECT:T.NOT_RESPONDER,LONG_PRESS_DETECTED:T.NOT_RESPONDER}},I={componentDidMount:function(){_.isTV&&(this._tvEventHandler=new n,this._tvEventHandler.enable(this,function(E,t){var R=o.findNodeHandle(E);t.dispatchConfig={},R===t.tag&&('focus'===t.eventType?E.touchableHandleFocus(t):'blur'===t.eventType?E.touchableHandleBlur(t):'select'===t.eventType&&E.touchableHandlePress&&!E.props.disabled&&E.touchableHandlePress(t))}))},componentWillUnmount:function(){this._tvEventHandler&&(this._tvEventHandler.disable(),delete this._tvEventHandler),this.touchableDelayTimeout&&clearTimeout(this.touchableDelayTimeout),this.longPressDelayTimeout&&clearTimeout(this.longPressDelayTimeout),this.pressOutDelayTimeout&&clearTimeout(this.pressOutDelayTimeout)},touchableGetInitialState:function(){return{touchable:{touchState:void 0,responderID:null}}},touchableHandleResponderTerminationRequest:function(){return!this.props.rejectResponderTermination},touchableHandleStartShouldSetResponder:function(){return!this.props.disabled},touchableLongPressCancelsPress:function(){return!0},touchableHandleResponderGrant:function(E){var t=E.currentTarget;E.persist(),this.pressOutDelayTimeout&&clearTimeout(this.pressOutDelayTimeout),this.pressOutDelayTimeout=null,this.state.touchable.touchState=T.NOT_RESPONDER,this.state.touchable.responderID=t,this._receiveSignal(c.RESPONDER_GRANT,E);var R=void 0!==this.touchableGetHighlightDelayMS?Math.max(this.touchableGetHighlightDelayMS(),0):130;0!==(R=isNaN(R)?130:R)?this.touchableDelayTimeout=setTimeout(this._handleDelay.bind(this,E),R):this._handleDelay(E);var _=void 0!==this.touchableGetLongPressDelayMS?Math.max(this.touchableGetLongPressDelayMS(),10):370;_=isNaN(_)?370:_,this.longPressDelayTimeout=setTimeout(this._handleLongDelay.bind(this,E),_+R)},touchableHandleResponderRelease:function(E){this.pressInLocation=null,this._receiveSignal(c.RESPONDER_RELEASE,E)},touchableHandleResponderTerminate:function(E){this.pressInLocation=null,this._receiveSignal(c.RESPONDER_TERMINATED,E)},touchableHandleResponderMove:function(E){if(this.state.touchable.positionOnActivate){var t=this.state.touchable.positionOnActivate,R=this.state.touchable.dimensionsOnActivate,_=this.touchableGetPressRectOffset?this.touchableGetPressRectOffset():{left:20,right:20,top:20,bottom:20},s=_.left,o=_.top,S=_.right,n=_.bottom,l=this.touchableGetHitSlop?this.touchableGetHitSlop():null;l&&(s+=l.left||0,o+=l.top||0,S+=l.right||0,n+=l.bottom||0);var N=h(E.nativeEvent),u=N&&N.pageX,P=N&&N.pageY;if(this.pressInLocation)this._getDistanceBetweenPoints(u,P,this.pressInLocation.pageX,this.pressInLocation.pageY)>10&&this._cancelLongPressDelayTimeout();if(u>t.left-s&&P>t.top-o&&u2?f-2:0),u=2;u1&&void 0!==arguments[1]?arguments[1]:{}).iterations;return V},event:function(t,n){return null},createAnimatedComponent:E,attachNativeEvent:o,forkEvent:f.forkEvent,unforkEvent:f.unforkEvent,Event:u,__PropsOnlyForTests:s}},217,[53,218,227,220,221,233,219,238,246]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=r(d[1]),s=r(d[2]),v=r(d[3]),o=r(d[4]),c=r(d[5]),_=r(d[3]).shouldUseNativeDriver;function l(t,n,_){var l=[];c(_[0]&&_[0].nativeEvent,'Native driven events only support animated values contained inside `nativeEvent`.'),(function t(n,v){if(n instanceof s)n.__makeNative(),l.push({nativeEventPath:v,animatedValueTag:n.__getNativeTag()});else if('object'==typeof n)for(var o in n)t(n[o],v.concat(o))})(_[0].nativeEvent,[]);var h=o.findNodeHandle(t);return l.forEach(function(t){v.API.addAnimatedEventToView(h,n,t)}),{detach:function(){l.forEach(function(t){v.API.removeAnimatedEventFromView(h,n,t.animatedValueTag)})}}}var h=(function(){function v(n){var s=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};t(this,v),this._listeners=[],this._argMapping=n,s.listener&&this.__addListener(s.listener),this._callListeners=this._callListeners.bind(this),this._attachedEvent=null,this.__isNative=_(s)}return n(v,[{key:"__addListener",value:function(t){this._listeners.push(t)}},{key:"__removeListener",value:function(t){this._listeners=this._listeners.filter(function(n){return n!==t})}},{key:"__attach",value:function(t,n){c(this.__isNative,'Only native driven events need to be attached.'),this._attachedEvent=l(t,n,this._argMapping)}},{key:"__detach",value:function(t,n){c(this.__isNative,'Only native driven events need to be detached.'),this._attachedEvent&&this._attachedEvent.detach()}},{key:"__getHandler",value:function(){var t=this;return this.__isNative?this._callListeners:function(){for(var n=arguments.length,v=new Array(n),o=0;oo){if('identity'===f)return c;'clamp'===f&&(c=o)}return u===p?u:n===o?t<=n?u:p:(n===-1/0?c=-c:o===1/0?c-=n:c=(c-n)/(o-n),c=l(c),u===-1/0?c=-c:p===1/0?c+=u:c=c*(p-u)+u,c)}function x(t){var n=_(t);return null===n?t:"rgba("+((4278190080&(n=n||0))>>>24)+", "+((16711680&n)>>>16)+", "+((65280&n)>>>8)+", "+(255&n)/255+")"}var k=/[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?/g;function b(t){var n=t.outputRange;s(n.length>=2,'Bad output range'),C(n=n.map(x));var o=n[0].match(k).map(function(){return[]});n.forEach(function(t){t.match(k).forEach(function(t,n){o[n].push(+t)})});var u,p=n[0].match(k).map(function(n,u){return y(h({},t,{outputRange:o[u]}))}),l='string'==typeof(u=n[0])&&u.startsWith('rgb');return function(t){var o=0;return n[0].replace(k,function(){var n=+p[o++](t);return l&&(n=o<4?Math.round(n):Math.round(1e3*n)/1e3),String(n)})}}function C(t){for(var n=t[0].replace(k,''),o=1;o=t);++o);return o-1}function N(t){s(t.length>=2,'inputRange must have at least 2 elements');for(var n=1;n=t[n-1],'inputRange must be monotonically non-decreasing '+t)}function w(t,n){s(n.length>=2,t+' must have at least 2 elements'),s(2!==n.length||n[0]!==-1/0||n[1]!==1/0,t+'cannot be ]-infinity;+infinity[ '+n)}var D=(function(h){function _(n,p){var l;return t(this,_),(l=o(this,u(_).call(this)))._parent=n,l._config=p,l._interpolation=y(p),l}return l(_,f),n(_,[{key:"__makeNative",value:function(){this._parent.__makeNative(),p(u(_.prototype),"__makeNative",this).call(this)}},{key:"__getValue",value:function(){var t=this._parent.__getValue();return s('number'==typeof t,'Cannot interpolate an input which is not a number.'),this._interpolation(t)}},{key:"interpolate",value:function(t){return new _(this,t)}},{key:"__attach",value:function(){this._parent.__addChild(this)}},{key:"__detach",value:function(){this._parent.__removeChild(this),p(u(_.prototype),"__detach",this).call(this)}},{key:"__transformDataType",value:function(t){return t.map(c.transformDataType)}},{key:"__getNativeConfig",value:function(){return{inputRange:this._config.inputRange,outputRange:this.__transformDataType(this._config.outputRange),extrapolateLeft:this._config.extrapolateLeft||this._config.extrapolate||'extend',extrapolateRight:this._config.extrapolateRight||this._config.extrapolate||'extend',type:'interpolation'}}}]),_})();D.__createInterpolation=y,m.exports=D},220,[4,5,6,9,46,10,53,221,224,222,16,69]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=r(d[1]),s=r(d[2]),_=s.API,u=r(d[3]),o=1,v=(function(){function v(){t(this,v),this._listeners={}}return n(v,[{key:"__attach",value:function(){}},{key:"__detach",value:function(){this.__isNative&&null!=this.__nativeTag&&(s.API.dropAnimatedNode(this.__nativeTag),this.__nativeTag=void 0)}},{key:"__getValue",value:function(){}},{key:"__getAnimatedValue",value:function(){return this.__getValue()}},{key:"__addChild",value:function(t){}},{key:"__removeChild",value:function(t){}},{key:"__getChildren",value:function(){return[]}}]),n(v,[{key:"__makeNative",value:function(){if(!this.__isNative)throw new Error('This node cannot be made a "native" animated node');this.hasListeners()&&this._startListeningToNativeValueUpdates()}},{key:"addListener",value:function(t){var n=String(o++);return this._listeners[n]=t,this.__isNative&&this._startListeningToNativeValueUpdates(),n}},{key:"removeListener",value:function(t){delete this._listeners[t],this.__isNative&&!this.hasListeners()&&this._stopListeningForNativeValueUpdates()}},{key:"removeAllListeners",value:function(){this._listeners={},this.__isNative&&this._stopListeningForNativeValueUpdates()}},{key:"hasListeners",value:function(){return!!Object.keys(this._listeners).length}},{key:"_startListeningToNativeValueUpdates",value:function(){var t=this;this.__nativeAnimatedValueListener&&!this.__shouldUpdateListenersForNewNativeTag||(this.__shouldUpdateListenersForNewNativeTag&&(this.__shouldUpdateListenersForNewNativeTag=!1,this._stopListeningForNativeValueUpdates()),_.startListeningToAnimatedNodeValue(this.__getNativeTag()),this.__nativeAnimatedValueListener=s.nativeEventEmitter.addListener('onAnimatedValueUpdate',function(n){n.tag===t.__getNativeTag()&&t._onAnimatedValueUpdateReceived(n.value)}))}},{key:"_onAnimatedValueUpdateReceived",value:function(t){this.__callListeners(t)}},{key:"__callListeners",value:function(t){for(var n in this._listeners)this._listeners[n]({value:t})}},{key:"_stopListeningForNativeValueUpdates",value:function(){this.__nativeAnimatedValueListener&&(this.__nativeAnimatedValueListener.remove(),this.__nativeAnimatedValueListener=null,_.stopListeningToAnimatedNodeValue(this.__getNativeTag()))}},{key:"__getNativeTag",value:function(){if(s.assertNativeAnimatedModule(),u(this.__isNative,'Attempt to get native tag from node not marked as "native"'),null==this.__nativeTag){var t=s.generateNewNodeTag();this.__nativeTag=t,s.API.createAnimatedNode(t,this.__getNativeConfig()),this.__shouldUpdateListenersForNewNativeTag=!0}return this.__nativeTag}},{key:"__getNativeConfig",value:function(){throw new Error('This JS animated node type cannot be used as native animated node')}},{key:"toJSON",value:function(){return this.__getValue()}}]),v})();m.exports=v},221,[4,5,222,16]); -__d(function(g,r,i,a,m,e,d){'use strict';var t,n=r(d[0]),o=n(r(d[1])),l=n(r(d[2])),u=n(r(d[3])),s=1,f=1,v=!1,c=[],N={enableQueue:function(){v=!0},disableQueue:function(){(0,u.default)(l.default,'Native animated module is not available'),v=!1;for(var t=0,n=c.length;t=t.length)break;l=t[n++]}else{if((n=t.next()).done)break;l=n.value}var o=l;o.__makeNative(),c.API.connectAnimatedNodes(this.__getNativeTag(),o.__getNativeTag())}}h(s(u.prototype),"__makeNative",this).call(this)}},{key:"__addChild",value:function(t){0===this._children.length&&this.__attach(),this._children.push(t),this.__isNative&&(t.__makeNative(),c.API.connectAnimatedNodes(this.__getNativeTag(),t.__getNativeTag()))}},{key:"__removeChild",value:function(t){var _=this._children.indexOf(t);-1!==_?(this.__isNative&&t.__isNative&&c.API.disconnectAnimatedNodes(this.__getNativeTag(),t.__getNativeTag()),this._children.splice(_,1),0===this._children.length&&this.__detach()):console.warn("Trying to remove a child that doesn't exist")}},{key:"__getChildren",value:function(){return this._children}},{key:"__callListeners",value:function(t){if(h(s(u.prototype),"__callListeners",this).call(this,t),!this.__isNative){var _=this._children,n=Array.isArray(_),l=0;for(_=n?_:_["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var o;if(n){if(l>=_.length)break;o=_[l++]}else{if((l=_.next()).done)break;o=l.value}var c=o;c.__getValue&&c.__callListeners(c.__getValue())}}}}]),u})();m.exports=v},224,[4,5,6,9,46,10,221,222]); -__d(function(g,r,i,a,m,e,d){'use strict';var n=r(d[0]),t=r(d[1]),o=r(d[2]),c=(r(d[3]),r(d[4])),s=r(d[5]),u=new t,l={Events:s({interactionStart:!0,interactionComplete:!0}),runAfterInteractions:function(n){var t=[],o=new Promise(function(o){k(),n&&t.push(n),t.push({run:o,name:'resolve '+(n&&n.name||'?')}),h.enqueueTasks(t)});return{then:o.then.bind(o),done:function(){if(o.done)return o.done.apply(o,arguments);console.warn('Tried to call done when not supported by current Promise implementation.')},cancel:function(){h.cancelTasks(t)}}},createInteractionHandle:function(){k();var n=++T;return p.add(n),n},clearInteractionHandle:function(n){c(!!n,'InteractionManager: Must provide a handle to clear.'),k(),p.delete(n),v.add(n)},addListener:u.addListener.bind(u),setDeadline:function(n){E=n}},f=new Set,p=new Set,v=new Set,h=new o({onMoreTasks:k}),w=0,T=0,E=-1;function k(){w||(w=E>0?setTimeout(I,0):setImmediate(I))}function I(){w=0;var t=f.size;p.forEach(function(n){return f.add(n)}),v.forEach(function(n){return f.delete(n)});var o=f.size;if(0!==t&&0===o?u.emit(l.Events.interactionComplete):0===t&&0!==o&&u.emit(l.Events.interactionStart),0===o)for(;h.hasTasksToProcess();)if(h.processNext(),E>0&&n.getEventLoopRunningTime()>=E){k();break}p.clear(),v.clear()}m.exports=l},225,[29,48,226,156,16,211]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),u=r(d[1]),s=r(d[2]),n=(r(d[3]),r(d[4])),o=(function(){function o(t){var s=t.onMoreTasks;u(this,o),this._onMoreTasks=s,this._queueStack=[{tasks:[],popable:!1}]}return s(o,[{key:"enqueue",value:function(t){this._getCurrentQueue().push(t)}},{key:"enqueueTasks",value:function(t){var u=this;t.forEach(function(t){return u.enqueue(t)})}},{key:"cancelTasks",value:function(u){this._queueStack=this._queueStack.map(function(s){return t({},s,{tasks:s.tasks.filter(function(t){return-1===u.indexOf(t)})})}).filter(function(t,u){return t.tasks.length>0||0===u})}},{key:"hasTasksToProcess",value:function(){return this._getCurrentQueue().length>0}},{key:"processNext",value:function(){var t=this._getCurrentQueue();if(t.length){var u=t.shift();try{u.gen?this._genPromise(u):u.run?u.run():(n('function'==typeof u,'Expected Function, SimpleTask, or PromiseTask, but got:\n'+JSON.stringify(u,null,2)),u())}catch(t){throw t.message='TaskQueue: Error with task '+(u.name||'')+': '+t.message,t}}}},{key:"_getCurrentQueue",value:function(){var t=this._queueStack.length-1,u=this._queueStack[t];return u.popable&&0===u.tasks.length&&this._queueStack.length>1?(this._queueStack.pop(),this._getCurrentQueue()):u.tasks}},{key:"_genPromise",value:function(t){var u=this;this._queueStack.push({tasks:[],popable:!1});var s=this._queueStack.length-1;t.gen().then(function(){u._queueStack[s].popable=!0,u.hasTasksToProcess()&&u._onMoreTasks()}).catch(function(u){throw u.message="TaskQueue: Error resolving Promise in task "+t.name+": "+u.message,u}).done()}}]),o})();m.exports=o},226,[53,4,5,156,16]); -__d(function(g,r,i,a,m,e,d){'use strict';var n=r(d[0]),t=r(d[1]),o=t.AnimatedEvent,u=t.attachNativeEvent,s=r(d[2]),c=r(d[3]),f=r(d[4]),v=r(d[5]),p=r(d[6]),l=r(d[7]),h=r(d[8]),_=r(d[9]),N=r(d[10]),w=r(d[11]),E=r(d[12]),y=r(d[13]),D=r(d[14]),L=r(d[15]),A=r(d[16]),U=r(d[17]),k=function(n,t){return n&&t.onComplete?function(){t.onComplete&&t.onComplete.apply(t,arguments),n&&n.apply(void 0,arguments)}:n||t.onComplete},V=function(t,o,u){if(t instanceof y){var s=n({},o),c=n({},o);for(var f in o){var v=o[f],p=v.x,l=v.y;void 0!==p&&void 0!==l&&(s[f]=p,c[f]=l)}var h=u(t.x,s),_=u(t.y,c);return x([h,_],{stopTogether:!1})}return null},C=function t(o,u){var s=function(n,t,o){o=k(o,t);var u=n,s=t;u.stopTracking(),t.toValue instanceof h?u.track(new w(u,t.toValue,A,s,o)):u.animate(new A(s),o)};return V(o,u,t)||{start:function(n){s(o,u,n)},stop:function(){o.stopAnimation()},reset:function(){o.resetAnimation()},_startNativeLoop:function(t){var c=n({},u,{iterations:t});s(o,c)},_isUsingNativeDriver:function(){return u.useNativeDriver||!1}}},T=function(n){var t=0;return{start:function(o){0===n.length?o&&o({finished:!0}):n[t].start(function u(s){s.finished&&++t!==n.length?n[t].start(u):o&&o(s)})},stop:function(){t1&&void 0!==arguments[1]?arguments[1]:{},o=t.iterations,u=void 0===o?-1:o,s=t.resetBeforeIteration,c=void 0===s||s,f=!1,v=0;return{start:function(t){n&&0!==u?n._isUsingNativeDriver()?n._startNativeLoop(u):(function o(){var s=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{finished:!0};f||v===u||!1===s.finished?t&&t(s):(v++,c&&n.reset(),n.start(o))})():t&&t({finished:!0})},stop:function(){f=!0,n.stop()},reset:function(){v=0,f=!1,n.reset()},_startNativeLoop:function(){throw new Error('Loops run using the native driver cannot contain Animated.loop animations')},_isUsingNativeDriver:function(){return n._isUsingNativeDriver()}}},event:function(n,t){var u=new o(n,t);return u.__isNative?u:u.__getHandler()},createAnimatedComponent:U,attachNativeEvent:u,forkEvent:function(n,t){return n?n instanceof o?(n.__addListener(t),n):function(){'function'==typeof n&&n.apply(void 0,arguments),t.apply(void 0,arguments)}:t},unforkEvent:function(n,t){n&&n instanceof o&&n.__removeListener(t)},Event:o,__PropsOnlyForTests:_}},227,[53,218,228,229,230,220,231,232,221,233,236,237,219,238,239,241,243,246]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),_=r(d[1]),n=r(d[2]),h=r(d[3]),u=r(d[4]),s=r(d[5]),o=r(d[6]),l=(r(d[7]),r(d[8])),v=r(d[9]),c=(function(c){function f(_,u){var s;return t(this,f),(s=n(this,h(f).call(this)))._a='number'==typeof _?new l(_):_,s._b='number'==typeof u?new l(u):u,s}return s(f,v),_(f,[{key:"__makeNative",value:function(){this._a.__makeNative(),this._b.__makeNative(),u(h(f.prototype),"__makeNative",this).call(this)}},{key:"__getValue",value:function(){return this._a.__getValue()+this._b.__getValue()}},{key:"interpolate",value:function(t){return new o(this,t)}},{key:"__attach",value:function(){this._a.__addChild(this),this._b.__addChild(this)}},{key:"__detach",value:function(){this._a.__removeChild(this),this._b.__removeChild(this),u(h(f.prototype),"__detach",this).call(this)}},{key:"__getNativeConfig",value:function(){return{type:'addition',input:[this._a.__getNativeTag(),this._b.__getNativeTag()]}}}]),f})();m.exports=c},228,[4,5,6,9,46,10,220,221,219,224]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),_=r(d[1]),n=r(d[2]),u=r(d[3]),h=r(d[4]),s=r(d[5]),l=r(d[6]),v=(r(d[7]),r(d[8])),c=(function(c){function o(_,h,s){var l;return t(this,o),(l=n(this,u(o).call(this)))._a=_,l._min=h,l._max=s,l._value=l._lastValue=l._a.__getValue(),l}return s(o,v),_(o,[{key:"__makeNative",value:function(){this._a.__makeNative(),h(u(o.prototype),"__makeNative",this).call(this)}},{key:"interpolate",value:function(t){return new l(this,t)}},{key:"__getValue",value:function(){var t=this._a.__getValue(),_=t-this._lastValue;return this._lastValue=t,this._value=Math.min(Math.max(this._value+_,this._min),this._max),this._value}},{key:"__attach",value:function(){this._a.__addChild(this)}},{key:"__detach",value:function(){this._a.__removeChild(this),h(u(o.prototype),"__detach",this).call(this)}},{key:"__getNativeConfig",value:function(){return{type:'diffclamp',input:this._a.__getNativeTag(),min:this._min,max:this._max}}}]),o})();m.exports=c},229,[4,5,6,9,46,10,220,221,224]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),_=r(d[1]),n=r(d[2]),h=r(d[3]),s=r(d[4]),o=r(d[5]),u=r(d[6]),l=(r(d[7]),r(d[8])),v=r(d[9]),c=(function(c){function f(_,s){var o;return t(this,f),(o=n(this,h(f).call(this)))._a='number'==typeof _?new l(_):_,o._b='number'==typeof s?new l(s):s,o}return o(f,v),_(f,[{key:"__makeNative",value:function(){this._a.__makeNative(),this._b.__makeNative(),s(h(f.prototype),"__makeNative",this).call(this)}},{key:"__getValue",value:function(){var t=this._a.__getValue(),_=this._b.__getValue();return 0===_&&console.error('Detected division by zero in AnimatedDivision'),t/_}},{key:"interpolate",value:function(t){return new u(this,t)}},{key:"__attach",value:function(){this._a.__addChild(this),this._b.__addChild(this)}},{key:"__detach",value:function(){this._a.__removeChild(this),this._b.__removeChild(this),s(h(f.prototype),"__detach",this).call(this)}},{key:"__getNativeConfig",value:function(){return{type:'division',input:[this._a.__getNativeTag(),this._b.__getNativeTag()]}}}]),f})();m.exports=c},230,[4,5,6,9,46,10,220,221,219,224]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),u=r(d[1]),_=r(d[2]),s=r(d[3]),n=r(d[4]),h=r(d[5]),l=r(d[6]),o=(r(d[7]),r(d[8])),c=(function(c){function v(u,n){var h;return t(this,v),(h=_(this,s(v).call(this)))._a=u,h._modulus=n,h}return h(v,o),u(v,[{key:"__makeNative",value:function(){this._a.__makeNative(),n(s(v.prototype),"__makeNative",this).call(this)}},{key:"__getValue",value:function(){return(this._a.__getValue()%this._modulus+this._modulus)%this._modulus}},{key:"interpolate",value:function(t){return new l(this,t)}},{key:"__attach",value:function(){this._a.__addChild(this)}},{key:"__detach",value:function(){this._a.__removeChild(this),n(s(v.prototype),"__detach",this).call(this)}},{key:"__getNativeConfig",value:function(){return{type:'modulus',input:this._a.__getNativeTag(),modulus:this._modulus}}}]),v})();m.exports=c},231,[4,5,6,9,46,10,220,221,224]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),_=r(d[1]),n=r(d[2]),h=r(d[3]),u=r(d[4]),s=r(d[5]),l=r(d[6]),o=(r(d[7]),r(d[8])),c=r(d[9]),v=(function(v){function f(_,u){var s;return t(this,f),(s=n(this,h(f).call(this)))._a='number'==typeof _?new o(_):_,s._b='number'==typeof u?new o(u):u,s}return s(f,c),_(f,[{key:"__makeNative",value:function(){this._a.__makeNative(),this._b.__makeNative(),u(h(f.prototype),"__makeNative",this).call(this)}},{key:"__getValue",value:function(){return this._a.__getValue()*this._b.__getValue()}},{key:"interpolate",value:function(t){return new l(this,t)}},{key:"__attach",value:function(){this._a.__addChild(this),this._b.__addChild(this)}},{key:"__detach",value:function(){this._a.__removeChild(this),this._b.__removeChild(this),u(h(f.prototype),"__detach",this).call(this)}},{key:"__getNativeConfig",value:function(){return{type:'multiplication',input:[this._a.__getNativeTag(),this._b.__getNativeTag()]}}}]),f})();m.exports=v},232,[4,5,6,9,46,10,220,221,219,224]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=r(d[1]),_=r(d[2]),s=r(d[3]),o=r(d[4]),c=r(d[5]),v=r(d[6]),h=r(d[7]).AnimatedEvent,l=r(d[8]),p=r(d[9]),u=r(d[10]),f=r(d[11]),N=r(d[12]),V=(function(V){function k(_,c){var v;return n(this,k),v=s(this,o(k).call(this)),_.style&&(_=t({},_,{style:new p(_.style)})),v._props=_,v._callback=c,v.__attach(),v}return v(k,l),_(k,[{key:"__getValue",value:function(){var t={};for(var n in this._props){var _=this._props[n];_ instanceof l?(!_.__isNative||_ instanceof p)&&(t[n]=_.__getValue()):t[n]=_ instanceof h?_.__getHandler():_}return t}},{key:"__getAnimatedValue",value:function(){var t={};for(var n in this._props){var _=this._props[n];_ instanceof l&&(t[n]=_.__getAnimatedValue())}return t}},{key:"__attach",value:function(){for(var t in this._props){var n=this._props[t];n instanceof l&&n.__addChild(this)}}},{key:"__detach",value:function(){for(var t in this.__isNative&&this._animatedView&&this.__disconnectAnimatedView(),this._props){var n=this._props[t];n instanceof l&&n.__removeChild(this)}c(o(k.prototype),"__detach",this).call(this)}},{key:"update",value:function(){this._callback()}},{key:"__makeNative",value:function(){if(!this.__isNative){for(var t in this.__isNative=!0,this._props){var n=this._props[t];n instanceof l&&n.__makeNative()}this._animatedView&&this.__connectAnimatedView()}}},{key:"setNativeView",value:function(t){this._animatedView!==t&&(this._animatedView=t,this.__isNative&&this.__connectAnimatedView())}},{key:"__connectAnimatedView",value:function(){N(this.__isNative,'Expected node to be marked as "native"');var t=f.findNodeHandle(this._animatedView);N(null!=t,'Unable to locate attached view in the native tree'),u.API.connectAnimatedNodeToView(this.__getNativeTag(),t)}},{key:"__disconnectAnimatedView",value:function(){N(this.__isNative,'Expected node to be marked as "native"');var t=f.findNodeHandle(this._animatedView);N(null!=t,'Unable to locate attached view in the native tree'),u.API.disconnectAnimatedNodeFromView(this.__getNativeTag(),t)}},{key:"__getNativeConfig",value:function(){var t={};for(var n in this._props){var _=this._props[n];_ instanceof l&&(_.__makeNative(),t[n]=_.__getNativeTag())}return{type:'props',props:t}}}]),k})();m.exports=V},233,[53,4,5,6,9,46,10,218,221,234,222,92,16]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=r(d[1]),s=r(d[2]),l=r(d[3]),_=r(d[4]),y=r(d[5]),o=r(d[6]),u=r(d[7]),v=r(d[8]),f=r(d[9]),h=r(d[10]),c=r(d[11]),k=(function(k){function A(s){var y;return n(this,A),y=l(this,_(A).call(this)),(s=c(s)||{}).transform&&(s=t({},s,{transform:new v(s.transform)})),y._style=s,y}return o(A,f),s(A,[{key:"_walkStyleAndGetValues",value:function(t){var n={};for(var s in t){var l=t[s];l instanceof u?l.__isNative||(n[s]=l.__getValue()):l&&!Array.isArray(l)&&'object'==typeof l?n[s]=this._walkStyleAndGetValues(l):n[s]=l}return n}},{key:"__getValue",value:function(){return this._walkStyleAndGetValues(this._style)}},{key:"_walkStyleAndGetAnimatedValues",value:function(t){var n={};for(var s in t){var l=t[s];l instanceof u?n[s]=l.__getAnimatedValue():l&&!Array.isArray(l)&&'object'==typeof l&&(n[s]=this._walkStyleAndGetAnimatedValues(l))}return n}},{key:"__getAnimatedValue",value:function(){return this._walkStyleAndGetAnimatedValues(this._style)}},{key:"__attach",value:function(){for(var t in this._style){var n=this._style[t];n instanceof u&&n.__addChild(this)}}},{key:"__detach",value:function(){for(var t in this._style){var n=this._style[t];n instanceof u&&n.__removeChild(this)}y(_(A.prototype),"__detach",this).call(this)}},{key:"__makeNative",value:function(){for(var t in this._style){var n=this._style[t];n instanceof u&&n.__makeNative()}y(_(A.prototype),"__makeNative",this).call(this)}},{key:"__getNativeConfig",value:function(){var t={};for(var n in this._style)if(this._style[n]instanceof u){var s=this._style[n];s.__makeNative(),t[n]=s.__getNativeTag()}return h.validateStyles(t),{type:'style',style:t}}}]),A})();m.exports=k},234,[53,4,5,6,9,46,10,221,235,224,222,89]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=r(d[1]),o=r(d[2]),s=r(d[3]),f=r(d[4]),_=r(d[5]),u=r(d[6]),c=r(d[7]),v=r(d[8]),h=(function(h){function l(n){var f;return t(this,l),(f=o(this,s(l).call(this)))._transforms=n,f}return _(l,c),n(l,[{key:"__makeNative",value:function(){this._transforms.forEach(function(t){for(var n in t){var o=t[n];o instanceof u&&o.__makeNative()}}),f(s(l.prototype),"__makeNative",this).call(this)}},{key:"__getValue",value:function(){return this._transforms.map(function(t){var n={};for(var o in t){var s=t[o];n[o]=s instanceof u?s.__getValue():s}return n})}},{key:"__getAnimatedValue",value:function(){return this._transforms.map(function(t){var n={};for(var o in t){var s=t[o];n[o]=s instanceof u?s.__getAnimatedValue():s}return n})}},{key:"__attach",value:function(){var t=this;this._transforms.forEach(function(n){for(var o in n){var s=n[o];s instanceof u&&s.__addChild(t)}})}},{key:"__detach",value:function(){var t=this;this._transforms.forEach(function(n){for(var o in n){var s=n[o];s instanceof u&&s.__removeChild(t)}}),f(s(l.prototype),"__detach",this).call(this)}},{key:"__getNativeConfig",value:function(){var t=[];return this._transforms.forEach(function(n){for(var o in n){var s=n[o];s instanceof u?t.push({type:'animated',property:o,nodeTag:s.__getNativeTag()}):t.push({type:'static',property:o,value:v.transformDataType(s)})}}),v.validateTransform(t),{type:'transform',transforms:t}}}]),l})();m.exports=h},235,[4,5,6,9,46,10,221,224,222]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),_=r(d[1]),n=r(d[2]),h=r(d[3]),u=r(d[4]),s=r(d[5]),o=r(d[6]),l=(r(d[7]),r(d[8])),c=r(d[9]),v=(function(v){function f(_,u){var s;return t(this,f),(s=n(this,h(f).call(this)))._a='number'==typeof _?new l(_):_,s._b='number'==typeof u?new l(u):u,s}return s(f,c),_(f,[{key:"__makeNative",value:function(){this._a.__makeNative(),this._b.__makeNative(),u(h(f.prototype),"__makeNative",this).call(this)}},{key:"__getValue",value:function(){return this._a.__getValue()-this._b.__getValue()}},{key:"interpolate",value:function(t){return new o(this,t)}},{key:"__attach",value:function(){this._a.__addChild(this),this._b.__addChild(this)}},{key:"__detach",value:function(){this._a.__removeChild(this),this._b.__removeChild(this),u(h(f.prototype),"__detach",this).call(this)}},{key:"__getNativeConfig",value:function(){return{type:'subtraction',input:[this._a.__getNativeTag(),this._b.__getNativeTag()]}}}]),f})();m.exports=v},236,[4,5,6,9,46,10,220,221,219,224]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=r(d[1]),_=r(d[2]),s=r(d[3]),o=r(d[4]),u=r(d[5]),l=r(d[6]),h=(r(d[7]),r(d[8])),v=r(d[9]),c=v.generateNewAnimationId,f=v.shouldUseNativeDriver,k=(function(v){function k(t,_,u,l,h){var v;return n(this,k),(v=s(this,o(k).call(this)))._value=t,v._parent=_,v._animationClass=u,v._animationConfig=l,v._useNativeDriver=f(l),v._callback=h,v.__attach(),v}return l(k,h),_(k,[{key:"__makeNative",value:function(){this.__isNative=!0,this._parent.__makeNative(),u(o(k.prototype),"__makeNative",this).call(this),this._value.__makeNative()}},{key:"__getValue",value:function(){return this._parent.__getValue()}},{key:"__attach",value:function(){this._parent.__addChild(this),this._useNativeDriver&&this.__makeNative()}},{key:"__detach",value:function(){this._parent.__removeChild(this),u(o(k.prototype),"__detach",this).call(this)}},{key:"update",value:function(){this._value.animate(new this._animationClass(t({},this._animationConfig,{toValue:this._animationConfig.toValue.__getValue()})),this._callback)}},{key:"__getNativeConfig",value:function(){var n=new this._animationClass(t({},this._animationConfig,{toValue:void 0})).__getNativeAnimationConfig();return{type:'tracking',animationId:c(),animationConfig:n,toValue:this._parent.__getNativeTag(),value:this._value.__getNativeTag()}}}]),k})();m.exports=k},237,[53,4,5,6,9,46,10,219,221,222]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),s=r(d[1]),n=r(d[2]),u=r(d[3]),l=r(d[4]),f=r(d[5]),o=r(d[6]),y=r(d[7]),h=1,x=(function(x){function c(s){var l;t(this,c),l=n(this,u(c).call(this));var o=s||{x:0,y:0};return'number'==typeof o.x&&'number'==typeof o.y?(l.x=new f(o.x),l.y=new f(o.y)):(y(o.x instanceof f&&o.y instanceof f,"AnimatedValueXY must be initialized with an object of numbers or AnimatedValues."),l.x=o.x,l.y=o.y),l._listeners={},l}return l(c,o),s(c,[{key:"setValue",value:function(t){this.x.setValue(t.x),this.y.setValue(t.y)}},{key:"setOffset",value:function(t){this.x.setOffset(t.x),this.y.setOffset(t.y)}},{key:"flattenOffset",value:function(){this.x.flattenOffset(),this.y.flattenOffset()}},{key:"extractOffset",value:function(){this.x.extractOffset(),this.y.extractOffset()}},{key:"__getValue",value:function(){return{x:this.x.__getValue(),y:this.y.__getValue()}}},{key:"resetAnimation",value:function(t){this.x.resetAnimation(),this.y.resetAnimation(),t&&t(this.__getValue())}},{key:"stopAnimation",value:function(t){this.x.stopAnimation(),this.y.stopAnimation(),t&&t(this.__getValue())}},{key:"addListener",value:function(t){var s=this,n=String(h++),u=function(n){n.value;t(s.__getValue())};return this._listeners[n]={x:this.x.addListener(u),y:this.y.addListener(u)},n}},{key:"removeListener",value:function(t){this.x.removeListener(this._listeners[t].x),this.y.removeListener(this._listeners[t].y),delete this._listeners[t]}},{key:"removeAllListeners",value:function(){this.x.removeAllListeners(),this.y.removeAllListeners(),this._listeners={}}},{key:"getLayout",value:function(){return{left:this.x,top:this.y}}},{key:"getTranslateTransform",value:function(){return[{translateX:this.x},{translateY:this.y}]}}]),c})();m.exports=x},238,[4,5,6,9,10,219,224,16]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=r(d[1]),s=r(d[2]),o=r(d[3]),_=r(d[4]),h=r(d[5]),l=r(d[6]),c=r(d[7]).shouldUseNativeDriver,u=(function(u){function v(n){var _,h,l,u;return t(this,v),(u=s(this,o(v).call(this)))._deceleration=null!=(_=n.deceleration)?_:.998,u._velocity=n.velocity,u._useNativeDriver=c(n),u.__isInteraction=null!=(h=n.isInteraction)?h:!u._useNativeDriver,u.__iterations=null!=(l=n.iterations)?l:1,u}return h(v,l),n(v,[{key:"__getNativeAnimationConfig",value:function(){return{type:'decay',deceleration:this._deceleration,velocity:this._velocity,iterations:this.__iterations}}},{key:"start",value:function(t,n,s,o,_){this.__active=!0,this._lastValue=t,this._fromValue=t,this._onUpdate=n,this.__onEnd=s,this._startTime=Date.now(),this._useNativeDriver?this.__startNativeAnimation(_):this._animationFrame=requestAnimationFrame(this.onUpdate.bind(this))}},{key:"onUpdate",value:function(){var t=Date.now(),n=this._fromValue+this._velocity/(1-this._deceleration)*(1-Math.exp(-(1-this._deceleration)*(t-this._startTime)));this._onUpdate(n),Math.abs(this._lastValue-n)<.1?this.__debouncedOnEnd({finished:!0}):(this._lastValue=n,this.__active&&(this._animationFrame=requestAnimationFrame(this.onUpdate.bind(this))))}},{key:"stop",value:function(){_(o(v.prototype),"stop",this).call(this),this.__active=!1,g.cancelAnimationFrame(this._animationFrame),this.__debouncedOnEnd({finished:!1})}}]),v})();m.exports=u},239,[4,5,6,9,46,10,240,222]); -__d(function(g,r,i,a,m,e,d){'use strict';var n=r(d[0]),t=r(d[1]),o=r(d[2]),_=(function(){function _(){n(this,_)}return t(_,[{key:"start",value:function(n,t,o,_,u){}},{key:"stop",value:function(){this.__nativeId&&o.API.stopAnimation(this.__nativeId)}},{key:"__getNativeAnimationConfig",value:function(){throw new Error('This animation type cannot be offloaded to native')}},{key:"__debouncedOnEnd",value:function(n){var t=this.__onEnd;this.__onEnd=null,t&&t(n)}},{key:"__startNativeAnimation",value:function(n){o.API.enableQueue(),n.__makeNative(),o.API.disableQueue(),this.__nativeId=o.generateNewAnimationId(),o.API.startAnimatingNode(this.__nativeId,n.__getNativeTag(),this.__getNativeAnimationConfig(),this.__debouncedOnEnd.bind(this))}}]),_})();m.exports=_},240,[4,5,222]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),s=r(d[1]),n=r(d[2]),o=r(d[3]),l=r(d[4]),h=r(d[5]),_=(r(d[6]),r(d[7]),r(d[8])),u=r(d[9]),f=r(d[10]),c=r(d[11]).shouldUseNativeDriver,v=(function(v){function p(s){var l,h,_,v,y,V,T,b,M,D,P,S;if(t(this,p),(M=n(this,o(p).call(this)))._overshootClamping=null!=(l=s.overshootClamping)&&l,M._restDisplacementThreshold=null!=(h=s.restDisplacementThreshold)?h:.001,M._restSpeedThreshold=null!=(_=s.restSpeedThreshold)?_:.001,M._initialVelocity=null!=(v=s.velocity)?v:0,M._lastVelocity=null!=(y=s.velocity)?y:0,M._toValue=s.toValue,M._delay=null!=(V=s.delay)?V:0,M._useNativeDriver=c(s),M.__isInteraction=null!=(T=s.isInteraction)?T:!M._useNativeDriver,M.__iterations=null!=(b=s.iterations)?b:1,void 0!==s.stiffness||void 0!==s.damping||void 0!==s.mass)f(void 0===s.bounciness&&void 0===s.speed&&void 0===s.tension&&void 0===s.friction,'You can define one of bounciness/speed, tension/friction, or stiffness/damping/mass, but not more than one'),M._stiffness=null!=(D=s.stiffness)?D:100,M._damping=null!=(P=s.damping)?P:10,M._mass=null!=(S=s.mass)?S:1;else if(void 0!==s.bounciness||void 0!==s.speed){var U,A;f(void 0===s.tension&&void 0===s.friction&&void 0===s.stiffness&&void 0===s.damping&&void 0===s.mass,'You can define one of bounciness/speed, tension/friction, or stiffness/damping/mass, but not more than one');var C=u.fromBouncinessAndSpeed(null!=(U=s.bounciness)?U:8,null!=(A=s.speed)?A:12);M._stiffness=C.stiffness,M._damping=C.damping,M._mass=1}else{var N,k,F=u.fromOrigamiTensionAndFriction(null!=(N=s.tension)?N:40,null!=(k=s.friction)?k:7);M._stiffness=F.stiffness,M._damping=F.damping,M._mass=1}return f(M._stiffness>0,'Stiffness value must be greater than 0'),f(M._damping>0,'Damping value must be greater than 0'),f(M._mass>0,'Mass value must be greater than 0'),M}return h(p,_),s(p,[{key:"__getNativeAnimationConfig",value:function(){var t;return{type:'spring',overshootClamping:this._overshootClamping,restDisplacementThreshold:this._restDisplacementThreshold,restSpeedThreshold:this._restSpeedThreshold,stiffness:this._stiffness,damping:this._damping,mass:this._mass,initialVelocity:null!=(t=this._initialVelocity)?t:this._lastVelocity,toValue:this._toValue,iterations:this.__iterations}}},{key:"start",value:function(t,s,n,o,l){var h=this;if(this.__active=!0,this._startPosition=t,this._lastPosition=this._startPosition,this._onUpdate=s,this.__onEnd=n,this._lastTime=Date.now(),this._frameTime=0,o instanceof p){var _=o.getInternalState();this._lastPosition=_.lastPosition,this._lastVelocity=_.lastVelocity,this._initialVelocity=this._lastVelocity,this._lastTime=_.lastTime}var u=function(){h._useNativeDriver?h.__startNativeAnimation(l):h.onUpdate()};this._delay?this._timeout=setTimeout(u,this._delay):u()}},{key:"getInternalState",value:function(){return{lastPosition:this._lastPosition,lastVelocity:this._lastVelocity,lastTime:this._lastTime}}},{key:"onUpdate",value:function(){var t=Date.now();t>this._lastTime+64&&(t=this._lastTime+64);var s=(t-this._lastTime)/1e3;this._frameTime+=s;var n=this._damping,o=this._mass,l=this._stiffness,h=-this._initialVelocity,_=n/(2*Math.sqrt(l*o)),u=Math.sqrt(l/o),f=u*Math.sqrt(1-_*_),c=this._toValue-this._startPosition,v=0,p=0,y=this._frameTime;if(_<1){var V=Math.exp(-_*u*y);v=this._toValue-V*((h+_*u*c)/f*Math.sin(f*y)+c*Math.cos(f*y)),p=_*u*V*(Math.sin(f*y)*(h+_*u*c)/f+c*Math.cos(f*y))-V*(Math.cos(f*y)*(h+_*u*c)-f*c*Math.sin(f*y))}else{var T=Math.exp(-u*y);v=this._toValue-T*(c+(h+u*c)*y),p=T*(h*(y*u-1)+y*c*(u*u))}if(this._lastTime=t,this._lastPosition=v,this._lastVelocity=p,this._onUpdate(v),this.__active){var b=!1;this._overshootClamping&&0!==this._stiffness&&(b=this._startPositionthis._toValue:v18&&A<=44?p(A):h(A),s(2*M-M*M,v,.01));return{stiffness:n(x),damping:t(B)}}}},242,[]); -__d(function(g,r,i,a,m,e,d){'use strict';var t,n=r(d[0]),s=r(d[1]),o=r(d[2]),_=r(d[3]),u=r(d[4]),h=r(d[5]),l=(r(d[6]),r(d[7]),r(d[8])),v=r(d[9]).shouldUseNativeDriver;function c(){if(!t){var n=r(d[10]);t=n.inOut(n.ease)}return t}var f=(function(t){function f(t){var s,u,h,l,p,V;return n(this,f),(V=o(this,_(f).call(this)))._toValue=t.toValue,V._easing=null!=(s=t.easing)?s:c(),V._duration=null!=(u=t.duration)?u:500,V._delay=null!=(h=t.delay)?h:0,V.__iterations=null!=(l=t.iterations)?l:1,V._useNativeDriver=v(t),V.__isInteraction=null!=(p=t.isInteraction)?p:!V._useNativeDriver,V}return h(f,l),s(f,[{key:"__getNativeAnimationConfig",value:function(){for(var t=[],n=Math.round(this._duration/16.666666666666668),s=0;s=this._startTime+this._duration)return 0===this._duration?this._onUpdate(this._toValue):this._onUpdate(this._fromValue+this._easing(1)*(this._toValue-this._fromValue)),void this.__debouncedOnEnd({finished:!0});this._onUpdate(this._fromValue+this._easing((t-this._startTime)/this._duration)*(this._toValue-this._fromValue)),this.__active&&(this._animationFrame=requestAnimationFrame(this.onUpdate.bind(this)))}},{key:"stop",value:function(){u(_(f.prototype),"stop",this).call(this),this.__active=!1,clearTimeout(this._timeout),g.cancelAnimationFrame(this._animationFrame),this.__debouncedOnEnd({finished:!1})}}]),f})();m.exports=f},243,[4,5,6,9,46,10,219,238,240,222,244]); -__d(function(g,r,i,a,m,e,d){'use strict';var n,u=r(d[0]),t=r(d[1]),o=(function(){function o(){u(this,o)}return t(o,null,[{key:"step0",value:function(n){return n>0?1:0}},{key:"step1",value:function(n){return n>=1?1:0}},{key:"linear",value:function(n){return n}},{key:"ease",value:function(u){return n||(n=o.bezier(.42,0,1,1)),n(u)}},{key:"quad",value:function(n){return n*n}},{key:"cubic",value:function(n){return n*n*n}},{key:"poly",value:function(n){return function(u){return Math.pow(u,n)}}},{key:"sin",value:function(n){return 1-Math.cos(n*Math.PI/2)}},{key:"circle",value:function(n){return 1-Math.sqrt(1-n*n)}},{key:"exp",value:function(n){return Math.pow(2,10*(n-1))}},{key:"elastic",value:function(){var n=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:1)*Math.PI;return function(u){return 1-Math.pow(Math.cos(u*Math.PI/2),3)*Math.cos(u*n)}}},{key:"back",value:function(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1.70158;return function(u){return u*u*((n+1)*u-n)}}},{key:"bounce",value:function(n){if(n<.36363636363636365)return 7.5625*n*n;if(n<.7272727272727273){var u=n-.5454545454545454;return 7.5625*u*u+.75}if(n<.9090909090909091){var t=n-.8181818181818182;return 7.5625*t*t+.9375}var o=n-.9545454545454546;return 7.5625*o*o+.984375}},{key:"bezier",value:function(n,u,t,o){return r(d[2])(n,u,t,o)}},{key:"in",value:function(n){return n}},{key:"out",value:function(n){return function(u){return 1-n(1-u)}}},{key:"inOut",value:function(n){return function(u){return u<.5?n(2*u)/2:1-n(2*(1-u))/2}}}]),o})();m.exports=o},244,[4,5,245]); -__d(function(g,r,i,a,m,e,d){'use strict';var n=4,t=.001,u=1e-7,o=10,f=.1,c='function'==typeof Float32Array;function v(n,t){return 1-3*t+3*n}function s(n,t){return 3*t-6*n}function w(n){return 3*n}function l(n,t,u){return((v(t,u)*n+s(t,u))*n+w(t))*n}function y(n,t,u){return 3*v(t,u)*n*n+2*s(t,u)*n+w(t)}function b(n,t,f,c,v){var s,w,y=0,b=t,h=f;do{(s=l(w=b+(h-b)/2,c,v)-n)>0?h=w:b=w}while(Math.abs(s)>u&&++y=0&&n<=1&&o>=0&&o<=1))throw new Error('bezier x values must be in [0, 1] range');var s=c?new Float32Array(11):new Array(11);if(n!==u||o!==v)for(var w=0;w<11;++w)s[w]=l(w*f,n,o);function A(u){for(var c=0,v=1;10!==v&&s[v]<=u;++v)c+=f;var w=c+(u-s[--v])/(s[v+1]-s[v])*f,l=y(w,n,o);return l>=t?h(u,w,n,o):0===l?w:b(u,c,c+f,n,o)}return function(t){return n===u&&o===v?t:0===t?0:1===t?1:l(A(t),u,v)}}},245,[]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=r(d[1]),o=r(d[2]),s=r(d[3]),p=r(d[4]),c=r(d[5]),_=r(d[6]).AnimatedEvent,h=r(d[7]),l=r(d[8]),v=r(d[9]),u=r(d[10]);m.exports=function(f,N){u('function'!=typeof f||f.prototype&&f.prototype.isReactComponent,"`createAnimatedComponent` does not support stateless functional components; use a class component instead.");var k=(function(v){function u(t){var o;return n(this,u),(o=s(this,p(u).call(this,t)))._invokeAnimatedPropsCallbackOnMount=!1,o._eventDetachers=[],o._animatedPropsCallback=function(){if(null==o._component)o._invokeAnimatedPropsCallbackOnMount=!0;else if(u.__skipSetNativeProps_FOR_TESTS_ONLY||'function'!=typeof o._component.setNativeProps)o.forceUpdate();else{if(o._propsAnimated.__isNative)throw new Error("Attempting to run JS driven animation on animated node that has been moved to \"native\" earlier by starting an animation with `useNativeDriver: true`");o._component.setNativeProps(o._propsAnimated.__getAnimatedValue())}},o._setComponentRef=function(t){o._prevComponent=o._component,o._component=t},o}return c(u,v),o(u,[{key:"componentWillUnmount",value:function(){this._propsAnimated&&this._propsAnimated.__detach(),this._detachNativeEvents()}},{key:"setNativeProps",value:function(t){this._component.setNativeProps(t)}},{key:"UNSAFE_componentWillMount",value:function(){this._attachProps(this.props)}},{key:"componentDidMount",value:function(){this._invokeAnimatedPropsCallbackOnMount&&(this._invokeAnimatedPropsCallbackOnMount=!1,this._animatedPropsCallback()),this._propsAnimated.setNativeView(this._component),this._attachNativeEvents()}},{key:"_attachNativeEvents",value:function(){var t,n=this,o=(null==(t=this._component)?void 0:t.getScrollableNode)?this._component.getScrollableNode():this._component,s=function(t){var s=n.props[t];s instanceof _&&s.__isNative&&(s.__attach(o,t),n._eventDetachers.push(function(){return s.__detach(o,t)}))};for(var p in this.props)s(p)}},{key:"_detachNativeEvents",value:function(){this._eventDetachers.forEach(function(t){return t()}),this._eventDetachers=[]}},{key:"_attachProps",value:function(t){var n=this._propsAnimated;this._propsAnimated=new h(t,this._animatedPropsCallback),n&&n.__detach()}},{key:"UNSAFE_componentWillReceiveProps",value:function(t){this._attachProps(t)}},{key:"componentDidUpdate",value:function(t){this._component!==this._prevComponent&&this._propsAnimated.setNativeView(this._component),this._component===this._prevComponent&&t===this.props||(this._detachNativeEvents(),this._attachNativeEvents())}},{key:"render",value:function(){var n=this._propsAnimated.__getValue();return l.createElement(f,t({},N,n,{ref:this._setComponentRef,collapsable:!this._propsAnimated.__isNative&&n.collapsable}))}},{key:"getNode",value:function(){return this._component}}]),u})(l.Component);k.__skipSetNativeProps_FOR_TESTS_ONLY=!1;var y=f.propTypes;return k.propTypes={style:function(t,n,o){if(y)for(var s in v)y[s]||void 0===t[s]||console.warn('You are setting the style `{ '+s+": ... }` as a prop. You should nest it in a style object. E.g. `{ style: { "+s+': ... } }`')}},k}},246,[24,4,5,6,9,10,218,233,59,83,16]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),o=r(d[1]);m.exports=o(t,{scrollEventThrottle:1e-4})},247,[248,246]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=r(d[1]),o=r(d[2]),s=r(d[3]),l=r(d[4]),u=r(d[5]),c=r(d[6]),f=r(d[7]),p=(r(d[8]),r(d[9])),h=r(d[10]),C=r(d[11]),v=r(d[12]),y=r(d[13]),b=r(d[14]),_=f({},v.defaultProps,{numColumns:1,removeClippedSubviews:!1}),w=(function(_){function w(t){var u;return o(this,w),(u=s(this,l(w).call(this,t)))._virtualizedListPairs=[],u._captureRef=function(t){u._listRef=t},u._getItem=function(t,n){var o=u.props.numColumns;if(o>1){for(var s=[],l=0;l1?(b(Array.isArray(t),"FlatList: Encountered internal consistency error, expected each item to consist of an array with 1-%s columns; instead, received a single item.",l),t.map(function(t,o){return s(t,n*l+o)}).join(':')):s(t,n)},u._renderer=function(){var t=u.props,o=t.ListItemComponent,s=t.renderItem,l=t.numColumns,c=t.columnWrapperStyle,f=function(t){return o?h.createElement(o,t):s?s(t):null};return n({},o?'ListItemComponent':'renderItem',function(t){if(l>1){var n=t.item,o=t.index;return b(Array.isArray(n),'Expected array of items with numColumns > 1'),h.createElement(C,{style:y.compose(I.row,c)},n.map(function(n,s){var u=f({item:n,index:o*l+s,separators:t.separators});return null!=u?h.createElement(h.Fragment,{key:s},u):null}))}return f(t)})},u._checkProps(u.props),u.props.viewabilityConfigCallbackPairs?u._virtualizedListPairs=u.props.viewabilityConfigCallbackPairs.map(function(t){return{viewabilityConfig:t.viewabilityConfig,onViewableItemsChanged:u._createOnViewableItemsChanged(t.onViewableItemsChanged)}}):u.props.onViewableItemsChanged&&u._virtualizedListPairs.push({viewabilityConfig:u.props.viewabilityConfig,onViewableItemsChanged:u._createOnViewableItemsChanged(u.props.onViewableItemsChanged)}),u}return c(w,_),u(w,[{key:"scrollToEnd",value:function(t){this._listRef&&this._listRef.scrollToEnd(t)}},{key:"scrollToIndex",value:function(t){this._listRef&&this._listRef.scrollToIndex(t)}},{key:"scrollToItem",value:function(t){this._listRef&&this._listRef.scrollToItem(t)}},{key:"scrollToOffset",value:function(t){this._listRef&&this._listRef.scrollToOffset(t)}},{key:"recordInteraction",value:function(){this._listRef&&this._listRef.recordInteraction()}},{key:"flashScrollIndicators",value:function(){this._listRef&&this._listRef.flashScrollIndicators()}},{key:"getScrollResponder",value:function(){if(this._listRef)return this._listRef.getScrollResponder()}},{key:"getScrollableNode",value:function(){if(this._listRef)return this._listRef.getScrollableNode()}},{key:"setNativeProps",value:function(t){this._listRef&&this._listRef.setNativeProps(t)}}]),u(w,[{key:"componentDidUpdate",value:function(t){b(t.numColumns===this.props.numColumns,"Changing numColumns on the fly is not supported. Change the key prop on FlatList when changing the number of columns to force a fresh render of the component."),b(t.onViewableItemsChanged===this.props.onViewableItemsChanged,'Changing onViewableItemsChanged on the fly is not supported'),b(!p(t.viewabilityConfig,this.props.viewabilityConfig),'Changing viewabilityConfig on the fly is not supported'),b(t.viewabilityConfigCallbackPairs===this.props.viewabilityConfigCallbackPairs,'Changing viewabilityConfigCallbackPairs on the fly is not supported'),this._checkProps(this.props)}},{key:"_checkProps",value:function(t){var n=t.getItem,o=t.getItemCount,s=t.horizontal,l=t.numColumns,u=t.columnWrapperStyle,c=t.onViewableItemsChanged,f=t.viewabilityConfigCallbackPairs;b(!n&&!o,'FlatList does not support custom data formats.'),l>1?b(!s,'numColumns does not support horizontal.'):b(!u,'columnWrapperStyle not supported for single column lists'),b(!(c&&f),"FlatList does not support setting both onViewableItemsChanged and viewabilityConfigCallbackPairs.")}},{key:"_pushMultiColumnViewable",value:function(t,n){var o=this.props,s=o.numColumns,l=o.keyExtractor;n.item.forEach(function(o,u){b(null!=n.index,'Missing index!');var c=n.index*s+u;t.push(f({},n,{item:o,key:l(o,c),index:c}))})}},{key:"_createOnViewableItemsChanged",value:function(t){var n=this;return function(o){var s=n.props.numColumns;if(t)if(s>1){var l=[],u=[];o.viewableItems.forEach(function(t){return n._pushMultiColumnViewable(u,t)}),o.changed.forEach(function(t){return n._pushMultiColumnViewable(l,t)}),t({viewableItems:u,changed:l})}else t(o)}}},{key:"render",value:function(){return h.createElement(v,t({},this.props,{getItem:this._getItem,getItemCount:this._getItemCount,keyExtractor:this._keyExtractor,ref:this._captureRef,viewabilityConfigCallbackPairs:this._virtualizedListPairs},this._renderer()))}}]),w})(h.PureComponent);w.defaultProps=_;var I=y.create({row:{flexDirection:'row'}});m.exports=w},248,[24,54,4,6,9,5,10,53,57,166,59,90,249,62,16]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),s=r(d[1]),o=r(d[2]),n=r(d[3]),l=r(d[4]),h=r(d[5]),c=r(d[6]),p=r(d[7]),u=r(d[8]),f=r(d[9]),_=r(d[10]),v=r(d[11]),y=r(d[12]),C=r(d[13]),L=r(d[14]),S=r(d[15]),b=r(d[16]),M=r(d[17]),I=r(d[18]),x=(r(d[19]),r(d[20])),R=r(d[21]),k=(r(d[22]),r(d[23]).computeWindowedRenderLimits),E=!1,w='',T=(function(v){function T(t,c){var p;n(this,T),(p=l(this,h(T).call(this,t,c)))._getScrollMetrics=function(){return p._scrollMetrics},p._getOutermostParentListRef=function(){return p._isNestedWithSameOrientation()?p.context.virtualizedList.getOutermostParentListRef():u(u(p))},p._getNestedChildState=function(t){var s=p._nestedChildLists.get(t);return s&&s.state},p._registerAsNestedChild=function(t){var s=p._cellKeysToChildListKeys.get(t.cellKey)||new Set;s.add(t.key),p._cellKeysToChildListKeys.set(t.cellKey,s);var o=p._nestedChildLists.get(t.key);o&&null!==o.ref&&console.error("A VirtualizedList contains a cell which itself contains more than one VirtualizedList of the same orientation as the parent list. You must pass a unique listKey prop to each sibling list."),p._nestedChildLists.set(t.key,{ref:t.ref,state:null}),p._hasInteracted&&t.ref.recordInteraction()},p._unregisterAsNestedChild=function(t){p._nestedChildLists.set(t.key,{ref:null,state:t.state})},p._onUpdateSeparators=function(t,s){t.forEach(function(t){var o=null!=t&&p._cellRefs[t];o&&o.updateSeparatorProps(s)})},p._averageCellLength=0,p._cellKeysToChildListKeys=new Map,p._cellRefs={},p._frames={},p._footerLength=0,p._hasDataChangedSinceEndReached=!0,p._hasDoneInitialScroll=!1,p._hasInteracted=!1,p._hasMore=!1,p._hasWarned={},p._headerLength=0,p._hiPriInProgress=!1,p._highestMeasuredFrameIndex=0,p._indicesToKeys=new Map,p._nestedChildLists=new Map,p._offsetFromParentVirtualizedList=0,p._prevParentOffset=0,p._scrollMetrics={contentLength:0,dOffset:0,dt:10,offset:0,timestamp:0,velocity:0,visibleLength:0},p._scrollRef=null,p._sentEndForContentLength=0,p._totalCellLength=0,p._totalCellsMeasured=0,p._viewabilityTuples=[],p._captureScrollRef=function(t){p._scrollRef=t},p._defaultRenderScrollComponent=function(t){var o=t.onRefresh;return p._isNestedWithSameOrientation()?y.createElement(M,t):o?(R('boolean'==typeof t.refreshing,'`refreshing` prop must be set as a boolean in order to use `onRefresh`, but got `'+JSON.stringify(t.refreshing)+'`'),y.createElement(S,s({},t,{refreshControl:null==t.refreshControl?y.createElement(L,{refreshing:t.refreshing,onRefresh:o,progressViewOffset:t.progressViewOffset}):t.refreshControl}))):y.createElement(S,t)},p._onCellUnmount=function(t){var s=p._frames[t];s&&(p._frames[t]=o({},s,{inLayout:!1}))},p._onLayout=function(t){p._isNestedWithSameOrientation()?p.measureLayoutRelativeToContainingList():p._scrollMetrics.visibleLength=p._selectLength(t.nativeEvent.layout),p.props.onLayout&&p.props.onLayout(t),p._scheduleCellsToRenderUpdate(),p._maybeCallOnEndReached()},p._onLayoutEmpty=function(t){p.props.onLayout&&p.props.onLayout(t)},p._onLayoutFooter=function(t){p._footerLength=p._selectLength(t.nativeEvent.layout)},p._onLayoutHeader=function(t){p._headerLength=p._selectLength(t.nativeEvent.layout)},p._onContentSizeChange=function(t,s){t>0&&s>0&&null!=p.props.initialScrollIndex&&p.props.initialScrollIndex>0&&!p._hasDoneInitialScroll&&(p.scrollToIndex({animated:!1,index:p.props.initialScrollIndex}),p._hasDoneInitialScroll=!0),p.props.onContentSizeChange&&p.props.onContentSizeChange(t,s),p._scrollMetrics.contentLength=p._selectLength({height:s,width:t}),p._scheduleCellsToRenderUpdate(),p._maybeCallOnEndReached()},p._convertParentScrollMetrics=function(t){var s=t.offset-p._offsetFromParentVirtualizedList,o=t.visibleLength,n=s-p._scrollMetrics.offset;return{visibleLength:o,contentLength:p._scrollMetrics.contentLength,offset:s,dOffset:n}},p._onScroll=function(t){p._nestedChildLists.forEach(function(s){s.ref&&s.ref._onScroll(t)}),p.props.onScroll&&p.props.onScroll(t);var s=t.timeStamp,o=p._selectLength(t.nativeEvent.layoutMeasurement),n=p._selectLength(t.nativeEvent.contentSize),l=p._selectOffset(t.nativeEvent.contentOffset),h=l-p._scrollMetrics.offset;if(p._isNestedWithSameOrientation()){if(0===p._scrollMetrics.contentLength)return;var c=p._convertParentScrollMetrics({visibleLength:o,offset:l});o=c.visibleLength,n=c.contentLength,l=c.offset,h=c.dOffset}var u=p._scrollMetrics.timestamp?Math.max(1,s-p._scrollMetrics.timestamp):1,f=h/u;u>500&&p._scrollMetrics.dt>500&&n>5*o&&!p._hasWarned.perf&&(x("VirtualizedList: You have a large list that is slow to update - make sure your renderItem function renders components that follow React performance best practices like PureComponent, shouldComponentUpdate, etc.",{dt:u,prevDt:p._scrollMetrics.dt,contentLength:n}),p._hasWarned.perf=!0),p._scrollMetrics={contentLength:n,dt:u,dOffset:h,offset:l,timestamp:s,velocity:f,visibleLength:o},p._updateViewableItems(p.props.data),p.props&&(p._maybeCallOnEndReached(),0!==f&&p._fillRateHelper.activate(),p._computeBlankness(),p._scheduleCellsToRenderUpdate())},p._onScrollBeginDrag=function(t){p._nestedChildLists.forEach(function(s){s.ref&&s.ref._onScrollBeginDrag(t)}),p._viewabilityTuples.forEach(function(t){t.viewabilityHelper.recordInteraction()}),p._hasInteracted=!0,p.props.onScrollBeginDrag&&p.props.onScrollBeginDrag(t)},p._onScrollEndDrag=function(t){var s=t.nativeEvent.velocity;s&&(p._scrollMetrics.velocity=p._selectOffset(s)),p._computeBlankness(),p.props.onScrollEndDrag&&p.props.onScrollEndDrag(t)},p._onMomentumScrollEnd=function(t){p._scrollMetrics.velocity=0,p._computeBlankness(),p.props.onMomentumScrollEnd&&p.props.onMomentumScrollEnd(t)},p._updateCellsToRender=function(){var t=p.props,s=t.data,o=t.getItemCount,n=t.onEndReachedThreshold,l=p._isVirtualizationDisabled();p._updateViewableItems(s),s&&p.setState(function(t){var h;if(l){var c=p._scrollMetrics,u=c.contentLength,f=c.offset,_=c.visibleLength,v=u-_-f0)for(var y=h.first,C=h.last,L=y;L<=C;L++){var S=p._indicesToKeys.get(L),b=S&&p._cellKeysToChildListKeys.get(S);if(b){var M=!1,I=b,x=Array.isArray(I),R=0;for(I=x?I:I["function"==typeof Symbol&&"function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var E;if(x){if(R>=I.length)break;E=I[R++]}else{if((R=I.next()).done)break;E=R.value}var w=E,T=p._nestedChildLists.get(w);if(T&&T.ref&&T.ref.hasMore()){M=!0;break}}if(M){h.last=L;break}}}return h})},p._createViewToken=function(t,s){var o=p.props,n=o.data,l=o.getItem,h=o.keyExtractor,c=l(n,t);return{index:t,item:c,key:h(c,t),isViewable:s}},p._getFrameMetricsApprox=function(t){var s=p._getFrameMetrics(t);if(s&&s.index===t)return s;var o=p.props.getItemLayout;return R(!o,'Should not have to estimate frames when a measurement metrics function is provided'),{length:p._averageCellLength,offset:p._averageCellLength*t}},p._getFrameMetrics=function(t){var s=p.props,o=s.data,n=s.getItem,l=s.getItemCount,h=s.getItemLayout,c=s.keyExtractor;R(l(o)>t,'Tried to get frame for out of range index '+t);var u=n(o,t),f=u&&p._frames[c(u,t)];return f&&f.index===t||h&&(f=h(o,t)),f},R(!t.onScroll||!t.onScroll.__isNative,"Components based on VirtualizedList must be wrapped with Animated.createAnimatedComponent to support native onScroll events with useNativeDriver"),R(t.windowSize>0,'VirtualizedList: The windowSize prop must be present and set to a value greater than 0.'),p._fillRateHelper=new _(p._getFrameMetrics),p._updateCellsToRenderBatcher=new f(p._updateCellsToRender,p.props.updateCellsBatchingPeriod),p.props.viewabilityConfigCallbackPairs?p._viewabilityTuples=p.props.viewabilityConfigCallbackPairs.map(function(t){return{viewabilityHelper:new I(t.viewabilityConfig),onViewableItemsChanged:t.onViewableItemsChanged}}):p.props.onViewableItemsChanged&&p._viewabilityTuples.push({viewabilityHelper:new I(p.props.viewabilityConfig),onViewableItemsChanged:p.props.onViewableItemsChanged});var v={first:p.props.initialScrollIndex||0,last:Math.min(p.props.getItemCount(p.props.data),(p.props.initialScrollIndex||0)+p.props.initialNumToRender)-1};if(p._isNestedWithSameOrientation()){var C=p.context.virtualizedList.getNestedChildState(p.props.listKey||p._getCellKey());C&&(v=C,p.state=C,p._frames=C.frames)}return p.state=v,p}return p(T,v),c(T,[{key:"scrollToEnd",value:function(t){var s=!t||t.animated,o=this.props.getItemCount(this.props.data)-1,n=this._getFrameMetricsApprox(o),l=Math.max(0,n.offset+n.length+this._footerLength-this._scrollMetrics.visibleLength);this._scrollRef.scrollTo(this.props.horizontal?{x:l,animated:s}:{y:l,animated:s})}},{key:"scrollToIndex",value:function(t){var s=this.props,o=s.data,n=s.horizontal,l=s.getItemCount,h=s.getItemLayout,c=s.onScrollToIndexFailed,p=t.animated,u=t.index,f=t.viewOffset,_=t.viewPosition;if(R(u>=0&&uthis._highestMeasuredFrameIndex)return R(!!c,"scrollToIndex should be used in conjunction with getItemLayout or onScrollToIndexFailed, otherwise there is no way to know the location of offscreen indices or handle failures."),void c({averageItemLength:this._averageCellLength,highestMeasuredFrameIndex:this._highestMeasuredFrameIndex,index:u});var v=this._getFrameMetricsApprox(u),y=Math.max(0,v.offset-(_||0)*(this._scrollMetrics.visibleLength-v.length))-(f||0);this._scrollRef.scrollTo(n?{x:y,animated:p}:{y:y,animated:p})}},{key:"scrollToItem",value:function(t){for(var s=t.item,n=this.props,l=n.data,h=n.getItem,c=(0,n.getItemCount)(l),p=0;p0){E=!1,w='';var R=f?'width':'height',k=this.props.initialScrollIndex?-1:this.props.initialNumToRender-1,T=this.state,z=T.first,F=T.last;this._pushCells(C,S,L,0,k,v);var K=Math.max(k+1,z);if(!_&&z>k+1){var N=!1;if(L.size>0)for(var V=c?1:0,A=K-1;A>k;A--)if(L.has(A+V)){var D=this._getFrameMetricsApprox(k),B=this._getFrameMetricsApprox(A),H=B.offset-D.offset-(this.props.initialScrollIndex?0:D.length);C.push(y.createElement(M,{key:"$sticky_lead",style:t({},R,H)})),this._pushCells(C,S,L,A,A,v);var U=this._getFrameMetricsApprox(z).offset-(B.offset+B.length);C.push(y.createElement(M,{key:"$sticky_trail",style:t({},R,U)})),N=!0;break}if(!N){var W=this._getFrameMetricsApprox(k),$=this._getFrameMetricsApprox(z).offset-(W.offset+W.length);C.push(y.createElement(M,{key:"$lead_spacer",style:t({},R,$)}))}}if(this._pushCells(C,S,L,K,F,v),!this._hasWarned.keys&&E&&(console.warn("VirtualizedList: missing keys for items, make sure to specify a key or id property on each item or provide a custom keyExtractor.",w),this._hasWarned.keys=!0),!_&&F=p.length)break;_=p[f++]}else{if((f=p.next()).done)break;_=f.value}var v=_,y=this._nestedChildLists.get(v);y&&y.ref&&y.ref.measureLayoutRelativeToContainingList()}}this._computeBlankness(),this._updateViewableItems(this.props.data)}},{key:"measureLayoutRelativeToContainingList",value:function(){var t=this;try{if(!this._scrollRef)return;this._scrollRef.measureLayout(this.context.virtualizedList.getOutermostParentListRef().getScrollRef().getNativeScrollRef(),function(s,o,n,l){t._offsetFromParentVirtualizedList=t._selectOffset({x:s,y:o}),t._scrollMetrics.contentLength=t._selectLength({width:n,height:l});var h=t._convertParentScrollMetrics(t.context.virtualizedList.getScrollMetrics());t._scrollMetrics.visibleLength=h.visibleLength,t._scrollMetrics.offset=h.offset},function(t){console.warn("VirtualizedList: Encountered an error while measuring a list's offset from its containing VirtualizedList.")})}catch(t){console.warn('measureLayoutRelativeToContainingList threw an error',t.stack)}}},{key:"_renderDebugOverlay",value:function(){for(var t=this._scrollMetrics.visibleLength/(this._scrollMetrics.contentLength||1),s=[],o=this.props.getItemCount(this.props.data),n=0;n0){var _=l-this._getFrameMetricsApprox(s).offset;u=u||_<0||c<-2&&_2&&v0&&void 0!==arguments[0]?arguments[0]:{abort:!1};this._taskHandle&&(this._taskHandle.cancel(),t.abort||this._callback(),this._taskHandle=null)}},{key:"schedule",value:function(){var t=this;if(!this._taskHandle){var n=setTimeout(function(){t._taskHandle=l.runAfterInteractions(function(){t._taskHandle=null,t._callback()})},this._delay);this._taskHandle={cancel:function(){return clearTimeout(n)}}}}}]),s})();m.exports=s},250,[4,5,225]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=r(d[1]),s=r(d[2]),l=r(d[3]),_=r(d[4]),h=function t(){s(this,t),this.any_blank_count=0,this.any_blank_ms=0,this.any_blank_speed_sum=0,this.mostly_blank_count=0,this.mostly_blank_ms=0,this.pixels_blank=0,this.pixels_sampled=0,this.pixels_scrolled=0,this.total_time_spent=0,this.sample_count=0},o=[],u=10,f=null,c=(function(){function c(t){s(this,c),this._anyBlankStartTime=null,this._enabled=!1,this._info=new h,this._mostlyBlankStartTime=null,this._samplesStartTime=null,this._getFrameMetrics=t,this._enabled=(f||0)>Math.random(),this._resetData()}return n(c,null,[{key:"addListener",value:function(t){return _(null!==f,'Call `FillRateHelper.setSampleRate` before `addListener`.'),o.push(t),{remove:function(){o=o.filter(function(n){return t!==n})}}}},{key:"setSampleRate",value:function(t){f=t}},{key:"setMinSampleCount",value:function(t){u=t}}]),n(c,[{key:"activate",value:function(){this._enabled&&null==this._samplesStartTime&&(this._samplesStartTime=l())}},{key:"deactivateAndFlush",value:function(){if(this._enabled){var n=this._samplesStartTime;if(null!=n)if(this._info.sample_count0&&(k=Math.min(u,Math.max(0,p.offset-h)));for(var b=0,v=n.last,S=this._getFrameMetrics(v);v>=n.first&&(!S||!S.inLayout);)S=this._getFrameMetrics(v),v--;if(S&&v0?(this._anyBlankStartTime=c,this._info.any_blank_speed_sum+=f,this._info.any_blank_count++,this._info.pixels_blank+=T,B>.5&&(this._mostlyBlankStartTime=c,this._info.mostly_blank_count++)):(f<.01||Math.abs(_)<1)&&this.deactivateAndFlush(),B}},{key:"enabled",value:function(){return this._enabled}},{key:"_resetData",value:function(){this._anyBlankStartTime=null,this._info=new h,this._mostlyBlankStartTime=null,this._samplesStartTime=null}}]),c})();m.exports=c},251,[53,5,4,113,18]); -__d(function(g,r,i,a,m,e,d){'use strict';var s,t=r(d[0]),n=t(r(d[1])),o=t(r(d[2])),f=t(r(d[3])),h=t(r(d[4])),p=t(r(d[5])),l=t(r(d[6])),u=t(r(d[7])),c=(t(r(d[8])),t(r(d[9]))),v=(r(d[10]),r(d[11]));r(d[12]);s={SIZE:{}};var R=(function(s){function t(){var s,n;(0,f.default)(this,t);for(var o=arguments.length,h=new Array(o),u=0;u0&&void 0!==arguments[0]?arguments[0]:0,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;console.warn('`scrollWithoutAnimationTo` is deprecated. Use `scrollTo` instead'),this.scrollTo({x:n,y:t,animated:!1})}},{key:"flashScrollIndicators",value:function(){this._scrollResponder.scrollResponderFlashScrollIndicators()}},{key:"_getKeyForIndex",value:function(t,n){var o=n[t];return o&&o.key}},{key:"_updateAnimatedNodeAttachment",value:function(){this._scrollAnimatedValueAttachment&&this._scrollAnimatedValueAttachment.detach(),this.props.stickyHeaderIndices&&this.props.stickyHeaderIndices.length>0&&(this._scrollAnimatedValueAttachment=R.attachNativeEvent(this._scrollViewRef,'onScroll',[{nativeEvent:{contentOffset:{y:this._scrollAnimatedValue}}}]))}},{key:"_setStickyHeaderRef",value:function(t,n){n?this._stickyHeaderRefs.set(t,n):this._stickyHeaderRefs.delete(t)}},{key:"_onStickyHeaderLayout",value:function(t,n,o){var l=this.props.stickyHeaderIndices;if(l){var s=_.Children.toArray(this.props.children);if(o===this._getKeyForIndex(t,s)){var c=n.nativeEvent.layout.y;this._headerLayoutYs.set(o,c);var p=l[l.indexOf(t)-1];if(null!=p){var h=this._stickyHeaderRefs.get(this._getKeyForIndex(p,s));h&&h.setNextHeaderY&&h.setNextHeaderY(c)}}}}},{key:"render",value:function(){var l,s,c=this;s=n,V(void 0!==(l=t),'ScrollViewClass must not be undefined'),V(void 0!==s,'ScrollContentContainerViewClass must not be undefined');var p=[!0===this.props.horizontal&&b.contentContainerHorizontal,this.props.contentContainerStyle],h={};this.props.onContentSizeChange&&(h={onLayout:this._handleContentOnLayout});var u=this.props.stickyHeaderIndices,R=this.props.children;if(null!=u&&u.length>0){var v=_.Children.toArray(this.props.children);R=v.map(function(t,n){var o=t?u.indexOf(n):-1;if(o>-1){var l=t.key,s=u[o+1],p=c.props.StickyHeaderComponent||H;return _.createElement(p,{key:l,ref:function(t){return c._setStickyHeaderRef(l,t)},nextHeaderLayoutY:c._headerLayoutYs.get(c._getKeyForIndex(s,v)),onLayout:function(t){return c._onStickyHeaderLayout(n,t,l)},scrollAnimatedValue:c._scrollAnimatedValue,inverted:c.props.invertStickyHeaders,scrollViewHeight:c.state.layoutHeight},t)}return t})}R=_.createElement(E.Provider,{value:!0===this.props.horizontal?x:M},R);var S=Array.isArray(u)&&u.length>0,w=_.createElement(s,o({},h,{ref:this._setInnerViewRef,style:p,removeClippedSubviews:this.props.removeClippedSubviews,collapsable:!1}),R),C=void 0!==this.props.alwaysBounceHorizontal?this.props.alwaysBounceHorizontal:this.props.horizontal,A=void 0!==this.props.alwaysBounceVertical?this.props.alwaysBounceVertical:!this.props.horizontal,I=!!this.props.DEPRECATED_sendUpdatedChildFrames,z=!0===this.props.horizontal?b.baseHorizontal:b.baseVertical,L=f({},this.props,{alwaysBounceHorizontal:C,alwaysBounceVertical:A,style:[z,this.props.style],onContentSizeChange:null,onLayout:this._handleLayout,onMomentumScrollBegin:this._scrollResponder.scrollResponderHandleMomentumScrollBegin,onMomentumScrollEnd:this._scrollResponder.scrollResponderHandleMomentumScrollEnd,onResponderGrant:this._scrollResponder.scrollResponderHandleResponderGrant,onResponderReject:this._scrollResponder.scrollResponderHandleResponderReject,onResponderRelease:this._scrollResponder.scrollResponderHandleResponderRelease,onResponderTerminate:this._scrollResponder.scrollResponderHandleTerminate,onResponderTerminationRequest:this._scrollResponder.scrollResponderHandleTerminationRequest,onScrollBeginDrag:this._scrollResponder.scrollResponderHandleScrollBeginDrag,onScrollEndDrag:this._scrollResponder.scrollResponderHandleScrollEndDrag,onScrollShouldSetResponder:this._scrollResponder.scrollResponderHandleScrollShouldSetResponder,onStartShouldSetResponder:this._scrollResponder.scrollResponderHandleStartShouldSetResponder,onStartShouldSetResponderCapture:this._scrollResponder.scrollResponderHandleStartShouldSetResponderCapture,onTouchEnd:this._scrollResponder.scrollResponderHandleTouchEnd,onTouchMove:this._scrollResponder.scrollResponderHandleTouchMove,onTouchStart:this._scrollResponder.scrollResponderHandleTouchStart,onTouchCancel:this._scrollResponder.scrollResponderHandleTouchCancel,onScroll:this._handleScroll,scrollBarThumbImage:T(this.props.scrollBarThumbImage),scrollEventThrottle:S?1:this.props.scrollEventThrottle,sendMomentumEvents:!(!this.props.onMomentumScrollBegin&&!this.props.onMomentumScrollEnd),DEPRECATED_sendUpdatedChildFrames:I,snapToStart:!1!==this.props.snapToStart,snapToEnd:!1!==this.props.snapToEnd,pagingEnabled:!0===this.props.pagingEnabled&&null==this.props.snapToInterval&&null==this.props.snapToOffsets}),N=this.props.decelerationRate;null!=N&&(L.decelerationRate=k(N));var B=this.props.refreshControl;return B?_.createElement(l,o({},L,{ref:this._setScrollViewRef}),y.isTV?null:B,w):_.createElement(l,o({},L,{ref:this._setScrollViewRef}),w)}}]),C})(_.Component);I.Context=E;var b=w.create({baseVertical:{flexGrow:1,flexShrink:1,flexDirection:'column',overflow:'scroll'},baseHorizontal:{flexGrow:1,flexShrink:1,flexDirection:'row',overflow:'scroll'},contentContainerHorizontal:{flexDirection:'row'}});m.exports=I},255,[24,4,5,6,9,10,8,53,227,57,59,92,256,263,62,90,262,89,16,264,184,179,265]); -__d(function(g,r,i,a,m,e,d){'use strict';var o=r(d[0]),s=r(d[1]),n=r(d[2]),l=r(d[3]),t=r(d[4]),c=r(d[5]),p=r(d[6]),h=r(d[7]),u=r(d[8]),S=r(d[9]),b=r(d[10]).ScrollViewManager,R={Mixin:{_subscriptionKeyboardWillShow:null,_subscriptionKeyboardWillHide:null,_subscriptionKeyboardDidShow:null,_subscriptionKeyboardDidHide:null,scrollResponderMixinGetInitialState:function(){return{isTouching:!1,lastMomentumScrollBeginTime:0,lastMomentumScrollEndTime:0,observedScrollSinceBecomingResponder:!1,becameResponderWhileAnimating:!1}},scrollResponderHandleScrollShouldSetResponder:function(){return!0!==this.props.disableScrollViewPanResponder&&this.state.isTouching},scrollResponderHandleStartShouldSetResponder:function(o){if(!0===this.props.disableScrollViewPanResponder)return!1;var s=t.currentlyFocusedField();return'handled'===this.props.keyboardShouldPersistTaps&&null!=s&&o.target!==s},scrollResponderHandleStartShouldSetResponderCapture:function(o){if(this.scrollResponderIsAnimating())return!0;if(!0===this.props.disableScrollViewPanResponder)return!1;var s=t.currentlyFocusedField(),n=this.props.keyboardShouldPersistTaps;return!(n&&'never'!==n||null==s||!o.target||t.isTextInput(o.target))},scrollResponderHandleResponderReject:function(){},scrollResponderHandleTerminationRequest:function(){return!this.state.observedScrollSinceBecomingResponder},scrollResponderHandleTouchEnd:function(o){var s=o.nativeEvent;this.state.isTouching=0!==s.touches.length,this.props.onTouchEnd&&this.props.onTouchEnd(o)},scrollResponderHandleTouchCancel:function(o){this.state.isTouching=!1,this.props.onTouchCancel&&this.props.onTouchCancel(o)},scrollResponderHandleResponderRelease:function(o){this.props.onResponderRelease&&this.props.onResponderRelease(o);var s=t.currentlyFocusedField();!0===this.props.keyboardShouldPersistTaps||'always'===this.props.keyboardShouldPersistTaps||null==s||o.target===s||this.state.observedScrollSinceBecomingResponder||this.state.becameResponderWhileAnimating||(this.props.onScrollResponderKeyboardDismissed&&this.props.onScrollResponderKeyboardDismissed(o),t.blurTextInput(s))},scrollResponderHandleScroll:function(o){this.state.observedScrollSinceBecomingResponder=!0,this.props.onScroll&&this.props.onScroll(o)},scrollResponderHandleResponderGrant:function(o){this.state.observedScrollSinceBecomingResponder=!1,this.props.onResponderGrant&&this.props.onResponderGrant(o),this.state.becameResponderWhileAnimating=this.scrollResponderIsAnimating()},scrollResponderHandleScrollBeginDrag:function(o){s.beginScroll(),this.props.onScrollBeginDrag&&this.props.onScrollBeginDrag(o)},scrollResponderHandleScrollEndDrag:function(o){var n=o.nativeEvent.velocity;this.scrollResponderIsAnimating()||n&&(0!==n.x||0!==n.y)||s.endScroll(),this.props.onScrollEndDrag&&this.props.onScrollEndDrag(o)},scrollResponderHandleMomentumScrollBegin:function(o){this.state.lastMomentumScrollBeginTime=u(),this.props.onMomentumScrollBegin&&this.props.onMomentumScrollBegin(o)},scrollResponderHandleMomentumScrollEnd:function(o){s.endScroll(),this.state.lastMomentumScrollEndTime=u(),this.props.onMomentumScrollEnd&&this.props.onMomentumScrollEnd(o)},scrollResponderHandleTouchStart:function(o){this.state.isTouching=!0,this.props.onTouchStart&&this.props.onTouchStart(o)},scrollResponderHandleTouchMove:function(o){this.props.onTouchMove&&this.props.onTouchMove(o)},scrollResponderIsAnimating:function(){return u()-this.state.lastMomentumScrollEndTime<16||this.state.lastMomentumScrollEndTime0){v.push(H),L.push(0),v.push(H+1),L.push(1);var Y=(y||0)-l-o;Y>H&&(v.push(Y,Y+1),L.push(Y-H,Y-H))}}}else{v.push(h),L.push(0);var x=(y||0)-l;x>=h?(v.push(x,x+1),L.push(x-h,x-h)):(v.push(h+1),L.push(1))}var C=this.props.scrollAnimatedValue.interpolate({inputRange:v,outputRange:L}),E=p.Children.only(this.props.children);return p.createElement(c,{collapsable:!1,onLayout:this._onLayout,style:[E.props.style,f.header,{transform:[{translateY:C}]}]},p.cloneElement(E,{style:f.fill,onLayout:void 0}))}}]),h})(p.Component),f=h.create({header:{zIndex:10},fill:{flex:1}});m.exports=v},263,[4,5,6,9,10,227,59,62,90]); -__d(function(g,r,i,a,m,e,d){'use strict';r(d[0]);m.exports=function(t){return'normal'===t?.998:'fast'===t?.99:t}},264,[57]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0])(Object.create(null),{margin:!0,marginHorizontal:!0,marginVertical:!0,marginBottom:!0,marginTop:!0,marginLeft:!0,marginRight:!0,flex:!0,flexGrow:!0,flexShrink:!0,flexBasis:!0,alignSelf:!0,height:!0,minHeight:!0,maxHeight:!0,width:!0,minWidth:!0,maxWidth:!0,position:!0,left:!0,right:!0,bottom:!0,top:!0,transform:!0});m.exports=function(n){var o={},f={};return n&&Object.keys(n).forEach(function(h){var l=n[h];t[h]?f[h]=l:o[h]=l}),{outer:f,inner:o}}},265,[24]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=r(d[1]),s=r(d[2]),o=r(d[3]),l=r(d[4]),h=(function(){function h(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{viewAreaCoveragePercentThreshold:0};s(this,h),this._hasInteracted=!1,this._timers=new Set,this._viewableIndices=[],this._viewableItems=new Map,this._config=t}return o(h,[{key:"dispose",value:function(){this._timers.forEach(clearTimeout)}},{key:"computeViewableItems",value:function(t,n,s,o,h){var c=this._config,f=c.itemVisiblePercentThreshold,v=c.viewAreaCoveragePercentThreshold,b=null!=v,_=b?v:f;l(null!=_&&null!=f!=(null!=v),'Must set exactly one of itemVisiblePercentThreshold or viewAreaCoveragePercentThreshold');var w=[];if(0===t)return w;var y=-1,I=h||{first:0,last:t-1},p=I.first,k=I.last;if(k>=t)return console.warn('Invalid render range computing viewability '+JSON.stringify({renderRange:h,itemCount:t})),[];for(var S=p;S<=k;S++){var T=o(S);if(T){var A=T.offset-n,V=A+T.length;if(A0)y=S,u(b,_,A,V,s,T.length)&&w.push(S);else if(y>=0)break}}return w}},{key:"onUpdate",value:function(t,n,s,o,l,h,u){var c=this;if((!this._config.waitForInteraction||this._hasInteracted)&&0!==t&&o(0)){var f=[];if(t&&(f=this.computeViewableItems(t,n,s,o,u)),this._viewableIndices.length!==f.length||!this._viewableIndices.every(function(t,n){return t===f[n]}))if(this._viewableIndices=f,this._config.minimumViewTime){var v=setTimeout(function(){c._timers.delete(v),c._onUpdateSync(f,h,l)},this._config.minimumViewTime);this._timers.add(v)}else this._onUpdateSync(f,h,l)}}},{key:"resetViewableIndices",value:function(){this._viewableIndices=[]}},{key:"recordInteraction",value:function(){this._hasInteracted=!0}},{key:"_onUpdateSync",value:function(s,o,l){var h=this;s=s.filter(function(t){return h._viewableIndices.includes(t)});var u=this._viewableItems,c=new Map(s.map(function(t){var n=l(t,!0);return[n.key,n]})),f=[],v=c,b=Array.isArray(v),_=0;for(v=b?v:v["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var w;if(b){if(_>=v.length)break;w=v[_++]}else{if((_=v.next()).done)break;w=_.value}var y=n(w,2),I=y[0],p=y[1];u.has(I)||f.push(p)}var k=u,S=Array.isArray(k),T=0;for(k=S?k:k["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var A;if(S){if(T>=k.length)break;A=k[T++]}else{if((T=k.next()).done)break;A=T.value}var V=n(A,2),x=V[0],M=V[1];c.has(x)||f.push(t({},M,{isViewable:!1}))}f.length>0&&(this._viewableItems=c,o({viewableItems:Array.from(c.values()),changed:f,viewabilityConfig:this._config}))}}]),h})();function u(t,n,s,o,l,h){if(f(s,o,l))return!0;var u=c(s,o,l);return 100*(t?u/l:u/h)>=n}function c(t,n,s){var o=Math.min(n,s)-Math.max(t,0);return Math.max(0,o)}function f(t,n,s){return t>=0&&n<=s&&n>t}m.exports=h},266,[53,25,4,5,16]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=r(d[1]);function s(t,s,f){for(var l=[],o=0,u=0;u=t[c]&&(l[c]=u,o++,c===t.length-1))return n(o===t.length,'bad offsets input, should be in increasing order: %s',JSON.stringify(t)),l;return l}function f(t,n){return n.last-n.first+1-Math.max(0,1+Math.min(n.last,t.last)-Math.max(n.first,t.first))}var l={computeWindowedRenderLimits:function(n,l,o,u){var h=n.data,v=n.getItemCount,c=n.maxToRenderPerBatch,x=n.windowSize,M=v(h);if(0===M)return l;var w=u.offset,b=u.velocity,p=u.visibleLength,C=Math.max(0,w),O=C+p,y=(x-1)*p,L=b>1?'after':b<-1?'before':'none',R=Math.max(0,C-.5*y),S=Math.max(0,O+.5*y);if(o(M-1).offset=_);){var E=z>=c,F=N<=l.first||N>l.last,P=N>J&&(!E||!F),W=T>=l.last||T=N&&N>=0&&T=J&&T<=_&&N<=k.first&&T>=k.last))throw new Error('Bad window calculation '+JSON.stringify({first:N,last:T,itemCount:M,overscanFirst:J,overscanLast:_,visible:k}));return{first:N,last:T}},elementsThatOverlapOffsets:s,newRangeCount:f};m.exports=l},267,[25,16]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),s=r(d[1]);m.exports=s(t)},268,[269,246]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=r(d[1]),o=r(d[2]),s=r(d[3]),c=r(d[4]),u=(r(d[5]),r(d[6])),h=r(d[7]),l=r(d[8]),f=r(d[9]),p=s.ImageViewManager,w=l('RCTImageView');var v=function(n,o){var s,u,l=f(n.source)||{uri:void 0,width:void 0,height:void 0};if(Array.isArray(l))u=h([y.base,n.style])||{},s=l;else{var p=l.width,v=l.height,z=l.uri;u=h([{width:p,height:v},y.base,n.style])||{},s=[l],''===z&&console.warn('source.uri should not be an empty string')}var I=n.resizeMode||u.resizeMode||'cover',b=u.tintColor;if(null!=n.src&&console.warn('The component requires a `source` property rather than `src`.'),null!=n.children)throw new Error('The component cannot contain children. If you want to render content on top of the image, consider using the component or absolute positioning.');return c.createElement(w,t({},n,{ref:o,style:u,resizeMode:I,tintColor:b,source:s}))};(v=c.forwardRef(v)).displayName='Image',v.getSize=function(t,n,o){p.getSize(t,n,o||function(){console.warn('Failed to get size for image: '+t)})},v.getSizeWithHeaders=function(t,n,o,s){return p.getSizeWithHeaders({uri:t,headers:n}).then(function(t){o(t.width,t.height)}).catch(s||function(){console.warn('Failed to get size for image: '+t)})},v.prefetch=function(t){return p.prefetchImage(t)},v.queryCache=function(t){return n.async(function(o){for(;;)switch(o.prev=o.next){case 0:return o.next=2,n.awrap(p.queryCache(t));case 2:return o.abrupt("return",o.sent);case 3:case"end":return o.stop()}},null,this)},v.resolveAssetSource=f,v.propTypes=o;var y=u.create({base:{overflow:'hidden'}});m.exports=v},269,[24,270,272,23,59,92,62,89,184,179]); -__d(function(g,r,i,a,m,e,d){m.exports=r(d[0])},270,[271]); -__d(function(g,r,i,a,m,e,d){var t=(function(t){"use strict";var n,o=Object.prototype,c=o.hasOwnProperty,u="function"==typeof Symbol?Symbol:{},h=u.iterator||"@@iterator",f=u.asyncIterator||"@@asyncIterator",s=u.toStringTag||"@@toStringTag";function l(t,n,o,c){var u=n&&n.prototype instanceof E?n:E,h=Object.create(u.prototype),f=new A(c||[]);return h._invoke=F(t,o,f),h}function p(t,n,o){try{return{type:"normal",arg:t.call(n,o)}}catch(t){return{type:"throw",arg:t}}}t.wrap=l;var y="suspendedStart",v="suspendedYield",w="executing",L="completed",x={};function E(){}function b(){}function _(){}var j={};j[h]=function(){return this};var O=Object.getPrototypeOf,k=O&&O(O(R([])));k&&k!==o&&c.call(k,h)&&(j=k);var G=_.prototype=E.prototype=Object.create(j);function N(t){["next","throw","return"].forEach(function(n){t[n]=function(t){return this._invoke(n,t)}})}function P(t){function n(o,u,h,f){var s=p(t[o],t,u);if("throw"!==s.type){var l=s.arg,y=l.value;return y&&"object"==typeof y&&c.call(y,"__await")?Promise.resolve(y.__await).then(function(t){n("next",t,h,f)},function(t){n("throw",t,h,f)}):Promise.resolve(y).then(function(t){l.value=t,h(l)},function(t){return n("throw",t,h,f)})}f(s.arg)}var o;this._invoke=function(t,c){function u(){return new Promise(function(o,u){n(t,c,o,u)})}return o=o?o.then(u,u):u()}}function F(t,n,o){var c=y;return function(u,h){if(c===w)throw new Error("Generator is already running");if(c===L){if("throw"===u)throw h;return Y()}for(o.method=u,o.arg=h;;){var f=o.delegate;if(f){var s=S(f,o);if(s){if(s===x)continue;return s}}if("next"===o.method)o.sent=o._sent=o.arg;else if("throw"===o.method){if(c===y)throw c=L,o.arg;o.dispatchException(o.arg)}else"return"===o.method&&o.abrupt("return",o.arg);c=w;var l=p(t,n,o);if("normal"===l.type){if(c=o.done?L:v,l.arg===x)continue;return{value:l.arg,done:o.done}}"throw"===l.type&&(c=L,o.method="throw",o.arg=l.arg)}}}function S(t,o){var c=t.iterator[o.method];if(c===n){if(o.delegate=null,"throw"===o.method){if(t.iterator.return&&(o.method="return",o.arg=n,S(t,o),"throw"===o.method))return x;o.method="throw",o.arg=new TypeError("The iterator does not provide a 'throw' method")}return x}var u=p(c,t.iterator,o.arg);if("throw"===u.type)return o.method="throw",o.arg=u.arg,o.delegate=null,x;var h=u.arg;return h?h.done?(o[t.resultName]=h.value,o.next=t.nextLoc,"return"!==o.method&&(o.method="next",o.arg=n),o.delegate=null,x):h:(o.method="throw",o.arg=new TypeError("iterator result is not an object"),o.delegate=null,x)}function T(t){var n={tryLoc:t[0]};1 in t&&(n.catchLoc=t[1]),2 in t&&(n.finallyLoc=t[2],n.afterLoc=t[3]),this.tryEntries.push(n)}function I(t){var n=t.completion||{};n.type="normal",delete n.arg,t.completion=n}function A(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(T,this),this.reset(!0)}function R(t){if(t){var o=t[h];if(o)return o.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var u=-1,f=function o(){for(;++u=0;--h){var f=this.tryEntries[h],s=f.completion;if("root"===f.tryLoc)return u("end");if(f.tryLoc<=this.prev){var l=c.call(f,"catchLoc"),p=c.call(f,"finallyLoc");if(l&&p){if(this.prev=0;--o){var u=this.tryEntries[o];if(u.tryLoc<=this.prev&&c.call(u,"finallyLoc")&&this.prev=0;--n){var o=this.tryEntries[n];if(o.finallyLoc===t)return this.complete(o.completion,o.afterLoc),I(o),x}},catch:function(t){for(var n=this.tryEntries.length-1;n>=0;--n){var o=this.tryEntries[n];if(o.tryLoc===t){var c=o.completion;if("throw"===c.type){var u=c.arg;I(o)}return u}}throw new Error("illegal catch attempt")},delegateYield:function(t,o,c){return this.delegate={iterator:R(t),resultName:o,nextLoc:c},"next"===this.method&&(this.arg=n),x}},t})("object"==typeof m?m.exports:{});try{regeneratorRuntime=t}catch(n){Function("r","regeneratorRuntime = r")(t)}},271,[]); -__d(function(g,r,i,a,m,e,d){'use strict';var n=r(d[0]),o=r(d[1]),t=r(d[2]),s=r(d[3]),c=r(d[4]);m.exports={style:s(t),source:o,defaultSource:c.oneOfType([c.shape({uri:c.string,width:c.number,height:c.number,scale:c.number}),c.number]),accessible:c.bool,accessibilityLabel:c.node,blurRadius:c.number,capInsets:n,resizeMethod:c.oneOf(['auto','resize','scale']),resizeMode:c.oneOf(['cover','contain','stretch','repeat','center']),testID:c.string,onLayout:c.func,onLoadStart:c.func,onProgress:c.func,onError:c.func,onPartialLoad:c.func,onLoad:c.func,onLoadEnd:c.func}},272,[201,273,67,202,71]); -__d(function(g,r,i,a,m,e,d){'use strict';var n=r(d[0]),t=n.shape({uri:n.string,bundle:n.string,method:n.string,headers:n.objectOf(n.string),body:n.string,cache:n.oneOf(['default','reload','force-cache','only-if-cached']),width:n.number,height:n.number,scale:n.number}),c=n.oneOfType([t,n.number,n.arrayOf(t)]);m.exports=c},273,[71]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),o=r(d[1]);m.exports=o(t,{scrollEventThrottle:1e-4})},274,[255,246]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),o=r(d[1]);m.exports=o(t,{scrollEventThrottle:1e-4})},275,[276,246]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=r(d[1]),s=r(d[2]),o=r(d[3]),f=r(d[4]),p=r(d[5]),c=r(d[6]),l=(r(d[7]),r(d[8])),u=(r(d[9]),r(d[10])),R=c({},u.defaultProps,{stickySectionHeadersEnabled:!0}),h=(function(c){function R(){var t,s;n(this,R);for(var p=arguments.length,c=new Array(p),l=0;l0&&this.props.stickySectionHeadersEnabled&&(l+=this._listRef._getFrameMetricsApprox(o-t.itemIndex).length);var p=n({},t,{viewOffset:l,index:o});this._listRef.scrollToIndex(p)}},{key:"getListRef",value:function(){return this._listRef}}]),p(I,[{key:"UNSAFE_componentWillReceiveProps",value:function(t){this.setState(this._computeState(t))}},{key:"_computeState",value:function(t){var o=t.ListHeaderComponent?1:0,s=[],l=t.sections?t.sections.reduce(function(n,l){return s.push(n+o),n+t.getItemCount(l.data)+2},0):0;return{childProps:n({},t,{renderItem:this._renderItem,ItemSeparatorComponent:void 0,data:t.sections,getItemCount:function(){return l},getItem:function(n,o){return x(t,n,o)},keyExtractor:this._keyExtractor,onViewableItemsChanged:t.onViewableItemsChanged?this._onViewableItemsChanged:void 0,stickyHeaderIndices:t.stickySectionHeadersEnabled?s:void 0})}}},{key:"render",value:function(){return h.createElement(S,t({},this.state.childProps,{ref:this._captureRef}))}},{key:"_subExtractor",value:function(t){for(var n=t,o=this.props,s=o.getItem,l=o.getItemCount,p=o.keyExtractor,c=o.sections,u=0;u=l(f)+1)n-=l(f)+1;else return-1===n?{section:h,key:S+':header',index:null,header:!0,trailingSection:c[u+1]}:n===l(f)?{section:h,key:S+':footer',index:null,header:!1,trailingSection:c[u+1]}:{section:h,key:S+':'+(h.keyExtractor||p)(s(f,n),n),index:n,leadingItem:s(f,n-1),leadingSection:c[u-1],trailingItem:s(f,n+1),trailingSection:c[u+1]}}}},{key:"_getSeparatorComponent",value:function(t,n){if(!(n=n||this._subExtractor(t)))return null;var o=n.section.ItemSeparatorComponent||this.props.ItemSeparatorComponent,s=this.props.SectionSeparatorComponent,l=t===this.state.childProps.getItemCount()-1,p=n.index===this.props.getItemCount(n.section.data)-1;return s&&p?s:!o||p||l?null:o}}]),I})(h.PureComponent);I.defaultProps=n({},S.defaultProps,{data:[]});var _=(function(t){function u(){var t,p;o(this,u);for(var c=arguments.length,h=new Array(c),f=0;f10?o:10,update:{duration:o>10?o:10,type:f.Types[s]||'keyboard'}}),n.setState({bottom:u}))}else n.setState({bottom:0})},n._onLayout=function(t){n._frame=t.nativeEvent.layout,n._initialFrameHeight||(n._initialFrameHeight=n._frame.height)},n.state={bottom:0},n.viewRef=y.createRef(),n}return h(p,_),s(p,[{key:"_relativeKeyboardHeight",value:function(t){var n=this._frame;if(!n||!t)return 0;var o=t.screenY-this.props.keyboardVerticalOffset;return Math.max(n.y+n.height-o,0)}},{key:"componentDidMount",value:function(){this._subscriptions=[c.addListener('keyboardWillChangeFrame',this._onKeyboardChange)]}},{key:"componentWillUnmount",value:function(){this._subscriptions.forEach(function(t){t.remove()})}},{key:"render",value:function(){var o=this.props,s=o.behavior,l=o.children,u=o.contentContainerStyle,h=o.enabled,c=(o.keyboardVerticalOffset,o.style),f=n(o,["behavior","children","contentContainerStyle","enabled","keyboardVerticalOffset","style"]),_=h?this.state.bottom:0;switch(s){case'height':var p;return null!=this._frame&&this.state.bottom>0&&(p={height:this._initialFrameHeight-_,flex:0}),y.createElement(v,t({ref:this.viewRef,style:b.compose(c,p),onLayout:this._onLayout},f),l);case'position':return y.createElement(v,t({ref:this.viewRef,style:c,onLayout:this._onLayout},f),y.createElement(v,{style:b.compose(u,{bottom:_})},l));case'padding':return y.createElement(v,t({ref:this.viewRef,style:b.compose(c,{paddingBottom:_}),onLayout:this._onLayout},f),l);default:return y.createElement(v,t({ref:this.viewRef,onLayout:this._onLayout,style:c},f),l)}}}]),p})(y.Component);_.defaultProps={enabled:!0,keyboardVerticalOffset:0},m.exports=_},296,[24,55,4,5,6,9,10,259,261,57,59,62,90]); -__d(function(g,r,i,a,m,e,d){var n=r(d[0]),t=n(r(d[1])),l=n(r(d[2])),s=n(r(d[3])),o=n(r(d[4])),u=n(r(d[5])),c=n(r(d[6])),f=n(r(d[7])),h=r(d[8]),p=r(d[9]),k=r(d[10]),v=(function(n){function v(){var n,t;(0,l.default)(this,v);for(var s=arguments.length,c=new Array(s),f=0;f=1&&(l=_.createElement(y,{style:o.style,allowFontScaling:o.allowFontScaling,maxFontSizeMultiplier:o.maxFontSizeMultiplier},l)),o.inputView&&(l=[l,o.inputView]),o.style.unshift(L.multilineInput),s=_.createElement(t,u({ref:this._setNativeRef},o,{children:l,onFocus:this._onFocus,onBlur:this._onBlur,onChange:this._onChange,onContentSizeChange:this.props.onContentSizeChange,onSelectionChange:this._onSelectionChange,onTextInput:this._onTextInput,onSelectionChangeShouldSetResponder:N,text:this._getText(),dataDetectorTypes:this.props.dataDetectorTypes,onScroll:this._onScroll}))}else s=_.createElement(n,u({ref:this._setNativeRef},o,{onFocus:this._onFocus,onBlur:this._onBlur,onChange:this._onChange,onSelectionChange:this._onSelectionChange,onSelectionChangeShouldSetResponder:N,text:this._getText()}));return _.createElement(I,{onLayout:o.onLayout,onPress:this._onPress,rejectResponderTermination:!0,accessible:o.accessible,accessibilityLabel:o.accessibilityLabel,accessibilityRole:o.accessibilityRole,accessibilityStates:o.accessibilityStates,accessibilityState:o.accessibilityState,nativeID:this.props.nativeID,testID:o.testID},s)},_renderIOS:function(){var s=u({},this.props);s.style=[this.props.style],s.selection&&null==s.selection.end&&(s.selection={start:s.selection.start,end:s.selection.start});var o=s.multiline?t:n;s.multiline&&s.style.unshift(L.multilineInput);var l=_.createElement(o,u({ref:this._setNativeRef},s,{onFocus:this._onFocus,onBlur:this._onBlur,onChange:this._onChange,onContentSizeChange:this.props.onContentSizeChange,onSelectionChange:this._onSelectionChange,onTextInput:this._onTextInput,onSelectionChangeShouldSetResponder:N,text:this._getText(),dataDetectorTypes:this.props.dataDetectorTypes,onScroll:this._onScroll}));return _.createElement(I,{onLayout:s.onLayout,onPress:this._onPress,rejectResponderTermination:s.rejectResponderTermination,accessible:s.accessible,accessibilityLabel:s.accessibilityLabel,accessibilityRole:s.accessibilityRole,accessibilityStates:s.accessibilityStates,accessibilityState:s.accessibilityState,nativeID:this.props.nativeID,testID:s.testID},l)},_renderAndroid:function(){var t=u({},this.props);t.style=[this.props.style],t.autoCapitalize=t.autoCapitalize||'sentences';var n=this.props.children,s=0;_.Children.forEach(n,function(){return++s}),R(!(this.props.value&&s),'Cannot specify both value and children.'),s>1&&(n=_.createElement(y,null,n)),t.selection&&null==t.selection.end&&(t.selection={start:t.selection.start,end:t.selection.start});var o=_.createElement(void 0,u({ref:this._setNativeRef},t,{mostRecentEventCount:0,onFocus:this._onFocus,onBlur:this._onBlur,onChange:this._onChange,onSelectionChange:this._onSelectionChange,onTextInput:this._onTextInput,text:this._getText(),children:n,disableFullscreenUI:this.props.disableFullscreenUI,textBreakStrategy:this.props.textBreakStrategy,onScroll:this._onScroll}));return _.createElement(I,{onLayout:t.onLayout,onPress:this._onPress,accessible:this.props.accessible,accessibilityLabel:this.props.accessibilityLabel,accessibilityRole:this.props.accessibilityRole,accessibilityStates:this.props.accessibilityStates,accessibilityState:this.props.accessibilityState,nativeID:this.props.nativeID,testID:this.props.testID},o)},_onFocus:function(t){this.props.onFocus&&this.props.onFocus(t),this.props.selectionState&&this.props.selectionState.focus()},_onPress:function(t){(this.props.editable||void 0===this.props.editable)&&this.focus()},_onChange:function(t){this._inputRef&&this._inputRef.setNativeProps&&S.setNativeProps(this._inputRef,{mostRecentEventCount:t.nativeEvent.eventCount});var n=t.nativeEvent.text;this.props.onChange&&this.props.onChange(t),this.props.onChangeText&&this.props.onChangeText(n),this._inputRef&&(this._lastNativeText=n,this.forceUpdate())},_onSelectionChange:function(t){this.props.onSelectionChange&&this.props.onSelectionChange(t),this._inputRef&&(this._lastNativeSelection=t.nativeEvent.selection,(this.props.selection||this.props.selectionState)&&this.forceUpdate())},componentDidUpdate:function(){var t={};this._lastNativeText!==this.props.value&&'string'==typeof this.props.value&&(t.text=this.props.value);var n=this.props.selection;this._lastNativeSelection&&n&&(this._lastNativeSelection.start!==n.start||this._lastNativeSelection.end!==n.end)&&(t.selection=this.props.selection),Object.keys(t).length>0&&this._inputRef&&this._inputRef.setNativeProps&&S.setNativeProps(this._inputRef,t),this.props.selectionState&&n&&this.props.selectionState.update(n.start,n.end)},_onBlur:function(t){this.blur(),this.props.onBlur&&this.props.onBlur(t),this.props.selectionState&&this.props.selectionState.blur()},_onTextInput:function(t){this.props.onTextInput&&this.props.onTextInput(t)},_onScroll:function(t){this.props.onScroll&&this.props.onScroll(t)}}),E=((function(t){function n(){return s(this,n),l(this,c(n).apply(this,arguments))}p(n,t),o(n,[{key:"clear",value:function(){}},{key:"isFocused",value:function(){}}])})(S.NativeComponent),D),L=v.create({multilineInput:{paddingTop:5}});m.exports=E},324,[4,5,6,9,10,24,325,328,280,57,59,92,62,199,204,165,281,77,282,16,184,18]); -__d(function(g,r,i,a,m,e,d){'use strict';var n=r(d[0]),o=r(d[1]),t=r(d[2]),l=r(d[3]),s=r(d[4]),c=r(d[5]),u=['phoneNumber','link','address','calendarEvent','none','all'];m.exports=n({},l,{autoCapitalize:o.oneOf(['none','sentences','words','characters']),autoCompleteType:o.oneOf(['cc-csc','cc-exp','cc-exp-month','cc-exp-year','cc-number','email','name','password','postal-code','street-address','tel','username','off']),autoCorrect:o.bool,spellCheck:o.bool,autoFocus:o.bool,allowFontScaling:o.bool,maxFontSizeMultiplier:o.number,editable:o.bool,keyboardType:o.oneOf(['default','email-address','numeric','phone-pad','number-pad','ascii-capable','numbers-and-punctuation','url','name-phone-pad','decimal-pad','twitter','web-search','visible-password']),keyboardAppearance:o.oneOf(['default','light','dark']),returnKeyType:o.oneOf(['done','go','next','search','send','none','previous','default','emergency-call','google','join','route','yahoo']),returnKeyLabel:o.string,maxLength:o.number,numberOfLines:o.number,disableFullscreenUI:o.bool,enablesReturnKeyAutomatically:o.bool,multiline:o.bool,textBreakStrategy:o.oneOf(['simple','highQuality','balanced']),onBlur:o.func,onFocus:o.func,onChange:o.func,onChangeText:o.func,onContentSizeChange:o.func,onTextInput:o.func,onEndEditing:o.func,onSelectionChange:o.func,onSubmitEditing:o.func,onKeyPress:o.func,onLayout:o.func,onScroll:o.func,placeholder:o.string,placeholderTextColor:t,scrollEnabled:o.bool,secureTextEntry:o.bool,selectionColor:t,selectionState:o.instanceOf(s),selection:o.shape({start:o.number.isRequired,end:o.number}),value:o.string,defaultValue:o.string,clearButtonMode:o.oneOf(['never','while-editing','unless-editing','always']),clearTextOnFocus:o.bool,selectTextOnFocus:o.bool,blurOnSubmit:o.bool,style:c.propTypes.style,underlineColorAndroid:t,inlineImageLeft:o.string,inlineImagePadding:o.number,rejectResponderTermination:o.bool,dataDetectorTypes:o.oneOfType([o.oneOf(u),o.arrayOf(o.oneOf(u))]),caretHidden:o.bool,contextMenuHidden:o.bool,inputAccessoryViewID:o.string,textContentType:o.oneOf(['none','URL','addressCity','addressCityAndState','addressState','countryName','creditCardNumber','emailAddress','familyName','fullStreetAddress','givenName','jobTitle','location','middleName','name','namePrefix','nameSuffix','nickname','organizationName','postalCode','streetAddressLine1','streetAddressLine2','sublocality','telephoneNumber','username','password','newPassword','oneTimeCode']),showSoftInputOnFocus:o.bool})},325,[53,71,68,326,328,199]); -__d(function(g,r,i,a,m,e,d){'use strict';var o=r(d[0]),n=r(d[1]),s=r(d[2]),t=r(d[3]),c=r(d[4]),l=r(d[5]),b=r(d[6]),u=b.DeprecatedAccessibilityRoles,p=b.DeprecatedAccessibilityStates,f=s(t);m.exports=o({accessible:l.bool,accessibilityLabel:l.node,accessibilityHint:l.string,accessibilityActions:l.arrayOf(l.string),accessibilityIgnoresInvertColors:l.bool,accessibilityRole:l.oneOf(u),accessibilityStates:l.arrayOf(l.oneOf(p)),accessibilityState:l.object,accessibilityLiveRegion:l.oneOf(['none','polite','assertive']),importantForAccessibility:l.oneOf(['auto','yes','no','no-hide-descendants']),accessibilityViewIsModal:l.bool,accessibilityElementsHidden:l.bool,onAccessibilityAction:l.func,onAccessibilityTap:l.func,onMagicTap:l.func,testID:l.string,nativeID:l.string,onResponderGrant:l.func,onResponderMove:l.func,onResponderReject:l.func,onResponderRelease:l.func,onResponderTerminate:l.func,onResponderTerminationRequest:l.func,onStartShouldSetResponder:l.func,onStartShouldSetResponderCapture:l.func,onMoveShouldSetResponder:l.func,onMoveShouldSetResponderCapture:l.func,hitSlop:n,onLayout:l.func,pointerEvents:l.oneOf(['box-none','none','box-only','auto']),style:f,removeClippedSubviews:l.bool,renderToHardwareTextureAndroid:l.bool,shouldRasterizeIOS:l.bool,collapsable:l.bool,needsOffscreenAlphaCompositing:l.bool},c)},326,[53,201,202,83,327,71,287]); -__d(function(g,r,i,a,m,e,d){'use strict'},327,[]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),s=r(d[1]),f=r(d[2]),u=(function(){function f(s,u){t(this,f),this._anchorOffset=s,this._focusOffset=u,this._hasFocus=!1}return s(f,[{key:"update",value:function(t,s){this._anchorOffset===t&&this._focusOffset===s||(this._anchorOffset=t,this._focusOffset=s,this.emit('update'))}},{key:"constrainLength",value:function(t){this.update(Math.min(this._anchorOffset,t),Math.min(this._focusOffset,t))}},{key:"focus",value:function(){this._hasFocus||(this._hasFocus=!0,this.emit('focus'))}},{key:"blur",value:function(){this._hasFocus&&(this._hasFocus=!1,this.emit('blur'))}},{key:"hasFocus",value:function(){return this._hasFocus}},{key:"isCollapsed",value:function(){return this._anchorOffset===this._focusOffset}},{key:"isBackward",value:function(){return this._anchorOffset>this._focusOffset}},{key:"getAnchorOffset",value:function(){return this._hasFocus?this._anchorOffset:null}},{key:"getFocusOffset",value:function(){return this._hasFocus?this._focusOffset:null}},{key:"getStartOffset",value:function(){return this._hasFocus?Math.min(this._anchorOffset,this._focusOffset):null}},{key:"getEndOffset",value:function(){return this._hasFocus?Math.max(this._anchorOffset,this._focusOffset):null}},{key:"overlaps",value:function(t,s){return this.hasFocus()&&this.getStartOffset()<=s&&t<=this.getEndOffset()}}]),f})();f(u,{blur:!0,focus:!0,update:!0}),m.exports=u},328,[4,5,329]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=r(d[1]),s=r(d[2]),_=r(d[3]),o=r(d[4]),v=r(d[5])({__types:!0});var E={emit:function(t,n,s,_,o,v,E){return this.__getEventEmitter().emit(t,n,s,_,o,v,E)},emitAndHold:function(t,n,s,_,o,v,E){return this.__getEventEmitter().emitAndHold(t,n,s,_,o,v,E)},addListener:function(t,n,s){return this.__getEventEmitter().addListener(t,n,s)},once:function(t,n,s){return this.__getEventEmitter().once(t,n,s)},addRetroactiveListener:function(t,n,s){return this.__getEventEmitter().addRetroactiveListener(t,n,s)},addListenerMap:function(t,n){return this.__getEventEmitter().addListenerMap(t,n)},addRetroactiveListenerMap:function(t,n){return this.__getEventEmitter().addListenerMap(t,n)},removeAllListeners:function(){this.__getEventEmitter().removeAllListeners()},removeCurrentListener:function(){this.__getEventEmitter().removeCurrentListener()},releaseHeldEventType:function(t){this.__getEventEmitter().releaseHeldEventType(t)},__getEventEmitter:function(){if(!this.__eventEmitter){var t=new n,o=new _;this.__eventEmitter=new s(t,o)}return this.__eventEmitter}};m.exports=function(n,s){o(s,'Must supply set of valid event types');var _=n.prototype||n;o(!_.__eventEmitter,'An active emitter is already mixed in');var u=n.constructor;u&&o(u===Object||u===Function,'Mix EventEmitter into a class, not an instance'),_.hasOwnProperty(v)?t(_.__types,s):_.__types?_.__types=t({},_.__types,s):_.__types=s,t(_,E)}},329,[24,48,330,331,16,332]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=r(d[1]),s=(function(){function s(n,l){t(this,s),this._emitter=n,this._eventHolder=l,this._currentEventToken=null,this._emittingHeldEvents=!1}return n(s,[{key:"addListener",value:function(t,n,s){return this._emitter.addListener(t,n,s)}},{key:"once",value:function(t,n,s){return this._emitter.once(t,n,s)}},{key:"addRetroactiveListener",value:function(t,n,s){var l=this._emitter.addListener(t,n,s);return this._emittingHeldEvents=!0,this._eventHolder.emitToListener(t,n,s),this._emittingHeldEvents=!1,l}},{key:"removeAllListeners",value:function(t){this._emitter.removeAllListeners(t)}},{key:"removeCurrentListener",value:function(){this._emitter.removeCurrentListener()}},{key:"listeners",value:function(t){return this._emitter.listeners(t)}},{key:"emit",value:function(t){for(var n,s=arguments.length,l=new Array(s>1?s-1:0),o=1;o1?l-1:0),u=1;u1?v-1:0),u=1;u=n.length)break;_=n[x++]}else{if((x=n.next()).done)break;_=x.value}var b=_,y=(0,u.default)(b,2),S=y[0],v=y[1];l[S]=v()}var p={},k=t._fileSources,D=Array.isArray(k),E=0;for(k=D?k:k["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var h;if(D){if(E>=k.length)break;h=k[E++]}else{if((E=k.next()).done)break;h=E.value}var B=h,A=(0,u.default)(B,2),R=A[0],w=A[1];p[R]=w()}return f('BugReporting extraData:',l),null!=o.default&&null!=o.default.setExtraData&&o.default.setExtraData(l,p),null!=c.default&&null!=c.default.setExtraData&&c.default.setExtraData(l,'From BugReporting.js'),{extras:l,files:p}}}]),t})();_._extraSources=new Map,_._fileSources=new Map,_._subscription=null,_._redboxSubscription=null,m.exports=_},339,[3,25,4,5,340,341,45,156,342]); -__d(function(g,r,i,a,m,e,d){var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var u=t(r(d[1])).get('BugReporting');e.default=u},340,[2,22]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var u=t(r(d[1])).get('RedBox');e.default=u},341,[2,22]); -__d(function(g,r,i,a,m,e,d){'use strict';m.exports=function(){try{return"React tree dumps have been temporarily disabled while React is upgraded to Fiber."}catch(t){return'Failed to dump react tree: '+t}}},342,[]); -__d(function(g,r,i,a,m,e,d){'use strict';var n=[],t={name:'default'},c={setActiveScene:function(c){t=c,n.forEach(function(n){return n(t)})},getActiveScene:function(){return t},addActiveSceneChangedListener:function(t){return n.push(t),{remove:function(){n=n.filter(function(n){return t!==n})}}}};m.exports=c},343,[]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=t(r(d[1])),l=t(r(d[2])),o=t(r(d[3])),c=r(d[4]),p=r(d[5]),u=r(d[6]),s=r(d[7]);r(d[8]),m.exports=function(t,f,v,_,E,T,x){var A;s(v,'Expect to have a valid rootTag, instead got ',v);var R=p.createElement(o.default.Provider,{value:null!=(A=x)?A:l.default},p.createElement(c,{rootTag:v,WrapperComponent:_},p.createElement(t,(0,n.default)({},f,{rootTag:v})),!0===E&&!0===T?p.createElement(u,null):null));l.default.startTimespan('renderApplication_React_render'),E?r(d[9]).render(R,v):r(d[10]).render(R,v),l.default.stopTimespan('renderApplication_React_render')}},344,[3,24,154,345,302,59,346,16,347,348,92]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),c=r(d[1])(r(d[2])),n=t(r(d[3])),o=c.createContext(n.default);m.exports=o},345,[3,2,59,154]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=r(d[1]),o=r(d[2]),c=r(d[3]);var f=n.create({container:{alignItems:'center',justifyContent:'center',backgroundColor:'rgba(0,0,0, 0.25)',position:'absolute',top:0,right:0,padding:2},text:{fontSize:6,color:'#ffffff'}});m.exports=function(){return t.createElement(c,{style:f.container},t.createElement(o,{style:f.text},"FABRIC"))}},346,[59,62,199,90]); -__d(function(g,r,i,a,m,e,d){'use strict';var n,t=r(d[0]),o=r(d[1]);function v(){}if(t.isTV){var u=new o,f=new Set;u.enable(this,function(t,o){if(o&&'menu'===o.eventType){for(var v=!0,u=Array.from(f.values()).reverse(),s=0;sthis.eventPool.length&&this.eventPool.push(e)}function G(e){e.eventPool=[],e.getPooled=q,e.release=$}o(X.prototype,{preventDefault:function(){this.defaultPrevented=!0;var e=this.nativeEvent;e&&(e.preventDefault?e.preventDefault():"unknown"!=typeof e.returnValue&&(e.returnValue=!1),this.isDefaultPrevented=Y)},stopPropagation:function(){var e=this.nativeEvent;e&&(e.stopPropagation?e.stopPropagation():"unknown"!=typeof e.cancelBubble&&(e.cancelBubble=!0),this.isPropagationStopped=Y)},persist:function(){this.isPersistent=Y},isPersistent:V,destructor:function(){var e,t=this.constructor.Interface;for(e in t)this[e]=null;this.nativeEvent=this._targetInst=this.dispatchConfig=null,this.isPropagationStopped=this.isDefaultPrevented=V,this._dispatchInstances=this._dispatchListeners=null}}),X.Interface={type:null,target:null,currentTarget:function(){return null},eventPhase:null,bubbles:null,cancelable:null,timeStamp:function(e){return e.timeStamp||Date.now()},defaultPrevented:null,isTrusted:null},X.extend=function(e){function t(){}function n(){return r.apply(this,arguments)}var r=this;t.prototype=r.prototype;var i=new t;return o(i,n.prototype),n.prototype=i,n.prototype.constructor=n,n.Interface=o({},r.Interface,e),n.extend=r.extend,G(n),n},G(X);var J=X.extend({touchHistory:function(){return null}});function K(e){return"topTouchStart"===e}function Z(e){return"topTouchMove"===e}var ee=["topTouchStart"],te=["topTouchMove"],ne=["topTouchCancel","topTouchEnd"],re=[],ie={touchBank:re,numberActiveTouches:0,indexOfSingleActiveTouch:-1,mostRecentTimeStamp:0};function le(e){return e.timeStamp||e.timestamp}function ae(e){if(null==(e=e.identifier))throw f(Error("Touch object is missing identifier."));return e}function oe(e){var t=ae(e),n=re[t];n?(n.touchActive=!0,n.startPageX=e.pageX,n.startPageY=e.pageY,n.startTimeStamp=le(e),n.currentPageX=e.pageX,n.currentPageY=e.pageY,n.currentTimeStamp=le(e),n.previousPageX=e.pageX,n.previousPageY=e.pageY,n.previousTimeStamp=le(e)):(n={touchActive:!0,startPageX:e.pageX,startPageY:e.pageY,startTimeStamp:le(e),currentPageX:e.pageX,currentPageY:e.pageY,currentTimeStamp:le(e),previousPageX:e.pageX,previousPageY:e.pageY,previousTimeStamp:le(e)},re[t]=n),ie.mostRecentTimeStamp=le(e)}function ue(e){var t=re[ae(e)];t?(t.touchActive=!0,t.previousPageX=t.currentPageX,t.previousPageY=t.currentPageY,t.previousTimeStamp=t.currentTimeStamp,t.currentPageX=e.pageX,t.currentPageY=e.pageY,t.currentTimeStamp=le(e),ie.mostRecentTimeStamp=le(e)):console.warn("Cannot record touch move without a touch start.\nTouch Move: %s\n","Touch Bank: %s",se(e),fe())}function ce(e){var t=re[ae(e)];t?(t.touchActive=!1,t.previousPageX=t.currentPageX,t.previousPageY=t.currentPageY,t.previousTimeStamp=t.currentTimeStamp,t.currentPageX=e.pageX,t.currentPageY=e.pageY,t.currentTimeStamp=le(e),ie.mostRecentTimeStamp=le(e)):console.warn("Cannot record touch end without a touch start.\nTouch End: %s\n","Touch Bank: %s",se(e),fe())}function se(e){return JSON.stringify({identifier:e.identifier,pageX:e.pageX,pageY:e.pageY,timestamp:le(e)})}function fe(){var e=JSON.stringify(re.slice(0,20));return 20 component."));return n=St,St+=2,{node:ct(n,"RCTRawText",t,{text:e},r)}}var Pt=setTimeout,Ct=clearTimeout;function _t(e){var t=e.node,n=Ke(null,Ye,{style:{display:"none"}},e.canonical.viewConfig.validAttributes);return{node:pt(t,n),canonical:e.canonical}}var Rt=/^(.*)[\\\/]/;function Nt(e){var t="";do{e:switch(e.tag){case 3:case 4:case 6:case 7:case 10:case 9:var n="";break e;default:var r=e._debugOwner,i=e._debugSource,l=Oe(e.type);n=null,r&&(n=Oe(r.type)),r=l,l="",i?l=" (at "+i.fileName.replace(Rt,"")+":"+i.lineNumber+")":n&&(l=" (created by "+n+")"),n="\n in "+(r||"Unknown")+l}t+=n,e=e.return}while(e);return t}new Set;var It=[],zt=-1;function Ut(e){0>zt||(e.current=It[zt],It[zt]=null,zt--)}function Mt(e,t){It[++zt]=e.current,e.current=t}var At={},Dt={current:At},Ft={current:!1},jt=At;function Ot(e,t){var n=e.type.contextTypes;if(!n)return At;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var i,l={};for(i in n)l[i]=t[i];return r&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=l),l}function Wt(e){return null!==(e=e.childContextTypes)&&void 0!==e}function Ht(e){Ut(Ft),Ut(Dt)}function Bt(e){Ut(Ft),Ut(Dt)}function Qt(e,t,n){if(Dt.current!==At)throw f(Error("Unexpected context found on stack. This error is likely caused by a bug in React. Please file an issue."));Mt(Dt,t),Mt(Ft,n)}function Lt(e,t,n){var r=e.stateNode;if(e=t.childContextTypes,"function"!=typeof r.getChildContext)return n;for(var i in r=r.getChildContext())if(!(i in e))throw f(Error((Oe(t)||"Unknown")+'.getChildContext(): key "'+i+'" is not defined in childContextTypes.'));return o({},n,r)}function Yt(e){var t=e.stateNode;return t=t&&t.__reactInternalMemoizedMergedChildContext||At,jt=Dt.current,Mt(Dt,t),Mt(Ft,Ft.current),!0}function Vt(e,t,n){var r=e.stateNode;if(!r)throw f(Error("Expected to have an instance by this point. This error is likely caused by a bug in React. Please file an issue."));n?(t=Lt(e,t,jt),r.__reactInternalMemoizedMergedChildContext=t,Ut(Ft),Ut(Dt),Mt(Dt,t)):Ut(Ft),Mt(Ft,n)}var Xt=s.unstable_runWithPriority,qt=s.unstable_scheduleCallback,$t=s.unstable_cancelCallback,Gt=s.unstable_shouldYield,Jt=s.unstable_requestPaint,Kt=s.unstable_now,Zt=s.unstable_getCurrentPriorityLevel,en=s.unstable_ImmediatePriority,tn=s.unstable_UserBlockingPriority,nn=s.unstable_NormalPriority,rn=s.unstable_LowPriority,ln=s.unstable_IdlePriority,an={},on=void 0!==Jt?Jt:function(){},un=null,cn=null,sn=!1,fn=Kt(),dn=1e4>fn?Kt:function(){return Kt()-fn};function pn(){switch(Zt()){case en:return 99;case tn:return 98;case nn:return 97;case rn:return 96;case ln:return 95;default:throw f(Error("Unknown priority level."))}}function hn(e){switch(e){case 99:return en;case 98:return tn;case 97:return nn;case 96:return rn;case 95:return ln;default:throw f(Error("Unknown priority level."))}}function mn(e,t){return e=hn(e),Xt(e,t)}function gn(e,t,n){return e=hn(e),qt(e,t,n)}function yn(e){return null===un?(un=[e],cn=qt(en,bn)):un.push(e),an}function vn(){null!==cn&&$t(cn),bn()}function bn(){if(!sn&&null!==un){sn=!0;var e=0;try{var t=un;mn(99,function(){for(;e=(e=10*(1073741821-t)-10*(1073741821-e))?99:250>=e?98:5250>=e?97:95}function En(e,t){return e===t&&(0!==e||1/e==1/t)||e!=e&&t!=t}var xn=Object.prototype.hasOwnProperty;function Sn(e,t){if(En(e,t))return!0;if("object"!=typeof e||null===e||"object"!=typeof t||null===t)return!1;var n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return!1;for(r=0;r=t&&(hi=!0),e.firstContext=null)}function An(e,t){if(Rn!==e&&!1!==t&&0!==t)if("number"==typeof t&&1073741823!==t||(Rn=e,t=1073741823),t={context:e,observedBits:t,next:null},null===_n){if(null===Cn)throw f(Error("Context can only be read while React is rendering. In classes, you can read it in the render method or getDerivedStateFromProps. In function components, you can read it directly in the function body, but not inside Hooks like useReducer() or useMemo()."));_n=t,Cn.dependencies={expirationTime:0,firstContext:t,responders:null}}else _n=_n.next=t;return e._currentValue2}var Dn=!1;function Fn(e){return{baseState:e,firstUpdate:null,lastUpdate:null,firstCapturedUpdate:null,lastCapturedUpdate:null,firstEffect:null,lastEffect:null,firstCapturedEffect:null,lastCapturedEffect:null}}function jn(e){return{baseState:e.baseState,firstUpdate:e.firstUpdate,lastUpdate:e.lastUpdate,firstCapturedUpdate:null,lastCapturedUpdate:null,firstEffect:null,lastEffect:null,firstCapturedEffect:null,lastCapturedEffect:null}}function On(e,t){return{expirationTime:e,suspenseConfig:t,tag:0,payload:null,callback:null,next:null,nextEffect:null}}function Wn(e,t){null===e.lastUpdate?e.firstUpdate=e.lastUpdate=t:(e.lastUpdate.next=t,e.lastUpdate=t)}function Hn(e,t){var n=e.alternate;if(null===n){var r=e.updateQueue,i=null;null===r&&(r=e.updateQueue=Fn(e.memoizedState))}else r=e.updateQueue,i=n.updateQueue,null===r?null===i?(r=e.updateQueue=Fn(e.memoizedState),i=n.updateQueue=Fn(n.memoizedState)):r=e.updateQueue=jn(i):null===i&&(i=n.updateQueue=jn(r));null===i||r===i?Wn(r,t):null===r.lastUpdate||null===i.lastUpdate?(Wn(r,t),Wn(i,t)):(Wn(r,t),i.lastUpdate=t)}function Bn(e,t){var n=e.updateQueue;null===(n=null===n?e.updateQueue=Fn(e.memoizedState):Qn(e,n)).lastCapturedUpdate?n.firstCapturedUpdate=n.lastCapturedUpdate=t:(n.lastCapturedUpdate.next=t,n.lastCapturedUpdate=t)}function Qn(e,t){var n=e.alternate;return null!==n&&t===n.updateQueue&&(t=e.updateQueue=jn(t)),t}function Ln(e,t,n,r,i,l){switch(n.tag){case 1:return"function"==typeof(e=n.payload)?e.call(l,r,i):e;case 3:e.effectTag=-2049&e.effectTag|64;case 0:if(null===(i="function"==typeof(e=n.payload)?e.call(l,r,i):e)||void 0===i)break;return o({},r,i);case 2:Dn=!0}return r}function Yn(e,t,n,r,i){Dn=!1;for(var l=(t=Qn(e,t)).baseState,a=null,o=0,u=t.firstUpdate,c=l;null!==u;){var s=u.expirationTime;sm?(g=f,f=null):g=f.sibling;var y=p(i,f,o[m],u);if(null===y){null===f&&(f=g);break}e&&f&&null===y.alternate&&t(i,f),a=l(y,a,m),null===s?c=y:s.sibling=y,s=y,f=g}if(m===o.length)return n(i,f),c;if(null===f){for(;mg?(y=m,m=null):y=m.sibling;var b=p(i,m,v.value,u);if(null===b){null===m&&(m=y);break}e&&m&&null===b.alternate&&t(i,m),a=l(b,a,g),null===s?c=b:s.sibling=b,s=b,m=y}if(v.done)return n(i,m),c;if(null===m){for(;!v.done;g++,v=o.next())null!==(v=d(i,v.value,u))&&(a=l(v,a,g),null===s?c=v:s.sibling=v,s=v);return c}for(m=r(i,m);!v.done;g++,v=o.next())null!==(v=h(m,i,g,v.value,u))&&(e&&null!==v.alternate&&m.delete(null===v.key?g:v.key),a=l(v,a,g),null===s?c=v:s.sibling=v,s=v);return e&&m.forEach(function(e){return t(i,e)}),c}return function(e,r,l,o){var u="object"==typeof l&&null!==l&&l.type===Pe&&null===l.key;u&&(l=l.props.children);var c="object"==typeof l&&null!==l;if(c)switch(l.$$typeof){case we:e:{for(c=l.key,u=r;null!==u;){if(u.key===c){if(7===u.tag?l.type===Pe:u.elementType===l.type){n(e,u.sibling),(r=i(u,l.type===Pe?l.props.children:l.props)).ref=rr(e,u,l),r.return=e,e=r;break e}n(e,u);break}t(e,u),u=u.sibling}l.type===Pe?((r=oa(l.props.children,e.mode,o,l.key)).return=e,e=r):((o=aa(l.type,l.key,l.props,null,e.mode,o)).ref=rr(e,r,l),o.return=e,e=o)}return a(e);case ke:e:{for(u=l.key;null!==r;){if(r.key===u){if(4===r.tag&&r.stateNode.containerInfo===l.containerInfo&&r.stateNode.implementation===l.implementation){n(e,r.sibling),(r=i(r,l.children||[])).return=e,e=r;break e}n(e,r);break}t(e,r),r=r.sibling}(r=ca(l,e.mode,o)).return=e,e=r}return a(e)}if("string"==typeof l||"number"==typeof l)return l=""+l,null!==r&&6===r.tag?(n(e,r.sibling),(r=i(r,l)).return=e,e=r):(n(e,r),(r=ua(l,e.mode,o)).return=e,e=r),a(e);if(nr(l))return m(e,r,l,o);if(je(l))return g(e,r,l,o);if(c&&ir(e,l),void 0===l&&!u)switch(e.tag){case 1:case 0:throw e=e.type,f(Error((e.displayName||e.name||"Component")+"(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null."))}return n(e,r)}}var ar=lr(!0),or=lr(!1),ur={},cr={current:ur},sr={current:ur},fr={current:ur};function dr(e){if(e===ur)throw f(Error("Expected host context to exist. This error is likely caused by a bug in React. Please file an issue."));return e}function pr(e,t){Mt(fr,t),Mt(sr,e),Mt(cr,ur),Ut(cr),Mt(cr,{isInAParentText:!1})}function hr(e){Ut(cr),Ut(sr),Ut(fr)}function mr(e){dr(fr.current);var t=dr(cr.current),n=e.type;n="AndroidTextInput"===n||"RCTMultilineTextInputView"===n||"RCTSinglelineTextInputView"===n||"RCTText"===n||"RCTVirtualText"===n,t!==(n=t.isInAParentText!==n?{isInAParentText:n}:t)&&(Mt(sr,e),Mt(cr,n))}function gr(e){sr.current===e&&(Ut(cr),Ut(sr))}var yr=1,vr=1,br=2,Tr={current:0};function Er(e){for(var t=e;null!==t;){if(13===t.tag){if(null!==t.memoizedState)return t}else if(19===t.tag&&void 0!==t.memoizedProps.revealOrder){if(0!=(64&t.effectTag))return t}else if(null!==t.child){t.child.return=t,t=t.child;continue}if(t===e)break;for(;null===t.sibling;){if(null===t.return||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}return null}function xr(e,t){return{responder:e,props:t}}var Sr=0,wr=2,kr=4,Pr=8,Cr=16,_r=32,Rr=64,Nr=128,Ir=xe.ReactCurrentDispatcher,zr=0,Ur=null,Mr=null,Ar=null,Dr=null,Fr=null,jr=null,Or=0,Wr=null,Hr=0,Br=!1,Qr=null,Lr=0;function Yr(){throw f(Error("Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem."))}function Vr(e,t){if(null===t)return!1;for(var n=0;nOr&&(Or=s)):(Wl(s,u.suspenseConfig),l=u.eagerReducer===e?u.eagerState:e(l,u.action)),a=u,u=u.next}while(null!==u&&u!==r);c||(o=a,i=l),En(l,t.memoizedState)||(hi=!0),t.memoizedState=l,t.baseUpdate=o,t.baseState=i,n.lastRenderedState=l}return[t.memoizedState,n.dispatch]}function Zr(e,t,n,r){return e={tag:e,create:t,destroy:n,deps:r,next:null},null===Wr?(Wr={lastEffect:null}).lastEffect=e.next=e:null===(t=Wr.lastEffect)?Wr.lastEffect=e.next=e:(n=t.next,t.next=e,e.next=n,Wr.lastEffect=e),e}function ei(e,t,n,r){var i=$r();Hr|=e,i.memoizedState=Zr(t,n,void 0,void 0===r?null:r)}function ti(e,t,n,r){var i=Gr();r=void 0===r?null:r;var l=void 0;if(null!==Mr){var a=Mr.memoizedState;if(l=a.destroy,null!==r&&Vr(r,a.deps))return void Zr(Sr,n,l,r)}Hr|=e,i.memoizedState=Zr(t,n,l,r)}function ni(e,t){return"function"==typeof t?(e=e(),t(e),function(){t(null)}):null!==t&&void 0!==t?(e=e(),t.current=e,function(){t.current=null}):void 0}function ri(){}function ii(e,t,n){if(!(25>Lr))throw f(Error("Too many re-renders. React limits the number of renders to prevent an infinite loop."));var r=e.alternate;if(e===Ur||null!==r&&r===Ur)if(Br=!0,e={expirationTime:zr,suspenseConfig:null,action:n,eagerReducer:null,eagerState:null,next:null},null===Qr&&(Qr=new Map),void 0===(n=Qr.get(t)))Qr.set(t,e);else{for(t=n;null!==t.next;)t=t.next;t.next=e}else{var i=Nl(),l=qn.suspense;l={expirationTime:i=Il(i,e,l),suspenseConfig:l,action:n,eagerReducer:null,eagerState:null,next:null};var a=t.last;if(null===a)l.next=l;else{var o=a.next;null!==o&&(l.next=o),a.next=l}if(t.last=l,0===e.expirationTime&&(null===r||0===r.expirationTime)&&null!==(r=t.lastRenderedReducer))try{var u=t.lastRenderedState,c=r(u,n);if(l.eagerReducer=r,l.eagerState=c,En(c,u))return}catch(e){}zl(e,i)}}var li={readContext:An,useCallback:Yr,useContext:Yr,useEffect:Yr,useImperativeHandle:Yr,useLayoutEffect:Yr,useMemo:Yr,useReducer:Yr,useRef:Yr,useState:Yr,useDebugValue:Yr,useResponder:Yr},ai={readContext:An,useCallback:function(e,t){return $r().memoizedState=[e,void 0===t?null:t],e},useContext:An,useEffect:function(e,t){return ei(516,192,e,t)},useImperativeHandle:function(e,t,n){return n=null!==n&&void 0!==n?n.concat([e]):null,ei(4,36,ni.bind(null,t,e),n)},useLayoutEffect:function(e,t){return ei(4,36,e,t)},useMemo:function(e,t){var n=$r();return t=void 0===t?null:t,e=e(),n.memoizedState=[e,t],e},useReducer:function(e,t,n){var r=$r();return t=void 0!==n?n(t):t,r.memoizedState=r.baseState=t,e=(e=r.queue={last:null,dispatch:null,lastRenderedReducer:e,lastRenderedState:t}).dispatch=ii.bind(null,Ur,e),[r.memoizedState,e]},useRef:function(e){return e={current:e},$r().memoizedState=e},useState:function(e){var t=$r();return"function"==typeof e&&(e=e()),t.memoizedState=t.baseState=e,e=(e=t.queue={last:null,dispatch:null,lastRenderedReducer:Jr,lastRenderedState:e}).dispatch=ii.bind(null,Ur,e),[t.memoizedState,e]},useDebugValue:ri,useResponder:xr},oi={readContext:An,useCallback:function(e,t){var n=Gr();t=void 0===t?null:t;var r=n.memoizedState;return null!==r&&null!==t&&Vr(t,r[1])?r[0]:(n.memoizedState=[e,t],e)},useContext:An,useEffect:function(e,t){return ti(516,192,e,t)},useImperativeHandle:function(e,t,n){return n=null!==n&&void 0!==n?n.concat([e]):null,ti(4,36,ni.bind(null,t,e),n)},useLayoutEffect:function(e,t){return ti(4,36,e,t)},useMemo:function(e,t){var n=Gr();t=void 0===t?null:t;var r=n.memoizedState;return null!==r&&null!==t&&Vr(t,r[1])?r[0]:(e=e(),n.memoizedState=[e,t],e)},useReducer:Kr,useRef:function(){return Gr().memoizedState},useState:function(e){return Kr(Jr)},useDebugValue:ri,useResponder:xr},ui=null,ci=null,si=!1;function fi(e,t){switch(e.tag){case 5:return null!==(t=ot(e.type,e.pendingProps))&&(e.stateNode=t,!0);case 6:return null!==(t=ot(e.pendingProps))&&(e.stateNode=t,!0);case 13:default:return!1}}function di(e){if(si){var t=ci;if(t){var n=t;if(!fi(e,t)){if(!(t=ot())||!fi(e,t))return e.effectTag|=2,si=!1,void(ui=e);var r=ui,i=na(5,null,null,0);i.elementType="DELETED",i.type="DELETED",i.stateNode=n,i.return=r,i.effectTag=8,null!==r.lastEffect?(r.lastEffect.nextEffect=i,r.lastEffect=i):r.firstEffect=r.lastEffect=i}ui=e,ci=ot()}else e.effectTag|=2,si=!1,ui=e}}var pi=xe.ReactCurrentOwner,hi=!1;function mi(e,t,n,r){t.child=null===e?or(t,null,n,r):ar(t,e.child,n,r)}function gi(e,t,n,r,i){n=n.render;var l=t.ref;return Mn(t,i),r=Xr(e,t,n,r,l,i),null===e||hi?(t.effectTag|=1,mi(e,t,r,i),t.child):(t.updateQueue=e.updateQueue,t.effectTag&=-517,e.expirationTime<=i&&(e.expirationTime=0),_i(e,t,i))}function yi(e,t,n,r,i,l){if(null===e){var a=n.type;return"function"!=typeof a||ra(a)||void 0!==a.defaultProps||null!==n.compare||void 0!==n.defaultProps?((e=aa(n.type,null,r,null,t.mode,l)).ref=t.ref,e.return=t,t.child=e):(t.tag=15,t.type=a,vi(e,t,a,r,i,l))}return a=e.child,it)&&Pl.set(e,t))}}function Ul(e,t){e.expirationTimei.firstPendingTime&&(i.firstPendingTime=t),0===(e=i.lastPendingTime)||t=t)&&(gn(97,function(){return n._onComplete(),null}),!0)}function Fl(){if(null!==Pl){var e=Pl;Pl=null,e.forEach(function(e,t){yn(Ol.bind(null,t,e))}),vn()}}function jl(e,t){e.finishedWork=null,e.finishedExpirationTime=0;var n=e.timeoutHandle;if(-1!==n&&(e.timeoutHandle=-1,Ct(n)),null!==cl)for(n=cl.return;null!==n;){var r=n;switch(r.tag){case 1:var i=r.type.childContextTypes;null!==i&&void 0!==i&&Ht();break;case 3:hr(),Bt();break;case 5:gr(r);break;case 4:hr();break;case 13:case 19:Ut(Tr);break;case 10:zn(r)}n=n.return}ul=e,cl=la(e.current,null),sl=t,fl=nl,pl=dl=1073741823,hl=null,ml=!1}function Ol(e,t,n){if((48&ol)!==Ki)throw f(Error("Should not already be working."));if(e.firstPendingTime component higher in the tree to provide a loading indicator or placeholder to display."+Nt(u))}fl!==al&&(fl=rl),c=Di(c,u),u=o;do{switch(u.tag){case 3:u.effectTag|=2048,u.expirationTime=s,Bn(u,s=Xi(u,c,s));break e;case 1:if(d=c,a=u.type,o=u.stateNode,0==(64&u.effectTag)&&("function"==typeof a.getDerivedStateFromError||null!==o&&"function"==typeof o.componentDidCatch&&(null===El||!El.has(o)))){u.effectTag|=2048,u.expirationTime=s,Bn(u,s=qi(u,d,s));break e}}u=u.return}while(null!==u)}cl=Bl(l)}if(ol=r,Nn(),Gi.current=i,null!==cl)return Ol.bind(null,e,t)}if(e.finishedWork=e.current.alternate,e.finishedExpirationTime=t,Dl(e,t))return null;switch(ul=null,fl){case nl:throw f(Error("Should have a work-in-progress."));case rl:return(r=e.lastPendingTime)(n=r-n)&&(n=0),t<(n=(120>n?120:480>n?480:1080>n?1080:1920>n?1920:3e3>n?3e3:4320>n?4320:1960*$i(n/1960))-n)&&(n=t)),10=(t=0|(i=hl).busyMinDurationMs)?t=0:(n=0|i.busyDelayMs,t=(r=dn()-(10*(1073741821-r)-(0|i.timeoutMs||5e3)))<=n?0:n+t-r),10i.tailExpiration&&1r&&(r=l),a>r&&(r=a),i=i.sibling;n.childExpirationTime=r}if(null!==t)return t;null!==e&&0==(1024&e.effectTag)&&(null===e.firstEffect&&(e.firstEffect=cl.firstEffect),null!==cl.lastEffect&&(null!==e.lastEffect&&(e.lastEffect.nextEffect=cl.firstEffect),e.lastEffect=cl.lastEffect),1i?l:i,e.firstPendingTime=i,i=n?ki(e,t,n):(Mt(Tr,Tr.current&yr),null!==(t=_i(e,t,n))?t.sibling:null);Mt(Tr,Tr.current&yr);break;case 19:if(r=t.childExpirationTime>=n,0!=(64&e.effectTag)){if(r)return Ci(e,t,n);t.effectTag|=64}var i=t.memoizedState;if(null!==i&&(i.rendering=null,i.tail=null),Mt(Tr,Tr.current),!r)return null}return _i(e,t,n)}}else hi=!1;switch(t.expirationTime=0,t.tag){case 2:if(r=t.type,null!==e&&(e.alternate=null,t.alternate=null,t.effectTag|=2),e=t.pendingProps,i=Ot(t,Dt.current),Mn(t,n),i=Xr(null,t,r,e,i,n),t.effectTag|=1,"object"==typeof i&&null!==i&&"function"==typeof i.render&&void 0===i.$$typeof){if(t.tag=1,qr(),Wt(r)){var l=!0;Yt(t)}else l=!1;t.memoizedState=null!==i.state&&void 0!==i.state?i.state:null;var a=r.getDerivedStateFromProps;"function"==typeof a&&Gn(t,r,a,e),i.updater=Jn,t.stateNode=i,i._reactInternalFiber=t,tr(t,r,e,n),t=xi(null,t,r,!0,l,n)}else t.tag=0,mi(null,t,i,n),t=t.child;return t;case 16:switch(i=t.elementType,null!==e&&(e.alternate=null,t.alternate=null,t.effectTag|=2),e=t.pendingProps,i=kn(i),t.type=i,l=t.tag=ia(i),e=wn(i,e),l){case 0:t=Ti(null,t,i,e,n);break;case 1:t=Ei(null,t,i,e,n);break;case 11:t=gi(null,t,i,e,n);break;case 14:t=yi(null,t,i,wn(i.type,e),r,n);break;default:throw f(Error("Element type is invalid. Received a promise that resolves to: "+i+". Lazy element type must resolve to a class or function."))}return t;case 0:return r=t.type,i=t.pendingProps,Ti(e,t,r,i=t.elementType===r?i:wn(r,i),n);case 1:return r=t.type,i=t.pendingProps,Ei(e,t,r,i=t.elementType===r?i:wn(r,i),n);case 3:if(Si(t),null===(r=t.updateQueue))throw f(Error("If the root does not have an updateQueue, we should have already bailed out. This error is likely caused by a bug in React. Please file an issue."));return i=null!==(i=t.memoizedState)?i.element:null,Yn(t,r,t.pendingProps,null,n),(r=t.memoizedState.element)===i?t=_i(e,t,n):(mi(e,t,r,n),t=t.child),t;case 5:return mr(t),null===e&&di(t),r=t.pendingProps.children,bi(e,t),mi(e,t,r,n),t.child;case 6:return null===e&&di(t),null;case 13:return ki(e,t,n);case 4:return pr(t,t.stateNode.containerInfo),r=t.pendingProps,null===e?t.child=ar(t,null,r,n):mi(e,t,r,n),t.child;case 11:return r=t.type,i=t.pendingProps,gi(e,t,r,i=t.elementType===r?i:wn(r,i),n);case 7:return mi(e,t,t.pendingProps,n),t.child;case 8:case 12:return mi(e,t,t.pendingProps.children,n),t.child;case 10:e:{if(r=t.type._context,i=t.pendingProps,a=t.memoizedProps,In(t,l=i.value),null!==a){var o=a.value;if(0===(l=En(o,l)?0:0|("function"==typeof r._calculateChangedBits?r._calculateChangedBits(o,l):1073741823))){if(a.children===i.children&&!Ft.current){t=_i(e,t,n);break e}}else for(null!==(o=t.child)&&(o.return=t);null!==o;){var u=o.dependencies;if(null!==u){a=o.child;for(var c=u.firstContext;null!==c;){if(c.context===r&&0!=(c.observedBits&l)){1===o.tag&&((c=On(n,null)).tag=2,Hn(o,c)),o.expirationTimeo&&(s+=c&&u?v.currentPageX:c&&!u?v.currentPageY:!c&&u?v.previousPageX:v.previousPageY,h=1);else for(var C=0;C=o){s+=c&&u?l.currentPageX:c&&!u?l.currentPageY:!c&&u?l.previousPageX:l.previousPageY,h++}}return h>0?s/h:n.noCentroid},currentCentroidXOfTouchesChangedAfter:function(t,o){return n.centroidDimension(t,o,!0,!0)},currentCentroidYOfTouchesChangedAfter:function(t,o){return n.centroidDimension(t,o,!1,!0)},previousCentroidXOfTouchesChangedAfter:function(t,o){return n.centroidDimension(t,o,!0,!1)},previousCentroidYOfTouchesChangedAfter:function(t,o){return n.centroidDimension(t,o,!1,!1)},currentCentroidX:function(t){return n.centroidDimension(t,0,!0,!0)},currentCentroidY:function(t){return n.centroidDimension(t,0,!1,!0)},noCentroid:-1};m.exports=n},364,[]); -__d(function(g,r,i,a,m,e,d){'use strict';var n=r(d[0]),s=n(r(d[1])),o=n(r(d[2])),t=n(r(d[3])),E=n(r(d[4])),A=n(r(d[5])),u=n(r(d[6])),_=n(r(d[7])),S=(r(d[8]),Object.freeze({GRANTED:'granted',DENIED:'denied',NEVER_ASK_AGAIN:'never_ask_again'})),l=Object.freeze({READ_CALENDAR:'android.permission.READ_CALENDAR',WRITE_CALENDAR:'android.permission.WRITE_CALENDAR',CAMERA:'android.permission.CAMERA',READ_CONTACTS:'android.permission.READ_CONTACTS',WRITE_CONTACTS:'android.permission.WRITE_CONTACTS',GET_ACCOUNTS:'android.permission.GET_ACCOUNTS',ACCESS_FINE_LOCATION:'android.permission.ACCESS_FINE_LOCATION',ACCESS_COARSE_LOCATION:'android.permission.ACCESS_COARSE_LOCATION',RECORD_AUDIO:'android.permission.RECORD_AUDIO',READ_PHONE_STATE:'android.permission.READ_PHONE_STATE',CALL_PHONE:'android.permission.CALL_PHONE',READ_CALL_LOG:'android.permission.READ_CALL_LOG',WRITE_CALL_LOG:'android.permission.WRITE_CALL_LOG',ADD_VOICEMAIL:'com.android.voicemail.permission.ADD_VOICEMAIL',USE_SIP:'android.permission.USE_SIP',PROCESS_OUTGOING_CALLS:'android.permission.PROCESS_OUTGOING_CALLS',BODY_SENSORS:'android.permission.BODY_SENSORS',SEND_SMS:'android.permission.SEND_SMS',RECEIVE_SMS:'android.permission.RECEIVE_SMS',READ_SMS:'android.permission.READ_SMS',RECEIVE_WAP_PUSH:'android.permission.RECEIVE_WAP_PUSH',RECEIVE_MMS:'android.permission.RECEIVE_MMS',READ_EXTERNAL_STORAGE:'android.permission.READ_EXTERNAL_STORAGE',WRITE_EXTERNAL_STORAGE:'android.permission.WRITE_EXTERNAL_STORAGE'}),R=(function(){function n(){(0,t.default)(this,n),this.PERMISSIONS=l,this.RESULTS=S}return(0,E.default)(n,[{key:"checkPermission",value:function(n){return console.warn('"PermissionsAndroid.checkPermission" is deprecated. Use "PermissionsAndroid.check" instead'),console.warn('"PermissionsAndroid" module works only for Android platform.'),Promise.resolve(!1)}},{key:"check",value:function(n){return console.warn('"PermissionsAndroid" module works only for Android platform.'),Promise.resolve(!1)}},{key:"requestPermission",value:function(n,s){var t;return o.default.async(function(E){for(;;)switch(E.prev=E.next){case 0:return console.warn('"PermissionsAndroid.requestPermission" is deprecated. Use "PermissionsAndroid.request" instead'),console.warn('"PermissionsAndroid" module works only for Android platform.'),E.abrupt("return",Promise.resolve(!1));case 4:return E.next=6,o.default.awrap(this.request(n,s));case 6:return t=E.sent,E.abrupt("return",t===this.RESULTS.GRANTED);case 8:case"end":return E.stop()}},null,this)}},{key:"request",value:function(n,t){return o.default.async(function(E){for(;;)switch(E.prev=E.next){case 0:return console.warn('"PermissionsAndroid" module works only for Android platform.'),E.abrupt("return",Promise.resolve(this.RESULTS.DENIED));case 3:if((0,_.default)(u.default,'PermissionsAndroid is not installed correctly.'),!t){E.next=10;break}return E.next=7,o.default.awrap(u.default.shouldShowRequestPermissionRationale(n));case 7:if(!E.sent||!A.default){E.next=10;break}return E.abrupt("return",new Promise(function(o,E){var _=(0,s.default)({},t);A.default.showAlert(_,function(){return E(new Error('Error showing rationale'))},function(){return o(u.default.requestPermission(n))})}));case 10:return E.abrupt("return",u.default.requestPermission(n));case 11:case"end":return E.stop()}},null,this)}},{key:"requestMultiple",value:function(n){return console.warn('"PermissionsAndroid" module works only for Android platform.'),Promise.resolve({})}}]),n})();R=new R,m.exports=R},365,[3,53,270,4,5,143,366,16,57]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var o=t(r(d[1])).get('PermissionsAndroid');e.default=o},366,[2,22]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),o=t(r(d[1])),n=t(r(d[2])),l=t(r(d[3])),u=r(d[4]),c=r(d[5]),s=new u(l.default),f=new Map,v=(function(){function t(n){var l=this;(0,o.default)(this,t),this._data={},this._remoteNotificationCompleteCallbackCalled=!1,this._isRemote=n.remote,this._isRemote&&(this._notificationId=n.notificationId),n.remote?Object.keys(n).forEach(function(t){var o=n[t];'aps'===t?(l._alert=o.alert,l._sound=o.sound,l._badgeCount=o.badge,l._category=o.category,l._contentAvailable=o['content-available'],l._threadID=o['thread-id']):l._data[t]=o}):(this._badgeCount=n.applicationIconBadgeNumber,this._sound=n.soundName,this._alert=n.alertBody,this._data=n.userInfo,this._category=n.category)}return(0,n.default)(t,null,[{key:"presentLocalNotification",value:function(t){c(l.default,'PushNotificationManager is not available.'),l.default.presentLocalNotification(t)}},{key:"scheduleLocalNotification",value:function(t){c(l.default,'PushNotificationManager is not available.'),l.default.scheduleLocalNotification(t)}},{key:"cancelAllLocalNotifications",value:function(){c(l.default,'PushNotificationManager is not available.'),l.default.cancelAllLocalNotifications()}},{key:"removeAllDeliveredNotifications",value:function(){c(l.default,'PushNotificationManager is not available.'),l.default.removeAllDeliveredNotifications()}},{key:"getDeliveredNotifications",value:function(t){c(l.default,'PushNotificationManager is not available.'),l.default.getDeliveredNotifications(t)}},{key:"removeDeliveredNotifications",value:function(t){c(l.default,'PushNotificationManager is not available.'),l.default.removeDeliveredNotifications(t)}},{key:"setApplicationIconBadgeNumber",value:function(t){c(l.default,'PushNotificationManager is not available.'),l.default.setApplicationIconBadgeNumber(t)}},{key:"getApplicationIconBadgeNumber",value:function(t){c(l.default,'PushNotificationManager is not available.'),l.default.getApplicationIconBadgeNumber(t)}},{key:"cancelLocalNotifications",value:function(t){c(l.default,'PushNotificationManager is not available.'),l.default.cancelLocalNotifications(t)}},{key:"getScheduledLocalNotifications",value:function(t){c(l.default,'PushNotificationManager is not available.'),l.default.getScheduledLocalNotifications(t)}},{key:"addEventListener",value:function(o,n){var l;c('notification'===o||'register'===o||'registrationError'===o||'localNotification'===o,'PushNotificationIOS only supports `notification`, `register`, `registrationError`, and `localNotification` events'),'notification'===o?l=s.addListener("remoteNotificationReceived",function(o){n(new t(o))}):'localNotification'===o?l=s.addListener("localNotificationReceived",function(o){n(new t(o))}):'register'===o?l=s.addListener("remoteNotificationsRegistered",function(t){n(t.deviceToken)}):'registrationError'===o&&(l=s.addListener("remoteNotificationRegistrationError",function(t){n(t)})),f.set(o,l)}},{key:"removeEventListener",value:function(t,o){c('notification'===t||'register'===t||'registrationError'===t||'localNotification'===t,'PushNotificationIOS only supports `notification`, `register`, `registrationError`, and `localNotification` events');var n=f.get(t);n&&(n.remove(),f.delete(t))}},{key:"requestPermissions",value:function(t){var o={};return o=t?{alert:!!t.alert,badge:!!t.badge,sound:!!t.sound}:{alert:!0,badge:!0,sound:!0},c(l.default,'PushNotificationManager is not available.'),l.default.requestPermissions(o)}},{key:"abandonPermissions",value:function(){c(l.default,'PushNotificationManager is not available.'),l.default.abandonPermissions()}},{key:"checkPermissions",value:function(t){c('function'==typeof t,'Must provide a valid callback'),c(l.default,'PushNotificationManager is not available.'),l.default.checkPermissions(t)}},{key:"getInitialNotification",value:function(){return c(l.default,'PushNotificationManager is not available.'),l.default.getInitialNotification().then(function(o){return o&&new t(o)})}}]),(0,n.default)(t,[{key:"finish",value:function(t){this._isRemote&&this._notificationId&&!this._remoteNotificationCompleteCallbackCalled&&(this._remoteNotificationCompleteCallbackCalled=!0,c(l.default,'PushNotificationManager is not available.'),l.default.onFinishRemoteNotification(this._notificationId,t))}},{key:"getMessage",value:function(){return this._alert}},{key:"getSound",value:function(){return this._sound}},{key:"getCategory",value:function(){return this._category}},{key:"getAlert",value:function(){return this._alert}},{key:"getContentAvailable",value:function(){return this._contentAvailable}},{key:"getBadgeCount",value:function(){return this._badgeCount}},{key:"getData",value:function(){return this._data}},{key:"getThreadID",value:function(){return this._threadID}}]),t})();v.FetchResult={NewData:'UIBackgroundFetchResultNewData',NoData:'UIBackgroundFetchResultNoData',ResultFailed:'UIBackgroundFetchResultFailed'},m.exports=v},367,[3,4,5,368,125,16]); -__d(function(g,r,i,a,m,e,d){var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var o=t(r(d[1])).get('PushNotificationManager');e.default=o},368,[2,22]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),s=t(r(d[1])),n=t(r(d[2])),c=r(d[3]),l=r(d[4]),u=[],o={_settings:n.default&&n.default.getConstants().settings,get:function(t){return this._settings[t]},set:function(t){this._settings=(0,s.default)(this._settings,t),n.default.setValues(t)},watchKeys:function(t,s){'string'==typeof t&&(t=[t]),l(Array.isArray(t),'keys should be a string or array of strings');var n=u.length;return u.push({keys:t,callback:s}),n},clearWatch:function(t){t1&&void 0!==arguments[1]?arguments[1]:{};return u('object'==typeof t&&null!==t,'Content to share must be a valid object'),u('string'==typeof t.url||'string'==typeof t.message,'At least one of URL and message is required'),u('object'==typeof n&&null!==n,'Options must be a valid object'),new Promise(function(o,l){var f=c(n.tintColor);u(s.default,'NativeActionSheetManager is not registered on iOS, but it should be.'),s.default.showShareActionSheetWithOptions({message:'string'==typeof t.message?t.message:void 0,url:'string'==typeof t.url?t.url:void 0,subject:n.subject,tintColor:null!=f?f:void 0,excludedActivityTypes:n.excludedActivityTypes},function(t){return l(t)},function(t,n){o(t?{action:'sharedAction',activityType:n}:{action:'dismissedAction'})})})}}]),t})();l.sharedAction='sharedAction',l.dismissedAction='dismissedAction',m.exports=l},371,[3,4,5,335,372,57,16,84]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var u=t(r(d[1])).get('ShareModule');e.default=u},372,[2,22]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),u=t(r(d[1])),n=t(r(d[2])),f=t(r(d[3])),l=t(r(d[4])),s=t(r(d[5])),c=(function(t){function s(){return(0,u.default)(this,s),(0,n.default)(this,(0,f.default)(s).apply(this,arguments))}return(0,l.default)(s,t),s})(r(d[6]));m.exports=new c(s.default)},373,[3,4,6,9,10,323,125]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=t(r(d[1])),s=t(r(d[2])),u=t(r(d[3])),o=t(r(d[4])),c=(function(){function t(){(0,s.default)(this,t)}return(0,u.default)(t,null,[{key:"open",value:function(t){return n.default.async(function(n){for(;;)switch(n.prev=n.next){case 0:if(!o.default){n.next=4;break}return n.abrupt("return",o.default.open(t));case 4:return n.abrupt("return",Promise.reject({message:'TimePickerAndroid is not supported on this platform.'}));case 5:case"end":return n.stop()}},null,this)}}]),t})();c.timeSetAction='timeSetAction',c.dismissedAction='dismissedAction',m.exports=c},374,[3,270,4,5,375]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var u=t(r(d[1])).get('TimePickerAndroid');e.default=u},375,[2,22]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),o={show:function(o,s){t(!1,'ToastAndroid is not supported on this platform.')},showWithGravity:function(o,s,n){t(!1,'ToastAndroid is not supported on this platform.')},showWithGravityAndOffset:function(o,s,n,p,f){t(!1,'ToastAndroid is not supported on this platform.')}};m.exports=o},376,[18]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]),n=r(d[1]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){var t=u.default.get('window'),n=f.useState(!1)[1].bind(null,function(t){return!t}),c=f.useState(t)[0];return f.useEffect(function(){return u.default.addEventListener('change',n),u.default.get('window')!==c&&n(),function(){u.default.removeEventListener('change',n)}},[n,c]),t};var u=n(r(d[2])),f=t(r(d[3]))},377,[2,3,64,59]); -__d(function(g,r,i,a,m,e,d){'use strict';var A=r(d[0])({BOM:"\ufeff",BULLET:"\u2022",BULLET_SP:"\xa0\u2022\xa0",MIDDOT:"\xb7",MIDDOT_SP:"\xa0\xb7\xa0",MIDDOT_KATAKANA:"\u30fb",MDASH:"\u2014",MDASH_SP:"\xa0\u2014\xa0",NDASH:"\u2013",NDASH_SP:"\xa0\u2013\xa0",NBSP:"\xa0",PIZZA:"\ud83c\udf55",TRIANGLE_LEFT:"\u25c0",TRIANGLE_RIGHT:"\u25b6"});m.exports=A},378,[37]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0])(r(d[1])),n=(r(d[2]),!1),o=0;function u(u){var l=arguments.length>1&&void 0!==arguments[1]&&arguments[1];n||(n=!0,0===u[0]&&(t.default.vibrate(),u=u.slice(1)),0!==u.length?setTimeout(function(){return f(++o,u,l,1)},u[0]):n=!1)}function f(u,l,v,c){if(n&&u===o){if(t.default.vibrate(),c>=l.length){if(!v)return void(n=!1);c=0}setTimeout(function(){return f(u,l,v,c+1)},l[c])}}var l={vibrate:function(){var o=arguments.length>0&&void 0!==arguments[0]?arguments[0]:400,f=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(!n)if('number'==typeof o)t.default.vibrate();else{if(!Array.isArray(o))throw new Error('Vibration pattern should be a number or array');u(o,f)}},cancel:function(){n=!1}};m.exports=l},379,[3,380,57]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var n=t(r(d[1])).getEnforcing('Vibration');e.default=n},380,[2,22]); -__d(function(g,r,i,a,m,e,d){'use strict';var n,t=r(d[0]),u=r(d[1]),l=r(d[2]),o=r(d[3]),s=r(d[4]);n=(function(n){function c(){return t(this,c),l(this,o(c).apply(this,arguments))}return s(c,n),u(c,[{key:"render",value:function(){return null}}],[{key:"ignoreWarnings",value:function(n){}},{key:"install",value:function(){}},{key:"uninstall",value:function(){}}]),c})(r(d[5]).Component),m.exports=n},381,[4,5,6,9,10,59]); -__d(function(g,r,i,a,m,e,d){'use strict';var n=r(d[0]),s=n.shape({x:n.number,y:n.number});m.exports=s},382,[71]); -__d(function(g,r,i,a,m,e,d){var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var n=t(r(d[1])),u=t(r(d[2])),c=r(d[3]),l=c.NativeModules.RNBackgroundTimer,o=new c.NativeEventEmitter(l),s=new((function(){function t(){var u=this;(0,n.default)(this,t),this.uniqueId=0,this.callbacks={},o.addListener('backgroundTimer.timeout',function(t){if(u.callbacks[t]){var n=u.callbacks[t].callback;u.callbacks[t].interval?l.setTimeout(t,u.callbacks[t].timeout):delete u.callbacks[t],n()}})}return(0,u.default)(t,[{key:"start",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0;return l.start(t)}},{key:"stop",value:function(){return l.stop()}},{key:"runBackgroundTimer",value:function(t,n){var u=this,l=c.Platform.select({ios:function(){return c.NativeAppEventEmitter},android:function(){return c.DeviceEventEmitter}})();this.start(0),this.backgroundListener=l.addListener('backgroundTimer',function(){u.backgroundListener.remove(),u.backgroundClockMethod(t,n)})}},{key:"backgroundClockMethod",value:function(t,n){var u=this;this.backgroundTimer=this.setTimeout(function(){t(),u.backgroundClockMethod(t,n)},n)}},{key:"stopBackgroundTimer",value:function(){this.stop(),this.clearTimeout(this.backgroundTimer)}},{key:"setTimeout",value:function(t,n){this.uniqueId+=1;var u=this.uniqueId;return this.callbacks[u]={callback:t,interval:!1,timeout:n},l.setTimeout(u,n),u}},{key:"clearTimeout",value:function(t){this.callbacks[t]&&delete this.callbacks[t]}},{key:"setInterval",value:function(t,n){this.uniqueId+=1;var u=this.uniqueId;return this.callbacks[u]={callback:t,interval:!0,timeout:n},l.setTimeout(u,n),u}},{key:"clearInterval",value:function(t){this.callbacks[t]&&delete this.callbacks[t]}}]),t})());e.default=s},383,[3,4,5,15]); -__d(function(g,r,i,a,m,e,d){!(function(t){'use strict';var s=!1;if(!t.forceJURL)try{var h=new URL('b','http://a');h.pathname='c%20d',s='http://a/c%20d'===h.href}catch(t){}if(!s){var n=Object.create(null);n.ftp=21,n.file=0,n.gopher=70,n.http=80,n.https=443,n.ws=80,n.wss=443;var o=Object.create(null);o['%2e']='.',o['.%2e']='..',o['%2e.']='..',o['%2e%2e']='..';var l=void 0,_=/[a-zA-Z]/,c=/[a-zA-Z0-9\+\-\.]/;I.prototype={toString:function(){return this.href},get href(){if(this._isInvalid)return this._url;var t='';return''==this._username&&null==this._password||(t=this._username+(null!=this._password?':'+this._password:'')+'@'),this.protocol+(this._isRelative?'//'+t+this.host:'')+this.pathname+this._query+this._fragment},set href(t){k.call(this),b.call(this,t)},get protocol(){return this._scheme+':'},set protocol(t){this._isInvalid||b.call(this,t+':','scheme start')},get host(){return this._isInvalid?'':this._port?this._host+':'+this._port:this._host},set host(t){!this._isInvalid&&this._isRelative&&b.call(this,t,'host')},get hostname(){return this._host},set hostname(t){!this._isInvalid&&this._isRelative&&b.call(this,t,'hostname')},get port(){return this._port},set port(t){!this._isInvalid&&this._isRelative&&b.call(this,t,'port')},get pathname(){return this._isInvalid?'':this._isRelative?'/'+this._path.join('/'):this._schemeData},set pathname(t){!this._isInvalid&&this._isRelative&&(this._path=[],b.call(this,t,'relative path start'))},get search(){return this._isInvalid||!this._query||'?'==this._query?'':this._query},set search(t){!this._isInvalid&&this._isRelative&&(this._query='?','?'==t[0]&&(t=t.slice(1)),b.call(this,t,'query'))},get hash(){return this._isInvalid||!this._fragment||'#'==this._fragment?'':this._fragment},set hash(t){this._isInvalid||(this._fragment='#','#'==t[0]&&(t=t.slice(1)),b.call(this,t,'fragment'))},get origin(){var t;if(this._isInvalid||!this._scheme)return'';switch(this._scheme){case'data':case'file':case'javascript':case'mailto':return'null'}return(t=this.host)?this._scheme+'://'+t:''}};var p=t.URL;p&&(I.createObjectURL=function(t){return p.createObjectURL.apply(p,arguments)},I.revokeObjectURL=function(t){p.revokeObjectURL(t)}),t.URL=I}function u(t){return void 0!==n[t]}function f(){k.call(this),this._isInvalid=!0}function v(t){return''==t&&f.call(this),t.toLowerCase()}function y(t){var s=t.charCodeAt(0);return s>32&&s<127&&-1==[34,35,60,62,63,96].indexOf(s)?t:encodeURIComponent(t)}function w(t){var s=t.charCodeAt(0);return s>32&&s<127&&-1==[34,35,60,62,96].indexOf(s)?t:encodeURIComponent(t)}function b(t,s,h){function p(t){L.push(t)}var b=s||'scheme start',k=0,I='',R=!1,q=!1,L=[];t:for(;(t[k-1]!=l||0==k)&&!this._isInvalid;){var U=t[k];switch(b){case'scheme start':if(!U||!_.test(U)){if(s){p('Invalid scheme.');break t}I='',b='no scheme';continue}I+=U.toLowerCase(),b='scheme';break;case'scheme':if(U&&c.test(U))I+=U.toLowerCase();else{if(':'!=U){if(s){if(l==U)break t;p('Code point not allowed in scheme: '+U);break t}I='',k=0,b='no scheme';continue}if(this._scheme=I,I='',s)break t;u(this._scheme)&&(this._isRelative=!0),b='file'==this._scheme?'relative':this._isRelative&&h&&h._scheme==this._scheme?'relative or authority':this._isRelative?'authority first slash':'scheme data'}break;case'scheme data':'?'==U?(this._query='?',b='query'):'#'==U?(this._fragment='#',b='fragment'):l!=U&&'\t'!=U&&'\n'!=U&&'\r'!=U&&(this._schemeData+=y(U));break;case'no scheme':if(h&&u(h._scheme)){b='relative';continue}p('Missing scheme.'),f.call(this);break;case'relative or authority':if('/'!=U||'/'!=t[k+1]){p('Expected /, got: '+U),b='relative';continue}b='authority ignore slashes';break;case'relative':if(this._isRelative=!0,'file'!=this._scheme&&(this._scheme=h._scheme),l==U){this._host=h._host,this._port=h._port,this._path=h._path.slice(),this._query=h._query,this._username=h._username,this._password=h._password;break t}if('/'==U||'\\'==U)'\\'==U&&p('\\ is an invalid code point.'),b='relative slash';else if('?'==U)this._host=h._host,this._port=h._port,this._path=h._path.slice(),this._query='?',this._username=h._username,this._password=h._password,b='query';else{if('#'!=U){var C=t[k+1],j=t[k+2];('file'!=this._scheme||!_.test(U)||':'!=C&&'|'!=C||l!=j&&'/'!=j&&'\\'!=j&&'?'!=j&&'#'!=j)&&(this._host=h._host,this._port=h._port,this._username=h._username,this._password=h._password,this._path=h._path.slice(),this._path.pop()),b='relative path';continue}this._host=h._host,this._port=h._port,this._path=h._path.slice(),this._query=h._query,this._fragment='#',this._username=h._username,this._password=h._password,b='fragment'}break;case'relative slash':if('/'!=U&&'\\'!=U){'file'!=this._scheme&&(this._host=h._host,this._port=h._port,this._username=h._username,this._password=h._password),b='relative path';continue}'\\'==U&&p('\\ is an invalid code point.'),b='file'==this._scheme?'file host':'authority ignore slashes';break;case'authority first slash':if('/'!=U){p("Expected '/', got: "+U),b='authority ignore slashes';continue}b='authority second slash';break;case'authority second slash':if(b='authority ignore slashes','/'!=U){p("Expected '/', got: "+U);continue}break;case'authority ignore slashes':if('/'!=U&&'\\'!=U){b='authority';continue}p('Expected authority, got: '+U);break;case'authority':if('@'==U){R&&(p('@ already seen.'),I+='%40'),R=!0;for(var O=0;O=s.length)break;v=s[y++]}else{if((y=s.next()).done)break;v=y.value}var c=v,k=(0,n.default)(c,2),_=k[0],P=k[1];_=_.substring(o),t.hasOwnProperty(_)||(t[_]=P)}l()})})})}},{key:"key",value:function(t){var n=Object.keys(this);return t=n+o||n?new java.lang.String(t,n,o)+'':t}function u(t,n){t.currentElement?t.currentElement.appendChild(n):t.doc.appendChild(n)}t.prototype.parseFromString=function(t,c){var l=this.options,s=new h,u=l.domBuilder||new o,f=l.errorHandler,p=l.locator,D=l.xmlns||{},E={lt:'<',gt:'>',amp:'&',quot:'"',apos:"'"};return p&&u.setDocumentLocator(p),s.errorHandler=n(f,u,p),s.domBuilder=l.domBuilder||u,/\/x?html?$/.test(c)&&(E.nbsp='\xa0',E.copy='\xa9',D['']='http://www.w3.org/1999/xhtml'),D.xml=D.xml||'http://www.w3.org/XML/1998/namespace',t?s.parse(t,D,E):s.errorHandler.error("invalid doc source"),u.doc},o.prototype={startDocument:function(){this.doc=(new f).createDocument(null,null,null),this.locator&&(this.doc.documentURI=this.locator.systemId)},startElement:function(t,n,o,l){var s=this.doc,h=s.createElementNS(t,o||n),f=l.length;u(this,h),this.currentElement=h,this.locator&&c(this.locator,h);for(var p=0;p65535){var n=55296+((t-=65536)>>10),s=56320+(1023&t);return String.fromCharCode(n,s)}return String.fromCharCode(t)}function l(t){var n=t.slice(1,-1);return n in s?s[n]:'#'===n.charAt(0)?o(parseInt(n.substr(1).replace('x','0x'))):(u.error('entity not found:'+t),t)}function f(n){if(n>O){var s=t.substring(O,n).replace(/&#?\w+;/g,l);x&&h(O),c.characters(s,0,n-O),O=n}}function h(n,s){for(;n>=w&&(s=b.exec(t));)p=s.index,w=p+s[0].length,x.lineNumber++;x.columnNumber=n-p+1}for(var p=0,w=0,b=/.*(?:\r\n?|\n)|.*$/g,x=c.locator,E=[{currentNSMap:n}],M={},O=0;;){try{var T=t.indexOf('<',O);if(T<0){if(!t.substr(O).match(/^\s*$/)){var S=c.doc,q=S.createTextNode(t.substr(O));S.appendChild(q),c.currentElement=q}return}switch(T>O&&f(T),t.charAt(T+1)){case'/':var y=t.indexOf('>',T+3),_=t.substring(T+2,y),I=E.pop();y<0?(_=t.substring(T+2).replace(/[\s<].*/,''),u.error("end tag name: "+_+' is not complete:'+I.tagName),y=T+1+_.length):_.match(/\sO?O=y:f(Math.max(T,O)+1)}}function v(t,n){return n.lineNumber=t.lineNumber,n.columnNumber=t.columnNumber,n}function N(t,n,s,b,x,v){for(var N,F=++n,D=c;;){var k=t.charAt(F);switch(k){case'=':if(D===u)N=t.slice(n,F),D=l;else{if(D!==o)throw new Error('attribute equal must after attrName');D=l}break;case'\'':case'"':if(D===l||D===u){if(D===u&&(v.warning('attribute value must after "="'),N=t.slice(n,F)),n=F+1,!((F=t.indexOf(k,n))>0))throw new Error('attribute value no end \''+k+'\' match');E=t.slice(n,F).replace(/&#?\w+;/g,x),s.add(N,E,n-1),D=h}else{if(D!=f)throw new Error('attribute value must after "="');E=t.slice(n,F).replace(/&#?\w+;/g,x),s.add(N,E,n),v.warning('attribute "'+N+'" missed start quot('+k+')!!'),n=F+1,D=h}break;case'/':switch(D){case c:s.setTagName(t.slice(n,F));case h:case p:case w:D=w,s.closed=!0;case f:case u:case o:break;default:throw new Error("attribute invalid close char('/')")}break;case'':return v.error('unexpected end of input'),D==c&&s.setTagName(t.slice(n,F)),F;case'>':switch(D){case c:s.setTagName(t.slice(n,F));case h:case p:case w:break;case f:case u:'/'===(E=t.slice(n,F)).slice(-1)&&(s.closed=!0,E=E.slice(0,-1));case o:D===o&&(E=N),D==f?(v.warning('attribute "'+E+'" missed quot(")!!'),s.add(N,E.replace(/&#?\w+;/g,x),n)):('http://www.w3.org/1999/xhtml'===b['']&&E.match(/^(?:disabled|checked|selected)$/i)||v.warning('attribute "'+E+'" missed value!! "'+E+'" instead!!'),s.add(E,E,n));break;case l:throw new Error('attribute value missed!!')}return F;case"\x80":k=' ';default:if(k<=' ')switch(D){case c:s.setTagName(t.slice(n,F)),D=p;break;case u:N=t.slice(n,F),D=o;break;case f:var E=t.slice(n,F).replace(/&#?\w+;/g,x);v.warning('attribute "'+E+'" missed quot(")!!'),s.add(N,E,n);case h:D=p}else switch(D){case o:s.tagName;'http://www.w3.org/1999/xhtml'===b['']&&N.match(/^(?:disabled|checked|selected)$/i)||v.warning('attribute "'+N+'" missed value!! "'+N+'" instead2!!'),s.add(N,N,n),n=F,D=u;break;case h:v.warning('attribute space is required"'+N+'"!!');case p:D=u,n=F;break;case l:D=f,n=F;break;case w:throw new Error("elements closed character '/' and '>' must be connected to")}}F++}}function F(t,n,s){for(var c=t.tagName,u=null,o=t.length;o--;){var l=t[o],f=l.qName,h=l.value;if((x=f.indexOf(':'))>0)var p=l.prefix=f.slice(0,x),w=f.slice(x+1),b='xmlns'===p&&w;else w=f,p=null,b='xmlns'===f&&'';l.localName=w,!1!==b&&(null==u&&(u={},E(s,s={})),s[b]=u[b]=h,l.uri='http://www.w3.org/2000/xmlns/',n.startPrefixMapping(b,h))}for(o=t.length;o--;){(p=(l=t[o]).prefix)&&('xml'===p&&(l.uri='http://www.w3.org/XML/1998/namespace'),'xmlns'!==p&&(l.uri=s[p||'']))}var x;(x=c.indexOf(':'))>0?(p=t.prefix=c.slice(0,x),w=t.localName=c.slice(x+1)):(p=null,w=t.localName=c);var v=t.uri=s[p||''];if(n.startElement(v,w,c,t),!t.closed)return t.currentNSMap=s,t.localNSMap=u,!0;if(n.endElement(v,w,c),u)for(p in u)n.endPrefixMapping(p)}function D(t,n,s,c,u){if(/^(?:script|textarea)$/i.test(s)){var o=t.indexOf('',n),l=t.substring(n+1,o);if(/[&<]/.test(l))return/^script$/i.test(s)?(u.characters(l,0,l.length),o):(l=l.replace(/&#?\w+;/g,c),u.characters(l,0,l.length),o)}return n+1}function k(t,n,s,c){var u=c[s];return null==u&&((u=t.lastIndexOf(''))n?(s.comment(t,n+4,u-n-4),u+3):(c.error("Unclosed comment"),-1):-1;default:if('CDATA['==t.substr(n+3,6)){var u=t.indexOf(']]>',n+9);return s.startCDATA(),s.characters(t,n+9,u-n-9),s.endCDATA(),u+3}var o=O(t,n),l=o.length;if(l>1&&/!doctype/i.test(o[0][0])){var f=o[1][0],h=l>3&&/^public$/i.test(o[2][0])&&o[3][0],p=l>4&&o[4][0],w=o[l-1];return s.startDTD(f,h&&h.replace(/^(['"])(.*?)\1$/,'$2'),p&&p.replace(/^(['"])(.*?)\1$/,'$2')),s.endDTD(),w.index+w[0].length}}return-1}function $(t,n,s){var c=t.indexOf('?>',n);if(c){var u=t.substring(n,c).match(/^<\?(\S*)\s*([\s\S]*?)\s*$/);if(u){u[0].length;return s.processingInstruction(u[1],u[2]),c+2}return-1}return-1}function A(t){}function M(t,n){return t.__proto__=n,t}function O(t,n){var s,c=[],u=/'[^']+'|"[^"]+"|[^\s<>\/=]+=?|(\/?\s*>|<)/g;for(u.lastIndex=n,u.exec(t);s=u.exec(t);)if(c.push(s),s[1])return c}b.prototype={parse:function(t,n,s){var c=this.domBuilder;c.startDocument(),E(n,n={}),x(t,n,s,c,this.errorHandler),c.endDocument()}},A.prototype={setTagName:function(t){if(!s.test(t))throw new Error('invalid tagName:'+t);this.tagName=t},add:function(t,n,c){if(!s.test(t))throw new Error('invalid attribute:'+t);this[this.length++]={qName:t,value:n,offset:c}},length:0,getLocalName:function(t){return this[t].localName},getLocator:function(t){return this[t].locator},getQName:function(t){return this[t].qName},getURI:function(t){return this[t].uri},getValue:function(t){return this[t].value}},M({},M.prototype)instanceof M||(M=function(t,n){function s(){}for(n in s.prototype=n,s=new s,t)s[n]=t[n];return s}),e.XMLReader=b},390,[]); -__d(function(g,r,i,a,m,e,d){function t(t,n){for(var o in t)n[o]=t[o]}function n(n,o){var u=n.prototype;if(Object.create){var s=Object.create(o.prototype);u.__proto__=s}if(!(u instanceof o)){function l(){}l.prototype=o.prototype,t(u,l=new l),n.prototype=u=l}u.constructor!=n&&('function'!=typeof n&&console.error("unknow Class:"+n),u.constructor=n)}var o='http://www.w3.org/1999/xhtml',u={},s=u.ELEMENT_NODE=1,l=u.ATTRIBUTE_NODE=2,c=u.TEXT_NODE=3,h=u.CDATA_SECTION_NODE=4,p=u.ENTITY_REFERENCE_NODE=5,f=u.ENTITY_NODE=6,N=u.PROCESSING_INSTRUCTION_NODE=7,v=u.COMMENT_NODE=8,w=u.DOCUMENT_NODE=9,E=u.DOCUMENT_TYPE_NODE=10,y=u.DOCUMENT_FRAGMENT_NODE=11,b=u.NOTATION_NODE=12,T={},_={},D=(T.INDEX_SIZE_ERR=(_[1]="Index size error",1),T.DOMSTRING_SIZE_ERR=(_[2]="DOMString size error",2),T.HIERARCHY_REQUEST_ERR=(_[3]="Hierarchy request error",3)),S=(T.WRONG_DOCUMENT_ERR=(_[4]="Wrong document",4),T.INVALID_CHARACTER_ERR=(_[5]="Invalid character",5),T.NO_DATA_ALLOWED_ERR=(_[6]="No data allowed",6),T.NO_MODIFICATION_ALLOWED_ERR=(_[7]="No modification allowed",7),T.NOT_FOUND_ERR=(_[8]="Not found",8)),C=(T.NOT_SUPPORTED_ERR=(_[9]="Not supported",9),T.INUSE_ATTRIBUTE_ERR=(_[10]="Attribute in use",10));T.INVALID_STATE_ERR=(_[11]="Invalid state",11),T.SYNTAX_ERR=(_[12]="Syntax error",12),T.INVALID_MODIFICATION_ERR=(_[13]="Invalid modification",13),T.NAMESPACE_ERR=(_[14]="Invalid namespace",14),T.INVALID_ACCESS_ERR=(_[15]="Invalid access",15);function I(t,n){if(n instanceof Error)var o=n;else o=this,Error.call(this,_[t]),this.message=_[t],Error.captureStackTrace&&Error.captureStackTrace(this,I);return o.code=t,n&&(this.message=this.message+": "+n),o}function A(){}function R(t,n){this._node=t,this._refresh=n,x(this)}function x(n){var o=n._node._inc||n._node.ownerDocument._inc;if(n._inc!=o){var u=n._refresh(n._node);he(n,'length',u.length),t(u,n),n._inc=o}}function O(){}function U(t,n){for(var o=t.length;o--;)if(t[o]===n)return o}function M(t,n,o,u){if(u?n[U(n,u)]=o:n[n.length++]=o,t){o.ownerElement=t;var s=t.ownerDocument;s&&(u&&Y(s,t,u),F(s,t,o))}}function B(t,n,o){var u=U(n,o);if(!(u>=0))throw I(S,new Error(t.tagName+'@'+o));for(var s=n.length-1;u'==t&&'>')||'&'==t&&'&'||'"'==t&&'"'||'&#'+t.charCodeAt()+';'}function k(t,n){if(n(t))return!0;if(t=t.firstChild)do{if(k(t,n))return!0}while(t=t.nextSibling)}function j(){}function F(t,n,o){t&&t._inc++,'http://www.w3.org/2000/xmlns/'==o.namespaceURI&&(n._nsMap[o.prefix?o.localName:'']=o.value)}function Y(t,n,o,u){t&&t._inc++,'http://www.w3.org/2000/xmlns/'==o.namespaceURI&&delete n._nsMap[o.prefix?o.localName:'']}function z(t,n,o){if(t&&t._inc){t._inc++;var u=n.childNodes;if(o)u[u.length++]=o;else{for(var s=n.firstChild,l=0;s;)u[l++]=s,s=s.nextSibling;u.length=l}}}function $(t,n){var o=n.previousSibling,u=n.nextSibling;return o?o.nextSibling=u:t.firstChild=u,u?u.previousSibling=o:t.lastChild=o,z(t.ownerDocument,t),n}function X(t,n,o){var u=n.parentNode;if(u&&u.removeChild(n),n.nodeType===y){var s=n.firstChild;if(null==s)return n;var l=n.lastChild}else s=l=n;var c=o?o.previousSibling:t.lastChild;s.previousSibling=c,l.nextSibling=o,c?c.nextSibling=s:t.firstChild=s,null==o?t.lastChild=l:o.previousSibling=l;do{s.parentNode=t}while(s!==l&&(s=s.nextSibling));return z(t.ownerDocument||t,t),n.nodeType==y&&(n.firstChild=n.lastChild=null),n}function G(t,n){var o=n.parentNode;if(o){var u=t.lastChild;o.removeChild(n);u=t.lastChild}u=t.lastChild;return n.parentNode=t,n.previousSibling=u,n.nextSibling=null,u?u.nextSibling=n:t.firstChild=n,t.lastChild=n,z(t.ownerDocument,t,n),n}function H(){this._nsMap={}}function W(){}function q(){}function Z(){}function Q(){}function J(){}function K(){}function ee(){}function te(){}function ne(){}function re(){}function ie(){}function oe(){}function ae(t,n){var o=[],u=9==this.nodeType?this.documentElement:this,s=u.prefix,l=u.namespaceURI;if(l&&null==s&&null==(s=u.lookupPrefix(l)))var c=[{namespace:l,prefix:null}];return se(this,o,t,n,c),o.join('')}function ue(t,n,o){var u=t.prefix||'',s=t.namespaceURI;if(!u&&!s)return!1;if("xml"===u&&"http://www.w3.org/XML/1998/namespace"===s||'http://www.w3.org/2000/xmlns/'==s)return!1;for(var l=o.length;l--;){var c=o[l];if(c.prefix==u)return c.namespace!=s}return!0}function se(t,n,u,f,b){if(f){if(!(t=f(t)))return;if('string'==typeof t)return void n.push(t)}switch(t.nodeType){case s:b||(b=[]);b.length;var T=t.attributes,_=T.length,D=t.firstChild,S=t.tagName;u=o===t.namespaceURI||u,n.push('<',S);for(var C=0;C<_;C++){'xmlns'==(I=T.item(C)).prefix?b.push({prefix:I.localName,namespace:I.value}):'xmlns'==I.nodeName&&b.push({prefix:'',namespace:I.value})}for(C=0;C<_;C++){var I;if(ue(I=T.item(C),0,b)){var A=I.prefix||'',R=I.namespaceURI,x=A?' xmlns:'+A:" xmlns";n.push(x,'="',R,'"'),b.push({prefix:A,namespace:R})}se(I,n,u,f,b)}if(ue(t,0,b)){A=t.prefix||'',R=t.namespaceURI,x=A?' xmlns:'+A:" xmlns";n.push(x,'="',R,'"'),b.push({prefix:A,namespace:R})}if(D||u&&!/^(?:meta|link|img|br|hr|input)$/i.test(S)){if(n.push('>'),u&&/^script$/i.test(S))for(;D;)D.data?n.push(D.data):se(D,n,u,f,b),D=D.nextSibling;else for(;D;)se(D,n,u,f,b),D=D.nextSibling;n.push('')}else n.push('/>');return;case w:case y:for(D=t.firstChild;D;)se(D,n,u,f,b),D=D.nextSibling;return;case l:return n.push(' ',t.name,'="',t.value.replace(/[<&"]/g,V),'"');case c:return n.push(t.data.replace(/[<&]/g,V));case h:return n.push('');case v:return n.push("\x3c!--",t.data,"--\x3e");case E:var O=t.publicId,U=t.systemId;if(n.push('');else if(U&&'.'!=U)n.push(' SYSTEM "',U,'">');else{var M=t.internalSubset;M&&n.push(" [",M,"]"),n.push(">")}return;case N:return n.push("");case p:return n.push('&',t.nodeName,';');default:n.push('??',t.nodeName)}}function le(t,n,o){var u;switch(n.nodeType){case s:(u=n.cloneNode(!1)).ownerDocument=t;case y:break;case l:o=!0}if(u||(u=n.cloneNode(!1)),u.ownerDocument=t,u.parentNode=null,o)for(var c=n.firstChild;c;)u.appendChild(le(t,c,o)),c=c.nextSibling;return u}function ce(t,n,o){var u=new n.constructor;for(var c in n){var h=n[c];'object'!=typeof h&&h!=u[c]&&(u[c]=h)}switch(n.childNodes&&(u.childNodes=new A),u.ownerDocument=t,u.nodeType){case s:var p=n.attributes,f=u.attributes=new O,N=p.length;f._ownerElement=u;for(var v=0;v0},lookupPrefix:function(t){for(var n=this;n;){var o=n._nsMap;if(o)for(var u in o)if(o[u]==t)return u;n=n.nodeType==l?n.ownerDocument:n.parentNode}return null},lookupNamespaceURI:function(t){for(var n=this;n;){var o=n._nsMap;if(o&&t in o)return o[t];n=n.nodeType==l?n.ownerDocument:n.parentNode}return null},isDefaultNamespace:function(t){return null==this.lookupPrefix(t)}},t(u,L),t(u,L.prototype),j.prototype={nodeName:'#document',nodeType:w,doctype:null,documentElement:null,_inc:1,insertBefore:function(t,n){if(t.nodeType==y){for(var o=t.firstChild;o;){var u=o.nextSibling;this.insertBefore(o,n),o=u}return t}return null==this.documentElement&&t.nodeType==s&&(this.documentElement=t),X(this,t,n),t.ownerDocument=this,t},removeChild:function(t){return this.documentElement==t&&(this.documentElement=null),$(this,t)},importNode:function(t,n){return le(this,t,n)},getElementById:function(t){var n=null;return k(this.documentElement,function(o){if(o.nodeType==s&&o.getAttribute('id')==t)return n=o,!0}),n},createElement:function(t){var n=new H;return n.ownerDocument=this,n.nodeName=t,n.tagName=t,n.childNodes=new A,(n.attributes=new O)._ownerElement=n,n},createDocumentFragment:function(){var t=new re;return t.ownerDocument=this,t.childNodes=new A,t},createTextNode:function(t){var n=new Z;return n.ownerDocument=this,n.appendData(t),n},createComment:function(t){var n=new Q;return n.ownerDocument=this,n.appendData(t),n},createCDATASection:function(t){var n=new J;return n.ownerDocument=this,n.appendData(t),n},createProcessingInstruction:function(t,n){var o=new ie;return o.ownerDocument=this,o.tagName=o.target=t,o.nodeValue=o.data=n,o},createAttribute:function(t){var n=new W;return n.ownerDocument=this,n.name=t,n.nodeName=t,n.localName=t,n.specified=!0,n},createEntityReference:function(t){var n=new ne;return n.ownerDocument=this,n.nodeName=t,n},createElementNS:function(t,n){var o=new H,u=n.split(':'),s=o.attributes=new O;return o.childNodes=new A,o.ownerDocument=this,o.nodeName=n,o.tagName=n,o.namespaceURI=t,2==u.length?(o.prefix=u[0],o.localName=u[1]):o.localName=n,s._ownerElement=o,o},createAttributeNS:function(t,n){var o=new W,u=n.split(':');return o.ownerDocument=this,o.nodeName=n,o.name=n,o.namespaceURI=t,o.specified=!0,2==u.length?(o.prefix=u[0],o.localName=u[1]):o.localName=n,o}},n(j,L),H.prototype={nodeType:s,hasAttribute:function(t){return null!=this.getAttributeNode(t)},getAttribute:function(t){var n=this.getAttributeNode(t);return n&&n.value||''},getAttributeNode:function(t){return this.attributes.getNamedItem(t)},setAttribute:function(t,n){var o=this.ownerDocument.createAttribute(t);o.value=o.nodeValue=""+n,this.setAttributeNode(o)},removeAttribute:function(t){var n=this.getAttributeNode(t);n&&this.removeAttributeNode(n)},appendChild:function(t){return t.nodeType===y?this.insertBefore(t,null):G(this,t)},setAttributeNode:function(t){return this.attributes.setNamedItem(t)},setAttributeNodeNS:function(t){return this.attributes.setNamedItemNS(t)},removeAttributeNode:function(t){return this.attributes.removeNamedItem(t.nodeName)},removeAttributeNS:function(t,n){var o=this.getAttributeNodeNS(t,n);o&&this.removeAttributeNode(o)},hasAttributeNS:function(t,n){return null!=this.getAttributeNodeNS(t,n)},getAttributeNS:function(t,n){var o=this.getAttributeNodeNS(t,n);return o&&o.value||''},setAttributeNS:function(t,n,o){var u=this.ownerDocument.createAttributeNS(t,n);u.value=u.nodeValue=""+o,this.setAttributeNode(u)},getAttributeNodeNS:function(t,n){return this.attributes.getNamedItemNS(t,n)},getElementsByTagName:function(t){return new R(this,function(n){var o=[];return k(n,function(u){u===n||u.nodeType!=s||'*'!==t&&u.tagName!=t||o.push(u)}),o})},getElementsByTagNameNS:function(t,n){return new R(this,function(o){var u=[];return k(o,function(l){l===o||l.nodeType!==s||'*'!==t&&l.namespaceURI!==t||'*'!==n&&l.localName!=n||u.push(l)}),u})}},j.prototype.getElementsByTagName=H.prototype.getElementsByTagName,j.prototype.getElementsByTagNameNS=H.prototype.getElementsByTagNameNS,n(H,L),W.prototype.nodeType=l,n(W,L),q.prototype={data:'',substringData:function(t,n){return this.data.substring(t,t+n)},appendData:function(t){t=this.data+t,this.nodeValue=this.data=t,this.length=t.length},insertData:function(t,n){this.replaceData(t,0,n)},appendChild:function(t){throw new Error(_[D])},deleteData:function(t,n){this.replaceData(t,n,"")},replaceData:function(t,n,o){o=this.data.substring(0,t)+o+this.data.substring(t+n),this.nodeValue=this.data=o,this.length=o.length}},n(q,L),Z.prototype={nodeName:"#text",nodeType:c,splitText:function(t){var n=this.data,o=n.substring(t);n=n.substring(0,t),this.data=this.nodeValue=n,this.length=n.length;var u=this.ownerDocument.createTextNode(o);return this.parentNode&&this.parentNode.insertBefore(u,this.nextSibling),u}},n(Z,q),Q.prototype={nodeName:"#comment",nodeType:v},n(Q,q),J.prototype={nodeName:"#cdata-section",nodeType:h},n(J,q),K.prototype.nodeType=E,n(K,L),ee.prototype.nodeType=b,n(ee,L),te.prototype.nodeType=f,n(te,L),ne.prototype.nodeType=p,n(ne,L),re.prototype.nodeName="#document-fragment",re.prototype.nodeType=y,n(re,L),ie.prototype.nodeType=N,n(ie,L),oe.prototype.serializeToString=function(t,n,o){return ae.call(t,n,o)},L.prototype.toString=ae;try{if(Object.defineProperty){function pe(t){switch(t.nodeType){case s:case y:var n=[];for(t=t.firstChild;t;)7!==t.nodeType&&8!==t.nodeType&&n.push(pe(t)),t=t.nextSibling;return n.join('');default:return t.nodeValue}}Object.defineProperty(R.prototype,'length',{get:function(){return x(this),this.$$length}}),Object.defineProperty(L.prototype,'textContent',{get:function(){return pe(this)},set:function(t){switch(this.nodeType){case s:case y:for(;this.firstChild;)this.removeChild(this.firstChild);(t||String(t))&&this.appendChild(this.ownerDocument.createTextNode(t));break;default:this.data=t,this.value=t,this.nodeValue=t}}}),he=function(t,n,o){t['$$'+n]=o}}}catch(t){}e.DOMImplementation=P,e.XMLSerializer=oe},391,[]); -__d(function(g,r,i,a,m,e,d){var o=r(d[0]),l=r(d[1]),t={},n=[],s=o.levels.TRACE;m.exports={addGlobalTransport:function(l){o.addGlobalTransport(l)},removeGlobalTransport:function(l){o.removeGlobalTransport(l)},setGlobalOptions:function(l){o.setGlobalOptions(l)},getLogger:function(l,v,f){var u=new o(s,l,v,f);return l?(t[l]=t[l]||[],t[l].push(u)):n.push(u),u},setLogLevelById:function(o,l){for(var s=l?t[l]||[]:n,v=0;v1&&O.push("<"+h.methodName+">: ");var N=O.concat(f);b.bind(v).apply(v,N)}}}function c(n,o,l,c){this.id=o,this.options=c||{},this.transports=l,this.transports||(this.transports=[]),this.level=t[n];for(var f=Object.keys(t),h=0;h=this.maxEntryLength&&this._flush(!0,!0)},s.prototype.start=function(){this._reschedulePublishInterval()},s.prototype._reschedulePublishInterval=function(){this.storeLogsIntervalID&&(window.clearTimeout(this.storeLogsIntervalID),this.storeLogsIntervalID=null),this.storeLogsIntervalID=window.setTimeout(this._flush.bind(this,!1,!0),this.storeInterval)},s.prototype.flush=function(){this._flush(!1,!0)},s.prototype._flush=function(t,s){this.totalLen>0&&(this.logStorage.isReady()||t)&&(this.logStorage.isReady()?(this.outputCache.length&&(this.outputCache.forEach(function(t){this.logStorage.storeLogs(t)}.bind(this)),this.outputCache=[]),this.logStorage.storeLogs(this.queue)):this.outputCache.push(this.queue),this.queue=[],this.totalLen=0),s&&this._reschedulePublishInterval()},s.prototype.stop=function(){this._flush(!1,!1)},m.exports=s},394,[393]); -__d(function(e,t,i,r,s,a,n){s.exports={_args:[["github:jitsi/react-native#efd2aff5661d75a230e36406b698cfe0ee545be2","/Users/djorkaeff/Downloads/rocket-chat/jitsi-meet"]],_from:"github:jitsi/react-native#efd2aff5661d75a230e36406b698cfe0ee545be2",_id:"react-native@github:jitsi/react-native#efd2aff5661d75a230e36406b698cfe0ee545be2",_inBundle:!1,_integrity:"",_location:"/react-native",_phantomChildren:{"@hapi/joi":"15.1.1","@react-native-community/cli-debugger-ui":"3.0.0","@react-native-community/cli-tools":"3.0.0","@react-native-community/cli-types":"3.0.0","@types/color-name":"1.1.1","@types/istanbul-lib-coverage":"2.0.1","@types/istanbul-reports":"1.1.1","@types/yargs-parser":"15.0.0","color-convert":"1.9.1","command-exists":"1.2.8",commander:"2.20.0",compression:"1.7.4",connect:"3.7.0","core-js":"2.5.3",cosmiconfig:"5.2.0",deepmerge:"3.3.0",didyoumean:"1.2.1",envinfo:"7.5.0",errorhandler:"1.5.1","escape-string-regexp":"1.0.5",execa:"1.0.0","fbjs-css-vars":"1.0.2","fs-extra":"7.0.1",glob:"7.1.2","graceful-fs":"4.1.11",inquirer:"3.3.0","isomorphic-fetch":"2.2.1","js-tokens":"3.0.2",lodash:"4.17.13","loose-envify":"1.3.1",metro:"0.56.4","metro-config":"0.56.4","metro-core":"0.56.4","metro-react-native-babel-transformer":"0.56.4",minimist:"1.2.0",mkdirp:"0.5.1",morgan:"1.9.1","node-notifier":"5.4.3","object-assign":"4.1.1",open:"6.4.0",ora:"3.4.0",plist:"3.0.1",promise:"7.3.1","serve-static":"1.13.2",setimmediate:"1.0.5","shell-quote":"1.6.1","sudo-prompt":"9.1.1",wcwidth:"1.0.1",ws:"1.1.5"},_requested:{type:"git",raw:"github:jitsi/react-native#efd2aff5661d75a230e36406b698cfe0ee545be2",rawSpec:"github:jitsi/react-native#efd2aff5661d75a230e36406b698cfe0ee545be2",saveSpec:"github:jitsi/react-native#efd2aff5661d75a230e36406b698cfe0ee545be2",fetchSpec:null,gitCommittish:"efd2aff5661d75a230e36406b698cfe0ee545be2"},_requiredBy:["/"],_resolved:"github:jitsi/react-native#efd2aff5661d75a230e36406b698cfe0ee545be2",_spec:"github:jitsi/react-native#efd2aff5661d75a230e36406b698cfe0ee545be2",_where:"/Users/djorkaeff/Downloads/rocket-chat/jitsi-meet",bin:{"react-native":"./cli.js"},bugs:{url:"https://github.com/facebook/react-native/issues"},dependencies:{"@babel/runtime":"^7.0.0","@react-native-community/cli":"^3.0.0","@react-native-community/cli-platform-android":"^3.0.0","@react-native-community/cli-platform-ios":"^3.0.0","abort-controller":"^3.0.0",art:"^0.10.0","base64-js":"^1.1.2",connect:"^3.6.5","create-react-class":"^15.6.3","escape-string-regexp":"^1.0.5","event-target-shim":"^5.0.1",fbjs:"^1.0.0","fbjs-scripts":"^1.1.0","hermes-engine":"^0.2.1",invariant:"^2.2.4","jsc-android":"^245459.0.0","metro-babel-register":"^0.56.0","metro-react-native-babel-transformer":"^0.56.0","metro-source-map":"^0.56.0",nullthrows:"^1.1.0","pretty-format":"^24.7.0",promise:"^7.1.1","prop-types":"^15.7.2","react-devtools-core":"^3.6.3","react-refresh":"^0.4.0","regenerator-runtime":"^0.13.2",scheduler:"0.15.0","stacktrace-parser":"^0.1.3","whatwg-fetch":"^3.0.0"},description:"A framework for building native apps using React",detox:{"test-runner":"jest","runner-config":"RNTester/e2e/config.json",specs:"",configurations:{"ios.sim.release":{binaryPath:"RNTester/build/Build/Products/Release-iphonesimulator/RNTester.app/",build:"xcodebuild -workspace RNTester/RNTesterPods.xcworkspace -scheme RNTester -configuration Release -sdk iphonesimulator -derivedDataPath RNTester/build -UseModernBuildSystem=NO -quiet",type:"ios.simulator",name:"iPhone 6s"},"ios.sim.debug":{binaryPath:"RNTester/build/Build/Products/Debug-iphonesimulator/RNTester.app/",build:"xcodebuild -workspace RNTester/RNTesterPods.xcworkspace -scheme RNTester -configuration Debug -sdk iphonesimulator -derivedDataPath RNTester/build -UseModernBuildSystem=NO -quiet",type:"ios.simulator",name:"iPhone 6s"}}},devDependencies:{"@babel/core":"^7.0.0","@babel/generator":"^7.0.0","@react-native-community/eslint-plugin":"1.0.0","@reactions/component":"^2.0.2",async:"^2.4.0","babel-eslint":"10.0.1","clang-format":"^1.2.4",coveralls:"^3.0.2",detox:"12.2.0",eslint:"5.1.0","eslint-config-fb-strict":"24.3.0","eslint-config-fbjs":"2.1.0","eslint-config-prettier":"^6.0.0","eslint-plugin-babel":"^5.3.0","eslint-plugin-eslint-comments":"^3.1.1","eslint-plugin-flowtype":"2.50.3","eslint-plugin-jest":"22.4.1","eslint-plugin-jsx-a11y":"6.2.1","eslint-plugin-prettier":"2.6.2","eslint-plugin-react":"7.12.4","eslint-plugin-react-hooks":"^1.5.1","eslint-plugin-react-native":"3.6.0","eslint-plugin-relay":"1.3.0","flow-bin":"^0.105.0","flow-remove-types":"1.2.3",jest:"^24.8.0","jest-junit":"^6.3.0",jscodeshift:"^0.6.2",mkdirp:"^0.5.1",prettier:"1.17.0",react:"16.9.0","react-test-renderer":"16.9.0",shelljs:"^0.7.8",ws:"^6.1.4",yargs:"^9.0.0"},engines:{node:">=8.3"},files:[".flowconfig","android","cli.js","flow","init.sh","scripts/compose-source-maps.js","scripts/ios-configure-glog.sh","scripts/ios-install-third-party.sh","scripts/launchPackager.bat","scripts/launchPackager.command","scripts/node-binary.sh","scripts/packager.sh","scripts/react-native-xcode.sh","jest-preset.js","jest","lib","rn-get-polyfills.js","Libraries","LICENSE","packager","react-native.config.js","react.gradle","React.podspec","React-Core.podspec","React","ReactAndroid","ReactCommon","README.md","third-party-podspecs","template","local-cli","template.config.js","!template/node_modules","!template/yarn.lock","!template/package-lock.json"],homepage:"https://github.com/facebook/react-native#readme","jest-junit":{outputDirectory:"reports/junit",outputName:"js-test-results.xml"},license:"MIT",main:"Libraries/react-native/react-native-implementation.js",name:"react-native",peerDependencies:{react:"16.9.0"},repository:{type:"git",url:"git+ssh://git@github.com/facebook/react-native.git"},scripts:{"build-ios-e2e":"detox build -c ios.sim.release","clang-format":"clang-format -i --glob=*/**/*.{h,cpp,m,mm}","docker-build-android":"docker build -t reactnativeci/android -f .circleci/Dockerfiles/Dockerfile.android .","docker-setup-android":"docker pull reactnativecommunity/react-native-android",flow:"flow","flow-check-android":"flow check --flowconfig-name .flowconfig.android","flow-check-ios":"flow check",format:"npm run prettier && npm run clang-format","format-check":"prettier --list-different \"./**/*.{js,md,yml}\"",lint:"eslint .","lint-ci":"./scripts/circleci/analyze_code.sh && yarn shellcheck",prettier:"prettier --write \"./**/*.{js,md,yml}\"",shellcheck:"./scripts/circleci/analyze_scripts.sh",start:"react-native start",test:"jest","test-android-all":"yarn run docker-build-android && yarn run test-android-run-unit && yarn run test-android-run-instrumentation && yarn run test-android-run-e2e","test-android-e2e":"yarn run docker-build-android && yarn run test-android-run-e2e","test-android-instrumentation":"yarn run docker-build-android && yarn run test-android-run-instrumentation","test-android-run-e2e":"docker run --privileged -it reactnativeci/android bash .circleci/Dockerfiles/scripts/run-ci-e2e-tests.sh --android --js","test-android-run-instrumentation":"docker run --cap-add=SYS_ADMIN -it reactnativeci/android bash .circleci/Dockerfiles/scripts/run-android-docker-instrumentation-tests.sh","test-android-run-unit":"docker run --cap-add=SYS_ADMIN -it reactnativeci/android bash .circleci/Dockerfiles/scripts/run-android-docker-unit-tests.sh","test-android-unit":"yarn run docker-build-android && yarn run test-android-run-unit","test-ci":"jest --maxWorkers=2 --ci --reporters=\"default\" --reporters=\"jest-junit\"","test-ios":"./scripts/objc-test.sh test","test-ios-e2e":"detox test -c ios.sim.release RNTester/e2e"},version:"0.61.5-jitsi.1"}},395,[]); -__d(function(g,r,i,a,m,e,d){var n=r(d[0]),o=r(d[1]),t=n(r(d[2]));!(function(n){void 0===n.MediaStream&&(n.MediaStream=o.MediaStream),void 0===n.MediaStreamTrack&&(n.MediaStreamTrack=o.MediaStreamTrack),void 0===n.RTCIceCandidate&&(n.RTCIceCandidate=o.RTCIceCandidate),void 0===n.RTCPeerConnection&&(n.RTCPeerConnection=t.default),void 0===n.RTCPeerConnection&&(n.webkitRTCPeerConnection=t.default),void 0===n.RTCSessionDescription&&(n.RTCSessionDescription=o.RTCSessionDescription);var s=n.navigator;s&&(void 0===s.mediaDevices&&(s.mediaDevices=o.mediaDevices),void 0===s.permissions&&(s.permissions=o.permissions))})(g||window||this)},396,[3,397,430]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.registerGlobals=function(){if('object'!=typeof navigator)throw new Error('navigator is not an object');navigator.mediaDevices||(navigator.mediaDevices={});navigator.mediaDevices.getUserMedia=s.default.getUserMedia.bind(s.default),navigator.mediaDevices.enumerateDevices=s.default.enumerateDevices.bind(s.default),g.RTCPeerConnection=n.default,g.RTCIceCandidate=u.default,g.RTCSessionDescription=o.default,g.MediaStream=c.default,g.MediaStreamTrack=l.default},Object.defineProperty(e,"RTCPeerConnection",{enumerable:!0,get:function(){return n.default}}),Object.defineProperty(e,"RTCIceCandidate",{enumerable:!0,get:function(){return u.default}}),Object.defineProperty(e,"RTCSessionDescription",{enumerable:!0,get:function(){return o.default}}),Object.defineProperty(e,"RTCView",{enumerable:!0,get:function(){return f.default}}),Object.defineProperty(e,"MediaStream",{enumerable:!0,get:function(){return c.default}}),Object.defineProperty(e,"MediaStreamTrack",{enumerable:!0,get:function(){return l.default}}),Object.defineProperty(e,"mediaDevices",{enumerable:!0,get:function(){return s.default}}),Object.defineProperty(e,"permissions",{enumerable:!0,get:function(){return b.default}});var n=t(r(d[1])),u=t(r(d[2])),o=t(r(d[3])),f=t(r(d[4])),c=t(r(d[5])),l=t(r(d[6])),s=t(r(d[7])),b=t(r(d[8]))},397,[3,398,417,416,421,403,409,426,429]); -__d(function(g,r,i,a,m,e,d){'use strict';var n=r(d[0]),t=r(d[1]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var o=t(r(d[2])),c=t(r(d[3])),s=t(r(d[4])),u=t(r(d[5])),f=t(r(d[6])),l=t(r(d[7])),v=t(r(d[8])),h=r(d[9]),p=t(r(d[10])),C=t(r(d[11])),_=(t(r(d[12])),t(r(d[13]))),S=t(r(d[14])),E=t(r(d[15])),I=t(r(d[16])),w=t(r(d[17])),k=t(r(d[18])),y=t(r(d[19])),D=n(r(d[20])),O=h.NativeModules.WebRTCModule,L=0,b=(function(n){function t(n){var o;return(0,c.default)(this,t),(o=(0,u.default)(this,(0,f.default)(t).call(this))).signalingState='stable',o.iceGatheringState='new',o.iceConnectionState='new',o._localStreams=[],o._remoteStreams=[],o._dataChannelIds=new Set,o._peerConnectionId=L++,O.peerConnectionInit(n,o._peerConnectionId),o._registerEvents(),o}return(0,l.default)(t,n),(0,s.default)(t,[{key:"addStream",value:function(n){-1===this._localStreams.indexOf(n)&&(O.peerConnectionAddStream(n._reactTag,this._peerConnectionId),this._localStreams.push(n))}},{key:"removeStream",value:function(n){var t=this._localStreams.indexOf(n);-1!==t&&(this._localStreams.splice(t,1),O.peerConnectionRemoveStream(n._reactTag,this._peerConnectionId))}},{key:"createOffer",value:function(n){var t=this;return new Promise(function(o,c){O.peerConnectionCreateOffer(t._peerConnectionId,D.normalizeOfferAnswerOptions(n),function(n,t){n?o(new I.default(t)):c(t)})})}},{key:"createAnswer",value:function(){var n=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return new Promise(function(o,c){O.peerConnectionCreateAnswer(n._peerConnectionId,D.normalizeOfferAnswerOptions(t),function(n,t){n?o(new I.default(t)):c(t)})})}},{key:"setConfiguration",value:function(n){O.peerConnectionSetConfiguration(n,this._peerConnectionId)}},{key:"setLocalDescription",value:function(n){var t=this;return new Promise(function(o,c){O.peerConnectionSetLocalDescription(n.toJSON?n.toJSON():n,t._peerConnectionId,function(s,u){s?(t.localDescription=n,o()):c(u)})})}},{key:"setRemoteDescription",value:function(n){var t=this;return new Promise(function(o,c){O.peerConnectionSetRemoteDescription(n.toJSON?n.toJSON():n,t._peerConnectionId,function(s,u){s?(t.remoteDescription=n,o()):c(u)})})}},{key:"addIceCandidate",value:function(n){var t=this;return new Promise(function(o,c){O.peerConnectionAddICECandidate(n.toJSON?n.toJSON():n,t._peerConnectionId,function(n){n?o():c(new Error('Failed to add ICE candidate'))})})}},{key:"getStats",value:function(n){var t=this;return new Promise(function(o,c){O.peerConnectionGetStats(n&&n.id||'',t._peerConnectionId,function(n,t){if(n)try{var s=JSON.parse(t);o(s)}catch(n){c(n)}else c(new Error(t))})})}},{key:"getLocalStreams",value:function(){return this._localStreams.slice()}},{key:"getRemoteStreams",value:function(){return this._remoteStreams.slice()}},{key:"close",value:function(){O.peerConnectionClose(this._peerConnectionId)}},{key:"_getTrack",value:function(n,t){var o=this._remoteStreams.find(function(t){return t._reactTag===n});return o&&o._tracks.find(function(n){return n.id===t})}},{key:"_unregisterEvents",value:function(){this._subscriptions.forEach(function(n){return n.remove()}),this._subscriptions=[]}},{key:"_registerEvents",value:function(){var n=this;this._subscriptions=[h.DeviceEventEmitter.addListener('peerConnectionOnRenegotiationNeeded',function(t){t.id===n._peerConnectionId&&n.dispatchEvent(new y.default('negotiationneeded'))}),h.DeviceEventEmitter.addListener('peerConnectionIceConnectionChanged',function(t){t.id===n._peerConnectionId&&(n.iceConnectionState=t.iceConnectionState,n.dispatchEvent(new y.default('iceconnectionstatechange')),'closed'===t.iceConnectionState&&n._unregisterEvents())}),h.DeviceEventEmitter.addListener('peerConnectionSignalingStateChanged',function(t){t.id===n._peerConnectionId&&(n.signalingState=t.signalingState,n.dispatchEvent(new y.default('signalingstatechange')))}),h.DeviceEventEmitter.addListener('peerConnectionAddedStream',function(t){if(t.id===n._peerConnectionId){var o=new p.default(t);n._remoteStreams.push(o),n.dispatchEvent(new C.default('addstream',{stream:o}))}}),h.DeviceEventEmitter.addListener('peerConnectionRemovedStream',function(t){if(t.id===n._peerConnectionId){var o=n._remoteStreams.find(function(n){return n._reactTag===t.streamId});if(o){var c=n._remoteStreams.indexOf(o);-1!==c&&n._remoteStreams.splice(c,1)}n.dispatchEvent(new C.default('removestream',{stream:o}))}}),h.DeviceEventEmitter.addListener('mediaStreamTrackMuteChanged',function(t){if(t.peerConnectionId===n._peerConnectionId){var o=n._getTrack(t.streamReactTag,t.trackId);if(o){o.muted=t.muted;var c=t.muted?'mute':'unmute';o.dispatchEvent(new _.default(c,{track:o}))}}}),h.DeviceEventEmitter.addListener('peerConnectionGotICECandidate',function(t){if(t.id===n._peerConnectionId){var o=new w.default(t.candidate),c=new k.default('icecandidate',{candidate:o});n.dispatchEvent(c)}}),h.DeviceEventEmitter.addListener('peerConnectionIceGatheringChanged',function(t){t.id===n._peerConnectionId&&(n.iceGatheringState=t.iceGatheringState,'complete'===n.iceGatheringState&&n.dispatchEvent(new k.default('icecandidate',null)),n.dispatchEvent(new y.default('icegatheringstatechange')))}),h.DeviceEventEmitter.addListener('peerConnectionDidOpenDataChannel',function(t){if(t.id===n._peerConnectionId){var o=t.dataChannel,c=o.id;if('number'==typeof c&&-1!==c){var s=new S.default(n._peerConnectionId,o.label,o);n._dataChannelIds.add(c),n.dispatchEvent(new E.default('datachannel',{channel:s}))}}})]}},{key:"createDataChannel",value:function(n,t){var c,s=this._dataChannelIds;if(t&&'id'in t){if('number'!=typeof(c=t.id))throw new TypeError('DataChannel id must be a number: '+c);if(s.has(c))throw new ResourceInUse('DataChannel id already in use: '+c)}else{for(c=1;c<65535&&s.has(c);++c);t=(0,o.default)({id:c},t)}return O.createDataChannel(this._peerConnectionId,n,t),s.add(c),new S.default(this._peerConnectionId,n,t)}}]),t})((0,v.default)(['connectionstatechange','icecandidate','icecandidateerror','iceconnectionstatechange','icegatheringstatechange','negotiationneeded','signalingstatechange','datachannel','addstream','removestream']));e.default=b},398,[2,3,24,4,5,6,9,10,399,15,403,411,409,412,413,415,416,417,418,419,420]); -__d(function(g,r,i,a,m,e,d){"use strict";var t=r(d[0]),n=r(d[1]),l=r(d[2]),o=t.LISTENERS,u=t.CAPTURE,f=t.BUBBLE,c=t.ATTRIBUTE,s=t.newNode,v=n.defineCustomEventTarget,h=l.createEventWrapper,E=l.STOP_IMMEDIATE_PROPAGATION_FLAG,p="undefined"!=typeof window&&void 0!==window.EventTarget,w=m.exports=function t(){if(!(this instanceof t)){if(1===arguments.length&&Array.isArray(arguments[0]))return v(t,arguments[0]);if(arguments.length>0){for(var n=Array(arguments.length),l=0;l=f.length)break;T=f[h++]}else{if((h=f.next()).done)break;T=h.value}var _=T;o.addTrack(_)}}else if(Array.isArray(t)){y.mediaStreamCreate(o.id);var b=t,p=Array.isArray(b),S=0;for(b=p?b:b["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var A;if(p){if(S>=b.length)break;A=b[S++]}else{if((S=b.next()).done)break;A=S.value}var R=A;o.addTrack(R)}}else{if(!('object'==typeof t&&t.streamId&&t.streamReactTag&&t.tracks))throw new TypeError("invalid type: "+typeof t);o.id=t.streamId,o._reactTag=t.streamReactTag;var w=t.tracks,x=Array.isArray(w),C=0;for(w=x?w:w["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var I;if(x){if(C>=w.length)break;I=w[C++]}else{if((C=w.next()).done)break;I=C.value}var M=I;o._tracks.push(new v.default(M))}}return o}return(0,f.default)(s,t),(0,o.default)(s,[{key:"addTrack",value:function(t){-1===this._tracks.indexOf(t)&&(this._tracks.push(t),y.mediaStreamAddTrack(this._reactTag,t.id))}},{key:"removeTrack",value:function(t){var n=this._tracks.indexOf(t);-1!==n&&(this._tracks.splice(n,1),y.mediaStreamRemoveTrack(this._reactTag,t.id))}},{key:"getTracks",value:function(){return this._tracks.slice()}},{key:"getTrackById",value:function(t){return this._tracks.find(function(n){return n.id===t})}},{key:"getAudioTracks",value:function(){return this._tracks.filter(function(t){return'audio'===t.kind})}},{key:"getVideoTracks",value:function(){return this._tracks.filter(function(t){return'video'===t.kind})}},{key:"clone",value:function(){throw new Error('Not implemented.')}},{key:"toURL",value:function(){return this._reactTag}},{key:"release",value:function(){y.mediaStreamRelease(this._reactTag)}}]),s})((0,l.default)(['active','inactive','addtrack','removetrack']));e.default=h},403,[3,4,5,6,9,10,15,399,404,409]); -__d(function(g,r,i,a,m,e,d){var v=r(d[0]),n=r(d[1]),o=n;o.v1=v,o.v4=n,m.exports=o},404,[405,408]); -__d(function(g,r,i,a,m,e,d){var n,o,s=r(d[0]),c=r(d[1]),v=0,l=0;m.exports=function(u,t,f){var k=t&&f||0,q=t||[],w=(u=u||{}).node||n,h=void 0!==u.clockseq?u.clockseq:o;if(null==w||null==h){var _=s();null==w&&(w=n=[1|_[0],_[1],_[2],_[3],_[4],_[5]]),null==h&&(h=o=16383&(_[6]<<8|_[7]))}var p=void 0!==u.msecs?u.msecs:(new Date).getTime(),x=void 0!==u.nsecs?u.nsecs:l+1,C=p-v+(x-l)/1e4;if(C<0&&void 0===u.clockseq&&(h=h+1&16383),(C<0||p>v)&&void 0===u.nsecs&&(x=0),x>=1e4)throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');v=p,l=x,o=h;var D=(1e4*(268435455&(p+=122192928e5))+x)%4294967296;q[k++]=D>>>24&255,q[k++]=D>>>16&255,q[k++]=D>>>8&255,q[k++]=255&D;var E=p/4294967296*1e4&268435455;q[k++]=E>>>8&255,q[k++]=255&E,q[k++]=E>>>24&15|16,q[k++]=E>>>16&255,q[k++]=h>>>8|128,q[k++]=255&h;for(var M=0;M<6;++M)q[k+M]=w[M];return t||c(q)}},405,[406,407]); -__d(function(g,r,i,a,m,e,d){var n='undefined'!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||'undefined'!=typeof msCrypto&&'function'==typeof window.msCrypto.getRandomValues&&msCrypto.getRandomValues.bind(msCrypto);if(n){var t=new Uint8Array(16);m.exports=function(){return n(t),t}}else{var o=new Array(16);m.exports=function(){for(var n,t=0;t<16;t++)0==(3&t)&&(n=4294967296*Math.random()),o[t]=n>>>((3&t)<<3)&255;return o}}},406,[]); -__d(function(g,r,i,a,m,e,d){for(var n=[],t=0;t<256;++t)n[t]=(t+256).toString(16).substr(1);m.exports=function(t,o){var u=o||0,f=n;return[f[t[u++]],f[t[u++]],f[t[u++]],f[t[u++]],'-',f[t[u++]],f[t[u++]],'-',f[t[u++]],f[t[u++]],'-',f[t[u++]],f[t[u++]],'-',f[t[u++]],f[t[u++]],f[t[u++]],f[t[u++]],f[t[u++]],f[t[u++]]].join('')}},407,[]); -__d(function(g,r,i,a,m,e,d){var n=r(d[0]),o=r(d[1]);m.exports=function(t,f,u){var l=f&&u||0;'string'==typeof t&&(f='binary'===t?new Array(16):null,t=null);var v=(t=t||{}).random||(t.rng||n)();if(v[6]=15&v[6]|64,v[8]=63&v[8]|128,f)for(var y=0;y<16;++y)f[l+y]=v[y];return f||o(v)}},408,[406,407]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var n=t(r(d[1])),o=t(r(d[2])),l=t(r(d[3])),u=t(r(d[4])),s=t(r(d[5])),c=r(d[6]),f=t(r(d[7])),h=(t(r(d[8])),c.NativeModules.WebRTCModule),v=(function(t){function c(t){var o;(0,n.default)(this,c),o=(0,l.default)(this,(0,u.default)(c).call(this));var s=t.readyState.toLowerCase();return o._enabled=t.enabled,o.id=t.id,o.kind=t.kind,o.label=t.label,o.muted=!1,o.readonly=!0,o.remote=t.remote,o.readyState="initializing"===s||"live"===s?"live":"ended",o}return(0,s.default)(c,t),(0,o.default)(c,[{key:"stop",value:function(){h.mediaStreamTrackSetEnabled(this.id,!1),this.readyState='ended'}},{key:"_switchCamera",value:function(){if(this.remote)throw new Error('Not implemented for remote tracks');if('video'!==this.kind)throw new Error('Only implemented for video tracks');h.mediaStreamTrackSwitchCamera(this.id)}},{key:"applyConstraints",value:function(){throw new Error('Not implemented.')}},{key:"clone",value:function(){throw new Error('Not implemented.')}},{key:"getCapabilities",value:function(){throw new Error('Not implemented.')}},{key:"getConstraints",value:function(){throw new Error('Not implemented.')}},{key:"getSettings",value:function(){throw new Error('Not implemented.')}},{key:"release",value:function(){h.mediaStreamTrackRelease(this.id)}},{key:"enabled",get:function(){return this._enabled},set:function(t){t!==this._enabled&&(h.mediaStreamTrackSetEnabled(this.id,!this._enabled),this._enabled=!this._enabled,this.muted=!this._enabled)}}]),c})((0,f.default)(['ended','mute','unmute','overconstrained']));e.default=v},409,[3,4,5,6,9,10,15,399,410]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var u=t(r(d[1])),f=t(r(d[2]));e.default=function t(l,n){(0,f.default)(this,t),this.type=l.toString(),(0,u.default)(this,n)}},410,[3,24,4]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var u=t(r(d[1])),f=t(r(d[2]));e.default=function t(l,n){(0,f.default)(this,t),this.type=l.toString(),(0,u.default)(this,n)}},411,[3,24,4]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var u=t(r(d[1])),f=t(r(d[2]));e.default=function t(l,n){(0,f.default)(this,t),this.type=l.toString(),(0,u.default)(this,n)}},412,[3,24,4]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var n=t(r(d[1])),o=t(r(d[2])),s=t(r(d[3])),f=t(r(d[4])),u=t(r(d[5])),l=t(r(d[6])),c=r(d[7]),h=t(r(d[8])),y=t(r(d[9])),p=t(r(d[10])),v=t(r(d[11])),b=c.NativeModules.WebRTCModule,_=((function(t){function n(){return(0,o.default)(this,n),(0,s.default)(this,(0,f.default)(n).apply(this,arguments))}(0,u.default)(n,t)})((0,l.default)(Error)),(function(t){function l(t,n,u){var c;return(0,o.default)(this,l),(c=(0,s.default)(this,(0,f.default)(l).call(this))).binaryType='arraybuffer',c.bufferedAmount=0,c.bufferedAmountLowThreshold=0,c.maxPacketLifeTime=null,c.maxRetransmits=null,c.negotiated=!1,c.ordered=!0,c.protocol='',c.readyState='connecting',c._peerConnectionId=t,c.label=n,c.id='id'in u?u.id:-1,c.ordered=!!u.ordered,c.maxPacketLifeTime=u.maxPacketLifeTime,c.maxRetransmits=u.maxRetransmits,c.protocol=u.protocol||'',c.negotiated=!!u.negotiated,c._registerEvents(),c}return(0,u.default)(l,t),(0,n.default)(l,[{key:"send",value:function(t){if('string'!=typeof t){if(ArrayBuffer.isView(t))t=new Uint8Array(t.buffer,t.byteOffset,t.byteLength);else{if(!(t instanceof ArrayBuffer))throw new TypeError('Data must be either string, ArrayBuffer, or ArrayBufferView');t=new Uint8Array(t)}b.dataChannelSend(this._peerConnectionId,this.id,h.default.fromByteArray(t),'binary')}else b.dataChannelSend(this._peerConnectionId,this.id,t,'text')}},{key:"close",value:function(){'closing'!==this.readyState&&'closed'!==this.readyState&&(this.readyState='closing',b.dataChannelClose(this._peerConnectionId,this.id))}},{key:"_unregisterEvents",value:function(){this._subscriptions.forEach(function(t){return t.remove()}),this._subscriptions=[]}},{key:"_registerEvents",value:function(){var t=this;this._subscriptions=[c.DeviceEventEmitter.addListener('dataChannelStateChanged',function(n){n.peerConnectionId===t._peerConnectionId&&n.id===t.id&&(t.readyState=n.state,'open'===t.readyState?t.dispatchEvent(new v.default('open',{channel:t})):'close'===t.readyState&&(t.dispatchEvent(new v.default('close',{channel:t})),t._unregisterEvents()))}),c.DeviceEventEmitter.addListener('dataChannelReceiveMessage',function(n){if(n.peerConnectionId===t._peerConnectionId&&n.id===t.id){var o=n.data;'binary'===n.type&&(o=h.default.toByteArray(n.data).buffer),t.dispatchEvent(new p.default('message',{data:o}))}})]}}]),l})((0,y.default)(['open','message','bufferedamountlow','close','error'])));e.default=_},413,[3,5,4,6,9,10,100,15,128,399,414,415]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var u=t(r(d[1])),f=t(r(d[2]));e.default=function t(l,n){(0,f.default)(this,t),this.type=l.toString(),(0,u.default)(this,n)}},414,[3,24,4]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var u=t(r(d[1])),f=t(r(d[2]));e.default=function t(l,n){(0,f.default)(this,t),this.type=l.toString(),(0,u.default)(this,n)}},415,[3,24,4]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var u=t(r(d[1])),s=t(r(d[2])),n=(function(){function t(s){(0,u.default)(this,t),this.sdp=s.sdp,this.type=s.type}return(0,s.default)(t,[{key:"toJSON",value:function(){return{sdp:this.sdp,type:this.type}}}]),t})();e.default=n},416,[3,4,5]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var n=t(r(d[1])),s=t(r(d[2])),u=(function(){function t(s){(0,n.default)(this,t),this.candidate=s.candidate,this.sdpMLineIndex=s.sdpMLineIndex,this.sdpMid=s.sdpMid}return(0,s.default)(t,[{key:"toJSON",value:function(){return{candidate:this.candidate,sdpMLineIndex:this.sdpMLineIndex,sdpMid:this.sdpMid}}}]),t})();e.default=u},417,[3,4,5]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var n=t(r(d[1]));e.default=function t(u,c){(0,n.default)(this,t),this.type=u.toString(),this.candidate=null,c&&c.candidate&&(this.candidate=c.candidate)}},418,[3,4]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var u=t(r(d[1])),f=t(r(d[2]));e.default=function t(l,n){(0,f.default)(this,t),this.type=l.toString(),(0,u.default)(this,n)}},419,[3,24,4]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.normalizeOfferAnswerOptions=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},o={};if(!t)return o;t.mandatory&&(t=t.mandatory);for(var f=Object.entries(t),c=0;c0&&void 0!==arguments[0]?arguments[0]:{};if('object'!=typeof o)return Promise.reject(new TypeError('constraints is not a dictionary'));if(!(void 0!==o.audio&&o.audio||void 0!==o.video&&o.video))return Promise.reject(new TypeError('audio and/or video is required'));var t=[];(o=u.normalizeConstraints(o)).audio?t.push(v.default.request({name:'microphone'})):t.push(Promise.resolve(!1));o.video?t.push(v.default.request({name:'camera'})):t.push(Promise.resolve(!1));return new Promise(function(s,u){Promise.all(t).then(function(t){var v=(0,n.default)(t,2),p=v[0],h=v[1];if(p||h){p||delete o.audio,h||delete o.video;f.getUserMedia(o,function(o,t){var n={streamId:o,streamReactTag:o,tracks:t};s(new c.default(n))},function(o,t){var n;switch(o){case'TypeError':n=new TypeError(t)}n||(n=new l.default({message:t,name:o}));u(n)})}else{u(new l.default({message:'Permission denied.',name:'SecurityError'}))}})})};var n=t(r(d[2])),s=r(d[3]),u=o(r(d[4])),c=t(r(d[5])),l=t(r(d[6])),v=t(r(d[7])),f=s.NativeModules.WebRTCModule},427,[2,3,25,15,420,403,428,429]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var s=t(r(d[1]));e.default=function t(n){(0,s.default)(this,t),this.name=n.name,this.message=n.message,this.constraintName=n.constraintName}},428,[3,4]); -__d(function(g,r,i,a,m,e,d){'use strict';var n=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var t=n(r(d[1])),o=n(r(d[2])),s=r(d[3]),u=s.NativeModules.WebRTCModule,P=new((function(){function n(){(0,t.default)(this,n),this.RESULT={DENIED:'denied',GRANTED:'granted',PROMPT:'prompt'},this.VALID_PERMISSIONS=['camera','microphone'],this._lastReq=Promise.resolve()}return(0,o.default)(n,[{key:"_requestPermissionAndroid",value:function(n){return new Promise(function(t,o){s.PermissionsAndroid.request(n).then(function(n){return t(!0===n||n===s.PermissionsAndroid.RESULTS.GRANTED)},function(){return t(!1)})})}},{key:"_validatePermissionDescriptior",value:function(n){if("object"!=typeof n)throw new TypeError("Argument 1 of Permissions.query is not an object.");if(void 0===n.name)throw new TypeError("Missing required 'name' member of PermissionDescriptor.");if(-1===this.VALID_PERMISSIONS.indexOf(n.name))throw new TypeError("'name' member of PermissionDescriptor is not a valid value for enumeration PermissionName.")}},{key:"query",value:function(n){var t=this;try{this._validatePermissionDescriptior(n)}catch(n){return Promise.reject(n)}if('android'===s.Platform.OS){var o='camera'===n.name?s.PermissionsAndroid.PERMISSIONS.CAMERA:s.PermissionsAndroid.PERMISSIONS.RECORD_AUDIO;return new Promise(function(n,u){s.PermissionsAndroid.check(o).then(function(o){return n(o?t.RESULT.GRANTED:t.RESULT.PROMPT)},function(){return n(t.RESULT.PROMPT)})})}return'ios'===s.Platform.OS?u.checkPermission(n.name):Promise.reject(new TypeError("Unsupported platform."))}},{key:"request",value:function(n){var t=this;try{this._validatePermissionDescriptior(n)}catch(n){return Promise.reject(n)}if('android'===s.Platform.OS){var o='camera'===n.name?s.PermissionsAndroid.PERMISSIONS.CAMERA:s.PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,P=function(){return t._requestPermissionAndroid(o)};return this._lastReq=this._lastReq.then(P,P),this._lastReq}return'ios'===s.Platform.OS?u.requestPermission(n.name):Promise.reject(new TypeError("Unsupported platform."))}}]),n})());e.default=P},429,[3,4,5,15]); -__d(function(g,r,i,a,m,e,d){var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=f;var n=t(r(d[1])),o=t(r(d[2])),u=r(d[3]),s=r(d[4]);function f(){for(var t=this,n=arguments.length,o=new Array(n),u=0;u=10&&'typ'===v[6]){for(var l=[v[4]],h=!1,y=8;y>18&63)+s.charAt(h>>12&63)+s.charAt(h>>6&63)+s.charAt(63&h);return 2==A?(n=t.charCodeAt(p)<<8,o=t.charCodeAt(++p),l+=s.charAt((h=n+o)>>10)+s.charAt(h>>4&63)+s.charAt(h<<2&63)+'='):1==A&&(h=t.charCodeAt(p),l+=s.charAt(h>>2)+s.charAt(h<<4&63)+'=='),l},decode:function(t){var n=(t=String(t).replace(A,'')).length;n%4==0&&(n=(t=t.replace(/==?$/,'')).length),(n%4==1||/[^+a-zA-Z0-9/]/.test(t))&&f('Invalid character: the string to be decoded is not correctly encoded.');for(var o,c,h=0,l='',p=-1;++p>(-2*h&6)));return l},version:'0.1.0'};if('function'==typeof define&&'object'==typeof define.amd&&define.amd)define(function(){return l});else if(n&&!n.nodeType)if(o)o.exports=l;else for(var p in l)l.hasOwnProperty(p)&&(n[p]=l[p]);else t.base64=l})(this)},432,[]); -__d(function(g,r,i,a,m,e,d){'use strict';!(function(n){function t(n,t,o){var h,l,A,p,E,H,v,S,U,k=0,F=[],R=0,y=!1,B=[],L=[],T=!1,C=!1,Y=-1;if(h=(o=o||{}).encoding||"UTF8",(U=o.numRounds||1)!==parseInt(U,10)||1>U)throw Error("numRounds must a integer >= 1");if("SHA-1"===n)E=512,H=N,v=j,p=160,S=function(n){return n.slice()};else if(0===n.lastIndexOf("SHA-",0))if(H=function(t,o){return z(t,o,n)},v=function(t,o,u,f){var w,s;if("SHA-224"===n||"SHA-256"===n)w=15+(o+65>>>9<<4),s=16;else{if("SHA-384"!==n&&"SHA-512"!==n)throw Error("Unexpected error in SHA-2 implementation");w=31+(o+129>>>10<<5),s=32}for(;t.length<=w;)t.push(0);for(t[o>>>5]|=128<<24-o%32,o+=u,t[w]=4294967295&o,t[w-1]=o/4294967296|0,u=t.length,o=0;ot;t+=1)o[t]=n[t].slice();return o},Y=1,"SHA3-224"===n)E=1152,p=224;else if("SHA3-256"===n)E=1088,p=256;else if("SHA3-384"===n)E=832,p=384;else if("SHA3-512"===n)E=576,p=512;else if("SHAKE128"===n)E=1344,p=-1,x=31,C=!0;else{if("SHAKE256"!==n)throw Error("Chosen SHA variant is not supported");E=1088,p=-1,x=31,C=!0}v=function(n,t,o,u,f){var w,s=x,c=[],b=(o=E)>>>5,h=0,l=t>>>5;for(w=0;w=o;w+=b)u=Z(n.slice(w,w+b),u),t-=o;for(n=n.slice(w),t%=o;n.length>>3)>>2]^=s<=f));)c.push(n.a),0==64*(h+=1)%o&&Z(null,u);return c}}A=b(t,h,Y),l=K(n),this.setHMACKey=function(t,o,u){var f;if(!0===y)throw Error("HMAC key already set");if(!0===T)throw Error("Cannot set HMAC key after calling update");if(!0===C)throw Error("SHAKE is not supported for HMAC");if(t=(o=b(o,h=(u||{}).encoding||"UTF8",Y)(t)).binLen,o=o.value,u=(f=E>>>3)/4-1,ft/8){for(;o.length<=u;)o.push(0);o[u]&=4294967040}for(t=0;t<=u;t+=1)B[t]=909522486^o[t],L[t]=1549556828^o[t];l=H(B,l),k=E,y=!0},this.update=function(n){var t,o,u,f=0,w=E>>>5;for(n=(t=A(n,F,R)).binLen,o=t.value,t=n>>>5,u=0;u>>5),R=n%E,T=!0},this.getHash=function(t,o){var b,h,A,E;if(!0===y)throw Error("Cannot call getHash after setting HMAC key");if(A=c(o),!0===C){if(-1===A.shakeLen)throw Error("shakeLen must be specified in options");p=A.shakeLen}switch(t){case"HEX":b=function(n){return u(n,p,Y,A)};break;case"B64":b=function(n){return f(n,p,Y,A)};break;case"BYTES":b=function(n){return w(n,p,Y)};break;case"ARRAYBUFFER":try{h=new ArrayBuffer(0)}catch(n){throw Error("ARRAYBUFFER not supported by this environment")}b=function(n){return s(n,p,Y)};break;default:throw Error("format must be HEX, B64, BYTES, or ARRAYBUFFER")}for(E=v(F.slice(),R,k,S(l),p),h=1;h>>24-p%32),E=v(E,p,0,K(n),p);return b(E)},this.getHMAC=function(t,o){var b,h,A,U;if(!1===y)throw Error("Cannot call getHMAC without first setting HMAC key");switch(A=c(o),t){case"HEX":b=function(n){return u(n,p,Y,A)};break;case"B64":b=function(n){return f(n,p,Y,A)};break;case"BYTES":b=function(n){return w(n,p,Y)};break;case"ARRAYBUFFER":try{b=new ArrayBuffer(0)}catch(n){throw Error("ARRAYBUFFER not supported by this environment")}b=function(n){return s(n,p,Y)};break;default:throw Error("outputFormat must be HEX, B64, BYTES, or ARRAYBUFFER")}return h=v(F.slice(),R,k,S(l),p),U=H(L,K(n)),b(U=v(h,p,E,U,p))}}function o(n,t){this.a=n,this.b=t}function u(n,t,o,u){var f,w,s,c="";for(t/=8,s=-1===o?3:0,f=0;f>>2]>>>8*(s+f%4*o),c+="0123456789abcdef".charAt(w>>>4&15)+"0123456789abcdef".charAt(15&w);return u.outputUpper?c.toUpperCase():c}function f(n,t,o,u){var f,w,s,c,b="",h=t/8;for(c=-1===o?3:0,f=0;f>>2]:0,s=f+2>>2]:0,s=(n[f>>>2]>>>8*(c+f%4*o)&255)<<16|(w>>>8*(c+(f+1)%4*o)&255)<<8|s>>>8*(c+(f+2)%4*o)&255,w=0;4>w;w+=1)b+=8*f+6*w<=t?"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(s>>>6*(3-w)&63):u.b64Pad;return b}function w(n,t,o){var u,f,w,s="";for(t/=8,w=-1===o?3:0,u=0;u>>2]>>>8*(w+u%4*o)&255,s+=String.fromCharCode(f);return s}function s(n,t,o){t/=8;var u,f,w,s=new ArrayBuffer(t);for(w=new Uint8Array(s),f=-1===o?3:0,u=0;u>>2]>>>8*(f+u%4*o)&255;return s}function c(n){var t={outputUpper:!1,b64Pad:"=",shakeLen:-1};if(n=n||{},t.outputUpper=n.outputUpper||!1,!0===n.hasOwnProperty("b64Pad")&&(t.b64Pad=n.b64Pad),!0===n.hasOwnProperty("shakeLen")){if(0!=n.shakeLen%8)throw Error("shakeLen must be a multiple of 8");t.shakeLen=n.shakeLen}if("boolean"!=typeof t.outputUpper)throw Error("Invalid outputUpper formatting option");if("string"!=typeof t.b64Pad)throw Error("Invalid b64Pad formatting option");return t}function b(n,t,o){switch(t){case"UTF8":case"UTF16BE":case"UTF16LE":break;default:throw Error("encoding must be UTF8, UTF16BE, or UTF16LE")}switch(n){case"HEX":n=function(n,t,u){var f,w,s,c,b,h,l=n.length;if(0!=l%2)throw Error("String of HEX type must be in byte increments");for(t=t||[0],b=(u=u||0)>>>3,h=-1===o?3:0,f=0;f>>1)+b)>>>2;t.length<=s;)t.push(0);t[s]|=w<<8*(h+c%4*o)}return{value:t,binLen:4*l+u}};break;case"TEXT":n=function(n,u,f){var w,s,c,b,h,l,A,p,E=0;if(u=u||[0],h=(f=f||0)>>>3,"UTF8"===t)for(p=-1===o?3:0,c=0;c(w=n.charCodeAt(c))?s.push(w):2048>w?(s.push(192|w>>>6),s.push(128|63&w)):55296>w||57344<=w?s.push(224|w>>>12,128|w>>>6&63,128|63&w):(c+=1,w=65536+((1023&w)<<10|1023&n.charCodeAt(c)),s.push(240|w>>>18,128|w>>>12&63,128|w>>>6&63,128|63&w)),b=0;b>>2;u.length<=l;)u.push(0);u[l]|=s[b]<<8*(p+A%4*o),E+=1}else if("UTF16BE"===t||"UTF16LE"===t)for(p=-1===o?2:0,s="UTF16LE"===t&&1!==o||"UTF16LE"!==t&&1===o,c=0;c>>8),l=(A=E+h)>>>2;u.length<=l;)u.push(0);u[l]|=w<<8*(p+A%4*o),E+=2}return{value:u,binLen:8*E+f}};break;case"B64":n=function(n,t,u){var f,w,s,c,b,h,l,A,p=0;if(-1===n.search(/^[a-zA-Z0-9=+\/]+$/))throw Error("Invalid character in base-64 string");if(w=n.indexOf("="),n=n.replace(/\=/g,""),-1!==w&&w0;){var t=e.shift();if("function"==typeof t){var n=e.shift(),r=e.shift();t.call(n,r)}else t._settlePromises()}},i.prototype._drainQueues=function(){this._drainQueue(this._normalQueue),this._reset(),this._haveDrainedQueues=!0,this._drainQueue(this._lateQueue)},i.prototype._queueTick=function(){this._isTickUsed||(this._isTickUsed=!0,this._schedule(this.drainQueues))},i.prototype._reset=function(){this._isTickUsed=!1},n.exports=i,n.exports.firstLineError=c},{"./queue":26,"./schedule":29,"./util":36}],3:[function(e,t,n){"use strict";t.exports=function(e,t,n,r){var i=!1,a=function(e,t){this._reject(t)},o=function(e,t){t.promiseRejectionQueued=!0,t.bindingPromise._then(a,a,null,this,e)},s=function(e,t){0==(50397184&this._bitField)&&this._resolveCallback(t.target)},c=function(e,t){t.promiseRejectionQueued||this._reject(e)};e.prototype.bind=function(a){i||(i=!0,e.prototype._propagateFrom=r.propagateFromFunction(),e.prototype._boundValue=r.boundValueFunction());var u=n(a),l=new e(t);l._propagateFrom(this,1);var f=this._target();if(l._setBoundTo(u),u instanceof e){var d={promiseRejectionQueued:!1,promise:l,target:f,bindingPromise:u};f._then(t,o,void 0,l,d),u._then(s,c,void 0,l,d),l._setOnCancel(u)}else l._resolveCallback(f);return l},e.prototype._setBoundTo=function(e){void 0!==e?(this._bitField=2097152|this._bitField,this._boundTo=e):this._bitField=-2097153&this._bitField},e.prototype._isBound=function(){return 2097152==(2097152&this._bitField)},e.bind=function(t,n){return e.resolve(n).bind(t)}}},{}],4:[function(e,t,n){"use strict";var r;"undefined"!=typeof Promise&&(r=Promise);var i=e("./promise")();i.noConflict=function(){try{Promise===i&&(Promise=r)}catch(e){}return i},t.exports=i},{"./promise":22}],5:[function(e,t,n){"use strict";var r=Object.create;if(r){var i=r(null),a=r(null);i[" size"]=a[" size"]=0}t.exports=function(t){function n(e,n){var r;if(null!=e&&(r=e[n]),"function"!=typeof r){var i="Object "+o.classString(e)+" has no method '"+o.toString(n)+"'";throw new t.TypeError(i)}return r}function r(e){return n(e,this.pop()).apply(e,this)}function i(e){return e[this]}function a(e){var t=+this;return t<0&&(t=Math.max(0,t+e.length)),e[t]}var o=e("./util"),s=o.canEvaluate;o.isIdentifier,t.prototype.call=function(e){var t=[].slice.call(arguments,1);return t.push(e),this._then(r,void 0,void 0,t,void 0)},t.prototype.get=function(e){var t;if("number"==typeof e)t=a;else if(s){var n=(void 0)(e);t=null!==n?n:i}else t=i;return this._then(t,void 0,void 0,e,void 0)}}},{"./util":36}],6:[function(e,t,n){"use strict";t.exports=function(t,n,r,i){var a=e("./util"),o=a.tryCatch,s=a.errorObj,c=t._async;t.prototype.break=t.prototype.cancel=function(){if(!i.cancellation())return this._warn("cancellation is disabled");for(var e=this,t=e;e._isCancellable();){if(!e._cancelBy(t)){t._isFollowing()?t._followee().cancel():t._cancelBranched();break}var n=e._cancellationParent;if(null==n||!n._isCancellable()){e._isFollowing()?e._followee().cancel():e._cancelBranched();break}e._isFollowing()&&e._followee().cancel(),e._setWillBeCancelled(),t=e,e=n}},t.prototype._branchHasCancelled=function(){this._branchesRemainingToCancel--},t.prototype._enoughBranchesHaveCancelled=function(){return void 0===this._branchesRemainingToCancel||this._branchesRemainingToCancel<=0},t.prototype._cancelBy=function(e){return e===this?(this._branchesRemainingToCancel=0,this._invokeOnCancel(),!0):(this._branchHasCancelled(),!!this._enoughBranchesHaveCancelled()&&(this._invokeOnCancel(),!0))},t.prototype._cancelBranched=function(){this._enoughBranchesHaveCancelled()&&this._cancel()},t.prototype._cancel=function(){this._isCancellable()&&(this._setCancelled(),c.invoke(this._cancelPromises,this,void 0))},t.prototype._cancelPromises=function(){this._length()>0&&this._settlePromises()},t.prototype._unsetOnCancel=function(){this._onCancelField=void 0},t.prototype._isCancellable=function(){return this.isPending()&&!this._isCancelled()},t.prototype.isCancellable=function(){return this.isPending()&&!this.isCancelled()},t.prototype._doInvokeOnCancel=function(e,t){if(a.isArray(e))for(var n=0;n=0)return i[e]}var r=!1,i=[];return e.prototype._promiseCreated=function(){},e.prototype._pushContext=function(){},e.prototype._popContext=function(){return null},e._peekContext=e.prototype._peekContext=function(){},t.prototype._pushContext=function(){void 0!==this._trace&&(this._trace._promiseCreated=null,i.push(this._trace))},t.prototype._popContext=function(){if(void 0!==this._trace){var e=i.pop(),t=e._promiseCreated;return e._promiseCreated=null,t}return null},t.CapturedTrace=null,t.create=function(){if(r)return new t},t.deactivateLongStackTraces=function(){},t.activateLongStackTraces=function(){var i=e.prototype._pushContext,a=e.prototype._popContext,o=e._peekContext,s=e.prototype._peekContext,c=e.prototype._promiseCreated;t.deactivateLongStackTraces=function(){e.prototype._pushContext=i,e.prototype._popContext=a,e._peekContext=o,e.prototype._peekContext=s,e.prototype._promiseCreated=c,r=!1},r=!0,e.prototype._pushContext=t.prototype._pushContext,e.prototype._popContext=t.prototype._popContext,e._peekContext=e.prototype._peekContext=n,e.prototype._promiseCreated=function(){var e=this._peekContext();e&&null==e._promiseCreated&&(e._promiseCreated=this)}},t}},{}],9:[function(t,n,r){"use strict";n.exports=function(n,r){function i(e,t){return{promise:t}}function a(){return!1}function o(e,t,n){var r=this;try{e(t,n,function(e){if("function"!=typeof e)throw new TypeError("onCancel must be a function, got: "+x.toString(e));r._attachCancellationCallback(e)})}catch(e){return e}}function s(e){if(!this._isCancellable())return this;var t=this._onCancel();void 0!==t?x.isArray(t)?t.push(e):this._setOnCancel([t,e]):this._setOnCancel(e)}function c(){return this._onCancelField}function u(e){this._onCancelField=e}function l(){this._cancellationParent=void 0,this._onCancelField=void 0}function f(e,t){if(0!=(1&t)){this._cancellationParent=e;var n=e._branchesRemainingToCancel;void 0===n&&(n=0),e._branchesRemainingToCancel=n+1}0!=(2&t)&&e._isBound()&&this._setBoundTo(e._boundTo)}function d(){var e=this._boundTo;return void 0!==e&&e instanceof n?e.isFulfilled()?e.value():void 0:e}function h(){this._trace=new I(this._peekContext())}function p(e,t){if(D(e)){var n=this._trace;if(void 0!==n&&t&&(n=n._parent),void 0!==n)n.attachExtraTrace(e);else if(!e.__stackCleaned__){var r=k(e);x.notEnumerableProp(e,"stack",r.message+"\n"+r.stack.join("\n")),x.notEnumerableProp(e,"__stackCleaned__",!0)}}}function v(e,t,r){if(ne.warnings){var i,a=new A(e);if(t)r._attachExtraTrace(a);else if(ne.longStackTraces&&(i=n._peekContext()))i.attachExtraTrace(a);else{var o=k(a);a.stack=o.message+"\n"+o.stack.join("\n")}$("warning",a)||w(a,"",!0)}}function g(e,t){for(var n=0;n=0;--s)if(r[s]===a){o=s;break}for(s=o;s>=0;--s){var c=r[s];if(t[i]!==c)break;t.pop(),i--}t=r}}function b(e){for(var t=[],n=0;n0&&"SyntaxError"!=e.name&&(t=t.slice(n)),t}function k(e){var t=e.stack,n=e.toString();return t="string"==typeof t&&t.length>0?S(e):[" (No stack trace)"],{message:n,stack:"SyntaxError"==e.name?t:b(t)}}function w(e,t,n){if("undefined"!=typeof console){var r;if(x.isObject(e)){var i=e.stack;r=t+N(i,e)}else r=t+String(e);"function"==typeof M?M(r,n):"function"!=typeof console.log&&"object"!=typeof console.log||console.log(r)}}function C(e,t,n,r){var i=!1;try{"function"==typeof t&&(i=!0,"rejectionHandled"===e?t(r):t(n,r))}catch(e){j.throwLater(e)}"unhandledRejection"===e?$(e,n,r)||i||w(n,"Unhandled rejection "):$(e,r)}function _(e){var t;if("function"==typeof e)t="[function "+(e.name||"anonymous")+"]";else{if(t=e&&"function"==typeof e.toString?e.toString():x.toString(e),/\[object [a-zA-Z0-9$_]+\]/.test(t))try{t=JSON.stringify(e)}catch(e){}0===t.length&&(t="(empty array)")}return"(<"+T(t)+">, no stack trace)"}function T(e){return e.length<41?e:e.substr(0,38)+"..."}function P(){return"function"==typeof te}function E(e){var t=e.match(ee);if(t)return{fileName:t[1],line:parseInt(t[2],10)}}function I(e){this._parent=e,this._promisesCreated=0;var t=this._length=1+(void 0===e?0:e._length);te(this,I),t>32&&this.uncycle()}var R,O,M,F=n._getDomain,j=n._async,A=t("./errors").Warning,x=t("./util"),D=x.canAttachTrace,U=/[\\\/]bluebird[\\\/]js[\\\/](release|debug|instrumented)/,L=/\((?:timers\.js):\d+:\d+\)/,B=/[\/<\(](.+?):(\d+):(\d+)\)?\s*$/,H=null,N=null,V=!1,W=!(0==x.env("BLUEBIRD_DEBUG")),q=!(0==x.env("BLUEBIRD_WARNINGS")||!W&&!x.env("BLUEBIRD_WARNINGS")),G=!(0==x.env("BLUEBIRD_LONG_STACK_TRACES")||!W&&!x.env("BLUEBIRD_LONG_STACK_TRACES")),z=0!=x.env("BLUEBIRD_W_FORGOTTEN_RETURN")&&(q||!!x.env("BLUEBIRD_W_FORGOTTEN_RETURN"));n.prototype.suppressUnhandledRejections=function(){var e=this._target();e._bitField=-1048577&e._bitField|524288},n.prototype._ensurePossibleRejectionHandled=function(){if(0==(524288&this._bitField)){this._setRejectionIsUnhandled();var e=this;setTimeout(function(){e._notifyUnhandledRejection()},1)}},n.prototype._notifyUnhandledRejectionIsHandled=function(){C("rejectionHandled",R,void 0,this)},n.prototype._setReturnedNonUndefined=function(){this._bitField=268435456|this._bitField},n.prototype._returnedNonUndefined=function(){return 0!=(268435456&this._bitField)},n.prototype._notifyUnhandledRejection=function(){if(this._isRejectionUnhandled()){var e=this._settledValue();this._setUnhandledRejectionIsNotified(),C("unhandledRejection",O,e,this)}},n.prototype._setUnhandledRejectionIsNotified=function(){this._bitField=262144|this._bitField},n.prototype._unsetUnhandledRejectionIsNotified=function(){this._bitField=-262145&this._bitField},n.prototype._isUnhandledRejectionNotified=function(){return(262144&this._bitField)>0},n.prototype._setRejectionIsUnhandled=function(){this._bitField=1048576|this._bitField},n.prototype._unsetRejectionIsUnhandled=function(){this._bitField=-1048577&this._bitField,this._isUnhandledRejectionNotified()&&(this._unsetUnhandledRejectionIsNotified(),this._notifyUnhandledRejectionIsHandled())},n.prototype._isRejectionUnhandled=function(){return(1048576&this._bitField)>0},n.prototype._warn=function(e,t,n){return v(e,t,n||this)},n.onPossiblyUnhandledRejection=function(e){var t=F();O="function"==typeof e?null===t?e:x.domainBind(t,e):void 0},n.onUnhandledRejectionHandled=function(e){var t=F();R="function"==typeof e?null===t?e:x.domainBind(t,e):void 0};var Q=function(){};n.longStackTraces=function(){if(j.haveItemsQueued()&&!ne.longStackTraces)throw new Error("cannot enable long stack traces after promises have been created\n\n See http://goo.gl/MqrFmX\n");if(!ne.longStackTraces&&P()){var e=n.prototype._captureStackTrace,t=n.prototype._attachExtraTrace;ne.longStackTraces=!0,Q=function(){if(j.haveItemsQueued()&&!ne.longStackTraces)throw new Error("cannot enable long stack traces after promises have been created\n\n See http://goo.gl/MqrFmX\n");n.prototype._captureStackTrace=e,n.prototype._attachExtraTrace=t,r.deactivateLongStackTraces(),j.enableTrampoline(),ne.longStackTraces=!1},n.prototype._captureStackTrace=h,n.prototype._attachExtraTrace=p,r.activateLongStackTraces(),j.disableTrampolineIfNecessary()}},n.hasLongStackTraces=function(){return ne.longStackTraces&&P()};var J=(function(){try{if("function"==typeof CustomEvent){var e=new CustomEvent("CustomEvent");return x.global.dispatchEvent(e),function(e,t){var n=new CustomEvent(e.toLowerCase(),{detail:t,cancelable:!0});return!x.global.dispatchEvent(n)}}if("function"==typeof Event){e=new Event("CustomEvent");return x.global.dispatchEvent(e),function(e,t){var n=new Event(e.toLowerCase(),{cancelable:!0});return n.detail=t,!x.global.dispatchEvent(n)}}return(e=document.createEvent("CustomEvent")).initCustomEvent("testingtheevent",!1,!0,{}),x.global.dispatchEvent(e),function(e,t){var n=document.createEvent("CustomEvent");return n.initCustomEvent(e.toLowerCase(),!1,!0,t),!x.global.dispatchEvent(n)}}catch(e){}return function(){return!1}})(),K=x.isNode?function(){return e.emit.apply(e,arguments)}:x.global?function(e){var t="on"+e.toLowerCase(),n=x.global[t];return!!n&&(n.apply(x.global,[].slice.call(arguments,1)),!0)}:function(){return!1},X={promiseCreated:i,promiseFulfilled:i,promiseRejected:i,promiseResolved:i,promiseCancelled:i,promiseChained:function(e,t,n){return{promise:t,child:n}},warning:function(e,t){return{warning:t}},unhandledRejection:function(e,t,n){return{reason:t,promise:n}},rejectionHandled:i},$=function(e){var t=!1;try{t=K.apply(null,arguments)}catch(e){j.throwLater(e),t=!0}var n=!1;try{n=J(e,X[e].apply(null,arguments))}catch(e){j.throwLater(e),n=!0}return n||t};n.config=function(e){if("longStackTraces"in(e=Object(e))&&(e.longStackTraces?n.longStackTraces():!e.longStackTraces&&n.hasLongStackTraces()&&Q()),"warnings"in e){var t=e.warnings;ne.warnings=!!t,z=ne.warnings,x.isObject(t)&&"wForgottenReturn"in t&&(z=!!t.wForgottenReturn)}if("cancellation"in e&&e.cancellation&&!ne.cancellation){if(j.haveItemsQueued())throw new Error("cannot enable cancellation after promises are in use");n.prototype._clearCancellationData=l,n.prototype._propagateFrom=f,n.prototype._onCancel=c,n.prototype._setOnCancel=u,n.prototype._attachCancellationCallback=s,n.prototype._execute=o,Y=f,ne.cancellation=!0}return"monitoring"in e&&(e.monitoring&&!ne.monitoring?(ne.monitoring=!0,n.prototype._fireEvent=$):!e.monitoring&&ne.monitoring&&(ne.monitoring=!1,n.prototype._fireEvent=a)),n},n.prototype._fireEvent=a,n.prototype._execute=function(e,t,n){try{e(t,n)}catch(e){return e}},n.prototype._onCancel=function(){},n.prototype._setOnCancel=function(e){},n.prototype._attachCancellationCallback=function(e){},n.prototype._captureStackTrace=function(){},n.prototype._attachExtraTrace=function(){},n.prototype._clearCancellationData=function(){},n.prototype._propagateFrom=function(e,t){};var Y=function(e,t){0!=(2&t)&&e._isBound()&&this._setBoundTo(e._boundTo)},Z=function(){return!1},ee=/[\/<\(]([^:\/]+):(\d+):(?:\d+)\)?\s*$/;x.inherits(I,Error),r.CapturedTrace=I,I.prototype.uncycle=function(){var e=this._length;if(!(e<2)){for(var t=[],n={},r=0,i=this;void 0!==i;++r)t.push(i),i=i._parent;for(r=(e=this._length=r)-1;r>=0;--r){var a=t[r].stack;void 0===n[a]&&(n[a]=r)}for(r=0;r0&&(t[o-1]._parent=void 0,t[o-1]._length=1),t[r]._parent=void 0,t[r]._length=1;var s=r>0?t[r-1]:this;o=0;--u)t[u]._length=c,c++;return}}}},I.prototype.attachExtraTrace=function(e){if(!e.__stackCleaned__){this.uncycle();for(var t=k(e),n=t.message,r=[t.stack],i=this;void 0!==i;)r.push(b(i.stack.split("\n"))),i=i._parent;m(r),y(r),x.notEnumerableProp(e,"stack",g(n,r)),x.notEnumerableProp(e,"__stackCleaned__",!0)}};var te=(function(){var e=/^\s*at\s*/,t=function(e,t){return"string"==typeof e?e:void 0!==t.name&&void 0!==t.message?t.toString():_(t)};if("number"==typeof Error.stackTraceLimit&&"function"==typeof Error.captureStackTrace){Error.stackTraceLimit+=6,H=e,N=t;var n=Error.captureStackTrace;return Z=function(e){return U.test(e)},function(e,t){Error.stackTraceLimit+=6,n(e,t),Error.stackTraceLimit-=6}}var r,i=new Error;if("string"==typeof i.stack&&i.stack.split("\n")[0].indexOf("stackDetection@")>=0)return H=/@/,N=t,V=!0,function(e){e.stack=(new Error).stack};try{throw new Error}catch(e){r="stack"in e}return"stack"in i||!r||"number"!=typeof Error.stackTraceLimit?(N=function(e,t){return"string"==typeof e?e:"object"!=typeof t&&"function"!=typeof t||void 0===t.name||void 0===t.message?_(t):t.toString()},null):(H=e,N=t,function(e){Error.stackTraceLimit+=6;try{throw new Error}catch(t){e.stack=t.stack}Error.stackTraceLimit-=6})})();"undefined"!=typeof console&&void 0!==console.warn&&(M=function(e){console.warn(e)},x.isNode&&e.stderr.isTTY?M=function(e,t){var n=t?"\x1b[33m":"\x1b[31m";console.warn(n+e+"\x1b[0m\n")}:x.isNode||"string"!=typeof(new Error).stack||(M=function(e,t){console.warn("%c"+e,t?"color: darkorange":"color: red")}));var ne={warnings:q,longStackTraces:!1,cancellation:!1,monitoring:!1};return G&&n.longStackTraces(),{longStackTraces:function(){return ne.longStackTraces},warnings:function(){return ne.warnings},cancellation:function(){return ne.cancellation},monitoring:function(){return ne.monitoring},propagateFromFunction:function(){return Y},boundValueFunction:function(){return d},checkForgottenReturns:function(e,t,n,r,i){if(void 0===e&&null!==t&&z){if(void 0!==i&&i._returnedNonUndefined())return;if(0==(65535&r._bitField))return;n&&(n+=" ");var a="",o="";if(t._trace){for(var s=t._trace.stack.split("\n"),c=b(s),u=c.length-1;u>=0;--u){var l=c[u];if(!L.test(l)){var f=l.match(B);f&&(a="at "+f[1]+":"+f[2]+":"+f[3]+" ");break}}if(c.length>0){var d=c[0];for(u=0;u0&&(o="\n"+s[u-1]);break}}}var h="a promise was created in a "+n+"handler "+a+"but was not returned from it, see http://goo.gl/rRqMUw"+o;r._warn(h,!0,t)}},setBounds:function(e,t){if(P()){for(var n,r,i=e.stack.split("\n"),a=t.stack.split("\n"),o=-1,s=-1,c=0;c=s||(Z=function(e){if(U.test(e))return!0;var t=E(e);return!!(t&&t.fileName===n&&o<=t.line&&t.line<=s)})}},warn:v,deprecated:function(e,t){var n=e+" is deprecated and will be removed in a future version.";return t&&(n+=" Use "+t+" instead."),v(n)},CapturedTrace:I,fireDomEvent:J,fireGlobalEvent:K}}},{"./errors":12,"./util":36}],10:[function(e,t,n){"use strict";t.exports=function(e){function t(){return this.value}function n(){throw this.reason}e.prototype.return=e.prototype.thenReturn=function(n){return n instanceof e&&n.suppressUnhandledRejections(),this._then(t,void 0,void 0,{value:n},void 0)},e.prototype.throw=e.prototype.thenThrow=function(e){return this._then(n,void 0,void 0,{reason:e},void 0)},e.prototype.catchThrow=function(e){if(arguments.length<=1)return this._then(void 0,n,void 0,{reason:e},void 0);var t=arguments[1];return this.caught(e,function(){throw t})},e.prototype.catchReturn=function(n){if(arguments.length<=1)return n instanceof e&&n.suppressUnhandledRejections(),this._then(void 0,t,void 0,{value:n},void 0);var r=arguments[1];r instanceof e&&r.suppressUnhandledRejections();return this.caught(n,function(){return r})}}},{}],11:[function(e,t,n){"use strict";t.exports=function(e,t){function n(){return i(this)}var r=e.reduce,i=e.all;e.prototype.each=function(e){return r(this,e,t,0)._then(n,void 0,void 0,this,void 0)},e.prototype.mapSeries=function(e){return r(this,e,t,t)},e.each=function(e,i){return r(e,i,t,0)._then(n,void 0,void 0,e,void 0)},e.mapSeries=function(e,n){return r(e,n,t,t)}}},{}],12:[function(e,t,n){"use strict";function r(e,t){function n(r){if(!(this instanceof n))return new n(r);f(this,"message","string"==typeof r?r:t),f(this,"name",e),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):Error.call(this)}return l(n,Error),n}function i(e){if(!(this instanceof i))return new i(e);f(this,"name","OperationalError"),f(this,"message",e),this.cause=e,this.isOperational=!0,e instanceof Error?(f(this,"message",e.message),f(this,"stack",e.stack)):Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor)}var a,o,s=e("./es5"),c=s.freeze,u=e("./util"),l=u.inherits,f=u.notEnumerableProp,d=r("Warning","warning"),h=r("CancellationError","cancellation error"),p=r("TimeoutError","timeout error"),v=r("AggregateError","aggregate error");try{a=TypeError,o=RangeError}catch(e){a=r("TypeError","type error"),o=r("RangeError","range error")}for(var g="join pop push shift unshift slice filter forEach some every map indexOf lastIndexOf reduce reduceRight sort reverse".split(" "),y=0;y1?e.cancelPromise._reject(t):e.cancelPromise._cancel(),e.cancelPromise=null,!0)}function s(){return u.call(this,this.promise._target()._settledValue())}function c(e){if(!o(this,e))return d.e=e,d}function u(e){var i=this.promise,u=this.handler;if(!this.called){this.called=!0;var l=this.isFinallyHandler()?u.call(i._boundValue()):u.call(i._boundValue(),e);if(l===r)return l;if(void 0!==l){i._setReturnedNonUndefined();var h=n(l,i);if(h instanceof t){if(null!=this.cancelPromise){if(h._isCancelled()){var p=new f("late cancellation observer");return i._attachExtraTrace(p),d.e=p,d}h.isPending()&&h._attachCancellationCallback(new a(this))}return h._then(s,c,void 0,this,void 0)}}}return i.isRejected()?(o(this),d.e=e,d):(o(this),e)}var l=e("./util"),f=t.CancellationError,d=l.errorObj,h=e("./catch_filter")(r);return i.prototype.isFinallyHandler=function(){return 0===this.type},a.prototype._resultCancelled=function(){o(this.finallyHandler)},t.prototype._passThrough=function(e,t,n,r){return"function"!=typeof e?this.then():this._then(n,r,void 0,new i(this,t,e),void 0)},t.prototype.lastly=t.prototype.finally=function(e){return this._passThrough(e,0,u,u)},t.prototype.tap=function(e){return this._passThrough(e,1,u)},t.prototype.tapCatch=function(e){var n=arguments.length;if(1===n)return this._passThrough(e,1,void 0,u);var r,i=new Array(n-1),a=0;for(r=0;r0&&"function"==typeof arguments[t]&&(e=arguments[t]);var r=[].slice.call(arguments);e&&r.pop();var i=new n(r).promise();return void 0!==e?i.spread(e):i}}},{"./util":36}],18:[function(e,t,n){"use strict";t.exports=function(t,n,r,i,a,o){function s(e,t,n,r){this.constructor$(e),this._promise._captureStackTrace();var i=u();this._callback=null===i?t:l.domainBind(i,t),this._preservedValues=r===a?new Array(this.length()):null,this._limit=n,this._inFlight=0,this._queue=[],h.invoke(this._asyncInit,this,void 0)}function c(e,n,i,a){if("function"!=typeof n)return r("expecting a function but got "+l.classString(n));var o=0;if(void 0!==i){if("object"!=typeof i||null===i)return t.reject(new TypeError("options argument must be an object but it is "+l.classString(i)));if("number"!=typeof i.concurrency)return t.reject(new TypeError("'concurrency' must be a number but it is "+l.classString(i.concurrency)));o=i.concurrency}return new s(e,n,o="number"==typeof o&&isFinite(o)&&o>=1?o:0,a).promise()}var u=t._getDomain,l=e("./util"),f=l.tryCatch,d=l.errorObj,h=t._async;l.inherits(s,n),s.prototype._asyncInit=function(){this._init$(void 0,-2)},s.prototype._init=function(){},s.prototype._promiseFulfilled=function(e,n){var r=this._values,a=this.length(),s=this._preservedValues,c=this._limit;if(n<0){if(r[n=-1*n-1]=e,c>=1&&(this._inFlight--,this._drainQueue(),this._isResolved()))return!0}else{if(c>=1&&this._inFlight>=c)return r[n]=e,this._queue.push(n),!1;null!==s&&(s[n]=e);var u=this._promise,l=this._callback,h=u._boundValue();u._pushContext();var p=f(l).call(h,e,n,a),v=u._popContext();if(o.checkForgottenReturns(p,v,null!==s?"Promise.filter":"Promise.map",u),p===d)return this._reject(p.e),!0;var g=i(p,this._promise);if(g instanceof t){var y=(g=g._target())._bitField;if(0==(50397184&y))return c>=1&&this._inFlight++,r[n]=g,g._proxy(this,-1*(n+1)),!1;if(0==(33554432&y))return 0!=(16777216&y)?(this._reject(g._reason()),!0):(this._cancel(),!0);p=g._value()}r[n]=p}return++this._totalResolved>=a&&(null!==s?this._filter(r,s):this._resolve(r),!0)},s.prototype._drainQueue=function(){for(var e=this._queue,t=this._limit,n=this._values;e.length>0&&this._inFlight1){a.deprecated("calling Promise.try with more than 1 argument");var u=arguments[1],l=arguments[2];r=o.isArray(u)?s(e).apply(l,u):s(e).call(l,u)}else r=s(e)();var f=c._popContext();return a.checkForgottenReturns(r,f,"Promise.try",c),c._resolveFromSyncValue(r),c},t.prototype._resolveFromSyncValue=function(e){e===o.errorObj?this._rejectCallback(e.e,!1):this._resolveCallback(e,!0)}}},{"./util":36}],20:[function(e,t,n){"use strict";function r(e){return e instanceof Error&&c.getPrototypeOf(e)===Error.prototype}function i(e){var t;if(r(e)){(t=new s(e)).name=e.name,t.message=e.message,t.stack=e.stack;for(var n=c.keys(e),i=0;i1){var n,r=new Array(t-1),i=0;for(n=0;n0&&"function"!=typeof e&&"function"!=typeof t){var n=".then() only accepts functions but was passed: "+p.classString(e);arguments.length>1&&(n+=", "+p.classString(t)),this._warn(n)}return this._then(e,t,void 0,void 0,void 0)},a.prototype.done=function(e,t){this._then(e,t,void 0,void 0,void 0)._setIsFinal()},a.prototype.spread=function(e){return"function"!=typeof e?d("expecting a function but got "+p.classString(e)):this.all()._then(e,void 0,void 0,w,void 0)},a.prototype.toJSON=function(){var e={isFulfilled:!1,isRejected:!1,fulfillmentValue:void 0,rejectionReason:void 0};return this.isFulfilled()?(e.fulfillmentValue=this.value(),e.isFulfilled=!0):this.isRejected()&&(e.rejectionReason=this.reason(),e.isRejected=!0),e},a.prototype.all=function(){return arguments.length>0&&this._warn(".all() was passed arguments but it does not take any"),new T(this).promise()},a.prototype.error=function(e){return this.caught(p.originatesFromRejection,e)},a.getNewLibraryCopy=n.exports,a.is=function(e){return e instanceof a},a.fromNode=a.fromCallback=function(e){var t=new a(k);t._captureStackTrace();var n=arguments.length>1&&!!Object(arguments[1]).multiArgs,r=j(e)(M(t,n));return r===F&&t._rejectCallback(r.e,!0),t._isFateSealed()||t._setAsyncGuaranteed(),t},a.all=function(e){return new T(e).promise()},a.cast=function(e){var t=_(e);return t instanceof a||((t=new a(k))._captureStackTrace(),t._setFulfilled(),t._rejectionHandler0=e),t},a.resolve=a.fulfilled=a.cast,a.reject=a.rejected=function(e){var t=new a(k);return t._captureStackTrace(),t._rejectCallback(e,!0),t},a.setScheduler=function(e){if("function"!=typeof e)throw new b("expecting a function but got "+p.classString(e));return y.setScheduler(e)},a.prototype._then=function(e,t,n,r,i){var o=void 0!==i,s=o?i:new a(k),c=this._target(),l=c._bitField;o||(s._propagateFrom(this,3),s._captureStackTrace(),void 0===r&&0!=(2097152&this._bitField)&&(r=0!=(50397184&l)?this._boundValue():c===this?void 0:this._boundTo),this._fireEvent("promiseChained",this,s));var f=u();if(0!=(50397184&l)){var d,h,v=c._settlePromiseCtx;0!=(33554432&l)?(h=c._rejectionHandler0,d=e):0!=(16777216&l)?(h=c._fulfillmentHandler0,d=t,c._unsetRejectionIsUnhandled()):(v=c._settlePromiseLateCancellationObserver,h=new S("late cancellation observer"),c._attachExtraTrace(h),d=t),y.invoke(v,c,{handler:null===f?d:"function"==typeof d&&p.domainBind(f,d),promise:s,receiver:r,value:h})}else c._addCallbacks(e,t,s,r,f);return s},a.prototype._length=function(){return 65535&this._bitField},a.prototype._isFateSealed=function(){return 0!=(117506048&this._bitField)},a.prototype._isFollowing=function(){return 67108864==(67108864&this._bitField)},a.prototype._setLength=function(e){this._bitField=-65536&this._bitField|65535&e},a.prototype._setFulfilled=function(){this._bitField=33554432|this._bitField,this._fireEvent("promiseFulfilled",this)},a.prototype._setRejected=function(){this._bitField=16777216|this._bitField,this._fireEvent("promiseRejected",this)},a.prototype._setFollowing=function(){this._bitField=67108864|this._bitField,this._fireEvent("promiseResolved",this)},a.prototype._setIsFinal=function(){this._bitField=4194304|this._bitField},a.prototype._isFinal=function(){return(4194304&this._bitField)>0},a.prototype._unsetCancelled=function(){this._bitField=-65537&this._bitField},a.prototype._setCancelled=function(){this._bitField=65536|this._bitField,this._fireEvent("promiseCancelled",this)},a.prototype._setWillBeCancelled=function(){this._bitField=8388608|this._bitField},a.prototype._setAsyncGuaranteed=function(){y.hasCustomScheduler()||(this._bitField=134217728|this._bitField)},a.prototype._receiverAt=function(e){var t=0===e?this._receiver0:this[4*e-4+3];if(t!==h)return void 0===t&&this._isBound()?this._boundValue():t},a.prototype._promiseAt=function(e){return this[4*e-4+2]},a.prototype._fulfillmentHandlerAt=function(e){return this[4*e-4+0]},a.prototype._rejectionHandlerAt=function(e){return this[4*e-4+1]},a.prototype._boundValue=function(){},a.prototype._migrateCallback0=function(e){var t=(e._bitField,e._fulfillmentHandler0),n=e._rejectionHandler0,r=e._promise0,i=e._receiverAt(0);void 0===i&&(i=h),this._addCallbacks(t,n,r,i,null)},a.prototype._migrateCallbackAt=function(e,t){var n=e._fulfillmentHandlerAt(t),r=e._rejectionHandlerAt(t),i=e._promiseAt(t),a=e._receiverAt(t);void 0===a&&(a=h),this._addCallbacks(n,r,i,a,null)},a.prototype._addCallbacks=function(e,t,n,r,i){var a=this._length();if(a>=65531&&(a=0,this._setLength(0)),0===a)this._promise0=n,this._receiver0=r,"function"==typeof e&&(this._fulfillmentHandler0=null===i?e:p.domainBind(i,e)),"function"==typeof t&&(this._rejectionHandler0=null===i?t:p.domainBind(i,t));else{var o=4*a-4;this[o+2]=n,this[o+3]=r,"function"==typeof e&&(this[o+0]=null===i?e:p.domainBind(i,e)),"function"==typeof t&&(this[o+1]=null===i?t:p.domainBind(i,t))}return this._setLength(a+1),a},a.prototype._proxy=function(e,t){this._addCallbacks(void 0,void 0,t,e,null)},a.prototype._resolveCallback=function(e,t){if(0==(117506048&this._bitField)){if(e===this)return this._rejectCallback(l(),!1);var n=_(e,this);if(!(n instanceof a))return this._fulfill(e);t&&this._propagateFrom(n,2);var r=n._target();if(r===this)return void this._reject(l());var i=r._bitField;if(0==(50397184&i)){var o=this._length();o>0&&r._migrateCallback0(this);for(var s=1;s>>16)){if(e===this){var n=l();return this._attachExtraTrace(n),this._reject(n)}this._setFulfilled(),this._rejectionHandler0=e,(65535&t)>0&&(0!=(134217728&t)?this._settlePromises():y.settlePromises(this))}},a.prototype._reject=function(e){var t=this._bitField;if(!((117506048&t)>>>16)){if(this._setRejected(),this._fulfillmentHandler0=e,this._isFinal())return y.fatalError(e,p.isNode);(65535&t)>0?y.settlePromises(this):this._ensurePossibleRejectionHandled()}},a.prototype._fulfillPromises=function(e,t){for(var n=1;n0){if(0!=(16842752&e)){var n=this._fulfillmentHandler0;this._settlePromise0(this._rejectionHandler0,n,e),this._rejectPromises(t,n)}else{var r=this._rejectionHandler0;this._settlePromise0(this._fulfillmentHandler0,r,e),this._fulfillPromises(t,r)}this._setLength(0)}this._clearCancellationData()},a.prototype._settledValue=function(){var e=this._bitField;return 0!=(33554432&e)?this._rejectionHandler0:0!=(16777216&e)?this._fulfillmentHandler0:void 0},a.defer=a.pending=function(){return I.deprecated("Promise.defer","new Promise"),{promise:new a(k),resolve:o,reject:s}},p.notEnumerableProp(a,"_makeSelfResolutionError",l),t("./method")(a,k,_,d,I),t("./bind")(a,k,_,I),t("./cancel")(a,T,d,I),t("./direct_resolve")(a),t("./synchronous_inspection")(a),t("./join")(a,T,_,k,y,u),a.Promise=a,a.version="3.5.1",t("./map.js")(a,T,d,_,k,I),t("./call_get.js")(a),t("./using.js")(a,d,_,E,k,I),t("./timers.js")(a,k,I),t("./generators.js")(a,d,k,_,r,I),t("./nodeify.js")(a),t("./promisify.js")(a,k),t("./props.js")(a,T,_,d),t("./race.js")(a,k,_,d),t("./reduce.js")(a,T,d,_,k,I),t("./settle.js")(a,T,I),t("./some.js")(a,T,d),t("./filter.js")(a,k),t("./each.js")(a,k),t("./any.js")(a),p.toFastProperties(a),p.toFastProperties(a.prototype),c({a:1}),c({b:2}),c({c:3}),c(1),c(function(){}),c(void 0),c(!1),c(new a(k)),I.setBounds(g.firstLineError,p.lastLineError),a}},{"./any.js":1,"./async":2,"./bind":3,"./call_get.js":5,"./cancel":6,"./catch_filter":7,"./context":8,"./debuggability":9,"./direct_resolve":10,"./each.js":11,"./errors":12,"./es5":13,"./filter.js":14,"./finally":15,"./generators.js":16,"./join":17,"./map.js":18,"./method":19,"./nodeback":20,"./nodeify.js":21,"./promise_array":23,"./promisify.js":24,"./props.js":25,"./race.js":27,"./reduce.js":28,"./settle.js":30,"./some.js":31,"./synchronous_inspection":32,"./thenables":33,"./timers.js":34,"./using.js":35,"./util":36}],23:[function(e,t,n){"use strict";t.exports=function(t,n,r,i,a){function o(e){switch(e){case-2:return[];case-3:return{};case-6:return new Map}}function s(e){var r=this._promise=new t(n);e instanceof t&&r._propagateFrom(e,3),r._setOnCancel(this),this._values=e,this._length=0,this._totalResolved=0,this._init(void 0,-2)}var c=e("./util");return c.isArray,c.inherits(s,a),s.prototype.length=function(){return this._length},s.prototype.promise=function(){return this._promise},s.prototype._init=function e(n,a){var s=r(this._values,this._promise);if(s instanceof t){var u=(s=s._target())._bitField;if(this._values=s,0==(50397184&u))return this._promise._setAsyncGuaranteed(),s._then(e,this._reject,void 0,this,a);if(0==(33554432&u))return 0!=(16777216&u)?this._reject(s._reason()):this._cancel();s=s._value()}if(null!==(s=c.asArray(s)))0!==s.length?this._iterate(s):-5===a?this._resolveEmptyArray():this._resolve(o(a));else{var l=i("expecting an array or an iterable object but got "+c.classString(s)).reason();this._promise._rejectCallback(l,!1)}},s.prototype._iterate=function(e){var n=this.getActualLength(e.length);this._length=n,this._values=this.shouldCopyValues()?new Array(n):this._values;for(var i=this._promise,a=!1,o=null,s=0;s=this._length&&(this._resolve(this._values),!0)},s.prototype._promiseCancelled=function(){return this._cancel(),!0},s.prototype._promiseRejected=function(e){return this._totalResolved++,this._reject(e),!0},s.prototype._resultCancelled=function(){if(!this._isResolved()){var e=this._values;if(this._cancel(),e instanceof t)e.cancel();else for(var n=0;n=this._length){var n;if(this._isMap)n=d(this._values);else{n={};for(var r=this.length(),i=0,a=this.length();i>1},t.prototype.props=function(){return o(this)},t.props=function(e){return o(e)}}},{"./es5":13,"./util":36}],26:[function(e,t,n){"use strict";function r(e,t,n,r,i){for(var a=0;a=this._length&&(this._resolve(this._values),!0)},i.prototype._promiseFulfilled=function(e,t){var n=new a;return n._bitField=33554432,n._settledValueField=e,this._promiseResolved(t,n)},i.prototype._promiseRejected=function(e,t){var n=new a;return n._bitField=16777216,n._settledValueField=e,this._promiseResolved(t,n)},t.settle=function(e){return r.deprecated(".settle()",".reflect()"),new i(e).promise()},t.prototype.settle=function(){return t.settle(this)}}},{"./util":36}],31:[function(e,t,n){"use strict";t.exports=function(t,n,r){function i(e){this.constructor$(e),this._howMany=0,this._unwrap=!1,this._initialized=!1}function a(e,t){if((0|t)!==t||t<0)return r("expecting a positive integer\n\n See http://goo.gl/MqrFmX\n");var n=new i(e),a=n.promise();return n.setHowMany(t),n.init(),a}var o=e("./util"),s=e("./errors").RangeError,c=e("./errors").AggregateError,u=o.isArray,l={};o.inherits(i,n),i.prototype._init=function(){if(this._initialized){if(0===this._howMany)return void this._resolve([]);this._init$(void 0,-5);var e=u(this._values);!this._isResolved()&&e&&this._howMany>this._canPossiblyFulfill()&&this._reject(this._getRangeError(this.length()))}},i.prototype.init=function(){this._initialized=!0,this._init()},i.prototype.setUnwrap=function(){this._unwrap=!0},i.prototype.howMany=function(){return this._howMany},i.prototype.setHowMany=function(e){this._howMany=e},i.prototype._promiseFulfilled=function(e){return this._addFulfilled(e),this._fulfilled()===this.howMany()&&(this._values.length=this.howMany(),1===this.howMany()&&this._unwrap?this._resolve(this._values[0]):this._resolve(this._values),!0)},i.prototype._promiseRejected=function(e){return this._addRejected(e),this._checkOutcome()},i.prototype._promiseCancelled=function(){return this._values instanceof t||null==this._values?this._cancel():(this._addRejected(l),this._checkOutcome())},i.prototype._checkOutcome=function(){if(this.howMany()>this._canPossiblyFulfill()){for(var e=new c,t=this.length();t0?this._reject(e):this._cancel(),!0}return!1},i.prototype._fulfilled=function(){return this._totalResolved},i.prototype._rejected=function(){return this._values.length-this.length()},i.prototype._addRejected=function(e){this._values.push(e)},i.prototype._addFulfilled=function(e){this._values[this._totalResolved++]=e},i.prototype._canPossiblyFulfill=function(){return this.length()-this._rejected()},i.prototype._getRangeError=function(e){var t="Input array must contain at least "+this._howMany+" items but contains only "+e+" items";return new s(t)},i.prototype._resolveEmptyArray=function(){this._reject(this._getRangeError(0))},t.some=function(e,t){return a(e,t)},t.prototype.some=function(e){return a(this,e)},t._SomePromiseArray=i}},{"./errors":12,"./util":36}],32:[function(e,t,n){"use strict";t.exports=function(e){function t(e){void 0!==e?(e=e._target(),this._bitField=e._bitField,this._settledValueField=e._isFateSealed()?e._settledValue():void 0):(this._bitField=0,this._settledValueField=void 0)}t.prototype._settledValue=function(){return this._settledValueField};var n=t.prototype.value=function(){if(!this.isFulfilled())throw new TypeError("cannot get fulfillment value of a non-fulfilled promise\n\n See http://goo.gl/MqrFmX\n");return this._settledValue()},r=t.prototype.error=t.prototype.reason=function(){if(!this.isRejected())throw new TypeError("cannot get rejection reason of a non-rejected promise\n\n See http://goo.gl/MqrFmX\n");return this._settledValue()},i=t.prototype.isFulfilled=function(){return 0!=(33554432&this._bitField)},a=t.prototype.isRejected=function(){return 0!=(16777216&this._bitField)},o=t.prototype.isPending=function(){return 0==(50397184&this._bitField)},s=t.prototype.isResolved=function(){return 0!=(50331648&this._bitField)};t.prototype.isCancelled=function(){return 0!=(8454144&this._bitField)},e.prototype.__isCancelled=function(){return 65536==(65536&this._bitField)},e.prototype._isCancelled=function(){return this._target().__isCancelled()},e.prototype.isCancelled=function(){return 0!=(8454144&this._target()._bitField)},e.prototype.isPending=function(){return o.call(this._target())},e.prototype.isRejected=function(){return a.call(this._target())},e.prototype.isFulfilled=function(){return i.call(this._target())},e.prototype.isResolved=function(){return s.call(this._target())},e.prototype.value=function(){return n.call(this._target())},e.prototype.reason=function(){var e=this._target();return e._unsetRejectionIsUnhandled(),r.call(e)},e.prototype._value=function(){return this._settledValue()},e.prototype._reason=function(){return this._unsetRejectionIsUnhandled(),this._settledValue()},e.PromiseInspection=t}},{}],33:[function(e,t,n){"use strict";t.exports=function(t,n){function r(e){return e.then}function i(e){try{return r(e)}catch(e){return c.e=e,c}}function a(e){try{return l.call(e,"_promise0")}catch(e){return!1}}function o(e,r,i){var a=new t(n),o=a;i&&i._pushContext(),a._captureStackTrace(),i&&i._popContext();var u=!0,l=s.tryCatch(r).call(e,function(e){a&&(a._resolveCallback(e),a=null)},function(e){a&&(a._rejectCallback(e,u,!0),a=null)});return u=!1,a&&l===c&&(a._rejectCallback(l.e,!0,!0),a=null),o}var s=e("./util"),c=s.errorObj,u=s.isObject,l={}.hasOwnProperty;return function(e,r){if(u(e)){if(e instanceof t)return e;var s=i(e);if(s===c){r&&r._pushContext();var l=t.reject(s.e);return r&&r._popContext(),l}if("function"==typeof s)return a(e)?(l=new t(n),e._then(l._fulfill,l._reject,void 0,l,null),l):o(e,s,r)}return e}}},{"./util":36}],34:[function(e,t,n){"use strict";t.exports=function(t,n,r){function i(e){this.handle=e}function a(e){return clearTimeout(this.handle),e}function o(e){throw clearTimeout(this.handle),e}var s=e("./util"),c=t.TimeoutError;i.prototype._resultCancelled=function(){clearTimeout(this.handle)};var u=function(e){return l(+this).thenReturn(e)},l=t.delay=function(e,a){var o,s;return void 0!==a?(o=t.resolve(a)._then(u,null,null,e,void 0),r.cancellation()&&a instanceof t&&o._setOnCancel(a)):(o=new t(n),s=setTimeout(function(){o._fulfill()},+e),r.cancellation()&&o._setOnCancel(new i(s)),o._captureStackTrace()),o._setAsyncGuaranteed(),o};t.prototype.delay=function(e){return l(e,this)};var f=function(e,t,n){var r;r="string"!=typeof t?t instanceof Error?t:new c("operation timed out"):new c(t),s.markAsOriginatingFromRejection(r),e._attachExtraTrace(r),e._reject(r),null!=n&&n.cancel()};t.prototype.timeout=function(e,t){e=+e;var n,s,c=new i(setTimeout(function(){n.isPending()&&f(n,t,s)},e));return r.cancellation()?(s=this.then(),(n=s._then(a,o,void 0,c,void 0))._setOnCancel(c)):n=this._then(a,o,void 0,c,void 0),n}}},{"./util":36}],35:[function(e,t,n){"use strict";t.exports=function(t,n,r,i,a,o){function s(e){setTimeout(function(){throw e},0)}function c(e){var t=r(e);return t!==e&&"function"==typeof e._isDisposable&&"function"==typeof e._getDisposer&&e._isDisposable()&&t._setDisposable(e._getDisposer()),t}function u(e,n){var i=0,o=e.length,u=new t(a);return(function a(){if(i>=o)return u._fulfill();var l=c(e[i++]);if(l instanceof t&&l._isDisposable()){try{l=r(l._getDisposer().tryDispose(n),e.promise)}catch(e){return s(e)}if(l instanceof t)return l._then(a,s,null,null,null)}a()})(),u}function l(e,t,n){this._data=e,this._promise=t,this._context=n}function f(e,t,n){this.constructor$(e,t,n)}function d(e){return l.isDisposer(e)?(this.resources[this.index]._setDisposable(e),e.promise()):e}function h(e){this.length=e,this.promise=null,this[e-1]=null}var p=e("./util"),v=e("./errors").TypeError,g=e("./util").inherits,y=p.errorObj,m=p.tryCatch,b={};l.prototype.data=function(){return this._data},l.prototype.promise=function(){return this._promise},l.prototype.resource=function(){return this.promise().isFulfilled()?this.promise().value():b},l.prototype.tryDispose=function(e){var t=this.resource(),n=this._context;void 0!==n&&n._pushContext();var r=t!==b?this.doDispose(t,e):null;return void 0!==n&&n._popContext(),this._promise._unsetDisposable(),this._data=null,r},l.isDisposer=function(e){return null!=e&&"function"==typeof e.resource&&"function"==typeof e.tryDispose},g(f,l),f.prototype.doDispose=function(e,t){return this.data().call(e,e,t)},h.prototype._resultCancelled=function(){for(var e=this.length,n=0;n0},t.prototype._getDisposer=function(){return this._disposer},t.prototype._unsetDisposable=function(){this._bitField=-131073&this._bitField,this._disposer=void 0},t.prototype.disposer=function(e){if("function"==typeof e)return new f(e,this,i());throw new v}}},{"./errors":12,"./util":36}],36:[function(n,r,i){"use strict";function a(){try{var e=d;return d=null,e.apply(this,arguments)}catch(e){return v.e=e,v}}function o(e){return null==e||!0===e||!1===e||"string"==typeof e||"number"==typeof e}function s(e,t,n){if(o(e))return e;var r={value:n,configurable:!0,enumerable:!1,writable:!0};return h.defineProperty(e,t,r),e}function c(e){try{return e+""}catch(e){return"[no string representation]"}}function u(e){return e instanceof Error||null!==e&&"object"==typeof e&&"string"==typeof e.message&&"string"==typeof e.name}function l(e){return u(e)&&h.propertyIsWritable(e,"stack")}function f(e){return{}.toString.call(e)}var d,h=n("./es5"),p="undefined"==typeof navigator,v={e:{}},g="undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==t?t:void 0!==this?this:null,y=(function(){var e=[Array.prototype,Object.prototype,Function.prototype],t=function(t){for(var n=0;n1,r=t.length>0&&!(1===t.length&&"constructor"===t[0]),i=m.test(e+"")&&h.names(e).length>0;if(n||r||i)return!0}return!1}catch(e){return!1}},isIdentifier:function(e){return b.test(e)},inheritedDataKeys:y,getDataPropertyOrDefault:function(e,t,n){if(!h.isES5)return{}.hasOwnProperty.call(e,t)?e[t]:void 0;var r=Object.getOwnPropertyDescriptor(e,t);return null!=r?null==r.get&&null==r.set?r.value:n:void 0},thrower:function(e){throw e},isArray:h.isArray,asArray:k,notEnumerableProp:s,isPrimitive:o,isObject:function(e){return"function"==typeof e||"object"==typeof e&&null!==e},isError:u,canEvaluate:p,errorObj:v,tryCatch:function(e){return d=e,a},inherits:function(e,t){function n(){for(var n in this.constructor=e,this.constructor$=t,t.prototype)r.call(t.prototype,n)&&"$"!==n.charAt(n.length-1)&&(this[n+"$"]=t.prototype[n])}var r={}.hasOwnProperty;return n.prototype=t.prototype,e.prototype=new n,e.prototype},withAppended:function(e,t){var n,r=e.length,i=new Array(r+1);for(n=0;n10||t[0]>0})(),T.isNode&&T.toFastProperties(e);try{throw new Error}catch(e){T.lastLineError=e}r.exports=T},{"./es5":13}]},{},[4])(4)}),"undefined"!=typeof window&&null!==window?window.P=window.Promise:"undefined"!=typeof self&&null!==self&&(self.P=self.Promise)}).call(this,t("_process"),void 0!==e?e:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},t("timers").setImmediate)},{_process:15,timers:16}],2:[function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0}),n.PreCallTest=void 0;var i=(function(){function e(e,t){for(var n=0;n=10?e.stop():(e.turnConnection.disconnect(),setTimeout(function(){e._start()},0))}))}},{key:"stop",value:function(){var e=this;if(this.browserInfo.browserName!==l.Constants.browserName.msie&&this.active){this.active=!1,this.activeTurnTest&&this.activeTurnTest.forceStop();var t=this.onlineCheck.stop();this.resultsHandler&&this.resultsHandler.add("onlineStatus",t),this.turnConnection.getIceResults().then(function(t){e.resultsHandler&&e.resultsHandler.add("ice",t),e.turnConnection.disconnect(),e.sendResults()},function(t){e.resultsHandler&&e.resultsHandler.failure(t),e.turnConnection.disconnect(),e.sendResults()})}}},{key:"sendResults",value:function(){if(this.resultsHandler){var e=this.resultsHandler.getResults();this.resultsHandler=null,this.callback&&this.callback(e,null)}else this.callback&&this.callback(null,"No results present")}},{key:"callStarts",value:function(){this.callsInProgress+=1,this.resultsHandler&&this.resultsHandler.setStatusStopped(),this.stop()}},{key:"callFinished",value:function(){this.callsInProgress-=1}},{key:"getId",value:function(){return this.resultsHandler?this.resultsHandler.getId():null}},{key:"crashDisconnect",value:function(){try{this.turnConnection.disconnect()}catch(e){}}},{key:"startTurnTests",value:function(){var e=this;if(this.turnTestCounter>=this.turnTests.length)return new f(function(e,t){e()});var t=this.turnTests[this.turnTestCounter],n=null;switch(t){case d.RTT:n=new o.RttTest(this.turnConnection);break;case d.THROUGHPUT:n=new s.ThroughputTest(this.turnConnection,this.rtt);break;default:return new f(function(e,n){n(new Error("Unknown test: "+t))})}return this.activeTurnTest=n,this.active?n.start().then(function(){return e.handleTestResults(t,n.getResults()),e.turnTestCounter+=1,e.activeTurnTest=null,e.startTurnTests()},function(r){return e.handleTestResults(t,n.getResults(),r),e.turnTestCounter+=1,e.activeTurnTest=null,e.startTurnTests()}):new f(function(e,t){t(new Error("Test trying to start while testing is not active"))})}},{key:"handleTestResults",value:function(e,t){null==(2=this.intervalLength){var r=n-this.intervalStart,i=this.averageThroughput(this.intervalBytes,r),a=null;try{a=n-JSON.parse(this.lastMessage).timestamp}catch(e){}this.intervals.push({startTimestamp:this.intervalStart,endTimestamp:n,bytesReceived:this.intervalBytes,average:i,rtt:a}),this.intervalStart=n,this.intervalBytes=0}this.results.startTimestamp&&n-this.results.startTimestamp>this.duration/2&&(this.secondHalfStart||(this.secondHalfStart=n),this.secondHalfBytes+=e.length)}}},{key:"handleError",value:function(e){this.stop(),this.failed(e)}},{key:"averageThroughput",value:function(e,t){return e/(t/1e3)*8/1024}},{key:"bufferListener",value:function(){this.sendChannel.removeEventListener("bufferedamountlow",this.bufferListener.bind(this)),this.fillBuffer()}},{key:"fillBuffer",value:function(){for(0==this.sendChannel.bufferedAmount&&(this.bufferEmpty+=1);this.isActive();){if(this.sendChannel.bufferedAmount>this.bufferFullThreshold)return void(this.usePolling?setTimeout(this.fillBuffer.bind(this),250):this.sendChannel.addEventListener("bufferedamountlow",this.bufferListener.bind(this)));var e=this.messageMaker.make(this.sentBytes);this.sentBytes+=e.length,this.send(e)}this.sendChannel.removeEventListener("bufferedamountlow",this.bufferListener.bind(this))}},{key:"startSend",value:function(){this.isActive()&&(this.bufferFullThreshold=1e3*this.chunkSize,this.sendChannel=this.connection.sendChannel,this.usePolling=!0,"number"==typeof this.sendChannel.bufferedAmountLowThreshold&&(this.usePolling=!1,this.sendChannel.bufferedAmountLowThreshold=this.bufferFullThreshold/10),setTimeout(this.fillBuffer.bind(this),0))}},{key:"fillResults",value:function(){this.results.endTimestamp=c.getCurrent(),this.results.maxDuration=this.duration,this.results.forceStopped=this.forceStopped,this.results.bufferEmpty=this.bufferEmpty,this.results.intervals=this.intervals,this.results.bytesPrepared=this.sentBytes,this.results.bytesReceived=this.receivedBytes;var e=0,t=0;this.secondHalfStart&&(e=this.results.endTimestamp-this.secondHalfStart,t=this.averageThroughput(this.secondHalfBytes,e));var n=this.results.endTimestamp-this.results.startTimestamp,r=this.averageThroughput(this.receivedBytes,n);t>24;if("rtp"===this.protocol&&0<=n&&n<=2)switch(n){case 0:t="TLS";break;case 1:t="TCP";break;case 2:t="UDP"}return t}},{key:"getString",value:function(){return this.iceCandidateStr}},{key:"getType",value:function(){return this.type}},{key:"isHost",value:function(){return"host"===this.type.toLowerCase()}},{key:"isServerReflexive",value:function(){return"srflx"===this.type.toLowerCase()}},{key:"isPeerReflexive",value:function(){return"prflx"===this.type.toLowerCase()}},{key:"isRelay",value:function(){return"relay"===this.type.toLowerCase()||"relayed"===this.type.toLowerCase()}},{key:"getTypeTransport",value:function(){return this.typeTransport}},{key:"isTypeTransportUdp",value:function(){return"UDP"===this.typeTransport}},{key:"isTypeTransportTcp",value:function(){return"TCP"===this.typeTransport}},{key:"isTypeTransportTls",value:function(){return"TLS"===this.typeTransport}},{key:"getTransport",value:function(){return this.transport}},{key:"isUdp",value:function(){return"udp"===this.transport.toLowerCase()}},{key:"isTcp",value:function(){return"tcp"===this.transport.toLowerCase()}},{key:"getProtocol",value:function(){return this.protocol}},{key:"isRtp",value:function(){return"rtp"===this.protocol}},{key:"isRtcp",value:function(){return"rtcp"===this.protocol}},{key:"isIpv6",value:function(){return this.ipv6}},{key:"getIpAddress",value:function(){return this.ipAddress}},{key:"getPort",value:function(){return this.port}}]),e})();n.ParsedIceCandidate=a},{}],10:[function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0}),n.ResultsHandler=void 0;var i="function"==typeof Symbol&&"symbol"==typeof("function"==typeof Symbol?Symbol.iterator:"@@iterator")?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==("function"==typeof Symbol?Symbol.prototype:"@@prototype")?"symbol":typeof e},a=(function(){function e(e,t){for(var n=0;n>24;c.mozLocalTransport=this.formatRelayType(u)}c.mozLocalTransport=c.mozLocalTransport.toLowerCase()}t.push(c)}else s.remoteCandidate&&n.push(s.remoteCandidate)}if(i)for(var l=0;l1)for(var n=1;n=0&&(e._idleTimeoutId=setTimeout(function(){e._onTimeout&&e._onTimeout()},t))},n.setImmediate="function"==typeof t?t:function(e){var t=u++,r=!(arguments.length<2)&&s.call(arguments,1);return c[t]=!0,a(function(){c[t]&&(r?e.apply(null,r):e.call(null),n.clearImmediate(t))}),t},n.clearImmediate="function"==typeof r?r:function(e){delete c[e]}}).call(this,e("timers").setImmediate,e("timers").clearImmediate)},{"process/browser.js":15,timers:16}],17:[function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var i=(function(){function e(e,t){for(var n=0;n2&&void 0!==arguments[2]?arguments[2]:"")}function s(){var e=null,t=v.Registry.getEndpoint().getBrowserName();return"Firefox"===t?e=mozRTCPeerConnection:"Chrome"===t||"Opera"===t?e=webkitRTCPeerConnection:"Safari"===t?g.log("Browser type Safari"):"Edge"===t&&(e=window.RTCPeerConnection),e}function c(e){if(null===e)return!1;var t=v.Registry.getEndpoint().getCodeBase();if(t===f.codeBaseType.firefox)return"undefined"!=typeof mozRTCPeerConnection&&e instanceof mozRTCPeerConnection||"undefined"!=typeof RTCPeerConnection&&e instanceof RTCPeerConnection;if(t===f.codeBaseType.edge||"function"==typeof e)return!0;var n=s();return null!==n&&e instanceof n||void 0!==e.createOffer}var u="function"==typeof Symbol&&"symbol"==typeof("function"==typeof Symbol?Symbol.iterator:"@@iterator")?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==("function"==typeof Symbol?Symbol.prototype:"@@prototype")?"symbol":typeof e},l=(function(){function e(e,t){for(var n=0;n ("+r+") ["+t.toString()+"]"),null!==t.getLeft()&&e(t.getLeft(),n+1,"Left"),null!==t.getRight()&&e(t.getRight(),n+1,"Right")}})(this.root,0,"Root")):s.log("This tree is empty Duplicate Counter: "+this.duplicate_counter)}}]),e})();n.BinaryTree=c},{"../utility/csiologger":92,"./binarytreenode.js":24}],24:[function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var i=(function(){function e(e,t){for(var n=0;n1&&void 0!==arguments[1]&&arguments[1];this.length()>1e6?a.error("Maximum cached items reached, dropping."):t?this.priority.push(e):this.queue.push(e)}},{key:"pop",value:function(){return this.priority.length>0?this.priority.shift():this.queue.shift()}},{key:"peak",value:function(){return this.priority.length>0?this.priority[0]:this.queue.length>0?this.queue[0]:null}},{key:"length",value:function(){return this.queue.length+this.priority.length}},{key:"updateConferenceId",value:function(e){for(var t=0;t0&&void 0!==arguments[0]?arguments[0]:"Unknown";r(this,e),this.name=t,this.ports=new Map}return i(e,[{key:"bindPort",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this;this.ports.has(e)?o.warn("Port ("+e+") for "+this.name+" already exists."):this.ports.set(e,new a.Port(t,n))}},{key:"declarePort",value:function(e){this.ports.has(e)?o.warn("Port ("+e+") for "+this.name+" already exists."):this.ports.set(e,null)}},{key:"getPort",value:function(e){return this.ports.get(e)}},{key:"isConnected",value:function(e){return!!this.ports.has(e)&&null!==this.ports.get(e)}},{key:"connect",value:function(e,t){this.ports.has(e)?this.ports.set(e,t):o.warn("Port ("+e+") for "+this.name+" does not exists.")}},{key:"transmit",value:function(e){var t=this.ports.get(e);if(void 0!==t)if(null!==t){for(var n=arguments.length,r=Array(n>1?n-1:0),i=1;i1?n-1:0),i=1;i=a.pctSampleSize&&this.pctMeasurements.shift(),this.pctMeasurements.push(e);var t=e.getProvider();this.pctMeasurementsMap.has(t)||this.pctMeasurementsMap.set(t,[]),this.pctMeasurementsMap.get(t).push(e)}},{key:"clearPCTMeasurements",value:function(){this.pctMeasurements=[],this.pctMeasurementsMap=new Map}},{key:"doStats",value:function(e){var t={};return t.min=this.findMin(e),t.max=this.findMax(e),t.mean=this.calculateAverage(e),t.median=this.calculateMedian(e),t.stddev=this.calculateStandardDeviation(e,t.mean),t}},{key:"findMax",value:function(e){return e&&e.length?Math.max.apply(null,e):null}},{key:"findMin",value:function(e){return e&&e.length?Math.min.apply(null,e):null}},{key:"calculateAverage",value:function(e){return e&&e.length?e.reduce(function(e,t){return e+t},0)/e.length:0}},{key:"calculateMedian",value:function(e){if(!e)return 0;if(!e.length)return 0;var t=e.slice(0).sort(function(e,t){return e-t}),n=Math.floor(t.length/2);return t.length%2==0?(t[n]+t[n-1])/2:t[n]}},{key:"calculateStandardDeviation",value:function(e,t){if(!e)return 0;if(!e.length)return 0;var n=e.map(function(e){var n=e-t;return n*n}).reduce(function(e,t){return e+t},0);return Math.sqrt(n/(e.length-1))}},{key:"setAcceptability",value:function(e){var t=[];return t.push(e.throughput.median<30),t.push(e.loss.median>.05),t.push(e.rtt.median>400),e.acceptable=!t.reduce(function(e,t){return e||t},!1),e}},{key:"doInternalMeasurement",value:function(e){var t={},n=[],r=[],i=[],a=[];if(e)for(var o=0;o=.04?t-=3:t,t=n>=.025?t-=1:t,t=n>=.01?t-=1:t,t=r>=.04?t-=5:t,t=r>=.025?t-=3:t,r>=.005?t-=2:t}},{key:"scoreThroughPut",value:function(e){var t=0;if(!e||!e.throughput)return t;var n=e.throughput.median,r=e.throughput.min;return t=n>5e3?t+=5:t,t=n>2e3?t+=2:t,t=n>200?t+=1:t,t=r<100?t-=3:t,t=r<1e3?t-=2:t,(t=r<2e3?t-=1:t)>0?t:0}},{key:"aggregate",value:function(){var e=this,t=[];return e.pctMeasurementsMap.forEach(function(n,r){var i={};i.provider=r;var a=e.doInternalMeasurement(n);i.rtt=a.rtt,i.jitter=a.jitter,i.loss=a.loss,i.throughput=a.throughput,(i=e.setAcceptability(i)).rttScore=e.scoreRtt(),i.lossesScore=e.scoreLosses(),i.throughputScore=e.scoreThroughPut(),t.push(i)}),t}},{key:"getAggregate",value:function(e){var t=[];if(!e)return t;for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:null;r(this,e),this.target=t,this.object=n}return i(e,[{key:"transmit",value:function(e){this.target.apply(this.object,e)}},{key:"request",value:function(e){return this.target.apply(this.object,e)}}]),e})();n.Port=a},{}],30:[function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var i=Object.assign||function(e){for(var t=1;t1&&void 0!==arguments[1]?arguments[1]:void 0;r(this,e),this.value=t,this.next=n}return a(e,[{key:"setNext",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:void 0;this.next=e}}]),e})(),s=(function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0;r(this,e),this.capacity=t,this.root=n,this.tail=i,this.currentLength=0}return a(e,[{key:"size",value:function(){return this.currentLength}},{key:"isEmpty",value:function(){return this.currentLength<1}},{key:"isOverflow",value:function(){return this.size()>this.capacity}},{key:"push",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,t=this.tail;this.tail=new o(e),this.isEmpty()?this.root=this.tail:t.setNext(this.tail),this.currentLength+=1;var n=void 0;return this.isOverflow()&&(n=this.pop()),n}},{key:"pop",value:function(){if(!this.isEmpty()){var e=this.root.value;return this.root=this.root.next,this.currentLength-=1,e}}},{key:"getFront",value:function(){return this.root}},{key:"getBack",value:function(){return this.tail}},{key:"clear",value:function(){this.root=void 0,this.tail=void 0,this.currentLength=0}},{key:"toArray",value:function(){for(var e=i({},this.root),t=[];e;){var n=e,r=n.value;e=n.next,t.push(r)}return t}}]),e})();n.Queue=s},{}],31:[function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0}),n.SlidingWindow=void 0;var i=(function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:0;return this.items.length<=e?null:this.items[this.items.length-e-1].getValue()}},{key:"attach",value:function(e){this.plugins.push(e)}},{key:"addPreProcess",value:function(e){this.preProcesses.push(e)}},{key:"addPostProcess",value:function(e){this.postProcesses.push(e)}},{key:"detach",value:function(e){this.plugins=this.plugins.filter(function(t){return t!==e})}}]),e})();n.SlidingWindow=s},{"../utility/timestamps":104,"./switem":32}],32:[function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0}),n.SWItem=void 0;var i=(function(){function e(e,t){for(var n=0;n>>0,r=arguments[1],i=void 0,a=0;a0&&f.Registry.getEventMessageBuilder().make(v.precalltestEvents.associate,r,e,{ids:u})}},{key:"onStartPrecallTests",value:function(e,t){var n=f.Registry.getAuthenticator().getIceServers();n[0].label="callstats",e.push(n[0]),f.Registry.getPCTRunnerService().start(e,t)}},{key:"onSendCallDetails",value:function(e,t,n){d.warn("FSM onSendCallDetails");var r={};r.callType=n.callType,r.role=n.role,n.contactQueue&&(r.contactQueue=n.contactQueue),n.contactQueueID&&(r.contactQueueID=n.contactQueueID),n.routingProfile&&(r.routingProfile=n.routingProfile),n.routingProfileID&&(r.routingProfileID=n.routingProfileID),n.contactID&&(r.contactID=n.contactID),n.siteID&&(r.siteID=n.siteID,f.Registry.getCredentials().setSiteId(n.siteID)),f.Registry.getEventMessageBuilder().make(v.fabricEvent.callDetails,t,e,r)}},{key:"onSendFabricEvent",value:function(e,t,n,r){d.warn("FSM onSendFabricEvent");var i={};r&&((i=r).ssrc&&(i.ssrc=String(i.ssrc))),t===v.fabricEvent.activeDeviceList&&(i={mediaDeviceList:h.normalizeMediaDeviceList(r.deviceList)}),f.Registry.getEventMessageBuilder().make(t,n,e,i);var a=f.Registry.getConferenceManager().get(n);if(a){var o=a.getPeerConnectionManager().getPcHandler(e);t!==v.fabricEvent.fabricTerminated&&t!==v.internalFabricEvent.fabricSetupFailed||(o.stopUserAliveHandler(),o.setPcState(v.fabricState.terminated),o.stopStatsPolling(),a.getPeerConnectionManager().removePcStats(o&&o.getPcHash()),a.updateState()),t===v.fabricEvent.fabricHold&&(o.setPcState(v.fabricState.hold),o.stopStatsPolling()),t===v.fabricEvent.fabricResume&&(o.setPcState(v.fabricState.established),o.startStatsPolling())}}},{key:"onReportError",value:function(e,t,n,r,i,a){d.warn("FSM onReportError");var o={delay:0,reason:this.callFailureClassifier(n),function:n,magicKey:f.Registry.getEndpoint().getMagicKey(),endpoint:f.Registry.getEndpoint().serialize(),level:"debug"};if(r){var s=this.formatDomError(r);o.message=s.message,o.messageType=s.messageType,o.name=r.name,o.stack=r.stack}if(e){var c=f.Registry.getConferenceManager().get(t),u=void 0;if(c&&(u=c.getPeerConnectionManager().getPcHandler(e)),!u)return void d.error("onReportError: No handler found for given PeerConnection!");if(o.delay=p.getCurrent()-u.getStartTime(),o.fabricState=u.getPcState(),o.iceConnectionState=u.getIceConnectionState(),(i||a||e&&"closed"!==e.signalingState)&&f.Registry.getCredentials().getCollectSDP()&&n!==v.webRTCFunctions.applicationLog){var l={};l.localSDP=this.pickSDP(e,i,"localDescription"),l.remoteSDP=this.pickSDP(e,a,"remoteDescription"),f.Registry.getEventMessageBuilder().make(v.callstatsChannels.sdpSubmission,t,e,l)}}n===v.webRTCFunctions.applicationLog||n===v.webRTCFunctions.applicationError?f.Registry.getEventMessageBuilder().make(v.fabricEvent.applicationErrorLog,t,e,o):n===v.webRTCFunctions.iceConnectionFailure?this.handleIceConnectionFailure(e,t,o):(f.Registry.getEventMessageBuilder().make(v.fabricEvent.fabricSetupFailed,t,e,o),n===v.webRTCFunctions.getUserMedia&&this.handleGUMErrors(t))}},{key:"onAssociateMstWithUserID",value:function(e,t,n,r,i,a){var o=f.Registry.getConferenceManager().get(n);if(o){var s=o.getPeerConnectionManager().getPcHandler(e);"string"!=typeof r&&(r+=""),s.updateSSRCInfo(r,t,i,a)}}},{key:"onAttachWifiStatsHandler",value:function(e){f.Registry.getWifiStatsExecutor().setGetWifiStatsMethod(e)}},{key:"onSetProxyConfig",value:function(e){d.warn("FSM onSetProxyConfig"),e.collectorURL&&g.setBaseUrl(e.collectorURL),e.authServiceURL&&g.setAuthServiceUrl(e.authServiceURL),e.csioInternalAPIURL&&g.setQmodelThresholdsAPIUrl(e.csioInternalAPIURL),e.wsURL&&g.setWsUrl(e.wsURL),e.restEventURL&&g.setRestEventUrl(e.restEventURL),e.restStatsURL&&g.setRestStatsUrl(e.restStatsURL),e.appSettingsURL&&g.setConfigServiceUrl(e.appSettingsURL)}},{key:"onSendUserFeedback",value:function(e,t,n){var r={feedback:{overallRating:t.overall}};t.video&&(r.feedback.videoQualityRating=t.video),t.audio&&(r.feedback.audioQualityRating=t.audio),t.comment&&(r.feedback.comments=t.comment),f.Registry.getEventMessageBuilder().make(v.callstatsChannels.userFeedback,e,null,r)}},{key:"onOn",value:function(e,t){f.Registry.getCallbacks().set(e,t)}},{key:"onSetIdentifiers",value:function(e,t){if(e.conferenceID&&(f.Registry.getConferenceManager().updateConferenceId(e.conferenceID),f.Registry.getTransmissionManager().updateConferenceId(e.conferenceID),f.Registry.getTransmissionManager().trySend()),e.remoteUserID&&t){var n=f.Registry.getConferenceManager().getConferenceForPc(t);if(!n)return void d.log("onSetIdentifiers conference not found");var r=n.getPeerConnectionManager().getPcHandler(t);if(!r)return void d.log("pcHandler not found");r.updateRemoteId(e.remoteUserID),f.Registry.getTransmissionManager().trySend()}}},{key:"onMakePrecallTest",value:function(e,t){var n=e,r=t||"callstats";e||(n=this.authenticator.getIceServers(),r="callstats"),f.Registry.getPCTRunnerService().doPrecalltest(n,r)}},{key:"handleIceConnectionFailure",value:function(e,t,n){if(e){var r=f.Registry.getConferenceManager().get(t),i=void 0;if(r&&(i=r.getPeerConnectionManager().getPcHandler(e)),i)if(i.isFabricSetupSent()){var a={localIceCandidates:[],remoteIceCandidates:[],iceCandidatePairs:[]};a.delay=p.getCurrent()-i.getStartTime(),a.currIceConnectionState="failed",a.prevIceConnectionState="disconnected",f.Registry.getEventMessageBuilder().make(v.internalFabricEvent.iceFailed,t,e,a)}else n.delay=p.getCurrent()-i.getStartTime(),n.fabricState=i.getPcState(),n.iceConnectionState=i.getIceConnectionState(),f.Registry.getEventMessageBuilder().make(v.fabricEvent.fabricSetupFailed,t,e,n)}}},{key:"handleGUMErrors",value:function(e){var t=f.Registry.getConferenceManager().get(e);if(t||(f.Registry.getConferenceManager().add(e,f.Registry.getCredentials()),t=f.Registry.getConferenceManager().get(e)),!t.getUcId()){var n={endpointInfo:f.Registry.getEndpoint().serialize()};f.Registry.getEventMessageBuilder().make(v.internalFabricEvent.userJoined,e,null,n),t.setUserJoinedSent(!0)}}},{key:"callFailureClassifier",value:function(e){var t=void 0;return v.webRTCFunctions.hasOwnProperty(e)?e===v.webRTCFunctions.createOffer||e===v.webRTCFunctions.createAnswer||e===v.webRTCFunctions.setRemoteDescription?t=v.callFailureReasons.negotiationFailure:e===v.webRTCFunctions.setLocalDescription?t=v.callFailureReasons.sdpError:e===v.webRTCFunctions.addIceCandidate?t=v.callFailureReasons.sdpError:e===v.webRTCFunctions.getUserMedia?t=v.callFailureReasons.mediaConfigError:e===v.webRTCFunctions.iceConnectionFailure?t=v.callFailureReasons.iceFailure:e===v.webRTCFunctions.signalingError?t=v.callFailureReasons.signalingError:(e===v.webRTCFunctions.applicationLog||v.webRTCFunctions.applicationError)&&(t=v.callFailureReasons.applicationLog):t=v.callFailureReasons.invalidWebRTCFunctionName,t}},{key:"formatDomError",value:function(e){var t={},n={};e&&(window.DOMException&&e instanceof window.DOMException?(n.message=e.message,n.name=e.name,t.messageType="domError"):"object"===(void 0===e?"undefined":c(e))?(e.message&&(n.message=e.message),e.name&&(n.name=e.name),e.constraintName&&(n.name=e.constraintName),e.stack&&(n.stack=e.stack),t.messageType="json"):(n=e,t.messageType="text"));var r=this.truncateLog(n);return"object"===(void 0===r?"undefined":c(r))?t.message=JSON.stringify(r):t.message=r,t}},{key:"pickSDP",value:function(e,t,n){return t||(e&&e[n]?e[n].sdp:"")}},{key:"truncateString",value:function(e){return e.length>2e4&&(d.log("Log exceeds 20kb, It will be truncated"),e=e.substring(0,2e4)),e}},{key:"truncateLog",value:function(e){return e?("string"==typeof e?e=this.truncateString(e):"object"===(void 0===e?"undefined":c(e))&&e.message&&(e.message=this.truncateString(e.message)),e):e}}]),t})();n.MainFSM=T},{"../config/constants":36,"../config/settings":37,"../statspipeline/statsadapter":73,"../statspipeline/statsassembler":74,"../statspipeline/statsmonitor":76,"../statspipeline/statsparser":77,"../statspipeline/statstransmitter":78,"../utility/csiologger":92,"../utility/registry":100,"../utility/timestamps":104,"../utility/utils":106,"./statemachine":40}],39:[function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var i=(function(){function e(e,t){for(var n=0;n1?t-1:0),r=1;r",this.iceConnectionState);var e={changedState:o.fabricStateChangeType.iceConnectionState,prevState:this.oldIceConnectionState,newState:this.iceConnectionState};this.sendFabricStateChange(e)}},{key:"handleIceGatheringState",value:function(){if(this.iceGatheringState!==this.pc.iceGatheringState){"complete"===this.pc.iceGatheringState&&(this.iceGatheringDelay=c.getCurrent()-this.startTime),this.oldIceGatheringState=this.iceGatheringState,this.iceGatheringState=this.pc.iceGatheringState,l.warn("CALLBACK: ICE gathering state change",this.oldIceGatheringState,"->",this.iceGatheringState);var e={changedState:o.fabricStateChangeType.iceGatheringState,prevState:this.oldIceGatheringState,newState:this.iceGatheringState};this.sendFabricStateChange(e)}}},{key:"handleIceChecking",value:function(){var e=c.getCurrent();if("disconnected"===this.oldIceConnectionState&&(this.pcState===o.fabricState.checkingDisrupted||this.pcState===o.fabricState.disrupted)){var t={prevIceConnectionState:this.oldIceConnectionState,currIceConnectionState:this.iceConnectionState,delay:e-this.connectionDisruptedTS};this.pcState===o.fabricState.disrupted&&(t.prevIceCandidatePair=this.prevActiveIceCandidatePair,t.currIceCandidatePair=this.activeIceCandidatePair,t.delay=e-this.disruptedTS,this.emb.make(o.internalFabricEvent.iceDisruptionEnd,this.conferenceId,this.pc,t)),this.pcState=o.fabricState.initializing,this.emb.make(o.internalFabricEvent.iceConnectionDisruptionEnd,this.conferenceId,this.pc,t)}}},{key:"handleIceConnectedOrCompleted",value:function(e){var t=c.getCurrent();this.pcState===o.fabricState.disrupted&&(e.prevIceCandidatePair=this.prevActiveIceCandidatePair,e.currIceCandidatePair=this.activeIceCandidatePair,e.delay=t-this.disruptedTS,this.emb.make(o.internalFabricEvent.iceDisruptionEnd,this.conferenceId,this.pc,e)),this.iceConnectivityDelay=t-this.startTime,this.established=!0,this.pcState=o.fabricState.established,this.sendfabricSetup(),this.startStatsPolling()}},{key:"sendfabricSetup",value:function(){if(this.fabricSetupSent)l.log("fabricSetup has been sent already");else{var e={delay:c.getCurrent()-this.startTime,iceGatheringDelay:this.iceGatheringDelay,iceConnectivityDelay:this.iceConnectivityDelay,localIceCandidates:this.localIceCandidates,remoteIceCandidates:this.remoteIceCandidates,iceCandidatePairs:this.iceCandidatePairs,remoteEndpointType:o.endpointType.peer,fabricTransmissionDirection:o.transmissionDirection.sendrecv,iceServers:this.iceServersURLs,sdpSemantics:this.sdpSemantics},t=this.getActiveIceCandidatePair();t&&(e.selectedCandidatePairID=t.id),this.fabricSetupSent=!0;var n=void 0;if(this.conferenceId){var r=s.Registry.getConferenceManager().get(this.conferenceId);r&&r.getPeerConnectionManager()&&(n=r.getPeerConnectionManager().getPcHandler(this.pc),e.remoteEndpointType=n.getRemoteEndpointType(),e.fabricTransmissionDirection=n.getFabricTransmissionDirection())}this.pcState=o.fabricState.established,this.emb.make(o.internalFabricEvent.fabricSetup,this.conferenceId,this.pc,e)}}},{key:"isFabricSetupSent",value:function(){return this.fabricSetupSent}},{key:"startStatsPolling",value:function(){this.getStatsHandler.startStatsPolling()}},{key:"stopStatsPolling",value:function(){this.getStatsHandler.stopStatsPolling()}},{key:"handleIceFailed",value:function(e){e.currIceCandidatePair=this.activeIceCandidatePair,e.delay=c.getCurrent()-this.startTime,this.pcState=o.fabricState.failed,"checking"===e.prevIceConnectionState?this.sendIceFailed(e):"completed"===e.prevIceConnectionState||"connected"===e.prevIceConnectionState?this.emb.make(o.internalFabricEvent.fabricDropped,this.conferenceId,this.pc,e):"disconnected"===e.prevIceConnectionState&&this.established?this.emb.make(o.internalFabricEvent.fabricDropped,this.conferenceId,this.pc,e):"disconnected"===e.prevIceConnectionState&&this.sendIceFailed(e)}},{key:"getActiveIceCandidatePair",value:function(){var e=null,t=this.iceCandidatePairs;if(t&&t.length>0){var n=t.filter(function(e){return"true"===e.selected||"true"===e.googActiveConnection||!0===e.selected||!0===e.googActiveConnection});n.length>0&&(e=n[0])}return e}},{key:"sendIceFailed",value:function(e){e.localIceCandidates=this.localIceCandidates,e.remoteIceCandidates=this.remoteIceCandidates,e.iceCandidatePairs=this.iceCandidatePairs,l.log("sending icefailed ",e),this.emb.make(o.internalFabricEvent.iceFailed,this.conferenceId,this.pc,e)}},{key:"sendFabricTransportSwitch",value:function(e){var t=this,n={};n.prevIceCandidatePair=t.activeIceCandidatePair,n.relayType=e,n.currIceConnectionState=t.iceConnectionState,n.prevIceConnectionState=t.oldIceConnectionState,n.switchDelay=null,t.getStatsHandler.getIceCandidates().then(function(e){t.localIceCandidates=e.localIceCandidates,t.remoteIceCandidates=e.remoteIceCandidates,t.iceCandidatePairs=e.iceCandidatePairs,t.activeIceCandidatePair=t.getActiveIceCandidatePair(),n.currIceCandidatePair=t.activeIceCandidatePair,n.localIceCandidates=t.localIceCandidates,n.remoteIceCandidates=t.remoteIceCandidates,l.log("sending fabric transport switch ",n),"completed"!==n.currIceConnectionState&&"connected"!==n.currIceConnectionState||"completed"!==n.prevIceConnectionState&&"connected"!==n.prevIceConnectionState||t.emb.make(o.internalFabricEvent.fabricTransportSwitch,t.conferenceId,t.pc,n)})}},{key:"handleIceDisconnected",value:function(e){var t=c.getCurrent();this.startTime=t,e.prevIceConnectionStateTs=this.iceConnectionStateTS,e.currIceCandidatePair=this.activeIceCandidatePair,"connected"===e.prevIceConnectionState||"completed"===e.prevIceConnectionState?(this.pcState=o.fabricState.disrupted,this.disruptedTS=t,this.emb.make(o.internalFabricEvent.iceDisruptionStart,this.conferenceId,this.pc,e),this.callback&&this.callback(u.csError.appConnectivityError,"Connectivity check for PC object to "+this.remoteId+" failed.")):"checking"===e.prevIceConnectionState&&(this.pcState=o.fabricState.checkingDisrupted,this.connectionDisruptedTS=t,this.emb.make(o.internalFabricEvent.iceConnectionDisruptionStart,this.conferenceId,this.pc,e),this.callback&&this.callback(u.csError.appConnectivityError,"Connectivity check for PC object to "+this.remoteId+" failed."))}},{key:"handleIceClosed",value:function(e){"new"===e.prevIceConnectionState||"checking"===e.prevIceConnectionState?(e.delay=c.getCurrent()-this.startTime,e.localIceCandidates=this.localIceCandidates,e.remoteIceCandidates=this.remoteIceCandidates,e.iceCandidatePairs=this.iceCandidatePairs,this.emb.make(o.internalFabricEvent.iceAborted,this.conferenceId,this.pc,e)):"connected"!==e.prevIceConnectionState&&"completed"!==e.prevIceConnectionState||(e.prevIceCandidatePair=this.activeIceCandidatePair,this.emb.make(o.internalFabricEvent.iceTerminated,this.conferenceId,this.pc,e)),this.pcState=o.fabricState.terminated,this.conferenceId&&s.Registry.getConferenceManager().get(this.conferenceId).updateState(),this.stopStatsPolling()}},{key:"handleIceRestart",value:function(e){e.prevIceCandidatePair=this.prevActiveIceCandidatePair,"new"!==e.prevIceConnectionState&&(l.log("iceRestarted sending"),this.established=!1,this.emb.make(o.internalFabricEvent.iceRestarted,this.conferenceId,this.pc,e))}},{key:"pcSignalingStateChangeCallback",value:function(e){var t=this;if(e){var n=this.signalingState;this.signalingState=this.pc.signalingState,l.warn("CALLBACK: signaling state change",n,"->",this.signalingState);var r={changedState:o.fabricStateChangeType.signalingState,prevState:n,newState:this.signalingState};if(this.sendFabricStateChange(r),"have-remote-offer"!==this.signalingState&&"stable"!==this.signalingState||(this.precalltest.callStarts(),s.Registry.getPCTRunnerService().setCallInProgress(!0),this.genericevent.sendEvent(o.logEvents.log,{msg:"precalltest told to stop "})),"closed"===this.signalingState&&(this.emb.make(o.fabricEvent.fabricTerminated,this.conferenceId,this.pc),this.userAlive.stop(),this.precalltest.callFinished(),s.Registry.getPCTRunnerService().setCallInProgress(!1),this.stopStatsPolling(),this.pcState=o.fabricState.terminated,this.conferenceId)){var i=s.Registry.getConferenceManager().get(this.conferenceId);if(i&&i.getPeerConnectionManager()){var a=i.getPeerConnectionManager().getPcHandler(this.pc);i.getPeerConnectionManager().removePcStats(a&&a.getPcHash())}i.updateState()}"have-local-offer"!==this.signalingState&&"have-local-pranswer"!==this.signalingState&&"stable"!==this.signalingState||(l.log(this.signalingState,".. requesting sender config."),s.Registry.getConfigServiceWrapper().initiateSenderConfig(this.pc).then(function(){var e=s.Registry.getConfigServiceWrapper().getSenderConfig();l.log("Sender config:",e);var n=o.callstatsChannels.senderConfiguration;e&&s.Registry.getEventMessageBuilder().make(n,t.conferenceId,t.pc,e)}).catch(function(e){l.warn(e)}))}}},{key:"pcNegotiationNeededCallback",value:function(e){e&&(this.negotiationNeeded++,this.startTime=c.getCurrent(),l.warn("CALLBACK: negotiation needed",this.negotiationNeeded))}}]),e})();n.PcCallbackHandler=f},{"../config/callstatserrors":35,"../config/constants":36,"../utility/csiologger":92,"../utility/registry":100,"../utility/timestamps":104}],43:[function(e,t,n){"use strict";function r(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0}),n.PeerConnectionHandler=void 0;var a=(function(){function e(e,t){for(var n=0;n0)this.handleErrorActions(r["urn:x-callstats:auth:errorActions"]);else{if(200===t.status){if("bearer"!==r.token_type)return S.error(this.name+": successful, but token type was not bearer. Scheduling retry."),void this.sendNextRequest();this.setupToken(r.access_token),r.iceServers&&(this.iceServers=r.iceServers),r.metadata&&r.metadata.urls&&(this.backendURLs=r.metadata.urls,this.backendURLs.events&&f.setRestEventUrl(this.backendURLs.events+"/"),this.backendURLs.stats&&f.setRestStatsUrl(this.backendURLs.stats+"/"),this.backendURLs.config&&f.setConfigServiceUrl(this.backendURLs.config+"/"));var i=parseInt(1e3*parseInt(r.expires_in)*.9);return this.setupReauthTimer(i),this.renew=!1,this.initCallback&&this.initCallback(h.csError.success,p.csCallBackMessages.authSuccessful),this.elapsed=n,void this.completeProcess()}S.error("Authentication failed, but no error actions were defined in response."),this.sendNextRequest()}}},{key:"request",value:function(){var e=this;this.clearReauthTimer();var t=new Promise(function(t,n){e.tempResolve=t,e.tempReject=n});return this.tokenGenerator(this.renew,function(t,n){if(null!==t)return e.initCallback&&e.initCallback(h.csError.tokenGenerationError,t.toString()),e.rejectCb(new Error(e.name+": tokenGenerationError")),S.error("tokenGenerationError ",t),null;var r=f.authServiceUrl+"authenticate",i={client_id:e.credentials.userId+"@"+e.credentials.getAppId(),code:n,grant_type:"authorization_code"};(0,y.sendPostRequest)(r,{"Content-Type":"application/x-www-form-urlencoded"},k,i).then(function(t){e.tempResolve(t)},function(t){e.tempReject(t)})}),t}},{key:"tokenGeneratorCreator",value:function(e,t){var n=this;return function(r,i){var a=null;if(!r&&null!==a)return i(null,a);var o=n.credentials,s={userID:o.getUserId(),appID:o.getAppId()};t&&(s.keyId=t),n.jwt.sign({alg:"HS256"},s,e).then(function(e){a=e,i(null,e)}).catch(function(e){i(e)})}}},{key:"createTokenGenerator",value:function(e){var t=this;return new Promise(function(n,r){var i=null;e.indexOf(":")>-1&&(i=d.strtohex(e.split(":")[0]),e=e.split(":")[1]),t.jwt.importKey(e).then(function(r){e=null;var a=t.tokenGeneratorCreator(r,i);n(a)}).catch(function(e){S.error(t.name+": could not import key ("+e+")"),r(e)})})}}]),t})();n.Authenticator=w},{"../browserapi/localstorage":20,"../config/callstatserrors":35,"../config/constants":36,"../config/settings":37,"../utility/base64":89,"../utility/csiologger":92,"../utility/json":97,"../utility/registry":100,"./jwt/jwt":54,"./jwt/jwttoken":55,"./xmlhttp":60,"./xmlhttpservice":61}],47:[function(e,t,n){"use strict";function r(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0}),n.GenericEventHandler=void 0;var a=(function(){function e(e,t){for(var n=0;n6e4?(h.Registry.getGenericEventHandler().sendEvent(p.logEvents.log,{msg:"latency > MAX_ALLOWED_LATENCY: clockSync reset"}),this.offsetResults=[]):this.addOffset(e,r,n),this.offsetResults.length>=5?(this.calculateOffset(),this.endTime=f.getCurrent(),this.completeProcess()):this.sendRequest()}},{key:"isCompleted",value:function(){return this.completed}},{key:"addOffset",value:function(e,t,n){var r=e.now+t-n;this.offsetResults.push(r)}},{key:"calculateOffset",value:function(){var e=this.offsetResults.reduce(function(e,t){return e+t});this.currentOffset=e/this.offsetResults.length,this.currentOffset=isNaN(this.currentOffset)?0:this.currentOffset,h.Registry.getGenericEventHandler().sendEvent(p.logEvents.log,{msg:"clockSync Done, offset is: "+this.currentOffset+"results length"+this.offsetResults.length}),this.offsetResults=[],this.completed=!0}}]),t})();n.ClockSync=v},{"../config/constants":36,"../config/settings":37,"../utility/registry":100,"../utility/timestamps":104,"./xmlhttp":60,"./xmlhttpservice":61}],49:[function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var i=(function(){function e(e,t){for(var n=0;n1)return f.warn("Multiple PCs found, skipping"),null;if(!e.getSenders||"function"!=typeof e.getSenders)return f.warn("Get senders error"),t;for(var r=e.getSenders(),i=void 0,o=0;o=0;h--)f[h]=c.charCodeAt(h);var p=r.subtlecrypto.sign(d,n,f);"ie"===r.cryptotype?(p.onerror=a,p.oncomplete=function(e){c=r.buildToken(e.target.result,c),i(c)}):p.then(function(e){c=r.buildToken(e,c),i(c)}).catch(function(e){a(e)})})}},{key:"buildToken",value:function(e,t){for(var n="",r=new Uint8Array(e),i=r.byteLength,a=0;a0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return function(n,r,i){"success"===n.status?e&&e(n,r):t&&t(n)}}Object.defineProperty(n,"__esModule",{value:!0}),n.RestRelays=void 0;var o=(function(){function e(e,t){for(var n=0;n2&&void 0!==arguments[2]?arguments[2]:null;i(this,e),this.baseUrl=t,this.urlAppendix=n,this.responseHandler=r}return o(e,[{key:"getRequestUrl",value:function(e,t,n){return this.makeRequestUrl(e,t,n),this.requestUrl.toString()}},{key:"makeRequestUrl",value:function(e,t,n){e===s.precalltestEvents.results?this.requestUrl=new l.Url(this.baseUrl,u.Registry.getCredentials().getAppId(),this.urlAppendix):(e===s.internalFabricEvent.userJoined&&n&&(n=""),this.requestUrl=new l.Url(this.baseUrl,u.Registry.getCredentials().getAppId()+"/conferences/"+t,n,this.urlAppendix))}},{key:"handleResponse",value:function(e,t,n){this.responseHandler(e,t,n)}}]),e})();n.RestRelays=d},{"../config/constants":36,"../config/settings":37,"../utility/csiologger":92,"../utility/registry":100,"../utility/url":105}],59:[function(e,t,n){"use strict";function r(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0}),n.TransmissionManager=void 0;var a=(function(){function e(e,t){for(var n=0;n0&&this.startTimer());this.setupConnection()}},{key:"setupConnection",value:function(){this.connectionManager.setup().then(function(){l.log("Connected to connectionManager")}).catch(function(e){return l.log("Could not connect to connectionManager",e)})}},{key:"canSendUserAlive",value:function(e,t){return!(this.lastUserAliveTS[t]&&e-this.lastUserAliveTS[t]<9e3)}},{key:"sendMessage",value:function(){var e=void 0,t=void 0;if(0===this.getCacheLength())return!1;for(var n in this.cache)if(this.cache.hasOwnProperty(n)&&(t=n,(e=this.cache[t].peak())&&e.canBeSent()))break;if(!e||!e.canBeSent())return!1;if(e=this.cache[t].pop(),this.lastTS=o.getCurrent(),e.eventType===u.internalFabricEvent.userAlive){if(!this.canSendUserAlive(this.lastTS,t))return!0;this.lastUserAliveTS[t]=this.lastTS}return l.log("sending message type :",e.eventType,e.toJson()),this.connectionManager.send(e.toJson()),!0}},{key:"startTimer",value:function(){var e=this;this.timerStarted||0!=this.getCacheLength()&&(this.timerStarted=!0,setTimeout(function(){e.timerStarted=!1,e.trySend()},200))}},{key:"timeToSend",value:function(){return o.getCurrent()>=this.lastTS+200}},{key:"getCacheLength",value:function(){var e=0;for(var t in this.cache)this.cache.hasOwnProperty(t)&&(e+=this.cache[t].length());return e}},{key:"updateConferenceId",value:function(e){var t=u.tmpConferenceId;this.cache[t]&&this.cache[t].updateConferenceId(e)}}]),e})();n.TransmissionManager=f},{"../collections/cache":25,"../config/constants":36,"../utility/csiologger":92,"../utility/registry":100,"../utility/timestamps":104}],60:[function(e,t,n){"use strict";function r(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t,n,r,i){return new Promise(function(a,o){var f,d=null,h=new XMLHttpRequest,p=u.Registry.getEndpoint().getBrowserName();if(h){for(var v in f=s.getCurrent(),h.open(e,t),p!==c.browserName.msie&&(h.timeout=r),n)n.hasOwnProperty(v)&&h.setRequestHeader(v,n[v]);var g=null;if("POST"===e){if("application/x-www-form-urlencoded"===n["Content-Type"]){var y=[];for(var m in i)i.hasOwnProperty(m)&&y.push(encodeURIComponent(m)+"="+encodeURIComponent(i[m]));g=y.join("&")}"application/json"===n["Content-Type"]&&(g=JSON.stringify(i))}h.onload=function(){d=s.getCurrent();var e=new l(h,d-f);a(e)},h.ontimeout=function(){o(new Error("connection timeout"))},h.onreadystatechange=function(){4===h.readyState&&0===h.status&&o(new Error("no server response received"))},h.send(g)}else o(new Error("creating instance failed"))})}Object.defineProperty(n,"__esModule",{value:!0});var o=(function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:"XMLHttpService",n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:s,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:c;r(this,e),this.name=t,this.minRetryTimeout=n,this.sigmoid=new a.Sigmoid(i-n,15,.5),this.reset()}return i(e,[{key:"reset",value:function(){this.inProgress=!1,this.completed=!1,this.resolveCb&&this.rejectCb(new Error(this.name+": resetting")),this.resolveCb=null,this.rejectCb=null}},{key:"initiate",value:function(){var e=this;if(this.inProgress)return new Promise(function(t,n){n(new Error(e.name+": in progress"))});var t=new Promise(function(t,n){e.resolveCb=t,e.rejectCb=n});return this.inProgress=!0,this.sendRequest(),t}},{key:"isCompleted",value:function(){return this.completed}},{key:"handleSendError",value:function(e){o.log(this.name+": send next request ("+e+")"),this.sendNextRequest()}},{key:"handleResponseProxy",value:function(e){this.handleResponse(e),this.resetTimeout()}},{key:"handleResponse",value:function(e){o.error(this.name+": handleResponse() not implemented"),this.completeProcess()}},{key:"completeProcess",value:function(){this.inProgress=!1,this.completed=!0,this.resolveCb.apply(this,arguments)}},{key:"request",value:function(){return o.error(this.name+": request() not implemented!"),new Promise(function(e,t){e()})}},{key:"sendRequest",value:function(){if(this.inProgress){var e=this.request();e&&e.then(this.handleResponseProxy.bind(this),this.handleSendError.bind(this))}}},{key:"sendNextRequest",value:function(){setTimeout(this.sendRequest.bind(this),this.getTimeout())}},{key:"resetTimeout",value:function(){this.sigmoid.reset()}},{key:"getTimeout",value:function(){return this.minRetryTimeout+this.sigmoid.getActual()}}]),e})();n.XMLHttpService=u},{"../utility/csiologger":92,"../utility/sigmoid":102}],62:[function(e,t,n){"use strict";function r(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0}),n.IntervalStatsMonitor=void 0;var a=(function(){function e(e,t){for(var n=0;n2&&void 0!==arguments[2]?arguments[2]:0,r=this.getTotalBytes(e),i=this.getTotalBytes(t);if(!u.checkForPositiveValue(r)||!u.checkForPositiveValue(i)||!u.checkForPositiveValue(n))return null;var a=(8*r-8*i)/Math.max(n,1);return u.checkForPositiveValue(a)?a:null}},{key:"getIntervalPacketLoss",value:function(e,t,n){var r=this.getTotalLostPackets(e);if(!n)return u.checkForPositiveValue(r)?r:null;var i=this.getTotalLostPackets(t);if(!u.checkForPositiveValue(r)||!u.checkForPositiveValue(i))return null;var a=r-i;return u.checkForPositiveValue(a)?a:null}},{key:"getIntervalPacketRate",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;if(!u.checkForPositiveValue(n))return null;var r=this.getTotalPackets(e),i=this.getTotalPackets(t);if(!u.checkForPositiveValue(r)<0||!u.checkForPositiveValue(i))return null;var a=(r-i)/(Math.max(n,1)/1e3);return u.checkForPositiveValue(a)?a:null}},{key:"getIntervalFractionLost",value:function(e,t,n){var r=this.getIntervalPacketLoss(e,t,n),i=this.getTotalPackets(e)-this.getTotalPackets(t);if(!u.checkForPositiveValue(r)||!u.checkForPositiveValue(i))return null;var a=r/Math.max(i+r,1);return u.checkForPositiveValue(a)?a:null}},{key:"getIntervalStat",value:function(e,t){var n=e.getCurrent(),r=e.getPrevious(t),i=e.getElapsedTime(t),a=new Map;if(r)for(var o=0,s=r.length;o0&&void 0!==arguments[0]?arguments[0]:{},t=arguments[1],n=e,r=e.tracks||[],i=0,a=r.length;i0&&this.frameHeight>0?this.resolution=new a.Resolution(this.frameWidth,this.frameHeight,this.frameRateReceived):this.resolution=null}},{key:"getJitter",value:function(){return this.jitter}},{key:"getRTT",value:function(){return this.rtt}},{key:"getLostPackets",value:function(){return this.lostPackets}},{key:"getDiscardedPackets",value:function(){return this.discardedPackets}},{key:"getReceivedPackets",value:function(){return this.receivedPackets}},{key:"getSentPackets",value:function(){return this.sentPackets}},{key:"getSentBytes",value:function(){return this.sentBytes}},{key:"getReceivedBytes",value:function(){return this.receivedBytes}},{key:"setFractionLost",value:function(e){this.fractionLost=void 0===e?null:e}},{key:"getFractionLost",value:function(){return this.fractionLost}},{key:"extractTrack",value:function(){var e=this.track;return this.track=null,e}},{key:"toString",value:function(){return"pcHash: "+this.pcHash+", ssrc: "+this.ssrc+", streamType: "+this.streamType+", mediaType: "+this.mediaType+", reportType: "+this.reportType+", frameRateReceived: "+this.frameRateReceived+", frameHeight: "+this.frameHeight+", frameWidth: "+this.frameWidth+", droppedFramesNum: "+this.droppedFramesNum+", rtt: "+this.rtt+", jitter: "+this.jitter+", lostPackets: "+this.lostPackets+", receivedPackets: "+this.receivedPackets+", sentPackets: "+this.sentPackets+", discardedPackets: "+this.discardedPackets+", sentBytes: "+this.sentBytes+", receivedBytes: "+this.receivedBytes+", fractionLost: "+this.fractionLost}}]),e})();n.Measurement=s},{"./resolution":72,"./validator":87}],64:[function(e,t,n){"use strict";function r(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0}),n.CPULimitationObserver=void 0;var a=(function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:void 0,t=e&&e.getRequestedMeasurement();if(!t)return!0;if(e.getStreamType()===o.streamType.inbound){if(t.getReceivedBytes()<1)return!0}else if(t.getSentBytes()<1)return!0;return!e.lastTrack||!e.lastTrack.data||!e.lastTrack.data.mimeType&&!e.lastTrack.data.googCodecName}},{key:"isValidTrack",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:void 0,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:o.streamType.inbound;if(!e)return!1;var n=e.getRequestedMeasurement();return!!n&&n.getReportType()===o.reportType.local&&e.getStreamType()===t&&e.getMediaType()===o.mediaType.audio}},{key:"accept",value:function(e){var t=this,n=e.filter(function(e){return t.isValidTrack(e,o.streamType.inbound)}),r=e.filter(function(e){return t.isValidTrack(e,o.streamType.outbound)}),i=this.getDisruptions(n,r);i.length>0&&this.notifierCallback(i)}},{key:"toString",value:function(){return"DisruptionObserver"}},{key:"getDisruptedTrack",value:function(){var e=this;return(arguments.length>0&&void 0!==arguments[0]?arguments[0]:[]).find(function(t){return t&&!1===t.hasTraffic()&&!1===e.isDeadTrack(t)})}},{key:"isStartedAndHasTraffic",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=e.filter(function(e){return 0===e.getStartTime()}).length<1,n=e.filter(function(e){return!e.hasTraffic()}).length<1;return e.length>0&&t&&n}},{key:"hasTracksAndTraffic",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=e.filter(function(e){return!e.hasTraffic()}).length<1;return e.length>0&&t}},{key:"isInitialSetupDelayPassed",value:function(){return c.getCurrent()>this.startTime+15e3}},{key:"isInbOneWayAudioDisruption",value:function(e,t){if(this.isStartedAndHasTraffic(t)&&this.isInitialSetupDelayPassed()){var n=void 0;if(!this.hasTracksAndTraffic(e)){var r=this.getDisruptedTrack(e),i=r&&r.getSSRC();i&&(n=new s.OneWayMediaDisruption(o.oneWayMediaTypes.audio,i,o.streamType.inbound))}return n}}},{key:"isOutbOneWayAudioDisruption",value:function(e,t){if(this.isStartedAndHasTraffic(e)&&this.isInitialSetupDelayPassed()){var n=void 0;if(!this.hasTracksAndTraffic(t)){var r=this.getDisruptedTrack(t),i=r&&r.getSSRC();i&&(n=new s.OneWayMediaDisruption(o.oneWayMediaTypes.audio,i,o.streamType.outbound))}return n}}},{key:"updateDisruptionAndRecoveryCount",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;return e?(t=Math.min(t+1,l),n=0):(n=Math.min(n+1,l),t=0),{disruptionCount:t,recoveryCount:n}}},{key:"getDisruptionState",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return!1===n&&e>=5?f:!0===n&&t>=5?d:h}},{key:"getAudioDisruption",value:function(e,t,n){var r=void 0,i=void 0;if(n===o.streamType.inbound?(r=this.isInbOneWayAudioDisruption(e,t),i=this.oneWayInbAudioDisruption):n===o.streamType.outbound&&(r=this.isOutbOneWayAudioDisruption(e,t),i=this.oneWayOutbAudioDisruption),i){var a=this.updateDisruptionAndRecoveryCount(r,i.disruptionCount,i.recoveryCount),s=a.disruptionCount,c=a.recoveryCount,u=this.getDisruptionState(s,c,i.started);return u===f?(i.started=!0,i.disruption=r.setStart(),i.disruptionCount=0,i.recoveryCount=0):u===d?(i.started=!1,i.disruption=i.disruption.setEnd(),i.disruptionCount=0,i.recoveryCount=0):(i.recoveryCount=c,i.disruptionCount=s),u!==h?i.disruption:void 0}}},{key:"getDisruptions",value:function(e,t){var n=[],r=this.getAudioDisruption(e,t,o.streamType.inbound),i=this.getAudioDisruption(e,t,o.streamType.outbound);return r&&n.push(r),i&&n.push(i),n}}]),e})();n.OneWayMediaObserver=p},{"../../config/constants":36,"../../utility/registry":100,"../../utility/timestamps":104,"../onewaymediadisruption":69}],66:[function(e,t,n){"use strict";function r(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0}),n.QPSumObserver=void 0;var a=(function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;if(null===e||void 0===e||Math.abs(e)i;return a?(this.consecutivePositive+=1,this.consecutivePositive>this.resetThreshold&&this.runningStats.reset()):this.consecutivePositive=0,a}}]),e})(),p=(function(){function e(t){var n=t.maxMarginFactor,r=void 0===n?l.adaptiveStatsThresholds.maxMarginFactor:n,a=t.marginReductionFactor,o=void 0===a?l.adaptiveStatsThresholds.marginReductionFactor:a,s=t.marginIncreaseFactor,c=void 0===s?l.adaptiveStatsThresholds.marginIncreaseFactor:s,u=t.marginDecreaseIntervalInMs,f=void 0===u?l.adaptiveStatsThresholds.marginDecreaseIntervalInMs:u,d=t.maxGradualCounter,p=void 0===d?l.adaptiveStatsThresholds.maxGradualCounter:d,v=t.minIntervalInMs,g=void 0===v?l.adaptiveStatsThresholds.minIntervalInMs:v,y=t.rippleBase,m=void 0===y?l.adaptiveStatsThresholds.rippleBase:y,b=t.windowSize,S=void 0===b?l.adaptiveStatsThresholds.windowSize:b,k=t.resetThreshold,w=void 0===k?l.adaptiveStatsThresholds.resetThreshold:k,C=t.minThreshold,_=void 0===C?l.adaptiveStatsThresholds.minThreshold:C;i(this,e),this.rttTester=new h("RTT Tester",_.rtt,S,w),this.throughputTester=new h("Throughput Tester",_.throughput,S,w),this.FLTester=new h("FL Tester",_.fractionalLoss,S,w),this.marginFactor=1,this.lastDecreased=0,this.lastTriggering=0,this.maxMarginFactor=r,this.marginReductionFactor=o,this.marginIncreaseFactor=c,this.marginDecreaseIntervalInMs=f,this.maxGradualCounter=p,this.gradualCounter=p,this.minIntervalInMs=g,this.rippleBase=m}return o(e,[{key:"test",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0,n=t?{}:e.peek();if(!n)return!1;var r=(t?{}:e.getTrack()).data,i=t?t.rtt:n.getRTT(),a=u.checkForNan(parseInt(t?t.throughput:r.intervalBandwidth,10)),o=t?t.loss:n.getFractionLost(),c=t?t.time:s.getCurrent(),l=this.rttTester.doTest(i,this.marginFactor),f=this.throughputTester.doTest(a,this.marginFactor),d=this.FLTester.doTest(o,this.marginFactor);if(l||f||d)return this.marginFactor=Math.min(this.marginFactor*this.marginIncreaseFactor,this.maxMarginFactor),this.lastTriggering=c,this.lastDecreased=c,this.gradualCounter=0,!0;if(c-this.lastDecreased>this.marginDecreaseIntervalInMs&&(this.marginFactor=Math.max(this.marginFactor*this.marginReductionFactor,1),this.lastDecreased=c),this.gradualCounter1&&void 0!==arguments[1]?arguments[1]:{};i(this,e),t?(this.notifyCallback=t,this.minIntervalInMs=n.minIntervalInMs||l.adaptiveStatsThresholds.minIntervalInMs,this.maxIntervalInMs=n.maxIntervalInMs||l.adaptiveStatsThresholds.maxIntervalInMs,this.config=n,this.notified=0,this.testers=new Map):d.warn("notifyCallback was null or undefined : "+t)}return o(e,[{key:"setup",value:function(e,t){this.minIntervalInMs=e,this.maxIntervalInMs=t}},{key:"getMostRecentTrackStartTime",value:function(){return(arguments.length>0&&void 0!==arguments[0]?arguments[0]:[]).reduce(function(e,t){return!!t&&"function"==typeof t.getCreationTime&&Math.max(t.getCreationTime(),e)},Number.MIN_VALUE)}},{key:"accept",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0,n=t?t.time:s.getCurrent(),r=n-this.notified,i=this.doSend(e,t);if(this.minIntervalInMs===this.maxIntervalInMs)return d.log("Elapsed time in fix intervalset: "+r),void(r>this.minIntervalInMs&&(this.notifyCallback&&this.notifyCallback(n),this.notified=n));if(!(rl.adaptiveStatsThresholds.initialNotifyIntervalTimeoutInMs)return this.notifyCallback&&this.notifyCallback(n),void(this.notified=n);r0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0;if(t){if(this.testers.has("test-ssrc")||this.testers.set("test-ssrc",new p(a({},this.config,{minIntervalInMs:this.minIntervalInMs,maxIntervalInMs:this.maxIntervalInMs}))),this.testers.get("test-ssrc").test(e,t))return!0}else for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:"0",i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=!(arguments.length>3&&void 0!==arguments[3])||arguments[3];r(this,e),this.mediaType=t,this.ssrc=""+n,this.streamType=i,this.started=a}return i(e,[{key:"setStart",value:function(){return this.started=!0,this}},{key:"setEnd",value:function(){return this.started=!1,this}},{key:"getContent",value:function(){return{mediaType:this.mediaType,ssrc:this.ssrc,streamType:this.streamType}}},{key:"isStarted",value:function(){return this.started}},{key:"toString",value:function(){return JSON.stringify({started:this.started,ssrc:this.ssrc,mediaType:this.mediaType})}}]),e})();n.OneWayMediaDisruption=a},{}],70:[function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var i=(function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:o.avQualityRatings.unknown){case o.avQualityRatings.bad:return o.qualityRating.bad;case o.avQualityRatings.fair:return o.qualityRating.fair;case o.avQualityRatings.excellent:return o.qualityRating.excellent}return 0}},{key:"toQualityString",value:function(){switch(arguments.length>0&&void 0!==arguments[0]?arguments[0]:o.qualityRating.excellent){case o.qualityRating.excellent:return o.avQualityRatings.excellent;case o.qualityRating.good:case o.qualityRating.fair:case o.qualityRating.poor:return o.avQualityRatings.fair;case o.qualityRating.bad:return o.avQualityRatings.bad}return o.avQualityRatings.unknown}},{key:"inboundAudioQuality",value:function(){var e=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}).data||{},t=[];if(e.csioIntBRKbps&&00&&void 0!==arguments[0]?arguments[0]:{}).data||{},t=[];if(e.csioIntBRKbps&&00&&void 0!==arguments[0]?arguments[0]:{}).data||{},t=[];if(e.csioIntBRKbps&&00&&void 0!==arguments[0]?arguments[0]:{}).data||{},t=[];if(e.csioIntBRKbps&&00&&void 0!==arguments[0]?arguments[0]:[],t=0,n=0,r=0,i=e.length;r0&&void 0!==arguments[0]?arguments[0]:{},t=e.tracks||[],n=0,i=t.length;n0)return r;for(var o=void 0,s=0;s0||parseInt(a.transportStats.bytesSent,10)>0)&&n.transportStats.push(a.transportStats):"true"!==a.transportStats.selected&&!0!==a.transportStats.selected||n.transportStats.push(a.transportStats))}if(n.tracks){var o=f.Registry.getConferenceManager().getConferenceForPcHash(t),s=void 0;o&&(s=o.getPeerConnectionManager().getPcHandlerByHash(t)),n.tracks.forEach(function(e){var t=s.getSSRCInfo(e.data.ssrc);void 0!==t&&t.localStartTime||s&&(s.updateSDP(n.tracks),t=s.getSSRCInfo(e.data.ssrc)),t&&(e.cname=t.cname,e.msid=t.msid,e.associatedVideoTag=t.associatedVideoTag,e.usageLabel=t.usageLabel)})}return n.transportStats&&this.codeBase===u.codeBaseType.firefox&&(n.transportStats=this.getAddressInfoFromCandidates(n.transportStats,n.localIceCandidates,n.remoteIceCandidates)),n}},{key:"getParsedStats",value:function(e){var t={};if(e.timestamp instanceof Date&&(t.timestamp=e.timestamp.getTime().toString()),e.type&&(t.type=e.type),e.names){for(var n=e.names(),r=0;r0)return n[0]}}},{key:"formatRelayType",value:function(e){var t="None";switch(e){case 0:t="TURN/TLS";break;case 1:t="TURN/TCP";break;case 2:t="TURN/UDP"}return t}},{key:"getRelayType",value:function(e,t){var n=this,r=void 0;return t.getIceCandidates().some(function(t){if(t.typePreference){var i=t.typePreference>>24;return"rtp"===t.protocol&&t.address===e&&(i>=0&&i<=2&&(r=n.formatTypePreference(i)),!0)}return!1}),r}},{key:"getTransportInfo",value:function(e,t){for(var n={},r=!1,i=0;i0?a.statsType="outbound-rtp":a.statsType="inbound-rtp"}"remote-inbound-rtp"!==a.statsType&&"remote-outbound-rtp"!==a.statsType&&(!0!==i.isRemote&&"true"!==i.isRemote||(a.statsType="remote-"+a.statsType)),n.streams[i.ssrc]=a,n.mediaStreamTracks.push(a)}}this.callback(n)}}]),e})();n.StatsCallbackBuilder=o},{"../utility/registry":100}],76:[function(e,t,n){"use strict";function r(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function o(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(n,"__esModule",{value:!0}),n.StatsMonitor=n.StatsMonitorIO=void 0;var s=(function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:null;null===e&&(e=k.statsDestination.backend);var t=new h.StatsTuple(this.getCandidatePairs(),this.lastPcStats.getCodec(),this.lastPcStats.getTrackStats(),this.transportsmonitor.getIntervalStats(),this.tracksmonitor.extractTracks(),e),n=this.intervalstatsmonitor.getIntervalStats(e);t=this.intervalstatsmonitor.updateIntervalStats(t,n),t=this.qualityevaluator.updateQualityStats(t),this.transmit(C.StatsTupleOut,t)}},{key:"sendDisruptions",value:function(e){var t=this;e.forEach(function(e){e.isStarted()?t.sendEventMsg(k.internalFabricEvent.oneWayMediaStart,e.getContent()):t.sendEventMsg(k.internalFabricEvent.oneWayMediaStop,e.getContent())})}},{key:"sendCPULimitationObservations",value:function(e){}},{key:"sendQPSumDistortions",value:function(e){}},{key:"sendThroughputObservations",value:function(e){this.sendEventMsg(k.internalFabricEvent.sendingThroughputObservations,e)}},{key:"sendEventMsg",value:function(e,t){if(this.lastPcHash){var n=p.Registry.getConferenceManager().getConferenceForPcHash(this.lastPcHash);if(n){var r=n.getPeerConnectionManager().getPcHandlerByHash(this.lastPcHash),i=r.getPeerConnection(),a=r.getConferenceId();p.Registry.getEventMessageBuilder().make(e,a,i,t)}}}},{key:"delete",value:function(e){this.tracksmonitor&&this.tracksmonitor.deleteTracks(e),this.transportsmonitor&&this.transportsmonitor.delete(e),this.intervalstatsmonitor&&this.intervalstatsmonitor.delete(e),this.candidatepairs&&this.candidatepairs.has(e)&&this.candidatepairs.delete(e)}}]),t})();n.StatsMonitor=_},{"../collections/component":26,"../config/constants":36,"../utility/csiologger":92,"../utility/registry":100,"../utility/timestamps":104,"./intervalstatsmonitor":62,"./monitorhooks/cpulimitationobserver":64,"./monitorhooks/onewaymediaobserver":65,"./monitorhooks/qpsumobserver":66,"./monitorhooks/sendingtrigger":67,"./monitorhooks/throughputobserver":68,"./qualityevaluator":71,"./statstuple":79,"./tracksmonitor":85,"./transportsmonitor":86}],77:[function(e,t,n){"use strict";function r(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function o(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(n,"__esModule",{value:!0}),n.StatsParser=n.StatsParserIO=void 0;var s=(function(){function e(e,t){for(var n=0;n2&&void 0!==arguments[2]?arguments[2]:null;r(this,t);var o=i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,n,a));return o.sum=0,o.counter=0,o}return a(t,s.SWPlugin),o(t,[{key:"add",value:function(e){this.filter(e)&&(this.sum+=this.extract(e),++this.counter,this.calculate())}},{key:"remove",value:function(e){this.filter(e)&&(this.sum-=this.extract(e),--this.counter,this.calculate())}},{key:"calculate",value:function(){var e=0;this.counter<1?this.notify(e):(e=this.sum/this.counter,this.notify(e))}}]),t})();n.SWAvg=c},{"./swplugin":83}],81:[function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(n,"__esModule",{value:!0}),n.SWBTreePercentile=void 0;var o=(function(){function e(e,t){var n=[],r=!0,i=!1,a=void 0;try{for(var o,s=e["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();!(r=(o=s.next()).done)&&(n.push(o.value),!t||n.length!==t);r=!0);}catch(e){i=!0,a=e}finally{try{!r&&s.return&&s.return()}finally{if(i)throw a}}return n}return function(t,n){if(Array.isArray(t))return t;if(("function"==typeof Symbol?Symbol.iterator:"@@iterator")in Object(t))return e(t,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}})(),s=(function(){function e(e,t){for(var n=0;n4&&void 0!==arguments[4]?arguments[4]:null,c=arguments.length>5&&void 0!==arguments[5]?arguments[5]:null,u=arguments.length>6&&void 0!==arguments[6]?arguments[6]:null;r(this,t);var f=i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,a,o,c));if(992&&void 0!==arguments[2]?arguments[2]:null;r(this,t);var o=i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,null,null,a));return o.addFunc=e,o.remFunc=n,o}return a(t,s.SWPlugin),o(t,[{key:"add",value:function(e){this.filter(e)&&this.addFunc&&this.addFunc(e)}},{key:"remove",value:function(e){this.filter(e)&&this.remFunc&&this.remFunc(e)}},{key:"toString",value:function(){return"SWFuncPlugin"}}]),t})();n.SWFunctor=c},{"./swplugin":83}],83:[function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0}),n.SWPlugin=void 0;var i=(function(){function e(e,t){for(var n=0;n2&&void 0!==arguments[2]?arguments[2]:null;r(this,e),this.extractorFnc=t,this.notifierFnc=n,this.filterFunc=i}return i(e,[{key:"notify",value:function(e){this.notifierFnc?this.notifierFnc(e):a.warn("Failed notification for "+this.toString())}},{key:"extract",value:function(e){return this.extractorFnc?this.extractorFnc(e):(a.warn(this.toString()+" tried to extract without extractorFnc"),null)}},{key:"filter",value:function(e){return!this.filterFunc||this.filterFunc(e)}},{key:"add",value:function(e){a.log("Abstract method is called width value: "+e)}},{key:"remove",value:function(e){a.log("Abstract method is called with value: "+e)}},{key:"toString",value:function(){return"SWPlugin"}}]),e})();n.SWPlugin=o},{"../../utility/csiologger":92}],84:[function(e,t,n){"use strict";function r(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}function i(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0}),n.TrackMonitor=void 0;var c=function e(t,n,r){null===t&&(t=Function.prototype);var i=Object.getOwnPropertyDescriptor(t,n);if(void 0===i){var a=Object.getPrototypeOf(t);return null===a?void 0:e(a,n,r)}if("value"in i)return i.value;var o=i.get;return void 0!==o?o.call(r):void 0},u=(function(){function e(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:1};this.evaluators.push(t)}}]),e})(),S=(function(e){function t(e,n,r,a){o(this,t);var s=i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,n));return s.thresholds=[],s.enableThresholds=!1,s.requestTime=0,s.started=0,s.created=v.getCurrent(),s.mediaType=a,s.streamType=r,s.qualityHelper=new b,s.metrics=s.makeTrack(),s.lastTrack={},s.prevFrameRateMean=null,s.ssrc=null,s}return a(t,f.SlidingWindow),u(t,null,[{key:"make",value:function(e,n,r,i){var a=new t(e,n,r,i),o=a.metrics;return a.attach(new d.SWAvg(function(e){return e.getJitter()},function(e){o.csioAvgJitter=e},function(e){var t=e.getJitter();return null!==t&&void 0!==t})),a.attach(new d.SWAvg(function(e){return e.getRTT()},function(e){o.csioAvgRtt=e},function(e){var t=e.getRTT();return null!==t&&void 0!==t})),a.attach(new h.SWBTreePercentile(95,function(e,t){var n=e.getJitter(),r=t.getJitter();return n==r?0:n0&&r>=0&&(t.csioEstFrameRatePerSecond=1e3*r/i)}}),e.attach(new p.SWFunctor(function(n){var r=v.getCurrent(),i=n.getResolution(),a=e.getRequestedMeasurement(),o=e.getRequestTime(),s=8*n.getReceivedBytes(),c=n.getReceivedPackets(),u=0,f=0,d=0,h=Math.max(r-e.getStartTime(),d);a?(u=s-8*a.getReceivedBytes(),f=Math.max(r-o,d)):(d=l.Registry.getCredentials().isAdaptiveStatsEnabled()?g.adaptiveStatsIntervalsInMs.min:l.Registry.getCredentials().getStatsSubmissionInterval(),h=Math.max(r-e.getStartTime(),d),u=s,f=Math.max(h,d)),t.csioAvgBRKbps=s/h,t.intervalBandwidth=Math.max(u/f,0),t.csioAvgPacketSize=n.getReceivedBytes()/Math.max(c,1),t.csiores=i},null,null)),e.attach(new h.SWBTreePercentile(95,function(e,t){var n=e.getFractionLost(),r=t.getFractionLost();return n==r?0:n=0},function(e,t){return e}))}},{key:"setupOutboundMonitor",value:function(e){var t=e.metrics;e.addPreProcess(function(t){var n=t.getFractionLost();if(!y.checkForPositiveValue(n)){var r=t.getLostPackets(),i=t.getReceivedPackets(),a=e.getRequestedMeasurement(),o=0,s=0;a?(o=r-a.getLostPackets(),s=i-a.getReceivedPackets()):(o=r,s=i),y.checkForPositiveValue(o)&&y.checkForPositiveValue(s)&&(n=o/Math.max(s+o,1),y.checkForPositiveValue(n)&&t.setFractionLost(n))}}),e.attach(new p.SWFunctor(function(n){var r=v.getCurrent(),i=n.getResolution(),a=e.getRequestedMeasurement(),o=e.getRequestTime(),s=8*n.getSentBytes(),c=n.getSentPackets(),u=0,f=0,d=0,h=Math.max(r-e.getStartTime(),d);a?(u=s-8*a.getSentBytes(),f=Math.max(r-o,d)):(d=l.Registry.getCredentials().isAdaptiveStatsEnabled()?g.adaptiveStatsIntervalsInMs.min:l.Registry.getCredentials().getStatsSubmissionInterval(),h=Math.max(r-e.getStartTime(),d),u=s,f=Math.max(h,d)),t.csioAvgBRKbps=s/h,t.intervalBandwidth=Math.max(u/f,0),t.csioAvgPacketSize=n.getSentBytes()/Math.max(c,1),t.csiores=i},null,null)),e.attach(new h.SWBTreePercentile(95,function(e,t){var n=e.getFractionLost(),r=t.getFractionLost();return n==r?0:n=0},function(e,t){return e}))}},{key:"setupAudioMonitor",value:function(e){var t=e.metrics;e.attach(new p.SWFunctor(function(e){t.csioMediaType=g.mediaType.audio},null,null))}},{key:"setupVideoMonitor",value:function(e){var t=e.metrics;e.attach(new d.SWAvg(function(e){return e.getFrameRateReceived()},function(n){e.prevFrameRateMean=t.csioFrameRateMean,t.csioPrevFrameRateMean=t.csioFrameRateMean,t.csioFrameRateMean=n},function(e){var t=e.getFrameRateReceived();return null!==t&&void 0!==t})),e.attach(new d.SWAvg(function(e){return e.getFrameHeight()},function(e){t.csioFrameHeightMean=e},function(e){var t=e.getFrameHeight();return null!==t&&void 0!==t})),e.attach(new d.SWAvg(function(e){return e.getFrameWidth()},function(e){t.csioFrameWidthMean=e},function(e){var t=e.getFrameWidth();return null!==t&&void 0!==t})),e.attach(new h.SWBTreePercentile(50,function(e,t){var n=e.getFrameRateReceived(),r=t.getFrameRateReceived();return n==r?0:n1&&void 0!==arguments[1]?arguments[1]:1;this.qualityHelper.addEvaluator(e,t)}},{key:"addPreProcess",value:function(e){c(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"addPreProcess",this).call(this,e)}},{key:"addPostProcess",value:function(e){c(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"addPostProcess",this).call(this,e)}}]),t})();n.TrackMonitor=S},{"../collections/slidingwindow":31,"../config/constants":36,"../statspipeline/swplugins/swavg":80,"../statspipeline/swplugins/swbtreepercentile":81,"../statspipeline/swplugins/swfunctor":82,"../utility/csiologger":92,"../utility/registry":100,"../utility/timestamps":104,"./validator":87}],85:[function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0}),n.TracksMonitor=void 0;var i=(function(){function e(e,t){for(var n=0;n0||a.csioIntBytesReceived>0)?(a.csioTurnMins=r+o.csioTurnMins,a.csioBytesSent=o.csioBytesSent+a.csioIntBytesSent,a.csioBytesReceived=o.csioBytesReceived+a.csioIntBytesReceived):a.csioTurnMins=o.csioTurnMins}return t}},{key:"getIntervalStatForChrome",value:function(e){var t=e.getActual(),n=e.getPrevious(),r=e.getElapsedTime();if(!n)return actual;for(var i=0;i0||a.csioIntBytesReceived>0)?(a.csioTurnMins=r+o.csioTurnMins,a.csioBytesSent=o.csioBytesSent+a.csioIntBytesSent,a.csioBytesReceived=o.csioBytesReceived+a.csioIntBytesReceived):a.csioTurnMins=o.csioTurnMins}return t}}]),e})();n.TransportsMonitor=u},{"../config/constants":36,"../utility/timestamps":104}],87:[function(e,t,n){"use strict";function r(e){return isNaN(e)?null:e}Object.defineProperty(n,"__esModule",{value:!0}),n.checkForNan=r,n.checkForNegativeValue=function(e){return null!==r(e)&&0<=e?e:null},n.checkForPositiveValue=function(e){return void 0!==e&&null!==r(e)&&e>=0}},{}],88:[function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var i=(function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]&&arguments[0];this.adaptiveStatsEnabled=e}}]),e})();n.Credentials=u},{"../config/constants":36,"./csiologger":92}],92:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.info=function(){var e;"true"===r.csioDebug&&(e=console).info.apply(e,arguments)},n.log=function(){var e;"true"===r.csioDebug&&(e=console).log.apply(e,arguments)},n.warn=function(){var e;"true"===r.csioDebug&&(e=console).warn.apply(e,arguments)},n.error=function(){var e;(e=console).warn.apply(e,arguments)};var r=(function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t})(e("../config/settings"))},{"../config/settings":37}],93:[function(e,t,n){"use strict";function r(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0}),n.Endpoint=void 0;var a=(function(){function e(e,t){for(var n=0;n3&&void 0!==arguments[3]?arguments[3]:{};if("string"!=typeof e||null===r||"object"!==(void 0===r?"undefined":a(r)))return l.error("failed typeof checks:",e,void 0===e?"undefined":a(e),void 0===r?"undefined":a(r),r),u.Registry.getGenericEventHandler().sendEvent(c.logEvents.error,{msg:"failed typeof checks:"+e+":"+(void 0===r?"undefined":a(r))+":"+(void 0===e?"undefined":a(e))}),!1;if(null===t&&e!==c.precalltestEvents.results)return l.error("failed conferenceId checks:",e,t),u.Registry.getGenericEventHandler().sendEvent(c.logEvents.error,{msg:"failed conferenceId checks:"+e}),!1;if(!n&&e!==c.callstatsChannels.userFeedback&&e!==c.fabricEvent.applicationErrorLog&&e!==c.fabricEvent.fabricSetupFailed&&e!==c.internalFabricEvent.userJoined&&e!==c.precalltestEvents.results)return l.error("peerconnection cannot be null",e),u.Registry.getGenericEventHandler().sendEvent(c.logEvents.error,{msg:"peerconnection cannot be null"+e}),!1;if(!s.EventMessage.checkCustomEntries(e,r))return l.error("failed checks:",e,r),u.Registry.getGenericEventHandler().sendEvent(c.logEvents.error,{msg:"failed customEntries checks:"+e}),!1;var i=void 0;if(t){var o=u.Registry.getConferenceManager().get(t);o&&n&&(i=o.getPeerConnectionManager().getPcHandler(n))}var f=new s.EventMessage(e,t,r,i);return this.transmissionmanager.send(f),!0}}]),e})();n.EventMessageBuilder=f},{"../config/constants":36,"./csiologger":92,"./eventmessage":94,"./registry":100}],96:[function(e,t,n){"use strict";function r(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=0;if(!e)return n;for(var r=0,i=e.length;r127&&r<2048?(t[t.length]=r>>6|192,t[t.length]=63&r|128):(t[t.length]=r>>12|224,t[t.length]=r>>6&63|128,t[t.length]=63&r|128)}return new Uint8Array(t).buffer}function a(e){for(var t=new DataView(e),n="",r=void 0,i=0;i-1){for(var n=!1,r={fileName:e.filename,line:e.lineno,col:e.colno,jsVersion:a.version,eventType:"error",message:e.message,pageURL:window.location.href},s=i.Registry.getConferenceManager().getConferenceIds(),c=0;c0&&void 0!==arguments[0]?arguments[0]:100;r(this,e),this.queue=new a.Queue(t),this.cumulativeSum=0}return i(e,[{key:"add",value:function(e){this.cumulativeSum+=e;var t=this.queue.push(e);t&&(this.cumulativeSum-=t)}},{key:"getMean",value:function(){return this.queue.size()<1?null:this.cumulativeSum/this.queue.size()}},{key:"getVariance",value:function(){if(this.queue.size()<2)return null;for(var e=this.getMean(),t=0,n=this.queue.getFront();n;){var r=n,i=r.value-e;t+=i*i,n=r.next}return t/this.queue.size()}},{key:"getStd",value:function(){if(this.queue.size()<2)return null;var e=this.getVariance();return Math.sqrt(e)}},{key:"reset",value:function(){this.cumulativeSum=0,this.queue.clear()}}]),e})();n.RunningStats=o},{"../collections/queue":30}],102:[function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var i=(function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:1;return this.actualStep+=e,this.max/(1+Math.exp(-1*this.stepness*(this.actualStep-this.midpoint)))}}]),e})();n.Sigmoid=a},{}],103:[function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0}),n.TimeoutProcess=void 0;var i=(function(){function e(e,t){for(var n=0;n1?n-1:0),a=1;a0&&void 0!==arguments[0]?arguments[0]:{};return function(o,n){var c=n()['features/base/config'].enableClosePage;if(c){var s=n()['features/base/jwt'].isGuest;window.sessionStorage.setItem('guest',s);var u='close.html';return interfaceConfig.SHOW_PROMOTIONAL_CLOSE_PAGE?u='close3.html':t.feedbackSubmitted||(u='close2.html'),void o(S("static/"+u))}t.showThankYou&&o((0,v.showNotification)({titleArguments:{appName:(0,R.getName)()},titleKey:'dialog.thankYou'})),n()['features/base/config'].enableWelcomePage&&setTimeout(function(){o(k('/'))},t.showThankYou?3e3:500)}};var o=t(r(d[1])),n=r(d[2]),c=r(d[3]),s=r(d[4]),u=r(d[5]),f=r(d[6]),l=r(d[7]),h=r(d[8]),p=r(d[9]),v=r(d[10]),b=r(d[11]),R=r(d[12]),w=t(r(d[13]));function L(t){return function(f,l){var v,b,L,k,S,U,C,P,T,N,W;return o.default.async(function(x){for(;;)switch(x.prev=x.next){case 0:if((v=(0,p.parseURIString)(t))&&v.host||(b=(0,p.parseURIString)((0,R.getDefaultURL)(l)),v?(v.host=b.host,v.hostname=b.hostname,v.pathname=b.pathname+v.pathname.substr(1),v.port=b.port,v.protocol=b.protocol):v=b),v.protocol||(v.protocol='https:'),k=(L=v).contextRoot,S=L.host,U=L.room,C=new URL(v.toString()),'ReactNative'===navigator.product&&f((0,s.disconnect)()),f((0,c.configWillLoad)(C,U)),'http:'!==(P=v.protocol.toLowerCase())&&'https:'!==P&&(P='https:'),N=(T=P+"//"+S+(k||'/'))+"config.js",U&&(N+="?room="+(0,p.getBackendSafeRoomName)(U)),U||(W=(0,c.restoreConfig)(T)),W){x.next=30;break}return x.prev=14,x.next=17,o.default.awrap((0,u.loadConfig)(N));case 17:W=x.sent,f((0,c.storeConfig)(T,W)),x.next=30;break;case 21:if(x.prev=21,x.t0=x.catch(14),W=(0,c.restoreConfig)(T)){x.next=30;break}if(!U){x.next=28;break}return f((0,c.loadConfigError)(x.t0,C)),x.abrupt("return");case 28:w.default.warn('Failed to load config but there is no room, applying a fake one'),W=(0,c.createFakeConfig)(T);case 30:if(l()['features/base/config'].locationURL===C){x.next=33;break}return f((0,c.loadConfigError)(new Error('Config no longer needed!'),C)),x.abrupt("return");case 33:f((0,s.setLocationURL)(C)),f((0,c.setConfig)(W)),f((0,n.setRoom)(U)),U&&'ReactNative'===navigator.product&&(f((0,h.createDesiredLocalTracks)()),f((0,s.connect)()));case 37:case"end":return x.stop()}},null,this,[[14,21]])}}function k(t){return function(o,n){var c=n()['features/base/connection'].locationURL,s=new URL(c.href);s.pathname=t,window.location.assign(s.toString())}}function S(t){return function(){var o=window.location,n=t;n.startsWith('/')||(n.startsWith('./')&&(n=n.substring(2)),n=(0,p.getLocationContextRoot)(o)+n),o.pathname=n}}function U(t,o){var n=(0,l.toState)(o)['features/base/tracks'],c=(0,h.isLocalVideoTrackMuted)(n),s=(0,h.isLocalTrackMuted)(n,f.MEDIA_TYPE.AUDIO);return(0,p.addHashParamsToURL)(new URL(t),{'config.startWithAudioMuted':s,'config.startWithVideoMuted':c})}function C(){return function(t,o){var n=o(),c=U(n['features/base/connection'].locationURL,n),s=window.location,u=s.search;s.replace(c.toString()),c.search===u&&s.reload()}}},436,[3,270,437,516,1105,442,684,474,883,446,854,1159,1177,1178]); -__d(function(g,r,i,a,m,e,d){Object.defineProperty(e,"__esModule",{value:!0});var t=r(d[0]);Object.keys(t).forEach(function(n){"default"!==n&&"__esModule"!==n&&Object.defineProperty(e,n,{enumerable:!0,get:function(){return t[n]}})});var n=r(d[1]);Object.keys(n).forEach(function(t){"default"!==t&&"__esModule"!==t&&Object.defineProperty(e,t,{enumerable:!0,get:function(){return n[t]}})});var u=r(d[2]);Object.keys(u).forEach(function(t){"default"!==t&&"__esModule"!==t&&Object.defineProperty(e,t,{enumerable:!0,get:function(){return u[t]}})});var o=r(d[3]);Object.keys(o).forEach(function(t){"default"!==t&&"__esModule"!==t&&Object.defineProperty(e,t,{enumerable:!0,get:function(){return o[t]}})}),r(d[4]),r(d[5])},437,[438,1111,1112,1113,1115,1149]); -__d(function(g,r,i,a,m,e,d){var n=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.authStatusChanged=function(n,t){return{type:l.AUTH_STATUS_CHANGED,authEnabled:n,authLogin:t}},e.conferenceFailed=S,e.conferenceJoined=R,e.conferenceLeft=D,e.conferenceSubjectChanged=y,e.conferenceTimestampChanged=O,e.conferenceWillJoin=L,e.conferenceWillLeave=function(n){return{type:l.CONFERENCE_WILL_LEAVE,conference:n}},e.createConference=function(){return function(n,o){var u=o(),f=u['features/base/connection'],s=f.connection,p=f.locationURL;if(!s)throw new Error('Cannot create a conference without a connection!');var l=u['features/base/conference'],T=l.password,S=l.room;if(!S)throw new Error('Cannot join a conference without a room name!');var R=u['features/base/config'],D=(0,C.getLocalParticipant)(u),y=D.email,O=D.name,L=s.initJitsiConference((0,_.getBackendSafeRoomName)(S),(0,t.default)({},R,{applicationName:(0,c.getName)(),getWiFiStatsMethod:(0,_.getJitsiMeetGlobalNS)().getWiFiStats,confID:""+p.host+p.pathname,statisticsDisplayName:R.enableDisplayNameInStats?O:void 0,statisticsId:R.enableEmailInStats?y:void 0}));s[E.JITSI_CONNECTION_CONFERENCE_KEY]=L,L[N.JITSI_CONFERENCE_URL_KEY]=p,n(I(L)),v(L,n),(0,A.sendLocalParticipant)(u,L),L.join(T)}},e.checkIfCanJoin=function(){return function(n,t){var o=t()['features/base/conference'],c=o.authRequired,u=o.password;c&&n(I(c)),c&&c.join(u)}},e.dataChannelOpened=function(){return{type:l.DATA_CHANNEL_OPENED}},e.kickedOut=h,e.lockStateChanged=M,e.onStartMutedPolicyChanged=J,e.p2pStatusChanged=function(n){return{type:l.P2P_STATUS_CHANGED,p2p:n}},e.sendTones=function(n,t,o){return{type:l.SEND_TONES,tones:n,duration:t,pause:o}},e.setDesktopSharingEnabled=function(n){return{type:l.SET_DESKTOP_SHARING_ENABLED,desktopSharingEnabled:n}},e.setFollowMe=function(n){return{type:l.SET_FOLLOW_ME,enabled:n}},e.setMaxReceiverVideoQuality=function(n){return{type:l.SET_MAX_RECEIVER_VIDEO_QUALITY,maxReceiverVideoQuality:n}},e.setPassword=function(n,t,o){return function(c,u){switch(t){case n.join:var E=u()['features/base/conference'];E.passwordRequired===n&&(c({type:l.SET_PASSWORD,conference:n,method:t,password:o}),(E=u()['features/base/conference']).password!==o||E.passwordRequired||E.conference||t.call(n,o));break;case n.lock:var f=u()['features/base/conference'];return f.conference===n?t.call(n,o).then(function(){return c({type:l.SET_PASSWORD,conference:n,method:t,password:o})}).catch(function(n){return c({type:l.SET_PASSWORD_FAILED,error:n})}):Promise.reject()}}},e.setPreferredVideoQuality=function(n){return{type:l.SET_PREFERRED_VIDEO_QUALITY,preferredVideoQuality:n}},e.setRoom=function(n){return{type:l.SET_ROOM,room:n}},e.setStartMutedPolicy=function(n,t){return function(o,c){var u=(0,A.getCurrentConference)(c());return u&&u.setStartMutedPolicy({audio:n,video:t}),o(J(n,t))}},e.setSubject=function(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:'';return function(t,o){var c=o()['features/base/conference'].conference;c?c.setSubject(n):t({type:l.SET_PENDING_SUBJECT_CHANGE,subject:n})}};var t=n(r(d[1])),o=r(d[2]),c=r(d[3]),u=r(d[4]),E=r(d[5]),f=r(d[6]),s=r(d[7]),C=r(d[8]),p=r(d[9]),_=r(d[10]),l=r(d[11]),N=r(d[12]),A=r(d[13]),T=n(r(d[14]));function v(n,t){n.on(f.JitsiConferenceEvents.CONFERENCE_ERROR,function(n){return T.default.error('Conference error.',n)}),n.on(f.JitsiConferenceEvents.CONFERENCE_FAILED,function(){for(var o=arguments.length,c=new Array(o),u=0;u1&&void 0!==arguments[1]?arguments[1]:{};return{action:t,attributes:n,source:'jitsi-meet-api'}},e.createAudioOnlyChangedEvent=function(t){return{action:"audio.only."+(t?'enabled':'disabled')}},e.createConnectionEvent=function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return{action:t,actionSubject:'connection',attributes:n}},e.createCalendarClickedEvent=function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return{action:'clicked',actionSubject:t,attributes:n,source:'calendar',type:o}},e.createCalendarSelectedEvent=function(){return{action:'selected',actionSubject:'calendar.selected',attributes:arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},source:'calendar',type:o}},e.createCalendarConnectedEvent=function(){return{action:'calendar.connected',actionSubject:'calendar.connected',attributes:arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}}},e.createRecentClickedEvent=function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return{action:'clicked',actionSubject:t,attributes:n,source:'recent.list',type:o}},e.createChromeExtensionBannerEvent=function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return{action:t?'install':'cancel',attributes:n,source:'chrome.extension.banner',type:o}},e.createRecentSelectedEvent=function(){return{action:'selected',actionSubject:'recent.list.selected',attributes:arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},source:'recent.list',type:o}},e.createDeepLinkingPageEvent=function(t,n){var c=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return{action:t,actionSubject:n,source:'deepLinkingPage',attributes:c}},e.createDeviceChangedEvent=function(t,n){return{action:'device.changed',attributes:{device_type:n,media_type:t}}},e.createE2EEEvent=function(t){return{action:t,actionSubject:'e2ee'}},e.createFeedbackOpenEvent=function(){return{action:'feedback.opened'}},e.createInviteDialogEvent=function(t,n){var c=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return{action:t,actionSubject:n,attributes:c,source:'inviteDialog'}},e.createNetworkInfoEvent=function(t){var n=t.isOnline,c=t.networkType,o=t.details,u={isOnline:n};return c&&(u.networkType=c),o&&(u.details=o),{action:'network.info',attributes:u}},e.createOfferAnswerFailedEvent=function(){return{action:'offer.answer.failure'}},e.createPageReloadScheduledEvent=function(t,c,o){return{action:'page.reload.scheduled',attributes:(0,n.default)({reason:t,timeout:c},o)}},e.createPinnedEvent=function(t,n,o){return{type:c,action:t,actionSubject:'participant',objectType:'participant',objectId:n,attributes:o}},e.createProfilePanelButtonEvent=function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return{action:'clicked',actionSubject:t,attributes:n,source:'profile.panel',type:o}},e.createRecordingDialogEvent=function(t,n){var c=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return{action:'clicked',actionSubject:n,attributes:c,source:t+".recording.dialog",type:o}},e.createLiveStreamingDialogEvent=function(t,n){return{action:'clicked',actionSubject:n,source:t+".liveStreaming.dialog",type:o}},e.createLocalTracksDurationEvent=function(t){var n=t.audio,c=t.video,o=t.conference,u=c.camera,l=c.desktop;return{action:'local.tracks.durations',attributes:{audio:n.value,camera:u.value,conference:o.value,desktop:l.value}}},e.createRecordingEvent=function(t,n,c){return{action:t,actionSubject:"recording."+n,attributes:{value:c}}},e.createRejoinedEvent=function(t){var n=t.url,c=t.lastConferenceDuration,o=t.timeSinceLeft;return{action:'rejoined',attributes:{lastConferenceDuration:c,timeSinceLeft:o,url:n}}},e.createRemoteMuteConfirmedEvent=function(t){return{action:'clicked',actionSubject:'remote.mute.dialog.confirm.button',attributes:{participant_id:t},source:'remote.mute.dialog',type:o}},e.createRemoteVideoMenuButtonEvent=function(t,n){return{action:'clicked',actionSubject:t,attributes:n,source:'remote.video.menu',type:o}},e.createVideoBlurEvent=function(t){return{action:t,actionSubject:'video.blur'}},e.createScreenSharingEvent=function(t){return{action:t,actionSubject:'screen.sharing'}},e.createSelectParticipantFailedEvent=function(t){var n={action:'select.participant.failed'};t&&(n.error=t.toString());return n},e.createSharedVideoEvent=function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return{action:t,attributes:n,actionSubject:'shared.video'}},e.createShortcutEvent=function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:u,c=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return{action:n,actionSubject:'keyboard.shortcut',actionSubjectId:t,attributes:c,source:'keyboard.shortcut',type:o}},e.createStartAudioOnlyEvent=function(t){return{action:'start.audio.only',attributes:{enabled:t}}},e.createStartSilentEvent=function(){return{action:'start.silent'}},e.createStartMutedConfigurationEvent=function(t,n,c){return{action:'start.muted.configuration',attributes:{source:t,audio_mute:n,video_mute:c}}},e.createSyncTrackStateEvent=function(t,n){return{action:'sync.track.state',attributes:{media_type:t,muted:n}}},e.createToolbarEvent=function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return{action:'clicked',actionSubject:t,attributes:n,source:'toolbar.button',type:o}},e.createTrackMutedEvent=function(t,n){var c=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];return{action:'track.muted',attributes:{media_type:t,muted:c,reason:n}}},e.createWelcomePageEvent=function(t,n){var c=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return{action:t,actionSubject:n,attributes:c,source:'welcomePage'}},e.VIDEO_MUTE=e.AUDIO_MUTE=e.ACTION_SHORTCUT_TRIGGERED=e.ACTION_SHORTCUT_RELEASED=e.ACTION_SHORTCUT_PRESSED=e.ACTION_UNPINNED=e.ACTION_PINNED=void 0;var n=t(r(d[1])),c='track',o='ui';e.ACTION_PINNED='pinned';e.ACTION_UNPINNED='unpinned';e.ACTION_SHORTCUT_PRESSED='pressed';e.ACTION_SHORTCUT_RELEASED='released';var u='triggered';e.ACTION_SHORTCUT_TRIGGERED=u;e.AUDIO_MUTE='audio.mute';e.VIDEO_MUTE='video.mute'},440,[3,53]); -__d(function(g,r,i,a,m,e,d){var t=r(d[0]),n=r(d[1]);Object.defineProperty(e,"__esModule",{value:!0}),e.sendAnalytics=function(t){try{s.analytics.sendEvent(t)}catch(t){f.default.warn("Error sending analytics event: "+t)}},e.resetAnalytics=function(){s.analytics.reset()},e.createHandlers=function(t){var n=t.getState;if((0,l.getJitsiMeetGlobalNS)().analyticsHandlers=[],window.analyticsHandlers=[],!(0,s.isAnalyticsEnabled)(n))return Promise.resolve([]);var c=n(),v=c['features/base/config'],h=c['features/base/connection'].locationURL,p=h?h.host:'',b=v.analytics,w=void 0===b?{}:b,A=v.deploymentInfo,E=w.amplitudeAPPKey,k=w.blackListedEvents,S=w.scriptURLs,P=w.googleAnalyticsTrackingId,H=w.matomoEndpoint,I=w.matomoSiteID,L=w.whiteListedEvents,x=c['features/base/jwt'],M=x.group,N=x.user,C={amplitudeAPPKey:E,blackListedEvents:k,envType:A&&A.envType||'dev',googleAnalyticsTrackingId:P,matomoEndpoint:H,matomoSiteID:I,group:M,host:p,product:A&&A.product,subproduct:A&&A.environment,user:N&&N.id,version:s.default.version,whiteListedEvents:L},T=[];try{var _=new u.AmplitudeHandler(C);T.push(_)}catch(t){}try{var j=new u.MatomoHandler(C);T.push(j)}catch(t){}return y(S,C).then(function(t){if(T.push.apply(T,(0,o.default)(t)),0===T.length)throw new Error('No analytics handlers created!');return T}).catch(function(t){return s.analytics.dispose(),f.default.error(t),[]})},e.initAnalytics=function(t,n){var o=t.getState;if(!(0,s.isAnalyticsEnabled)(o)||0===n.length)return;var l=o(),u=l['features/base/config'],f=u.deploymentInfo,y=l['features/base/jwt'],v=y.group,h=y.server,p=l['features/base/conference'].room,b={};h&&(b.server=h);v&&(b.group=v);if(b.websocket='ReactNative'!==navigator.product&&'string'==typeof u.websocket,f)for(var w in f)f.hasOwnProperty(w)&&(b[w]=f[w]);if(s.analytics.addPermanentProperties(b),s.analytics.setConferenceName(p),s.analytics.setAnalyticsHandlers(n),!(0,c.isMobileBrowser)()&&s.browser.isChrome()){var A=l['features/base/config'].chromeExtensionBanner;(0,c.checkChromeExtensionsInstalled)(A).then(function(t){(null==t?void 0:t.length)&&s.analytics.addPermanentProperties({hasChromeExtension:t.some(function(t){return t})})})}};var o=n(r(d[2])),s=t(r(d[3])),l=r(d[4]),c=r(d[5]),u=r(d[6]),f=n(r(d[7]));function y(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],n=arguments.length>1?arguments[1]:void 0,s=[],c=function(t){s.push((0,l.loadScript)(t).then(function(){return{type:'success'}},function(n){return{type:'error',error:n,url:t}}))},u=t,y=Array.isArray(u),v=0;for(u=y?u:u["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var h;if(y){if(v>=u.length)break;h=u[v++]}else{if((v=u.next()).done)break;h=v.value}c(h)}return Promise.all(s).then(function(t){var s=t,c=Array.isArray(s),u=0;for(s=c?s:s["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var y;if(c){if(u>=s.length)break;y=s[u++]}else{if((u=s.next()).done)break;y=u.value}var v=y;'error'===v.type&&f.default.warn("Failed to load "+v.url+": "+v.error)}var h=[],p=(0,o.default)((0,l.getJitsiMeetGlobalNS)().analyticsHandlers).concat((0,o.default)(window.analyticsHandlers)),b=Array.isArray(p),w=0;for(p=b?p:p["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var A;if(b){if(w>=p.length)break;A=p[w++]}else{if((w=p.next()).done)break;A=w.value}var E=A;try{h.push(new E(n))}catch(t){f.default.warn("Error creating analytics handler: "+t)}}return f.default.debug("Loaded "+h.length+" analytics handlers"),h})}},441,[2,3,31,442,446,1045,1046,1053]); -__d(function(g,r,i,a,m,e,d){var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0});var n={analytics:!0,browser:!0,JitsiConferenceErrors:!0,JitsiConferenceEvents:!0,JitsiConnectionErrors:!0,JitsiConnectionEvents:!0,JitsiConnectionQualityEvents:!0,JitsiDetectionEvents:!0,JitsiE2ePingEvents:!0,JitsiMediaDevicesEvents:!0,JitsiParticipantConnectionStatus:!0,JitsiRecordingConstants:!0,JitsiSIPVideoGWStatus:!0,JitsiTrackErrors:!0,JitsiTrackEvents:!0};Object.defineProperty(e,"default",{enumerable:!0,get:function(){return s.default}}),e.JitsiTrackEvents=e.JitsiTrackErrors=e.JitsiSIPVideoGWStatus=e.JitsiRecordingConstants=e.JitsiParticipantConnectionStatus=e.JitsiMediaDevicesEvents=e.JitsiE2ePingEvents=e.JitsiDetectionEvents=e.JitsiConnectionQualityEvents=e.JitsiConnectionEvents=e.JitsiConnectionErrors=e.JitsiConferenceEvents=e.JitsiConferenceErrors=e.browser=e.analytics=void 0;var s=t(r(d[1])),o=r(d[2]);Object.keys(o).forEach(function(t){"default"!==t&&"__esModule"!==t&&(Object.prototype.hasOwnProperty.call(n,t)||Object.defineProperty(e,t,{enumerable:!0,get:function(){return o[t]}}))});var c=r(d[3]);Object.keys(c).forEach(function(t){"default"!==t&&"__esModule"!==t&&(Object.prototype.hasOwnProperty.call(n,t)||Object.defineProperty(e,t,{enumerable:!0,get:function(){return c[t]}}))});var v=r(d[4]);Object.keys(v).forEach(function(t){"default"!==t&&"__esModule"!==t&&(Object.prototype.hasOwnProperty.call(n,t)||Object.defineProperty(e,t,{enumerable:!0,get:function(){return v[t]}}))}),r(d[5]),r(d[6]);var u=s.default.analytics;e.analytics=u;var f=s.default.util.browser;e.browser=f;var l=s.default.errors.conference;e.JitsiConferenceErrors=l;var J=s.default.events.conference;e.JitsiConferenceEvents=J;var E=s.default.errors.connection;e.JitsiConnectionErrors=E;var y=s.default.events.connection;e.JitsiConnectionEvents=y;var C=s.default.events.connectionQuality;e.JitsiConnectionQualityEvents=C;var p=s.default.events.detection;e.JitsiDetectionEvents=p;var b=s.default.events.e2eping;e.JitsiE2ePingEvents=b;var P=s.default.events.mediaDevices;e.JitsiMediaDevicesEvents=P;var O=s.default.constants.participantConnectionStatus;e.JitsiParticipantConnectionStatus=O;var j=s.default.constants.recording;e.JitsiRecordingConstants=j;var k=s.default.constants.sipVideoGW;e.JitsiSIPVideoGWStatus=k;var S=s.default.errors.track;e.JitsiTrackErrors=S;var _=s.default.events.track;e.JitsiTrackEvents=_},442,[3,443,469,470,471,515,1044]); -__d(function(g,r,i,a,m,e,d){var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return n.default}}),r(d[1]);var n=t(r(d[2]));!(function(t){if(void 0===t.$){var n=r(d[3]);n(t),t.$=n}})(g||window||this)},443,[3,444,466,468]); -__d(function(g,r,i,a,m,e,d){r(d[0])},444,[445]); -__d(function(g,r,i,a,m,e,d){var t=r(d[0]),s=r(d[1]);t.NativeModules.WiFiStats&&((0,s.getJitsiMeetGlobalNS)().getWiFiStats=t.NativeModules.WiFiStats.getWiFiStats)},445,[15,446]); -__d(function(g,r,i,a,m,e,d){Object.defineProperty(e,"__esModule",{value:!0});var t=r(d[0]);Object.keys(t).forEach(function(n){"default"!==n&&"__esModule"!==n&&Object.defineProperty(e,n,{enumerable:!0,get:function(){return t[n]}})});var n=r(d[1]);Object.keys(n).forEach(function(t){"default"!==t&&"__esModule"!==t&&Object.defineProperty(e,t,{enumerable:!0,get:function(){return n[t]}})});var u=r(d[2]);Object.keys(u).forEach(function(t){"default"!==t&&"__esModule"!==t&&Object.defineProperty(e,t,{enumerable:!0,get:function(){return u[t]}})});var o=r(d[3]);Object.keys(o).forEach(function(t){"default"!==t&&"__esModule"!==t&&Object.defineProperty(e,t,{enumerable:!0,get:function(){return o[t]}})});var c=r(d[4]);Object.keys(c).forEach(function(t){"default"!==t&&"__esModule"!==t&&Object.defineProperty(e,t,{enumerable:!0,get:function(){return c[t]}})});var f=r(d[5]);Object.keys(f).forEach(function(t){"default"!==t&&"__esModule"!==t&&Object.defineProperty(e,t,{enumerable:!0,get:function(){return f[t]}})})},446,[447,448,450,451,462,463]); -__d(function(g,r,i,a,m,e,d){Object.defineProperty(e,"__esModule",{value:!0}),e.createDeferred=function(){var n={};return n.promise=new Promise(function(o,t){n.resolve=o,n.reject=t}),n},e.escapeRegexp=function(o){if('string'!=typeof o)throw new TypeError('Expected a string');return o.replace(n,'\\$&')},e.getBaseUrl=function(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:window,o=n.document.querySelector('base');if(o&&o.href)return o.href;var t=n.location,u=t.protocol,c=t.host;return u+"//"+c},e.getJitsiMeetGlobalNS=function(){window.JitsiMeetJS||(window.JitsiMeetJS={});window.JitsiMeetJS.app||(window.JitsiMeetJS.app={});return window.JitsiMeetJS.app},e.assignIfDefined=function(n,o){var t=Object(n);for(var u in o)if(o.hasOwnProperty(u)){var c=o[u];void 0!==c&&(t[u]=c)}return t},e.reportError=function(n){var o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:'';console.error(o,n),window.onerror&&window.onerror(o,null,null,null,n)};var n=/[|\\{}()[\]^$+*?.-]/g},447,[]); -__d(function(g,r,i,a,m,e,d){Object.defineProperty(e,"__esModule",{value:!0}),e.doGetJSON=function(o,u){var c=fetch(o).then(function(t){var n=t.json();return t.ok?n:n.then(function(t){return Promise.reject(t)})});if(u)return(0,t.timeoutPromise)(c,n).catch(function(o){return o.status>=400&&o.status<500?Promise.reject(o):(0,t.timeoutPromise)(c,n)});return c};var t=r(d[0]),n=3e3},448,[449]); -__d(function(g,r,i,a,m,e,d){Object.defineProperty(e,"__esModule",{value:!0}),e.timeoutPromise=function(t,n){return new Promise(function(o,u){var c=setTimeout(function(){return u(new Error('timeout'))},n);t.then(function(t){o(t),clearTimeout(c)},function(t){u(t),clearTimeout(c)})})}},449,[]); -__d(function(g,r,i,a,m,e,d){var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.loadScript=function(t){var u,s,c,l,f,p,w,h,x,b,v,_=arguments;return n.default.async(function(k){for(;;)switch(k.prev=k.next){case 0:if(u=_.length>1&&void 0!==_[1]?_[1]:o,s=_.length>2&&void 0!==_[2]&&_[2],c=new URL(t),l=c.hostname,f=c.pathname,p=c.protocol,l&&f&&p){k.next=5;break}throw new Error("unexpected url: "+t);case 5:return w=new AbortController,h=w.signal,x=setTimeout(function(){w.abort()},u),k.next=10,n.default.awrap(fetch(t,{signal:h}));case 10:b=k.sent,clearTimeout(x),k.t0=b.status,k.next=200===k.t0?15:21;break;case 15:return k.next=17,n.default.awrap(b.text());case 17:if(v=k.sent,!s){k.next=20;break}return k.abrupt("return",v);case 20:return k.abrupt("return",eval.call(window,v));case 21:throw new Error("loadScript error: "+b.statusText);case 22:case"end":return k.stop()}},null,this)};var n=t(r(d[1])),o=5e3},450,[3,270]); -__d(function(g,r,i,a,m,e,d){var n=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.openURLInBrowser=function(n){o.Linking.openURL(n).catch(function(o){t.default.error("An error occurred while trying to open "+n,o)})};var o=r(d[1]),t=n(r(d[2]))},451,[3,15,452]); -__d(function(g,r,i,a,m,e,d){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var t=(0,r(d[0]).getLogger)('features/base/util');e.default=t},452,[453]); -__d(function(g,r,i,a,m,e,d){var o=r(d[0]),t=r(d[1]);Object.defineProperty(e,"__esModule",{value:!0}),e.getLogger=function(o){var t='ReactNative'===navigator.product?f:v;return(0,n.getLogger)(o,void 0,t)},e._initLogging=void 0;var l=t(r(d[2])),n=o(r(d[3])),u=t(r(d[4])),v={},f={disableCallerInfo:!0};var s=l.default.once(function(){if('ReactNative'===navigator.product){var o=r(d[5]).default;n.default.setGlobalOptions(f),o.setGlobalLogOptions(f),n.default.removeGlobalTransport(console),o.removeGlobalLogTransport(console),n.default.addGlobalTransport(u.default),o.addGlobalLogTransport(u.default)}});e._initLogging=s},453,[2,3,454,392,455,443]); -__d(function(n,t,r,e,u,i,o){(function(){var t,r=200,e='Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',o='Expected a function',f='__lodash_hash_undefined__',a=500,c='__lodash_placeholder__',l=1,s=2,h=4,p=1,v=2,_=1,g=2,d=4,y=8,x=16,b=32,w=64,m=128,j=256,A=512,k=30,z='...',O=800,I=16,R=1,E=2,S=1/0,L=9007199254740991,W=1.7976931348623157e308,C=NaN,T=4294967295,U=4294967294,B=2147483647,$=[['ary',m],['bind',_],['bindKey',g],['curry',y],['curryRight',x],['flip',A],['partial',b],['partialRight',w],['rearg',j]],D='[object Arguments]',M='[object Array]',F='[object AsyncFunction]',N='[object Boolean]',P='[object Date]',Z='[object DOMException]',q='[object Error]',K='[object Function]',V='[object GeneratorFunction]',G='[object Map]',H='[object Number]',J='[object Null]',Y='[object Object]',Q='[object Proxy]',X='[object RegExp]',nn='[object Set]',tn='[object String]',rn='[object Symbol]',en='[object Undefined]',un='[object WeakMap]',on='[object WeakSet]',fn='[object ArrayBuffer]',an='[object DataView]',cn='[object Float32Array]',ln='[object Float64Array]',sn='[object Int8Array]',hn='[object Int16Array]',pn='[object Int32Array]',vn='[object Uint8Array]',_n='[object Uint8ClampedArray]',gn='[object Uint16Array]',dn='[object Uint32Array]',yn=/\b__p \+= '';/g,xn=/\b(__p \+=) '' \+/g,bn=/(__e\(.*?\)|\b__t\)) \+\n'';/g,wn=/&(?:amp|lt|gt|quot|#39);/g,mn=/[&<>"']/g,jn=RegExp(wn.source),An=RegExp(mn.source),kn=/<%-([\s\S]+?)%>/g,zn=/<%([\s\S]+?)%>/g,On=/<%=([\s\S]+?)%>/g,In=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,Rn=/^\w*$/,En=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,Sn=/[\\^$.*+?()[\]{}|]/g,Ln=RegExp(Sn.source),Wn=/^\s+|\s+$/g,Cn=/^\s+/,Tn=/\s+$/,Un=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,Bn=/\{\n\/\* \[wrapped with (.+)\] \*/,$n=/,? & /,Dn=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,Mn=/\\(\\)?/g,Fn=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,Nn=/\w*$/,Pn=/^[-+]0x[0-9a-f]+$/i,Zn=/^0b[01]+$/i,qn=/^\[object .+?Constructor\]$/,Kn=/^0o[0-7]+$/i,Vn=/^(?:0|[1-9]\d*)$/,Gn=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,Hn=/($^)/,Jn=/['\n\r\u2028\u2029\\]/g,Yn="[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]",Qn="[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]",Xn="(?:\\ud83c[\\udde6-\\uddff]){2}",nt="[\\ud800-\\udbff][\\udc00-\\udfff]",tt="[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|\\ud83c[\\udffb-\\udfff])?"+("(?:\\u200d(?:"+["[^\\ud800-\\udfff]",Xn,nt].join('|')+")[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|\\ud83c[\\udffb-\\udfff])?)*"),rt='(?:'+["[\\u2700-\\u27bf]",Xn,nt].join('|')+')'+tt,et='(?:'+["[^\\ud800-\\udfff][\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]?",Qn,Xn,nt,"[\\ud800-\\udfff]"].join('|')+')',ut=RegExp("['\u2019]",'g'),it=RegExp(Qn,'g'),ot=RegExp("\\ud83c[\\udffb-\\udfff](?=\\ud83c[\\udffb-\\udfff])|"+et+tt,'g'),ft=RegExp(["[A-Z\\xc0-\\xd6\\xd8-\\xde]?[a-z\\xdf-\\xf6\\xf8-\\xff]+(?:['\u2019](?:d|ll|m|re|s|t|ve))?(?="+[Yn,"[A-Z\\xc0-\\xd6\\xd8-\\xde]",'$'].join('|')+')',"(?:[A-Z\\xc0-\\xd6\\xd8-\\xde]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?(?="+[Yn,"[A-Z\\xc0-\\xd6\\xd8-\\xde](?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])",'$'].join('|')+')',"[A-Z\\xc0-\\xd6\\xd8-\\xde]?(?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?:['\u2019](?:d|ll|m|re|s|t|ve))?","[A-Z\\xc0-\\xd6\\xd8-\\xde]+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?",'\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])','\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])','\\d+',rt].join('|'),'g'),at=RegExp("[\\u200d\\ud800-\\udfff\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff\\ufe0e\\ufe0f]"),ct=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,lt=['Array','Buffer','DataView','Date','Error','Float32Array','Float64Array','Function','Int8Array','Int16Array','Int32Array','Map','Math','Object','Promise','RegExp','Set','String','Symbol','TypeError','Uint8Array','Uint8ClampedArray','Uint16Array','Uint32Array','WeakMap','_','clearTimeout','isFinite','parseInt','setTimeout'],st=-1,ht={};ht[cn]=ht[ln]=ht[sn]=ht[hn]=ht[pn]=ht[vn]=ht[_n]=ht[gn]=ht[dn]=!0,ht[D]=ht[M]=ht[fn]=ht[N]=ht[an]=ht[P]=ht[q]=ht[K]=ht[G]=ht[H]=ht[Y]=ht[X]=ht[nn]=ht[tn]=ht[un]=!1;var pt={};pt[D]=pt[M]=pt[fn]=pt[an]=pt[N]=pt[P]=pt[cn]=pt[ln]=pt[sn]=pt[hn]=pt[pn]=pt[G]=pt[H]=pt[Y]=pt[X]=pt[nn]=pt[tn]=pt[rn]=pt[vn]=pt[_n]=pt[gn]=pt[dn]=!0,pt[q]=pt[K]=pt[un]=!1;var vt={'\\':'\\',"'":"'",'\n':'n','\r':'r',"\u2028":'u2028',"\u2029":'u2029'},_t=parseFloat,gt=parseInt,dt='object'==typeof n&&n&&n.Object===Object&&n,yt='object'==typeof self&&self&&self.Object===Object&&self,xt=dt||yt||Function('return this')(),bt='object'==typeof i&&i&&!i.nodeType&&i,wt=bt&&'object'==typeof u&&u&&!u.nodeType&&u,mt=wt&&wt.exports===bt,jt=mt&&dt.process,At=(function(){try{var n=wt&&wt.require&&wt.require('util').types;return n||jt&&jt.binding&&jt.binding('util')}catch(n){}})(),kt=At&&At.isArrayBuffer,zt=At&&At.isDate,Ot=At&&At.isMap,It=At&&At.isRegExp,Rt=At&&At.isSet,Et=At&&At.isTypedArray;function St(n,t,r){switch(r.length){case 0:return n.call(t);case 1:return n.call(t,r[0]);case 2:return n.call(t,r[0],r[1]);case 3:return n.call(t,r[0],r[1],r[2])}return n.apply(t,r)}function Lt(n,t,r,e){for(var u=-1,i=null==n?0:n.length;++u-1}function $t(n,t,r){for(var e=-1,u=null==n?0:n.length;++e-1;);return r}function lr(n,t){for(var r=n.length;r--&&Ht(t,n[r],0)>-1;);return r}function sr(n,t){for(var r=n.length,e=0;r--;)n[r]===t&&++e;return e}var hr=nr({'\xc0':'A','\xc1':'A','\xc2':'A','\xc3':'A','\xc4':'A','\xc5':'A','\xe0':'a','\xe1':'a','\xe2':'a','\xe3':'a','\xe4':'a','\xe5':'a','\xc7':'C','\xe7':'c','\xd0':'D','\xf0':'d','\xc8':'E','\xc9':'E','\xca':'E','\xcb':'E','\xe8':'e','\xe9':'e','\xea':'e','\xeb':'e','\xcc':'I','\xcd':'I','\xce':'I','\xcf':'I','\xec':'i','\xed':'i','\xee':'i','\xef':'i','\xd1':'N','\xf1':'n','\xd2':'O','\xd3':'O','\xd4':'O','\xd5':'O','\xd6':'O','\xd8':'O','\xf2':'o','\xf3':'o','\xf4':'o','\xf5':'o','\xf6':'o','\xf8':'o','\xd9':'U','\xda':'U','\xdb':'U','\xdc':'U','\xf9':'u','\xfa':'u','\xfb':'u','\xfc':'u','\xdd':'Y','\xfd':'y','\xff':'y','\xc6':'Ae','\xe6':'ae','\xde':'Th','\xfe':'th','\xdf':'ss',"\u0100":'A',"\u0102":'A',"\u0104":'A',"\u0101":'a',"\u0103":'a',"\u0105":'a',"\u0106":'C',"\u0108":'C',"\u010a":'C',"\u010c":'C',"\u0107":'c',"\u0109":'c',"\u010b":'c',"\u010d":'c',"\u010e":'D',"\u0110":'D',"\u010f":'d',"\u0111":'d',"\u0112":'E',"\u0114":'E',"\u0116":'E',"\u0118":'E',"\u011a":'E',"\u0113":'e',"\u0115":'e',"\u0117":'e',"\u0119":'e',"\u011b":'e',"\u011c":'G',"\u011e":'G',"\u0120":'G',"\u0122":'G',"\u011d":'g',"\u011f":'g',"\u0121":'g',"\u0123":'g',"\u0124":'H',"\u0126":'H',"\u0125":'h',"\u0127":'h',"\u0128":'I',"\u012a":'I',"\u012c":'I',"\u012e":'I',"\u0130":'I',"\u0129":'i',"\u012b":'i',"\u012d":'i',"\u012f":'i',"\u0131":'i',"\u0134":'J',"\u0135":'j',"\u0136":'K',"\u0137":'k',"\u0138":'k',"\u0139":'L',"\u013b":'L',"\u013d":'L',"\u013f":'L',"\u0141":'L',"\u013a":'l',"\u013c":'l',"\u013e":'l',"\u0140":'l',"\u0142":'l',"\u0143":'N',"\u0145":'N',"\u0147":'N',"\u014a":'N',"\u0144":'n',"\u0146":'n',"\u0148":'n',"\u014b":'n',"\u014c":'O',"\u014e":'O',"\u0150":'O',"\u014d":'o',"\u014f":'o',"\u0151":'o',"\u0154":'R',"\u0156":'R',"\u0158":'R',"\u0155":'r',"\u0157":'r',"\u0159":'r',"\u015a":'S',"\u015c":'S',"\u015e":'S',"\u0160":'S',"\u015b":'s',"\u015d":'s',"\u015f":'s',"\u0161":'s',"\u0162":'T',"\u0164":'T',"\u0166":'T',"\u0163":'t',"\u0165":'t',"\u0167":'t',"\u0168":'U',"\u016a":'U',"\u016c":'U',"\u016e":'U',"\u0170":'U',"\u0172":'U',"\u0169":'u',"\u016b":'u',"\u016d":'u',"\u016f":'u',"\u0171":'u',"\u0173":'u',"\u0174":'W',"\u0175":'w',"\u0176":'Y',"\u0177":'y',"\u0178":'Y',"\u0179":'Z',"\u017b":'Z',"\u017d":'Z',"\u017a":'z',"\u017c":'z',"\u017e":'z',"\u0132":'IJ',"\u0133":'ij',"\u0152":'Oe',"\u0153":'oe',"\u0149":"'n","\u017f":'s'}),pr=nr({'&':'&','<':'<','>':'>','"':'"',"'":'''});function vr(n){return'\\'+vt[n]}function _r(n,r){return null==n?t:n[r]}function gr(n){return at.test(n)}function dr(n){return ct.test(n)}function yr(n){for(var t,r=[];!(t=n.next()).done;)r.push(t.value);return r}function xr(n){var t=-1,r=Array(n.size);return n.forEach(function(n,e){r[++t]=[e,n]}),r}function br(n,t){return function(r){return n(t(r))}}function wr(n,t){for(var r=-1,e=n.length,u=0,i=[];++r','"':'"',''':"'"});function Rr(n){for(var t=ot.lastIndex=0;ot.test(n);)++t;return t}function Er(n){return n.match(ot)||[]}function Sr(n){return n.match(ft)||[]}var Lr=(function n(u){var i,Dn=(u=null==u?xt:Lr.defaults(xt.Object(),u,Lr.pick(xt,lt))).Array,Yn=u.Date,Qn=u.Error,Xn=u.Function,nt=u.Math,tt=u.Object,rt=u.RegExp,et=u.String,ot=u.TypeError,ft=Dn.prototype,at=Xn.prototype,ct=tt.prototype,vt=u['__core-js_shared__'],dt=at.toString,yt=ct.hasOwnProperty,bt=0,wt=(i=/[^.]+$/.exec(vt&&vt.keys&&vt.keys.IE_PROTO||''))?'Symbol(src)_1.'+i:'',jt=ct.toString,At=dt.call(tt),Zt=xt._,qt=rt('^'+dt.call(yt).replace(Sn,'\\$&').replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,'$1.*?')+'$'),nr=mt?u.Buffer:t,Ar=u.Symbol,Rr=u.Uint8Array,Er=nr?nr.allocUnsafe:t,Wr=br(tt.getPrototypeOf,tt),Cr=tt.create,Tr=ct.propertyIsEnumerable,Ur=ft.splice,Br=Ar?"function"==typeof Ar?Ar.isConcatSpreadable:"@@isConcatSpreadable":t,$r=Ar?"function"==typeof Ar?Ar.iterator:"@@iterator":t,Dr=Ar?"function"==typeof Ar?Ar.toStringTag:"@@toStringTag":t,Mr=(function(){try{var n=co(tt,'defineProperty');return n({},'',{}),n}catch(n){}})(),Fr=u.clearTimeout!==xt.clearTimeout&&u.clearTimeout,Nr=Yn&&Yn.now!==xt.Date.now&&Yn.now,Pr=u.setTimeout!==xt.setTimeout&&u.setTimeout,Zr=nt.ceil,qr=nt.floor,Kr=tt.getOwnPropertySymbols,Vr=nr?nr.isBuffer:t,Gr=u.isFinite,Hr=ft.join,Jr=br(tt.keys,tt),Yr=nt.max,Qr=nt.min,Xr=Yn.now,ne=u.parseInt,te=nt.random,re=ft.reverse,ee=co(u,'DataView'),ue=co(u,'Map'),ie=co(u,'Promise'),oe=co(u,'Set'),fe=co(u,'WeakMap'),ae=co(tt,'create'),ce=fe&&new fe,le={},se=Ko(ee),he=Ko(ue),pe=Ko(ie),ve=Ko(oe),_e=Ko(fe),ge=Ar?"function"==typeof Ar?Ar.prototype:"@@prototype":t,de=ge?ge.valueOf:t,ye=ge?ge.toString:t;function xe(n){if(sa(n)&&!na(n)&&!(n instanceof je)){if(n instanceof me)return n;if(yt.call(n,'__wrapped__'))return Go(n)}return new me(n)}var be=(function(){function n(){}return function(r){if(!la(r))return{};if(Cr)return Cr(r);n.prototype=r;var e=new n;return n.prototype=t,e}})();function we(){}function me(n,r){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!r,this.__index__=0,this.__values__=t}function je(n){this.__wrapped__=n,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=T,this.__views__=[]}function Ae(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t=r?n:r)),n}function Ne(n,r,e,u,i,o){var f,a=r&l,c=r&s,p=r&h;if(e&&(f=i?e(n,u,i,o):e(n)),f!==t)return f;if(!la(n))return n;var v=na(n);if(v){if(f=yo(n),!a)return bi(n,f)}else{var _=po(n),g=_==K||_==V;if(ua(n))return hi(n,a);if(_==Y||_==D||g&&!i){if(f=c||g?{}:xo(n),!a)return c?ji(n,$e(f,n)):mi(n,Be(f,n))}else{if(!pt[_])return i?n:{};f=bo(n,_,a)}}o||(o=new Ie);var d=o.get(n);if(d)return d;o.set(n,f),ga(n)?n.forEach(function(t){f.add(Ne(t,r,e,t,n,o))}):ha(n)&&n.forEach(function(t,u){f.set(u,Ne(t,r,e,u,n,o))});var y=v?t:(p?c?ro:to:c?Na:Fa)(n);return Wt(y||n,function(t,u){y&&(t=n[u=t]),Ce(f,u,Ne(t,r,e,u,n,o))}),f}function Pe(n){var t=Fa(n);return function(r){return Ze(r,n,t)}}function Ze(n,r,e){var u=e.length;if(null==n)return!u;for(n=tt(n);u--;){var i=e[u],o=r[i],f=n[i];if(f===t&&!(i in n)||!o(f))return!1}return!0}function qe(n,r,e){if('function'!=typeof n)throw new ot(o);return Do(function(){n.apply(t,e)},r)}function Ke(n,t,e,u){var i=-1,o=Bt,f=!0,a=n.length,c=[],l=t.length;if(!a)return c;e&&(t=Dt(t,or(e))),u?(o=$t,f=!1):t.length>=r&&(o=ar,f=!1,t=new Oe(t));n:for(;++i-1},ke.prototype.set=function(n,t){var r=this.__data__,e=Te(r,n);return e<0?(++this.size,r.push([n,t])):r[e][1]=t,this},ze.prototype.clear=function(){this.size=0,this.__data__={hash:new Ae,map:new(ue||ke),string:new Ae}},ze.prototype.delete=function(n){var t=fo(this,n).delete(n);return this.size-=t?1:0,t},ze.prototype.get=function(n){return fo(this,n).get(n)},ze.prototype.has=function(n){return fo(this,n).has(n)},ze.prototype.set=function(n,t){var r=fo(this,n),e=r.size;return r.set(n,t),this.size+=r.size==e?0:1,this},Oe.prototype.add=Oe.prototype.push=function(n){return this.__data__.set(n,f),this},Oe.prototype.has=function(n){return this.__data__.has(n)},Ie.prototype.clear=function(){this.__data__=new ke,this.size=0},Ie.prototype.delete=function(n){var t=this.__data__,r=t.delete(n);return this.size=t.size,r},Ie.prototype.get=function(n){return this.__data__.get(n)},Ie.prototype.has=function(n){return this.__data__.has(n)},Ie.prototype.set=function(n,t){var r=this.__data__;if(r instanceof ke){var e=r.__data__;if(!ue||e.length<199)return e.push([n,t]),this.size=++r.size,this;r=this.__data__=new ze(e)}return r.set(n,t),this.size=r.size,this};var Ve=zi(ru),Ge=zi(eu,!0);function He(n,t){var r=!0;return Ve(n,function(n,e,u){return r=!!t(n,e,u)}),r}function Je(n,r,e){for(var u=-1,i=n.length;++ui?0:i+e),(u=u===t||u>i?i:Aa(u))<0&&(u+=i),u=e>u?0:ka(u);e0&&r(f)?t>1?Xe(f,t-1,r,e,u):Mt(u,f):e||(u[u.length]=f)}return u}var nu=Oi(),tu=Oi(!0);function ru(n,t){return n&&nu(n,t,Fa)}function eu(n,t){return n&&tu(n,t,Fa)}function uu(n,t){return Ut(t,function(t){return fa(n[t])})}function iu(n,r){for(var e=0,u=(r=ai(r,n)).length;null!=n&&et}function cu(n,t){return null!=n&&yt.call(n,t)}function lu(n,t){return null!=n&&t in tt(n)}function su(n,t,r){return n>=Qr(t,r)&&n=120&&s.length>=120)?new Oe(f&&s):t}s=n[0];var h=-1,p=a[0];n:for(;++h-1;)f!==n&&Ur.call(f,a,1),Ur.call(n,a,1);return n}function Tu(n,t){for(var r=n?t.length:0,e=r-1;r--;){var u=t[r];if(r==e||u!==i){var i=u;jo(u)?Ur.call(n,u,1):ni(n,u)}}return n}function Uu(n,t){return n+qr(te()*(t-n+1))}function Bu(n,t,r,e){for(var u=-1,i=Yr(Zr((t-n)/(r||1)),0),o=Dn(i);i--;)o[e?i:++u]=n,n+=r;return o}function $u(n,t){var r='';if(!n||t<1||t>L)return r;do{t%2&&(r+=n),(t=qr(t/2))&&(n+=n)}while(t);return r}function Du(n,t){return Mo(Co(n,t,pc),n+'')}function Mu(n){return Ee(Ja(n))}function Fu(n,t){var r=Ja(n);return Po(r,Fe(t,0,r.length))}function Nu(n,r,e,u){if(!la(n))return n;for(var i=-1,o=(r=ai(r,n)).length,f=o-1,a=n;null!=a&&++iu?0:u+t),(r=r>u?u:r)<0&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0;for(var i=Dn(u);++e>>1,o=n[i];null!==o&&!ya(o)&&(r?o<=t:o=r){var l=t?null:qi(n);if(l)return mr(l);f=!1,i=ar,c=new Oe}else c=t?[]:a;n:for(;++u=u?n:Ku(n,r,e)}var si=Fr||function(n){return xt.clearTimeout(n)};function hi(n,t){if(t)return n.slice();var r=n.length,e=Er?Er(r):new n.constructor(r);return n.copy(e),e}function pi(n){var t=new n.constructor(n.byteLength);return new Rr(t).set(new Rr(n)),t}function vi(n,t){var r=t?pi(n.buffer):n.buffer;return new n.constructor(r,n.byteOffset,n.byteLength)}function _i(n,t){var r=t?pi(n.buffer):n.buffer;return new n.constructor(r,n.byteOffset,n.length)}function gi(n,r){if(n!==r){var e=n!==t,u=null===n,i=n==n,o=ya(n),f=r!==t,a=null===r,c=r==r,l=ya(r);if(!a&&!l&&!o&&n>r||o&&f&&c&&!a&&!l||u&&f&&c||!e&&c||!i)return 1;if(!u&&!o&&!l&&n=f?a:a*('desc'==r[e]?-1:1)}return n.index-t.index}function yi(n,t,r,e){for(var u=-1,i=n.length,o=r.length,f=-1,a=t.length,c=Yr(i-o,0),l=Dn(a+c),s=!e;++f1?e[i-1]:t,f=i>2?e[2]:t;for(o=n.length>3&&'function'==typeof o?(i--,o):t,f&&Ao(e[0],e[1],f)&&(o=i<3?t:o,i=1),r=tt(r);++u-1?i[o?r[f]:f]:t}}function Ci(n){return no(function(r){var e=r.length,u=e,i=me.prototype.thru;for(n&&r.reverse();u--;){var f=r[u];if('function'!=typeof f)throw new ot(o);if(i&&!a&&'wrapper'==uo(f))var a=new me([],!0)}for(u=a?u:e;++u1&&g.reverse(),s&&c<_&&(g.length=c),this&&this!==xt&&this instanceof t&&(A=y||Si(A)),A.apply(j,g)}}function Ui(n,t){return function(r,e){return pu(r,n,t(e),{})}}function Bi(n,r){return function(e,u){var i;if(e===t&&u===t)return r;if(e!==t&&(i=e),u!==t){if(i===t)return u;'string'==typeof e||'string'==typeof u?(e=Qu(e),u=Qu(u)):(e=Yu(e),u=Yu(u)),i=n(e,u)}return i}}function $i(n){return no(function(t){return t=Dt(t,or(oo())),Du(function(r){var e=this;return n(t,function(n){return St(n,e,r)})})})}function Di(n,r){var e=(r=r===t?' ':Qu(r)).length;if(e<2)return e?$u(r,n):r;var u=$u(r,Zr(n/zr(r)));return gr(r)?li(Or(u),0,n).join(''):u.slice(0,n)}function Mi(n,t,r,e){var u=t&_,i=Si(n);return function t(){for(var o=-1,f=arguments.length,a=-1,c=e.length,l=Dn(c+f),s=this&&this!==xt&&this instanceof t?i:n;++aa))return!1;var l=o.get(n);if(l&&o.get(r))return l==r;var s=-1,h=!0,_=e&v?new Oe:t;for(o.set(n,r),o.set(r,n);++s1?'& ':'')+t[e],t=t.join(r>2?', ':' '),n.replace(Un,'{\n/* [wrapped with '+t+'] */\n')}function mo(n){return na(n)||Xf(n)||!!(Br&&n&&n[Br])}function jo(n,t){var r=typeof n;return!!(t=null==t?L:t)&&('number'==r||'symbol'!=r&&Vn.test(n))&&n>-1&&n%1==0&&n0){if(++r>=O)return arguments[0]}else r=0;return n.apply(t,arguments)}}function Po(n,r){var e=-1,u=n.length,i=u-1;for(r=r===t?u:r;++e1?n[r-1]:t;return _f(n,e='function'==typeof e?(n.pop(),e):t)});function mf(n){var t=xe(n);return t.__chain__=!0,t}function jf(n,t){return t(n)}var Af=no(function(n){var r=n.length,e=r?n[0]:0,u=this.__wrapped__,i=function(t){return Me(t,n)};return!(r>1||this.__actions__.length)&&u instanceof je&&jo(e)?((u=u.slice(e,+e+(r?1:0))).__actions__.push({func:jf,args:[i],thisArg:t}),new me(u,this.__chain__).thru(function(n){return r&&!n.length&&n.push(t),n})):this.thru(i)});var kf=Ai(function(n,t,r){yt.call(n,r)?++n[r]:De(n,r,1)});var zf=Wi(Qo),Of=Wi(Xo);function If(n,t){return(na(n)?Wt:Ve)(n,oo(t,3))}function Rf(n,t){return(na(n)?Ct:Ge)(n,oo(t,3))}var Ef=Ai(function(n,t,r){yt.call(n,r)?n[r].push(t):De(n,r,[t])});var Sf=Du(function(n,t,r){var e=-1,u='function'==typeof t,i=ra(n)?Dn(n.length):[];return Ve(n,function(n){i[++e]=u?St(t,n,r):vu(n,t,r)}),i}),Lf=Ai(function(n,t,r){De(n,r,t)});function Wf(n,t){return(na(n)?Dt:Au)(n,oo(t,3))}var Cf=Ai(function(n,t,r){n[r?0:1].push(t)},function(){return[[],[]]});var Tf=Du(function(n,t){if(null==n)return[];var r=t.length;return r>1&&Ao(n,t[0],t[1])?t=[]:r>2&&Ao(t[0],t[1],t[2])&&(t=[t[0]]),Eu(n,Xe(t,1),[])}),Uf=Nr||function(){return xt.Date.now()};function Bf(n,r,e){return r=e?t:r,r=n&&null==r?n.length:r,Vi(n,m,t,t,t,t,r)}function $f(n,r){var e;if('function'!=typeof r)throw new ot(o);return n=Aa(n),function(){return--n>0&&(e=r.apply(this,arguments)),n<=1&&(r=t),e}}var Df=Du(function(n,t,r){var e=_;if(r.length){var u=wr(r,io(Df));e|=b}return Vi(n,e,t,r,u)}),Mf=Du(function(n,t,r){var e=3;if(r.length){var u=wr(r,io(Mf));e|=b}return Vi(t,e,n,r,u)});function Ff(n,r,e){var u,i,f,a,c,l,s=0,h=!1,p=!1,v=!0;if('function'!=typeof n)throw new ot(o);function _(r){var e=u,o=i;return u=i=t,s=r,a=n.apply(o,e)}function g(n){return s=n,c=Do(x,r),h?_(n):a}function d(n){var t=r-(n-l);return p?Qr(t,f-(n-s)):t}function y(n){var e=n-l;return l===t||e>=r||e<0||p&&n-s>=f}function x(){var n=Uf();if(y(n))return b(n);c=Do(x,d(n))}function b(n){return c=t,v&&u?_(n):(u=i=t,a)}function w(){var n=Uf(),e=y(n);if(u=arguments,i=this,l=n,e){if(c===t)return g(l);if(p)return si(c),c=Do(x,r),_(l)}return c===t&&(c=Do(x,r)),a}return r=za(r)||0,la(e)&&(h=!!e.leading,f=(p='maxWait'in e)?Yr(za(e.maxWait)||0,r):f,v='trailing'in e?!!e.trailing:v),w.cancel=function(){c!==t&&si(c),s=0,u=l=i=c=t},w.flush=function(){return c===t?a:b(Uf())},w}var Nf=Du(function(n,t){return qe(n,1,t)}),Pf=Du(function(n,t,r){return qe(n,za(t)||0,r)});function Zf(n,t){if('function'!=typeof n||null!=t&&'function'!=typeof t)throw new ot(o);var r=function r(){var e=arguments,u=t?t.apply(this,e):e[0],i=r.cache;if(i.has(u))return i.get(u);var o=n.apply(this,e);return r.cache=i.set(u,o)||i,o};return r.cache=new(Zf.Cache||ze),r}function qf(n){if('function'!=typeof n)throw new ot(o);return function(){var t=arguments;switch(t.length){case 0:return!n.call(this);case 1:return!n.call(this,t[0]);case 2:return!n.call(this,t[0],t[1]);case 3:return!n.call(this,t[0],t[1],t[2])}return!n.apply(this,t)}}Zf.Cache=ze;var Kf=ci(function(n,t){var r=(t=1==t.length&&na(t[0])?Dt(t[0],or(oo())):Dt(Xe(t,1),or(oo()))).length;return Du(function(e){for(var u=-1,i=Qr(e.length,r);++u=t}),Xf=_u((function(){return arguments})())?_u:function(n){return sa(n)&&yt.call(n,'callee')&&!Tr.call(n,'callee')},na=Dn.isArray,ta=kt?or(kt):function(n){return sa(n)&&fu(n)==fn};function ra(n){return null!=n&&ca(n.length)&&!fa(n)}function ea(n){return sa(n)&&ra(n)}var ua=Vr||zc,ia=zt?or(zt):function(n){return sa(n)&&fu(n)==P};function oa(n){if(!sa(n))return!1;var t=fu(n);return t==q||t==Z||'string'==typeof n.message&&'string'==typeof n.name&&!va(n)}function fa(n){if(!la(n))return!1;var t=fu(n);return t==K||t==V||t==F||t==Q}function aa(n){return'number'==typeof n&&n==Aa(n)}function ca(n){return'number'==typeof n&&n>-1&&n%1==0&&n<=L}function la(n){var t=typeof n;return null!=n&&('object'==t||'function'==t)}function sa(n){return null!=n&&'object'==typeof n}var ha=Ot?or(Ot):function(n){return sa(n)&&po(n)==G};function pa(n){return'number'==typeof n||sa(n)&&fu(n)==H}function va(n){if(!sa(n)||fu(n)!=Y)return!1;var t=Wr(n);if(null===t)return!0;var r=yt.call(t,'constructor')&&t.constructor;return'function'==typeof r&&r instanceof r&&dt.call(r)==At}var _a=It?or(It):function(n){return sa(n)&&fu(n)==X};var ga=Rt?or(Rt):function(n){return sa(n)&&po(n)==nn};function da(n){return'string'==typeof n||!na(n)&&sa(n)&&fu(n)==tn}function ya(n){return'symbol'==typeof n||sa(n)&&fu(n)==rn}var xa=Et?or(Et):function(n){return sa(n)&&ca(n.length)&&!!ht[fu(n)]};var ba=Ni(ju),wa=Ni(function(n,t){return n<=t});function ma(n){if(!n)return[];if(ra(n))return da(n)?Or(n):bi(n);if($r&&n[$r])return yr(n[$r]());var t=po(n);return(t==G?xr:t==nn?mr:Ja)(n)}function ja(n){return n?(n=za(n))===S||n===-1/0?(n<0?-1:1)*W:n==n?n:0:0===n?n:0}function Aa(n){var t=ja(n),r=t%1;return t==t?r?t-r:t:0}function ka(n){return n?Fe(Aa(n),0,T):0}function za(n){if('number'==typeof n)return n;if(ya(n))return C;if(la(n)){var t='function'==typeof n.valueOf?n.valueOf():n;n=la(t)?t+'':t}if('string'!=typeof n)return 0===n?n:+n;n=n.replace(Wn,'');var r=Zn.test(n);return r||Kn.test(n)?gt(n.slice(2),r?2:8):Pn.test(n)?C:+n}function Oa(n){return wi(n,Na(n))}function Ia(n){return null==n?'':Qu(n)}var Ra=ki(function(n,t){if(Io(t)||ra(t))wi(t,Fa(t),n);else for(var r in t)yt.call(t,r)&&Ce(n,r,t[r])}),Ea=ki(function(n,t){wi(t,Na(t),n)}),Sa=ki(function(n,t,r,e){wi(t,Na(t),n,e)}),La=ki(function(n,t,r,e){wi(t,Fa(t),n,e)}),Wa=no(Me);var Ca=Du(function(n,r){n=tt(n);var e=-1,u=r.length,i=u>2?r[2]:t;for(i&&Ao(r[0],r[1],i)&&(u=1);++e1),t}),wi(n,ro(n),r),e&&(r=Ne(r,7,Ji));for(var u=t.length;u--;)ni(r,t[u]);return r});var Ka=no(function(n,t){return null==n?{}:Su(n,t)});function Va(n,t){if(null==n)return{};var r=Dt(ro(n),function(n){return[n]});return t=oo(t),Lu(n,r,function(n,r){return t(n,r[0])})}var Ga=Ki(Fa),Ha=Ki(Na);function Ja(n){return null==n?[]:fr(n,Fa(n))}var Ya=Ei(function(n,t,r){return t=t.toLowerCase(),n+(r?Qa(t):t)});function Qa(n){return oc(Ia(n).toLowerCase())}function Xa(n){return(n=Ia(n))&&n.replace(Gn,hr).replace(it,'')}var nc=Ei(function(n,t,r){return n+(r?'-':'')+t.toLowerCase()}),tc=Ei(function(n,t,r){return n+(r?' ':'')+t.toLowerCase()}),rc=Ri('toLowerCase');var ec=Ei(function(n,t,r){return n+(r?'_':'')+t.toLowerCase()});var uc=Ei(function(n,t,r){return n+(r?' ':'')+oc(t)});var ic=Ei(function(n,t,r){return n+(r?' ':'')+t.toUpperCase()}),oc=Ri('toUpperCase');function fc(n,r,e){return n=Ia(n),(r=e?t:r)===t?dr(n)?Sr(n):Kt(n):n.match(r)||[]}var ac=Du(function(n,r){try{return St(n,t,r)}catch(n){return oa(n)?n:new Qn(n)}}),cc=no(function(n,t){return Wt(t,function(t){t=qo(t),De(n,t,Df(n[t],n))}),n});function lc(n){return function(){return n}}var sc=Ci(),hc=Ci(!0);function pc(n){return n}function vc(n){return bu('function'==typeof n?n:Ne(n,l))}var _c=Du(function(n,t){return function(r){return vu(r,n,t)}}),gc=Du(function(n,t){return function(r){return vu(n,r,t)}});function dc(n,t,r){var e=Fa(t),u=uu(t,e);null!=r||la(t)&&(u.length||!e.length)||(r=t,t=n,n=this,u=uu(t,Fa(t)));var i=!(la(r)&&'chain'in r&&!r.chain),o=fa(n);return Wt(u,function(r){var e=t[r];n[r]=e,o&&(n.prototype[r]=function(){var t=this.__chain__;if(i||t){var r=n(this.__wrapped__);return(r.__actions__=bi(this.__actions__)).push({func:e,args:arguments,thisArg:n}),r.__chain__=t,r}return e.apply(n,Mt([this.value()],arguments))})}),n}function yc(){}var xc=$i(Dt),bc=$i(Tt),wc=$i(Pt);function mc(n){return ko(n)?Xt(qo(n)):Wu(n)}var jc=Fi(),Ac=Fi(!0);function kc(){return[]}function zc(){return!1}var Oc=Bi(function(n,t){return n+t},0),Ic=Zi('ceil'),Rc=Bi(function(n,t){return n/t},1),Ec=Zi('floor');var Sc,Lc=Bi(function(n,t){return n*t},1),Wc=Zi('round'),Cc=Bi(function(n,t){return n-t},0);return xe.after=function(n,t){if('function'!=typeof t)throw new ot(o);return n=Aa(n),function(){if(--n<1)return t.apply(this,arguments)}},xe.ary=Bf,xe.assign=Ra,xe.assignIn=Ea,xe.assignInWith=Sa,xe.assignWith=La,xe.at=Wa,xe.before=$f,xe.bind=Df,xe.bindAll=cc,xe.bindKey=Mf,xe.castArray=function(){if(!arguments.length)return[];var n=arguments[0];return na(n)?n:[n]},xe.chain=mf,xe.chunk=function(n,r,e){r=(e?Ao(n,r,e):r===t)?1:Yr(Aa(r),0);var u=null==n?0:n.length;if(!u||r<1)return[];for(var i=0,o=0,f=Dn(Zr(u/r));i>>0)?(n=Ia(n))&&('string'==typeof r||null!=r&&!_a(r))&&!(r=Qu(r))&&gr(n)?li(Or(n),0,e):n.split(r,e):[]},xe.spread=function(n,t){if('function'!=typeof n)throw new ot(o);return t=null==t?0:Yr(Aa(t),0),Du(function(r){var e=r[t],u=li(r,0,t);return e&&Mt(u,e),St(n,this,u)})},xe.tail=function(n){var t=null==n?0:n.length;return t?Ku(n,1,t):[]},xe.take=function(n,r,e){return n&&n.length?Ku(n,0,(r=e||r===t?1:Aa(r))<0?0:r):[]},xe.takeRight=function(n,r,e){var u=null==n?0:n.length;return u?Ku(n,(r=u-(r=e||r===t?1:Aa(r)))<0?0:r,u):[]},xe.takeRightWhile=function(n,t){return n&&n.length?ri(n,oo(t,3),!1,!0):[]},xe.takeWhile=function(n,t){return n&&n.length?ri(n,oo(t,3)):[]},xe.tap=function(n,t){return t(n),n},xe.throttle=function(n,t,r){var e=!0,u=!0;if('function'!=typeof n)throw new ot(o);return la(r)&&(e='leading'in r?!!r.leading:e,u='trailing'in r?!!r.trailing:u),Ff(n,t,{leading:e,maxWait:t,trailing:u})},xe.thru=jf,xe.toArray=ma,xe.toPairs=Ga,xe.toPairsIn=Ha,xe.toPath=function(n){return na(n)?Dt(n,qo):ya(n)?[n]:bi(Zo(Ia(n)))},xe.toPlainObject=Oa,xe.transform=function(n,t,r){var e=na(n),u=e||ua(n)||xa(n);if(t=oo(t,4),null==r){var i=n&&n.constructor;r=u?e?new i:[]:la(n)&&fa(i)?be(Wr(n)):{}}return(u?Wt:ru)(n,function(n,e,u){return t(r,n,e,u)}),r},xe.unary=function(n){return Bf(n,1)},xe.union=sf,xe.unionBy=hf,xe.unionWith=pf,xe.uniq=function(n){return n&&n.length?Xu(n):[]},xe.uniqBy=function(n,t){return n&&n.length?Xu(n,oo(t,2)):[]},xe.uniqWith=function(n,r){return r='function'==typeof r?r:t,n&&n.length?Xu(n,t,r):[]},xe.unset=function(n,t){return null==n||ni(n,t)},xe.unzip=vf,xe.unzipWith=_f,xe.update=function(n,t,r){return null==n?n:ti(n,t,fi(r))},xe.updateWith=function(n,r,e,u){return u='function'==typeof u?u:t,null==n?n:ti(n,r,fi(e),u)},xe.values=Ja,xe.valuesIn=function(n){return null==n?[]:fr(n,Na(n))},xe.without=gf,xe.words=fc,xe.wrap=function(n,t){return Vf(fi(t),n)},xe.xor=df,xe.xorBy=yf,xe.xorWith=xf,xe.zip=bf,xe.zipObject=function(n,t){return ii(n||[],t||[],Ce)},xe.zipObjectDeep=function(n,t){return ii(n||[],t||[],Nu)},xe.zipWith=wf,xe.entries=Ga,xe.entriesIn=Ha,xe.extend=Ea,xe.extendWith=Sa,dc(xe,xe),xe.add=Oc,xe.attempt=ac,xe.camelCase=Ya,xe.capitalize=Qa,xe.ceil=Ic,xe.clamp=function(n,r,e){return e===t&&(e=r,r=t),e!==t&&(e=(e=za(e))==e?e:0),r!==t&&(r=(r=za(r))==r?r:0),Fe(za(n),r,e)},xe.clone=function(n){return Ne(n,h)},xe.cloneDeep=function(n){return Ne(n,5)},xe.cloneDeepWith=function(n,r){return Ne(n,5,r='function'==typeof r?r:t)},xe.cloneWith=function(n,r){return Ne(n,h,r='function'==typeof r?r:t)},xe.conformsTo=function(n,t){return null==t||Ze(n,t,Fa(t))},xe.deburr=Xa,xe.defaultTo=function(n,t){return null==n||n!=n?t:n},xe.divide=Rc,xe.endsWith=function(n,r,e){n=Ia(n),r=Qu(r);var u=n.length,i=e=e===t?u:Fe(Aa(e),0,u);return(e-=r.length)>=0&&n.slice(e,i)==r},xe.eq=Jf,xe.escape=function(n){return(n=Ia(n))&&An.test(n)?n.replace(mn,pr):n},xe.escapeRegExp=function(n){return(n=Ia(n))&&Ln.test(n)?n.replace(Sn,'\\$&'):n},xe.every=function(n,r,e){var u=na(n)?Tt:He;return e&&Ao(n,r,e)&&(r=t),u(n,oo(r,3))},xe.find=zf,xe.findIndex=Qo,xe.findKey=function(n,t){return Vt(n,oo(t,3),ru)},xe.findLast=Of,xe.findLastIndex=Xo,xe.findLastKey=function(n,t){return Vt(n,oo(t,3),eu)},xe.floor=Ec,xe.forEach=If,xe.forEachRight=Rf,xe.forIn=function(n,t){return null==n?n:nu(n,oo(t,3),Na)},xe.forInRight=function(n,t){return null==n?n:tu(n,oo(t,3),Na)},xe.forOwn=function(n,t){return n&&ru(n,oo(t,3))},xe.forOwnRight=function(n,t){return n&&eu(n,oo(t,3))},xe.get=Ua,xe.gt=Yf,xe.gte=Qf,xe.has=function(n,t){return null!=n&&go(n,t,cu)},xe.hasIn=Ba,xe.head=tf,xe.identity=pc,xe.includes=function(n,t,r,e){n=ra(n)?n:Ja(n),r=r&&!e?Aa(r):0;var u=n.length;return r<0&&(r=Yr(u+r,0)),da(n)?r<=u&&n.indexOf(t,r)>-1:!!u&&Ht(n,t,r)>-1},xe.indexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=null==r?0:Aa(r);return u<0&&(u=Yr(e+u,0)),Ht(n,t,u)},xe.inRange=function(n,r,e){return r=ja(r),e===t?(e=r,r=0):e=ja(e),su(n=za(n),r,e)},xe.invoke=Ma,xe.isArguments=Xf,xe.isArray=na,xe.isArrayBuffer=ta,xe.isArrayLike=ra,xe.isArrayLikeObject=ea,xe.isBoolean=function(n){return!0===n||!1===n||sa(n)&&fu(n)==N},xe.isBuffer=ua,xe.isDate=ia,xe.isElement=function(n){return sa(n)&&1===n.nodeType&&!va(n)},xe.isEmpty=function(n){if(null==n)return!0;if(ra(n)&&(na(n)||'string'==typeof n||'function'==typeof n.splice||ua(n)||xa(n)||Xf(n)))return!n.length;var t=po(n);if(t==G||t==nn)return!n.size;if(Io(n))return!wu(n).length;for(var r in n)if(yt.call(n,r))return!1;return!0},xe.isEqual=function(n,t){return gu(n,t)},xe.isEqualWith=function(n,r,e){var u=(e='function'==typeof e?e:t)?e(n,r):t;return u===t?gu(n,r,t,e):!!u},xe.isError=oa,xe.isFinite=function(n){return'number'==typeof n&&Gr(n)},xe.isFunction=fa,xe.isInteger=aa,xe.isLength=ca,xe.isMap=ha,xe.isMatch=function(n,t){return n===t||yu(n,t,ao(t))},xe.isMatchWith=function(n,r,e){return e='function'==typeof e?e:t,yu(n,r,ao(r),e)},xe.isNaN=function(n){return pa(n)&&n!=+n},xe.isNative=function(n){if(Oo(n))throw new Qn(e);return xu(n)},xe.isNil=function(n){return null==n},xe.isNull=function(n){return null===n},xe.isNumber=pa,xe.isObject=la,xe.isObjectLike=sa,xe.isPlainObject=va,xe.isRegExp=_a,xe.isSafeInteger=function(n){return aa(n)&&n>=-9007199254740991&&n<=L},xe.isSet=ga,xe.isString=da,xe.isSymbol=ya,xe.isTypedArray=xa,xe.isUndefined=function(n){return n===t},xe.isWeakMap=function(n){return sa(n)&&po(n)==un},xe.isWeakSet=function(n){return sa(n)&&fu(n)==on},xe.join=function(n,t){return null==n?'':Hr.call(n,t)},xe.kebabCase=nc,xe.last=of,xe.lastIndexOf=function(n,r,e){var u=null==n?0:n.length;if(!u)return-1;var i=u;return e!==t&&(i=(i=Aa(e))<0?Yr(u+i,0):Qr(i,u-1)),r==r?kr(n,r,i):Gt(n,Yt,i,!0)},xe.lowerCase=tc,xe.lowerFirst=rc,xe.lt=ba,xe.lte=wa,xe.max=function(n){return n&&n.length?Je(n,pc,au):t},xe.maxBy=function(n,r){return n&&n.length?Je(n,oo(r,2),au):t},xe.mean=function(n){return Qt(n,pc)},xe.meanBy=function(n,t){return Qt(n,oo(t,2))},xe.min=function(n){return n&&n.length?Je(n,pc,ju):t},xe.minBy=function(n,r){return n&&n.length?Je(n,oo(r,2),ju):t},xe.stubArray=kc,xe.stubFalse=zc,xe.stubObject=function(){return{}},xe.stubString=function(){return''},xe.stubTrue=function(){return!0},xe.multiply=Lc,xe.nth=function(n,r){return n&&n.length?Ru(n,Aa(r)):t},xe.noConflict=function(){return xt._===this&&(xt._=Zt),this},xe.noop=yc,xe.now=Uf,xe.pad=function(n,t,r){n=Ia(n);var e=(t=Aa(t))?zr(n):0;if(!t||e>=t)return n;var u=(t-e)/2;return Di(qr(u),r)+n+Di(Zr(u),r)},xe.padEnd=function(n,t,r){n=Ia(n);var e=(t=Aa(t))?zr(n):0;return t&&er){var u=n;n=r,r=u}if(e||n%1||r%1){var i=te();return Qr(n+i*(r-n+_t('1e-'+((i+'').length-1))),r)}return Uu(n,r)},xe.reduce=function(n,t,r){var e=na(n)?Ft:tr,u=arguments.length<3;return e(n,oo(t,4),r,u,Ve)},xe.reduceRight=function(n,t,r){var e=na(n)?Nt:tr,u=arguments.length<3;return e(n,oo(t,4),r,u,Ge)},xe.repeat=function(n,r,e){return r=(e?Ao(n,r,e):r===t)?1:Aa(r),$u(Ia(n),r)},xe.replace=function(){var n=arguments,t=Ia(n[0]);return n.length<3?t:t.replace(n[1],n[2])},xe.result=function(n,r,e){var u=-1,i=(r=ai(r,n)).length;for(i||(i=1,n=t);++uL)return[];var r=T,e=Qr(n,T);t=oo(t),n-=T;for(var u=ur(e,t);++r=o)return n;var a=e-zr(u);if(a<1)return u;var c=f?li(f,0,a).join(''):n.slice(0,a);if(i===t)return c+u;if(f&&(a+=c.length-a),_a(i)){if(n.slice(a).search(i)){var l,s=c;for(i.global||(i=rt(i.source,Ia(Nn.exec(i))+'g')),i.lastIndex=0;l=i.exec(s);)var h=l.index;c=c.slice(0,h===t?a:h)}}else if(n.indexOf(Qu(i),a)!=a){var p=c.lastIndexOf(i);p>-1&&(c=c.slice(0,p))}return c+u},xe.unescape=function(n){return(n=Ia(n))&&jn.test(n)?n.replace(wn,Ir):n},xe.uniqueId=function(n){var t=++bt;return Ia(n)+t},xe.upperCase=ic,xe.upperFirst=oc,xe.each=If,xe.eachRight=Rf,xe.first=tf,dc(xe,(Sc={},ru(xe,function(n,t){yt.call(xe.prototype,t)||(Sc[t]=n)}),Sc),{chain:!1}),xe.VERSION="4.17.13",Wt(['bind','bindKey','curry','curryRight','partial','partialRight'],function(n){xe[n].placeholder=xe}),Wt(['drop','take'],function(n,r){je.prototype[n]=function(e){e=e===t?1:Yr(Aa(e),0);var u=this.__filtered__&&!r?new je(this):this.clone();return u.__filtered__?u.__takeCount__=Qr(e,u.__takeCount__):u.__views__.push({size:Qr(e,T),type:n+(u.__dir__<0?'Right':'')}),u},je.prototype[n+'Right']=function(t){return this.reverse()[n](t).reverse()}}),Wt(['filter','map','takeWhile'],function(n,t){var r=t+1,e=r==R||3==r;je.prototype[n]=function(n){var t=this.clone();return t.__iteratees__.push({iteratee:oo(n,3),type:r}),t.__filtered__=t.__filtered__||e,t}}),Wt(['head','last'],function(n,t){var r='take'+(t?'Right':'');je.prototype[n]=function(){return this[r](1).value()[0]}}),Wt(['initial','tail'],function(n,t){var r='drop'+(t?'':'Right');je.prototype[n]=function(){return this.__filtered__?new je(this):this[r](1)}}),je.prototype.compact=function(){return this.filter(pc)},je.prototype.find=function(n){return this.filter(n).head()},je.prototype.findLast=function(n){return this.reverse().find(n)},je.prototype.invokeMap=Du(function(n,t){return'function'==typeof n?new je(this):this.map(function(r){return vu(r,n,t)})}),je.prototype.reject=function(n){return this.filter(qf(oo(n)))},je.prototype.slice=function(n,r){n=Aa(n);var e=this;return e.__filtered__&&(n>0||r<0)?new je(e):(n<0?e=e.takeRight(-n):n&&(e=e.drop(n)),r!==t&&(e=(r=Aa(r))<0?e.dropRight(-r):e.take(r-n)),e)},je.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},je.prototype.toArray=function(){return this.take(T)},ru(je.prototype,function(n,r){var e=/^(?:filter|find|map|reject)|While$/.test(r),u=/^(?:head|last)$/.test(r),i=xe[u?'take'+('last'==r?'Right':''):r],o=u||/^find/.test(r);i&&(xe.prototype[r]=function(){var r=this.__wrapped__,f=u?[1]:arguments,a=r instanceof je,c=f[0],l=a||na(r),s=function(n){var t=i.apply(xe,Mt([n],f));return u&&h?t[0]:t};l&&e&&'function'==typeof c&&1!=c.length&&(a=l=!1);var h=this.__chain__,p=!!this.__actions__.length,v=o&&!h,_=a&&!p;if(!o&&l){r=_?r:new je(this);var g=n.apply(r,f);return g.__actions__.push({func:jf,args:[s],thisArg:t}),new me(g,h)}return v&&_?n.apply(this,f):(g=this.thru(s),v?u?g.value()[0]:g.value():g)})}),Wt(['pop','push','shift','sort','splice','unshift'],function(n){var t=ft[n],r=/^(?:push|sort|unshift)$/.test(n)?'tap':'thru',e=/^(?:pop|shift)$/.test(n);xe.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){var u=this.value();return t.apply(na(u)?u:[],n)}return this[r](function(r){return t.apply(na(r)?r:[],n)})}}),ru(je.prototype,function(n,t){var r=xe[t];if(r){var e=r.name+'';yt.call(le,e)||(le[e]=[]),le[e].push({name:t,func:r})}}),le[Ti(t,g).name]=[{name:'wrapper',func:t}],je.prototype.clone=function(){var n=new je(this.__wrapped__);return n.__actions__=bi(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=bi(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=bi(this.__views__),n},je.prototype.reverse=function(){if(this.__filtered__){var n=new je(this);n.__dir__=-1,n.__filtered__=!0}else(n=this.clone()).__dir__*=-1;return n},je.prototype.value=function(){var n=this.__wrapped__.value(),t=this.__dir__,r=na(n),e=t<0,u=r?n.length:0,i=vo(0,u,this.__views__),o=i.start,f=i.end,a=f-o,c=e?f:o-1,l=this.__iteratees__,s=l.length,h=0,p=Qr(a,this.__takeCount__);if(!r||!e&&u==a&&p==a)return ei(n,this.__actions__);var v=[];n:for(;a--&&h=this.__values__.length;return{done:n,value:n?t:this.__values__[this.__index__++]}},xe.prototype.plant=function(n){for(var r,e=this;e instanceof we;){var u=Go(e);u.__index__=0,u.__values__=t,r?i.__wrapped__=u:r=u;var i=u;e=e.__wrapped__}return i.__wrapped__=n,r},xe.prototype.reverse=function(){var n=this.__wrapped__;if(n instanceof je){var r=n;return this.__actions__.length&&(r=new je(this)),(r=r.reverse()).__actions__.push({func:jf,args:[lf],thisArg:t}),new me(r,this.__chain__)}return this.thru(lf)},xe.prototype.toJSON=xe.prototype.valueOf=xe.prototype.value=function(){return ei(this.__wrapped__,this.__actions__)},xe.prototype.first=xe.prototype.head,$r&&(xe.prototype[$r]=function(){return this}),xe})();'function'==typeof define&&'object'==typeof define.amd&&define.amd?(xt._=Lr,define(function(){return Lr})):wt?((wt.exports=Lr)._=Lr,bt._=Lr):xt._=Lr}).call(this)},454,[]); -__d(function(g,r,i,a,m,e,d){var n=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var t=n(r(d[1])),o=r(d[2]),u=r(d[3]),f=o.NativeModules.LogBridge;function c(n){var t,o=n.stack;return'function'==typeof n.cause&&(t=n.cause())&&(o+="\nCaused by: "+c(t)),o}var s=['trace','debug','info','log','warn','error'].reduce(function(n,o){return n[o]=function(n){for(var s=arguments.length,v=new Array(s>1?s-1:0),l=1;l=l)return t;switch(t){case'%s':return String(c[u++]);case'%d':return Number(c[u++]);case'%j':try{return JSON.stringify(c[u++])}catch(t){return'[Circular]'}default:return t}}),f=c[u];u=3&&(o.depth=arguments[2]),arguments.length>=4&&(o.colors=arguments[3]),E(n)?o.showHidden=n:n&&e._extend(o,n),D(o.showHidden)&&(o.showHidden=!1),D(o.depth)&&(o.depth=2),D(o.colors)&&(o.colors=!1),D(o.customInspect)&&(o.customInspect=!0),o.colors&&(o.stylize=l),y(o,t,o.depth)}function l(t,n){var o=s.styles[n];return o?"\x1b["+s.colors[o][0]+'m'+t+"\x1b["+s.colors[o][1]+'m':t}function p(t,n){return t}function f(t){var n={};return t.forEach(function(t,o){n[t]=!0}),n}function y(t,n,o){if(t.customInspect&&n&&F(n.inspect)&&n.inspect!==e.inspect&&(!n.constructor||n.constructor.prototype!==n)){var u=n.inspect(o,t);return x(u)||(u=y(t,u,o)),u}var c=b(t,n);if(c)return c;var s=Object.keys(n),l=f(s);if(t.showHidden&&(s=Object.getOwnPropertyNames(n)),$(n)&&(s.indexOf('message')>=0||s.indexOf('description')>=0))return h(n);if(0===s.length){if(F(n)){var p=n.name?': '+n.name:'';return t.stylize('[Function'+p+']','special')}if(P(n))return t.stylize(RegExp.prototype.toString.call(n),'regexp');if(T(n))return t.stylize(Date.prototype.toString.call(n),'date');if($(n))return h(n)}var E,S='',z=!1,D=['{','}'];(w(n)&&(z=!0,D=['[',']']),F(n))&&(S=' [Function'+(n.name?': '+n.name:'')+']');return P(n)&&(S=' '+RegExp.prototype.toString.call(n)),T(n)&&(S=' '+Date.prototype.toUTCString.call(n)),$(n)&&(S=' '+h(n)),0!==s.length||z&&0!=n.length?o<0?P(n)?t.stylize(RegExp.prototype.toString.call(n),'regexp'):t.stylize('[Object]','special'):(t.seen.push(n),E=z?v(t,n,o,l,s):s.map(function(u){return O(t,n,o,l,u,z)}),t.seen.pop(),j(E,S,D)):D[0]+S+D[1]}function b(t,n){if(D(n))return t.stylize('undefined','undefined');if(x(n)){var o='\''+JSON.stringify(n).replace(/^"|"$/g,'').replace(/'/g,"\\'").replace(/\\"/g,'"')+'\'';return t.stylize(o,'string')}return z(n)?t.stylize(''+n,'number'):E(n)?t.stylize(''+n,'boolean'):S(n)?t.stylize('null','null'):void 0}function h(t){return'['+Error.prototype.toString.call(t)+']'}function v(t,n,o,u,c){for(var s=[],l=0,p=n.length;l-1&&(p=s?p.split('\n').map(function(t){return' '+t}).join('\n').substr(2):'\n'+p.split('\n').map(function(t){return' '+t}).join('\n')):p=t.stylize('[Circular]','special')),D(l)){if(s&&c.match(/^\d+$/))return p;(l=JSON.stringify(''+c)).match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(l=l.substr(1,l.length-2),l=t.stylize(l,'name')):(l=l.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),l=t.stylize(l,'string'))}return l+': '+p}function j(t,n,o){return t.reduce(function(t,n){return 0,n.indexOf('\n')>=0&&0,t+n.replace(/\u001b\[\d\d?m/g,'').length+1},0)>60?o[0]+(''===n?'':n+'\n ')+' '+t.join(',\n ')+' '+o[1]:o[0]+n+' '+t.join(', ')+' '+o[1]}function w(t){return Array.isArray(t)}function E(t){return'boolean'==typeof t}function S(t){return null===t}function z(t){return'number'==typeof t}function x(t){return'string'==typeof t}function D(t){return void 0===t}function P(t){return N(t)&&'[object RegExp]'===_(t)}function N(t){return'object'==typeof t&&null!==t}function T(t){return N(t)&&'[object Date]'===_(t)}function $(t){return N(t)&&('[object Error]'===_(t)||t instanceof Error)}function F(t){return'function'==typeof t}function _(t){return Object.prototype.toString.call(t)}function k(t){return t<10?'0'+t.toString(10):t.toString(10)}e.debuglog=function(t){if(t=t.toUpperCase(),!o[t])if(u.test(t)){var n=process.pid;o[t]=function(){var o=e.format.apply(e,arguments);console.error('%s %d: %s',t,n,o)}}else o[t]=function(){};return o[t]},e.inspect=s,s.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},s.styles={special:'cyan',number:'yellow',boolean:'yellow',undefined:'grey',null:'bold',string:'green',date:'magenta',regexp:'red'},e.types=r(d[0]),e.isArray=w,e.isBoolean=E,e.isNull=S,e.isNullOrUndefined=function(t){return null==t},e.isNumber=z,e.isString=x,e.isSymbol=function(t){return'symbol'==typeof t},e.isUndefined=D,e.isRegExp=P,e.types.isRegExp=P,e.isObject=N,e.isDate=T,e.types.isDate=T,e.isError=$,e.types.isNativeError=$,e.isFunction=F,e.isPrimitive=function(t){return null===t||'boolean'==typeof t||'number'==typeof t||'string'==typeof t||'symbol'==typeof t||void 0===t},e.isBuffer=r(d[1]);var A=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];function R(t,n){return Object.prototype.hasOwnProperty.call(t,n)}e.log=function(){var t,n;console.log('%s - %s',(t=new Date,n=[k(t.getHours()),k(t.getMinutes()),k(t.getSeconds())].join(':'),[t.getDate(),A[t.getMonth()],n].join(' ')),e.format.apply(e,arguments))},e.inherits=r(d[2]),e._extend=function(t,n){if(!n||!N(n))return t;for(var o=Object.keys(n),u=o.length;u--;)t[o[u]]=n[o[u]];return t};var U='undefined'!=typeof Symbol?Symbol('util.promisify.custom'):void 0;function J(t,n){if(!t){var o=new Error('Promise was rejected with a falsy value');o.reason=t,t=o}return n(t)}e.promisify=function(n){if('function'!=typeof n)throw new TypeError('The "original" argument must be of type Function');if(U&&n[U]){var o;if('function'!=typeof(o=n[U]))throw new TypeError('The "util.promisify.custom" argument must be of type Function');return Object.defineProperty(o,U,{value:o,enumerable:!1,writable:!1,configurable:!0}),o}function o(){for(var t,o,u=new Promise(function(n,u){t=n,o=u}),c=[],s=0;s=0&&'[object Array]'!==o.call(t)&&'[object Function]'===o.call(t.callee)},l=(function(){return n(arguments)})();n.isLegacyArguments=c,m.exports=l?n:c},459,[]); -__d(function(g,r,i,a,m,e,d){'use strict';var t=Object.prototype.toString,o=Function.prototype.toString,n=/^\s*(?:function)?\*/,c='function'==typeof Symbol&&'symbol'==typeof("function"==typeof Symbol?Symbol.toStringTag:"@@toStringTag"),u=Object.getPrototypeOf,f=(function(){if(!c)return!1;try{return Function('return function*() {}')()}catch(t){}})(),y=f?u(f):{};m.exports=function(f){return'function'==typeof f&&(!!n.test(o.call(f))||(c?u(f)===y:'[object GeneratorFunction]'===t.call(f)))}},460,[]); -__d(function(g,r,i,a,m,e,d){'function'==typeof Object.create?m.exports=function(t,o){t.super_=o,t.prototype=Object.create(o.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}})}:m.exports=function(t,o){t.super_=o;var p=function(){};p.prototype=o.prototype,t.prototype=new p,t.prototype.constructor=t}},461,[]); -__d(function(g,r,i,a,m,e,d){var t=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.getBackendSafeRoomName=function(t){if(!t)return t;try{t=decodeURIComponent(t)}catch(t){}return t=(t=(0,s.normalizeNFKC)(t)).toLowerCase(),(t=encodeURIComponent(t)).toLowerCase()},e.getLocationContextRoot=v,e.parseStandardURIString=l,e.parseURIString=function(t){if('string'!=typeof t)return;var n=l(f(t));n.contextRoot=v(n);var o=n.pathname,s=o.lastIndexOf('/'),h=o.substring(s+1)||void 0;if(h){var c=u(h);c!==h&&(h=c,n.pathname=o.substring(0,s+1)+(h||''))}return n.room=h,n},e.safeDecodeURIComponent=function(t){try{return decodeURIComponent(t)}catch(t){}return t},e.toURLString=function(t){var n;switch(typeof t){case'object':t&&(n=t instanceof URL?t.href:x(t));break;case'string':n=String(t)}return n},e.urlObjectToString=x,e.addHashParamsToURL=function(t){var s=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},h=(0,o.parseURLParams)(t),c=p((0,n.default)({},h,s));c.length&&(t.hash="#"+c.join('&'));return t},e.URI_PROTOCOL_PATTERN=e.APP_LINK_SCHEME=void 0;var n=t(r(d[1])),o=r(d[2]),s=r(d[3]);e.APP_LINK_SCHEME='org.jitsi.meet:';var h='[\\:\\?#\\[\\]@!$&\'()*+,;=>0&&void 0!==arguments[0]?arguments[0]:{},n=[];for(var o in t)try{n.push(o+"="+encodeURIComponent(JSON.stringify(t[o])))}catch(t){console.warn("Error encoding "+o+": "+t)}return n}function l(t){var n,o,s,h={toString:R};if(t=t.replace(/\s/g,''),(o=(n=new RegExp(c,'gi')).exec(t))&&(h.protocol=o[1].toLowerCase(),t=t.substring(n.lastIndex)),o=(n=new RegExp("^(//[^/?#]+)",'gi')).exec(t)){var u=o[1].substring(2);t=t.substring(n.lastIndex);var f=u.indexOf('@');-1!==f&&(u=u.substring(f+1)),h.host=u;var v=u.lastIndexOf(':');-1!==v&&(h.port=u.substring(v+1),u=u.substring(0,v)),h.hostname=u}if((o=(n=new RegExp("^([^?#]*)",'gi')).exec(t))&&(s=o[1],t=t.substring(n.lastIndex)),s?s.startsWith('/')||(s="/"+s):s='/',h.pathname=s,t.startsWith('?')){var p=t.indexOf('#',1);-1===p&&(p=t.length),h.search=t.substring(0,p),t=t.substring(p)}else h.search='';return h.hash=t.startsWith('#')?t:'',h}function R(t){var n=t||this,o=n.hash,s=n.host,h=n.pathname,c=n.protocol,u=n.search,f='';return c&&(f+=c),s&&(f+="//"+s),f+=h||'/',u&&(f+=u),o&&(f+=o),f}function x(t){var n=l(f(t.serverURL&&t.room?new URL(t.room,t.serverURL).toString():t.room?t.room:t.url||''));if(!n.protocol){var o=t.protocol||t.scheme;o&&(o.endsWith(':')||(o+=':'),n.protocol=o)}var s=n.pathname;if(!n.host){var h=t.domain||t.host||t.hostname;if(h){var c=l(f("org.jitsi.meet://"+h)),u=c.host,v=c.hostname,R=c.pathname,x=c.port;u&&(n.host=u,n.hostname=v,n.port=x),'/'===s&&'/'!==R&&(s=R)}}var I=t.roomName||t.room;!I||!n.pathname.endsWith('/')&&n.pathname.endsWith("/"+I)||(s.endsWith('/')||(s+='/'),s+=I),n.pathname=s;var O=t.jwt;if(O){var b=n.search;-1===b.indexOf('?jwt=')&&-1===b.indexOf('&jwt=')&&(b.startsWith('?')||(b="?"+b),1===b.length||(b+='&'),b+="jwt="+O,n.search=b)}for(var w=n.hash,C=['config','interfaceConfig','devices','userInfo'],L=0;L1&&void 0!==arguments[1]&&arguments[1],o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:'hash',h='search'===o?n.search:n.hash,l={},v=h&&h.substr(1).split('&')||[];if('hash'===o&&1===v.length){var c=v[0];if(c.startsWith('/')&&1===c.split('&').length)return l}return v.forEach(function(n){var o=n.split('='),h=o[0];if(h){var v;try{if(v=o[1],!s){var c=decodeURIComponent(v).replace(/\\&/,'&');v='undefined'===c?void 0:JSON.parse(c)}}catch(n){return void(0,t.reportError)(n,"Failed to parse URL parameter value: "+String(v))}l[h]=v}}),l};var t=r(d[0])},463,[447]); -__d(function(g,r,i,a,m,e,d){var n=r(d[0]);Object.defineProperty(e,"__esModule",{value:!0}),e.normalizeNFKC=function(n){return o.nfkc(n)};var o=n(r(d[1]))},464,[2,465]); -__d(function(g,r,i,a,m,e,d){!(function(t){"use strict";for(var n=[null,0,{}],o=10,s=44032,u=4352,f=4449,h=4519,c=21,l=28,p=588,C=function(t,n){this.codepoint=t,this.feature=n},v={},w=[],B=0;B<=255;++B)w[B]=0;var y=[function(t,o,s){return o<60||13311>8&255]>o&&(v[n]=u),u},function(t,n,o){return o?t(n,o):new C(n,null)},function(t,n,o){var v;if(n=55296&&t<=56319},C.isLowSurrogate=function(t){return t>=56320&&t<=57343},C.prototype.prepFeature=function(){this.feature||(this.feature=C.fromCharCode(this.codepoint,!0).feature)},C.prototype.toString=function(){if(this.codepoint<65536)return String.fromCharCode(this.codepoint);var t=this.codepoint-65536;return String.fromCharCode(Math.floor(t/1024)+55296,t%1024+56320)},C.prototype.getDecomp=function(){return this.prepFeature(),this.feature[0]||null},C.prototype.isCompatibility=function(){return this.prepFeature(),!!this.feature[1]&&256&this.feature[1]},C.prototype.isExclude=function(){return this.prepFeature(),!!this.feature[1]&&512&this.feature[1]},C.prototype.getCanonicalClass=function(){return this.prepFeature(),this.feature[1]?255&this.feature[1]:0},C.prototype.getComposite=function(t){if(this.prepFeature(),!this.feature[2])return null;var n=this.feature[2][t.codepoint];return n?C.fromCharCode(n):null};var F=function(t){this.str=t,this.cursor=0};F.prototype.next=function(){if(this.str&&this.cursor0;--o){if(this.resBuf[o-1].getCanonicalClass()<=t)break}this.resBuf.splice(o,0,n)}while(0!==t);return this.resBuf.shift()};var S=function(t){this.it=t,this.procBuf=[],this.resBuf=[],this.lastClass=null};S.prototype.next=function(){for(;0===this.resBuf.length;){var t=this.it.next();if(!t){this.resBuf=this.procBuf,this.procBuf=[];break}if(0===this.procBuf.length)this.lastClass=t.getCanonicalClass(),this.procBuf.push(t);else{var n=this.procBuf[0].getComposite(t),o=t.getCanonicalClass();n&&(this.lastClass>16)+(t>>16)+(n>>16)<<16|65535&n},o=function(e){if("string"!=typeof e)throw new Error("str2binl was passed a non-string");for(var t=[],n=0;n<8*e.length;n+=8)t[n>>5]|=(255&e.charCodeAt(n/8))<>>32-c,n);var s,c},s=function(e,t,n,r,i,o,s){return a(t&n|~t&r,e,t,i,o,s)},c=function(e,t,n,r,i,o,s){return a(t&r|n&~r,e,t,i,o,s)},u=function(e,t,n,r,i,o,s){return a(t^n^r,e,t,i,o,s)},d=function(e,t,n,r,i,o,s){return a(n^(t|~r),e,t,i,o,s)},l=function(e,t){e[t>>5]|=128<>>9<<4)]=t;for(var n,r,o,a,l=1732584193,h=-271733879,p=-1732584194,f=271733878,m=0;m>2]>>n%4*8+4&15)+"0123456789abcdef".charAt(e[n>>2]>>n%4*8&15);return t})(l(o(e),8*e.length))},hash:function(e){return(function(e){for(var t="",n=0;n<32*e.length;n+=8)t+=String.fromCharCode(e[n>>5]>>>n%32&255);return t})(l(o(e),8*e.length))}};function p(e,t){e[t>>5]|=128<<24-t%32,e[15+(t+64>>9<<4)]=t;var n,r,i,o,a,s,c,u,d=new Array(80),l=1732584193,h=-271733879,p=-1732584194,v=271733878,_=-1009589776;for(n=0;n16&&(n=p(n,8*e.length));for(var r=new Array(16),i=new Array(16),o=0;o<16;o++)r[o]=909522486^n[o],i[o]=1549556828^n[o];var a=p(r.concat(_(t)),512+8*t.length);return p(i.concat(a),672)}function g(e,t){var n=(65535&e)+(65535&t);return(e>>16)+(t>>16)+(n>>16)<<16|65535&n}function y(e,t){return e<>>32-t}function _(e){for(var t=[],n=0;n<8*e.length;n+=8)t[n>>5]|=(255&e.charCodeAt(n/8))<<24-n%32;return t}function S(e){for(var t,n,r="",i=0;i<4*e.length;i+=3)for(t=(e[i>>2]>>8*(3-i%4)&255)<<16|(e[i+1>>2]>>8*(3-(i+1)%4)&255)<<8|e[i+2>>2]>>8*(3-(i+2)%4)&255,n=0;n<4;n++)8*i+6*n>32*e.length?r+="=":r+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(t>>6*(3-n)&63);return r}function E(e){for(var t="",n=0;n<32*e.length;n+=8)t+=String.fromCharCode(e[n>>5]>>>24-n%32&255);return t}var b={b64_hmac_sha1:function(e,t){return S(v(e,t))},b64_sha1:function(e){return S(p(_(e),8*e.length))},binb2str:E,core_hmac_sha1:v,str_hmac_sha1:function(e,t){return E(v(e,t))},str_sha1:function(e){return E(p(_(e),8*e.length))}},C=function(e){var t,n,r="",i=e.length;for(t=0;t=0&&n<=127?r+=e.charAt(t):n>2047?(r+=String.fromCharCode(224|n>>12&15),r+=String.fromCharCode(128|n>>6&63),r+=String.fromCharCode(128|n>>0&63)):(r+=String.fromCharCode(192|n>>6&31),r+=String.fromCharCode(128|n>>0&63));return r},T=function(e){for(var t in e=e||{})if(Object.prototype.hasOwnProperty.call(e,t)){var r="",i="",o="",a=e[t],s="object"===n(a),c=escape(unescape(s?a.value:a));s&&(r=a.expires?";expires="+a.expires:"",i=a.domain?";domain="+a.domain:"",o=a.path?";path="+a.path:""),document.cookie=t+"="+c+r+i+o}};function A(e,t){return new w.Builder(e,t)}function R(e){return new w.Builder("iq",e)}function k(e){return new w.Builder("presence",e)}var w={VERSION:"@VERSION@",NS:{HTTPBIND:"http://jabber.org/protocol/httpbind",BOSH:"urn:xmpp:xbosh",CLIENT:"jabber:client",AUTH:"jabber:iq:auth",ROSTER:"jabber:iq:roster",PROFILE:"jabber:iq:profile",DISCO_INFO:"http://jabber.org/protocol/disco#info",DISCO_ITEMS:"http://jabber.org/protocol/disco#items",MUC:"http://jabber.org/protocol/muc",SASL:"urn:ietf:params:xml:ns:xmpp-sasl",STREAM:"http://etherx.jabber.org/streams",FRAMING:"urn:ietf:params:xml:ns:xmpp-framing",BIND:"urn:ietf:params:xml:ns:xmpp-bind",SESSION:"urn:ietf:params:xml:ns:xmpp-session",VERSION:"jabber:iq:version",STANZAS:"urn:ietf:params:xml:ns:xmpp-stanzas",XHTML_IM:"http://jabber.org/protocol/xhtml-im",XHTML:"http://www.w3.org/1999/xhtml"},XHTML:{tags:["a","blockquote","br","cite","em","img","li","ol","p","span","strong","ul","body"],attributes:{a:["href"],blockquote:["style"],br:[],cite:["style"],em:[],img:["src","alt","style","height","width"],li:["style"],ol:["style"],p:["style"],span:["style"],strong:[],ul:["style"],body:[]},css:["background-color","color","font-family","font-size","font-style","font-weight","margin-left","margin-right","text-align","text-decoration"],validTag:function(e){for(var t=0;t0)for(var n=0;n/g,">")).replace(/'/g,"'")).replace(/"/g,""")},xmlunescape:function(e){return(e=(e=(e=(e=e.replace(/\&/g,"&")).replace(/</g,"<")).replace(/>/g,">")).replace(/'/g,"'")).replace(/"/g,'"')},xmlTextNode:function(e){return w.xmlGenerator().createTextNode(e)},xmlHtmlNode:function(e){var t;return DOMParser?t=(new DOMParser).parseFromString(e,"text/xml"):((t=new ActiveXObject("Microsoft.XMLDOM")).async="false",t.loadXML(e)),t},getText:function(e){if(!e)return null;var t="";0===e.childNodes.length&&e.nodeType===w.ElementType.TEXT&&(t+=e.nodeValue);for(var n=0;n0&&(a=s.join("; "),t.setAttribute(o,a))}else t.setAttribute(o,a)}for(var p=0;p/g,"\\3e").replace(/@/g,"\\40")},unescapeNode:function(e){return"string"!=typeof e?e:e.replace(/\\20/g," ").replace(/\\22/g,'"').replace(/\\26/g,"&").replace(/\\27/g,"'").replace(/\\2f/g,"/").replace(/\\3a/g,":").replace(/\\3c/g,"<").replace(/\\3e/g,">").replace(/\\40/g,"@").replace(/\\5c/g,"\\")},getNodeFromJid:function(e){return e.indexOf("@")<0?null:e.split("@")[0]},getDomainFromJid:function(e){var t=w.getBareJidFromJid(e);if(t.indexOf("@")<0)return t;var n=t.split("@");return n.splice(0,1),n.join("@")},getResourceFromJid:function(e){if(!e)return null;var t=e.split("/");return t.length<2?null:(t.splice(0,1),t.join("/"))},getBareJidFromJid:function(e){return e?e.split("/")[0]:null},_handleError:function(e){void 0!==e.stack&&w.fatal(e.stack),e.sourceURL?w.fatal("error: "+this.handler+" "+e.sourceURL+":"+e.line+" - "+e.name+": "+e.message):e.fileName?w.fatal("error: "+this.handler+" "+e.fileName+":"+e.lineNumber+" - "+e.name+": "+e.message):w.fatal("error: "+e.message)},log:function(e,t){e===this.LogLevel.FATAL&&"object"===n(window.console)&&"function"==typeof window.console.error&&window.console.error(t)},debug:function(e){this.log(this.LogLevel.DEBUG,e)},info:function(e){this.log(this.LogLevel.INFO,e)},warn:function(e){this.log(this.LogLevel.WARN,e)},error:function(e){this.log(this.LogLevel.ERROR,e)},fatal:function(e){this.log(this.LogLevel.FATAL,e)},serialize:function(e){if(!e)return null;"function"==typeof e.tree&&(e=e.tree());var t=r(Array(e.attributes.length).keys()).map(function(t){return e.attributes[t].nodeName});t.sort();var n=t.reduce(function(t,n){return"".concat(t," ").concat(n,'="').concat(w.xmlescape(e.attributes.getNamedItem(n).value),'"')},"<".concat(e.nodeName));if(e.childNodes.length>0){n+=">";for(var i=0;i"}}n+=""}else n+="/>";return n},_requestId:0,_connectionPlugins:{},addConnectionPlugin:function(e,t){w._connectionPlugins[e]=t},Builder:function(e,t){"presence"!==e&&"message"!==e&&"iq"!==e||(t&&!t.xmlns?t.xmlns=w.NS.CLIENT:t||(t={xmlns:w.NS.CLIENT})),this.nodeTree=w.xmlElement(e,t),this.node=this.nodeTree}};w.Builder.prototype={tree:function(){return this.nodeTree},toString:function(){return w.serialize(this.nodeTree)},up:function(){return this.node=this.node.parentNode,this},root:function(){return this.node=this.nodeTree,this},attrs:function(e){for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&(void 0===e[t]?this.node.removeAttribute(t):this.node.setAttribute(t,e[t]));return this},c:function(e,t,n){var r=w.xmlElement(e,t,n);return this.node.appendChild(r),"string"!=typeof n&&"number"!=typeof n&&(this.node=r),this},cnode:function(e){var t,n=w.xmlGenerator();try{t=void 0!==n.importNode}catch(e){t=!1}var r=t?n.importNode(e,!0):w.copyElement(e);return this.node.appendChild(r),this.node=r,this},t:function(e){var t=w.xmlTextNode(e);return this.node.appendChild(t),this},h:function(e){var t=document.createElement("body");t.innerHTML=e;for(var n=w.createHtml(t);n.childNodes.length>0;)this.node.appendChild(n.childNodes[0]);return this}},w.Handler=function(e,t,n,r,i,o,a){this.handler=e,this.ns=t,this.name=n,this.type=r,this.id=i,this.options=a||{matchBareFromJid:!1,ignoreNamespaceFragment:!1},this.options.matchBare&&(w.warn('The "matchBare" option is deprecated, use "matchBareFromJid" instead.'),this.options.matchBareFromJid=this.options.matchBare,delete this.options.matchBare),this.options.matchBareFromJid?this.from=o?w.getBareJidFromJid(o):null:this.from=o,this.user=!0},w.Handler.prototype={getNamespace:function(e){var t=e.getAttribute("xmlns");return t&&this.options.ignoreNamespaceFragment&&(t=t.split("#")[0]),t},namespaceMatch:function(e){var t=this,n=!1;return!this.ns||(w.forEachChild(e,null,function(e){t.getNamespace(e)===t.ns&&(n=!0)}),n||this.getNamespace(e)===this.ns)},isMatch:function(e){var t=e.getAttribute("from");this.options.matchBareFromJid&&(t=w.getBareJidFromJid(t));var n=e.getAttribute("type");return!(!this.namespaceMatch(e)||this.name&&!w.isTagEqual(e,this.name)||this.type&&(Array.isArray(this.type)?-1===this.type.indexOf(n):n!==this.type)||this.id&&e.getAttribute("id")!==this.id||this.from&&t!==this.from)},run:function(e){var t=null;try{t=this.handler(e)}catch(e){throw w._handleError(e),e}return t},toString:function(){return"{Handler: "+this.handler+"("+this.name+","+this.id+","+this.ns+")}"}},w.TimedHandler=function(e,t){this.period=e,this.handler=t,this.lastCalled=(new Date).getTime(),this.user=!0},w.TimedHandler.prototype={run:function(){return this.lastCalled=(new Date).getTime(),this.handler()},reset:function(){this.lastCalled=(new Date).getTime()},toString:function(){return"{TimedHandler: "+this.handler+"("+this.period+")}"}},w.Connection=function(e,t){var n=this;this.service=e,this.options=t||{};var r=this.options.protocol||"";for(var i in 0===e.indexOf("ws:")||0===e.indexOf("wss:")||0===r.indexOf("ws")?this._proto=new w.Websocket(this):this._proto=new w.Bosh(this),this.jid="",this.domain=null,this.features=null,this._sasl_data={},this.do_session=!1,this.do_bind=!1,this.timedHandlers=[],this.handlers=[],this.removeTimeds=[],this.removeHandlers=[],this.addTimeds=[],this.addHandlers=[],this.protocolErrorHandlers={HTTP:{},websocket:{}},this._idleTimeout=null,this._disconnectTimeout=null,this.authenticated=!1,this.connected=!1,this.disconnecting=!1,this.do_authentication=!0,this.paused=!1,this.restored=!1,this._data=[],this._uniqueId=0,this._sasl_success_handler=null,this._sasl_failure_handler=null,this._sasl_challenge_handler=null,this.maxRetries=5,this._idleTimeout=setTimeout(function(){return n._onIdle()},100),T(this.options.cookies),this.registerSASLMechanisms(this.options.mechanisms),w._connectionPlugins)if(Object.prototype.hasOwnProperty.call(w._connectionPlugins,i)){var o=function(){};o.prototype=w._connectionPlugins[i],this[i]=new o,this[i].init(this)}},w.Connection.prototype={reset:function(){this._proto._reset(),this.do_session=!1,this.do_bind=!1,this.timedHandlers=[],this.handlers=[],this.removeTimeds=[],this.removeHandlers=[],this.addTimeds=[],this.addHandlers=[],this.authenticated=!1,this.connected=!1,this.disconnecting=!1,this.restored=!1,this._data=[],this._requests=[],this._uniqueId=0},pause:function(){this.paused=!0},resume:function(){this.paused=!1},getUniqueId:function(e){var t="xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(e){var t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)});return"string"==typeof e||"number"==typeof e?t+":"+e:t+""},addProtocolErrorHandler:function(e,t,n){this.protocolErrorHandlers[e][t]=n},connect:function(e,t,n,r,i,o,a){this.jid=e,this.authzid=w.getBareJidFromJid(this.jid),this.authcid=a||w.getNodeFromJid(this.jid),this.pass=t,this.servtype="xmpp",this.connect_callback=n,this.disconnecting=!1,this.connected=!1,this.authenticated=!1,this.restored=!1,this.domain=w.getDomainFromJid(this.jid),this._changeConnectStatus(w.Status.CONNECTING,null),this._proto._connect(r,i,o)},attach:function(e,t,n,r,i,o,a){if(!(this._proto instanceof w.Bosh)){var s=new Error('The "attach" method can only be used with a BOSH connection.');throw s.name="StropheSessionError",s}this._proto._attach(e,t,n,r,i,o,a)},restore:function(e,t,n,r,i){if(!this._sessionCachingSupported()){var o=new Error('The "restore" method can only be used with a BOSH connection.');throw o.name="StropheSessionError",o}this._proto._restore(e,t,n,r,i)},_sessionCachingSupported:function(){if(this._proto instanceof w.Bosh){if(!JSON)return!1;try{sessionStorage.setItem("_strophe_","_strophe_"),sessionStorage.removeItem("_strophe_")}catch(e){return!1}return!0}return!1},xmlInput:function(e){},xmlOutput:function(e){},rawInput:function(e){},rawOutput:function(e){},nextValidRid:function(e){},send:function(e){if(null!==e){if("function"==typeof e.sort)for(var t=0;t=0&&this.addHandlers.splice(t,1)},registerSASLMechanisms:function(e){this.mechanisms={},(e=e||[w.SASLAnonymous,w.SASLExternal,w.SASLMD5,w.SASLOAuthBearer,w.SASLXOAuth2,w.SASLPlain,w.SASLSHA1]).forEach(this.registerSASLMechanism.bind(this))},registerSASLMechanism:function(e){this.mechanisms[e.prototype.name]=e},disconnect:function(e){if(this._changeConnectStatus(w.Status.DISCONNECTING,e),w.warn("Disconnect was called because: "+e),this.connected){var t=!1;this.disconnecting=!0,this.authenticated&&(t=k({xmlns:w.NS.CLIENT,type:"unavailable"})),this._disconnectTimeout=this._addSysTimedHandler(3e3,this._onDisconnectTimeout.bind(this)),this._proto._disconnect(t)}else w.warn("Disconnect was called before Strophe connected to the server"),this._proto._abortAllRequests(),this._doDisconnect()},_changeConnectStatus:function(e,t,n){for(var r in w._connectionPlugins)if(Object.prototype.hasOwnProperty.call(w._connectionPlugins,r)){var i=this[r];if(i.statusChanged)try{i.statusChanged(e,t)}catch(e){w.error("".concat(r," plugin caused an exception changing status: ").concat(e))}}if(this.connect_callback)try{this.connect_callback(e,t,n)}catch(e){w._handleError(e),w.error("User connection callback caused an exception: ".concat(e))}},_doDisconnect:function(e){"number"==typeof this._idleTimeout&&clearTimeout(this._idleTimeout),null!==this._disconnectTimeout&&(this.deleteTimedHandler(this._disconnectTimeout),this._disconnectTimeout=null),w.debug("_doDisconnect was called"),this._proto._doDisconnect(),this.authenticated=!1,this.disconnecting=!1,this.restored=!1,this.handlers=[],this.timedHandlers=[],this.removeTimeds=[],this.removeHandlers=[],this.addTimeds=[],this.addHandlers=[],this._changeConnectStatus(w.Status.DISCONNECTED,e),this.connected=!1},_dataRecv:function(e,t){var n=this;w.debug("_dataRecv called");var r=this._proto._reqToData(e);if(null!==r){for(this.xmlInput!==w.Connection.prototype.xmlInput&&(r.nodeName===this._proto.strip&&r.childNodes.length?this.xmlInput(r.childNodes[0]):this.xmlInput(r)),this.rawInput!==w.Connection.prototype.rawInput&&(t?this.rawInput(t):this.rawInput(w.serialize(r)));this.removeHandlers.length>0;){var i=this.removeHandlers.pop(),o=this.handlers.indexOf(i);o>=0&&this.handlers.splice(o,1)}for(;this.addHandlers.length>0;)this.handlers.push(this.addHandlers.pop());if(this.disconnecting&&this._proto._emptyQueue())this._doDisconnect();else{var a=r.getAttribute("type");if(null!==a&&"terminate"===a){if(this.disconnecting)return;var s=r.getAttribute("condition"),c=r.getElementsByTagName("conflict");return null!==s?("remote-stream-error"===s&&c.length>0&&(s="conflict"),this._changeConnectStatus(w.Status.CONNFAIL,s)):this._changeConnectStatus(w.Status.CONNFAIL,w.ErrorCondition.UNKOWN_REASON),void this._doDisconnect(s)}w.forEachChild(r,null,function(e){var t=n.handlers;n.handlers=[];for(var r=0;r0:r.getElementsByTagName("stream:features").length>0||r.getElementsByTagName("features").length>0){var i=[],o=r.getElementsByTagName("mechanism");if(o.length>0)for(var a=0;ae[n].prototype.priority&&(n=r);if(n!==t){var i=e[t];e[t]=e[n],e[n]=i}}return e},authenticate:function(e){this._attemptSASLAuth(e)||this._attemptLegacyAuth()},_attemptSASLAuth:function(e){e=this.sortMechanismsByPriority(e||[]);for(var t=!1,n=0;n0&&(t=w.ErrorCondition.CONFLICT),this._changeConnectStatus(w.Status.AUTHFAIL,t,e),!1;var n=e.getElementsByTagName("bind");if(!(n.length>0))return w.warn("Resource binding failed."),this._changeConnectStatus(w.Status.AUTHFAIL,null,e),!1;var r=n[0].getElementsByTagName("jid");r.length>0&&(this.jid=w.getText(r[0]),this.do_session?this._establishSession():(this.authenticated=!0,this._changeConnectStatus(w.Status.CONNECTED,null)))},_establishSession:function(){if(!this.do_session)throw new Error("Strophe.Connection.prototype._establishSession "+"called but apparently ".concat(w.NS.SESSION," wasn't advertised by the server"));this._addSysHandler(this._onSessionResultIQ.bind(this),null,null,null,"_session_auth_2"),this.send(R({type:"set",id:"_session_auth_2"}).c("session",{xmlns:w.NS.SESSION}).tree())},_onSessionResultIQ:function(e){if("result"===e.getAttribute("type"))this.authenticated=!0,this._changeConnectStatus(w.Status.CONNECTED,null);else if("error"===e.getAttribute("type"))return w.warn("Session creation failed."),this._changeConnectStatus(w.Status.AUTHFAIL,null,e),!1;return!1},_sasl_failure_cb:function(e){return this._sasl_success_handler&&(this.deleteHandler(this._sasl_success_handler),this._sasl_success_handler=null),this._sasl_challenge_handler&&(this.deleteHandler(this._sasl_challenge_handler),this._sasl_challenge_handler=null),this._sasl_mechanism&&this._sasl_mechanism.onFailure(),this._changeConnectStatus(w.Status.AUTHFAIL,null,e),!1},_auth2_cb:function(e){return"result"===e.getAttribute("type")?(this.authenticated=!0,this._changeConnectStatus(w.Status.CONNECTED,null)):"error"===e.getAttribute("type")&&(this._changeConnectStatus(w.Status.AUTHFAIL,null,e),this.disconnect("authentication failed")),!1},_addSysTimedHandler:function(e,t){var n=new w.TimedHandler(e,t);return n.user=!1,this.addTimeds.push(n),n},_addSysHandler:function(e,t,n,r,i){var o=new w.Handler(e,t,n,r,i);return o.user=!1,this.addHandlers.push(o),o},_onDisconnectTimeout:function(){return w.debug("_onDisconnectTimeout was called"),this._changeConnectStatus(w.Status.CONNTIMEOUT,null),this._proto._onDisconnectTimeout(),this._doDisconnect(),!1},_onIdle:function(){for(var e=this;this.addTimeds.length>0;)this.timedHandlers.push(this.addTimeds.pop());for(;this.removeTimeds.length>0;){var t=this.removeTimeds.pop(),n=this.timedHandlers.indexOf(t);n>=0&&this.timedHandlers.splice(n,1)}for(var r=(new Date).getTime(),i=[],o=0;o0&&(n="conflict"),this._conn._changeConnectStatus(P.Status.CONNFAIL,n)):this._conn._changeConnectStatus(P.Status.CONNFAIL,"unknown"),this._conn._doDisconnect(n),P.Status.CONNFAIL}this.sid||(this.sid=e.getAttribute("sid"));var i=e.getAttribute("requests");i&&(this.window=parseInt(i,10));var o=e.getAttribute("hold");o&&(this.hold=parseInt(o,10));var a=e.getAttribute("wait");a&&(this.wait=parseInt(a,10));var s=e.getAttribute("inactivity");s&&(this.inactivity=parseInt(s,10))},_disconnect:function(e){this._sendTerminate(e)},_doDisconnect:function(){this.sid=null,this.rid=Math.floor(4294967295*Math.random()),this._conn._sessionCachingSupported()&&window.sessionStorage.removeItem("strophe-bosh-session"),this._conn.nextValidRid(this.rid)},_emptyQueue:function(){return 0===this._requests.length},_callProtocolErrorHandlers:function(e){var t=this._getRequestStatus(e),n=this._conn.protocolErrorHandlers.HTTP[t];n&&n.call(this,t)},_hitError:function(e){this.errors++,P.warn("request errored, status: "+e+", number of errors: "+this.errors),this.errors>4&&this._conn._onDisconnectTimeout()},_no_auth_received:function(e){P.warn("Server did not yet offer a supported authentication mechanism. Sending a blank poll request."),e=e?e.bind(this._conn):this._conn._connect_cb.bind(this._conn);var t=this._buildBody();this._requests.push(new P.Request(t.tree(),this._onRequestStateChange.bind(this,e),t.tree().getAttribute("rid"))),this._throttledRequestHandler()},_onDisconnectTimeout:function(){this._abortAllRequests()},_abortAllRequests:function(){for(;this._requests.length>0;){var e=this._requests.pop();e.abort=!0,e.xhr.abort(),e.xhr.onreadystatechange=function(){}}},_onIdle:function(){var e=this._conn._data;if(this._conn.authenticated&&0===this._requests.length&&0===e.length&&!this._conn.disconnecting&&(P.debug("no requests during idle cycle, sending blank request"),e.push(null)),!this._conn.paused){if(this._requests.length<2&&e.length>0){for(var t=this._buildBody(),n=0;n0){var r=this._requests[0].age();null!==this._requests[0].dead&&this._requests[0].timeDead()>Math.floor(P.SECONDARY_TIMEOUT*this.wait)&&this._throttledRequestHandler(),r>Math.floor(P.TIMEOUT*this.wait)&&(P.warn("Request "+this._requests[0].id+" timed out, over "+Math.floor(P.TIMEOUT*this.wait)+" seconds since last activity"),this._throttledRequestHandler())}}},_getRequestStatus:function(e,t){var n;if(4===e.xhr.readyState)try{n=e.xhr.status}catch(e){P.error("Caught an error while retrieving a request's status, reqStatus: "+n)}return void 0===n&&(n="number"==typeof t?t:0),n},_onRequestStateChange:function(e,t){if(P.debug("request id "+t.id+"."+t.sends+" state changed to "+t.xhr.readyState),t.abort)t.abort=!1;else if(4===t.xhr.readyState){var n=this._getRequestStatus(t);if(this.lastResponseHeaders=t.xhr.getAllResponseHeaders(),this.disconnecting&&n>=400)return this._hitError(n),void this._callProtocolErrorHandlers(t);var r=n>0&&n<500,i=t.sends>this._conn.maxRetries;if((r||i)&&(this._removeRequest(t),P.debug("request id "+t.id+" should now be removed")),200===n){var o=this._requests[0]===t;(this._requests[1]===t||o&&this._requests.length>0&&this._requests[0].age()>Math.floor(P.SECONDARY_TIMEOUT*this.wait))&&this._restartRequest(0),this._conn.nextValidRid(Number(t.rid)+1),P.debug("request id "+t.id+"."+t.sends+" got 200"),e(t),this.errors=0}else 0===n||n>=400&&n<600||n>=12e3?(P.error("request id "+t.id+"."+t.sends+" error "+n+" happened"),this._hitError(n),this._callProtocolErrorHandlers(t),n>=400&&n<500&&(this._conn._changeConnectStatus(P.Status.DISCONNECTING,null),this._conn._doDisconnect())):P.error("request id "+t.id+"."+t.sends+" error "+n+" happened");r||i?i&&!this._conn.connected&&this._conn._changeConnectStatus(P.Status.CONNFAIL,"giving-up"):this._throttledRequestHandler()}},_processRequest:function(e){var t=this,n=this._requests[e],r=this._getRequestStatus(n,-1);if(n.sends>this._conn.maxRetries)this._conn._onDisconnectTimeout();else{var i=n.age(),o=!isNaN(i)&&i>Math.floor(P.TIMEOUT*this.wait),a=null!==n.dead&&n.timeDead()>Math.floor(P.SECONDARY_TIMEOUT*this.wait),s=4===n.xhr.readyState&&(r<1||r>=500);if((o||a||s)&&(a&&P.error("Request ".concat(this._requests[e].id," timed out (secondary), restarting")),n.abort=!0,n.xhr.abort(),n.xhr.onreadystatechange=function(){},this._requests[e]=new P.Request(n.xmlData,n.origFunc,n.rid,n.sends),n=this._requests[e]),0===n.xhr.readyState){P.debug("request id "+n.id+"."+n.sends+" posting");try{var c=this._conn.options.contentType||"text/xml; charset=utf-8";n.xhr.open("POST",this._conn.service,!this._conn.options.sync),void 0!==n.xhr.setRequestHeader&&n.xhr.setRequestHeader("Content-Type",c),this._conn.options.withCredentials&&(n.xhr.withCredentials=!0)}catch(e){return P.error("XHR open failed: "+e.toString()),this._conn.connected||this._conn._changeConnectStatus(P.Status.CONNFAIL,"bad-service"),void this._conn.disconnect()}var u=function(){if(n.date=new Date,t._conn.options.customHeaders){var e=t._conn.options.customHeaders;for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&n.xhr.setRequestHeader(r,e[r])}n.xhr.send(n.data)};if(n.sends>1){var d=1e3*Math.min(Math.floor(P.TIMEOUT*this.wait),Math.pow(n.sends,3));setTimeout(function(){u()},d)}else u();n.sends++,this._conn.xmlOutput!==P.Connection.prototype.xmlOutput&&(n.xmlData.nodeName===this.strip&&n.xmlData.childNodes.length?this._conn.xmlOutput(n.xmlData.childNodes[0]):this._conn.xmlOutput(n.xmlData)),this._conn.rawOutput!==P.Connection.prototype.rawOutput&&this._conn.rawOutput(n.data)}else P.debug("_processRequest: "+(0===e?"first":"second")+" request has readyState of "+n.xhr.readyState)}},_removeRequest:function(e){P.debug("removing request");for(var t=this._requests.length-1;t>=0;t--)e===this._requests[t]&&this._requests.splice(t,1);e.xhr.onreadystatechange=function(){},this._throttledRequestHandler()},_restartRequest:function(e){var t=this._requests[e];null===t.dead&&(t.dead=new Date),this._processRequest(e)},_reqToData:function(e){try{return e.getResponse()}catch(e){if("parsererror"!==e.message)throw e;this._conn.disconnect("strophe-parsererror")}},_sendTerminate:function(e){P.debug("_sendTerminate was called");var t=this._buildBody().attrs({type:"terminate"});e&&t.cnode(e.tree());var n=new P.Request(t.tree(),this._onRequestStateChange.bind(this,this._conn._dataRecv.bind(this._conn)),t.tree().getAttribute("rid"));this._requests.push(n),this._throttledRequestHandler()},_send:function(){var e=this;clearTimeout(this._conn._idleTimeout),this._throttledRequestHandler(),this._conn._idleTimeout=setTimeout(function(){return e._conn._onIdle()},100)},_sendRestart:function(){this._throttledRequestHandler(),clearTimeout(this._conn._idleTimeout)},_throttledRequestHandler:function(){this._requests?P.debug("_throttledRequestHandler called with "+this._requests.length+" requests"):P.debug("_throttledRequestHandler called with undefined requests"),this._requests&&0!==this._requests.length&&(this._requests.length>0&&this._processRequest(0),this._requests.length>1&&Math.abs(this._requests[0].rid-this._requests[1].rid): "+n);var r=e.getAttribute("version");return"string"!=typeof r?t="Missing version in ":"1.0"!==r&&(t="Wrong version in : "+r),!t||(this._conn._changeConnectStatus(O.Status.CONNFAIL,t),this._conn._doDisconnect(),!1)},_connect_cb_wrapper:function(e){if(0===e.data.indexOf("\s*)*/,"");if(""===t)return;var n=(new DOMParser).parseFromString(t,"text/xml").documentElement;this._conn.xmlInput(n),this._conn.rawInput(e.data),this._handleStreamStart(n)&&this._connect_cb(n)}else if(0===e.data.indexOf("=0&&i.indexOf("wss:")>=0||o.indexOf("ws:")>=0)&&(this._conn._changeConnectStatus(O.Status.REDIRECT,"Received see-other-uri, resetting connection"),this._conn.reset(),this._conn.service=i,this._connect())}else this._conn._changeConnectStatus(O.Status.CONNFAIL,"Received closing stream"),this._conn._doDisconnect()}else{var a=this._streamWrap(e.data),s=(new DOMParser).parseFromString(a,"text/xml").documentElement;this.socket.onmessage=this._onMessage.bind(this),this._conn._connect_cb(s,null,e.data)}},_disconnect:function(e){if(this.socket&&this.socket.readyState!==WebSocket.CLOSED){e&&this._conn.send(e);var t=N("close",{xmlns:O.NS.FRAMING});this._conn.xmlOutput(t.tree());var n=O.serialize(t);this._conn.rawOutput(n);try{this.socket.send(n)}catch(e){O.warn("Couldn't send tag.")}}this._conn._doDisconnect()},_doDisconnect:function(){O.debug("WebSockets _doDisconnect was called"),this._closeSocket()},_streamWrap:function(e){return""+e+""},_closeSocket:function(){if(this.socket)try{this.socket.onclose=null,this.socket.onerror=null,this.socket.onmessage=null,this.socket.close()}catch(e){O.debug(e.message)}this.socket=null},_emptyQueue:function(){return!0},_onClose:function(e){this._conn.connected&&!this._conn.disconnecting?(O.error("Websocket closed unexpectedly"),this._conn._doDisconnect()):e&&1006===e.code&&!this._conn.connected&&this.socket?(O.error("Websocket closed unexcectedly"),this._conn._changeConnectStatus(O.Status.CONNFAIL,"The WebSocket connection could not be established or was disconnected."),this._conn._doDisconnect()):O.debug("Websocket closed")},_no_auth_received:function(e){O.error("Server did not offer a supported authentication mechanism"),this._conn._changeConnectStatus(O.Status.CONNFAIL,O.ErrorCondition.NO_AUTH_MECH),e&&e.call(this._conn),this._conn._doDisconnect()},_onDisconnectTimeout:function(){},_abortAllRequests:function(){},_onError:function(e){O.error("Websocket error "+e),this._conn._changeConnectStatus(O.Status.CONNFAIL,"The WebSocket connection could not be established or was disconnected."),this._disconnect()},_onIdle:function(){var e=this._conn._data;if(e.length>0&&!this._conn.paused){for(var t=0;t=e.length)break;r=e[n++]}else{if((n=e.next()).done)break;r=n.value}var i=r;this.stopCallStats(i.tpc)}var o=this.rtpStatsMap.keys(),a=Array.isArray(o),s=0;for(o=a?o:o["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var c;if(a){if(s>=o.length)break;c=o[s++]}else{if((s=o.next()).done)break;c=s.value}var u=c;this._stopRemoteStats(u)}this.eventEmitter&&this.eventEmitter.removeAllListeners()}finally{_.instances.delete(this)}},_.stopLocalStats=function(e){if(_.audioLevelsEnabled)for(var t=0;t<_.localStats.length;t++)if(_.localStats[t].stream===e){_.localStats.splice(t,1)[0].stop();break}},_.prototype._stopRemoteStats=function(e){var t=this.rtpStatsMap.get(e);t&&(t.stop(),this.rtpStatsMap.delete(e))},_.prototype.stopRemoteStats=function(e){this._stopRemoteStats(e.id)},_.prototype.startCallStats=function(e,t){if(this.callStatsIntegrationEnabled)if(this.callsStatsInstances.has(e.id))v.error("CallStats instance for ${tpc} exists already");else{v.info("Starting CallStats for "+e+"...");var n=new c.a(e,{confID:this._getCallStatsConfID(),remoteUserID:t});this.callsStatsInstances.set(e.id,n)}},_._getAllCallStatsInstances=function(){var e=new Set,t=_.instances,n=Array.isArray(t),r=0;for(t=n?t:t["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var i;if(n){if(r>=t.length)break;i=t[r++]}else{if((r=t.next()).done)break;i=r.value}var o=i.callsStatsInstances.values(),a=Array.isArray(o),s=0;for(o=a?o:o["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var c;if(a){if(s>=o.length)break;c=o[s++]}else{if((s=o.next()).done)break;c=s.value}var u=c;e.add(u)}}return e},_.prototype._getCallStatsConfID=function(){return this.options.callStatsConfIDNamespace?this.options.callStatsConfIDNamespace+"/"+this.options.roomName:this.options.roomName},_.prototype.stopCallStats=function(e){var t=this.callsStatsInstances.get(e.id);t&&(1===this.callsStatsInstances.size&&this.eventEmitter.emit(m.b),this.callsStatsInstances.delete(e.id),t.sendTerminateEvent())},_.prototype.isCallstatsEnabled=function(){return this.callStatsIntegrationEnabled},_.prototype.sendConnectionResumeOrHoldEvent=function(e,t){var n=this.callsStatsInstances.get(e.id);n&&n.sendResumeOrHoldEvent(t)},_.prototype.sendIceConnectionFailedEvent=function(e){var t=this.callsStatsInstances.get(e.id);t&&t.sendIceConnectionFailedEvent()},_.prototype.sendMuteEvent=function(e,t,n){var r=e&&this.callsStatsInstances.get(e.id);c.a.sendMuteEvent(t,n,r)},_.prototype.sendScreenSharingEvent=function(e,t){var n=this.callsStatsInstances.values(),r=Array.isArray(n),i=0;for(n=r?n:n["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var o;if(r){if(i>=n.length)break;o=n[i++]}else{if((i=n.next()).done)break;o=i.value}o.sendScreenSharingEvent(e,t)}},_.prototype.sendDominantSpeakerEvent=function(e){var t=this.callsStatsInstances.values(),n=Array.isArray(t),r=0;for(t=n?t:t["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var i;if(n){if(r>=t.length)break;i=t[r++]}else{if((r=t.next()).done)break;i=r.value}i.sendDominantSpeakerEvent()}this.xmpp.sendDominantSpeakerEvent(e)},_.sendActiveDeviceListEvent=function(e){var t=_._getAllCallStatsInstances();if(t.size){var n=t,r=Array.isArray(n),i=0;for(n=r?n:n["function"==typeof Symbol&&"function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var o;if(r){if(i>=n.length)break;o=n[i++]}else{if((i=n.next()).done)break;o=i.value}var a=o;c.a.sendActiveDeviceListEvent(e,a)}}else c.a.sendActiveDeviceListEvent(e,null)},_.prototype.associateStreamWithVideoTag=function(e,t,n,r,i,o){var a=this.callsStatsInstances.get(e.id);a&&a.associateStreamWithVideoTag(t,n,r,i,o)},_.sendGetUserMediaFailed=function(e){var t=e instanceof f.a?(function(e){var t=new Error;return t.stack=e.stack,t.name=(e.name||"Unknown error")+(e.gum&&e.gum.error&&e.gum.error.name?" - "+e.gum.error.name:""),t.constraintName=e.gum&&e.gum.constraints?JSON.stringify(e.gum.constraints):"",t.message=e.message,t})(e):e,n=_._getAllCallStatsInstances();if(n.size){var r=n,i=Array.isArray(r),o=0;for(r=i?r:r["function"==typeof Symbol&&"function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var a;if(i){if(o>=r.length)break;a=r[o++]}else{if((o=r.next()).done)break;a=o.value}var s=a;c.a.sendGetUserMediaFailed(t,s)}}else c.a.sendGetUserMediaFailed(t,null)},_.prototype.sendCreateOfferFailed=function(e,t){var n=this.callsStatsInstances.get(t.id);n&&n.sendCreateOfferFailed(e)},_.prototype.sendCreateAnswerFailed=function(e,t){var n=this.callsStatsInstances.get(t.id);n&&n.sendCreateAnswerFailed(e)},_.prototype.sendSetLocalDescFailed=function(e,t){var n=this.callsStatsInstances.get(t.id);n&&n.sendSetLocalDescFailed(e)},_.prototype.sendSetRemoteDescFailed=function(e,t){var n=this.callsStatsInstances.get(t.id);n&&n.sendSetRemoteDescFailed(e)},_.prototype.sendAddIceCandidateFailed=function(e,t){var n=this.callsStatsInstances.get(t.id);n&&n.sendAddIceCandidateFailed(e)},_.sendLog=function(e){var t=new Set,n=_.instances,r=Array.isArray(n),i=0;for(n=r?n:n["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var o;if(r){if(i>=n.length)break;o=n[i++]}else{if((i=n.next()).done)break;o=i.value}var a=o;if(a.callStatsApplicationLogsDisabled)return;a.callsStatsInstances.size&&t.add(a.callsStatsInstances.values().next().value)}if(t.size){var s=t,u=Array.isArray(s),d=0;for(s=u?s:s["function"==typeof Symbol&&"function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var l;if(u){if(d>=s.length)break;l=s[d++]}else{if((d=s.next()).done)break;l=d.value}var h=l;c.a.sendApplicationLog(e,h)}}else c.a.sendApplicationLog(e,null)},_.prototype.sendFeedback=function(e,t){return _.analytics.sendEvent(a.n,{rating:e,comment:t}),c.a.sendFeedback(this._getCallStatsConfID(),e,t)},_.LOCAL_JID=n(139).LOCAL_JID,_.reportGlobalError=function(e){e instanceof f.a&&e.gum?_.sendGetUserMediaFailed(e):_.sendLog(e)},_.sendAnalyticsAndLog=function(e){var t,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};e?(t="object"==typeof e?e:{name:e,properties:n},v.log(JSON.stringify(t)),this.analytics.sendEvent(e,n)):v.warn("No event or event name given.")},_.sendAnalytics=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};this.analytics.sendEvent(e,t)}}).call(this,"modules/statistics/statistics.js")},function(e,t,n){"use strict";(function(e){var r=n(4),i=n(35),o=n.n(i),a=n(1),s=Object(r.getLogger)(e),c={filterSpecialChars:function(e){return e?e.replace(/[\\\/\{,\}\+]/g,""):e},iceparams:function(e,t){var n,r,i=null;return(r=c.findLine(e,"a=ice-ufrag:",t))&&(n=c.findLine(e,"a=ice-pwd:",t))&&(i={ufrag:c.parseICEUfrag(r),pwd:c.parseICEPwd(n)}),i},parseICEUfrag:function(e){return e.substring(12)},buildICEUfrag:function(e){return"a=ice-ufrag:"+e},parseICEPwd:function(e){return e.substring(10)},buildICEPwd:function(e){return"a=ice-pwd:"+e},parseMID:function(e){return e.substring(6)},parseMLine:function(e){var t={},n=e.substring(2).split(" ");return t.media=n.shift(),t.port=n.shift(),t.proto=n.shift(),""===n[n.length-1]&&n.pop(),t.fmt=n,t},buildMLine:function(e){return"m="+e.media+" "+e.port+" "+e.proto+" "+e.fmt.join(" ")},parseRTPMap:function(e){var t={},n=e.substring(9).split(" ");return t.id=n.shift(),n=n[0].split("/"),t.name=n.shift(),t.clockrate=n.shift(),t.channels=n.length?n.shift():"1",t},parseSCTPMap:function(e){var t=e.substring(10).split(" ");return[t[0],t[1],t.length>2?t[2]:null]},buildRTPMap:function(e){var t="a=rtpmap:"+e.getAttribute("id")+" "+e.getAttribute("name")+"/"+e.getAttribute("clockrate");return e.getAttribute("channels")&&"1"!==e.getAttribute("channels")&&(t+="/"+e.getAttribute("channels")),t},parseCrypto:function(e){var t={},n=e.substring(9).split(" ");return t.tag=n.shift(),t["crypto-suite"]=n.shift(),t["key-params"]=n.shift(),n.length&&(t["session-params"]=n.join(" ")),t},parseFingerprint:function(e){var t={},n=e.substring(14).split(" ");return t.hash=n.shift(),t.fingerprint=n.shift(),t},parseFmtp:function(e){var t=[],n=e.split(" ");n.shift(),n=n.join(" ").split(";");for(var r=0;r1&&0===n)){var r=null;if(1===t)r=e.ssrcs[0].id;else if(2===t){var i=e.ssrcGroups.find(function(e){return"FID"===e.semantics});i&&(r=i.ssrcs.split(" ")[0])}else if(t>=3){var o=e.ssrcGroups.find(function(e){return"SIM"===e.semantics});o&&(r=o.ssrcs.split(" ")[0])}return r}},generateSsrc:function(){return o.a.randomInt(1,4294967295)},getSsrcAttribute:function(e,t,n){for(var r=0;r0)return t[0].substr("a=ice-ufrag:".length)},preferVideoCodec:function(e,t){var n=null;if(e&&t){for(var r=0;r=r.length)break;a=r[o++]}else{if((o=r.next()).done)break;a=o.value}var s=a;s.codec&&s.codec.toLowerCase()===t.toLowerCase()&&n.push(s.payload)}if(n.length>0){var c=n.map(function(e){return"apt="+e}),u=e.fmtp.filter(function(e){return-1!==c.indexOf(e.config)});n.push.apply(n,_toConsumableArray(u.map(function(e){return e.payload})));var d=e.payloads.toString().split(" ").map(Number).filter(function(e){return-1===n.indexOf(e)});0===d.length?(e.port=0,e.direction="inactive",e.payloads="*"):e.payloads=d.join(" "),e.rtp=e.rtp.filter(function(e){return-1!==d.indexOf(e.payload)}),e.fmtp=e.fmtp.filter(function(e){return-1!==d.indexOf(e.payload)}),e.rtcpFb&&(e.rtcpFb=e.rtcpFb.filter(function(e){return-1!==d.indexOf(e.payload)}))}}}};t.a=c}).call(this,"modules/xmpp/SDPUtil.js")},function(e,t,n){"use strict";function r(e){for(var t=1;t1&&void 0!==arguments[1]?arguments[1]:{};return{type:o,source:"get.user.media",action:e,attributes:t}},L=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return{type:o,source:"peer.conn.status",action:"duration",attributes:e}},x=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return{type:o,action:e,source:"jingle",attributes:t}},F=function(e,t){return{attributes:{media_type:e,value:t},action:"track.no.data.from.source",type:o}},j=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return{type:o,action:e,source:"p2p",attributes:t}},U=function(){return{type:o,action:"remotely.muted"}},H=function(e){return{type:o,action:"rtp.stats",attributes:e}},J=function(e){return{type:o,action:"rtt.by.region",attributes:e}},B=function(e){return{type:o,action:"transport.stats",attributes:e}};function G(e,t,n){return{type:o,action:"audio.output.problem",attributes:{userID:e,localAudioLevels:t,remoteAudioLevels:n}}}var V=function(e,t){return{type:o,action:"bridge-channel.error",attributes:{code:e,reason:t}}},q=function(e){return D("ttfm",e)}},function(e,t){e.exports={CREATE_ANSWER_FAILED:"rtc.create_answer_failed",CREATE_OFFER_FAILED:"rtc.create_offer_failed",DATA_CHANNEL_OPEN:"rtc.data_channel_open",ENDPOINT_CONN_STATUS_CHANGED:"rtc.endpoint_conn_status_changed",DOMINANT_SPEAKER_CHANGED:"rtc.dominant_speaker_changed",LASTN_ENDPOINT_CHANGED:"rtc.lastn_endpoint_changed",GRANTED_PERMISSIONS:"rtc.granted_permissions",IS_SELECTED_CHANGED:"rtc.is_selected_change",LASTN_VALUE_CHANGED:"rtc.lastn_value_changed",LOCAL_TRACK_SSRC_UPDATED:"rtc.local_track_ssrc_updated",TRACK_ATTACHED:"rtc.track_attached",REMOTE_TRACK_ADDED:"rtc.remote_track_added",REMOTE_TRACK_MUTE:"rtc.remote_track_mute",REMOTE_TRACK_REMOVED:"rtc.remote_track_removed",REMOTE_TRACK_UNMUTE:"rtc.remote_track_unmute",SET_LOCAL_DESCRIPTION_FAILED:"rtc.set_local_description_failed",SET_REMOTE_DESCRIPTION_FAILED:"rtc.set_remote_description_failed",AUDIO_OUTPUT_DEVICE_CHANGED:"rtc.audio_output_device_changed",DEVICE_LIST_CHANGED:"rtc.device_list_changed",DEVICE_LIST_WILL_CHANGE:"rtc.device_list_will_change",DEVICE_LIST_AVAILABLE:"rtc.device_list_available",ENDPOINT_MESSAGE_RECEIVED:"rtc.endpoint_message_received",LOCAL_UFRAG_CHANGED:"rtc.local_ufrag_changed",REMOTE_UFRAG_CHANGED:"rtc.remote_ufrag_changed"}},function(e,t,n){"use strict";n.d(t,"a",function(){return r}),n.d(t,"b",function(){return i}),n.d(t,"c",function(){return o});var r="audio",i="presenter",o="video"},function(e,t,n){"use strict";(function(e){var r=n(7),i=n(41),o=n.n(i),a=n(20),s=n.n(a),c=n(4),u=n(11),d=n.n(u),l=n(17),h=n(24),p=n(9),f=n(31),m=n.n(f),v=n(1),g=n(8),y=n.n(g),_=n(42),S=n(6),E=n(5),b=n(13),C=n.n(b);function T(e){for(var t=1;t1&&void 0!==arguments[1]?arguments[1]:{},n={audio:!1,video:!1},r=v.a.isFirefox()||v.a.isSafari()||v.a.isReactNative();if(e.indexOf("video")>=0){if(n.video={mandatory:{},optional:[]},t.cameraDeviceId)r&&(n.video.deviceId=t.cameraDeviceId),n.video.mandatory.sourceId=t.cameraDeviceId;else{var i=t.facingMode||o.a.USER;r&&(n.video.facingMode=i),n.video.optional.push({facingMode:i})}(t.minFps||t.maxFps||t.fps)&&((t.minFps||t.fps)&&(t.minFps=t.minFps||t.fps,n.video.mandatory.minFrameRate=t.minFps),t.maxFps&&(n.video.mandatory.maxFrameRate=t.maxFps)),(function(e,t,n){m.a[n]&&(t&&(e.video.width={ideal:m.a[n].width},e.video.height={ideal:m.a[n].height}),e.video.mandatory.minWidth=m.a[n].width,e.video.mandatory.minHeight=m.a[n].height),e.video.mandatory.minWidth&&(e.video.mandatory.maxWidth=e.video.mandatory.minWidth),e.video.mandatory.minHeight&&(e.video.mandatory.maxHeight=e.video.mandatory.minHeight)})(n,r,t.resolution)}if(e.indexOf("audio")>=0&&(v.a.isReactNative()?n.audio=!0:v.a.isFirefox()?t.micDeviceId?n.audio={mandatory:{},deviceId:t.micDeviceId,optional:[{sourceId:t.micDeviceId}]}:n.audio=!0:(n.audio={mandatory:{},optional:[]},t.micDeviceId&&(r&&(n.audio.deviceId=t.micDeviceId),n.audio.optional.push({sourceId:t.micDeviceId})),n.audio.optional.push({echoCancellation:!x&&!L},{googEchoCancellation:!x&&!L},{googAutoGainControl:!j&&!L},{googNoiseSuppression:!F&&!L},{googHighpassFilter:!U&&!L},{googNoiseSuppression2:!F&&!L},{googEchoCancellation2:!x&&!L},{googAutoGainControl2:!j&&!L}))),e.indexOf("screen")>=0)if(v.a.isChrome())n.video={mandatory:G(T({},t,{source:"screen"})),optional:[]};else if(v.a.isFirefox())n.video={mozMediaSource:"window",mediaSource:"window",frameRate:t.frameRate||{min:O,max:O}};else{var a="'screen' WebRTC media source is supported only in Chrome and Firefox";d.a.callErrorHandler(new Error(a)),R.error(a)}return e.indexOf("desktop")>=0&&(n.video={mandatory:G(T({},t,{source:"desktop"})),optional:[]},v.a.isElectron()&&t.screenShareAudio&&t.desktopStream.indexOf("screen")>=0&&(n.audio={mandatory:{chromeMediaSource:n.video.mandatory.chromeMediaSource}},delete n.video.mandatory.chromeMediaSourceId)),t.bandwidth&&(n.video||(n.video={mandatory:{},optional:[]}),n.video.optional.push({bandwidth:t.bandwidth})),v.a.isFirefox()&&t.firefox_fake_device&&(n.fake=!0),n}function G(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.desktopStream,n=e.frameRate,r=void 0===n?{min:O,max:O}:n,i=r.max,o=r.min,a={chromeMediaSource:e.source,maxWidth:window.screen.width,maxHeight:window.screen.height};return"number"==typeof o&&(a.minFrameRate=o),"number"==typeof i&&(a.maxFrameRate=i),void 0!==t&&(a.chromeMediaSourceId=t),a}function V(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t={frameRate:O},n=e.desktopSharingFrameRate;return n&&n.max&&(t.frameRate=n.max),t}function q(e,t){var n=Boolean(t)&&t.getAudioTracks().length>0,r=Boolean(t)&&t.getVideoTracks().length>0,i={};-1!==e.indexOf("video")&&(i.video=r),-1!==e.indexOf("audio")&&(i.audio=n),I.emit(y.a.GRANTED_PERMISSIONS,i)}function K(e){var t=e.filter(function(e){return"audioinput"===e.kind}).length,n=e.filter(function(e){return"audiooutput"===e.kind}).length,i=e.filter(function(e){return"videoinput"===e.kind}).length,o=e.filter(function(e){return"videooutput"===e.kind}).length;e.forEach(function(e){var a={audio_input_device_count:t,audio_output_device_count:n,video_input_device_count:i,video_output_device_count:o,device_id:e.deviceId,device_group_id:e.groupId,device_kind:e.kind,device_label:e.label};E.a.sendAnalytics(r.l,a)})}var z=new((function(e){function t(){return _classCallCheck(this,t),_possibleConstructorReturn(this,_getPrototypeOf(t).call(this,I))}return _inherits(t,e),_createClass(t,[{key:"init",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if("boolean"==typeof t.disableAEC&&(x=t.disableAEC,R.info("Disable AEC: "+x)),"boolean"==typeof t.disableNS&&(F=t.disableNS,R.info("Disable NS: "+F)),"boolean"==typeof t.disableAP&&(L=t.disableAP,R.info("Disable AP: "+L)),"boolean"==typeof t.disableAGC&&(j=t.disableAGC,R.info("Disable AGC: "+j)),"boolean"==typeof t.disableHPF&&(U=t.disableHPF,R.info("Disable HPF: "+U)),k=void 0,window.clearInterval(w),w=void 0,this.enumerateDevices=(function(){if(navigator.mediaDevices&&navigator.mediaDevices.enumerateDevices)return function(e){navigator.mediaDevices.enumerateDevices().then(e,function(){return e([])})}})(),v.a.usesNewGumFlow())this.RTCPeerConnectionType=RTCPeerConnection,this.attachMediaStream=W(function(e,t){e&&(e.srcObject=t)}),this.getStreamID=function(e){return e.id},this.getTrackID=function(e){return e.id};else{if(!v.a.isChromiumBased()&&!v.a.isReactNative()){var n="Endpoint does not appear to be WebRTC-capable";throw R.error(n),new Error(n)}this.RTCPeerConnectionType=RTCPeerConnection,this.attachMediaStream=W(function(e,t){return(function(e,t){var n,r="srcObject";r in e||(r="mozSrcObject")in e||(r=null),r?e[r]=t:(t&&((n=t.jitsiObjectURL)||(t.jitsiObjectURL=n=URL.createObjectURL(t))),e.src=n||"")})(e,t),e}),this.getStreamID=function(e){var t=e.id;return"number"==typeof t?t:S.a.filterSpecialChars(t)},this.getTrackID=function(e){return e.id},MediaStream.prototype.getVideoTracks||(MediaStream.prototype.getVideoTracks=function(){return this.videoTracks}),MediaStream.prototype.getAudioTracks||(MediaStream.prototype.getAudioTracks=function(){return this.audioTracks})}this._initPCConstraints(t),_.a.init(t,this.getUserMediaWithConstraints.bind(this)),this.isDeviceListAvailable()&&this.enumerateDevices(function(t){k=t.splice(0),R.debug("Available devices: ",k),K(k),I.emit(y.a.DEVICE_LIST_AVAILABLE,k);var n=function(){return e.enumerateDevices(function(e){(function(e){return e.length!==k.length||e.map(t).sort().join("")!==k.map(t).sort().join("");function t(e){return JSON.stringify({kind:e.kind,deviceId:e.deviceId,groupId:e.groupId,label:e.label,facing:e.facing})}})(e)&&(function(e){k=e.slice(0),R.info("list of media devices has changed:",k),K(k),I.emit(y.a.DEVICE_LIST_WILL_CHANGE,e),I.emit(y.a.DEVICE_LIST_CHANGED,e)})(e)})};v.a.supportsDeviceChangeEvent()?navigator.mediaDevices.addEventListener("devicechange",n):w=window.setInterval(n,3e3)})}},{key:"_initPCConstraints",value:function(e){v.a.isFirefox()?this.pcConstraints={}:(v.a.isChromiumBased()||v.a.isReactNative())&&(this.pcConstraints={optional:[{googHighStartBitrate:0},{googPayloadPadding:!0},{googScreencastMinBitrate:100},{googCpuOveruseDetection:!0},{googCpuOveruseEncodeUsage:!0},{googCpuUnderuseThreshold:55},{googCpuOveruseThreshold:85}]},e.useIPv6&&this.pcConstraints.optional.push({googIPv6:!0}),this.p2pPcConstraints=JSON.parse(JSON.stringify(this.pcConstraints))),this.p2pPcConstraints=this.p2pPcConstraints||this.pcConstraints}},{key:"getUserMediaWithConstraints",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=B(e,t);return R.info("Get media constraints",n),new Promise(function(t,r){navigator.mediaDevices.getUserMedia(n).then(function(n){R.log("onUserMediaSuccess"),q(e,n),t(n)}).catch(function(t){R.warn("Failed to get access to local media. "+t+" "+n+" "),q(e,void 0),r(new l.a(t,n,e))})})}},{key:"_newGetUserMediaWithConstraints",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return new Promise(function(n,r){navigator.mediaDevices.getUserMedia(t).then(function(t){R.log("onUserMediaSuccess"),q(e,t),n(t)}).catch(function(n){R.warn("Failed to get access to local media. "+n+" "+t+" "),q(e,void 0),r(new l.a(n,t,e))})})}},{key:"_newGetDesktopMedia",value:function(e){var t=this;return _.a.isSupported()&&v.a.supportsVideo()?new Promise(function(n,r){_.a.obtainStream(t._parseDesktopSharingOptions(e),function(e){n(e)},function(e){r(e)})}):Promise.reject(new Error("Desktop sharing is not supported!"))}},{key:"obtainAudioAndVideoPermissions",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return e.devices=e.devices||P.concat(),e.resolution=e.resolution||720,e.devices.includes("desktop")&&!_.a.isSupported()?Promise.reject(new Error("Desktop sharing is not supported!")):this._getAudioAndVideoStreams(e).then(function(t){return(function(e,t){var n,r,i,o=[];if(e){var a=e.audioVideo;if(a){var s=a.getAudioTracks();if(s.length){n=new MediaStream;for(var c=0;c0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1?arguments[1]:void 0,n=[],r=e.includes("audio"),i=t&&t.getAudioTracks().length>0;r&&!i&&n.push("audio");var o=e.includes("video"),a=t&&t.getVideoTracks().length>0;return o&&!a&&n.push("video"),n}},{key:"_parseDesktopSharingOptions",value:function(e){return T({},e.desktopSharingExtensionExternalInstallation,{desktopSharingSources:e.desktopSharingSources,gumOptions:{frameRate:e.desktopSharingFrameRate},trackOptions:V(e)})}},{key:"newObtainAudioAndVideoPermissions",value:function(e){var t=this;R.info("Using the new gUM flow");var n=[],r=function(){if(-1===(e.devices||[]).indexOf("desktop"))return Promise.resolve();var t=e.desktopSharingExtensionExternalInstallation,n=e.desktopSharingSourceDevice,r=e.desktopSharingSources,i=e.desktopSharingFrameRate;if(n){var o=k&&k.find(function(e){return"videoinput"===e.kind&&(e.deviceId===n||e.label===n)});if(!o)return Promise.reject(new l.a({name:"ConstraintNotSatisfiedError"},{},[n]));var a=this._parseDesktopSharingOptions(e),s=a.gumOptions,c=a.trackOptions,u={video:T({},s,{deviceId:o.deviceId})};return this._newGetUserMediaWithConstraints(["video"],u).then(function(e){var t=e&&e.getTracks()[0];return(t&&t.applyConstraints?t.applyConstraints(c):Promise.resolve()).then(function(){return{sourceType:"device",stream:e}})})}return this._newGetDesktopMedia({desktopSharingExtensionExternalInstallation:t,desktopSharingSources:r,desktopSharingFrameRate:i})}.bind(this),i=function(){var t=(e.devices||["audio","video"]).filter(function(e){return"audio"===e||"video"===e&&v.a.supportsVideo()});if(!t.length)return Promise.resolve();var n=(function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=JSON.parse(JSON.stringify(t.constraints||D));if(e.indexOf("video")>=0)if(n.video||(n.video={}),t.cameraDeviceId)n.video.deviceId=t.cameraDeviceId;else{var r=t.facingMode||o.a.USER;n.video.facingMode=r}else n.video=!1;return e.indexOf("audio")>=0?(n.audio&&"boolean"!=typeof n.audio||(n.audio={}),v.a.isFirefox()||v.a.isSafari()?n.audio={deviceId:t.micDeviceId,autoGainControl:!j&&!L,echoCancellation:!x&&!L,noiseSuppression:!F&&!L}:(n.audio.optional||(n.audio.optional=[]),n.audio.optional.push({sourceId:t.micDeviceId},{echoCancellation:!x&&!L},{googEchoCancellation:!x&&!L},{googAutoGainControl:!j&&!L},{googNoiseSuppression:!F&&!L},{googHighpassFilter:!U&&!L},{googNoiseSuppression2:!F&&!L},{googEchoCancellation2:!x&&!L},{googAutoGainControl2:!j&&!L}))):n.audio=!1,e.indexOf("desktop")>=0&&(n.video&&"boolean"!=typeof n.video||(n.video={}),n.video={mandatory:G(T({},t,{source:"desktop"}))}),n})(t,e);return R.info("Got media constraints: ",n),this._newGetUserMediaWithConstraints(t,n)}.bind(this);return r().then(function(e){if(e){var t=e.stream,r=e.sourceId,i=e.sourceType,o=t.getAudioTracks();if(o.length){var a=new MediaStream(o);n.push({stream:a,sourceId:r,sourceType:i,track:a.getAudioTracks()[0]})}var s=t.getVideoTracks();if(s.length){var c=new MediaStream(s);n.push({stream:c,sourceId:r,sourceType:i,track:c.getVideoTracks()[0],videoType:C.a.DESKTOP})}}}).then(i).then(function(t){if(t){var r=t.getAudioTracks();if(r.length){var i=new MediaStream(r);n.push({stream:i,track:i.getAudioTracks()[0],effects:e.effects})}var o=t.getVideoTracks();if(o.length){var a=new MediaStream(o);n.push({stream:a,track:a.getVideoTracks()[0],videoType:C.a.CAMERA,effects:e.effects})}}}).then(function(){return n}).catch(function(e){return n.forEach(function(e){var n=e.stream;t.stopMediaStream(n)}),Promise.reject(e)})}},{key:"isDeviceListAvailable",value:function(){return Boolean(navigator.mediaDevices&&navigator.mediaDevices.enumerateDevices)}},{key:"isDeviceChangeAvailable",value:function(e){return"output"!==e&&"audiooutput"!==e||J}},{key:"stopMediaStream",value:function(e){if(e){e.getTracks().forEach(function(e){e.stop&&e.stop()}),e.stop&&e.stop(),e.release&&e.release();var t=e.jitsiObjectURL;t&&(delete e.jitsiObjectURL,URL.revokeObjectURL(t))}}},{key:"isDesktopSharingEnabled",value:function(){return _.a.isSupported()}},{key:"setAudioOutputDevice",value:function(e){return this.isDeviceChangeAvailable("output")?H.setSinkId(e).then(function(){N=e,M=!0,R.log("Audio output device set to "+e),I.emit(y.a.AUDIO_OUTPUT_DEVICE_CHANGED,e)}):Promise.reject(new Error("Audio output device change is not supported"))}},{key:"getAudioOutputDevice",value:function(){return N}},{key:"getCurrentlyAvailableMediaDevices",value:function(){return k}},{key:"getEventDataForActiveDevice",value:function(e){var t=[],n={deviceId:e.deviceId,kind:e.kind,label:e.label,groupId:e.groupId};return t.push(n),{deviceList:t}}},{key:"setSuspendVideo",value:function(e,t){e.optional||(e.optional=[]),e.optional=e.optional.filter(function(e){return!e.hasOwnProperty("googSuspendBelowMinBitrate")}),t&&e.optional.push({googSuspendBelowMinBitrate:"true"})}}]),t})(h.a));function W(e){return function(t,n){var r=e.apply(z,arguments);return n&&z.isDeviceChangeAvailable("output")&&n.getAudioTracks&&n.getAudioTracks().length&&M&&t.setSinkId(z.getAudioOutputDevice()).catch(function(e){var n=new l.a(e,null,["audiooutput"]);d.a.callUnhandledRejectionHandler({promise:this,reason:n}),R.warn("Failed to set audio output device for the element. Default audio output device will be used instead",t,n)}),r}}t.a=z}).call(this,"modules/RTC/RTCUtils.js")},function(e,t){var n=[],r=window.onerror,i=window.onunhandledrejection;window.onerror=function(){for(var e=arguments.length,t=new Array(e),i=0;i0&&void 0!==arguments[0]?arguments[0]:[]).map(function(e){var t=e.sourceId,n=e.sourceType,r=e.stream,i=e.track,o=e.videoType,a=e.effects,s=i.getSettings(),u=s.deviceId,l=s.facingMode;return C=Object(d.c)(C),new c.a({deviceId:u,facingMode:l,mediaType:i.kind,rtcId:C,sourceId:t,sourceType:n,stream:r,track:i,videoType:o||null,effects:a})})}var R=(function(e){function t(e){var n,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return _classCallCheck(this,t),(n=_possibleConstructorReturn(this,_getPrototypeOf(t).call(this))).conference=e,n.peerConnections=new Map,n.localTracks=[],n.options=r,n._channel=null,n._channelOpen=!1,n._lastN=-1,n._lastNEndpoints=null,n._maxFrameHeight=void 0,n._pinnedEndpoint=null,n._selectedEndpoints=[],n._lastNChangeListener=n._onLastNChanged.bind(_assertThisInitialized(_assertThisInitialized(n))),n._onDeviceListChanged=n._onDeviceListChanged.bind(_assertThisInitialized(_assertThisInitialized(n))),n._updateAudioOutputForAudioTracks=n._updateAudioOutputForAudioTracks.bind(_assertThisInitialized(_assertThisInitialized(n))),m.a.isDeviceChangeAvailable("output")&&(m.a.addListener(f.a.AUDIO_OUTPUT_DEVICE_CHANGED,n._updateAudioOutputForAudioTracks),m.a.addListener(f.a.DEVICE_LIST_CHANGED,n._onDeviceListChanged)),n}return _inherits(t,e),_createClass(t,[{key:"destroy",value:function(){m.a.removeListener(f.a.AUDIO_OUTPUT_DEVICE_CHANGED,this._updateAudioOutputForAudioTracks),m.a.removeListener(f.a.DEVICE_LIST_CHANGED,this._onDeviceListChanged),this.removeListener(f.a.LASTN_ENDPOINT_CHANGED,this._lastNChangeListener),this._channelOpenListener&&this.removeListener(f.a.DATA_CHANNEL_OPEN,this._channelOpenListener)}},{key:"initializeBridgeChannel",value:function(e,t){var n=this;this._channel=new i.a(e,t,this.eventEmitter),this._channelOpenListener=function(){n._channelOpen=!0;try{n._channel.sendPinnedEndpointMessage(n._pinnedEndpoint),n._channel.sendSelectedEndpointsMessage(n._selectedEndpoints),void 0!==n._maxFrameHeight&&n._channel.sendReceiverVideoConstraintMessage(n._maxFrameHeight)}catch(e){a.a.callErrorHandler(e),E.error("Cannot send selected("+n._selectedEndpoint+")pinned("+n._pinnedEndpoint+")frameHeight("+n._maxFrameHeight+") endpoint message",e)}n.removeListener(f.a.DATA_CHANNEL_OPEN,n._channelOpenListener),n._channelOpenListener=null,-1!==n._lastN&&n._channel.sendSetLastNMessage(n._lastN)},this.addListener(f.a.DATA_CHANNEL_OPEN,this._channelOpenListener),this.addListener(f.a.LASTN_ENDPOINT_CHANGED,this._lastNChangeListener)}},{key:"_onDeviceListChanged",value:function(){this._updateAudioOutputForAudioTracks(m.a.getAudioOutputDevice())}},{key:"_onLastNChanged",value:function(){var e,t,n=this,r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],i=this._lastNEndpoints||[];this._lastNEndpoints=r,e=i.filter(function(e){return!n.isInLastN(e)}),t=r.filter(function(e){return-1===i.indexOf(e)}),this.conference.eventEmitter.emit(s.LAST_N_ENDPOINTS_CHANGED,e,t)}},{key:"onCallEnded",value:function(){this._channel&&(this._channel&&"websocket"===this._channel.mode&&this._channel.close(),this._channel=null,this._channelOpen=!1)}},{key:"setReceiverVideoConstraint",value:function(e){this._maxFrameHeight=e,this._channel&&this._channelOpen&&this._channel.sendReceiverVideoConstraintMessage(e)}},{key:"selectEndpoints",value:function(e){this._selectedEndpoints=e,this._channel&&this._channelOpen&&this._channel.sendSelectedEndpointsMessage(e)}},{key:"pinEndpoint",value:function(e){this._pinnedEndpoint=e,this._channel&&this._channelOpen&&this._channel.sendPinnedEndpointMessage(e)}},{key:"createPeerConnection",value:function(e,n,r,i){var o=t.getPCConstraints(r);void 0!==i.abtestSuspendVideo&&(m.a.setSuspendVideo(o,i.abtestSuspendVideo),v.a.analytics.addPermanentProperties({abtestSuspendVideo:i.abtestSuspendVideo})),h.a.supportsInsertableStreams()&&(E.debug("E2EE - setting insertable streams constraints"),n.forceEncodedAudioInsertableStreams=!0,n.forceEncodedVideoInsertableStreams=!0),h.a.supportsSdpSemantics()&&(n.sdpSemantics="plan-b"),n.bundlePolicy="max-bundle",b=Object(d.c)(b);var a=new g.a(this,b,e,n,o,r,i);return this.peerConnections.set(a.id,a),a}},{key:"_removePeerConnection",value:function(e){var t=e.id;return!!this.peerConnections.has(t)&&(this.peerConnections.delete(t),!0)}},{key:"addLocalTrack",value:function(e){if(!e)throw new Error("track must not be null nor undefined");this.localTracks.push(e),e.conference=this.conference}},{key:"getLastN",value:function(){return this._lastN}},{key:"getLocalVideoTrack",value:function(){var e=this.getLocalTracks(l.c);return e.length?e[0]:void 0}},{key:"getLocalAudioTrack",value:function(){var e=this.getLocalTracks(l.a);return e.length?e[0]:void 0}},{key:"getLocalTracks",value:function(e){var t=this.localTracks.slice();return void 0!==e&&(t=t.filter(function(t){return t.getType()===e})),t}},{key:"getRemoteTracks",value:function(e){var t=[],n=this.peerConnections.values(),r=Array.isArray(n),i=0;for(n=r?n:n["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var o;if(r){if(i>=n.length)break;o=n[i++]}else{if((i=n.next()).done)break;o=i.value}var a=o.getRemoteTracks(void 0,e);a&&(t=t.concat(a))}return t}},{key:"setAudioMute",value:function(e){var t=[];return this.getLocalTracks(l.a).forEach(function(n){t.push(e?n.mute():n.unmute())}),Promise.all(t)}},{key:"removeLocalTrack",value:function(e){var t=this.localTracks.indexOf(e);-1!==t&&this.localTracks.splice(t,1)}},{key:"removeRemoteTracks",value:function(e){var t=[],n=this.peerConnections.values(),r=Array.isArray(n),i=0;for(n=r?n:n["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var o;if(r){if(i>=n.length)break;o=n[i++]}else{if((i=n.next()).done)break;o=i.value}var a=o.removeRemoteTracks(e);t=t.concat(a)}return E.debug("Removed remote tracks for "+e+" count: "+t.length),t}},{key:"closeBridgeChannel",value:function(){this._channel&&(this._channel.close(),this._channelOpen=!1,this.removeListener(f.a.LASTN_ENDPOINT_CHANGED,this._lastNChangeListener))}},{key:"setAudioLevel",value:function(e,t,n,r){var i=e.getTrackBySSRC(t);i&&(i.isAudioTrack()?(i.isLocal()!==r&&E.error(i+" was expected to "+(r?"be":"not be")+" local"),i.setAudioLevel(n,e)):E.warn("Received audio level for non-audio track: "+t))}},{key:"sendChannelMessage",value:function(e,t){if(!this._channel)throw new Error("Channel support is disabled!");this._channel.sendMessage(e,t)}},{key:"setLastN",value:function(e){this._lastN!==e&&(this._lastN=e,this._channel&&this._channelOpen&&this._channel.sendSetLastNMessage(e),this.eventEmitter.emit(f.a.LASTN_VALUE_CHANGED,e))}},{key:"isInLastN",value:function(e){return!this._lastNEndpoints||this._lastNEndpoints.indexOf(e)>-1}},{key:"_updateAudioOutputForAudioTracks",value:function(e){var t=this.getRemoteTracks(l.a),n=Array.isArray(t),r=0;for(t=n?t:t["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var i;if(n){if(r>=t.length)break;i=t[r++]}else{if((r=t.next()).done)break;i=r.value}i.setAudioOutput(e)}}}],[{key:"newCreateLocalTracks",value:function(e){return A(e)}},{key:"obtainAudioAndVideoPermissions",value:function(e){var t=h.a.usesNewGumFlow();return(t?m.a.newObtainAudioAndVideoPermissions(e):m.a.obtainAudioAndVideoPermissions(e)).then(function(n){return t?A(n):T(n,e)})}},{key:"addListener",value:function(e,t){m.a.addListener(e,t)}},{key:"removeListener",value:function(e,t){m.a.removeListener(e,t)}},{key:"init",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return this.options=e,m.a.init(this.options)}},{key:"getPCConstraints",value:function(e){var t=e?m.a.p2pPcConstraints:m.a.pcConstraints;return t?JSON.parse(JSON.stringify(t)):{}}},{key:"attachMediaStream",value:function(e,t){return m.a.attachMediaStream(e,t)}},{key:"getStreamID",value:function(e){return m.a.getStreamID(e)}},{key:"getTrackID",value:function(e){return m.a.getTrackID(e)}},{key:"isDeviceListAvailable",value:function(){return m.a.isDeviceListAvailable()}},{key:"isDeviceChangeAvailable",value:function(e){return m.a.isDeviceChangeAvailable(e)}},{key:"isWebRtcSupported",value:function(){return h.a.isSupported()}},{key:"getAudioOutputDevice",value:function(){return m.a.getAudioOutputDevice()}},{key:"getCurrentlyAvailableMediaDevices",value:function(){return m.a.getCurrentlyAvailableMediaDevices()}},{key:"getEventDataForActiveDevice",value:function(e){return m.a.getEventDataForActiveDevice(e)}},{key:"setAudioOutputDevice",value:function(e){return m.a.setAudioOutputDevice(e)}},{key:"isUserStream",value:function(e){return t.isUserStreamById(m.a.getStreamID(e))}},{key:"isUserStreamById",value:function(e){return e&&"mixedmslabel"!==e&&"default"!==e}},{key:"enumerateDevices",value:function(e){m.a.enumerateDevices(e)}},{key:"stopMediaStream",value:function(e){m.a.stopMediaStream(e)}},{key:"isDesktopSharingEnabled",value:function(){return m.a.isDesktopSharingEnabled()}}]),t})(u.a)}).call(this,"modules/RTC/RTC.js")},function(e,t){e.exports={CAMERA:"camera",DESKTOP:"desktop"}},function(e,t,n){"use strict";n.r(t),n.d(t,"CHROME_EXTENSION_GENERIC_ERROR",function(){return r}),n.d(t,"CHROME_EXTENSION_INSTALLATION_ERROR",function(){return i}),n.d(t,"CHROME_EXTENSION_USER_GESTURE_REQUIRED",function(){return o}),n.d(t,"CHROME_EXTENSION_USER_CANCELED",function(){return a}),n.d(t,"CONSTRAINT_FAILED",function(){return s}),n.d(t,"ELECTRON_DESKTOP_PICKER_ERROR",function(){return c}),n.d(t,"ELECTRON_DESKTOP_PICKER_NOT_FOUND",function(){return u}),n.d(t,"FIREFOX_EXTENSION_NEEDED",function(){return d}),n.d(t,"GENERAL",function(){return l}),n.d(t,"NOT_FOUND",function(){return h}),n.d(t,"PERMISSION_DENIED",function(){return p}),n.d(t,"TRACK_IS_DISPOSED",function(){return f}),n.d(t,"TRACK_NO_STREAM_FOUND",function(){return m}),n.d(t,"UNSUPPORTED_RESOLUTION",function(){return v});var r="gum.chrome_extension_generic_error",i="gum.chrome_extension_installation_error",o="gum.chrome_extension_user_gesture_required",a="gum.chrome_extension_user_canceled",s="gum.constraint_failed",c="gum.electron_desktop_picker_error",u="gum.electron_desktop_picker_not_found",d="gum.firefox_extension_needed",l="gum.general",h="gum.not_found",p="gum.permission_denied",f="track.track_is_disposed",m="track.no_stream_found",v="gum.unsupported_resolution"},function(e,t,n){"use strict";n.r(t),n.d(t,"LOCAL_TRACK_STOPPED",function(){return r}),n.d(t,"TRACK_AUDIO_LEVEL_CHANGED",function(){return i}),n.d(t,"TRACK_AUDIO_OUTPUT_CHANGED",function(){return o}),n.d(t,"TRACK_MUTE_CHANGED",function(){return a}),n.d(t,"TRACK_VIDEOTYPE_CHANGED",function(){return s}),n.d(t,"NO_DATA_FROM_SOURCE",function(){return c});var r="track.stopped",i="track.audioLevelsChanged",o="track.audioOutputChanged",a="track.trackMuteChanged",s="track.videoTypeChanged",c="track.no_data_from_source"},function(e,t,n){"use strict";var r={};n.r(r),n.d(r,"CHROME",function(){return a}),n.d(r,"OPERA",function(){return s}),n.d(r,"FIREFOX",function(){return c}),n.d(r,"INTERNET_EXPLORER",function(){return u}),n.d(r,"SAFARI",function(){return d}),n.d(r,"NWJS",function(){return l}),n.d(r,"ELECTRON",function(){return h}),n.d(r,"REACT_NATIVE",function(){return p}),n.d(r,"UNKNOWN",function(){return f}),n(64);var i=n(77),o=n.n(i),a="chrome",s="opera",c="firefox",u="iexplorer",d="safari",l="nwjs",h="electron",p="react-native",f="unknown",m={Chrome:a,Chromium:a,Opera:s,Firefox:c,"Internet Explorer":u,Safari:d};function v(){var e=navigator.userAgent;if(e.match(/Electron/)){var t=e.match(/Electron\/([\d.]+)/)[1];return{name:h,version:t}}}function g(){var e=navigator.userAgent;if(e.match(/JitsiMeetNW/)){var t=e.match(/JitsiMeetNW\/([\d.]+)/)[1];return{name:l,version:t}}}function y(){var e,t,n=navigator.userAgent.match(/\b(react[ \t_-]*native)(?:\/(\S+))?/i);if(n||"ReactNative"===navigator.product)return n&&n.length>2&&(t=n[1],e=n[2]),t||(t="react-native"),e||(e="unknown"),{name:p,version:e}}function _(e){for(var t,n=[y,v,g],r=0;r72&&(t.name=a,t.version=n)}else t.name=a,t.version=e.match(/Chrome\/([\d.]+)/)[1];return t})())||{name:f,version:void 0}}var S=(function(){function e(t){var n,r;if(_classCallCheck(this,e),this._bowser=o.a.getParser(navigator.userAgent),void 0===t){var i=_(this._bowser);n=i.name,r=i.version}else t.name in m?(n=m[t.name],r=t.version):(n=f,r=void 0);this._name=n,this._version=r}return _createClass(e,[{key:"getName",value:function(){return this._name}},{key:"isChrome",value:function(){return this._name===a}},{key:"isOpera",value:function(){return this._name===s}},{key:"isFirefox",value:function(){return this._name===c}},{key:"isIExplorer",value:function(){return this._name===u}},{key:"isSafari",value:function(){return this._name===d}},{key:"isNWJS",value:function(){return this._name===l}},{key:"isElectron",value:function(){return this._name===h}},{key:"isReactNative",value:function(){return this._name===p}},{key:"getVersion",value:function(){return this._version}},{key:"_checkCondition",value:function(e){if(this._version)return this._bowser.satisfies(e)}},{key:"isVersionGreaterThan",value:function(e){return this._checkCondition(_defineProperty({},this._name,">"+e))}},{key:"isVersionLessThan",value:function(e){return this._checkCondition(_defineProperty({},this._name,"<"+e))}},{key:"isVersionEqualTo",value:function(e){return this._checkCondition(_defineProperty({},this._name,"~"+e))}}]),e})(),E=(function(){function e(){_classCallCheck(this,e)}return _createClass(e,[{key:"getItem",value:function(){}},{key:"setItem",value:function(){}},{key:"removeItem",value:function(){}},{key:"key",value:function(){}}]),e})(),b=new((function(e){function t(){var e,n;_classCallCheck(this,t),e=_possibleConstructorReturn(this,_getPrototypeOf(t).call(this));try{n=window.localStorage}catch(n){}return e.storage=n||new E,e}return _inherits(t,E),_createClass(t,[{key:"getItem",value:function(e){return this.storage.getItem(e)}},{key:"setItem",value:function(e,t){return this.storage.setItem(e,t)}},{key:"removeItem",value:function(e){return this.storage.removeItem(e)}},{key:"key",value:function(e){return this.storage.key(e)}}]),t})());n.d(t,"a",function(){return S}),n.d(t,"b",function(){return r}),n.d(t,"c",function(){return b})},function(e,t,n){"use strict";var r=n(14),i={};function o(e,t,n){if("object"==typeof e&&void 0!==e.name)switch(this.gum={error:e,constraints:t,devices:n&&Array.isArray(n)?n.slice(0):void 0},e.name){case"NotAllowedError":case"PermissionDeniedError":case"SecurityError":this.name=r.PERMISSION_DENIED,this.message=i[this.name]+(this.gum.devices||[]).join(", ");break;case"DevicesNotFoundError":case"NotFoundError":this.name=r.NOT_FOUND,this.message=i[this.name]+(this.gum.devices||[]).join(", ");break;case"ConstraintNotSatisfiedError":case"OverconstrainedError":var o=e.constraintName||e.constraint;t&&t.video&&(!n||n.indexOf("video")>-1)&&("minWidth"===o||"maxWidth"===o||"minHeight"===o||"maxHeight"===o||"width"===o||"height"===o||"deviceId"===o)?(this.name=r.UNSUPPORTED_RESOLUTION,this.message=i[this.name]+(function(e,t){if(t&&t.video&&t.video.mandatory)switch(e){case"width":return t.video.mandatory.minWidth;case"height":return t.video.mandatory.minHeight;default:return t.video.mandatory[e]||""}return""})(o,t)):(this.name=r.CONSTRAINT_FAILED,this.message=i[this.name]+e.constraintName);break;default:this.name=r.GENERAL,this.message=e.message||i[this.name]}else{if("string"!=typeof e)throw new Error("Invalid arguments");i[e]?(this.name=e,this.message=t||i[e]):this.message=e}this.stack=e.stack||(new Error).stack}i[r.UNSUPPORTED_RESOLUTION]="Video resolution is not supported: ",i[r.CHROME_EXTENSION_INSTALLATION_ERROR]="Failed to install Chrome extension",i[r.CHROME_EXTENSION_USER_GESTURE_REQUIRED]="Failed to install Chrome extension - installations can only be initiated by a user gesture.",i[r.CHROME_EXTENSION_USER_CANCELED]="User canceled Chrome's screen sharing prompt",i[r.CHROME_EXTENSION_GENERIC_ERROR]="Unknown error from Chrome extension",i[r.ELECTRON_DESKTOP_PICKER_ERROR]="Unkown error from desktop picker",i[r.ELECTRON_DESKTOP_PICKER_NOT_FOUND]="Failed to detect desktop picker",i[r.GENERAL]="Generic getUserMedia error",i[r.PERMISSION_DENIED]="User denied permission to use device(s): ",i[r.NOT_FOUND]="Requested device(s) was/were not found: ",i[r.CONSTRAINT_FAILED]="Constraint could not be satisfied: ",i[r.TRACK_IS_DISPOSED]="Track has been already disposed",i[r.TRACK_NO_STREAM_FOUND]="Track does not have an associated Media Stream",o.prototype=Object.create(Error.prototype),o.prototype.constructor=o,t.a=o},function(e,t,n){"use strict";n.d(t,"a",function(){return o});var r=n(1),i=n(6);function o(e){for(var t=e.split("\r\nm="),n=1,r=t.length;n=y.length)break;E=y[S++]}else{if((S=y.next()).done)break;E=S.value}var b=_slicedToArray(E,2),C=b[0],T=b[1];e.c("source",{ssrc:C,xmlns:"urn:xmpp:jingle:apps:rtp:ssma:0"}),T.forEach(function(t){var n=t.indexOf(" "),r=t.substr(n+1);if(e.c("parameter"),-1===r.indexOf(":"))e.attrs({name:r});else{var o=r.split(":",2)[0];e.attrs({name:o});var a=r.split(":",2)[1];a=i.a.filterSpecialChars(a),e.attrs({value:a})}e.up()}),e.up()}i.a.findLines(this.media[n],"a=ssrc-group:").forEach(function(t){var n=t.indexOf(" "),r=t.substr(0,n).substr(13),i=t.substr(14+r.length).split(" ");i.length&&(e.c("ssrc-group",{semantics:r,xmlns:"urn:xmpp:jingle:apps:rtp:ssma:0"}),i.forEach(function(t){return e.c("source",{ssrc:t}).up()}),e.up())})}var A=i.a.findLines(this.media[n],"a=rid");if(A.length&&r.a.usesRidsForSimulcast()){var R=A.map(function(e){return e.split(":")[1]}).map(function(e){return e.split(" ")[0]});R.forEach(function(t){e.c("source",{rid:t,xmlns:"urn:xmpp:jingle:apps:rtp:ssma:0"}),e.up()}),i.a.findLine(this.media[n],"a=simulcast")&&(e.c("rid-group",{semantics:"SIM",xmlns:"urn:xmpp:jingle:apps:rtp:ssma:0"}),R.forEach(function(t){e.c("source",{rid:t}).up()}),e.up())}if(i.a.findLine(this.media[n],"a=rtcp-mux")&&e.c("rtcp-mux").up(),this.rtcpFbToJingle(n,e,"*"),(s=i.a.findLines(this.media[n],"a=extmap:")).length)for(o=0;o2&&t.attrs({streams:a[2]}),t.up()}if(i.a.findLines(this.media[e],"a=fingerprint:",this.session).forEach(function(o){(n=i.a.parseFingerprint(o)).xmlns="urn:xmpp:jingle:apps:dtls:0",t.c("fingerprint").t(n.fingerprint),delete n.fingerprint,(o=i.a.findLine(r.media[e],"a=setup:",r.session))&&(n.setup=o.substr(8)),t.attrs(n),t.up()}),n=i.a.iceparams(this.media[e],this.session)){n.xmlns="urn:xmpp:jingle:transports:ice-udp:1",t.attrs(n);var s=i.a.findLines(this.media[e],"a=candidate:",this.session);s.length&&s.forEach(function(e){var n=i.a.candidateToJingle(e);r.failICE&&(n.ip="1.1.1.1");var o=n&&"string"==typeof n.protocol?n.protocol.toLowerCase():"";r.removeTcpCandidates&&("tcp"===o||"ssltcp"===o)||r.removeUdpCandidates&&"udp"===o||t.c("candidate",n).up()})}t.up()},o.prototype.rtcpFbToJingle=function(e,t,n){i.a.findLines(this.media[e],"a=rtcp-fb:"+n).forEach(function(e){var n=i.a.parseRTCPFB(e);"trr-int"===n.type?(t.c("rtcp-fb-trr-int",{xmlns:"urn:xmpp:jingle:apps:rtp:rtcp-fb:0",value:n.params[0]}),t.up()):(t.c("rtcp-fb",{xmlns:"urn:xmpp:jingle:apps:rtp:rtcp-fb:0",type:n.type}),n.params.length>0&&t.attrs({subtype:n.params[0]}),t.up())})},o.prototype.rtcpFbFromJingle=function(e,t){var n="",r=e.find('>rtcp-fb-trr-int[xmlns="urn:xmpp:jingle:apps:rtp:rtcp-fb:0"]');return r.length&&(n+="a=rtcp-fb:* trr-int ",r.attr("value")?n+=r.attr("value"):n+="0",n+="\r\n"),(r=e.find('>rtcp-fb[xmlns="urn:xmpp:jingle:apps:rtp:rtcp-fb:0"]')).each(function(){n+="a=rtcp-fb:"+t+" "+$(this).attr("type"),$(this).attr("subtype")&&(n+=" "+$(this).attr("subtype")),n+="\r\n"}),n},o.prototype.fromJingle=function(e){var t=this,n=Date.now();this.raw="v=0\r\no=- "+n+" 2 IN IP4 0.0.0.0\r\ns=-\r\nt=0 0\r\n";var r=$(e).find('>group[xmlns="urn:xmpp:jingle:apps:grouping:0"]');r.length&&r.each(function(e,n){var r=$(n).find(">content").map(function(e,t){return t.getAttribute("name")}).get();r.length>0&&(t.raw+="a=group:"+(n.getAttribute("semantics")||n.getAttribute("type"))+" "+r.join(" ")+"\r\n")}),this.session=this.raw,e.find(">content").each(function(){var e=t.jingle2media($(this));t.media.push(e)}),this.raw=this.session+this.media.join("")},o.prototype.jingle2media=function(e){var t=e.find("description"),n="",r=this,o=e.find('>transport>sctpmap[xmlns="urn:xmpp:jingle:transports:dtls-sctp:1"]'),a={media:t.attr("media"),port:"1"};if("rejected"===e.attr("senders")&&(a.port="0"),e.find(">transport>fingerprint").length||t.find("encryption").length?a.proto=o.length?"DTLS/SCTP":"RTP/SAVPF":a.proto="RTP/AVPF",o.length){n+="m=application "+a.port+" DTLS/SCTP "+o.attr("number")+"\r\n",n+="a=sctpmap:"+o.attr("number")+" "+o.attr("protocol");var s=o.attr("streams");n+=s?" "+s+"\r\n":"\r\n"}else a.fmt=t.find("payload-type").map(function(){return this.getAttribute("id")}).get(),n+=i.a.buildMLine(a)+"\r\n";switch(n+="c=IN IP4 0.0.0.0\r\n",o.length||(n+="a=rtcp:1 IN IP4 0.0.0.0\r\n"),(a=e.find('>transport[xmlns="urn:xmpp:jingle:transports:ice-udp:1"]')).length&&(a.attr("ufrag")&&(n+=i.a.buildICEUfrag(a.attr("ufrag"))+"\r\n"),a.attr("pwd")&&(n+=i.a.buildICEPwd(a.attr("pwd"))+"\r\n"),a.find(">fingerprint").each(function(){n+="a=fingerprint:"+this.getAttribute("hash"),n+=" "+$(this).text(),n+="\r\n",this.getAttribute("setup")&&(n+="a=setup:"+this.getAttribute("setup")+"\r\n")})),e.attr("senders")){case"initiator":n+="a=sendonly\r\n";break;case"responder":n+="a=recvonly\r\n";break;case"none":n+="a=inactive\r\n";break;case"both":n+="a=sendrecv\r\n"}return n+="a=mid:"+e.attr("name")+"\r\n",t.find("rtcp-mux").length&&(n+="a=rtcp-mux\r\n"),t.find("encryption").length&&t.find("encryption>crypto").each(function(){n+="a=crypto:"+this.getAttribute("tag"),n+=" "+this.getAttribute("crypto-suite"),n+=" "+this.getAttribute("key-params"),this.getAttribute("session-params")&&(n+=" "+this.getAttribute("session-params")),n+="\r\n"}),t.find("payload-type").each(function(){n+=i.a.buildRTPMap(this)+"\r\n",$(this).find(">parameter").length&&(n+="a=fmtp:"+this.getAttribute("id")+" ",n+=$(this).find("parameter").map(function(){var e=this.getAttribute("name");return(e?e+"=":"")+this.getAttribute("value")}).get().join("; "),n+="\r\n"),n+=r.rtcpFbFromJingle($(this),this.getAttribute("id"))}),n+=r.rtcpFbFromJingle(t,"*"),(a=t.find('>rtp-hdrext[xmlns="urn:xmpp:jingle:apps:rtp:rtp-hdrext:0"]')).each(function(){n+="a=extmap:"+this.getAttribute("id")+" "+this.getAttribute("uri")+"\r\n"}),e.find('>transport[xmlns="urn:xmpp:jingle:transports:ice-udp:1"]>candidate').each(function(){var e=this.getAttribute("protocol");e="string"==typeof e?e.toLowerCase():"",r.removeTcpCandidates&&("tcp"===e||"ssltcp"===e)||r.removeUdpCandidates&&"udp"===e||(r.failICE&&this.setAttribute("ip","1.1.1.1"),n+=i.a.candidateFromJingle(this))}),e.find('description>ssrc-group[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]').each(function(){var e=this.getAttribute("semantics"),t=$(this).find(">source").map(function(){return this.getAttribute("ssrc")}).get();t.length&&(n+="a=ssrc-group:"+e+" "+t.join(" ")+"\r\n")}),(a=e.find('description>source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]')).each(function(){var e=this.getAttribute("ssrc");$(this).find(">parameter").each(function(){var t=this.getAttribute("name"),r=this.getAttribute("value");r=i.a.filterSpecialChars(r),n+="a=ssrc:"+e+" "+t,r&&r.length&&(n+=":"+r),n+="\r\n"})}),n}},function(e,t,n){"use strict";n.r(t),n.d(t,"AUTHENTICATION_REQUIRED",function(){return r}),n.d(t,"CHAT_ERROR",function(){return i}),n.d(t,"CONFERENCE_DESTROYED",function(){return o}),n.d(t,"CONFERENCE_MAX_USERS",function(){return a}),n.d(t,"CONNECTION_ERROR",function(){return s}),n.d(t,"NOT_ALLOWED_ERROR",function(){return c}),n.d(t,"FOCUS_DISCONNECTED",function(){return u}),n.d(t,"FOCUS_LEFT",function(){return d}),n.d(t,"GRACEFUL_SHUTDOWN",function(){return l}),n.d(t,"ICE_FAILED",function(){return h}),n.d(t,"INCOMPATIBLE_SERVER_VERSIONS",function(){return p}),n.d(t,"OFFER_ANSWER_FAILED",function(){return f}),n.d(t,"PASSWORD_NOT_SUPPORTED",function(){return m}),n.d(t,"PASSWORD_REQUIRED",function(){return v}),n.d(t,"RESERVATION_ERROR",function(){return g}),n.d(t,"VIDEOBRIDGE_NOT_AVAILABLE",function(){return y});var r="conference.authenticationRequired",i="conference.chatError",o="conference.destroyed",a="conference.max_users",s="conference.connectionError",c="conference.connectionError.notAllowed",u="conference.focusDisconnected",d="conference.focusLeft",l="conference.gracefulShutdown",h="conference.iceFailed",p="conference.incompatible_server_versions",f="conference.offerAnswerFailed",m="conference.passwordNotSupported",v="conference.passwordRequired",g="conference.reservationError",y="conference.videobridgeNotAvailable"},function(e,t,n){"use strict";var r,i="object"==typeof Reflect?Reflect:null,o=i&&"function"==typeof i.apply?i.apply:function(e,t,n){return Function.prototype.apply.call(e,t,n)};r=i&&"function"==typeof i.ownKeys?i.ownKeys:Object.getOwnPropertySymbols?function(e){return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e))}:function(e){return Object.getOwnPropertyNames(e)};var a=Number.isNaN||function(e){return e!=e};function s(){s.init.call(this)}e.exports=s,s.EventEmitter=s,s.prototype._events=void 0,s.prototype._eventsCount=0,s.prototype._maxListeners=void 0;var c=10;function u(e){return void 0===e._maxListeners?s.defaultMaxListeners:e._maxListeners}function d(e,t,n,r){var i,o,a,s;if("function"!=typeof n)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof n);if(void 0===(o=e._events)?(o=e._events=Object.create(null),e._eventsCount=0):(void 0!==o.newListener&&(e.emit("newListener",t,n.listener?n.listener:n),o=e._events),a=o[t]),void 0===a)a=o[t]=n,++e._eventsCount;else if("function"==typeof a?a=o[t]=r?[n,a]:[a,n]:r?a.unshift(n):a.push(n),(i=u(e))>0&&a.length>i&&!a.warned){a.warned=!0;var c=new Error("Possible EventEmitter memory leak detected. "+a.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");c.name="MaxListenersExceededWarning",c.emitter=e,c.type=t,c.count=a.length,s=c,console&&console.warn&&console.warn(s)}return e}function l(){for(var e=[],t=0;t0&&(a=t[0]),a instanceof Error)throw a;var s=new Error("Unhandled error."+(a?" ("+a.message+")":""));throw s.context=a,s}var c=i[e];if(void 0===c)return!1;if("function"==typeof c)o(c,this,t);else{var u=c.length,d=m(c,u);for(n=0;n=0;o--)if(n[o]===t||n[o].listener===t){a=n[o].listener,i=o;break}if(i<0)return this;0===i?n.shift():(function(e,t){for(;t+1=0;r--)this.removeListener(e,t[r]);return this},s.prototype.listeners=function(e){return p(this,e,!0)},s.prototype.rawListeners=function(e){return p(this,e,!1)},s.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):f.call(e,t)},s.prototype.listenerCount=f,s.prototype.eventNames=function(){return this._eventsCount>0?r(this._events):[]}},function(e,t,n){"use strict";n.r(t),n.d(t,"DETECTOR_STATE_CHANGE",function(){return r}),n.d(t,"AUDIO_INPUT_STATE_CHANGE",function(){return i}),n.d(t,"NO_AUDIO_INPUT",function(){return o}),n.d(t,"VAD_NOISY_DEVICE",function(){return a}),n.d(t,"VAD_REPORT_PUBLISHED",function(){return s}),n.d(t,"VAD_SCORE_PUBLISHED",function(){return c}),n.d(t,"VAD_TALK_WHILE_MUTED",function(){return u});var r="detector_state_change",i="audio_input_state_changed",o="no_audio_input_detected",a="detection.vad_noise_device",s="vad-report-published",c="detection.vad_score_published",u="detection.vad_talk_while_muted"},function(e,t,n){var r=n(140),i=n(141);t.write=i,t.parse=r.parse,t.parseFmtpConfig=r.parseFmtpConfig,t.parseParams=r.parseParams,t.parsePayloads=r.parsePayloads,t.parseRemoteCandidates=r.parseRemoteCandidates,t.parseImageAttributes=r.parseImageAttributes,t.parseSimulcastStreamList=r.parseSimulcastStreamList},function(e,t,n){"use strict";n.r(t),n.d(t,"STATUS_AVAILABLE",function(){return r}),n.d(t,"STATUS_UNDEFINED",function(){return i}),n.d(t,"STATUS_BUSY",function(){return o}),n.d(t,"STATE_ON",function(){return a}),n.d(t,"STATE_OFF",function(){return s}),n.d(t,"STATE_PENDING",function(){return c}),n.d(t,"STATE_RETRYING",function(){return u}),n.d(t,"STATE_FAILED",function(){return d}),n.d(t,"ERROR_NO_CONNECTION",function(){return l}),n.d(t,"ERROR_SESSION_EXISTS",function(){return h});var r="available",i="undefined",o="busy",a="on",s="off",c="pending",u="retrying",d="failed",l="error_no_connection",h="error_session_already_exists"},function(e,t,n){"use strict";n.d(t,"a",function(){return o});var r=n(20),i=n.n(r),o=(function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:new i.a;_classCallCheck(this,e),this.eventEmitter=t,this.addEventListener=this.on=this.addListener,this.removeEventListener=this.off=this.removeListener}return _createClass(e,[{key:"addListener",value:function(e,t){var n=this;return this.eventEmitter.addListener(e,t),function(){return n.removeEventListener(e,t)}}},{key:"removeListener",value:function(e,t){this.eventEmitter.removeListener(e,t)}}]),e})()},function(e,t,n){"use strict";n.r(t),n.d(t,"CONNECTION_DISCONNECTED",function(){return r}),n.d(t,"CONNECTION_ESTABLISHED",function(){return i}),n.d(t,"CONNECTION_FAILED",function(){return o}),n.d(t,"WRONG_STATE",function(){return a});var r="connection.connectionDisconnected",i="connection.connectionEstablished",o="connection.connectionFailed",a="connection.wrongState"},function(e,t,n){"use strict";n.d(t,"a",function(){return r}),n.d(t,"b",function(){return i}),n.d(t,"c",function(){return o}),n.d(t,"d",function(){return a});var r="statistics.audioLevel",i="statistics.before_disposed",o="statistics.byte_sent_stats",a="statistics.connectionstats"},function(e,t,n){"use strict";n.d(t,"b",function(){return i}),n.d(t,"c",function(){return o}),n.d(t,"a",function(){return c});var r=n(22);function i(e){return parseInt(e.ssrcs.split(" ")[0],10)}function o(e){return parseInt(e.ssrcs.split(" ")[1],10)}function a(e){return e.ssrcs?e.ssrcs.map(function(e){return e.id}).filter(function(e,t,n){return n.indexOf(e)===t}).length:0}var s=(function(){function e(t){if(_classCallCheck(this,e),!t)throw new Error("mLine is undefined");this.mLine=t}return _createClass(e,[{key:"getSSRCAttrValue",value:function(e,t){var n=this.ssrcs.find(function(n){return n.id===e&&n.attribute===t});return n&&n.value}},{key:"removeSSRC",value:function(e){this.mLine.ssrcs&&this.mLine.ssrcs.length&&(this.mLine.ssrcs=this.mLine.ssrcs.filter(function(t){return t.id!==e}))}},{key:"addSSRCAttribute",value:function(e){this.ssrcs.push(e)}},{key:"findGroup",value:function(e,t){return this.ssrcGroups.find(function(n){return n.semantics===e&&(!t||t===n.ssrcs)})}},{key:"findGroups",value:function(e){return this.ssrcGroups.filter(function(t){return t.semantics===e})}},{key:"findGroupByPrimarySSRC",value:function(e,t){return this.ssrcGroups.find(function(n){return n.semantics===e&&i(n)===t})}},{key:"findSSRCByMSID",value:function(e){return this.ssrcs.find(function(t){return"msid"===t.attribute&&(null===e||t.value===e)})}},{key:"getSSRCCount",value:function(){return a(this.mLine)}},{key:"containsAnySSRCGroups",value:function(){return void 0!==this.mLine.ssrcGroups}},{key:"getPrimaryVideoSsrc",value:function(){var e=this.mLine.type;if("video"!==e)throw new Error("getPrimarySsrc doesn't work with '"+e+"'");if(1===a(this.mLine))return this.mLine.ssrcs[0].id;if(this.mLine.ssrcGroups){var t=this.findGroup("SIM");if(t)return i(t);var n=this.findGroup("FID");if(n)return i(n);var r=this.findGroup("FEC-FR");if(r)return i(r)}}},{key:"getRtxSSRC",value:function(e){var t=this.findGroupByPrimarySSRC("FID",e);return t&&o(t)}},{key:"getSSRCs",value:function(){return this.ssrcs.map(function(e){return e.id}).filter(function(e,t,n){return n.indexOf(e)===t})}},{key:"getPrimaryVideoSSRCs",value:function(){var e=this.mLine.type;if("video"!==e)throw new Error("getPrimaryVideoSSRCs doesn't work with "+e);var t=this.getSSRCs(),n=this.ssrcGroups,r=Array.isArray(n),i=0;for(n=r?n:n["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var a;if(r){if(i>=n.length)break;a=n[i++]}else{if((i=n.next()).done)break;a=i.value}var s=a;if("FID"===s.semantics||"FEC-FR"===s.semantics){var c=o(s);t.splice(t.indexOf(c),1)}}return t}},{key:"dumpSSRCGroups",value:function(){return JSON.stringify(this.mLine.ssrcGroups)}},{key:"removeGroupsWithSSRC",value:function(e){this.mLine.ssrcGroups&&(this.mLine.ssrcGroups=this.mLine.ssrcGroups.filter(function(t){return-1===t.ssrcs.indexOf(""+e)}))}},{key:"removeGroupsBySemantics",value:function(e){this.mLine.ssrcGroups&&(this.mLine.ssrcGroups=this.mLine.ssrcGroups.filter(function(t){return t.semantics!==e}))}},{key:"replaceSSRC",value:function(e,t){this.mLine.ssrcs&&this.mLine.ssrcs.forEach(function(n){n.id===e&&(n.id=t)})}},{key:"addSSRCGroup",value:function(e){this.ssrcGroups.push(e)}},{key:"ssrcs",get:function(){return this.mLine.ssrcs||(this.mLine.ssrcs=[]),this.mLine.ssrcs},set:function(e){this.mLine.ssrcs=e}},{key:"direction",get:function(){return this.mLine.direction},set:function(e){this.mLine.direction=e}},{key:"ssrcGroups",get:function(){return this.mLine.ssrcGroups||(this.mLine.ssrcGroups=[]),this.mLine.ssrcGroups},set:function(e){this.mLine.ssrcGroups=e}}]),e})(),c=(function(){function e(t){_classCallCheck(this,e),this.parsedSDP=r.parse(t)}return _createClass(e,[{key:"selectMedia",value:function(e){var t=this.parsedSDP.media.find(function(t){return t.type===e});return t?new s(t):null}},{key:"toRawSDP",value:function(){return r.write(this.parsedSDP)}}]),e})()},function(e,t,n){"use strict";n.r(t),n.d(t,"LOCAL_STATS_UPDATED",function(){return r}),n.d(t,"REMOTE_STATS_UPDATED",function(){return i});var r="cq.local_stats_updated",i="cq.remote_stats_updated"},function(e,t,n){"use strict";function r(e){var t=e;return e>=Number.MAX_SAFE_INTEGER&&(t=0),t+1}function i(e){return e.length>0?e.reduce(function(e,t){return e+t})/e.length:0}function o(e){return e.filter(function(e){return e>=0})}n.d(t,"c",function(){return r}),n.d(t,"a",function(){return i}),n.d(t,"b",function(){return o})},function(e,t,n){"use strict";n.d(t,"a",function(){return r});var r={ACCEPT:"session-accept",CONNECTION_ERROR:"connection-error-encountered",INITIATE:"session-initiate",TERMINATE:"session-terminate",TRANSPORT_INFO:"transport-info",UNAVAILABLE:"unavailable"}},function(e,t){e.exports={1080:{width:1920,height:1080,order:8},fullhd:{width:1920,height:1080,order:8},720:{width:1280,height:720,order:7},hd:{width:1280,height:720,order:7},960:{width:960,height:720,order:6},540:{width:960,height:540,order:5},qhd:{width:960,height:540,order:5},360:{width:640,height:360,order:4},640:{width:640,height:480,order:3},vga:{width:640,height:480,order:3},180:{width:320,height:180,order:2},320:{width:320,height:240,order:1}}},function(e,t,n){"use strict";n.d(t,"c",function(){return r}),n.d(t,"a",function(){return i}),n.d(t,"b",function(){return o});var r="pending",i="active",o="ended"},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return P});var r,i=n(1),o=n(11),a=n.n(o),s=n(4).getLogger(e),c="createOffer",u="createAnswer",d="setLocalDescription",l="setRemoteDescription",h="addIceCandidate",p="getUserMedia",f="iceConnectionFailure",m="applicationLog",v="fabricHold",g="fabricResume",y="audioMute",_="audioUnmute",S="videoPause",E="videoResume",b="screenShareStart",C="screenShareStop",T="dominantSpeaker",A="activeDeviceList",R="jitsi",k="error",w="event",I="mstWithUserID",P=(function(){function e(t,n){_classCallCheck(this,e),this.confID=n.confID,this.tpc=t,this.peerconnection=t.peerconnection,this.remoteUserID=n.remoteUserID||R,this.hasFabric=!1,e.fabrics.add(this),e.backendInitialized&&(this._addNewFabric(),1===e.fabrics.size&&e._emptyReportQueue(this))}return _createClass(e,null,[{key:"_addNewFabricCallback",value:function(t,n){e.backend&&"success"!==t&&s.error("Monitoring status: "+t+" msg: "+n)}},{key:"_initCallback",value:function(t,n){if(s.log("CallStats Status: err="+t+" msg="+n),"success"===t){e.backendInitialized=!0;var r=!1,i=null,o=e.fabrics.values(),a=Array.isArray(o),c=0;for(o=a?o:o["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var u;if(a){if(c>=o.length)break;u=o[c++]}else{if((c=o.next()).done)break;u=c.value}var d=u;d.hasFabric||(s.debug("addNewFabric - initCallback"),d._addNewFabric()&&(r=!0,i||(i=d)))}r&&e._emptyReportQueue(i)}}},{key:"_emptyReportQueue",value:function(t){var n=t.confID,r=t.peerconnection,i=e.reportsQueue,o=Array.isArray(i),a=0;for(i=o?i:i["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var s;if(o){if(a>=i.length)break;s=i[a++]}else{if((a=i.next()).done)break;s=a.value}var c=s;if(c.type===k){var u=c.data;e._reportError(t,u.type,u.error,u.pc||r)}else if(c.type===w){var d=c.data;e.backend.sendFabricEvent(c.pc||r,d.event,n,d.eventData)}else if(c.type===I){var l=c.data;e.backend.associateMstWithUserID(c.pc||r,l.callStatsId,n,l.ssrc,l.usageLabel,l.containerId)}}e.reportsQueue.length=0}},{key:"_reportError",value:function(t,n,r,i){var o=r;o||(s.warn("No error is passed!"),o=new Error("Unknown error")),e.backendInitialized&&t?e.backend.reportError(i,t.confID,n,o):e.reportsQueue.push({type:k,data:{error:o,pc:i,type:n}})}},{key:"_reportEvent",value:function(t,n,r){var i=t&&t.peerconnection,o=t&&t.confID;e.backendInitialized&&t?e.backend.sendFabricEvent(i,n,o,r):e.reportsQueue.push({confID:o,pc:i,type:w,data:{event:n,eventData:r}})}},{key:"_traceAndCatchBackendCalls",value:function(e){for(var t=["associateMstWithUserID","sendFabricEvent","sendUserFeedback"],n=function(t){var n=e[t];e[t]=function(){try{for(var t=arguments.length,r=new Array(t),i=0;i3?o-3:0),u=3;u0&&void 0!==arguments[0]?arguments[0]:(function(){return function e(){_classCallCheck(this,e)}})();return(function(t){function n(){var e,t;_classCallCheck(this,n);for(var r=arguments.length,i=new Array(r),o=0;o0&&void 0!==arguments[0]?arguments[0]:{},n=arguments.length>1?arguments[1]:void 0,r=arguments.length>2?arguments[2]:void 0,o=window.performance.now(),a=i.Strophe.getStatusString(n).toLowerCase();if(this.connectionTimes[a]=o,C.log("(TIME) Strophe "+a+(r?"["+r+"]":"")+":\t",o),this.eventEmitter.emit(E.a.CONNECTION_STATUS_CHANGED,t,n,r),n===i.Strophe.Status.CONNECTED||n===i.Strophe.Status.ATTACHED){(this.options.useStunTurn||this.options.p2p&&this.options.p2p.useStunTurn)&&this.connection.jingle.getStunAndTurnCredentials(),C.info("My Jabber ID: "+this.connection.jid),this._resetState();var u=this.connection.domain;this.caps.getFeaturesAndIdentities(u).then(function(t){var n=t.features,r=t.identities;n.has(i.Strophe.NS.PING)?(e._pingSupported=!0,e.connection.ping.startInterval(u)):C.warn("Ping NOT supported by "+u),r.forEach(function(t){"speakerstats"===t.type&&(e.speakerStatsComponentAddress=t.name),"conference_duration"===t.type&&(e.conferenceDurationComponentAddress=t.name)}),(e.speakerStatsComponentAddress||e.conferenceDurationComponentAddress)&&e.connection.addHandler(e._onPrivateMessage.bind(e),null,"message",null,null)}).catch(function(e){_.a.callErrorHandler(new Error("Feature discovery error: "+e)),C.error("Feature discovery error",e)}),t.password&&(this.authenticatedUser=!0),this.connection&&this.connection.connected&&i.Strophe.getResourceFromJid(this.connection.jid)&&this.eventEmitter.emit(c.CONNECTION_ESTABLISHED,i.Strophe.getResourceFromJid(this.connection.jid))}else if(n===i.Strophe.Status.CONNFAIL)"x-strophe-bad-non-anon-jid"===r?this.anonymousConnectionFailed=!0:this.connectionFailed=!0,this.lastErrorMsg=r,"giving-up"===r&&this.eventEmitter.emit(c.CONNECTION_FAILED,s.OTHER_ERROR,r);else if(n===i.Strophe.Status.ERROR)this.lastErrorMsg=r;else if(n===i.Strophe.Status.DISCONNECTED){this.connection.ping.stopInterval();var d=Boolean(this.disconnectInProgress),l=r||this.lastErrorMsg;if(this.anonymousConnectionFailed)this.eventEmitter.emit(c.CONNECTION_FAILED,s.PASSWORD_REQUIRED);else if(this.connectionFailed)this.eventEmitter.emit(c.CONNECTION_FAILED,s.OTHER_ERROR,l,void 0,this._getConnectionFailedReasonDetails());else if(d)this.eventEmitter.emit(c.CONNECTION_DISCONNECTED,l);else{C.error("XMPP connection dropped!");var h=i.Strophe.getLastErrorStatus();h>=500&&h<600?this.eventEmitter.emit(c.CONNECTION_FAILED,s.SERVER_ERROR,l||"server-error",void 0,this._getConnectionFailedReasonDetails()):this.eventEmitter.emit(c.CONNECTION_FAILED,s.CONNECTION_DROPPED_ERROR,l||"connection-dropped-error",void 0,this._getConnectionFailedReasonDetails())}}else n===i.Strophe.Status.AUTHFAIL&&this.eventEmitter.emit(c.CONNECTION_FAILED,s.PASSWORD_REQUIRED,r,t)}},{key:"_connect",value:function(e,t){this._resetState(),this.connection.connect(e,t,this.connectionHandler.bind(this,{jid:e,password:t}))}},{key:"attach",value:function(e){this._resetState();var t=this.connectionTimes.attaching=window.performance.now();C.log("(TIME) Strophe Attaching:\t",t),this.connection.attach(e.jid,e.sid,parseInt(e.rid,10)+1,this.connectionHandler.bind(this,{jid:e.jid,password:e.password}))}},{key:"_resetState",value:function(){this.anonymousConnectionFailed=!1,this.connectionFailed=!1,this.lastErrorMsg=void 0,this.disconnectInProgress=void 0}},{key:"connect",value:function(e,t){if(!e){var n=this.options.hosts,r=n.anonymousdomain,i=n.domain,o=r||i,a=window.location;if(r){var s=a&&a.search;(s&&-1!==s.indexOf("login=true")||this.token)&&(o=i)}e=o||a&&a.hostname}return this._connect(e,t)}},{key:"createRoom",value:function(e,t,n){var r=e+"@"+this.options.hosts.muc+"/",i=n?n(this.connection.jid,this.authenticatedUser):a.a.randomHexString(8).toLowerCase();return C.info("JID "+this.connection.jid+" using MUC nickname "+i),r+=i,this.connection.emuc.createRoom(r,null,t)}},{key:"getJid",value:function(){return this.connection.jid}},{key:"getJingleLog",value:function(){var e=this.connection.jingle;return e?e.getLog():{}}},{key:"getXmppLog",value:function(){return(this.connection.logger||{}).log||null}},{key:"dial",value:function(){var e;(e=this.connection.rayo).dial.apply(e,arguments)}},{key:"ping",value:function(e){var t=this;return new Promise(function(n,r){t.isPingSupported()?t.connection.ping.ping(t.connection.domain,n,r,e):r("PING operation is not supported by the server")})}},{key:"getSessions",value:function(){return this.connection.jingle.sessions}},{key:"disconnect",value:function(e){var t=this;return this.disconnectInProgress?this.disconnectInProgress:this.connection?(this.disconnectInProgress=new Promise(function(e){t.eventEmitter.on(E.a.CONNECTION_STATUS_CHANGED,function n(r,o){o===i.Strophe.Status.DISCONNECTED&&(e(),t.eventEmitter.removeListener(E.a.CONNECTION_STATUS_CHANGED,n))})}),this._cleanupXmppConnection(e),this.disconnectInProgress):Promise.resolve()}},{key:"_cleanupXmppConnection",value:function(e){if(!this.connection.isUsingWebSocket&&this.connection.flush(),!this.connection.isUsingWebSocket&&null!=e){var t=e.type;if(("beforeunload"===t||"unload"===t)&&(this.connection.options.sync=!0,this.connection.sendUnavailableBeacon()))return}this.connection.disconnect(),!0!==this.connection.options.sync&&this.connection.flush()}},{key:"_initStrophePlugins",value:function(){var e={jvb:{iceServers:[]},p2p:{iceServers:[]}},t=this.options.p2p&&this.options.p2p.stunServers||T;Array.isArray(t)&&(C.info("P2P STUN servers: ",t),e.p2p.iceServers=t),this.options.p2p&&this.options.p2p.iceTransportPolicy&&(C.info("P2P ICE transport policy: ",this.options.p2p.iceTransportPolicy),e.p2p.iceTransportPolicy=this.options.p2p.iceTransportPolicy),this.connection.addConnectionPlugin("emuc",new d.a(this)),this.connection.addConnectionPlugin("jingle",new l.a(this,this.eventEmitter,e)),this.connection.addConnectionPlugin("ping",new p.a(this)),this.connection.addConnectionPlugin("rayo",new f.a)}},{key:"_getConnectionFailedReasonDetails",value:function(){var e={};if(this.options.deploymentInfo&&this.options.deploymentInfo.shard&&this.connection.lastResponseHeaders){var t={};this.connection.lastResponseHeaders.trim().split(/[\r\n]+/).forEach(function(e){var n=e.split(": "),r=n.shift(),i=n.join(": ");t[r]=i}),e.shard_changed=this.options.deploymentInfo.shard!==t["x-jitsi-shard"]}return e.suspend_time=this.connection.ping.getPingSuspendTime(),e.time_since_last_success=this.connection.getTimeSinceLastSuccess(),e}},{key:"sendDominantSpeakerEvent",value:function(e){if(this.speakerStatsComponentAddress&&e){var t=Object(i.$msg)({to:this.speakerStatsComponentAddress});t.c("speakerstats",{xmlns:"http://jitsi.org/jitmeet",room:e}).up(),this.connection.send(t)}}},{key:"tryParseJSONAndVerify",value:function(e){try{var t=JSON.parse(e);if(t&&"object"==typeof t){var n=t[A];if(void 0!==n)return t;C.debug("parsing valid json but does not have correct structure","topic: ",n)}}catch(e){return!1}return!1}},{key:"_onPrivateMessage",value:function(e){var t=e.getAttribute("from");if(t===this.speakerStatsComponentAddress||t===this.conferenceDurationComponentAddress){var n=$(e).find(">json-message").text(),r=this.tryParseJSONAndVerify(n);return r&&"speakerstats"===r[A]&&r.users&&this.eventEmitter.emit(E.a.SPEAKER_STATS_RECEIVED,r.users),r&&"conference_duration"===r[A]&&r.created_timestamp&&this.eventEmitter.emit(E.a.CONFERENCE_TIMESTAMP_RECEIVED,r.created_timestamp),!0}}}]),t})(v.a)}).call(this,"modules/xmpp/xmpp.js")},function(e,t,n){"use strict";n.d(t,"a",function(){return r}),n.d(t,"b",function(){return i});var r="signaling.peerMuted",i="signaling.peerVideoType"},function(e,t,n){"use strict";n.r(t),n.d(t,"CONNECTION_DROPPED_ERROR",function(){return r}),n.d(t,"OTHER_ERROR",function(){return i}),n.d(t,"PASSWORD_REQUIRED",function(){return o}),n.d(t,"SERVER_ERROR",function(){return a});var r="connection.droppedError",i="connection.otherError",o="connection.passwordRequired",a="connection.serverError"},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return u});var r=n(4),i=n(3),o=(n(145),n(24)),a=n(97),s=n(98),c=Object(r.getLogger)(e),u=(function(e){function t(e){var n,r=e.enableWebsocketResume,o=e.websocketKeepAlive,a=e.serviceUrl;return _classCallCheck(this,t),(n=_possibleConstructorReturn(this,_getPrototypeOf(t).call(this)))._options={enableWebsocketResume:void 0===r||r,websocketKeepAlive:void 0===o?24e4:Number(o)},n._resumeRetryN=0,n._stropheConn=new i.Strophe.Connection(a),n._usesWebsocket=a.startsWith("ws:")||a.startsWith("wss:"),n._stropheConn.maxRetries=3,n._lastSuccessTracker=new s.a,n._lastSuccessTracker.startTracking(n._stropheConn),n._deferredIQs=[],n}return _inherits(t,e),_createClass(t,null,[{key:"Events",get:function(){return{CONN_STATUS_CHANGED:"CONN_STATUS_CHANGED"}}},{key:"Status",get:function(){return i.Strophe.Status}}]),_createClass(t,[{key:"addConnectionPlugin",value:function(e,t){this[e]=t,t.init(this)}},{key:"addHandler",value:function(){var e;(e=this._stropheConn).addHandler.apply(e,arguments)}},{key:"attach",value:function(e,t,n,r){for(var i,o=arguments.length,a=new Array(o>4?o-4:0),s=4;s3?i-3:0),a=3;a2?o-2:0),s=2;s=e.length)break;r=e[n++]}else{if((n=e.next()).done)break;r=n.value}r.reject(new Error("disconnect"))}this._deferredIQs=[]}},{key:"closeWebsocket",value:function(){this._stropheConn._proto&&this._stropheConn._proto.socket&&this._stropheConn._proto.socket.close()}},{key:"disconnect",value:function(){var e;clearTimeout(this._resumeTimeout),clearTimeout(this._wsKeepAlive),this._clearDeferredIQs(),(e=this._stropheConn).disconnect.apply(e,arguments)}},{key:"flush",value:function(){var e;(e=this._stropheConn).flush.apply(e,arguments)}},{key:"getTimeSinceLastSuccess",value:function(){return this._lastSuccessTracker.getTimeSinceLastSuccess()}},{key:"_maybeEnableStreamResume",value:function(){if(this._options.enableWebsocketResume){var e=this._stropheConn.streamManagement;this.isUsingWebSocket?e?e.isSupported()?e.getResumeToken()||(c.info("Enabling XEP-0198 stream management"),e.enable(!0)):c.warn("Stream resume enabled, but XEP-0198 is not supported by the server"):c.warn("Stream resume enabled, but Strophe streamManagement plugin is not installed"):c.warn("Stream resume enabled, but WebSockets are not enabled")}}},{key:"_maybeStartWSKeepAlive",value:function(){var e=this,t=this._options.websocketKeepAlive;if(this._usesWebsocket&&t>0){this._wsKeepAlive||c.info("WebSocket keep alive interval: "+t+"ms"),clearTimeout(this._wsKeepAlive);var n=.2*t+.8*Math.random()*t;c.debug("Scheduling next WebSocket keep-alive in "+n+"ms"),this._wsKeepAlive=setTimeout(function(){var t=e.service.replace("wss://","https://").replace("ws://","http://");fetch(t).catch(function(e){c.error("Websocket Keep alive failed for url: "+t,{error:e})}).then(function(){return e._maybeStartWSKeepAlive()})},n)}}},{key:"_processDeferredIQs",value:function(){var e=this,t=function(t){if(t.iq){clearTimeout(t.timeout);var n=Date.now()-t.start;e.sendIQ(t.iq,function(e){return t.resolve(e)},function(e){return t.reject(e)},n)}},n=this._deferredIQs,r=Array.isArray(n),i=0;for(n=r?n:n["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var o;if(r){if(i>=n.length)break;o=n[i++]}else{if((i=n.next()).done)break;o=i.value}t(o)}this._deferredIQs=[]}},{key:"send",value:function(e){if(!this.connected)throw new Error("Not connected");this._stropheConn.send(e)}},{key:"sendIQ",value:function(e,t,n,r){if(this.connected)return this._stropheConn.sendIQ(e,t,n,r);n("Not connected")}},{key:"sendIQ2",value:function(e,t){var n=this,r=t.timeout;return new Promise(function(t,i){if(n.connected)n.sendIQ(e,function(e){return t(e)},function(e){return i(e)});else{var o={iq:e,resolve:t,reject:i,start:Date.now(),timeout:setTimeout(function(){o.iq=void 0,i(void 0)},r)};n._deferredIQs.push(o)}})}},{key:"sendPresence",value:function(e,t,n,r){this.connected?this._stropheConn.sendPresence(e,t,n,r):n("Not connected")}},{key:"sendUnavailableBeacon",value:function(){if(!navigator.sendBeacon||this._stropheConn.disconnecting||!this._stropheConn.connected)return!1;this._stropheConn._changeConnectStatus(i.Strophe.Status.DISCONNECTING),this._stropheConn.disconnecting=!0;var e=this._stropheConn._proto._buildBody().attrs({type:"terminate"}),t=Object(i.$pres)({xmlns:i.Strophe.NS.CLIENT,type:"unavailable"});e.cnode(t.tree());var n=navigator.sendBeacon(-1===this.service.indexOf("https://")?"https:"+this.service:this.service,i.Strophe.serialize(e.tree()));return c.info("Successfully send unavailable beacon "+n),this._stropheConn._proto._abortAllRequests(),this._stropheConn._doDisconnect(),!0}},{key:"_tryResumingConnection",value:function(){var e=this,t=this._stropheConn.streamManagement,n=t&&t.getResumeToken();if(n){clearTimeout(this._resumeTimeout),this._resumeRetryN=Math.min(3,this._resumeRetryN+1);var r=Object(a.a)(this._resumeRetryN,1500,3);return c.info("Will try to resume the XMPP connection in "+r+"ms"),this._resumeTimeout=setTimeout(function(){c.info("Trying to resume the XMPP connection");var r=new URL(e._stropheConn.service),i=r.search;i+=-1===i.indexOf("?")?"?previd="+n:"&previd="+n,r.search=i,e._stropheConn.service=r.toString(),t.resume()},r),!0}return!1}},{key:"connected",get:function(){return this._status===i.Strophe.Status.CONNECTED||this._status===i.Strophe.Status.ATTACHED}},{key:"disco",get:function(){return this._stropheConn.disco}},{key:"disconnecting",get:function(){return!0===this._stropheConn.disconnecting}},{key:"domain",get:function(){return this._stropheConn.domain}},{key:"isUsingWebSocket",get:function(){return this._usesWebsocket}},{key:"jid",get:function(){return this._stropheConn.jid}},{key:"lastResponseHeaders",get:function(){return this._stropheConn._proto&&this._stropheConn._proto.lastResponseHeaders}},{key:"logger",get:function(){return this._stropheConn.logger}},{key:"options",get:function(){return this._stropheConn.options}},{key:"service",get:function(){return this._stropheConn.service}},{key:"status",get:function(){return this._status}}]),t})(o.a)}).call(this,"modules/xmpp/XmppConnection.js")},function(e,t){e.exports={ENVIRONMENT:"environment",USER:"user"}},function(e,t,n){"use strict";(function(e){var r=n(17),i=n(14),o=n(1);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var s=n(4).getLogger(e),c=n(11),u=!1,d=!1,l=null,h={intChromeExtPromise:null,obtainStream:null,init:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{desktopSharingChromeDisabled:!1,desktopSharingChromeExtId:null,desktopSharingFirefoxDisabled:!1},t=arguments.length>1?arguments[1]:void 0;this.options=e,l=t,this.obtainStream=this._createObtainStreamMethod(e),this.obtainStream||s.info("Desktop sharing disabled")},_createObtainStreamMethod:function(e){var t=this;return o.a.isNWJS()?function(e,t,n){window.JitsiMeetNW.obtainDesktopStream(t,function(e,t){var o;o=e&&"InvalidStateError"===e.name?new r.a(i.CHROME_EXTENSION_USER_CANCELED):new r.a(e,t,["desktop"]),"function"==typeof n&&n(o)})}:o.a.isElectron()?this.obtainScreenOnElectron:o.a.isChrome()||o.a.isOpera()?o.a.supportsGetDisplayMedia()&&!e.desktopSharingChromeDisabled?this.obtainScreenFromGetDisplayMedia:e.desktopSharingChromeDisabled||!e.desktopSharingChromeExtId?null:(s.info("Using Chrome extension for desktop sharing"),this.intChromeExtPromise=(function(e){return(function(e){0===$("link[rel=chrome-webstore-item]").length&&$("head").append(''),$("link[rel=chrome-webstore-item]").attr("href",p(e))})(e),new Promise(function(t){f(function(e,n){u=e,d=n,s.info("Chrome extension installed: "+u+" updateRequired: "+d),t()},e)})})(e).then(function(){t.intChromeExtPromise=null}),this.obtainScreenFromExtension):o.a.isFirefox()?e.desktopSharingFirefoxDisabled?null:o.a.supportsGetDisplayMedia()?this.obtainScreenFromGetDisplayMedia:this.obtainScreenOnFirefox:o.a.isSafari()&&o.a.supportsGetDisplayMedia()?this.obtainScreenFromGetDisplayMedia:(s.log("Screen sharing not supported by the current browser: ",o.a.getName()),null)},isSupported:function(){return null!==this.obtainStream},obtainScreenOnFirefox:function(e,t,n){!(function(e,t,n){l(["screen"],e).then(function(e){return t({stream:e})},n)})(e.gumOptions,t,n)},obtainScreenOnElectron:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length>1?arguments[1]:void 0,n=arguments.length>2?arguments[2]:void 0;if(window.JitsiMeetScreenObtainer&&window.JitsiMeetScreenObtainer.openDesktopPicker){var o=e.desktopSharingSources,a=e.gumOptions;window.JitsiMeetScreenObtainer.openDesktopPicker({desktopSharingSources:o||this.options.desktopSharingChromeSources},function(e,r){return m({response:{streamId:e,streamType:r,screenShareAudio:arguments.length>2&&void 0!==arguments[2]&&arguments[2]},gumOptions:a},t,n)},function(e){return n(new r.a(i.ELECTRON_DESKTOP_PICKER_ERROR,e))})}else n(new r.a(i.ELECTRON_DESKTOP_PICKER_NOT_FOUND))},obtainScreenFromExtension:function(e,t,n){var o=this;if(null===this.intChromeExtPromise){var a=this.options,c=a.desktopSharingChromeExtId,l=a.desktopSharingChromeSources,h=e.gumOptions,p={desktopSharingChromeExtId:c,desktopSharingChromeSources:e.desktopSharingSources||l,gumOptions:h};u?(function(e,t,n){var o=p.desktopSharingChromeSources,a=p.desktopSharingChromeExtId,c=p.gumOptions;chrome.runtime.sendMessage(a,{getStream:!0,sources:o},function(e){if(e)s.log("Response from extension: ",e),m({response:e,gumOptions:c},t,n);else{var o=chrome.runtime.lastError;n(o instanceof Error?o:new r.a(i.CHROME_EXTENSION_GENERIC_ERROR,o))}})})(0,t,n):(d&&alert("Jitsi Desktop Streamer requires update. Changes will take effect after next Chrome restart."),this.handleExternalInstall(e,t,n))}else this.intChromeExtPromise.then(function(){o.obtainScreenFromExtension(e,t,n)})},handleExternalInstall:function(e,t,n,r){var i=p(this.options);e.listener("waitingForExtension",i),this.checkForChromeExtensionOnInterval(e,t,n,r)},checkForChromeExtensionOnInterval:function(e,t,n){var o=this;!1!==e.checkAgain()?(function(e,t,n){return new Promise(function(n,r){var i=1,o=window.setInterval(function(){f(function(e){e?(window.clearInterval(o),n()):0==--i&&(r(),window.clearInterval(o))},e)},t)})})(this.options,e.interval).then(function(){u=!0,e.listener("extensionFound"),o.obtainScreenFromExtension(e,t,n)}).catch(function(){o.checkForChromeExtensionOnInterval(e,t,n)}):n(new r.a(i.CHROME_EXTENSION_INSTALLATION_ERROR))},obtainScreenFromGetDisplayMedia:function(e,t,n){s.info("Using getDisplayMedia for screen sharing"),(navigator.getDisplayMedia?navigator.getDisplayMedia.bind(navigator):navigator.mediaDevices.getDisplayMedia.bind(navigator.mediaDevices))({video:!0,audio:!0}).then(function(n){var r;if(n&&n.getTracks()&&n.getTracks().length>0){var i=n.getVideoTracks()[0];i&&(r=i.applyConstraints(e.trackOptions))}else r=Promise.resolve();r.then(function(){return t({stream:n,sourceId:n.id})})}).catch(function(){return n(new r.a(i.CHROME_EXTENSION_USER_CANCELED))})}};function p(e){return"https://chrome.google.com/webstore/detail/"+e.desktopSharingChromeExtId}function f(e,t){"undefined"!=typeof chrome&&chrome&&chrome.runtime?chrome.runtime.sendMessage(t.desktopSharingChromeExtId,{getVersion:!0},function(n){if(!n||!n.version)return s.warn("Extension not installed?: ",chrome.runtime.lastError),void e(!1,!1);var r=n.version;s.log("Extension version is: "+r);var i=(function(e,t){try{for(var n=e.split("."),r=t.split("."),i=Math.max(n.length,r.length),o=0;ou}return!1}catch(e){return c.callErrorHandler(e),s.error("Failed to parse extension version",e),!0}})(t.desktopSharingChromeMinExtVersion,r);e(!i,i)}):e(!1,!1)}function m(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{response:{},gumOptions:{}},t=arguments.length>1?arguments[1]:void 0,n=arguments.length>2?arguments[2]:void 0,o=e.response||{},s=o.streamId,c=o.streamType,u=o.screenShareAudio,d=o.error;if(s){var h=(function(e){for(var t=1;t=i}},{key:"refreshConnectionStatusForAll",value:function(){var e=this.conference.getParticipants(),t=Array.isArray(e),n=0;for(e=t?e:e["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var r;if(t){if(n>=e.length)break;r=e[n++]}else{if((n=e.next()).done)break;r=n.value}var i=r;this.figureOutConnectionStatus(i.getId())}}},{key:"figureOutConnectionStatus",value:function(t){var n=this.conference.getParticipantById(t);if(n){var r=this.conference.isP2PActive(),i=this._isRestoringTimedout(t),o=0===this.rtc.getLastN(),s=n.isVideoMuted()||o,c=this.isVideoTrackFrozen(n),u=this.rtc.isInLastN(t),d=this.connStatusFromJvb[t];"boolean"!=typeof d&&(f.debug("Assuming connection active by JVB - no notification"),d=!0);var l=r?e._getNewStateForP2PMode(s,c):e._getNewStateForJvbMode(d,u,i,s,c);l!==g.RESTORING&&this._clearRestoringTimer(t),f.debug("Figure out conn status for "+t+", is video muted: "+s+" is active(jvb): "+d+" video track frozen: "+c+" p2p mode: "+r+" is in last N: "+u+" currentStatus => newStatus: "+n.getConnectionStatus()+" => "+l);var p=this.connectionStatusMap[t]||{};if(!("p2p"in p&&"connectionStatus"in p&&p.p2p===r&&p.connectionStatus===l)){var m=Date.now();if(this.maybeSendParticipantConnectionStatusEvent(t,m),this.connectionStatusMap[t]=h({},p,{connectionStatus:l,p2p:r,startedMs:m}),!("videoType"in this.connectionStatusMap[t])){var v=n.getTracksByMediaType(a.c);Array.isArray(v)&&0!==v.length&&(this.connectionStatusMap[t].videoType=v[0].videoType)}}this._changeConnectionStatus(n,l)}else f.debug("figure out conn status - no participant for: "+t)}},{key:"maybeSendParticipantConnectionStatusEvent",value:function(e,t){var n=this.connectionStatusMap[e];n&&"startedMs"in n&&"videoType"in n&&"connectionStatus"in n&&"p2p"in n&&(n.value=t-n.startedMs,d.a.sendAnalytics(Object(l.J)(n)))}},{key:"_onLastNChanged",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=Date.now();f.debug("leaving/entering lastN",e,t,n);var r=e,i=Array.isArray(r),o=0;for(r=i?r:r["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var a;if(i){if(o>=r.length)break;a=r[o++]}else{if((o=r.next()).done)break;a=o.value}var s=a;this.enteredLastNTimestamp.delete(s),this._clearRestoringTimer(s),this.figureOutConnectionStatus(s)}var c=t,u=Array.isArray(c),d=0;for(c=u?c:c["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var l;if(u){if(d>=c.length)break;l=c[d++]}else{if((d=c.next()).done)break;l=d.value}var h=l;this.enteredLastNTimestamp.set(h,n),this.figureOutConnectionStatus(h)}}},{key:"_clearRestoringTimer",value:function(e){var t=this.restoringTimers.get(e);t&&(clearTimeout(t),this.restoringTimers.delete(e))}},{key:"_isRestoringTimedout",value:function(e){var t=this,n=this.enteredLastNTimestamp.get(e);return!!(n&&Date.now()-n>=1e4)||(this.restoringTimers.get(e)||this.restoringTimers.set(e,setTimeout(function(){return t.figureOutConnectionStatus(e)},1e4)),!1)}},{key:"onUserLeft",value:function(e){this.maybeSendParticipantConnectionStatusEvent(e,Date.now()),delete this.connectionStatusMap[e]}},{key:"onTrackRtcMuted",value:function(e){var t=this,n=e.getParticipantId(),r=this.conference.getParticipantById(n);if(f.debug("Detector track RTC muted: "+n,Date.now()),r){if(this.rtcMutedTimestamp[n]=Date.now(),!r.isVideoMuted()){this.clearTimeout(n);var i=this._getVideoFrozenTimeout(n);this.trackTimers[n]=window.setTimeout(function(){f.debug("Set RTC mute timeout for: "+n+" of "+i+" ms"),t.clearTimeout(n),t.figureOutConnectionStatus(n)},i)}}else f.error("No participant for id: "+n)}},{key:"onTrackRtcUnmuted",value:function(e){var t=e.getParticipantId();f.debug("Detector track RTC unmuted: "+t,Date.now()),this.clearTimeout(t),this.clearRtcMutedTimestamp(t),this.figureOutConnectionStatus(t)}},{key:"onSignallingMuteChanged",value:function(e){var t=e.getParticipantId();f.debug("Detector on track signalling mute changed: "+t,e.isMuted()),this.figureOutConnectionStatus(t)}},{key:"onTrackVideoTypeChanged",value:function(e,t){var n=e.getParticipantId(),r=Date.now();this.maybeSendParticipantConnectionStatusEvent(n,r),this.connectionStatusMap[n]=h({},this.connectionStatusMap[n]||{},{videoType:t,startedMs:r})}}]),e})()}).call(this,"modules/connectivity/ParticipantConnectionStatus.js")},function(e,t,n){"use strict";var r={generateIdentifier:function(){return Math.random().toString(36).substr(2,10)}};r.localCName=r.generateIdentifier(),r.splitLines=function(e){return e.trim().split("\n").map(function(e){return e.trim()})},r.splitSections=function(e){return e.split("\nm=").map(function(e,t){return(t>0?"m="+e:e).trim()+"\r\n"})},r.getDescription=function(e){var t=r.splitSections(e);return t&&t[0]},r.getMediaSections=function(e){var t=r.splitSections(e);return t.shift(),t},r.matchPrefix=function(e,t){return r.splitLines(e).filter(function(e){return 0===e.indexOf(t)})},r.parseCandidate=function(e){for(var t,n={foundation:(t=0===e.indexOf("a=candidate:")?e.substring(12).split(" "):e.substring(10).split(" "))[0],component:parseInt(t[1],10),protocol:t[2].toLowerCase(),priority:parseInt(t[3],10),ip:t[4],address:t[4],port:parseInt(t[5],10),type:t[7]},r=8;r0?t[0].split("/")[1]:"sendrecv",uri:t[1]}},r.writeExtmap=function(e){return"a=extmap:"+(e.id||e.preferredId)+(e.direction&&"sendrecv"!==e.direction?"/"+e.direction:"")+" "+e.uri+"\r\n"},r.parseFmtp=function(e){for(var t,n={},r=e.substr(e.indexOf(" ")+1).split(";"),i=0;i-1?(n.attribute=e.substr(t+1,r-t-1),n.value=e.substr(r+1)):n.attribute=e.substr(t+1),n},r.parseSsrcGroup=function(e){var t=e.substr(13).split(" ");return{semantics:t.shift(),ssrcs:t.map(function(e){return parseInt(e,10)})}},r.getMid=function(e){var t=r.matchPrefix(e,"a=mid:")[0];if(t)return t.substr(6)},r.parseFingerprint=function(e){var t=e.substr(14).split(" ");return{algorithm:t[0].toLowerCase(),value:t[1]}},r.getDtlsParameters=function(e,t){return{role:"auto",fingerprints:r.matchPrefix(e+t,"a=fingerprint:").map(r.parseFingerprint)}},r.writeDtlsParameters=function(e,t){var n="a=setup:"+t+"\r\n";return e.fingerprints.forEach(function(e){n+="a=fingerprint:"+e.algorithm+" "+e.value+"\r\n"}),n},r.parseCryptoLine=function(e){var t=e.substr(9).split(" ");return{tag:parseInt(t[0],10),cryptoSuite:t[1],keyParams:t[2],sessionParams:t.slice(3)}},r.writeCryptoLine=function(e){return"a=crypto:"+e.tag+" "+e.cryptoSuite+" "+("object"==typeof e.keyParams?r.writeCryptoKeyParams(e.keyParams):e.keyParams)+(e.sessionParams?" "+e.sessionParams.join(" "):"")+"\r\n"},r.parseCryptoKeyParams=function(e){if(0!==e.indexOf("inline:"))return null;var t=e.substr(7).split("|");return{keyMethod:"inline",keySalt:t[0],lifeTime:t[1],mkiValue:t[2]?t[2].split(":")[0]:void 0,mkiLength:t[2]?t[2].split(":")[1]:void 0}},r.writeCryptoKeyParams=function(e){return e.keyMethod+":"+e.keySalt+(e.lifeTime?"|"+e.lifeTime:"")+(e.mkiValue&&e.mkiLength?"|"+e.mkiValue+":"+e.mkiLength:"")},r.getCryptoParameters=function(e,t){return r.matchPrefix(e+t,"a=crypto:").map(r.parseCryptoLine)},r.getIceParameters=function(e,t){var n=r.matchPrefix(e+t,"a=ice-ufrag:")[0],i=r.matchPrefix(e+t,"a=ice-pwd:")[0];return n&&i?{usernameFragment:n.substr(12),password:i.substr(10)}:null},r.writeIceParameters=function(e){return"a=ice-ufrag:"+e.usernameFragment+"\r\na=ice-pwd:"+e.password+"\r\n"},r.parseRtpParameters=function(e){for(var t={codecs:[],headerExtensions:[],fecMechanisms:[],rtcp:[]},n=r.splitLines(e)[0].split(" "),i=3;i0?"9":"0",n+=" UDP/TLS/RTP/SAVPF ",n+=t.codecs.map(function(e){return void 0!==e.preferredPayloadType?e.preferredPayloadType:e.payloadType}).join(" ")+"\r\n",n+="c=IN IP4 0.0.0.0\r\n",n+="a=rtcp:9 IN IP4 0.0.0.0\r\n",t.codecs.forEach(function(e){n+=r.writeRtpMap(e),n+=r.writeFmtp(e),n+=r.writeRtcpFb(e)});var i=0;return t.codecs.forEach(function(e){e.maxptime>i&&(i=e.maxptime)}),i>0&&(n+="a=maxptime:"+i+"\r\n"),n+="a=rtcp-mux\r\n",t.headerExtensions&&t.headerExtensions.forEach(function(e){n+=r.writeExtmap(e)}),n},r.parseRtpEncodingParameters=function(e){var t,n=[],i=r.parseRtpParameters(e),o=-1!==i.fecMechanisms.indexOf("RED"),a=-1!==i.fecMechanisms.indexOf("ULPFEC"),s=r.matchPrefix(e,"a=ssrc:").map(function(e){return r.parseSsrcMedia(e)}).filter(function(e){return"cname"===e.attribute}),c=s.length>0&&s[0].ssrc,u=r.matchPrefix(e,"a=ssrc-group:FID").map(function(e){return e.substr(17).split(" ").map(function(e){return parseInt(e,10)})});u.length>0&&u[0].length>1&&u[0][0]===c&&(t=u[0][1]),i.codecs.forEach(function(e){if("RTX"===e.name.toUpperCase()&&e.parameters.apt){var r={ssrc:c,codecPayloadType:parseInt(e.parameters.apt,10)};c&&t&&(r.rtx={ssrc:t}),n.push(r),o&&((r=JSON.parse(JSON.stringify(r))).fec={ssrc:c,mechanism:a?"red+ulpfec":"red"},n.push(r))}}),0===n.length&&c&&n.push({ssrc:c});var d=r.matchPrefix(e,"b=");return d.length&&(d=0===d[0].indexOf("b=TIAS:")?parseInt(d[0].substr(7),10):0===d[0].indexOf("b=AS:")?1e3*parseInt(d[0].substr(5),10)*.95-16e3:void 0,n.forEach(function(e){e.maxBitrate=d})),n},r.parseRtcpParameters=function(e){var t={},n=r.matchPrefix(e,"a=ssrc:").map(function(e){return r.parseSsrcMedia(e)}).filter(function(e){return"cname"===e.attribute})[0];n&&(t.cname=n.value,t.ssrc=n.ssrc);var i=r.matchPrefix(e,"a=rtcp-rsize");t.reducedSize=i.length>0,t.compound=0===i.length;var o=r.matchPrefix(e,"a=rtcp-mux");return t.mux=o.length>0,t},r.parseMsid=function(e){var t,n=r.matchPrefix(e,"a=msid:");if(1===n.length)return{stream:(t=n[0].substr(7).split(" "))[0],track:t[1]};var i=r.matchPrefix(e,"a=ssrc:").map(function(e){return r.parseSsrcMedia(e)}).filter(function(e){return"msid"===e.attribute});return i.length>0?{stream:(t=i[0].value.split(" "))[0],track:t[1]}:void 0},r.parseSctpDescription=function(e){var t,n=r.parseMLine(e),i=r.matchPrefix(e,"a=max-message-size:");i.length>0&&(t=parseInt(i[0].substr(19),10)),isNaN(t)&&(t=65536);var o=r.matchPrefix(e,"a=sctp-port:");if(o.length>0)return{port:parseInt(o[0].substr(12),10),protocol:n.fmt,maxMessageSize:t};if(r.matchPrefix(e,"a=sctpmap:").length>0){var a=r.matchPrefix(e,"a=sctpmap:")[0].substr(10).split(" ");return{port:parseInt(a[0],10),protocol:a[1],maxMessageSize:t}}},r.writeSctpDescription=function(e,t){var n=[];return n="DTLS/SCTP"!==e.protocol?["m="+e.kind+" 9 "+e.protocol+" "+t.protocol+"\r\n","c=IN IP4 0.0.0.0\r\n","a=sctp-port:"+t.port+"\r\n"]:["m="+e.kind+" 9 "+e.protocol+" "+t.port+"\r\n","c=IN IP4 0.0.0.0\r\n","a=sctpmap:"+t.port+" "+t.protocol+" 65535\r\n"],void 0!==t.maxMessageSize&&n.push("a=max-message-size:"+t.maxMessageSize+"\r\n"),n.join("")},r.generateSessionId=function(){return Math.random().toString().substr(2,21)},r.writeSessionBoilerplate=function(e,t,n){var i=void 0!==t?t:2;return"v=0\r\no="+(n||"thisisadapterortc")+" "+(e||r.generateSessionId())+" "+i+" IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\n"},r.writeMediaSection=function(e,t,n,i){var o=r.writeRtpDescription(e.kind,t);if(o+=r.writeIceParameters(e.iceGatherer.getLocalParameters()),o+=r.writeDtlsParameters(e.dtlsTransport.getLocalParameters(),"offer"===n?"actpass":"active"),o+="a=mid:"+e.mid+"\r\n",e.direction?o+="a="+e.direction+"\r\n":e.rtpSender&&e.rtpReceiver?o+="a=sendrecv\r\n":e.rtpSender?o+="a=sendonly\r\n":e.rtpReceiver?o+="a=recvonly\r\n":o+="a=inactive\r\n",e.rtpSender){var a="msid:"+i.id+" "+e.rtpSender.track.id+"\r\n";o+="a="+a,o+="a=ssrc:"+e.sendEncodingParameters[0].ssrc+" "+a,e.sendEncodingParameters[0].rtx&&(o+="a=ssrc:"+e.sendEncodingParameters[0].rtx.ssrc+" "+a,o+="a=ssrc-group:FID "+e.sendEncodingParameters[0].ssrc+" "+e.sendEncodingParameters[0].rtx.ssrc+"\r\n")}return o+="a=ssrc:"+e.sendEncodingParameters[0].ssrc+" cname:"+r.localCName+"\r\n",e.rtpSender&&e.sendEncodingParameters[0].rtx&&(o+="a=ssrc:"+e.sendEncodingParameters[0].rtx.ssrc+" cname:"+r.localCName+"\r\n"),o},r.getDirection=function(e,t){for(var n=r.splitLines(e),i=0;icontent[name="video"]');if(t.length){var n=t[0].getAttribute("senders");if("both"===n||"initiator"===n||"responder"===n||"none"===n)return n}return null}}]),_createClass(t,[{key:"_assertNotEnded",value:function(){return this.state!==u.b}},{key:"doInitialize",value:function(e){var t=this;this.failICE=Boolean(e.failICE),this.lasticecandidate=!1,this.options=e,this.isReconnect=!1,this.wasstable=!1,this.webrtcIceUdpDisable=Boolean(e.webrtcIceUdpDisable),this.webrtcIceTcpDisable=Boolean(e.webrtcIceTcpDisable);var n={disableRtx:e.disableRtx};if(e.gatherStats&&(n.maxstats=300),n.capScreenshareBitrate=!1,this.isP2P){n.disableSimulcast=!0,n.disableH264=e.p2p&&e.p2p.disableH264,n.preferH264=e.p2p&&e.p2p.preferH264;var i=this._abtestSuspendVideoEnabled(e);void 0!==i&&(n.abtestSuspendVideo=i)}else n.disableSimulcast=e.disableSimulcast||e.preferH264&&!e.disableH264,n.preferH264=e.preferH264,n.enableLayerSuspension=e.enableLayerSuspension,e.testing&&e.testing.capScreenshareBitrate&&"number"==typeof e.testing.capScreenshareBitrate&&(n.capScreenshareBitrate=Math.random()0){var s=h.a.iceparams(r.media[i],r.session);s.xmlns="urn:xmpp:jingle:transports:ice-udp:1",n.c("content",{creator:t.initiatorJid===t.localJid?"initiator":"responder",name:o[0].sdpMid?o[0].sdpMid:a.media}).c("transport",s);for(var c=0;ccontent>transport>candidate").each(function(e,t){var r=h.a.candidateFromJingle(t);r=r.replace("\r\n","").replace("a=","");var i=new RTCIceCandidate({sdpMLineIndex:0,sdpMid:"",candidate:r});n.push(i)}),n.length?(C.debug("Queued add ("+n.length+") ICE candidates task..."),this.modificationQueue.push(function(e){for(var r=0;rdescription>source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]').each(function(e,n){var r=Number(n.getAttribute("ssrc"));t.isP2P?t.signalingLayer.setSSRCOwner(r,o.Strophe.getResourceFromJid(t.remoteJid)):$(n).find('>ssrc-info[xmlns="http://jitsi.org/jitmeet"]').each(function(e,n){var i=n.getAttribute("owner");i&&i.length&&(isNaN(r)||r<0?C.warn("Invalid SSRC "+r+" value received for "+i):t.signalingLayer.setSSRCOwner(r,o.Strophe.getResourceFromJid(i)))})})}},{key:"generateRecvonlySsrc",value:function(){this.peerconnection?this.peerconnection.generateRecvonlySsrc():C.error("Unable to generate recvonly SSRC - no peerconnection")}},{key:"acceptOffer",value:function(e,t,n,r){var i=this;this.setOfferAnswerCycle(e,function(){i.sendSessionAccept(t,n)},n,r)}},{key:"invite",value:function(e){var t=this;if(!this.isInitiator)throw new Error("Trying to invite from the responder session");this.modificationQueue.push(function(n){var r=e,i=Array.isArray(r),o=0;for(r=i?r:r["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var a;if(i){if(o>=r.length)break;a=r[o++]}else{if((o=r.next()).done)break;a=o.value}var s=a;t.peerconnection.addTrack(s,!0)}t.peerconnection.createOffer(t.mediaConstraints).then(function(e){t.peerconnection.setLocalDescription(e).then(function(){t.sendSessionInitiate(t.peerconnection.localDescription.sdp),n()},function(t){C.error("Failed to set local SDP",t,e),n(t)})},function(e){C.error("Failed to create an offer",e,t.mediaConstraints),n(e)})},function(e){e?C.error("invite error",e):C.debug("invite executed - OK")})}},{key:"sendSessionInitiate",value:function(e){var t=Object(o.$iq)({to:this.remoteJid,type:"set"}).c("jingle",{xmlns:"urn:xmpp:jingle:1",action:"session-initiate",initiator:this.initiatorJid,sid:this.sid});new d.a(e).toJingle(t,this.isInitiator?"initiator":"responder"),t=t.tree(),C.info("Session-initiate: ",t),this.connection.sendIQ(t,function(){C.info('Got RESULT for "session-initiate"')},function(e){C.error('"session-initiate" error',e)},T)}},{key:"setAnswer",value:function(e){if(!this.isInitiator)throw new Error("Trying to set an answer on the responder session");this.setOfferAnswerCycle(e,function(){C.info("setAnswer - succeeded")},function(e){C.error("setAnswer failed: ",e)})}},{key:"setOfferAnswerCycle",value:function(e,t,n,r){var i=this;this.modificationQueue.push(function(t){if(r){var n=r,o=Array.isArray(n),a=0;for(n=o?n:n["function"==typeof Symbol&&"function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var s;if(o){if(a>=n.length)break;s=n[a++]}else{if((a=n.next()).done)break;s=a.value}var c=s;i.peerconnection.addTrack(c)}}var l=i._processNewJingleOfferIq(e),h=i.peerconnection.localDescription.sdp,p=$(e).find('>bridge-session[xmlns="http://jitsi.org/protocol/focus"]').attr("id");p!==i._bridgeSessionId&&(i._bridgeSessionId=p),i._renegotiate(l.raw).then(function(){if(i.state===u.c&&(i.state=u.a,i.isP2P&&!i._localVideoActive&&i.sendContentModify(i._localVideoActive)),h){var e=new d.a(i.peerconnection.localDescription.sdp);i.notifyMySSRCUpdate(new d.a(h),e)}t()},function(e){C.error("Error renegotiating after setting new remote "+(i.isInitiator?"answer: ":"offer: ")+e,l),t(e)})},function(e){e?n(e):t()})}},{key:"replaceTransport",value:function(e,t,n){var r=this;this.room.eventEmitter.emit(y.a.ICE_RESTARTING,this);var i=e.clone();e.find(">content[name='data']").attr("senders","rejected"),e.find(">content>description>source").remove(),e.find(">content>description>ssrc-group").remove();var o=e.find(">content>transport>fingerprint");o.attr("hash","sha-1"),o.text("00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00"),this.setOfferAnswerCycle(e,function(){r.setOfferAnswerCycle(i,function(){var e=new d.a(r.peerconnection.localDescription.sdp);r.sendTransportAccept(e,t,n),r.room.eventEmitter.emit(y.a.ICE_RESTART_SUCCESS,r,i)},n)},n)}},{key:"sendSessionAccept",value:function(e,t){var n=this,r=new d.a(this.peerconnection.localDescription.sdp),i=Object(o.$iq)({to:this.remoteJid,type:"set"}).c("jingle",{xmlns:"urn:xmpp:jingle:1",action:"session-accept",initiator:this.initiatorJid,responder:this.responderJid,sid:this.sid});this.webrtcIceTcpDisable&&(r.removeTcpCandidates=!0),this.webrtcIceUdpDisable&&(r.removeUdpCandidates=!0),this.failICE&&(r.failICE=!0),r.toJingle(i,this.initiatorJid===this.localJid?"initiator":"responder",null),i=i.tree(),C.info("Sending session-accept",i),this.connection.sendIQ(i,e,this.newJingleErrorHandler(i,function(e){t(e),n.room.eventEmitter.emit(y.a.SESSION_ACCEPT_TIMEOUT,n)}),T)}},{key:"sendContentModify",value:function(e){var t=e?"both":"none",n=Object(o.$iq)({to:this.remoteJid,type:"set"}).c("jingle",{xmlns:"urn:xmpp:jingle:1",action:"content-modify",initiator:this.initiatorJid,sid:this.sid}).c("content",{name:"video",senders:t});C.info("Sending content-modify, video senders: "+t),this.connection.sendIQ(n,null,this.newJingleErrorHandler(n),T)}},{key:"sendTransportAccept",value:function(e,t,n){var r=this,i=Object(o.$iq)({to:this.remoteJid,type:"set"}).c("jingle",{xmlns:"urn:xmpp:jingle:1",action:"transport-accept",initiator:this.initiatorJid,sid:this.sid});e.media.forEach(function(t,n){var o=h.a.parseMLine(t.split("\r\n")[0]);i.c("content",{creator:r.initiatorJid===r.localJid?"initiator":"responder",name:o.media}),e.transportToJingle(n,i),i.up()}),i=i.tree(),C.info("Sending transport-accept: ",i),this.connection.sendIQ(i,t,this.newJingleErrorHandler(i,n),T)}},{key:"sendTransportReject",value:function(e,t){var n=Object(o.$iq)({to:this.remoteJid,type:"set"}).c("jingle",{xmlns:"urn:xmpp:jingle:1",action:"transport-reject",initiator:this.initiatorJid,sid:this.sid});n=n.tree(),C.info("Sending 'transport-reject",n),this.connection.sendIQ(n,e,this.newJingleErrorHandler(n,t),T)}},{key:"setSenderVideoConstraint",value:function(e){return this.peerconnection.setSenderVideoConstraint(e)}},{key:"terminate",value:function(e,t,n){if(this.state!==u.b){if(!n||Boolean(n.sendSessionTerminate)){var r=Object(o.$iq)({to:this.remoteJid,type:"set"}).c("jingle",{xmlns:"urn:xmpp:jingle:1",action:"session-terminate",initiator:this.initiatorJid,sid:this.sid}).c("reason").c(n&&n.reason||"success");n&&n.reasonDescription&&r.up().c("text").t(n.reasonDescription),r=r.tree(),C.info("Sending session-terminate",r),this.connection.sendIQ(r,e,this.newJingleErrorHandler(r,t),T)}else C.info("Skipped sending session-terminate for "+this);this.connection.jingle.terminate(this.sid)}}},{key:"onTerminated",value:function(e,t){C.info("Session terminated "+this,e,t),this._xmppListeners.forEach(function(e){return e()}),this._xmppListeners=[],this.close()}},{key:"onXmppStatusChanged",value:function(e){e===b.a.Status.CONNECTED&&this._cachedOldLocalSdp&&(C.info("Sending SSRC update on reconnect"),this.notifyMySSRCUpdate(this._cachedOldLocalSdp,this._cachedNewLocalSdp))}},{key:"_parseSsrcInfoFromSourceAdd",value:function(e,t){var n=[];return $(e).each(function(e,r){var i=$(r).attr("name"),o="";$(r).find('ssrc-group[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]').each(function(){var e=this.getAttribute("semantics"),t=$(this).find(">source").map(function(){return this.getAttribute("ssrc")}).get();t.length&&(o+="a=ssrc-group:"+e+" "+t.join(" ")+"\r\n")}),$(r).find('source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]').each(function(){var e=$(this).attr("ssrc");t.containsSSRC(e)?C.warn("Source-add request for existing SSRC: "+e):$(this).find(">parameter").each(function(){o+="a=ssrc:"+e+" "+$(this).attr("name"),$(this).attr("value")&&$(this).attr("value").length&&(o+=":"+$(this).attr("value")),o+="\r\n"})}),t.media.forEach(function(e,t){h.a.findLine(e,"a=mid:"+i)&&(n[t]||(n[t]=""),n[t]+=o)})}),n}},{key:"addRemoteStream",value:function(e){this._addOrRemoveRemoteStream(!0,e)}},{key:"removeRemoteStream",value:function(e){this._addOrRemoveRemoteStream(!1,e)}},{key:"_addOrRemoveRemoteStream",value:function(e,t){var n=this,r=e?"addRemoteStream":"removeRemoteStream";e&&this.readSsrcInfo(t),this.modificationQueue.push(function(i){if(!n.peerconnection.localDescription||!n.peerconnection.localDescription.sdp){var o=r+" - localDescription not ready yet";return C.error(o),void i(o)}C.log("Processing "+r),C.log("ICE connection state: ",n.peerconnection.iceConnectionState);var a=new d.a(n.peerconnection.localDescription.sdp),s=new d.a(n.peerconnection.remoteDescription.sdp),c=e?n._parseSsrcInfoFromSourceAdd(t,s):n._parseSsrcInfoFromSourceRemove(t,s),u=e?n._processRemoteAddSource(c):n._processRemoteRemoveSource(c);n._renegotiate(u.raw).then(function(){var e=new d.a(n.peerconnection.localDescription.sdp);C.log(r+" - OK, SDPs: ",a,e),n.notifyMySSRCUpdate(a,e),i()},function(e){C.error(r+" failed:",e),i(e)})})}},{key:"_processNewJingleOfferIq",value:function(e){var t=new d.a("");return this.webrtcIceTcpDisable&&(t.removeTcpCandidates=!0),this.webrtcIceUdpDisable&&(t.removeUdpCandidates=!0),this.failICE&&(t.failICE=!0),t.fromJingle(e),this.readSsrcInfo($(e).find(">content")),t}},{key:"_processRemoteRemoveSource",value:function(e){var t=s.a.usesPlanB()?new d.a(this.peerconnection.remoteDescription.sdp):new d.a(this.peerconnection.peerconnection.remoteDescription.sdp);return e.forEach(function(e,n){(e=e.split("\r\n")).pop(),s.a.usesPlanB()?e.forEach(function(e){t.media[n]=t.media[n].replace(e+"\r\n","")}):e.forEach(function(e){var n=t.media.findIndex(function(t){return t.includes(e)});n>-1&&(t.media[n]=t.media[n].replace(e+"\r\n",""),s.a.isFirefox()&&(t.media[n]=t.media[n].replace("a=sendonly","a=inactive")))})}),t.raw=t.session+t.media.join(""),t}},{key:"_processRemoteAddSource",value:function(e){var t=new d.a(this.peerconnection.remoteDescription.sdp);return e.forEach(function(e,n){t.media[n]+=e}),t.raw=t.session+t.media.join(""),t}},{key:"_renegotiate",value:function(e){if("closed"===this.peerconnection.signalingState){var t=new Error("Attempted to renegotiate in state closed");return this.room.eventEmitter.emit(y.a.RENEGOTIATION_FAILED,t,this),Promise.reject(t)}var n=e||this.peerconnection.remoteDescription.sdp;if(!n){var r=new Error("Can not renegotiate without remote description, current state: "+this.state);return this.room.eventEmitter.emit(y.a.RENEGOTIATION_FAILED,r,this),Promise.reject(r)}var i=new RTCSessionDescription({type:this.isInitiator?"answer":"offer",sdp:n});return this.isInitiator?this._initiatorRenegotiate(i):this._responderRenegotiate(i)}},{key:"_responderRenegotiate",value:function(e){var t=this;return C.debug("Renegotiate: setting remote description"),this.peerconnection.setRemoteDescription(e).then(function(){return C.debug("Renegotiate: creating answer"),t.peerconnection.createAnswer(t.mediaConstraints).then(function(e){return C.debug("Renegotiate: setting local description"),t.peerconnection.setLocalDescription(e)})})}},{key:"_initiatorRenegotiate",value:function(e){var t=this;return C.debug("Renegotiate: creating offer"),this.peerconnection.createOffer(this.mediaConstraints).then(function(n){return C.debug("Renegotiate: setting local description"),t.peerconnection.setLocalDescription(n).then(function(){return C.debug("Renegotiate: setting remote description"),t.peerconnection.setRemoteDescription(e)})})}},{key:"replaceTrack",value:function(e,t){var n=this,r=function(r){var i=n.peerconnection.localDescription.sdp;s.a.usesPlanB()&&(n.peerconnection.options.capScreenshareBitrate&&e&&t&&t.isVideoTrack()&&n.peerconnection.clearRecvonlySsrc(),!e&&t&&t.isVideoTrack()?n.peerconnection.clearRecvonlySsrc():e&&e.isVideoTrack()&&!t&&(n.peerconnection.clearRecvonlySsrc(),n.peerconnection.generateRecvonlySsrc())),n.peerconnection.replaceTrack(e,t).then(function(o){var a=Promise.resolve();o&&(e||t)&&n.state===u.a&&(a=n._renegotiate().then(function(){var e=new d.a(n.peerconnection.localDescription.sdp);n.notifyMySSRCUpdate(new d.a(i),e)},r)),a.then(function(){t&&!n.isP2P&&n.peerconnection.setMaxBitRate(t),r()},r)}).catch(function(e){r(e)})};return new Promise(function(e,t){n.modificationQueue.push(r,function(n){n?(C.error("Replace track error:",n),t(n)):(C.info("Replace track done!"),e())})})}},{key:"_parseSsrcInfoFromSourceRemove",value:function(e,t){var n=[];return $(e).each(function(e,r){var i=$(r).attr("name"),o="";$(r).find('ssrc-group[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]').each(function(){var e=this.getAttribute("semantics"),t=$(this).find(">source").map(function(){return this.getAttribute("ssrc")}).get();t.length&&(o+="a=ssrc-group:"+e+" "+t.join(" ")+"\r\n")});var a=[];$(r).find('source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]').each(function(){var e=$(this).attr("ssrc");a.push(e)}),t.media.forEach(function(e,t){h.a.findLine(e,"a=mid:"+i)&&(n[t]||(n[t]=""),a.forEach(function(r){var i=h.a.findLines(e,"a=ssrc:"+r);i.length&&(n[t]+=i.join("\r\n")+"\r\n")}),n[t]+=o)})}),n}},{key:"_verifyNoSSRCChanged",value:function(e,t){var n=new d.a(this.peerconnection.localDescription.sdp),r=new l.a(t,n),i=r.getNewMedia();if(Object.keys(i).length)return C.error(this+" - some SSRC were added on "+e,i),!1;var o=(r=new l.a(n,t)).getNewMedia();return!Object.keys(o).length||(C.error(this+" - some SSRCs were removed on "+e,o),!1)}},{key:"addTrackAsUnmute",value:function(e){return this._addRemoveTrackAsMuteUnmute(!1,e)}},{key:"removeTrackAsMute",value:function(e){return this._addRemoveTrackAsMuteUnmute(!0,e)}},{key:"_addRemoveTrackAsMuteUnmute",value:function(e,t){var n=this;if(!t)return Promise.reject('invalid "track" argument value');var r=e?"removeTrackMute":"addTrackUnmute",i=function(i){var o=n.peerconnection;if(o){var a=o.localDescription.sdp;(e?o.removeTrackMute(t):o.addTrackUnmute(t)).then(function(e){e&&a&&o.remoteDescription.sdp?n._renegotiate().then(function(){n._verifyNoSSRCChanged(r,new d.a(a)),i()}):i()},i)}else i("Error: tried "+r+" track with no active peerconnection")};return new Promise(function(e,t){n.modificationQueue.push(i,function(n){n?t(n):e()})})}},{key:"setMediaTransferActive",value:function(e,t){var n=this;if(!this.peerconnection)return Promise.reject('Can not modify transfer active state, before "initialize" is called');var r=e?"audio active":"audio inactive",i=t?"video active":"video inactive";C.info("Queued make "+i+", "+r+" task...");var o=function(r){var i=n.state===u.a,o=n.peerconnection.setAudioTransferActive(e);n._localVideoActive!==t&&(n._localVideoActive=t,n.isP2P&&i&&n.sendContentModify(t));var a=n.peerconnection.setVideoTransferActive(n._localVideoActive&&n._remoteVideoActive);i&&(o||a)?n._renegotiate().then(r,r):r()};return new Promise(function(e,t){n.modificationQueue.push(o,function(n){n?t(n):e()})})}},{key:"modifyContents",value:function(e){var n=this,r=t.parseVideoSenders(e);null!==r?(C.debug(this+" queued \"content-modify\" task(video senders=\""+r+"\")"),this.modificationQueue.push(function(e){n._assertNotEnded("content-modify")&&n._modifyRemoteVideoActive(r)?n._renegotiate().then(e,e):e()},function(e){e&&C.error('"content-modify" failed',e)})):C.error(this+" - failed to parse video \"senders\" attribute in\"content-modify\" action")}},{key:"_modifyRemoteVideoActive",value:function(e){var t="both"===e||"initiator"===e&&this.isInitiator||"responder"===e&&!this.isInitiator;return t!==this._remoteVideoActive&&(C.debug(this+" new remote video active: "+t),this._remoteVideoActive=t),this.peerconnection.setVideoTransferActive(this._localVideoActive&&this._remoteVideoActive)}},{key:"notifyMySSRCUpdate",value:function(e,t){if(this.state===u.a){if(!this.connection.connected)return this._cachedOldLocalSdp||(this._cachedOldLocalSdp=e),this._cachedNewLocalSdp=t,void C.warn("Not sending SSRC update while the signaling is disconnected");this._cachedOldLocalSdp=void 0,this._cachedNewLocalSdp=void 0;var n=new l.a(t,e),r=Object(o.$iq)({to:this.remoteJid,type:"set"}).c("jingle",{xmlns:"urn:xmpp:jingle:1",action:"source-remove",initiator:this.initiatorJid,sid:this.sid});n.toJingle(r)?(C.info("Sending source-remove",r.tree()),this.connection.sendIQ(r,null,this.newJingleErrorHandler(r),T)):C.log("removal not necessary"),n=new l.a(e,t);var i=Object(o.$iq)({to:this.remoteJid,type:"set"}).c("jingle",{xmlns:"urn:xmpp:jingle:1",action:"source-add",initiator:this.initiatorJid,sid:this.sid});n.toJingle(i)?(C.info("Sending source-add",i.tree()),this.connection.sendIQ(i,null,this.newJingleErrorHandler(i),T)):C.log("addition not necessary")}else C.warn("Skipping SSRC update in '"+this.state+" ' state.")}},{key:"newJingleErrorHandler",value:function(e,t){var n=this;return function(e){var r={},i=$(e).find("error");if(i.length){r.code=i.attr("code");var o=$(e).find("error :first");o.length&&(r.reason=o[0].tagName);var a=i.find(">text");a.length&&(r.msg=a.text())}e||(r.reason="timeout"),r.session=n.toString(),t?t(r):n.state===u.b&&"item-not-found"===r.reason?C.debug("Jingle error: "+JSON.stringify(r)):E.a.callErrorHandler(new Error("Jingle error: "+JSON.stringify(r)))}}},{key:"getIceConnectionState",value:function(){return this.peerconnection.getConnectionState()}},{key:"close",value:function(){var e=this;this.state=u.b,this.establishmentDuration=void 0,this.peerconnection&&(this.peerconnection.onicecandidate=null,this.peerconnection.oniceconnectionstatechange=null,this.peerconnection.onnegotiationneeded=null,this.peerconnection.onsignalingstatechange=null),this.modificationQueue.clear(),this.modificationQueue.push(function(t){e.signalingLayer.setChatRoom(null),e.peerconnection&&e.peerconnection.close(),t()}),this.modificationQueue.shutdown()}},{key:"toString",value:function(){return"JingleSessionPC[p2p="+this.isP2P+",initiator="+this.isInitiator+",sid="+this.sid+"]"}},{key:"_abtestSuspendVideoEnabled",value:function(e){var t=e.abTesting;if(t&&t.enableSuspendVideoTest){var n=this._getInitiatorJid();return Object(a.integerHash)(n)%2==0}}}]),t})(c.a)}).call(this,"modules/xmpp/JingleSessionPC.js")},function(e,t,n){"use strict";n.r(t),n.d(t,"DEVICE_LIST_CHANGED",function(){return r}),n.d(t,"PERMISSION_PROMPT_IS_SHOWN",function(){return i});var r="mediaDevices.devicechange",i="mediaDevices.permissionPromptIsShown"},function(e,t,n){(function(e,n){var r="__lodash_hash_undefined__",i=9007199254740991,o="[object Arguments]",a="[object Boolean]",s="[object Date]",c="[object Function]",u="[object GeneratorFunction]",d="[object Map]",l="[object Number]",h="[object Object]",p="[object RegExp]",f="[object Set]",m="[object String]",v="[object Symbol]",g="[object ArrayBuffer]",y="[object DataView]",_="[object Float32Array]",S="[object Float64Array]",E="[object Int8Array]",b="[object Int16Array]",C="[object Int32Array]",T="[object Uint8Array]",A="[object Uint8ClampedArray]",R="[object Uint16Array]",k="[object Uint32Array]",w=/\w*$/,I=/^\[object .+?Constructor\]$/,P=/^(?:0|[1-9]\d*)$/,D={};D[o]=D["[object Array]"]=D[g]=D[y]=D[a]=D[s]=D[_]=D[S]=D[E]=D[b]=D[C]=D[d]=D[l]=D[h]=D[p]=D[f]=D[m]=D[v]=D[T]=D[A]=D[R]=D[k]=!0,D["[object Error]"]=D[c]=D["[object WeakMap]"]=!1;var O="object"==typeof e&&e&&e.Object===Object&&e,N="object"==typeof self&&self&&self.Object===Object&&self,M=O||N||Function("return this")(),L=t&&!t.nodeType&&t,x=L&&"object"==typeof n&&n&&!n.nodeType&&n,F=x&&x.exports===L;function j(e,t){return e.set(t[0],t[1]),e}function U(e,t){return e.add(t),e}function H(e,t,n,r){var i=-1,o=e?e.length:0;for(r&&o&&(n=e[++i]);++i-1},Ae.prototype.set=function(e,t){var n=this.__data__,r=Pe(n,e);return r<0?n.push([e,t]):n[r][1]=t,this},Re.prototype.clear=function(){this.__data__={hash:new Te,map:new(he||Ae),string:new Te}},Re.prototype.delete=function(e){return Le(this,e).delete(e)},Re.prototype.get=function(e){return Le(this,e).get(e)},Re.prototype.has=function(e){return Le(this,e).has(e)},Re.prototype.set=function(e,t){return Le(this,e).set(e,t),this},ke.prototype.clear=function(){this.__data__=new Ae},ke.prototype.delete=function(e){return this.__data__.delete(e)},ke.prototype.get=function(e){return this.__data__.get(e)},ke.prototype.has=function(e){return this.__data__.has(e)},ke.prototype.set=function(e,t){var n=this.__data__;if(n instanceof Ae){var r=n.__data__;if(!he||r.length<199)return r.push([e,t]),this;n=this.__data__=new Re(r)}return n.set(e,t),this};var Fe=ce?G(ce,Object):function(){return[]},je=function(e){return Z.call(e)};function Ue(e,t){return!!(t=null==t?i:t)&&("number"==typeof e||P.test(e))&&e>-1&&e%1==0&&e-1&&e%1==0&&e<=i})(e.length)&&!Ke(e)}var qe=ue||function(){return!1};function Ke(e){var t=ze(e)?Z.call(e):"";return t==c||t==u}function ze(e){var t=typeof e;return!!e&&("object"==t||"function"==t)}function We(e){return Ve(e)?we(e):(function(e){if(!He(e))return de(e);var t=[];for(var n in Object(e))Y.call(e,n)&&"constructor"!=n&&t.push(n);return t})(e)}n.exports=function(e){return De(e,!0,!0)}}).call(this,n(43),n(70)(e))},function(e,t,n){"use strict";n.d(t,"a",function(){return o});var r=n(6);function i(e,t){if(!t)return!1;if(e.length!==t.length)return!1;for(var n=0,r=e.length;n1)for(var n=1;n.2?t-.2:n<-.4?t+.4:e).toFixed(3))})(r,t.audioLevel),t.callback(t.audioLevel))},this.intervalMilis)}},i.prototype.stop=function(){this.intervalId&&(clearInterval(this.intervalId),this.intervalId=null)},i.isLocalStatsSupported=function(){return Boolean(r)}},function(e,t,n){var r=n(138),i={loadScript:function(e,t,n,i,o,a){var s=document,c=s.createElement("script"),u=s.getElementsByTagName("script")[0];if(c.async=t,i){var d=r();if(d){var l=d.src,h=l.substring(0,l.lastIndexOf("/")+1);l&&h&&(e=h+e)}}o&&(c.onload=o),a&&(c.onerror=a),c.src=e,n?u.parentNode.insertBefore(c,u):u.parentNode.appendChild(c)}};e.exports=i},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return h});var r=n(20),i=n.n(r),o=n(4),a=n(15),s=n(9),c=n(10),u=Object(o.getLogger)(e),d={track_mute:"onmute",track_unmute:"onunmute",track_ended:"onended"};function l(e,t){e.oninactive=t}var h=(function(e){function t(e,n,r,i,o,a){var s;return _classCallCheck(this,t),(s=_possibleConstructorReturn(this,_getPrototypeOf(t).call(this))).addEventListener=s.addListener,s.removeEventListener=s.off=s.removeListener,s.containers=[],s.conference=e,s.audioLevel=-1,s.type=o,s.track=r,s.videoType=a,s.handlers=new Map,s.disposed=!1,s._streamInactiveHandler=i,s._setStream(n),s}return _inherits(t,e),_createClass(t,[{key:"_setHandler",value:function(e,t){if(d.hasOwnProperty(e)){if(t?this.handlers.set(e,t):this.handlers.delete(e),this.stream){var n=this.stream.getTracks(),r=Array.isArray(n),i=0;for(n=r?n:n["function"==typeof Symbol&&"function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var o;if(r){if(i>=n.length)break;o=n[i++]}else{if((i=n.next()).done)break;o=i.value}o[d[e]]=t}}}else u.error("Invalid handler type "+e)}},{key:"_unregisterHandlers",value:function(){if(this.stream){var e=this.handlers.keys(),t=Array.isArray(e),n=0;for(e=t?e:e["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var r;if(t){if(n>=e.length)break;r=e[n++]}else{if((n=e.next()).done)break;r=n.value}var i=r,o=this.stream.getVideoTracks(),a=Array.isArray(o),s=0;for(o=a?o:o["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var c;if(a){if(s>=o.length)break;c=o[s++]}else{if((s=o.next()).done)break;c=s.value}c[d[i]]=void 0}}this._streamInactiveHandler&&l(this.stream,void 0)}else u.warn(this+": unable to unregister handlers - no stream object")}},{key:"_setStream",value:function(e){if(this.stream!==e&&(this.stream=e,this.stream)){var t=this.handlers.keys(),n=Array.isArray(t),r=0;for(t=n?t:t["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var i;if(n){if(r>=t.length)break;i=t[r++]}else{if((r=t.next()).done)break;i=r.value}var o=i;this._setHandler(o,this.handlers.get(o))}this._streamInactiveHandler&&l(this.stream,this._streamInactiveHandler)}}},{key:"getType",value:function(){return this.type}},{key:"isAudioTrack",value:function(){return this.getType()===s.a}},{key:"isWebRTCTrackMuted",value:function(){return this.track&&this.track.muted}},{key:"isVideoTrack",value:function(){return this.getType()===s.c}},{key:"isLocal",value:function(){throw new Error("Not implemented by subclass")}},{key:"isLocalAudioTrack",value:function(){return this.isAudioTrack()&&this.isLocal()}},{key:"getOriginalStream",value:function(){return this.stream}},{key:"getStreamId",value:function(){return this.stream?this.stream.id:null}},{key:"getTrack",value:function(){return this.track}},{key:"getTrackLabel",value:function(){return this.track.label}},{key:"getTrackId",value:function(){return this.track?this.track.id:null}},{key:"getUsageLabel",value:function(){return this.isAudioTrack()?"mic":this.videoType?this.videoType:"default"}},{key:"_maybeFireTrackAttached",value:function(e){this.conference&&e&&this.conference._onTrackAttach(this,e)}},{key:"attach",value:function(e){this.stream&&(this._onTrackAttach(e),c.a.attachMediaStream(e,this.stream)),this.containers.push(e),this._maybeFireTrackAttached(e),this._attachTTFMTracker(e)}},{key:"detach",value:function(e){for(var t=this.containers,n=t.length-1;n>=0;--n){var r=t[n];e||(this._onTrackDetach(r),c.a.attachMediaStream(r,null)),e&&r!==e||t.splice(n,1)}e&&(this._onTrackDetach(e),c.a.attachMediaStream(e,null))}},{key:"_onTrackAttach",value:function(e){}},{key:"_onTrackDetach",value:function(e){}},{key:"_attachTTFMTracker",value:function(e){}},{key:"dispose",value:function(){return this.removeAllListeners(),this.disposed=!0,Promise.resolve()}},{key:"isScreenSharing",value:function(){}},{key:"getId",value:function(){return this.stream?c.a.getStreamID(this.stream):null}},{key:"isActive",value:function(){return void 0===this.stream.active||this.stream.active}},{key:"setAudioLevel",value:function(e,t){this.audioLevel!==e&&(this.audioLevel=e,this.emit(a.TRACK_AUDIO_LEVEL_CHANGED,e,t))}},{key:"getMSID",value:function(){var e=this.getStreamId(),t=this.getTrackId();return e&&t?e+" "+t:null}},{key:"setAudioOutput",value:function(e){var t=this;return c.a.isDeviceChangeAvailable("output")?this.isVideoTrack()?Promise.resolve():Promise.all(this.containers.map(function(t){return t.setSinkId(e).catch(function(e){throw u.warn("Failed to change audio output device on element. Default or previously set audio output device will be used.",t,e),e})})).then(function(){t.emit(a.TRACK_AUDIO_OUTPUT_CHANGED,e)}):Promise.reject(new Error("Audio output device change is not supported"))}}]),t})(i.a)}).call(this,"modules/RTC/JitsiTrack.js")},function(e,t,n){"use strict";function r(e){var t=window.AudioContext||window.webkitAudioContext;if(t)return new t(e)}n.d(t,"a",function(){return r})},function(e,t,n){"use strict";n.d(t,"a",function(){return c});var r=n(20),i=n.n(r),o=n(12),a=n(55),s=n(21),c=(function(e){function t(e,n,r){var i;return _classCallCheck(this,t),(i=_possibleConstructorReturn(this,_getPrototypeOf(t).call(this)))._procNodeSampleRate=e,i._vadProcessor=n,i._localTrack=r,i._bufferResidue=new Float32Array([]),i._audioContext=Object(a.a)({sampleRate:n.getRequiredPCMFrequency()}),i._vadSampleSize=n.getSampleLength(),i._onAudioProcess=i._onAudioProcess.bind(_assertThisInitialized(_assertThisInitialized(i))),i._initializeAudioContext(),i}return _inherits(t,e),_createClass(t,[{key:"_initializeAudioContext",value:function(){this._audioSource=this._audioContext.createMediaStreamSource(this._localTrack.stream),this._audioProcessingNode=this._audioContext.createScriptProcessor(this._procNodeSampleRate,1,1)}},{key:"_onAudioProcess",value:function(e){for(var t=e.inputBuffer.getChannelData(0),n=_toConsumableArray(this._bufferResidue).concat(_toConsumableArray(t)),r=Date.now(),i=0;i+this._vadSampleSizeu))return!1;var l=s.get(e);if(l&&s.get(t))return l==t;var h=-1,p=!0,f=n&o?new Ae:void 0;for(s.set(e,t),s.set(t,e);++h-1},Ce.prototype.set=function(e,t){var n=this.__data__,r=we(n,e);return r<0?(++this.size,n.push([e,t])):n[r][1]=t,this},Te.prototype.clear=function(){this.size=0,this.__data__={hash:new be,map:new(de||Ce),string:new be}},Te.prototype.delete=function(e){var t=xe(this,e).delete(e);return this.size-=t?1:0,t},Te.prototype.get=function(e){return xe(this,e).get(e)},Te.prototype.has=function(e){return xe(this,e).has(e)},Te.prototype.set=function(e,t){var n=xe(this,e),r=n.size;return n.set(e,t),this.size+=n.size==r?0:1,this},Ae.prototype.add=Ae.prototype.push=function(e){return this.__data__.set(e,r),this},Ae.prototype.has=function(e){return this.__data__.has(e)},Re.prototype.clear=function(){this.__data__=new Ce,this.size=0},Re.prototype.delete=function(e){var t=this.__data__,n=t.delete(e);return this.size=t.size,n},Re.prototype.get=function(e){return this.__data__.get(e)},Re.prototype.has=function(e){return this.__data__.has(e)},Re.prototype.set=function(e,t){var n=this.__data__;if(n instanceof Ce){var r=n.__data__;if(!de||r.length<199)return r.push([e,t]),this.size=++n.size,this;n=this.__data__=new Te(r)}return n.set(e,t),this.size=n.size,this};var je=ae?function(e){return null==e?[]:(e=Object(e),(function(e,t){for(var n=-1,r=null==e?0:e.length,i=0,o=[];++n-1&&e%1==0&&e-1&&e%1==0&&e<=a}function We(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}function $e(e){return null!=e&&"object"==typeof e}var Qe=j?(function(e){return function(t){return e(t)}})(j):function(e){return $e(e)&&ze(e.length)&&!!I[Ie(e)]};function Xe(e){return null!=(t=e)&&ze(t.length)&&!Ke(t)?ke(e):Ne(e);var t}n.exports=function(e,t){return De(e,t)}}).call(this,n(43),n(70)(e))},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return d}),n.d(t,"b",function(){return p});var r=n(3),i=n(0),o=n.n(i),a=n(24),s=n(4).getLogger(e),c=["category","type","lang","name"],u=["category","type","lang"],d="Feature version mismatch";function l(e,t){var n=0;return u.some(function(r){return 0!==(n=e[r]>t[r]?1:e[r]0&&void 0!==arguments[0]?arguments[0]:{},i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"http://jitsi.org/jitsimeet";if(_classCallCheck(this,t),(e=_possibleConstructorReturn(this,_getPrototypeOf(t).call(this))).node=i,e.disco=n.disco,!e.disco)throw new Error("Missing strophe-plugins (disco plugin is required)!");e.versionToCapabilities=Object.create(null),e.jidToVersion=Object.create(null),e.version="",e.rooms=new Set;var a=n.emuc;return a.addListener(o.a.EMUC_ROOM_ADDED,function(t){return e._addChatRoom(t)}),a.addListener(o.a.EMUC_ROOM_REMOVED,function(t){return e._removeChatRoom(t)}),Object.keys(a.rooms).forEach(function(t){e._addChatRoom(a.rooms[t])}),r.Strophe.addNamespace("CAPS","http://jabber.org/protocol/caps"),e.disco.addFeature(r.Strophe.NS.CAPS),n.addHandler(e._handleCaps.bind(_assertThisInitialized(_assertThisInitialized(e))),r.Strophe.NS.CAPS),e._onMucMemberLeft=e._removeJidToVersionEntry.bind(_assertThisInitialized(_assertThisInitialized(e))),_possibleConstructorReturn(e)}return _inherits(t,e),_createClass(t,[{key:"addFeature",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];this.disco.addFeature(e),this._generateVersion(),t&&this.submit()}},{key:"removeFeature",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];this.disco.removeFeature(e),this._generateVersion(),t&&this.submit()}},{key:"submit",value:function(){this.rooms.forEach(function(e){return e.sendPresence()})}},{key:"getFeatures",value:function(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:5e3,r=e in this.jidToVersion?this.jidToVersion[e]:null;if(!(r&&r.version in this.versionToCapabilities)){var i=r?r.node+"#"+r.version:null;return this._getDiscoInfo(e,i,n).then(function(e){var n=e.features,o=e.identities;if(r){var a=h(Array.from(o),Array.from(n)),c=r.node+"#"+a;return c===i?(t.versionToCapabilities[c]=n,n):t.versionToCapabilities[c]?t.versionToCapabilities[c]:(s.error("Expected node "+i+" but received "+c),Promise.reject(d))}})}return Promise.resolve(this.versionToCapabilities[r.version])}},{key:"getFeaturesAndIdentities",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:5e3;return this._getDiscoInfo(e,null,t)}},{key:"_getDiscoInfo",value:function(e,t,n){var r=this;return new Promise(function(i,o){return r.disco.info(e,t,function(e){var t=new Set,n=new Set;$(e).find(">query>feature").each(function(e,n){return t.add(n.getAttribute("var"))}),$(e).find(">query>identity").each(function(e,t){return n.add({type:t.getAttribute("type"),name:t.getAttribute("name"),category:t.getAttribute("category")})}),i({features:t,identities:n})},o,n)})}},{key:"_addChatRoom",value:function(e){this.rooms.add(e),e.addListener(o.a.MUC_MEMBER_LEFT,this._onMucMemberLeft),this._fixChatRoomPresenceMap(e)}},{key:"_removeChatRoom",value:function(e){this.rooms.delete(e),e.removeListener(o.a.MUC_MEMBER_LEFT,this._onMucMemberLeft)}},{key:"_fixChatRoomPresenceMap",value:function(e){e.addToPresence("c",{attributes:{xmlns:r.Strophe.NS.CAPS,hash:"sha-1",node:this.node,ver:this.version}})}},{key:"_notifyVersionChanged",value:function(){var e=this;this.rooms.forEach(function(t){return e._fixChatRoomPresenceMap(t)})}},{key:"_generateVersion",value:function(){this.version=h(this.disco._identities,this.disco._features),this._notifyVersionChanged()}},{key:"_handleCaps",value:function(e){var t=e.getAttribute("from"),n=e.querySelector("c"),r=n.getAttribute("ver"),i=n.getAttribute("node"),a=this.jidToVersion[t];return this.jidToVersion[t]={version:r,node:i},a&&a.version!==r&&this.eventEmitter.emit(o.a.PARTCIPANT_FEATURES_CHANGED,t),!0}},{key:"_removeJidToVersionEntry",value:function(e){e in this.jidToVersion&&delete this.jidToVersion[e]}}]),t})(a.a)}).call(this,"modules/xmpp/Caps.js")},function(e,t,n){"use strict";n.r(t),n.d(t,"ON",function(){return r}),n.d(t,"OFF",function(){return i});var r="on",i="off"},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return v}),n.d(t,"b",function(){return g});var r=n(4),i=n(22),o=n.n(i),a=n(15),s=n(1),c=n(8),u=n.n(c),d=n(9),l=n(13),h=Object(r.getLogger)(e),p="1",f="2",m="3",v=[p,f,m],g=(function(){function e(t){_classCallCheck(this,e),this.pc=t,this.simulcastEncodings=[{active:!0,maxBitrate:s.a.isFirefox()?25e5:2e5,rid:p,scaleResolutionDownBy:s.a.isFirefox()?1:4},{active:!0,maxBitrate:7e5,rid:f,scaleResolutionDownBy:2},{active:!0,maxBitrate:s.a.isFirefox()?2e5:25e5,rid:m,scaleResolutionDownBy:s.a.isFirefox()?4:1}],this.simulcastStreamConstraints=[]}return _createClass(e,[{key:"_ensureCorrectOrderOfSsrcs",value:function(e){var t=o.a.parse(e.sdp);return t.media.forEach(function(e){if("audio"!==e.type&&e.ssrcGroups&&e.ssrcGroups.length){var t=[];e.ssrcGroups[0].ssrcs.split(" ").forEach(function(n){var r=e.ssrcs.filter(function(e){return e.id.toString()===n});t=t.concat(r)}),e.ssrcs=t}}),new RTCSessionDescription({type:e.type,sdp:o.a.write(t)})}},{key:"_getStreamEncodings",value:function(e){return this.pc.isSimulcastOn()&&e.isVideoTrack()?this.simulcastEncodings:[{active:!0}]}},{key:"_insertUnifiedPlanSimulcastReceive",value:function(e){if(s.a.usesSdpMungingForSimulcast())return e;var t=o.a.parse(e.sdp),n=t.media.findIndex(function(e){return"video"===e.type});if(t.media[n].rids&&(t.media[n].simulcast_03||t.media[n].simulcast))return t.media.forEach(function(e,r){"video"===e.type&&r!==n&&(t.media[r].rids=void 0,t.media[r].simulcast=void 0,t.media[r].simulcast_03=void 0)}),new RTCSessionDescription({type:e.type,sdp:o.a.write(t)});t.media[n].rids=[{id:p,direction:"recv"},{id:f,direction:"recv"},{id:m,direction:"recv"}];var r=s.a.isFirefox()&&s.a.isVersionGreaterThan(71)?"recv "+v.join(";"):"recv rid="+v.join(";");return t.media[n].simulcast_03={value:r},new RTCSessionDescription({type:e.type,sdp:o.a.write(t)})}},{key:"_setSimulcastStreamConstraints",value:function(e){if(!s.a.isReactNative()){var t=e.getSettings().height;for(var n in this.simulcastEncodings)this.simulcastEncodings.hasOwnProperty(n)&&this.simulcastStreamConstraints.push({height:t/this.simulcastEncodings[n].scaleResolutionDownBy,rid:this.simulcastEncodings[n].rid})}}},{key:"addTrack",value:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=e.getTrack();if(t){var r={direction:"sendrecv",streams:[e.getOriginalStream()],sendEncodings:[]};s.a.isFirefox()||(r.sendEncodings=this._getStreamEncodings(e)),this.pc.peerconnection.addTransceiver(n,r)}else this.pc.peerconnection.addTrack(n);e.isVideoTrack()&&e.videoType===l.CAMERA&&this.pc.isSimulcastOn()&&this._setSimulcastStreamConstraints(e.getTrack())}},{key:"addTrackUnmute",value:function(e){var t=this,n=e.getType(),r=e.getTrack(),i=this.pc.peerconnection.getTransceivers().find(function(e){return e.receiver&&e.receiver.track&&e.receiver.track.kind===n});return i?(h.debug("Adding "+e+" on "+this.pc),"recvonly"===i.direction?(this.pc.peerconnection.addStream(e.getOriginalStream()),this.setEncodings(e),this.pc.localTracks.set(e.rtcId,e),i.direction="sendrecv",Promise.resolve(!1)):i.sender.replaceTrack(r).then(function(){return t.pc.localTracks.set(e.rtcId,e),Promise.resolve(!1)})):Promise.reject(new Error("RTCRtpTransceiver for "+n+" not found"))}},{key:"removeTrackMute",value:function(e){var t=this,n=e.getType(),r=this.pc.peerconnection.getTransceivers().find(function(t){return t.sender&&t.sender.track&&t.sender.track.id===e.getTrackId()});return r?(h.debug("Removing "+e+" on "+this.pc),r.sender.replaceTrack(null).then(function(){return t.pc.localTracks.delete(e.rtcId),Promise.resolve(!1)})):Promise.reject(new Error("RTCRtpTransceiver for "+n+" not found"))}},{key:"replaceTrack",value:function(e,t){var n=this;if(e&&t){var r=t.getType(),i=t.getOriginalStream(),o=r===d.a?i.getAudioTracks()[0]:i.getVideoTracks()[0],s=this.pc.peerconnection.getTransceivers().find(function(e){return e.receiver.track.kind===r&&!e.stopped});return s?(h.debug("Replacing "+e+" with "+t+" on "+this.pc),s.sender.replaceTrack(o).then(function(){var r=n.pc.localSSRCs.get(e.rtcId);n.pc.localTracks.delete(e.rtcId),n.pc.localSSRCs.delete(e.rtcId),n.pc._addedStreams=n.pc._addedStreams.filter(function(e){return e!==i}),n.pc.localTracks.set(t.rtcId,t),n.pc._addedStreams.push(i),n.pc.localSSRCs.set(t.rtcId,r),n.pc.eventEmitter.emit(u.a.LOCAL_TRACK_SSRC_UPDATED,t,n.pc._extractPrimarySSRC(r))})):Promise.reject(new Error("replace track failed"))}if(e&&!t){if(!this.removeTrackMute(e))return Promise.reject(new Error("replace track failed"));this.pc.localTracks.delete(e.rtcId),this.pc.localSSRCs.delete(e.rtcId)}else if(t&&!e){var c=this.pc.localSSRCs.get(t.rtcId);if(!this.addTrackUnmute(t))return Promise.reject(new Error("replace track failed"));t.emit(a.TRACK_MUTE_CHANGED,t),this.pc.localTracks.set(t.rtcId,t),this.pc.localSSRCs.set(t.rtcId,c)}return Promise.resolve(!1)}},{key:"setAudioTransferActive",value:function(e){return this.setMediaTransferActive("audio",e)}},{key:"setEncodings",value:function(e){var t=this.pc.peerconnection.getTransceivers().find(function(t){return t.sender&&t.sender.track&&t.sender.track.kind===e.getType()}),n=t.sender.getParameters();n.encodings=this._getStreamEncodings(e),t.sender.setParameters(n)}},{key:"setMediaTransferActive",value:function(e,t){var n=this.pc.peerconnection.getTransceivers().filter(function(t){return t.receiver&&t.receiver.track&&t.receiver.track.kind===e}),r=Array.from(this.pc.localTracks.values()).filter(function(t){return t.getType()===e});return t?n.forEach(function(e){if(r.length){e.direction="sendrecv";var t=e.sender.getParameters();t&&t.encodings&&t.encodings.length&&(t.encodings.forEach(function(e){e.active=!0}),e.sender.setParameters(t))}else e.direction="recvonly"}):n.forEach(function(e){e.direction="inactive"}),!1}},{key:"setVideoTransferActive",value:function(e){return this.setMediaTransferActive("video",e)}}]),e})()}).call(this,"modules/RTC/TPCUtils.js")},function(e,t){e.exports=(function(){"use strict";function e(t,n,r){_classCallCheck(this,e),this._userId=t,this.setDisplayName(n),this._isLocalStats=r||!1,this.setDominantSpeaker(!1),this.totalDominantSpeakerTime=0,this._dominantSpeakerStart=0,this._hasLeft=!1}return _createClass(e,[{key:"getUserId",value:function(){return this._userId}},{key:"getDisplayName",value:function(){return this.displayName}},{key:"setDisplayName",value:function(e){this.displayName=e}},{key:"isLocalStats",value:function(){return this._isLocalStats}},{key:"isDominantSpeaker",value:function(){return this._dominantSpeakerStart>0}},{key:"setDominantSpeaker",value:function(e){if(!this.isDominantSpeaker()&&e)this._dominantSpeakerStart=Date.now();else if(this.isDominantSpeaker()&&!e){var t=Date.now()-this._dominantSpeakerStart;this.totalDominantSpeakerTime+=t,this._dominantSpeakerStart=0}}},{key:"getTotalDominantSpeakerTime",value:function(){var e=this.totalDominantSpeakerTime;return this.isDominantSpeaker()&&(e+=Date.now()-this._dominantSpeakerStart),e}},{key:"hasLeft",value:function(){return this._hasLeft}},{key:"markAsHasLeft",value:function(){this._hasLeft=!0,this.setDominantSpeaker(!1)}}]),e})()},function(e,t){e.exports={IDENTITY_UPDATED:"authentication.identity_updated"}},function(module,exports,__webpack_require__){(function(process,global){var __WEBPACK_AMD_DEFINE_RESULT__;!(function(){"use strict";var ERROR="input is invalid type",WINDOW="object"==typeof window,root=WINDOW?window:{};root.JS_MD5_NO_WINDOW&&(WINDOW=!1);var WEB_WORKER=!WINDOW&&"object"==typeof self,NODE_JS=!root.JS_MD5_NO_NODE_JS&&"object"==typeof process&&process.versions&&process.versions.node;NODE_JS?root=global:WEB_WORKER&&(root=self);var COMMON_JS=!root.JS_MD5_NO_COMMON_JS&&"object"==typeof module&&module.exports,AMD=__webpack_require__(137),ARRAY_BUFFER=!root.JS_MD5_NO_ARRAY_BUFFER&&"undefined"!=typeof ArrayBuffer,HEX_CHARS="0123456789abcdef".split(""),EXTRA=[128,32768,8388608,-2147483648],SHIFT=[0,8,16,24],OUTPUT_TYPES=["hex","array","digest","buffer","arrayBuffer","base64"],BASE64_ENCODE_CHAR="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split(""),blocks=[],buffer8;if(ARRAY_BUFFER){var buffer=new ArrayBuffer(68);buffer8=new Uint8Array(buffer),blocks=new Uint32Array(buffer)}!root.JS_MD5_NO_NODE_JS&&Array.isArray||(Array.isArray=function(e){return"[object Array]"===Object.prototype.toString.call(e)}),!ARRAY_BUFFER||!root.JS_MD5_NO_ARRAY_BUFFER_IS_VIEW&&ArrayBuffer.isView||(ArrayBuffer.isView=function(e){return"object"==typeof e&&e.buffer&&e.buffer.constructor===ArrayBuffer});var createOutputMethod=function(e){return function(t){return new Md5(!0).update(t)[e]()}},createMethod=function(){var e=createOutputMethod("hex");NODE_JS&&(e=nodeWrap(e)),e.create=function(){return new Md5},e.update=function(t){return e.create().update(t)};for(var t=0;t>2]|=e[o]<>6,c[i++]=128|63&r):r<55296||r>=57344?(c[i++]=224|r>>12,c[i++]=128|r>>6&63,c[i++]=128|63&r):(r=65536+((1023&r)<<10|1023&e.charCodeAt(++o)),c[i++]=240|r>>18,c[i++]=128|r>>12&63,c[i++]=128|r>>6&63,c[i++]=128|63&r);else for(i=this.start;o>2]|=r<>2]|=(192|r>>6)<>2]|=(128|63&r)<=57344?(s[i>>2]|=(224|r>>12)<>2]|=(128|r>>6&63)<>2]|=(128|63&r)<>2]|=(240|r>>18)<>2]|=(128|r>>12&63)<>2]|=(128|r>>6&63)<>2]|=(128|63&r)<=64?(this.start=i-64,this.hash(),this.hashed=!0):this.start=i}return this.bytes>4294967295&&(this.hBytes+=this.bytes/4294967296<<0,this.bytes=this.bytes%4294967296),this}},Md5.prototype.finalize=function(){if(!this.finalized){this.finalized=!0;var e=this.blocks,t=this.lastByteIndex;e[t>>2]|=EXTRA[3&t],t>=56&&(this.hashed||this.hash(),e[0]=e[16],e[16]=e[1]=e[2]=e[3]=e[4]=e[5]=e[6]=e[7]=e[8]=e[9]=e[10]=e[11]=e[12]=e[13]=e[14]=e[15]=0),e[14]=this.bytes<<3,e[15]=this.hBytes<<3|this.bytes>>>29,this.hash()}},Md5.prototype.hash=function(){var e,t,n,r,i,o,a=this.blocks;this.first?t=((t=((e=((e=a[0]-680876937)<<7|e>>>25)-271733879<<0)^(n=((n=(-271733879^(r=((r=(-1732584194^2004318071&e)+a[1]-117830708)<<12|r>>>20)+e<<0)&(-271733879^e))+a[2]-1126478375)<<17|n>>>15)+r<<0)&(r^e))+a[3]-1316259209)<<22|t>>>10)+n<<0:(e=this.h0,t=this.h1,n=this.h2,t=((t+=((e=((e+=((r=this.h3)^t&(n^r))+a[0]-680876936)<<7|e>>>25)+t<<0)^(n=((n+=(t^(r=((r+=(n^e&(t^n))+a[1]-389564586)<<12|r>>>20)+e<<0)&(e^t))+a[2]+606105819)<<17|n>>>15)+r<<0)&(r^e))+a[3]-1044525330)<<22|t>>>10)+n<<0),t=((t+=((e=((e+=(r^t&(n^r))+a[4]-176418897)<<7|e>>>25)+t<<0)^(n=((n+=(t^(r=((r+=(n^e&(t^n))+a[5]+1200080426)<<12|r>>>20)+e<<0)&(e^t))+a[6]-1473231341)<<17|n>>>15)+r<<0)&(r^e))+a[7]-45705983)<<22|t>>>10)+n<<0,t=((t+=((e=((e+=(r^t&(n^r))+a[8]+1770035416)<<7|e>>>25)+t<<0)^(n=((n+=(t^(r=((r+=(n^e&(t^n))+a[9]-1958414417)<<12|r>>>20)+e<<0)&(e^t))+a[10]-42063)<<17|n>>>15)+r<<0)&(r^e))+a[11]-1990404162)<<22|t>>>10)+n<<0,t=((t+=((e=((e+=(r^t&(n^r))+a[12]+1804603682)<<7|e>>>25)+t<<0)^(n=((n+=(t^(r=((r+=(n^e&(t^n))+a[13]-40341101)<<12|r>>>20)+e<<0)&(e^t))+a[14]-1502002290)<<17|n>>>15)+r<<0)&(r^e))+a[15]+1236535329)<<22|t>>>10)+n<<0,t=((t+=((r=((r+=(t^n&((e=((e+=(n^r&(t^n))+a[1]-165796510)<<5|e>>>27)+t<<0)^t))+a[6]-1069501632)<<9|r>>>23)+e<<0)^e&((n=((n+=(e^t&(r^e))+a[11]+643717713)<<14|n>>>18)+r<<0)^r))+a[0]-373897302)<<20|t>>>12)+n<<0,t=((t+=((r=((r+=(t^n&((e=((e+=(n^r&(t^n))+a[5]-701558691)<<5|e>>>27)+t<<0)^t))+a[10]+38016083)<<9|r>>>23)+e<<0)^e&((n=((n+=(e^t&(r^e))+a[15]-660478335)<<14|n>>>18)+r<<0)^r))+a[4]-405537848)<<20|t>>>12)+n<<0,t=((t+=((r=((r+=(t^n&((e=((e+=(n^r&(t^n))+a[9]+568446438)<<5|e>>>27)+t<<0)^t))+a[14]-1019803690)<<9|r>>>23)+e<<0)^e&((n=((n+=(e^t&(r^e))+a[3]-187363961)<<14|n>>>18)+r<<0)^r))+a[8]+1163531501)<<20|t>>>12)+n<<0,t=((t+=((r=((r+=(t^n&((e=((e+=(n^r&(t^n))+a[13]-1444681467)<<5|e>>>27)+t<<0)^t))+a[2]-51403784)<<9|r>>>23)+e<<0)^e&((n=((n+=(e^t&(r^e))+a[7]+1735328473)<<14|n>>>18)+r<<0)^r))+a[12]-1926607734)<<20|t>>>12)+n<<0,t=((t+=((o=(r=((r+=((i=t^n)^(e=((e+=(i^r)+a[5]-378558)<<4|e>>>28)+t<<0))+a[8]-2022574463)<<11|r>>>21)+e<<0)^e)^(n=((n+=(o^t)+a[11]+1839030562)<<16|n>>>16)+r<<0))+a[14]-35309556)<<23|t>>>9)+n<<0,t=((t+=((o=(r=((r+=((i=t^n)^(e=((e+=(i^r)+a[1]-1530992060)<<4|e>>>28)+t<<0))+a[4]+1272893353)<<11|r>>>21)+e<<0)^e)^(n=((n+=(o^t)+a[7]-155497632)<<16|n>>>16)+r<<0))+a[10]-1094730640)<<23|t>>>9)+n<<0,t=((t+=((o=(r=((r+=((i=t^n)^(e=((e+=(i^r)+a[13]+681279174)<<4|e>>>28)+t<<0))+a[0]-358537222)<<11|r>>>21)+e<<0)^e)^(n=((n+=(o^t)+a[3]-722521979)<<16|n>>>16)+r<<0))+a[6]+76029189)<<23|t>>>9)+n<<0,t=((t+=((o=(r=((r+=((i=t^n)^(e=((e+=(i^r)+a[9]-640364487)<<4|e>>>28)+t<<0))+a[12]-421815835)<<11|r>>>21)+e<<0)^e)^(n=((n+=(o^t)+a[15]+530742520)<<16|n>>>16)+r<<0))+a[2]-995338651)<<23|t>>>9)+n<<0,t=((t+=((r=((r+=(t^((e=((e+=(n^(t|~r))+a[0]-198630844)<<6|e>>>26)+t<<0)|~n))+a[7]+1126891415)<<10|r>>>22)+e<<0)^((n=((n+=(e^(r|~t))+a[14]-1416354905)<<15|n>>>17)+r<<0)|~e))+a[5]-57434055)<<21|t>>>11)+n<<0,t=((t+=((r=((r+=(t^((e=((e+=(n^(t|~r))+a[12]+1700485571)<<6|e>>>26)+t<<0)|~n))+a[3]-1894986606)<<10|r>>>22)+e<<0)^((n=((n+=(e^(r|~t))+a[10]-1051523)<<15|n>>>17)+r<<0)|~e))+a[1]-2054922799)<<21|t>>>11)+n<<0,t=((t+=((r=((r+=(t^((e=((e+=(n^(t|~r))+a[8]+1873313359)<<6|e>>>26)+t<<0)|~n))+a[15]-30611744)<<10|r>>>22)+e<<0)^((n=((n+=(e^(r|~t))+a[6]-1560198380)<<15|n>>>17)+r<<0)|~e))+a[13]+1309151649)<<21|t>>>11)+n<<0,t=((t+=((r=((r+=(t^((e=((e+=(n^(t|~r))+a[4]-145523070)<<6|e>>>26)+t<<0)|~n))+a[11]-1120210379)<<10|r>>>22)+e<<0)^((n=((n+=(e^(r|~t))+a[2]+718787259)<<15|n>>>17)+r<<0)|~e))+a[9]-343485551)<<21|t>>>11)+n<<0,this.first?(this.h0=e+1732584193<<0,this.h1=t-271733879<<0,this.h2=n-1732584194<<0,this.h3=r+271733878<<0,this.first=!1):(this.h0=this.h0+e<<0,this.h1=this.h1+t<<0,this.h2=this.h2+n<<0,this.h3=this.h3+r<<0)},Md5.prototype.hex=function(){this.finalize();var e=this.h0,t=this.h1,n=this.h2,r=this.h3;return HEX_CHARS[e>>4&15]+HEX_CHARS[15&e]+HEX_CHARS[e>>12&15]+HEX_CHARS[e>>8&15]+HEX_CHARS[e>>20&15]+HEX_CHARS[e>>16&15]+HEX_CHARS[e>>28&15]+HEX_CHARS[e>>24&15]+HEX_CHARS[t>>4&15]+HEX_CHARS[15&t]+HEX_CHARS[t>>12&15]+HEX_CHARS[t>>8&15]+HEX_CHARS[t>>20&15]+HEX_CHARS[t>>16&15]+HEX_CHARS[t>>28&15]+HEX_CHARS[t>>24&15]+HEX_CHARS[n>>4&15]+HEX_CHARS[15&n]+HEX_CHARS[n>>12&15]+HEX_CHARS[n>>8&15]+HEX_CHARS[n>>20&15]+HEX_CHARS[n>>16&15]+HEX_CHARS[n>>28&15]+HEX_CHARS[n>>24&15]+HEX_CHARS[r>>4&15]+HEX_CHARS[15&r]+HEX_CHARS[r>>12&15]+HEX_CHARS[r>>8&15]+HEX_CHARS[r>>20&15]+HEX_CHARS[r>>16&15]+HEX_CHARS[r>>28&15]+HEX_CHARS[r>>24&15]},Md5.prototype.toString=Md5.prototype.hex,Md5.prototype.digest=function(){this.finalize();var e=this.h0,t=this.h1,n=this.h2,r=this.h3;return[255&e,e>>8&255,e>>16&255,e>>24&255,255&t,t>>8&255,t>>16&255,t>>24&255,255&n,n>>8&255,n>>16&255,n>>24&255,255&r,r>>8&255,r>>16&255,r>>24&255]},Md5.prototype.array=Md5.prototype.digest,Md5.prototype.arrayBuffer=function(){this.finalize();var e=new ArrayBuffer(16),t=new Uint32Array(e);return t[0]=this.h0,t[1]=this.h1,t[2]=this.h2,t[3]=this.h3,e},Md5.prototype.buffer=Md5.prototype.arrayBuffer,Md5.prototype.base64=function(){for(var e,t,n,r="",i=this.array(),o=0;o<15;)e=i[o++],t=i[o++],n=i[o++],r+=BASE64_ENCODE_CHAR[e>>>2]+BASE64_ENCODE_CHAR[63&(e<<4|t>>>4)]+BASE64_ENCODE_CHAR[63&(t<<2|n>>>6)]+BASE64_ENCODE_CHAR[63&n];return e=i[o],r+(BASE64_ENCODE_CHAR[e>>>2]+BASE64_ENCODE_CHAR[e<<4&63]+"==")};var exports=createMethod();COMMON_JS?module.exports=exports:(root.md5=exports,AMD&&(__WEBPACK_AMD_DEFINE_RESULT__=function(){return exports}.call(exports,__webpack_require__,exports,module),void 0===__WEBPACK_AMD_DEFINE_RESULT__||(module.exports=__WEBPACK_AMD_DEFINE_RESULT__)))})()}).call(this,__webpack_require__(51),__webpack_require__(43))},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return S});var r=n(4),i=n(54),o=n(17),a=n(14),s=n(15),c=n(1),u=n(10),d=n(41),l=n.n(d),h=n(9),p=n(8),f=n.n(p),m=n(13),v=n.n(m),g=n(7),y=n(5),_=Object(r.getLogger)(e),S=(function(e){function t(e){var n,r=e.deviceId,i=e.facingMode,o=e.mediaType,a=e.resolution,d=e.rtcId,l=e.sourceId,h=e.sourceType,p=e.stream,m=e.track,g=e.videoType,y=e.effects,_=void 0===y?[]:y;_classCallCheck(this,t),(n=_possibleConstructorReturn(this,_getPrototypeOf(t).call(this,null,p,m,function(){return n.emit(s.LOCAL_TRACK_STOPPED)},o,g)))._setEffectInProgress=!1;var S=_.find(function(e){return e.isEnabled(_assertThisInitialized(_assertThisInitialized(n)))});return S&&n._startStreamEffect(S),n.rtcId=d,n.sourceId=l,n.sourceType=h,c.a.usesNewGumFlow()?(n.resolution=m.getSettings().height,n._constraints=m.getConstraints(),Object.keys(n._constraints).length||g!==v.a.CAMERA||(n._constraints={height:m.getSettings().height,width:m.getSettings().width})):n.resolution=c.a.isFirefox()?null:a,n.deviceId=r,n._prevSetMuted=Promise.resolve(),n._facingMode=i,n._trackEnded=!1,n._hasSentData=!1,n._testDataSent=!0,n._realDeviceId=""===n.deviceId?void 0:n.deviceId,n._trackMutedTS=0,n._onDeviceListWillChange=function(e){var t=n._realDeviceId;n._setRealDeviceIdFromDeviceList(e),(void 0===n.getTrack().readyState&&void 0!==n._realDeviceId&&!e.find(function(e){return e.deviceId===n._realDeviceId})||void 0!==t&&void 0===n._realDeviceId)&&(n._trackEnded=!0)},n.isAudioTrack()&&u.a.isDeviceChangeAvailable("output")&&(n._onAudioOutputDeviceChanged=n.setAudioOutput.bind(_assertThisInitialized(_assertThisInitialized(n))),u.a.addListener(f.a.AUDIO_OUTPUT_DEVICE_CHANGED,n._onAudioOutputDeviceChanged)),u.a.addListener(f.a.DEVICE_LIST_WILL_CHANGE,n._onDeviceListWillChange),n._initNoDataFromSourceHandlers(),n}return _inherits(t,e),_createClass(t,[{key:"isEnded",value:function(){return this.isVideoTrack()&&this.isMuted()?this._trackEnded:"ended"===this.getTrack().readyState||this._trackEnded}},{key:"_initNoDataFromSourceHandlers",value:function(){var e=this;this._isNoDataFromSourceEventsEnabled()&&(this._setHandler("track_mute",function(){e._trackMutedTS=window.performance.now(),e._fireNoDataFromSourceEvent()}),this._setHandler("track_unmute",function(){e._fireNoDataFromSourceEvent(),y.a.sendAnalyticsAndLog(g.s,{media_type:e.getType(),track_type:"local",value:window.performance.now()-e._trackMutedTS})}),this.isVideoTrack()&&this.videoType===v.a.CAMERA&&this._setHandler("track_ended",function(){e.isReceivingData()||e._fireNoDataFromSourceEvent()}))}},{key:"_isNoDataFromSourceEventsEnabled",value:function(){return!this.isVideoTrack()||this.videoType!==v.a.DESKTOP}},{key:"_fireNoDataFromSourceEvent",value:function(){var e=!this.isReceivingData();this.emit(s.NO_DATA_FROM_SOURCE,e),y.a.sendAnalytics(Object(g.H)(this.getType(),e)),y.a.sendLog(JSON.stringify({name:s.NO_DATA_FROM_SOURCE,log:e}))}},{key:"_setRealDeviceIdFromDeviceList",value:function(e){var t=this.getTrack(),n=t.kind+"input",r=e.find(function(e){return e.kind===n&&e.label===t.label});if(!r&&"default"===this._realDeviceId){var i=(t.label||"").replace("Default - ","");r=e.find(function(e){return e.kind===n&&e.label===i})}this._realDeviceId=r?r.deviceId:void 0}},{key:"_setStream",value:function(e){_get(_getPrototypeOf(t.prototype),"_setStream",this).call(this,e),e?(this.storedMSID=this.getMSID(),_.debug("Setting new MSID: "+this.storedMSID+" on "+this)):_.debug("Setting 'null' stream on "+this)}},{key:"_startStreamEffect",value:function(e){this._streamEffect=e,this._originalStream=this.stream,this._setStream(this._streamEffect.startEffect(this._originalStream)),this.track=this.stream.getTracks()[0]}},{key:"_stopStreamEffect",value:function(){this._streamEffect&&(this._streamEffect.stopEffect(),this._setStream(this._originalStream),this.track=this.stream.getTracks()[0])}},{key:"_switchStreamEffect",value:function(e){this._streamEffect&&(this._stopStreamEffect(),this._streamEffect=void 0),e&&this._startStreamEffect(e)}},{key:"setEffect",value:function(e){var t=this;if(void 0===this._streamEffect&&void 0===e)return Promise.resolve();if(void 0!==e&&!e.isEnabled(this))return Promise.reject(new Error("Incompatible effect instance!"));if(!0===this._setEffectInProgress)return Promise.reject(new Error("setEffect already in progress!"));if(this.isMuted()&&!this.isAudioTrack())return this._streamEffect=e,Promise.resolve();var n=this.conference;return n?(this._setEffectInProgress=!0,c.a.usesUnifiedPlan()?(this._switchStreamEffect(e),this.isVideoTrack()&&this.containers.forEach(function(e){return u.a.attachMediaStream(e,t.stream)}),n.replaceTrack(this,this).then(function(){t._setEffectInProgress=!1}).catch(function(e){throw t._setEffectInProgress=!1,t._switchStreamEffect(),_.error("Failed to switch to the new stream!",e),e})):n.removeTrack(this).then(function(){return t._switchStreamEffect(e),t.isVideoTrack()&&t.containers.forEach(function(e){return u.a.attachMediaStream(e,t.stream)}),n.addTrack(t)}).then(function(){t._setEffectInProgress=!1}).catch(function(e){throw t._setEffectInProgress=!1,t._switchStreamEffect(),_.error("Failed to switch to the new stream!",e),e})):(this._switchStreamEffect(e),Promise.resolve())}},{key:"mute",value:function(){return this._queueSetMuted(!0)}},{key:"unmute",value:function(){return this._queueSetMuted(!1)}},{key:"_queueSetMuted",value:function(e){var t=this._setMuted.bind(this,e);return this._prevSetMuted=this._prevSetMuted.then(t,t),this._prevSetMuted}},{key:"_setMuted",value:function(e){var t=this;if(this.isMuted()===e)return Promise.resolve();if(this.disposed)return Promise.reject(new o.a(a.TRACK_IS_DISPOSED));var n=Promise.resolve(),r=function(){return _.info("Mute "+t+": "+e)};if(this.isAudioTrack()||this.videoType===v.a.DESKTOP||!c.a.doesVideoMuteByStreamRemove())r(),this.track&&(this.track.enabled=!e);else if(e)n=new Promise(function(e,n){r(),t._removeStreamFromConferenceAsMute(function(){t._streamEffect&&t._stopStreamEffect(),t._unregisterHandlers(),t.stopStream(),t._setStream(null),e()},n)});else{r();var i={cameraDeviceId:this.getDeviceId(),devices:[h.c],effects:this._streamEffect?[this._streamEffect]:[],facingMode:this.getCameraFacingMode()};c.a.usesNewGumFlow()?n=u.a.newObtainAudioAndVideoPermissions(_extends({},i,{constraints:{video:this._constraints}})):(this.resolution&&(i.resolution=this.resolution),n=u.a.obtainAudioAndVideoPermissions(i)),n=n.then(function(e){var n=t.getType()===h.b?h.c:t.getType(),r=c.a.usesNewGumFlow()?e.find(function(e){return e.track.kind===n}):e.find(function(e){return e.mediaType===n});if(!r)throw new o.a(a.TRACK_NO_STREAM_FOUND);return t._setStream(r.stream),t.track=r.track,t.videoType!==r.videoType&&(_.warn(t+": video type has changed after unmute!",t.videoType,r.videoType),t.videoType=r.videoType),t._streamEffect&&t._startStreamEffect(t._streamEffect),t.containers.map(function(e){return u.a.attachMediaStream(e,t.stream)}),t._addStreamToConferenceAsUnmute()})}return n.then(function(){return t._sendMuteStatus(e)}).then(function(){return t.emit(s.TRACK_MUTE_CHANGED,t)})}},{key:"_addStreamToConferenceAsUnmute",value:function(){var e=this;return this.conference?new Promise(function(t,n){e.conference._addLocalTrackAsUnmute(e).then(t,function(e){return n(new Error(e))})}):Promise.resolve()}},{key:"_removeStreamFromConferenceAsMute",value:function(e,t){this.conference?this.conference._removeLocalTrackAsMute(this).then(e,function(e){return t(new Error(e))}):e()}},{key:"_sendMuteStatus",value:function(e){var t=this;return this.conference&&this.conference.room?new Promise(function(n){t.conference.room[t.isAudioTrack()?"setAudioMute":"setVideoMute"](e,n)}):Promise.resolve()}},{key:"dispose",value:function(){var e=this;this._switchStreamEffect();var n=Promise.resolve();return this.conference&&(n=this.conference.removeTrack(this)),this.stream&&(this.stopStream(),this.detach()),u.a.removeListener(f.a.DEVICE_LIST_WILL_CHANGE,this._onDeviceListWillChange),this._onAudioOutputDeviceChanged&&u.a.removeListener(f.a.AUDIO_OUTPUT_DEVICE_CHANGED,this._onAudioOutputDeviceChanged),n.then(function(){return _get(_getPrototypeOf(t.prototype),"dispose",e).call(e)})}},{key:"isMuted",value:function(){return!(this.stream&&(!this.isVideoTrack()||this.isActive())&&this.track&&this.track.enabled)}},{key:"_setConference",value:function(e){this.conference=e;for(var t=0;t0&&(this._hasSentData=!0);var r=e.getConnectionState();this._testDataSent&&"connected"===r&&(setTimeout(function(){n._hasSentData||(_.warn(n+" 'bytes sent' <= 0: "+t),y.a.analytics.sendEvent(g.r,{media_type:n.getType()}))},3e3),this._testDataSent=!1)}},{key:"getCameraFacingMode",value:function(){if(this.isVideoTrack()&&this.videoType===v.a.CAMERA){var e;try{e=this.track.getSettings()}catch(e){}return e&&"facingMode"in e?e.facingMode:void 0!==this._facingMode?this._facingMode:l.a.USER}}},{key:"stopStream",value:function(){this._stopStreamInProgress=!0;try{u.a.stopMediaStream(this.stream)}finally{this._stopStreamInProgress=!1}}},{key:"_switchCamera",value:function(){this.isVideoTrack()&&this.videoType===v.a.CAMERA&&"function"==typeof this.track._switchCamera&&(this.track._switchCamera(),this._facingMode=this._facingMode===l.a.ENVIRONMENT?l.a.USER:l.a.ENVIRONMENT)}},{key:"isReceivingData",value:function(){return!(!this.isVideoTrack()||!this.isMuted()&&!this._stopStreamInProgress&&this.videoType!==v.a.DESKTOP)||!!this.stream&&(this._effectEnabled?this._originalStream:this.stream).getTracks().some(function(e){return!("readyState"in e&&"live"!==e.readyState||"muted"in e&&!0===e.muted)})}},{key:"toString",value:function(){return"LocalTrack["+this.rtcId+","+this.getType()+"]"}}]),t})(i.a)}).call(this,"modules/RTC/JitsiLocalTrack.js")},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return u});var r=n(20),i=n(4),o=n(2),a=n(21),s=n(56),c=Object(i.getLogger)(e),u=(function(e){function t(e,n){var r;return _classCallCheck(this,t),(r=_possibleConstructorReturn(this,_getPrototypeOf(t).call(this)))._createVADProcessor=n,r._vadEmitter=null,r._isVADEmitterRunning=!1,r._detectionServices=[],r._vadInitTracker=Promise.resolve(),r._processVADScore=r._processVADScore.bind(_assertThisInitialized(_assertThisInitialized(r))),e.on(o.TRACK_ADDED,r._trackAdded.bind(_assertThisInitialized(_assertThisInitialized(r)))),e.on(o.TRACK_REMOVED,r._trackRemoved.bind(_assertThisInitialized(_assertThisInitialized(r)))),e.on(o.TRACK_MUTE_CHANGED,r._trackMuteChanged.bind(_assertThisInitialized(_assertThisInitialized(r)))),r}return _inherits(t,e),_createClass(t,[{key:"addVADDetectionService",value:function(e){var t=this;this._detectionServices.push(e),e.on(a.DETECTOR_STATE_CHANGE,function(){!t._detectionServices.filter(function(e){return!0===e.isActive()}).length&&t._isVADEmitterRunning?t._stopVADEmitter():t._isVADEmitterRunning||t._startVADEmitter()})}},{key:"_startVADEmitter",value:function(){this._vadEmitter.on(a.VAD_SCORE_PUBLISHED,this._processVADScore),this._vadEmitter.start(),this._isVADEmitterRunning=!0}},{key:"_stopVADEmitter",value:function(){this._vadEmitter.removeListener(a.VAD_SCORE_PUBLISHED,this._processVADScore),this._vadEmitter.stop(),this._isVADEmitterRunning=!1}},{key:"_processVADScore",value:function(e){var t=this._detectionServices,n=Array.isArray(t),r=0;for(t=n?t:t["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var i;if(n){if(r>=t.length)break;i=t[r++]}else{if((r=t.next()).done)break;i=r.value}i.processVADScore(e)}}},{key:"_changeDetectorsMuteState",value:function(e){var t=this._detectionServices,n=Array.isArray(t),r=0;for(t=n?t:t["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var i;if(n){if(r>=t.length)break;i=t[r++]}else{if((r=t.next()).done)break;i=r.value}i.changeMuteState(e)}}},{key:"_trackAdded",value:function(e){var t=this;e.isLocalAudioTrack()&&(this._vadInitTracker=this._vadInitTracker.then(function(){return t._createVADProcessor()}).then(function(t){return s.a.create(e.getDeviceId(),4096,t)}).then(function(n){c.debug("Created VAD emitter for track: ",e.getTrackLabel()),t._vadEmitter=n,t._changeDetectorsMuteState(e.isMuted())}))}},{key:"_trackMuteChanged",value:function(e){var t=this;e.isLocalAudioTrack()&&(this._vadInitTracker=this._vadInitTracker.then(function(){t._changeDetectorsMuteState(e.isMuted())}))}},{key:"_trackRemoved",value:function(e){var t=this;e.isLocalAudioTrack()&&(this._vadInitTracker=this._vadInitTracker.then(function(){c.debug("Removing track from VAD detection - ",e.getTrackLabel()),t._vadEmitter&&(t._stopVADEmitter(),t._vadEmitter.destroy(),t._vadEmitter=null);var n=t._detectionServices,r=Array.isArray(n),i=0;for(n=r?n:n["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var o;if(r){if(i>=n.length)break;o=n[i++]}else{if((i=n.next()).done)break;o=i.value}o.reset()}}))}}]),t})(r.EventEmitter)}).call(this,"modules/detection/VADAudioAnalyser.js")},function(e,t,n){"use strict";n.d(t,"a",function(){return o});var r=n(3),i=n(46),o=(function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};_classCallCheck(this,e),this._connection=t.connection,this._mode=t.mode,this._setSessionID(t.sessionID),this.setStatus(t.status)}return _createClass(e,[{key:"getError",value:function(){return this._error}},{key:"getID",value:function(){return this._sessionID}},{key:"getInitiator",value:function(){return this._initiator}},{key:"getLiveStreamViewURL",value:function(){return this._liveStreamViewURL}},{key:"getStatus",value:function(){return this._status}},{key:"getTerminator",value:function(){return this._terminator}},{key:"getMode",value:function(){return this._mode}},{key:"setError",value:function(e){this._error=e}},{key:"setLiveStreamViewURL",value:function(e){this._liveStreamViewURL=e}},{key:"setStatus",value:function(e){this._status=e}},{key:"setInitiator",value:function(e){this._initiator=e}},{key:"setTerminator",value:function(e){this._terminator=e}},{key:"start",value:function(e){var t=this,n=e.appData,r=e.broadcastId,o=e.focusMucJid,a=e.streamId;return new Promise(function(e,s){t._connection.sendIQ(t._createIQ({action:"start",appData:n,focusMucJid:o,broadcastId:r,streamId:a}),function(n){t.setStatus("pending"),t._setSessionID(i.a.getSessionIdFromIq(n)),e()},function(e){t._setErrorFromIq(e),s(e)})})}},{key:"stop",value:function(e){var t=this,n=e.focusMucJid;return new Promise(function(e,r){t._connection.sendIQ(t._createIQ({action:"stop",focusMucJid:n}),e,r)})}},{key:"_createIQ",value:function(e){var t=e.action,n=e.appData,i=e.broadcastId,o=e.focusMucJid,a=e.streamId;return Object(r.$iq)({to:o,type:"set"}).c("jibri",{xmlns:"http://jitsi.org/protocol/jibri",action:t,app_data:n,recording_mode:this._mode,streamid:a,you_tube_broadcast_id:i}).up()}},{key:"_setErrorFromIq",value:function(e){var t=e.getElementsByTagName("error")[0];this.setError(t.children[0].tagName)}},{key:"_setSessionID",value:function(e){this._sessionID=e}}]),e})()},function(e,t,n){"use strict";var r=n(20),i=n.n(r),o=n(9),a=n(1),s=n(12),c=n(8),u=n.n(c),d=n(5),l=n(48);function h(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var p="microphone",f="camera";t.a=new((function(){function e(){var t=this;_classCallCheck(this,e),this._eventEmitter=new i.a,this._grantedPermissions={},s.a.addListener(u.a.DEVICE_LIST_CHANGED,function(e){return t._eventEmitter.emit(l.DEVICE_LIST_CHANGED,e)}),s.a.addListener(u.a.DEVICE_LIST_AVAILABLE,function(e){return t._logOutputDevice(t.getAudioOutputDevice(),e)}),s.a.addListener(u.a.GRANTED_PERMISSIONS,function(e){return t._handleGrantedPermissions(e)}),this._permissionsApiSupported=new Promise(function(e){navigator.permissions?navigator.permissions.query({name:f}).then(function(){return e(!0)},function(){return e(!1)}):e(!1)})}return _createClass(e,[{key:"_handleGrantedPermissions",value:function(e){this._grantedPermissions=(function(e){for(var t=1;t0&&this._logOutputDevice(e,s.a.getCurrentlyAvailableMediaDevices()),s.a.setAudioOutputDevice(e)}},{key:"addEventListener",value:function(e,t){this._eventEmitter.addListener(e,t)}},{key:"removeEventListener",value:function(e,t){this._eventEmitter.removeListener(e,t)}},{key:"emitEvent",value:function(e){for(var t,n=arguments.length,r=new Array(n>1?n-1:0),i=1;i1&&l.push("<"+a.methodName+">: ");var h=l.concat(o);d.bind(u).apply(u,h)}}}function a(e,t,r,i){this.id=t,this.options=i||{},this.transports=r,this.transports||(this.transports=[]),this.level=n[e];for(var a=Object.keys(n),s=0;s0&&t.data.push(e.data)},t},d.prototype.removeTrack=function(e){if(!e.isVideoTrack()){var t,n=this.recorders;for(t=0;t=r.length)break;h=r[l++]}else{if((l=r.next()).done)break;h=l.value}var p=h,f=o.a.obtainAudioAndVideoPermissions({devices:["audio"],micDeviceId:p.deviceId}).then(function(e){var t=e[0],n=t.getOriginalStream();return a.a.startLocalStats(n,t.setAudioLevel.bind(t)),t.addEventListener(i.LOCAL_TRACK_STOPPED,function(){a.a.stopLocalStats(n)}),t});n.push(f)}Promise.allSettled(n).then(function(t){var n=t.filter(function(e){return"fulfilled"===e.status}),r=t.filter(function(e){return"rejected"===e.status}),o=n.map(function(e){return e.value}),a=r.map(function(e){return e.value}),u=Array.isArray(a),l=0;for(a=u?a:a["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var h;if(u){if(l>=a.length)break;h=a[l++]}else{if((l=a.next()).done)break;h=l.value}var p=h;s.error("Failed to acquire audio device with error: ",p)}var f=function(t){t.on(i.TRACK_AUDIO_LEVEL_CHANGED,function(n){n>.008&&(d(o),e({deviceId:t.deviceId,deviceLabel:t.track.label}))})},m=o,v=Array.isArray(m),g=0;for(m=v?m:m["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var y;if(v){if(g>=m.length)break;y=m[g++]}else{if((g=m.next()).done)break;y=g.value}f(y)}setTimeout(function(){d(o),e({deviceId:"",deviceLabel:""})},c)})})})}function d(e){var t=e,n=Array.isArray(t),r=0;for(t=n?t:t["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var i;if(n){if(r>=t.length)break;i=t[r++]}else{if((r=t.next()).done)break;i=r.value}i.stopStream()}}}).call(this,"modules/detection/ActiveDeviceDetector.js")},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return l});var r=n(4),i=n(8),o=n.n(i),a=n(7),s=n(5),c=n(11),u=n.n(c),d=Object(r.getLogger)(e),l=(function(){function e(t,n,r){if(_classCallCheck(this,e),!t&&!n)throw new TypeError("At least peerconnection or wsUrl must be given");if(t&&n)throw new TypeError("Just one of peerconnection or wsUrl must be given");if(t?d.debug("constructor() with peerconnection"):d.debug("constructor() with wsUrl:\""+n+"\""),this._channel=null,this._eventEmitter=r,this._mode=null,this._areRetriesEnabled=!1,this._closedFromClient=!1,t){var i=t.createDataChannel("JVB data channel",{protocol:"http://jitsi.org/protocols/colibri"});this._handleChannel(i),this._mode="datachannel"}else n&&(this._areRetriesEnabled=!0,this._wsUrl=n,this._initWebSocket())}return _createClass(e,[{key:"_initWebSocket",value:function(){var e=new WebSocket(this._wsUrl);this._handleChannel(e),this._mode="websocket"}},{key:"_startConnectionRetries",value:function(){var e=this,t=1;this._retryTimeout=setTimeout(function n(){e.isOpen()||(e._initWebSocket(e._wsUrl),t=Math.min(2*t,60),e._retryTimeout=setTimeout(n,1e3*t))},1e3*t)}},{key:"_stopConnectionRetries",value:function(){this._retryTimeout&&(clearTimeout(this._retryTimeout),this._retryTimeout=void 0)}},{key:"_retryWebSocketConnection",value:function(e){var t=this;if(this._areRetriesEnabled){var n=e.code,r=e.reason;s.a.sendAnalytics(Object(a.y)(n,r)),this._areRetriesEnabled=!1,this._eventEmitter.once(o.a.DATA_CHANNEL_OPEN,function(){t._stopConnectionRetries(),t._areRetriesEnabled=!0}),this._startConnectionRetries()}}},{key:"close",value:function(){if(this._closedFromClient=!0,this._stopConnectionRetries(),this._areRetriesEnabled=!1,this._channel){try{this._channel.close()}catch(e){}this._channel=null}}},{key:"isOpen",value:function(){return this._channel&&("open"===this._channel.readyState||this._channel.readyState===WebSocket.OPEN)}},{key:"sendMessage",value:function(e,t){this._send({colibriClass:"EndpointMessage",msgPayload:t,to:e})}},{key:"sendSetLastNMessage",value:function(e){var t={colibriClass:"LastNChangedEvent",lastN:e};this._send(t),d.log("Channel lastN set to: "+e)}},{key:"sendPinnedEndpointMessage",value:function(e){d.log("sending pinned changed notification to the bridge for endpoint ",e),this._send({colibriClass:"PinnedEndpointChangedEvent",pinnedEndpoint:e||null})}},{key:"sendSelectedEndpointsMessage",value:function(e){d.log("sending selected changed notification to the bridge for endpoints",e),this._send({colibriClass:"SelectedEndpointsChangedEvent",selectedEndpoints:e})}},{key:"sendReceiverVideoConstraintMessage",value:function(e){d.log("sending a ReceiverVideoConstraint message with a maxFrameHeight of "+e+" pixels"),this._send({colibriClass:"ReceiverVideoConstraint",maxFrameHeight:e})}},{key:"_handleChannel",value:function(e){var t=this,n=this._eventEmitter;e.onopen=function(){d.info(t._mode+" channel opened"),n.emit(o.a.DATA_CHANNEL_OPEN)},e.onerror=function(e){"websocket"!==t._mode&&d.error("Channel error: "+e.message)},e.onmessage=function(e){var t,r=e.data;try{t=JSON.parse(r)}catch(e){return u.a.callErrorHandler(e),void d.error("Failed to parse channel message as JSON: ",r,e)}var i=t.colibriClass;switch(i){case"DominantSpeakerEndpointChangeEvent":var a=t.dominantSpeakerEndpoint;d.info("Channel new dominant speaker event: ",a),n.emit(o.a.DOMINANT_SPEAKER_CHANGED,a);break;case"EndpointConnectivityStatusChangeEvent":var s=t.endpoint,c="true"===t.active;d.info("Endpoint connection status changed: "+s+" active ? "+c),n.emit(o.a.ENDPOINT_CONN_STATUS_CHANGED,s,c);break;case"EndpointMessage":n.emit(o.a.ENDPOINT_MESSAGE_RECEIVED,t.from,t.msgPayload);break;case"LastNEndpointsChangeEvent":var l=t.lastNEndpoints;d.info("Channel new last-n event: ",l,t),n.emit(o.a.LASTN_ENDPOINT_CHANGED,l,t);break;case"SelectedUpdateEvent":var h=t.isSelected;d.info("SelectedUpdateEvent isSelected? "+h),n.emit(o.a.IS_SELECTED_CHANGED,h);break;default:d.debug("Channel JSON-formatted message: ",t),n.emit("rtc.datachannel."+i,t)}},e.onclose=function(e){d.info("Channel closed by "+(t._closedFromClient?"client":"server")),"websocket"===t._mode&&(t._closedFromClient||(d.error("Channel closed: "+e.code+" "+e.reason),t._retryWebSocketConnection(e))),t._channel=null},this._channel=e}},{key:"_send",value:function(e){var t=this._channel;if(!this.isOpen())throw d.error("Bridge Channel send: no opened channel."),new Error("No opened channel");t.send(JSON.stringify(e))}},{key:"mode",get:function(){return this._mode}}]),e})()}).call(this,"modules/RTC/BridgeChannel.js")},function(e,t,n){"use strict";(function(e){var r=n(7),i=n(4),o=n(1);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var s=Object(i.getLogger)(e);t.a=new((function(){function e(){_classCallCheck(this,e),this.reset()}return _createClass(e,[{key:"reset",value:function(){this.disposed=!1,this.analyticsHandlers=new Set,this.cache=[],this.permanentProperties={},this.conferenceName="",this.addPermanentProperties({user_agent:navigator.userAgent,browser_name:o.a.getName()})}},{key:"dispose",value:function(){s.warn("Disposing of analytics adapter."),this.analyticsHandlers&&this.analyticsHandlers.size>0&&this.analyticsHandlers.forEach(function(e){"function"==typeof e.dispose&&e.dispose()}),this.setAnalyticsHandlers([]),this.disposed=!0}},{key:"setAnalyticsHandlers",value:function(e){var t=this;if(!this.disposed){this.analyticsHandlers=new Set(e),this._setUserProperties();var n=this.cache;this.cache=null,n&&n.forEach(function(e){return t._sendEvent(e)})}}},{key:"_setUserProperties",value:function(){var e=this;this.analyticsHandlers.forEach(function(t){try{t.setUserProperties(e.permanentProperties)}catch(t){s.warn("Error in setUserProperties method of one of the analytics handlers: "+t)}})}},{key:"addPermanentProperties",value:function(e){this.permanentProperties=(function(e){for(var t=1;t1&&void 0!==arguments[1]?arguments[1]:{};if(!this.disposed){var n=null;"string"==typeof e?n={type:r.t,action:e,actionSubject:e,source:e,attributes:t}:"object"==typeof e&&(n=e),this._verifyRequiredFields(n)?this._sendEvent(n):s.error("Dropping a mis-formatted event: "+JSON.stringify(n))}}},{key:"_verifyRequiredFields",value:function(e){if(!e)return!1;e.type||(e.type=r.t);var t=e.type;return t!==r.t&&t!==r.u&&t!==r.w&&t!==r.v?(s.error("Unknown event type: "+t),!1):t===r.u?Boolean(e.name):(e.action=e.action||e.name||e.actionSubject,e.actionSubject=e.actionSubject||e.name||e.action,e.source=e.source||e.name||e.action||e.actionSubject,e.action&&e.actionSubject&&e.source?!!(t!==r.v||(e.objectType=e.objectType||"generic-object-type",e.containerType=e.containerType||"conference","conference"!==e.containerType||e.containerId||(e.containerId=this.conferenceName),e.objectType&&e.objectId&&e.containerType&&e.containerId))||(s.error("Required field missing (containerId, containerType, objectId or objectType)"),!1):(s.error("Required field missing (action, actionSubject or source)"),!1))}},{key:"_maybeCacheEvent",value:function(e){return!!this.cache&&(this.cache.push(e),this.cache.length>100&&this.cache.splice(0,1),!0)}},{key:"_sendEvent",value:function(e){this._maybeCacheEvent(e)||this.analyticsHandlers.forEach(function(t){try{t.sendEvent(e)}catch(e){s.warn("Error sending analytics event: "+e)}})}}]),e})())}).call(this,"modules/statistics/AnalyticsAdapter.js")},function(e,t,n){"use strict";(function(e,r){n.d(t,"a",function(){return s});var i=n(4),o=n(16),a=Object(i.getLogger)(e),s=(function(e){function t(){var e;return _classCallCheck(this,t),e=_possibleConstructorReturn(this,_getPrototypeOf(t).call(this)),a.info("This appears to be "+e.getName()+", ver: "+e.getVersion()),e}return _inherits(t,e),_createClass(t,[{key:"doesVideoMuteByStreamRemove",value:function(){return this.isChromiumBased()||this.isSafari()}},{key:"supportsP2P",value:function(){return!this.usesUnifiedPlan()}},{key:"isChromiumBased",value:function(){return this.isChrome()||this.isElectron()||this.isNWJS()||this.isOpera()}},{key:"isSupported",value:function(){return this.isChromiumBased()||this.isFirefox()||this.isReactNative()||this.isSafari()&&!this.isVersionLessThan("12.1")}},{key:"isUserInteractionRequiredForUnmute",value:function(){return this.isFirefox()&&this.isVersionLessThan("68")||this.isSafari()}},{key:"supportsVideoMuteOnConnInterrupted",value:function(){return this.isChromiumBased()||this.isReactNative()||this.isSafari()}},{key:"supportsBandwidthStatistics",value:function(){return!this.isFirefox()&&!this.isSafari()}},{key:"supportsDeviceChangeEvent",value:function(){return navigator.mediaDevices&&void 0!==navigator.mediaDevices.ondevicechange&&void 0!==navigator.mediaDevices.addEventListener}},{key:"supportsLocalCandidateRttStatistics",value:function(){return this.isChromiumBased()||this.isReactNative()||this.isSafari()}},{key:"supportsRTTStatistics",value:function(){return!this.isFirefox()}},{key:"supportsRtpSender",value:function(){return this.isFirefox()||this.isSafari()}},{key:"supportsRtx",value:function(){return!this.isFirefox()}},{key:"supportsVideo",value:function(){return!0}},{key:"usesPlanB",value:function(){return!this.usesUnifiedPlan()}},{key:"usesSdpMungingForSimulcast",value:function(){return this.isChromiumBased()||this.isSafari()}},{key:"usesUnifiedPlan",value:function(){return!!this.isFirefox()||!(!this.isSafari()||void 0===window.RTCRtpTransceiver)&&Object.keys(RTCRtpTransceiver.prototype).indexOf("currentDirection")>-1}},{key:"usesNewGumFlow",value:function(){return this.isChrome()?!this.isVersionLessThan(61):!(!this.isFirefox()&&!this.isSafari())||!!this.isChromiumBased()&&this._getChromiumBasedVersion()>=61}},{key:"usesAdapter",value:function(){return this.usesNewGumFlow()}},{key:"usesRidsForSimulcast",value:function(){return!1}},{key:"supportsGetDisplayMedia",value:function(){return void 0!==navigator.getDisplayMedia||void 0!==navigator.mediaDevices&&void 0!==navigator.mediaDevices.getDisplayMedia}},{key:"supportsInsertableStreams",value:function(){return Boolean(void 0!==window.RTCRtpSender&&window.RTCRtpSender.prototype.createEncodedVideoStreams)}},{key:"supportsSdpSemantics",value:function(){return this.isChromiumBased()&&this._getChromiumBasedVersion()>=65}},{key:"_getChromiumBasedVersion",value:function(){if(this.isChromiumBased()){if(this.isNWJS())return Number.parseInt(r.versions.chromium,10);var e=navigator.userAgent;if(e.match(/Chrome/))return Number.parseInt(e.match(/Chrome\/([\d.]+)/)[1],10)}return-1}}]),t})(o.a)}).call(this,"modules/browser/BrowserCapabilities.js",n(51))},function(e,t,n){e.exports=(function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&("function"==typeof Symbol?Symbol.toStringTag:"@@toStringTag")&&Object.defineProperty(e,"function"==typeof Symbol?Symbol.toStringTag:"@@toStringTag",{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)n.d(r,i,function(t){return e[t]}.bind(null,i));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=90)})({17:function(e,t,n){"use strict";t.__esModule=!0,t.default=void 0;var r=n(18),i=(function(){function e(){}return e.getFirstMatch=function(e,t){var n=t.match(e);return n&&n.length>0&&n[1]||""},e.getSecondMatch=function(e,t){var n=t.match(e);return n&&n.length>1&&n[2]||""},e.matchAndReturnConst=function(e,t,n){if(e.test(t))return n},e.getWindowsVersionName=function(e){switch(e){case"NT":return"NT";case"XP":return"XP";case"NT 5.0":return"2000";case"NT 5.1":return"XP";case"NT 5.2":return"2003";case"NT 6.0":return"Vista";case"NT 6.1":return"7";case"NT 6.2":return"8";case"NT 6.3":return"8.1";case"NT 10.0":return"10";default:return}},e.getMacOSVersionName=function(e){var t=e.split(".").splice(0,2).map(function(e){return parseInt(e,10)||0});if(t.push(0),10===t[0])switch(t[1]){case 5:return"Leopard";case 6:return"Snow Leopard";case 7:return"Lion";case 8:return"Mountain Lion";case 9:return"Mavericks";case 10:return"Yosemite";case 11:return"El Capitan";case 12:return"Sierra";case 13:return"High Sierra";case 14:return"Mojave";case 15:return"Catalina";default:return}},e.getAndroidVersionName=function(e){var t=e.split(".").splice(0,2).map(function(e){return parseInt(e,10)||0});if(t.push(0),!(1===t[0]&&t[1]<5))return 1===t[0]&&t[1]<6?"Cupcake":1===t[0]&&t[1]>=6?"Donut":2===t[0]&&t[1]<2?"Eclair":2===t[0]&&2===t[1]?"Froyo":2===t[0]&&t[1]>2?"Gingerbread":3===t[0]?"Honeycomb":4===t[0]&&t[1]<1?"Ice Cream Sandwich":4===t[0]&&t[1]<4?"Jelly Bean":4===t[0]&&t[1]>=4?"KitKat":5===t[0]?"Lollipop":6===t[0]?"Marshmallow":7===t[0]?"Nougat":8===t[0]?"Oreo":9===t[0]?"Pie":void 0},e.getVersionPrecision=function(e){return e.split(".").length},e.compareVersions=function(t,n,r){void 0===r&&(r=!1);var i=e.getVersionPrecision(t),o=e.getVersionPrecision(n),a=Math.max(i,o),s=0,c=e.map([t,n],function(t){var n=a-e.getVersionPrecision(t),r=t+new Array(n+1).join(".0");return e.map(r.split("."),function(e){return new Array(20-e.length).join("0")+e}).reverse()});for(r&&(s=a-Math.min(i,o)),a-=1;a>=s;){if(c[0][a]>c[1][a])return 1;if(c[0][a]===c[1][a]){if(a===s)return 0;a-=1}else if(c[0][a]0){var a=Object.keys(n),s=a.find(function(e){return t.isOS(e)});if(s){var c=this.satisfies(n[s]);if(void 0!==c)return c}var u=a.find(function(e){return t.isPlatform(e)});if(u){var d=this.satisfies(n[u]);if(void 0!==d)return d}}if(o>0){var l=Object.keys(i).find(function(e){return t.isBrowser(e,!0)});if(void 0!==l)return this.compareVersion(i[l])}},t.isBrowser=function(e,t){void 0===t&&(t=!1);var n=this.getBrowserName().toLowerCase(),r=e.toLowerCase(),i=s.default.getBrowserTypeByAlias(r);return t&&i&&(r=i.toLowerCase()),r===n},t.compareVersion=function(e){var t=[0],n=e,r=!1,i=this.getBrowserVersion();if("string"==typeof i)return">"===e[0]||"<"===e[0]?(n=e.substr(1),"="===e[1]?(r=!0,n=e.substr(2)):t=[],">"===e[0]?t.push(1):t.push(-1)):"="===e[0]?n=e.substr(1):"~"===e[0]&&(r=!0,n=e.substr(1)),t.indexOf(s.default.compareVersions(i,n,r))>-1},t.isOS=function(e){return this.getOSName(!0)===String(e).toLowerCase()},t.isPlatform=function(e){return this.getPlatformType(!0)===String(e).toLowerCase()},t.isEngine=function(e){return this.getEngineName(!0)===String(e).toLowerCase()},t.is=function(e){return this.isBrowser(e)||this.isOS(e)||this.isPlatform(e)},t.some=function(e){var t=this;return void 0===e&&(e=[]),e.some(function(e){return t.is(e)})},e})();t.default=u,e.exports=t.default},92:function(e,t,n){"use strict";t.__esModule=!0,t.default=void 0;var r,i=(r=n(17))&&r.__esModule?r:{default:r},o=/version\/(\d+(\.?_?\d+)+)/i,a=[{test:[/googlebot/i],describe:function(e){var t={name:"Googlebot"},n=i.default.getFirstMatch(/googlebot\/(\d+(\.\d+))/i,e)||i.default.getFirstMatch(o,e);return n&&(t.version=n),t}},{test:[/opera/i],describe:function(e){var t={name:"Opera"},n=i.default.getFirstMatch(o,e)||i.default.getFirstMatch(/(?:opera)[\s/](\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:[/opr\/|opios/i],describe:function(e){var t={name:"Opera"},n=i.default.getFirstMatch(/(?:opr|opios)[\s/](\S+)/i,e)||i.default.getFirstMatch(o,e);return n&&(t.version=n),t}},{test:[/SamsungBrowser/i],describe:function(e){var t={name:"Samsung Internet for Android"},n=i.default.getFirstMatch(o,e)||i.default.getFirstMatch(/(?:SamsungBrowser)[\s/](\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:[/Whale/i],describe:function(e){var t={name:"NAVER Whale Browser"},n=i.default.getFirstMatch(o,e)||i.default.getFirstMatch(/(?:whale)[\s/](\d+(?:\.\d+)+)/i,e);return n&&(t.version=n),t}},{test:[/MZBrowser/i],describe:function(e){var t={name:"MZ Browser"},n=i.default.getFirstMatch(/(?:MZBrowser)[\s/](\d+(?:\.\d+)+)/i,e)||i.default.getFirstMatch(o,e);return n&&(t.version=n),t}},{test:[/focus/i],describe:function(e){var t={name:"Focus"},n=i.default.getFirstMatch(/(?:focus)[\s/](\d+(?:\.\d+)+)/i,e)||i.default.getFirstMatch(o,e);return n&&(t.version=n),t}},{test:[/swing/i],describe:function(e){var t={name:"Swing"},n=i.default.getFirstMatch(/(?:swing)[\s/](\d+(?:\.\d+)+)/i,e)||i.default.getFirstMatch(o,e);return n&&(t.version=n),t}},{test:[/coast/i],describe:function(e){var t={name:"Opera Coast"},n=i.default.getFirstMatch(o,e)||i.default.getFirstMatch(/(?:coast)[\s/](\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:[/yabrowser/i],describe:function(e){var t={name:"Yandex Browser"},n=i.default.getFirstMatch(/(?:yabrowser)[\s/](\d+(\.?_?\d+)+)/i,e)||i.default.getFirstMatch(o,e);return n&&(t.version=n),t}},{test:[/ucbrowser/i],describe:function(e){var t={name:"UC Browser"},n=i.default.getFirstMatch(o,e)||i.default.getFirstMatch(/(?:ucbrowser)[\s/](\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:[/Maxthon|mxios/i],describe:function(e){var t={name:"Maxthon"},n=i.default.getFirstMatch(o,e)||i.default.getFirstMatch(/(?:Maxthon|mxios)[\s/](\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:[/epiphany/i],describe:function(e){var t={name:"Epiphany"},n=i.default.getFirstMatch(o,e)||i.default.getFirstMatch(/(?:epiphany)[\s/](\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:[/puffin/i],describe:function(e){var t={name:"Puffin"},n=i.default.getFirstMatch(o,e)||i.default.getFirstMatch(/(?:puffin)[\s/](\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:[/sleipnir/i],describe:function(e){var t={name:"Sleipnir"},n=i.default.getFirstMatch(o,e)||i.default.getFirstMatch(/(?:sleipnir)[\s/](\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:[/k-meleon/i],describe:function(e){var t={name:"K-Meleon"},n=i.default.getFirstMatch(o,e)||i.default.getFirstMatch(/(?:k-meleon)[\s/](\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:[/micromessenger/i],describe:function(e){var t={name:"WeChat"},n=i.default.getFirstMatch(/(?:micromessenger)[\s/](\d+(\.?_?\d+)+)/i,e)||i.default.getFirstMatch(o,e);return n&&(t.version=n),t}},{test:[/qqbrowser/i],describe:function(e){var t={name:/qqbrowserlite/i.test(e)?"QQ Browser Lite":"QQ Browser"},n=i.default.getFirstMatch(/(?:qqbrowserlite|qqbrowser)[/](\d+(\.?_?\d+)+)/i,e)||i.default.getFirstMatch(o,e);return n&&(t.version=n),t}},{test:[/msie|trident/i],describe:function(e){var t={name:"Internet Explorer"},n=i.default.getFirstMatch(/(?:msie |rv:)(\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:[/\sedg\//i],describe:function(e){var t={name:"Microsoft Edge"},n=i.default.getFirstMatch(/\sedg\/(\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:[/edg([ea]|ios)/i],describe:function(e){var t={name:"Microsoft Edge"},n=i.default.getSecondMatch(/edg([ea]|ios)\/(\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:[/vivaldi/i],describe:function(e){var t={name:"Vivaldi"},n=i.default.getFirstMatch(/vivaldi\/(\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:[/seamonkey/i],describe:function(e){var t={name:"SeaMonkey"},n=i.default.getFirstMatch(/seamonkey\/(\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:[/sailfish/i],describe:function(e){var t={name:"Sailfish"},n=i.default.getFirstMatch(/sailfish\s?browser\/(\d+(\.\d+)?)/i,e);return n&&(t.version=n),t}},{test:[/silk/i],describe:function(e){var t={name:"Amazon Silk"},n=i.default.getFirstMatch(/silk\/(\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:[/phantom/i],describe:function(e){var t={name:"PhantomJS"},n=i.default.getFirstMatch(/phantomjs\/(\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:[/slimerjs/i],describe:function(e){var t={name:"SlimerJS"},n=i.default.getFirstMatch(/slimerjs\/(\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:[/blackberry|\bbb\d+/i,/rim\stablet/i],describe:function(e){var t={name:"BlackBerry"},n=i.default.getFirstMatch(o,e)||i.default.getFirstMatch(/blackberry[\d]+\/(\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:[/(web|hpw)[o0]s/i],describe:function(e){var t={name:"WebOS Browser"},n=i.default.getFirstMatch(o,e)||i.default.getFirstMatch(/w(?:eb)?[o0]sbrowser\/(\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:[/bada/i],describe:function(e){var t={name:"Bada"},n=i.default.getFirstMatch(/dolfin\/(\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:[/tizen/i],describe:function(e){var t={name:"Tizen"},n=i.default.getFirstMatch(/(?:tizen\s?)?browser\/(\d+(\.?_?\d+)+)/i,e)||i.default.getFirstMatch(o,e);return n&&(t.version=n),t}},{test:[/qupzilla/i],describe:function(e){var t={name:"QupZilla"},n=i.default.getFirstMatch(/(?:qupzilla)[\s/](\d+(\.?_?\d+)+)/i,e)||i.default.getFirstMatch(o,e);return n&&(t.version=n),t}},{test:[/firefox|iceweasel|fxios/i],describe:function(e){var t={name:"Firefox"},n=i.default.getFirstMatch(/(?:firefox|iceweasel|fxios)[\s/](\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:[/chromium/i],describe:function(e){var t={name:"Chromium"},n=i.default.getFirstMatch(/(?:chromium)[\s/](\d+(\.?_?\d+)+)/i,e)||i.default.getFirstMatch(o,e);return n&&(t.version=n),t}},{test:[/chrome|crios|crmo/i],describe:function(e){var t={name:"Chrome"},n=i.default.getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:[/GSA/i],describe:function(e){var t={name:"Google Search"},n=i.default.getFirstMatch(/(?:GSA)\/(\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:function(e){var t=!e.test(/like android/i),n=e.test(/android/i);return t&&n},describe:function(e){var t={name:"Android Browser"},n=i.default.getFirstMatch(o,e);return n&&(t.version=n),t}},{test:[/playstation 4/i],describe:function(e){var t={name:"PlayStation 4"},n=i.default.getFirstMatch(o,e);return n&&(t.version=n),t}},{test:[/safari|applewebkit/i],describe:function(e){var t={name:"Safari"},n=i.default.getFirstMatch(o,e);return n&&(t.version=n),t}},{test:[/.*/i],describe:function(e){var t=-1!==e.search("\\(")?/^(.*)\/(.*)[ \t]\((.*)/:/^(.*)\/(.*) /;return{name:i.default.getFirstMatch(t,e),version:i.default.getSecondMatch(t,e)}}}];t.default=a,e.exports=t.default},93:function(e,t,n){"use strict";t.__esModule=!0,t.default=void 0;var r,i=(r=n(17))&&r.__esModule?r:{default:r},o=n(18),a=[{test:[/Roku\/DVP/],describe:function(e){var t=i.default.getFirstMatch(/Roku\/DVP-(\d+\.\d+)/i,e);return{name:o.OS_MAP.Roku,version:t}}},{test:[/windows phone/i],describe:function(e){var t=i.default.getFirstMatch(/windows phone (?:os)?\s?(\d+(\.\d+)*)/i,e);return{name:o.OS_MAP.WindowsPhone,version:t}}},{test:[/windows/i],describe:function(e){var t=i.default.getFirstMatch(/Windows ((NT|XP)( \d\d?.\d)?)/i,e),n=i.default.getWindowsVersionName(t);return{name:o.OS_MAP.Windows,version:t,versionName:n}}},{test:[/macintosh/i],describe:function(e){var t=i.default.getFirstMatch(/mac os x (\d+(\.?_?\d+)+)/i,e).replace(/[_\s]/g,"."),n=i.default.getMacOSVersionName(t),r={name:o.OS_MAP.MacOS,version:t};return n&&(r.versionName=n),r}},{test:[/(ipod|iphone|ipad)/i],describe:function(e){var t=i.default.getFirstMatch(/os (\d+([_\s]\d+)*) like mac os x/i,e).replace(/[_\s]/g,".");return{name:o.OS_MAP.iOS,version:t}}},{test:function(e){var t=!e.test(/like android/i),n=e.test(/android/i);return t&&n},describe:function(e){var t=i.default.getFirstMatch(/android[\s/-](\d+(\.\d+)*)/i,e),n=i.default.getAndroidVersionName(t),r={name:o.OS_MAP.Android,version:t};return n&&(r.versionName=n),r}},{test:[/(web|hpw)[o0]s/i],describe:function(e){var t=i.default.getFirstMatch(/(?:web|hpw)[o0]s\/(\d+(\.\d+)*)/i,e),n={name:o.OS_MAP.WebOS};return t&&t.length&&(n.version=t),n}},{test:[/blackberry|\bbb\d+/i,/rim\stablet/i],describe:function(e){var t=i.default.getFirstMatch(/rim\stablet\sos\s(\d+(\.\d+)*)/i,e)||i.default.getFirstMatch(/blackberry\d+\/(\d+([_\s]\d+)*)/i,e)||i.default.getFirstMatch(/\bbb(\d+)/i,e);return{name:o.OS_MAP.BlackBerry,version:t}}},{test:[/bada/i],describe:function(e){var t=i.default.getFirstMatch(/bada\/(\d+(\.\d+)*)/i,e);return{name:o.OS_MAP.Bada,version:t}}},{test:[/tizen/i],describe:function(e){var t=i.default.getFirstMatch(/tizen[/\s](\d+(\.\d+)*)/i,e);return{name:o.OS_MAP.Tizen,version:t}}},{test:[/linux/i],describe:function(){return{name:o.OS_MAP.Linux}}},{test:[/CrOS/],describe:function(){return{name:o.OS_MAP.ChromeOS}}},{test:[/PlayStation 4/],describe:function(e){var t=i.default.getFirstMatch(/PlayStation 4[/\s](\d+(\.\d+)*)/i,e);return{name:o.OS_MAP.PlayStation4,version:t}}}];t.default=a,e.exports=t.default},94:function(e,t,n){"use strict";t.__esModule=!0,t.default=void 0;var r,i=(r=n(17))&&r.__esModule?r:{default:r},o=n(18),a=[{test:[/googlebot/i],describe:function(){return{type:"bot",vendor:"Google"}}},{test:[/huawei/i],describe:function(e){var t=i.default.getFirstMatch(/(can-l01)/i,e)&&"Nova",n={type:o.PLATFORMS_MAP.mobile,vendor:"Huawei"};return t&&(n.model=t),n}},{test:[/nexus\s*(?:7|8|9|10).*/i],describe:function(){return{type:o.PLATFORMS_MAP.tablet,vendor:"Nexus"}}},{test:[/ipad/i],describe:function(){return{type:o.PLATFORMS_MAP.tablet,vendor:"Apple",model:"iPad"}}},{test:[/kftt build/i],describe:function(){return{type:o.PLATFORMS_MAP.tablet,vendor:"Amazon",model:"Kindle Fire HD 7"}}},{test:[/silk/i],describe:function(){return{type:o.PLATFORMS_MAP.tablet,vendor:"Amazon"}}},{test:[/tablet(?! pc)/i],describe:function(){return{type:o.PLATFORMS_MAP.tablet}}},{test:function(e){var t=e.test(/ipod|iphone/i),n=e.test(/like (ipod|iphone)/i);return t&&!n},describe:function(e){var t=i.default.getFirstMatch(/(ipod|iphone)/i,e);return{type:o.PLATFORMS_MAP.mobile,vendor:"Apple",model:t}}},{test:[/nexus\s*[0-6].*/i,/galaxy nexus/i],describe:function(){return{type:o.PLATFORMS_MAP.mobile,vendor:"Nexus"}}},{test:[/[^-]mobi/i],describe:function(){return{type:o.PLATFORMS_MAP.mobile}}},{test:function(e){return"blackberry"===e.getBrowserName(!0)},describe:function(){return{type:o.PLATFORMS_MAP.mobile,vendor:"BlackBerry"}}},{test:function(e){return"bada"===e.getBrowserName(!0)},describe:function(){return{type:o.PLATFORMS_MAP.mobile}}},{test:function(e){return"windows phone"===e.getBrowserName()},describe:function(){return{type:o.PLATFORMS_MAP.mobile,vendor:"Microsoft"}}},{test:function(e){var t=Number(String(e.getOSVersion()).split(".")[0]);return"android"===e.getOSName(!0)&&t>=3},describe:function(){return{type:o.PLATFORMS_MAP.tablet}}},{test:function(e){return"android"===e.getOSName(!0)},describe:function(){return{type:o.PLATFORMS_MAP.mobile}}},{test:function(e){return"macos"===e.getOSName(!0)},describe:function(){return{type:o.PLATFORMS_MAP.desktop,vendor:"Apple"}}},{test:function(e){return"windows"===e.getOSName(!0)},describe:function(){return{type:o.PLATFORMS_MAP.desktop}}},{test:function(e){return"linux"===e.getOSName(!0)},describe:function(){return{type:o.PLATFORMS_MAP.desktop}}},{test:function(e){return"playstation 4"===e.getOSName(!0)},describe:function(){return{type:o.PLATFORMS_MAP.tv}}},{test:function(e){return"roku"===e.getOSName(!0)},describe:function(){return{type:o.PLATFORMS_MAP.tv}}}];t.default=a,e.exports=t.default},95:function(e,t,n){"use strict";t.__esModule=!0,t.default=void 0;var r,i=(r=n(17))&&r.__esModule?r:{default:r},o=n(18),a=[{test:function(e){return"microsoft edge"===e.getBrowserName(!0)},describe:function(e){if(/\sedg\//i.test(e))return{name:o.ENGINE_MAP.Blink};var t=i.default.getFirstMatch(/edge\/(\d+(\.?_?\d+)+)/i,e);return{name:o.ENGINE_MAP.EdgeHTML,version:t}}},{test:[/trident/i],describe:function(e){var t={name:o.ENGINE_MAP.Trident},n=i.default.getFirstMatch(/trident\/(\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:function(e){return e.test(/presto/i)},describe:function(e){var t={name:o.ENGINE_MAP.Presto},n=i.default.getFirstMatch(/presto\/(\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:function(e){var t=e.test(/gecko/i),n=e.test(/like gecko/i);return t&&!n},describe:function(e){var t={name:o.ENGINE_MAP.Gecko},n=i.default.getFirstMatch(/gecko\/(\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}},{test:[/(apple)?webkit\/537\.36/i],describe:function(){return{name:o.ENGINE_MAP.Blink}}},{test:[/(apple)?webkit/i],describe:function(e){var t={name:o.ENGINE_MAP.WebKit},n=i.default.getFirstMatch(/webkit\/(\d+(\.?_?\d+)+)/i,e);return n&&(t.version=n),t}}];t.default=a,e.exports=t.default}})},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return p});var r=n(1),i=n(16),o=n(26),a=n(9),s=n(11),c=n(4).getLogger(e),u={};function d(e,t){return!t||t<=0||!e||e<=0?0:Math.round(e/t*100)}function l(){this.loss={},this.bitrate={download:0,upload:0},this.resolution={},this.framerate=0,this.codec=""}function h(){this.bandwidth={},this.bitrate={},this.packetLoss=null,this.transport=[]}function p(e,t,n,i){this._browserType=r.a.getName();var o=u[this._browserType];if(!o)throw"The browser type '"+this._browserType+"' isn't supported!";this._usesPromiseGetStats=r.a.isSafari()||r.a.isFirefox(),this._getStatValue=this._usesPromiseGetStats?this._defineNewGetStatValueMethod(o):this._defineGetStatValueMethod(o),this.peerconnection=e,this.baselineAudioLevelsReport=null,this.currentAudioLevelsReport=null,this.currentStatsReport=null,this.previousStatsReport=null,this.audioLevelReportHistory={},this.audioLevelsIntervalId=null,this.eventEmitter=i,this.conferenceStats=new h,this.audioLevelsIntervalMilis=t,this.statsIntervalId=null,this.statsIntervalMilis=n,this.ssrc2stats=new Map}u[i.b.FIREFOX]={ssrc:"ssrc",packetsReceived:"packetsReceived",packetsLost:"packetsLost",packetsSent:"packetsSent",bytesReceived:"bytesReceived",bytesSent:"bytesSent",framerateMean:"framerateMean",ip:"address",port:"port",protocol:"protocol"},u[i.b.CHROME]={receiveBandwidth:"googAvailableReceiveBandwidth",sendBandwidth:"googAvailableSendBandwidth",remoteAddress:"googRemoteAddress",transportType:"googTransportType",localAddress:"googLocalAddress",activeConnection:"googActiveConnection",ssrc:"ssrc",packetsReceived:"packetsReceived",packetsSent:"packetsSent",packetsLost:"packetsLost",bytesReceived:"bytesReceived",bytesSent:"bytesSent",googCodecName:"googCodecName",googFrameHeightReceived:"googFrameHeightReceived",googFrameWidthReceived:"googFrameWidthReceived",googFrameHeightSent:"googFrameHeightSent",googFrameWidthSent:"googFrameWidthSent",googFrameRateReceived:"googFrameRateReceived",googFrameRateSent:"googFrameRateSent",audioInputLevel:"audioInputLevel",audioOutputLevel:"audioOutputLevel",currentRoundTripTime:"googRtt",remoteCandidateType:"googRemoteCandidateType",localCandidateType:"googLocalCandidateType",ip:"ip",port:"port",protocol:"protocol"},u[i.b.OPERA]=u[i.b.CHROME],u[i.b.NWJS]=u[i.b.CHROME],u[i.b.ELECTRON]=u[i.b.CHROME],u[i.b.SAFARI]=u[i.b.CHROME],u[i.b.REACT_NATIVE]=u[i.b.CHROME],l.prototype.setLoss=function(e){this.loss=e||{}},l.prototype.setResolution=function(e){this.resolution=e||{}},l.prototype.addBitrate=function(e){this.bitrate.download+=e.download,this.bitrate.upload+=e.upload},l.prototype.resetBitrate=function(){this.bitrate.download=0,this.bitrate.upload=0},l.prototype.setFramerate=function(e){this.framerate=e||0},l.prototype.setCodec=function(e){this.codec=e||""},p.prototype.stop=function(){this.audioLevelsIntervalId&&(clearInterval(this.audioLevelsIntervalId),this.audioLevelsIntervalId=null),this.statsIntervalId&&(clearInterval(this.statsIntervalId),this.statsIntervalId=null)},p.prototype.errorCallback=function(e){s.callErrorHandler(e),c.error("Get stats error",e),this.stop()},p.prototype.start=function(e){var t=this,n=this;e&&(this.audioLevelsIntervalId=setInterval(function(){n.peerconnection.getStats(function(e){var r;r=e&&e.result&&"function"==typeof e.result?e.result():e,n.currentAudioLevelsReport=r,t._usesPromiseGetStats?n.processNewAudioLevelReport():n.processAudioLevelReport(),n.baselineAudioLevelsReport=n.currentAudioLevelsReport},function(e){return n.errorCallback(e)})},n.audioLevelsIntervalMilis)),this.statsIntervalId=setInterval(function(){n.peerconnection.getStats(function(e){var r;r=e&&e.result&&"function"==typeof e.result?e.result():e,n.currentStatsReport=r;try{t._usesPromiseGetStats?n.processNewStatsReport():n.processStatsReport()}catch(e){s.callErrorHandler(e),c.error("Unsupported key:"+e,e)}n.previousStatsReport=n.currentStatsReport},function(e){return n.errorCallback(e)})},n.statsIntervalMilis)},p.prototype._defineGetStatValueMethod=function(e){var t;switch(this._browserType){case i.b.CHROME:case i.b.OPERA:case i.b.NWJS:case i.b.ELECTRON:t=function(e,t){return e.stat(t)};break;case i.b.REACT_NATIVE:t=function(e,t){var n;return e.values.some(function(e){return!!e.hasOwnProperty(t)&&(n=e[t],!0)}),n};break;default:t=function(e,t){return e[t]}}return function(n,r){return t(n,(function(t){var n=e[t];if(n)return n;throw"The property '"+t+"' isn't supported!"})(r))}},p.prototype.getNonNegativeStat=function(e,t){var n=this._getStatValue(e,t);return"number"!=typeof n&&(n=Number(n)),isNaN(n)?0:Math.max(0,n)},p.prototype.processStatsReport=function(){var e=this;if(this.previousStatsReport){var t=this._getStatValue,n={};for(var r in this.currentStatsReport)if(this.currentStatsReport.hasOwnProperty(r)){var i=this.currentStatsReport[r];if(i){try{var a=t(i,"receiveBandwidth"),s=t(i,"sendBandwidth");(a||s)&&(this.conferenceStats.bandwidth={download:Math.round(a/1e3),upload:Math.round(s/1e3)})}catch(t){}if("googCandidatePair"===i.type)if("continue"===(function(){var n=void 0,r=void 0,o=void 0,a=void 0,s=void 0,c=void 0,u=void 0;try{if(!(n=t(i,"activeConnection")))return"continue";r=t(i,"remoteAddress"),u=t(i,"transportType"),a=t(i,"localAddress"),o=t(i,"localCandidateType"),s=t(i,"remoteCandidateType"),c=e.getNonNegativeStat(i,"currentRoundTripTime")}catch(e){}if(!r||!u||!a||"true"!==n)return"continue";var d=e.conferenceStats.transport;return d.some(function(e){return e.ip===r&&e.type===u&&e.localip===a})||d.push({ip:r,type:u,localip:a,p2p:e.peerconnection.isP2P,localCandidateType:o,remoteCandidateType:s,rtt:c}),"continue"})())continue;if("candidatepair"===i.type){if("succeeded"!==i.state||!i.selected)continue;var u=this.currentStatsReport[i.localCandidateId],d=this.currentStatsReport[i.remoteCandidateId];this.conferenceStats.transport.push({ip:d.ipAddress+":"+d.portNumber,type:u.transport,localip:u.ipAddress+":"+u.portNumber,p2p:this.peerconnection.isP2P,localCandidateType:u.candidateType,remoteCandidateType:d.candidateType})}if("ssrc"===i.type||"outboundrtp"===i.type||"inboundrtp"===i.type||"track"===i.type){var h=this.previousStatsReport[r],p=this.getNonNegativeStat(i,"ssrc");if("track"===i.type&&Array.isArray(i.ssrcIds)&&(p=Number(i.ssrcIds[0])),h&&p&&!0!==i.isRemote&&!0!==i.remoteSource){var f=this.ssrc2stats.get(p);f||(f=new l,this.ssrc2stats.set(p,f));var m=!0,v="packetsReceived",g=t(i,v);null!=g&&""!==g||(m=!1,null==(g=t(i,v="packetsSent"))&&c.warn("No packetsReceived nor packetsSent stat found")),(!g||g<0)&&(g=0);var y=this.getNonNegativeStat(h,v),_=Math.max(0,g-y),S=this.getNonNegativeStat(i,"packetsLost"),E=this.getNonNegativeStat(h,"packetsLost"),b=Math.max(0,S-E);f.setLoss({packetsTotal:_+b,packetsLost:b,isDownloadStream:m});var C=this.getNonNegativeStat(i,"bytesReceived"),T=this.getNonNegativeStat(h,"bytesReceived"),A=Math.max(0,C-T),R=0,k=t(i,"bytesSent");"number"!=typeof k&&"string"!=typeof k||(k=Number(k),isNaN(k)||(n[p]=k,k>0&&(R=k-t(h,"bytesSent")))),R=Math.max(0,R);var w=i.timestamp-h.timestamp,I=0,P=0;w>0&&(I=Math.round(8*A/w),P=Math.round(8*R/w)),f.addBitrate({download:I,upload:P});var D={height:null,width:null};try{var O=void 0,N=void 0;(O=t(i,"googFrameHeightReceived"))&&(N=t(i,"googFrameWidthReceived"))?(D.height=O,D.width=N):(O=t(i,"googFrameHeightSent"))&&(N=t(i,"googFrameWidthSent"))&&(D.height=O,D.width=N)}catch(t){}var M=void 0,L=void 0;try{M=t(i,"googFrameRateReceived")||t(i,"googFrameRateSent")||0}catch(t){try{M=this.getNonNegativeStat(i,"framerateMean")}catch(t){}}f.setFramerate(Math.round(M||0)),D.height&&D.width?f.setResolution(D):f.setResolution(null);try{L=t(i,"googCodecName")||""}catch(t){}f.setCodec(L)}}}}this.eventEmitter.emit(o.c,this.peerconnection,n),this._processAndEmitReport()}},p.prototype._processAndEmitReport=function(){var e=this,t={download:0,upload:0},n={download:0,upload:0},r=0,i=0,a={},s={},u={},l=0,h=0,p="",f=0,m=0,v="",g=this.ssrc2stats,y=Array.isArray(g),_=0;for(g=y?g:g["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var S;if(y){if(_>=g.length)break;S=g[_++]}else{if((_=g.next()).done)break;S=_.value}var E=_slicedToArray(S,2),b=E[0],C=E[1],T=C.loss,A=T.isDownloadStream?"download":"upload";t[A]+=T.packetsTotal,n[A]+=T.packetsLost,r+=C.bitrate.download,i+=C.bitrate.upload;var R=this.peerconnection.getTrackBySSRC(b);if(R){R.isAudioTrack()?(l+=C.bitrate.download,h+=C.bitrate.upload,p=C.codec):(f+=C.bitrate.download,m+=C.bitrate.upload,v=C.codec);var k=R.getParticipantId();if(k){var w=C.resolution;if(w.width&&w.height&&-1!==w.width&&-1!==w.height){var I=a[k]||{};I[b]=w,a[k]=I}if(0!==C.framerate){var P=s[k]||{};P[b]=C.framerate,s[k]=P}if(p.length&&v.length){var D={audio:p,video:v},O=u[k]||{};O[b]=D,u[k]=O}}else c.error("No participant ID returned by "+R)}C.resetBitrate()}this.conferenceStats.bitrate={upload:i,download:r},this.conferenceStats.bitrate.audio={upload:h,download:l},this.conferenceStats.bitrate.video={upload:m,download:f},this.conferenceStats.packetLoss={total:d(n.download+n.upload,t.download+t.upload),download:d(n.download,t.download),upload:d(n.upload,t.upload)};var N,M={};Object.keys(this.audioLevelReportHistory).forEach(function(t){var n=e.audioLevelReportHistory[t],r=n.data,i=n.isLocal,o=r.reduce(function(e,t){return e+t})/r.length;if(i)N=o;else{var a=e.peerconnection.getTrackBySSRC(Number(t));if(a){var s=a.getParticipantId();s&&(M[s]=o)}}}),this.audioLevelReportHistory={},this.eventEmitter.emit(o.d,this.peerconnection,{bandwidth:this.conferenceStats.bandwidth,bitrate:this.conferenceStats.bitrate,packetLoss:this.conferenceStats.packetLoss,resolution:a,framerate:s,codec:u,transport:this.conferenceStats.transport,localAvgAudioLevels:N,avgAudioLevels:M}),this.conferenceStats.transport=[]},p.prototype.processAudioLevelReport=function(){if(this.baselineAudioLevelsReport){var e=this._getStatValue;for(var t in this.currentAudioLevelsReport)if(this.currentAudioLevelsReport.hasOwnProperty(t)){var n=this.currentAudioLevelsReport[t];if("ssrc"===n.type||"track"===n.type){var r=this.baselineAudioLevelsReport[t],i=void 0,a=this.getNonNegativeStat(n,"ssrc");if(!a&&Array.isArray(n.ssrcIds)&&(a=Number(n.ssrcIds[0])),r)if(a){try{i=e(n,"audioInputLevel")||e(n,"audioOutputLevel")}catch(e){return c.warn("Audio Levels are not available in the statistics."),void clearInterval(this.audioLevelsIntervalId)}if(i){var s;s="ssrc"===n.type?!e(n,"packetsReceived"):!n.remoteSource,i/=32767,a in this.audioLevelReportHistory||(this.audioLevelReportHistory[a]={isLocal:s,data:[]}),this.audioLevelReportHistory[a].data.push(i),this.eventEmitter.emit(o.a,this.peerconnection,a,i,s)}}else Date.now()-n.timestamp<3e3&&c.warn("No ssrc: ");else c.warn(a+" not enough data")}}}},p.prototype._defineNewGetStatValueMethod=function(e){return function(t,n){return t[(function(t){var n=e[t];if(n)return n;throw"The property '"+t+"' isn't supported!"})(n)]}},p.prototype.getNonNegativeValue=function(e){var t=e;return"number"!=typeof t&&(t=Number(t)),isNaN(t)?0:Math.max(0,t)},p.prototype._calculateBitrate=function(e,t,n){var r=this.getNonNegativeValue(e[n]),i=this.getNonNegativeValue(t[n]),o=Math.max(0,r-i),a=e.timestamp-t.timestamp,s=0;return a>0&&(s=Math.round(8*o/a)),s},p.prototype.processNewStatsReport=function(){var e=this;if(this.previousStatsReport){var t=this._getStatValue,n={};this.currentStatsReport.forEach(function(r){if("candidate-pair"===r.type&&r.nominated&&"succeeded"===r.state){var i=r.availableIncomingBitrate,o=r.availableOutgoingBitrate;(i||o)&&(e.conferenceStats.bandwidth={download:Math.round(i/1e3),upload:Math.round(o/1e3)});var a=e.currentStatsReport.get(r.remoteCandidateId),s=e.currentStatsReport.get(r.localCandidateId);if(a&&s){var c=t(a,"ip")+":"+t(a,"port"),u=t(s,"ip")+":"+t(s,"port"),d=t(a,"protocol"),h=e.conferenceStats.transport;h.some(function(e){return e.ip===c&&e.type===d&&e.localip===u})||h.push({ip:c,type:d,localIp:u,p2p:e.peerconnection.isP2P,localCandidateType:s.candidateType,remoteCandidateType:a.candidateType,networkType:s.networkType,rtt:1e3*r.currentRoundTripTime})}}else if("inbound-rtp"===r.type||"outbound-rtp"===r.type){var p=e.previousStatsReport.get(r.id),f=e.getNonNegativeValue(r.ssrc);if(!p||!f)return;var m=e.ssrc2stats.get(f);m||(m=new l,e.ssrc2stats.set(f,m));var v=!0,g="packetsReceived";"outbound-rtp"===r.type&&(v=!1,g="packetsSent");var y=r[g];(!y||y<0)&&(y=0);var _=e.getNonNegativeValue(p[g]),S=Math.max(0,y-_),E=e.getNonNegativeValue(r.packetsLost),b=e.getNonNegativeValue(p.packetsLost),C=Math.max(0,E-b);m.setLoss({packetsTotal:S+C,packetsLost:C,isDownloadStream:v}),"inbound-rtp"===r.type?m.addBitrate({download:e._calculateBitrate(r,p,"bytesReceived"),upload:0}):(n[f]=e.getNonNegativeValue(r.bytesSent),m.addBitrate({download:0,upload:e._calculateBitrate(r,p,"bytesSent")}));var T=r.framerateMean;T&&m.setFramerate(Math.round(T||0))}else if("track"===r.type){var A={height:r.frameHeight,width:r.frameWidth},R=r.framesPerSecond;if(!R){var k=e.previousStatsReport.get(r.id);if(k){var w=r.timestamp-k.timestamp;w>0&&r.framesSent&&(R=(r.framesSent-k.framesSent)/w*1e3)}if(!R)return}var I=r.trackIdentifier,P=e.peerconnection.getSsrcByTrackId(I);if(!P)return;var D=e.ssrc2stats.get(P);D||(D=new l,e.ssrc2stats.set(P,D)),D.setFramerate(Math.round(R||0)),A.height&&A.width?D.setResolution(A):D.setResolution(null)}}),this.eventEmitter.emit(o.c,this.peerconnection,n),this._processAndEmitReport()}},p.prototype.processNewAudioLevelReport=function(){var e=this;this.baselineAudioLevelsReport&&this.currentAudioLevelsReport.forEach(function(t){if("track"===t.type){var n=t.audioLevel;if(n){var r=t.trackIdentifier,i=e.peerconnection.getSsrcByTrackId(r);if(i){var s=i===e.peerconnection.getLocalSSRC(e.peerconnection.getLocalTracks(a.a));e.eventEmitter.emit(o.a,e.peerconnection,i,n,s)}}}})}}).call(this,"modules/statistics/RTPStatsCollector.js")},function(e,t,n){"use strict";var r=n(45);function i(e,t,n,i,o){var a=r.writeRtpDescription(e.kind,t);if(a+=r.writeIceParameters(e.iceGatherer.getLocalParameters()),a+=r.writeDtlsParameters(e.dtlsTransport.getLocalParameters(),"offer"===n?"actpass":o||"active"),a+="a=mid:"+e.mid+"\r\n",e.rtpSender&&e.rtpReceiver?a+="a=sendrecv\r\n":e.rtpSender?a+="a=sendonly\r\n":e.rtpReceiver?a+="a=recvonly\r\n":a+="a=inactive\r\n",e.rtpSender){var s=e.rtpSender._initialTrackId||e.rtpSender.track.id;e.rtpSender._initialTrackId=s;var c="msid:"+(i?i.id:"-")+" "+s+"\r\n";a+="a="+c,a+="a=ssrc:"+e.sendEncodingParameters[0].ssrc+" "+c,e.sendEncodingParameters[0].rtx&&(a+="a=ssrc:"+e.sendEncodingParameters[0].rtx.ssrc+" "+c,a+="a=ssrc-group:FID "+e.sendEncodingParameters[0].ssrc+" "+e.sendEncodingParameters[0].rtx.ssrc+"\r\n")}return a+="a=ssrc:"+e.sendEncodingParameters[0].ssrc+" cname:"+r.localCName+"\r\n",e.rtpSender&&e.sendEncodingParameters[0].rtx&&(a+="a=ssrc:"+e.sendEncodingParameters[0].rtx.ssrc+" cname:"+r.localCName+"\r\n"),a}function o(e,t){var n={codecs:[],headerExtensions:[],fecMechanisms:[]},r=function(e,t){e=parseInt(e,10);for(var n=0;n=14393&&-1===e.indexOf("?transport=udp"):(n=!0,!0)}),delete e.url,e.urls=i?r[0]:r,!!r.length}})})(n.iceServers||[],t),this._iceGatherers=[],n.iceCandidatePoolSize)for(var a=n.iceCandidatePoolSize;a>0;a--)this._iceGatherers.push(new e.RTCIceGatherer({iceServers:n.iceServers,gatherPolicy:n.iceTransportPolicy}));else n.iceCandidatePoolSize=0;this._config=n,this.transceivers=[],this._sdpSessionId=r.generateSessionId(),this._sdpSessionVersion=0,this._dtlsRole=void 0,this._isClosed=!1};Object.defineProperty(d.prototype,"localDescription",{configurable:!0,get:function(){return this._localDescription}}),Object.defineProperty(d.prototype,"remoteDescription",{configurable:!0,get:function(){return this._remoteDescription}}),d.prototype.onicecandidate=null,d.prototype.onaddstream=null,d.prototype.ontrack=null,d.prototype.onremovestream=null,d.prototype.onsignalingstatechange=null,d.prototype.oniceconnectionstatechange=null,d.prototype.onconnectionstatechange=null,d.prototype.onicegatheringstatechange=null,d.prototype.onnegotiationneeded=null,d.prototype.ondatachannel=null,d.prototype._dispatchEvent=function(e,t){this._isClosed||(this.dispatchEvent(t),"function"==typeof this["on"+e]&&this["on"+e](t))},d.prototype._emitGatheringStateChange=function(){var e=new Event("icegatheringstatechange");this._dispatchEvent("icegatheringstatechange",e)},d.prototype.getConfiguration=function(){return this._config},d.prototype.getLocalStreams=function(){return this.localStreams},d.prototype.getRemoteStreams=function(){return this.remoteStreams},d.prototype._createTransceiver=function(e,t){var n=this.transceivers.length>0,r={track:null,iceGatherer:null,iceTransport:null,dtlsTransport:null,localCapabilities:null,remoteCapabilities:null,rtpSender:null,rtpReceiver:null,kind:e,mid:null,sendEncodingParameters:null,recvEncodingParameters:null,stream:null,associatedRemoteMediaStreams:[],wantReceive:!0};if(this.usingBundle&&n)r.iceTransport=this.transceivers[0].iceTransport,r.dtlsTransport=this.transceivers[0].dtlsTransport;else{var i=this._createIceAndDtlsTransports();r.iceTransport=i.iceTransport,r.dtlsTransport=i.dtlsTransport}return t||this.transceivers.push(r),r},d.prototype.addTrack=function(t,n){if(this._isClosed)throw c("InvalidStateError","Attempted to call addTrack on a closed peerconnection.");var r;if(this.transceivers.find(function(e){return e.track===t}))throw c("InvalidAccessError","Track already exists.");for(var i=0;i=15025)e.getTracks().forEach(function(t){n.addTrack(t,e)});else{var r=e.clone();e.getTracks().forEach(function(e,t){var n=r.getTracks()[t];e.addEventListener("enabled",function(e){n.enabled=e.enabled})}),r.getTracks().forEach(function(e){n.addTrack(e,r)})}},d.prototype.removeTrack=function(t){if(this._isClosed)throw c("InvalidStateError","Attempted to call removeTrack on a closed peerconnection.");if(!(t instanceof e.RTCRtpSender))throw new TypeError("Argument 1 of RTCPeerConnection.removeTrack does not implement interface RTCRtpSender.");var n=this.transceivers.find(function(e){return e.rtpSender===t});if(!n)throw c("InvalidAccessError","Sender was not created by this connection.");var r=n.stream;n.rtpSender.stop(),n.rtpSender=null,n.track=null,n.stream=null,-1===this.transceivers.map(function(e){return e.stream}).indexOf(r)&&this.localStreams.indexOf(r)>-1&&this.localStreams.splice(this.localStreams.indexOf(r),1),this._maybeFireNegotiationNeeded()},d.prototype.removeStream=function(e){var t=this;e.getTracks().forEach(function(e){var n=t.getSenders().find(function(t){return t.track===e});n&&t.removeTrack(n)})},d.prototype.getSenders=function(){return this.transceivers.filter(function(e){return!!e.rtpSender}).map(function(e){return e.rtpSender})},d.prototype.getReceivers=function(){return this.transceivers.filter(function(e){return!!e.rtpReceiver}).map(function(e){return e.rtpReceiver})},d.prototype._createIceGatherer=function(t,n){var r=this;if(n&&t>0)return this.transceivers[0].iceGatherer;if(this._iceGatherers.length)return this._iceGatherers.shift();var i=new e.RTCIceGatherer({iceServers:this._config.iceServers,gatherPolicy:this._config.iceTransportPolicy});return Object.defineProperty(i,"state",{value:"new",writable:!0}),this.transceivers[t].bufferedCandidateEvents=[],this.transceivers[t].bufferCandidates=function(e){var n=!e.candidate||0===Object.keys(e.candidate).length;i.state=n?"completed":"gathering",null!==r.transceivers[t].bufferedCandidateEvents&&r.transceivers[t].bufferedCandidateEvents.push(e)},i.addEventListener("localcandidate",this.transceivers[t].bufferCandidates),i},d.prototype._gather=function(t,n){var i=this,o=this.transceivers[n].iceGatherer;if(!o.onlocalcandidate){var a=this.transceivers[n].bufferedCandidateEvents;this.transceivers[n].bufferedCandidateEvents=null,o.removeEventListener("localcandidate",this.transceivers[n].bufferCandidates),o.onlocalcandidate=function(e){if(!(i.usingBundle&&n>0)){var a=new Event("icecandidate");a.candidate={sdpMid:t,sdpMLineIndex:n};var s=e.candidate,c=!s||0===Object.keys(s).length;if(c)"new"!==o.state&&"gathering"!==o.state||(o.state="completed");else{"new"===o.state&&(o.state="gathering"),s.component=1,s.ufrag=o.getLocalParameters().usernameFragment;var u=r.writeCandidate(s);a.candidate=_extends(a.candidate,r.parseCandidate(u)),a.candidate.candidate=u,a.candidate.toJSON=function(){return{candidate:a.candidate.candidate,sdpMid:a.candidate.sdpMid,sdpMLineIndex:a.candidate.sdpMLineIndex,usernameFragment:a.candidate.usernameFragment}}}var d=r.getMediaSections(i._localDescription.sdp);d[a.candidate.sdpMLineIndex]+=c?"a=end-of-candidates\r\n":"a="+a.candidate.candidate+"\r\n",i._localDescription.sdp=r.getDescription(i._localDescription.sdp)+d.join("");var l=i.transceivers.every(function(e){return e.iceGatherer&&"completed"===e.iceGatherer.state});"gathering"!==i.iceGatheringState&&(i.iceGatheringState="gathering",i._emitGatheringStateChange()),c||i._dispatchEvent("icecandidate",a),l&&(i._dispatchEvent("icecandidate",new Event("icecandidate")),i.iceGatheringState="complete",i._emitGatheringStateChange())}},e.setTimeout(function(){a.forEach(function(e){o.onlocalcandidate(e)})},0)}},d.prototype._createIceAndDtlsTransports=function(){var t=this,n=new e.RTCIceTransport(null);n.onicestatechange=function(){t._updateIceConnectionState(),t._updateConnectionState()};var r=new e.RTCDtlsTransport(n);return r.ondtlsstatechange=function(){t._updateConnectionState()},r.onerror=function(){Object.defineProperty(r,"state",{value:"failed",writable:!0}),t._updateConnectionState()},{iceTransport:n,dtlsTransport:r}},d.prototype._disposeIceAndDtlsTransports=function(e){var t=this.transceivers[e].iceGatherer;t&&(delete t.onlocalcandidate,delete this.transceivers[e].iceGatherer);var n=this.transceivers[e].iceTransport;n&&(delete n.onicestatechange,delete this.transceivers[e].iceTransport);var r=this.transceivers[e].dtlsTransport;r&&(delete r.ondtlsstatechange,delete r.onerror,delete this.transceivers[e].dtlsTransport)},d.prototype._transceive=function(e,n,i){var a=o(e.localCapabilities,e.remoteCapabilities);n&&e.rtpSender&&(a.encodings=e.sendEncodingParameters,a.rtcp={cname:r.localCName,compound:e.rtcpParameters.compound},e.recvEncodingParameters.length&&(a.rtcp.ssrc=e.recvEncodingParameters[0].ssrc),e.rtpSender.send(a)),i&&e.rtpReceiver&&a.codecs.length>0&&("video"===e.kind&&e.recvEncodingParameters&&t<15019&&e.recvEncodingParameters.forEach(function(e){delete e.rtx}),e.recvEncodingParameters.length?a.encodings=e.recvEncodingParameters:a.encodings=[{}],a.rtcp={compound:e.rtcpParameters.compound},e.rtcpParameters.cname&&(a.rtcp.cname=e.rtcpParameters.cname),e.sendEncodingParameters.length&&(a.rtcp.ssrc=e.sendEncodingParameters[0].ssrc),e.rtpReceiver.receive(a))},d.prototype.setLocalDescription=function(e){var t,n,i=this;if(-1===["offer","answer"].indexOf(e.type))return Promise.reject(c("TypeError",'Unsupported type "'+e.type+'"'));if(!a("setLocalDescription",e.type,i.signalingState)||i._isClosed)return Promise.reject(c("InvalidStateError","Can not set local "+e.type+" in state "+i.signalingState));if("offer"===e.type)t=r.splitSections(e.sdp),n=t.shift(),t.forEach(function(e,t){var n=r.parseRtpParameters(e);i.transceivers[t].localCapabilities=n}),i.transceivers.forEach(function(e,t){i._gather(e.mid,t)});else if("answer"===e.type){t=r.splitSections(i._remoteDescription.sdp),n=t.shift();var s=r.matchPrefix(n,"a=ice-lite").length>0;t.forEach(function(e,t){var a=i.transceivers[t],c=a.iceGatherer,u=a.iceTransport,d=a.dtlsTransport,l=a.localCapabilities,h=a.remoteCapabilities;if(!(r.isRejected(e)&&0===r.matchPrefix(e,"a=bundle-only").length||a.rejected)){var p=r.getIceParameters(e,n),f=r.getDtlsParameters(e,n);s&&(f.role="server"),i.usingBundle&&0!==t||(i._gather(a.mid,t),"new"===u.state&&u.start(c,p,s?"controlling":"controlled"),"new"===d.state&&d.start(f));var m=o(l,h);i._transceive(a,m.codecs.length>0,!1)}})}return i._localDescription={type:e.type,sdp:e.sdp},"offer"===e.type?i._updateSignalingState("have-local-offer"):i._updateSignalingState("stable"),Promise.resolve()},d.prototype.setRemoteDescription=function(i){var d=this;if(-1===["offer","answer"].indexOf(i.type))return Promise.reject(c("TypeError",'Unsupported type "'+i.type+'"'));if(!a("setRemoteDescription",i.type,d.signalingState)||d._isClosed)return Promise.reject(c("InvalidStateError","Can not set remote "+i.type+" in state "+d.signalingState));var l={};d.remoteStreams.forEach(function(e){l[e.id]=e});var h=[],p=r.splitSections(i.sdp),f=p.shift(),m=r.matchPrefix(f,"a=ice-lite").length>0,v=r.matchPrefix(f,"a=group:BUNDLE ").length>0;d.usingBundle=v;var g=r.matchPrefix(f,"a=ice-options:")[0];return d.canTrickleIceCandidates=!!g&&g.substr(14).split(" ").indexOf("trickle")>=0,p.forEach(function(a,c){var u=r.splitLines(a),p=r.getKind(a),g=r.isRejected(a)&&0===r.matchPrefix(a,"a=bundle-only").length,y=u[0].substr(2).split(" ")[2],_=r.getDirection(a,f),S=r.parseMsid(a),E=r.getMid(a)||r.generateIdentifier();if(g||"application"===p&&("DTLS/SCTP"===y||"UDP/DTLS/SCTP"===y))d.transceivers[c]={mid:E,kind:p,protocol:y,rejected:!0};else{var b,C,T,A,R,k,w,I,P;!g&&d.transceivers[c]&&d.transceivers[c].rejected&&(d.transceivers[c]=d._createTransceiver(p,!0));var D,O,N=r.parseRtpParameters(a);g||(D=r.getIceParameters(a,f),(O=r.getDtlsParameters(a,f)).role="client"),w=r.parseRtpEncodingParameters(a);var M=r.parseRtcpParameters(a),L=r.matchPrefix(a,"a=end-of-candidates",f).length>0,x=r.matchPrefix(a,"a=candidate:").map(function(e){return r.parseCandidate(e)}).filter(function(e){return 1===e.component});if(("offer"===i.type||"answer"===i.type)&&!g&&v&&c>0&&d.transceivers[c]&&(d._disposeIceAndDtlsTransports(c),d.transceivers[c].iceGatherer=d.transceivers[0].iceGatherer,d.transceivers[c].iceTransport=d.transceivers[0].iceTransport,d.transceivers[c].dtlsTransport=d.transceivers[0].dtlsTransport,d.transceivers[c].rtpSender&&d.transceivers[c].rtpSender.setTransport(d.transceivers[0].dtlsTransport),d.transceivers[c].rtpReceiver&&d.transceivers[c].rtpReceiver.setTransport(d.transceivers[0].dtlsTransport)),"offer"!==i.type||g)"answer"!==i.type||g||(C=(b=d.transceivers[c]).iceGatherer,T=b.iceTransport,A=b.dtlsTransport,R=b.rtpReceiver,k=b.sendEncodingParameters,I=b.localCapabilities,d.transceivers[c].recvEncodingParameters=w,d.transceivers[c].remoteCapabilities=N,d.transceivers[c].rtcpParameters=M,x.length&&"new"===T.state&&(!m&&!L||v&&0!==c?x.forEach(function(e){s(b.iceTransport,e)}):T.setRemoteCandidates(x)),v&&0!==c||("new"===T.state&&T.start(C,D,"controlling"),"new"===A.state&&A.start(O)),!o(b.localCapabilities,b.remoteCapabilities).codecs.filter(function(e){return"rtx"===e.name.toLowerCase()}).length&&b.sendEncodingParameters[0].rtx&&delete b.sendEncodingParameters[0].rtx,d._transceive(b,"sendrecv"===_||"recvonly"===_,"sendrecv"===_||"sendonly"===_),!R||"sendrecv"!==_&&"sendonly"!==_?delete b.rtpReceiver:(P=R.track,S?(l[S.stream]||(l[S.stream]=new e.MediaStream),n(P,l[S.stream]),h.push([P,R,l[S.stream]])):(l.default||(l.default=new e.MediaStream),n(P,l.default),h.push([P,R,l.default]))));else{(b=d.transceivers[c]||d._createTransceiver(p)).mid=E,b.iceGatherer||(b.iceGatherer=d._createIceGatherer(c,v)),x.length&&"new"===b.iceTransport.state&&(!L||v&&0!==c?x.forEach(function(e){s(b.iceTransport,e)}):b.iceTransport.setRemoteCandidates(x)),I=e.RTCRtpReceiver.getCapabilities(p),t<15019&&(I.codecs=I.codecs.filter(function(e){return"rtx"!==e.name})),k=b.sendEncodingParameters||[{ssrc:1001*(2*c+2)}];var F,j=!1;"sendrecv"===_||"sendonly"===_?(j=!b.rtpReceiver,R=b.rtpReceiver||new e.RTCRtpReceiver(b.dtlsTransport,p),j&&(P=R.track,S&&"-"===S.stream||(S?(l[S.stream]||(l[S.stream]=new e.MediaStream,Object.defineProperty(l[S.stream],"id",{get:function(){return S.stream}})),Object.defineProperty(P,"id",{get:function(){return S.track}}),F=l[S.stream]):(l.default||(l.default=new e.MediaStream),F=l.default)),F&&(n(P,F),b.associatedRemoteMediaStreams.push(F)),h.push([P,R,F]))):b.rtpReceiver&&b.rtpReceiver.track&&(b.associatedRemoteMediaStreams.forEach(function(t){var n=t.getTracks().find(function(e){return e.id===b.rtpReceiver.track.id});n&&(function(t,n){n.removeTrack(t),n.dispatchEvent(new e.MediaStreamTrackEvent("removetrack",{track:t}))})(n,t)}),b.associatedRemoteMediaStreams=[]),b.localCapabilities=I,b.remoteCapabilities=N,b.rtpReceiver=R,b.rtcpParameters=M,b.sendEncodingParameters=k,b.recvEncodingParameters=w,d._transceive(d.transceivers[c],!1,j)}}}),void 0===d._dtlsRole&&(d._dtlsRole="offer"===i.type?"active":"passive"),d._remoteDescription={type:i.type,sdp:i.sdp},"offer"===i.type?d._updateSignalingState("have-remote-offer"):d._updateSignalingState("stable"),Object.keys(l).forEach(function(t){var n=l[t];if(n.getTracks().length){if(-1===d.remoteStreams.indexOf(n)){d.remoteStreams.push(n);var r=new Event("addstream");r.stream=n,e.setTimeout(function(){d._dispatchEvent("addstream",r)})}h.forEach(function(e){var t=e[0],r=e[1];n.id===e[2].id&&u(d,t,r,[n])})}}),h.forEach(function(e){e[2]||u(d,e[0],e[1],[])}),e.setTimeout(function(){d&&d.transceivers&&d.transceivers.forEach(function(e){e.iceTransport&&"new"===e.iceTransport.state&&e.iceTransport.getRemoteCandidates().length>0&&(console.warn("Timeout for addRemoteCandidate. Consider sending an end-of-candidates notification"),e.iceTransport.addRemoteCandidate({}))})},4e3),Promise.resolve()},d.prototype.close=function(){this.transceivers.forEach(function(e){e.iceTransport&&e.iceTransport.stop(),e.dtlsTransport&&e.dtlsTransport.stop(),e.rtpSender&&e.rtpSender.stop(),e.rtpReceiver&&e.rtpReceiver.stop()}),this._isClosed=!0,this._updateSignalingState("closed")},d.prototype._updateSignalingState=function(e){this.signalingState=e;var t=new Event("signalingstatechange");this._dispatchEvent("signalingstatechange",t)},d.prototype._maybeFireNegotiationNeeded=function(){var t=this;"stable"===this.signalingState&&!0!==this.needNegotiation&&(this.needNegotiation=!0,e.setTimeout(function(){if(t.needNegotiation){t.needNegotiation=!1;var e=new Event("negotiationneeded");t._dispatchEvent("negotiationneeded",e)}},0))},d.prototype._updateIceConnectionState=function(){var e,t={new:0,closed:0,checking:0,connected:0,completed:0,disconnected:0,failed:0};if(this.transceivers.forEach(function(e){e.iceTransport&&!e.rejected&&t[e.iceTransport.state]++}),e="new",t.failed>0?e="failed":t.checking>0?e="checking":t.disconnected>0?e="disconnected":t.new>0?e="new":t.connected>0?e="connected":t.completed>0&&(e="completed"),e!==this.iceConnectionState){this.iceConnectionState=e;var n=new Event("iceconnectionstatechange");this._dispatchEvent("iceconnectionstatechange",n)}},d.prototype._updateConnectionState=function(){var e,t={new:0,closed:0,connecting:0,connected:0,completed:0,disconnected:0,failed:0};if(this.transceivers.forEach(function(e){e.iceTransport&&e.dtlsTransport&&!e.rejected&&(t[e.iceTransport.state]++,t[e.dtlsTransport.state]++)}),t.connected+=t.completed,e="new",t.failed>0?e="failed":t.connecting>0?e="connecting":t.disconnected>0?e="disconnected":t.new>0?e="new":t.connected>0&&(e="connected"),e!==this.connectionState){this.connectionState=e;var n=new Event("connectionstatechange");this._dispatchEvent("connectionstatechange",n)}},d.prototype.createOffer=function(){var n=this;if(n._isClosed)return Promise.reject(c("InvalidStateError","Can not call createOffer after close"));var o=n.transceivers.filter(function(e){return"audio"===e.kind}).length,a=n.transceivers.filter(function(e){return"video"===e.kind}).length,s=arguments[0];if(s){if(s.mandatory||s.optional)throw new TypeError("Legacy mandatory/optional constraints not supported.");void 0!==s.offerToReceiveAudio&&(o=!0===s.offerToReceiveAudio?1:!1===s.offerToReceiveAudio?0:s.offerToReceiveAudio),void 0!==s.offerToReceiveVideo&&(a=!0===s.offerToReceiveVideo?1:!1===s.offerToReceiveVideo?0:s.offerToReceiveVideo)}for(n.transceivers.forEach(function(e){"audio"===e.kind?--o<0&&(e.wantReceive=!1):"video"===e.kind&&--a<0&&(e.wantReceive=!1)});o>0||a>0;)o>0&&(n._createTransceiver("audio"),o--),a>0&&(n._createTransceiver("video"),a--);var u=r.writeSessionBoilerplate(n._sdpSessionId,n._sdpSessionVersion++);n.transceivers.forEach(function(i,o){var a=i.track,s=i.kind,c=i.mid||r.generateIdentifier();i.mid=c,i.iceGatherer||(i.iceGatherer=n._createIceGatherer(o,n.usingBundle));var u=e.RTCRtpSender.getCapabilities(s);t<15019&&(u.codecs=u.codecs.filter(function(e){return"rtx"!==e.name})),u.codecs.forEach(function(e){"H264"===e.name&&void 0===e.parameters["level-asymmetry-allowed"]&&(e.parameters["level-asymmetry-allowed"]="1"),i.remoteCapabilities&&i.remoteCapabilities.codecs&&i.remoteCapabilities.codecs.forEach(function(t){e.name.toLowerCase()===t.name.toLowerCase()&&e.clockRate===t.clockRate&&(e.preferredPayloadType=t.payloadType)})}),u.headerExtensions.forEach(function(e){(i.remoteCapabilities&&i.remoteCapabilities.headerExtensions||[]).forEach(function(t){e.uri===t.uri&&(e.id=t.id)})});var d=i.sendEncodingParameters||[{ssrc:1001*(2*o+1)}];a&&t>=15019&&"video"===s&&!d[0].rtx&&(d[0].rtx={ssrc:d[0].ssrc+1}),i.wantReceive&&(i.rtpReceiver=new e.RTCRtpReceiver(i.dtlsTransport,s)),i.localCapabilities=u,i.sendEncodingParameters=d}),"max-compat"!==n._config.bundlePolicy&&(u+="a=group:BUNDLE "+n.transceivers.map(function(e){return e.mid}).join(" ")+"\r\n"),u+="a=ice-options:trickle\r\n",n.transceivers.forEach(function(e,t){u+=i(e,e.localCapabilities,"offer",e.stream,n._dtlsRole),u+="a=rtcp-rsize\r\n",!e.iceGatherer||"new"===n.iceGatheringState||0!==t&&n.usingBundle||(e.iceGatherer.getLocalCandidates().forEach(function(e){e.component=1,u+="a="+r.writeCandidate(e)+"\r\n"}),"completed"===e.iceGatherer.state&&(u+="a=end-of-candidates\r\n"))});var d=new e.RTCSessionDescription({type:"offer",sdp:u});return Promise.resolve(d)},d.prototype.createAnswer=function(){var n=this;if(n._isClosed)return Promise.reject(c("InvalidStateError","Can not call createAnswer after close"));if("have-remote-offer"!==n.signalingState&&"have-local-pranswer"!==n.signalingState)return Promise.reject(c("InvalidStateError","Can not call createAnswer in signalingState "+n.signalingState));var a=r.writeSessionBoilerplate(n._sdpSessionId,n._sdpSessionVersion++);n.usingBundle&&(a+="a=group:BUNDLE "+n.transceivers.map(function(e){return e.mid}).join(" ")+"\r\n"),a+="a=ice-options:trickle\r\n";var s=r.getMediaSections(n._remoteDescription.sdp).length;n.transceivers.forEach(function(e,r){if(!(r+1>s)){if(e.rejected)return"application"===e.kind?"DTLS/SCTP"===e.protocol?a+="m=application 0 DTLS/SCTP 5000\r\n":a+="m=application 0 "+e.protocol+" webrtc-datachannel\r\n":"audio"===e.kind?a+="m=audio 0 UDP/TLS/RTP/SAVPF 0\r\na=rtpmap:0 PCMU/8000\r\n":"video"===e.kind&&(a+="m=video 0 UDP/TLS/RTP/SAVPF 120\r\na=rtpmap:120 VP8/90000\r\n"),void(a+="c=IN IP4 0.0.0.0\r\na=inactive\r\na=mid:"+e.mid+"\r\n");var c;e.stream&&("audio"===e.kind?c=e.stream.getAudioTracks()[0]:"video"===e.kind&&(c=e.stream.getVideoTracks()[0]),c&&t>=15019&&"video"===e.kind&&!e.sendEncodingParameters[0].rtx&&(e.sendEncodingParameters[0].rtx={ssrc:e.sendEncodingParameters[0].ssrc+1}));var u=o(e.localCapabilities,e.remoteCapabilities);!u.codecs.filter(function(e){return"rtx"===e.name.toLowerCase()}).length&&e.sendEncodingParameters[0].rtx&&delete e.sendEncodingParameters[0].rtx,a+=i(e,u,"answer",e.stream,n._dtlsRole),e.rtcpParameters&&e.rtcpParameters.reducedSize&&(a+="a=rtcp-rsize\r\n")}});var u=new e.RTCSessionDescription({type:"answer",sdp:a});return Promise.resolve(u)},d.prototype.addIceCandidate=function(e){var t,n=this;return e&&void 0===e.sdpMLineIndex&&!e.sdpMid?Promise.reject(new TypeError("sdpMLineIndex or sdpMid required")):new Promise(function(i,o){if(!n._remoteDescription)return o(c("InvalidStateError","Can not add ICE candidate without a remote description"));if(e&&""!==e.candidate){var a=e.sdpMLineIndex;if(e.sdpMid)for(var u=0;u0?r.parseCandidate(e.candidate):{};if("tcp"===l.protocol&&(0===l.port||9===l.port))return i();if(l.component&&1!==l.component)return i();if((0===a||a>0&&d.iceTransport!==n.transceivers[0].iceTransport)&&!s(d.iceTransport,l))return o(c("OperationError","Can not add ICE candidate"));var h=e.candidate.trim();0===h.indexOf("a=")&&(h=h.substr(2)),(t=r.getMediaSections(n._remoteDescription.sdp))[a]+="a="+(l.type?h:"end-of-candidates")+"\r\n",n._remoteDescription.sdp=r.getDescription(n._remoteDescription.sdp)+t.join("")}else for(var p=0;pthis.maxstats&&(i.values.shift(),i.times.shift()),i.endTime=o};var k=function(e){return null==e?"":"type: "+e.type+"\r\n"+e.sdp};R.prototype.getConnectionState=function(){var e=this.peerconnection.iceConnectionState;return"completed"===e?"connected":e},R.prototype._getDesiredMediaDirection=function(e){var t=!0;return e===d.a?t=this.audioTransferActive:e===d.c&&(t=this.videoTransferActive),t?this.hasAnyTracksOfType(e)?"sendrecv":"recvonly":"inactive"},R.prototype.isSimulcastOn=function(){return!this.options.disableSimulcast},R.prototype._peerVideoTypeChanged=function(e,t){if(e){var n=this.getRemoteTracks(e,d.c);n.length&&n[0]._setVideoType(t)}else A.error("No endpointID on peerVideoTypeChanged "+this)},R.prototype._peerMutedChanged=function(e,t,n){if(e){var r=this.getRemoteTracks(e,t);r.length&&r[0].setMute(n)}else A.error("On peerMuteChanged - no endpoint ID")},R.prototype.getLocalTracks=function(e){var t=Array.from(this.localTracks.values());return void 0!==e&&(t=t.filter(function(t){return t.getType()===e})),t},R.prototype.hasAnyTracksOfType=function(e){if(!e)throw new Error('"mediaType" is required');return this.getLocalTracks(e).length>0},R.prototype.getRemoteTracks=function(e,t){var n=[],r=e?[e]:this.remoteTracks.keys(),i=Array.isArray(r),o=0;for(r=i?r:r["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var a;if(i){if(o>=r.length)break;a=r[o++]}else{if((o=r.next()).done)break;a=o.value}var s=a,c=this.remoteTracks.get(s);if(c){var u=c.keys(),d=Array.isArray(u),l=0;for(u=d?u:u["function"==typeof Symbol&&"function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var h;if(d){if(l>=u.length)break;h=u[l++]}else{if((l=u.next()).done)break;h=l.value}var p=h;if(!t||t===p){var f=c.get(p);f&&n.push(f)}}}}return n},R.prototype.getTrackBySSRC=function(e){if("number"!=typeof e)throw new Error("SSRC "+e+" is not a number");var t=this.localTracks.values(),n=Array.isArray(t),r=0;for(t=n?t:t["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var i;if(n){if(r>=t.length)break;i=t[r++]}else{if((r=t.next()).done)break;i=r.value}var o=i;if(this.getLocalSSRC(o)===e)return o}var a=this.getRemoteTracks(),s=Array.isArray(a),c=0;for(a=s?a:a["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var u;if(s){if(c>=a.length)break;u=a[c++]}else{if((c=a.next()).done)break;u=c.value}var d=u;if(d.getSSRC()===e)return d}return null},R.prototype.getSsrcByTrackId=function(e){var t=function(t){return t.getTrack().id===e},n=this.getLocalTracks().find(t);if(n)return this.getLocalSSRC(n);var r=this.getRemoteTracks().find(t);return r?r.getSSRC():null},R.prototype._remoteStreamAdded=function(e){var t=this,n=p.a.getStreamID(e);if(p.a.isUserStreamById(n)){m.a.isChromiumBased()&&(e.onaddtrack=function(n){t._remoteTrackAdded(e,n.track)},e.onremovetrack=function(n){t._remoteTrackRemoved(e,n.track)});var r=e.getAudioTracks(),i=Array.isArray(r),o=0;for(r=i?r:r["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var a;if(i){if(o>=r.length)break;a=r[o++]}else{if((o=r.next()).done)break;a=o.value}var s=a;this._remoteTrackAdded(e,s)}var c=e.getVideoTracks(),u=Array.isArray(c),d=0;for(c=u?c:c["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var l;if(u){if(d>=c.length)break;l=c[d++]}else{if((d=c.next()).done)break;l=d.value}var h=l;this._remoteTrackAdded(e,h)}}else A.info(this+" ignored remote 'stream added' event for non-user streamid: "+n)},R.prototype._remoteTrackAdded=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,r=p.a.getStreamID(e),i=t.kind;if(this.isP2P||p.a.isUserStreamById(r))if(A.info(this+" remote track added:",r,i),i){var o,a=m.a.usesPlanB()?new S.a(this.remoteDescription.sdp):new S.a(this.peerconnection.remoteDescription.sdp);if(m.a.usesUnifiedPlan())if(n&&n.mid){var c=n.mid;o=a.media.filter(function(e){return C.a.findLine(e,"a=mid:"+c)})}else o=a.media.filter(function(e){var t=C.a.findLine(e,"a=msid");return void 0!==t&&r===t.substring(7).split(" ")[0]});else o=a.media.filter(function(e){return e.startsWith("m="+i)});if(o.length){var u=C.a.findLines(o[0],"a=ssrc:");if((u=u.filter(function(e){return-1!==e.indexOf("msid:"+r)})).length){var d=u[0].substring(7).split(" ")[0],l=Number(d),h=this.signalingLayer.getSSRCOwner(l);if(isNaN(l)||l<0)s.callErrorHandler(new Error("Invalid SSRC: "+d+" for remote track, msid: "+r+" media type: "+i));else if(h){A.log(this+" associated ssrc",h,l);var f=this.signalingLayer.getPeerMediaInfo(h,i);if(f){var v=f.muted,g=f.videoType;this._createRemoteTrack(h,e,t,i,g,l,v)}else s.callErrorHandler(new Error(this+": no peer media info available for "+h))}else s.callErrorHandler(new Error("No SSRC owner known for: "+l+" for remote track, msid: "+r+" media type: "+i))}else s.callErrorHandler(new Error("No SSRC lines for streamId "+r+" for remote track, media type: "+i))}else s.callErrorHandler(new Error("No media lines for type "+i+" found in remote SDP for remote track: "+r))}else s.callErrorHandler(new Error("MediaType undefined for remote track, stream id: "+r));else A.info(this+" ignored remote 'stream added' event for non-user streamid: "+r)},R.prototype._createRemoteTrack=function(e,t,n,r,i,o,a){var s=this.remoteTracks.get(e);s||(s=new Map,this.remoteTracks.set(e,s));var u=s.get(r);if(u&&u.getTrack()===n)A.info(this+" ignored duplicated remote track added event for: "+e+", "+r);else{u&&A.error(this+" overwriting remote track for"+e+" "+r);var d=new c.a(this.rtc,this.rtc.conference,e,t,n,r,i,o,a,this.isP2P);s.set(r,d),this.eventEmitter.emit(g.a.REMOTE_TRACK_ADDED,d)}},R.prototype._remoteStreamRemoved=function(e){if(p.a.isUserStream(e)){var t=e.getVideoTracks(),n=Array.isArray(t),r=0;for(t=n?t:t["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var i;if(n){if(r>=t.length)break;i=t[r++]}else{if((r=t.next()).done)break;i=r.value}var o=i;this._remoteTrackRemoved(e,o)}var a=e.getAudioTracks(),s=Array.isArray(a),c=0;for(a=s?a:a["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var u;if(s){if(c>=a.length)break;u=a[c++]}else{if((c=a.next()).done)break;u=c.value}var d=u;this._remoteTrackRemoved(e,d)}}else{var l=p.a.getStreamID(e);A.info("Ignored remote 'stream removed' event for non-user stream "+l)}},R.prototype._remoteTrackRemoved=function(e,t){var n=p.a.getStreamID(e),r=t&&p.a.getTrackID(t);A.info(this+" - remote track removed: "+n+", "+r),n?r?this._removeRemoteTrackById(n,r)||A.warn(this+" Removed track not found for msid: "+n+",\n track id: "+r):s.callErrorHandler(new Error(this+" remote track removal failed - no track ID")):s.callErrorHandler(new Error(this+" remote track removal failed - no stream ID"))},R.prototype._getRemoteTrackById=function(e,t){var n=this.remoteTracks.values(),r=Array.isArray(n),i=0;for(n=r?n:n["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var o;if(r){if(i>=n.length)break;o=n[i++]}else{if((i=n.next()).done)break;o=i.value}var a=o.values(),s=Array.isArray(a),c=0;for(a=s?a:a["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var u;if(s){if(c>=a.length)break;u=a[c++]}else{if((c=a.next()).done)break;u=c.value}var d=u;if(d.getStreamId()==e&&d.getTrackId()==t)return d}}},R.prototype.removeRemoteTracks=function(e){var t=[],n=this.remoteTracks.get(e);if(n){var r=n.get(d.a),i=n.get(d.c);r&&t.push(r),i&&t.push(i),this.remoteTracks.delete(e)}return A.debug(this+" removed remote tracks for "+e+" count: "+t.length),t},R.prototype._removeRemoteTrack=function(e){e.dispose();var t=e.getParticipantId(),n=this.remoteTracks.get(t);n?n.delete(e.getType())||A.error("Failed to remove "+e+" - type mapping messed up ?"):A.error("removeRemoteTrack: no remote tracks map for "+t),this.eventEmitter.emit(g.a.REMOTE_TRACK_REMOVED,e)},R.prototype._removeRemoteTrackById=function(e,t){var n=this._getRemoteTrackById(e,t);return n&&this._removeRemoteTrack(n),n};var w=function(e){if("object"!=typeof e||null===e||"string"!=typeof e.sdp)return A.warn("An empty description was passed as an argument."),e;var t=n(22),r=t.parse(e.sdp);void 0!==r&&void 0!==r.media&&Array.isArray(r.media)&&r.media.forEach(function(e){var t=[],n=[];if(void 0!==e.ssrcGroups&&Array.isArray(e.ssrcGroups)&&e.ssrcGroups.forEach(function(e){void 0!==e.semantics&&"FID"===e.semantics&&void 0!==e.ssrcs&&t.push(Number(e.ssrcs.split(" ")[0]))}),Array.isArray(e.ssrcs)){var r;for(r=0;r=0&&(n.push(e.ssrcs[r]),delete e.ssrcs[r]);for(r=0;r0&&void 0!==arguments[0]?arguments[0]:[];if(!m.a.isChrome()||!m.a.isVersionGreaterThan(70))return e;var t=_toConsumableArray(e);return e.filter(function(e){return"mslabel"===e.attribute&&"-"===e.value}).map(function(e){return e.id}).forEach(function(e){var n=t.find(function(t){return t.id===e&&"cname"===t.attribute});n.value="recvonly-"+e,(t=t.filter(function(t){return t.id!==e})).push(n)}),t})(n)}});var i=t.write(r);return new RTCSessionDescription({type:e.type,sdp:i})};R.prototype.getLocalSSRC=function(e){var t=this._getSSRC(e.rtcId);return t&&t.ssrcs[0]},R.prototype._injectSsrcGroupForUnifiedSimulcast=function(e){var t=a.a.parse(e.sdp),n=t.media.find(function(e){return"video"===e.type});if(n.simulcast||n.simulcast_03){var r=[];if(n.ssrcs.forEach(function(e){"msid"===e.attribute&&r.push(e.id)}),n.ssrcGroups=n.ssrcGroups||[],n.ssrcGroups.find(function(e){return"SIM"===e.semantics}))return e;n.ssrcGroups.push({semantics:"SIM",ssrcs:r.join(" ")})}return new RTCSessionDescription({type:e.type,sdp:a.a.write(t)})};var I={signalingState:function(){return this.peerconnection.signalingState},iceConnectionState:function(){return this.peerconnection.iceConnectionState},localDescription:function(){var e=this.peerconnection.localDescription;return e?(this.trace("getLocalDescription::preTransform",k(e)),m.a.usesUnifiedPlan()?(e=this.interop.toPlanB(e),this.trace("getLocalDescription::postTransform (Plan B)",k(e)),e=this._injectSsrcGroupForUnifiedSimulcast(e),this.trace("getLocalDescription::postTransform (inject ssrc group)",k(e))):(m.a.doesVideoMuteByStreamRemove()&&(e=this.localSdpMunger.maybeAddMutedLocalVideoTracksToSDP(e),A.debug("getLocalDescription::postTransform (munge local SDP)",e)),e=(function(e,t){if(!e)throw new Error("No local description passed in.");var n=new b.a(e.sdp),r=n.selectMedia("audio"),i=!1;r&&"sendrecv"!==r.direction&&(t.startSilent?r.direction="inactive":r.direction="sendrecv",i=!0);var o=n.selectMedia("video");return o&&"sendrecv"!==o.direction&&(o.direction="sendrecv",i=!0),i?new RTCSessionDescription({type:e.type,sdp:n.toRawSDP()}):e})(e,this.options)),e=this.localSdpMunger.transformStreamIdentifiers(e)):(A.debug("getLocalDescription no localDescription found"),{})},remoteDescription:function(){var e=this.peerconnection.remoteDescription;return e?(this.trace("getRemoteDescription::preTransform",k(e)),m.a.usesUnifiedPlan()&&(e=this.interop.toPlanB(e),this.trace("getRemoteDescription::postTransform (Plan B)",k(e))),e):(A.debug("getRemoteDescription no remoteDescription found"),{})}};function P(e){return e.getLocalTracks().some(function(e){return"camera"===e.videoType})}Object.keys(I).forEach(function(e){Object.defineProperty(R.prototype,e,{get:I[e]})}),R.prototype._getSSRC=function(e){return this.localSSRCs.get(e)},R.prototype.addTrack=function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=e.rtcId;if(A.info("add "+e+" to: "+this),this.localTracks.has(n))A.error(e+" is already in "+this);else{if(this.localTracks.set(n,e),m.a.usesUnifiedPlan()&&t)return this.tpcUtils.addTrack(e,t);var r=e.getOriginalStream();if(r?this._addStream(r):(!m.a.doesVideoMuteByStreamRemove()||e.isAudioTrack()||e.isVideoTrack()&&!e.isMuted())&&A.error(this+" no WebRTC stream for: "+e),m.a.usesPlanB()&&m.a.doesVideoMuteByStreamRemove()&&e.isVideoTrack()&&e.isMuted()){var i=this.generateNewStreamSSRCInfo(e);this.sdpConsistency.setPrimarySsrc(i.ssrcs[0]);var o=i.groups.find(function(e){return"SIM"===e.semantics});o&&this.simulcast.setSsrcCache(o.ssrcs);var a=i.groups.filter(function(e){return"FID"===e.semantics});if(a){var s=new Map;a.forEach(function(e){var t=e.ssrcs[0],n=e.ssrcs[1];s.set(t,n)}),this.rtxModifier.setSsrcCache(s)}}m.a.usesUnifiedPlan()&&!m.a.usesSdpMungingForSimulcast()&&this.tpcUtils.setEncodings(e),e.isVideoTrack()&&e.videoType===l.CAMERA&&this.isSimulcastOn()&&this.tpcUtils._setSimulcastStreamConstraints(e.getTrack())}},R.prototype.addTrackUnmute=function(e){if(m.a.usesUnifiedPlan())return this.tpcUtils.addTrackUnmute(e);if(!this._assertTrackBelongs("addTrackUnmute",e))return Promise.reject("Track not found on the peerconnection");A.info("Adding "+e+" as unmute to "+this);var t=e.getOriginalStream();return t?(this._addStream(t),Promise.resolve(!0)):(A.error("Unable to add "+e+" as unmute to "+this+" - no WebRTC stream"),Promise.reject("Stream not found"))},R.prototype._addStream=function(e){this.peerconnection.addStream(e),this._addedStreams.push(e)},R.prototype._removeStream=function(e){m.a.supportsRtpSender()?this._handleSenderRemoveStream(e):this.peerconnection.removeStream(e),this._addedStreams=this._addedStreams.filter(function(t){return t!==e})},R.prototype._assertTrackBelongs=function(e,t){var n=this.localTracks.has(t.rtcId);return n||A.error(e+": "+t+" does not belong to "+this),n},R.prototype.isMediaStreamInPc=function(e){return this._addedStreams.indexOf(e)>-1},R.prototype.removeTrack=function(e){if(m.a.usesUnifiedPlan())return this.tpcUtils.removeTrack(e);var t=e.getOriginalStream();this.trace("removeStream",e.rtcId,t?t.id:void 0),this._assertTrackBelongs("removeStream",e)&&(this.localTracks.delete(e.rtcId),this.localSSRCs.delete(e.rtcId),t&&(m.a.supportsRtpSender()?this._handleSenderRemoveStream(t):this.peerconnection.removeStream(t)))},R.prototype.findSenderByKind=function(e){return this.peerconnection.getSenders().find(function(t){return t.track&&t.track.kind===e})},R.prototype.findSenderByStream=function(e){var t=e.getTracks()[0];if(t)return this.peerconnection.getSenders().find(function(e){return e.track===t});A.error("Cannot find sender: no tracks.")},R.prototype.findReceiverForTrack=function(e){return this.peerconnection.getReceivers().find(function(t){return t.track===e})},R.prototype.findSenderForTrack=function(e){return this.peerconnection.getSenders().find(function(t){return t.track===e})},R.prototype.replaceTrack=function(e,t){return m.a.usesUnifiedPlan()?this.tpcUtils.replaceTrack(e,t):(e&&this.removeTrack(e),t&&this.addTrack(t),Promise.resolve(!0))},R.prototype.removeTrackMute=function(e){if(m.a.usesUnifiedPlan())return this.tpcUtils.removeTrackMute(e);var t=e.getOriginalStream();return this.trace("removeStreamMute",e.rtcId,t?t.id:null),this._assertTrackBelongs("removeStreamMute",e)?t?(A.info("Removing "+e+" as mute from "+this),this._removeStream(t),Promise.resolve(!0)):(A.error("removeStreamMute - no WebRTC stream for "+e),Promise.reject("Stream not found")):Promise.reject("Track not found in the peerconnection")},R.prototype._handleSenderRemoveStream=function(e){if(e){var t=this.findSenderByStream(e);t?this.peerconnection.removeTrack(t):A.log("Cannot remove tracks: no RTPSender.")}},R.prototype.createDataChannel=function(e,t){return this.trace("createDataChannel",e,t),this.peerconnection.createDataChannel(e,t)},R.prototype._ensureSimulcastGroupIsLast=function(e){var t=e.sdp,n=t.indexOf("m=video"),r=t.indexOf("a=ssrc-group:SIM",n),i=t.lastIndexOf("a=ssrc-group");if(-1===r||-1===i||i===r)return e;var o=t.indexOf("\r\n",r),a=t.substring(r,o+2);i=(t=t.replace(a,"")).lastIndexOf("a=ssrc-group");var s=t.indexOf("\r\n",i);return t=t.slice(0,s)+"\r\n"+a.trim()+t.slice(s),new RTCSessionDescription({type:e.type,sdp:t})},R.prototype._adjustLocalMediaDirection=function(e){var t=new b.a(e.sdp),n=!1,r=t.selectMedia("audio");if(r){var i=this._getDesiredMediaDirection(d.a);r.direction!==i&&(r.direction=i,A.info("Adjusted local audio direction to "+i),n=!0)}else A.warn('No "audio" media found int the local description');var o=t.selectMedia("video");if(o){var a=this._getDesiredMediaDirection(d.c);o.direction!==a&&(o.direction=a,A.info("Adjusted local video direction to "+a),n=!0)}else A.warn('No "video" media found in the local description');return n?new RTCSessionDescription({type:e.type,sdp:t.toRawSDP()}):e},R.prototype.setLocalDescription=function(e){var t=this,n=e;if(this.trace("setLocalDescription::preTransform",k(n)),this.options.disableH264||this.options.preferH264){var r=a.a.parse(n.sdp),i=r.media.find(function(e){return"video"===e.type});this.options.disableH264?C.a.stripVideoCodec(i,"h264"):C.a.preferVideoCodec(i,"h264"),n=new RTCSessionDescription({type:n.type,sdp:a.a.write(r)}),this.trace("setLocalDescription::postTransform (H264)",k(n))}return m.a.usesPlanB()?(n=this._adjustLocalMediaDirection(n),n=this._ensureSimulcastGroupIsLast(n)):(n=this.interop.toUnifiedPlan(n),this.trace("setLocalDescription::postTransform (Unified Plan)",k(n))),new Promise(function(e,r){t.peerconnection.setLocalDescription(n).then(function(){t.trace("setLocalDescriptionOnSuccess");var r=C.a.getUfrag(n.sdp);r!==t.localUfrag&&(t.localUfrag=r,t.eventEmitter.emit(g.a.LOCAL_UFRAG_CHANGED,t,r)),e()},function(e){t.trace("setLocalDescriptionOnFailure",e),t.eventEmitter.emit(g.a.SET_LOCAL_DESCRIPTION_FAILED,e,t),r(e)})})},R.prototype.setAudioTransferActive=function(e){if(A.debug(this+" audio transfer active: "+e),m.a.usesUnifiedPlan())return this.tpcUtils.setAudioTransferActive(e);var t=this.audioTransferActive!==e;return this.audioTransferActive=e,t},R.prototype.setMaxBitRate=function(e){var t=this;if(!(e.type===d.a||m.a.usesPlanB()&&!this.options.capScreenshareBitrate||m.a.usesPlanB()&&"camera"===e.videoType))if(this.peerconnection.getSenders){var n=e.videoType,r=e.track.id;this.peerconnection.getSenders().filter(function(e){return e.track&&e.track.id===r}).forEach(function(e){try{var r=e.getParameters();if(!r.encodings||!r.encodings.length)return;for(var i in A.debug("Setting max bitrate on video stream"),r.encodings)r.encodings.hasOwnProperty(i)&&(r.encodings[i].maxBitrate="desktop"===n&&m.a.usesPlanB()?5e5:t.isSimulcastOn()?t.tpcUtils.simulcastEncodings[i].maxBitrate:25e5);e.setParameters(r)}catch(e){A.error("Browser does not support getParameters/setParamters or setting max bitrate on the encodings: ",e)}})}else A.debug("Browser doesn't support RTCRtpSender")},R.prototype.setRemoteDescription=function(e){var t=this;if(this.trace("setRemoteDescription::preTransform",k(e)),m.a.usesPlanB()){if(e=this.simulcast.mungeRemoteDescription(e),this.trace("setRemoteDescription::postTransform (simulcast)",k(e)),this.options.preferH264){var n=a.a.parse(e.sdp),r=n.media.find(function(e){return"video"===e.type});C.a.preferVideoCodec(r,"h264"),e=new RTCSessionDescription({type:e.type,sdp:a.a.write(n)})}e=w(e)}else{var i=this.peerconnection.remoteDescription;e=this.interop.toUnifiedPlan(e,i),this.trace("setRemoteDescription::postTransform (Unified)",k(e)),this.isSimulcastOn()&&(e=this.simulcast.mungeRemoteDescription(e),e=this.tpcUtils._insertUnifiedPlanSimulcastReceive(e),this.trace("setRemoteDescription::postTransform (sim receive)",k(e)),e=this.tpcUtils._ensureCorrectOrderOfSsrcs(e))}return new Promise(function(n,r){t.peerconnection.setRemoteDescription(e).then(function(){t.trace("setRemoteDescriptionOnSuccess");var r=C.a.getUfrag(e.sdp);r!==t.remoteUfrag&&(t.remoteUfrag=r,t.eventEmitter.emit(g.a.REMOTE_UFRAG_CHANGED,t,r)),n()},function(e){t.trace("setRemoteDescriptionOnFailure",e),t.eventEmitter.emit(g.a.SET_REMOTE_DESCRIPTION_FAILED,e,t),r(e)})})},R.prototype.setSenderVideoConstraint=function(e){var t=this;this.senderVideoMaxHeight=e;var n=Array.from(this.localTracks.values()).find(function(e){return e.isVideoTrack()});if(!n||n.isMuted()||n.videoType!==l.CAMERA)return Promise.resolve();var r=n.getTrack();if(this.isSimulcastOn()){var i=Promise.resolve(),o=n._constraints.height.ideal?n._constraints.height.ideal:n._constraints.height;return r.getSettings().height!==o&&(i=r.applyConstraints(n._constraints)),i.then(function(){var n=t.tpcUtils.simulcastStreamConstraints.map(function(t){return t.height<=e}),r=t.findSenderByKind(d.c);if(!r)return Promise.reject(new Error("RTCRtpSender not found for local video"));var i=r.getParameters();if(!i||!i.encodings||!i.encodings.length)return Promise.reject(new Error("RTCRtpSendParameters not found for local video track"));for(var o in A.debug("Setting max height of "+e+" on local video"),i.encodings)i.encodings.hasOwnProperty(o)&&(i.encodings[o].active=n[o]);return r.setParameters(i)})}var a=(r.getSettings().width/r.getSettings().height).toPrecision(4);return A.debug("Setting max height of "+e+" on local video"),r.applyConstraints({aspectRatio:a,height:{ideal:e}})},R.prototype.setVideoTransferActive=function(e){if(A.debug(this+" video transfer active: "+e),m.a.usesUnifiedPlan())return this.tpcUtils.setVideoTransferActive(e);var t=this.videoTransferActive!==e;return this.videoTransferActive=e,t},R.prototype.sendTones=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:200,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:200;if(!this._dtmfSender){if(this.peerconnection.getSenders){var r=this.peerconnection.getSenders().find(function(e){return e.dtmf});this._dtmfSender=r&&r.dtmf,this._dtmfSender&&A.info(this+" initialized DTMFSender using getSenders")}if(!this._dtmfSender){var i=Array.from(this.localTracks.values()).find(function(e){return e.isAudioTrack()});this.peerconnection.createDTMFSender&&i&&(this._dtmfSender=this.peerconnection.createDTMFSender(i.getTrack())),this._dtmfSender&&A.info(this+" initialized DTMFSender using deprecated createDTMFSender")}this._dtmfSender&&(this._dtmfSender.ontonechange=this._onToneChange.bind(this))}if(this._dtmfSender){if(this._dtmfSender.toneBuffer)return void this._dtmfTonesQueue.push({tones:e,duration:t,interToneGap:n});this._dtmfSender.insertDTMF(e,t,n)}else A.warn(this+" sendTones - failed to select DTMFSender")},R.prototype._onToneChange=function(e){if(this._dtmfSender&&""===e.tone&&this._dtmfTonesQueue.length){var t=this._dtmfTonesQueue.shift(),n=t.tones,r=t.duration,i=t.interToneGap;this._dtmfSender.insertDTMF(n,r,i)}},R.prototype.generateRecvonlySsrc=function(){var e=C.a.generateSsrc();A.info(this+" generated new recvonly SSRC: "+e),this.sdpConsistency.setPrimarySsrc(e)},R.prototype.clearRecvonlySsrc=function(){A.info("Clearing primary video SSRC!"),this.sdpConsistency.clearVideoSsrcCache()},R.prototype.close=function(){this.trace("stop"),this.signalingLayer.off(T.a,this._peerMutedChanged),this.signalingLayer.off(T.b,this._peerVideoTypeChanged);var e=this.remoteTracks.values(),t=Array.isArray(e),n=0;for(e=t?e:e["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var r;if(t){if(n>=e.length)break;r=e[n++]}else{if((n=e.next()).done)break;r=n.value}var i=r.values(),o=Array.isArray(i),a=0;for(i=o?i:i["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var s;if(o){if(a>=i.length)break;s=i[a++]}else{if((a=i.next()).done)break;s=a.value}var c=s;this._removeRemoteTrack(c)}}this.remoteTracks.clear(),this._addedStreams=[],this._dtmfSender=null,this._dtmfTonesQueue=[],this.rtc._removePeerConnection(this)||A.error("RTC._removePeerConnection returned false"),null!==this.statsinterval&&(window.clearInterval(this.statsinterval),this.statsinterval=null),A.info("Closing "+this+"..."),this.peerconnection.close()},R.prototype.createAnswer=function(e){return this._createOfferOrAnswer(!1,e)},R.prototype.createOffer=function(e){return this._createOfferOrAnswer(!0,e)},R.prototype._createOfferOrAnswer=function(e,t){var n=this,r=e?"Offer":"Answer";this.trace("create"+r,JSON.stringify(t,null," "));var i=function(t,i,o){try{if(n.trace("create"+r+"OnSuccess::preTransform",k(t)),m.a.usesPlanB()&&(n.hasAnyTracksOfType(d.c)||n.sdpConsistency.hasPrimarySsrcCached()||n.generateRecvonlySsrc(),t=new RTCSessionDescription({type:t.type,sdp:n.sdpConsistency.makeVideoPrimarySsrcsConsistent(t.sdp)}),n.trace("create"+r+"OnSuccess::postTransform (make primary audio/video ssrcs consistent)",k(t))),n.isSimulcastOn()&&m.a.usesSdpMungingForSimulcast()&&(!n.options.capScreenshareBitrate||n.options.capScreenshareBitrate&&P(n))&&(t=n.simulcast.mungeLocalDescription(t),n.trace("create"+r+"OnSuccess::postTransform (simulcast)",k(t))),!n.options.disableRtx&&m.a.supportsRtx()&&(t=new RTCSessionDescription({type:t.type,sdp:n.rtxModifier.modifyRtxSsrcs(t.sdp)}),n.trace("create"+r+"OnSuccess::postTransform (rtx modifier)",k(t))),!e){var s=new S.a(n.remoteDescription.sdp),c=new S.a(t.sdp);!(function(e,t){(m.a.isChromiumBased()||m.a.isReactNative())&&e&&t&&e.media&&t.media&&e.media.length===t.media.length&&(t.media.forEach(function(n,r){C.a.findLine(e.media[r],"a=setup:actpass",e.session)&&(t.media[r]=n.replace(/a=setup:active/g,"a=setup:passive"))}),t.raw=t.session+t.media.join(""))})(s,c),t=new RTCSessionDescription({type:t.type,sdp:c.raw})}var u=(function(e){var t=new Map,n=new Map;if("object"!=typeof e||null===e||"string"!=typeof e.sdp)return A.warn("An empty description was passed as an argument."),t;var r=a.a.parse(e.sdp);if(!Array.isArray(r.media))return t;var i=r.media,o=Array.isArray(i),s=0;for(i=o?i:i["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var c;if(o){if(s>=i.length)break;c=i[s++]}else{if((s=i.next()).done)break;c=s.value}var u=c;if(Array.isArray(u.ssrcs)){if(Array.isArray(u.ssrcGroups)){var d=u.ssrcGroups,l=Array.isArray(d),h=0;for(d=l?d:d["function"==typeof Symbol&&"function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var p;if(l){if(h>=d.length)break;p=d[h++]}else{if((h=d.next()).done)break;p=h.value}var f=p;if(void 0!==f.semantics&&void 0!==f.ssrcs){var m=f.ssrcs.split(" ").map(function(e){return parseInt(e,10)}),v=m[0];f.ssrcs=m,n.has(v)||n.set(v,[]),n.get(v).push(f)}}}var g=u.ssrcs,y=Array.isArray(g),_=0;for(g=y?g:g["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var S;if(y){if(_>=g.length)break;S=g[_++]}else{if((_=g.next()).done)break;S=_.value}var E=S;if("msid"===E.attribute){var b=E.value,C=t.get(b);C||(C={ssrcs:[],groups:[],msid:b},t.set(b,C));var T=E.id;if(C.ssrcs.push(T),n.has(T)){var R=n.get(T),k=Array.isArray(R),w=0;for(R=k?R:R["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var I;if(k){if(w>=R.length)break;I=R[w++]}else{if((w=R.next()).done)break;I=w.value}var P=I;C.groups.push(P)}}}}}}return t})(t);A.debug("Got local SSRCs MAP: ",u),n._processLocalSSRCsMap(u),i(t)}catch(e){n.trace("create"+r+"OnError",e),n.trace("create"+r+"OnError",k(t)),A.error("create"+r+"OnError",e,k(t)),o(e)}},o=function(t,i){n.trace("create"+r+"OnFailure",t);var o=e?g.a.CREATE_OFFER_FAILED:g.a.CREATE_ANSWER_FAILED;n.eventEmitter.emit(o,t,n),i(t)};return new Promise(function(r,a){(e?n.peerconnection.createOffer(t):n.peerconnection.createAnswer(t)).then(function(e){return i(e,r,a)},function(e){return o(e,a)})})},R.prototype._extractPrimarySSRC=function(e){return e&&e.groups&&e.groups.length?e.groups[0].ssrcs[0]:e&&e.ssrcs&&e.ssrcs.length?e.ssrcs[0]:null},R.prototype._processLocalSSRCsMap=function(e){var t=this.localTracks.values(),n=Array.isArray(t),r=0;for(t=n?t:t["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var i;if(n){if(r>=t.length)break;i=t[r++]}else{if((r=t.next()).done)break;i=r.value}var o=i,a=o.storedMSID;if(e.has(a)){var s=e.get(a);if(!s)return void A.error("No SSRC found for: "+a+" in "+this);var c=this.localSSRCs.get(o.rtcId),u=this._extractPrimarySSRC(s),d=this._extractPrimarySSRC(c);u!==d?(null===d?A.info("Storing new local SSRC for "+o+" in "+this,s):A.error("Overwriting SSRC for "+o+" "+a+" in "+this+" with: ",s),this.localSSRCs.set(o.rtcId,s),this.eventEmitter.emit(g.a.LOCAL_TRACK_SSRC_UPDATED,o,u)):A.debug("The local SSRC("+u+") for "+o+" "+a+"is still up to date in "+this)}else o.isVideoTrack()||o.isMuted()||A.warn("No SSRCs found in the local SDP for "+o+" MSID: "+a+" in "+this)}},R.prototype.addIceCandidate=function(e){return this.trace("addIceCandidate",JSON.stringify({candidate:e.candidate,sdpMid:e.sdpMid,sdpMLineIndex:e.sdpMLineIndex,usernameFragment:e.usernameFragment},null," ")),this.peerconnection.addIceCandidate(e)},R.prototype.getStats=function(e,t){m.a.isSafari()||m.a.isFirefox()||m.a.isReactNative()?this.peerconnection.getStats().then(e).catch(t||function(){}):this.peerconnection.getStats(e)},R.prototype.generateNewStreamSSRCInfo=function(e){var t=e.rtcId,n=this._getSSRC(t);if(n&&A.error("Will overwrite local SSRCs for track ID: "+t),this.isSimulcastOn()&&(!this.options.capScreenshareBitrate||this.options.capScreenshareBitrate&&P(this))){n={ssrcs:[],groups:[]};for(var r=0;r<_.a.length;r++)n.ssrcs.push(C.a.generateSsrc());n.groups.push({ssrcs:n.ssrcs.slice(),semantics:"SIM"})}else n={ssrcs:[C.a.generateSsrc()],groups:[]};if(!this.options.disableRtx&&m.a.supportsRtx())for(var i=n.ssrcs.length,o=0;o=o.length)break;u=o[c++]}else{if((c=o.next()).done)break;u=c.value}var d=u,l=d.isMuted(),h=d.getOriginalStream(),p=h&&this.tpc.isMediaStreamInPc(h),f=l||!p;if(a.debug(this.tpc+" "+d+" muted: "+l+", is in PeerConnection: "+p+" => should fake sdp ? : "+f),f){var m=this.tpc.isSimulcastOn()?this.tpc.simulcast.ssrcCache:[this.tpc.sdpConsistency.cachedPrimarySsrc];if(m.length){r=!0,n.direction="sendrecv";var v="injected-"+m[0],g=m,y=Array.isArray(g),_=0;for(g=y?g:g["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var S;if(y){if(_>=g.length)break;S=g[_++]}else{if((_=g.next()).done)break;S=_.value}var E=S;n.removeSSRC(E),a.debug(this.tpc+" injecting video SSRC: "+E+" for "+d),n.addSSRCAttribute({id:E,attribute:"cname",value:v}),n.addSSRCAttribute({id:E,attribute:"msid",value:d.storedMSID})}if(m.length>1){var b={ssrcs:m.join(" "),semantics:"SIM"};n.findGroup(b.semantics,b.ssrcs)||(a.debug(this.tpc+" injecting SIM group for "+d,b),n.addSSRCGroup(b))}this.tpc.options.disableRtx||this.tpc.rtxModifier.modifyRtxSsrcs2(n)}else a.error("No SSRCs stored for: "+d+" in "+this.tpc)}}return r}},{key:"_transformMediaIdentifiers",value:function(e){var t=this.tpc.id,n=e.ssrcs,r=Array.isArray(n),i=0;for(n=r?n:n["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var o;if(r){if(i>=n.length)break;o=n[i++]}else{if((i=n.next()).done)break;o=i.value}var s=o;switch(s.attribute){case"cname":case"label":case"mslabel":s.value=s.value&&s.value+"-"+t;break;case"msid":if(s.value){var c=s.value.split(" ");if(2===c.length){var u=c[0],d=c[1];s.value=u+"-"+t+" "+d+"-"+t}else a.warn("Unable to munge local MSID- weird format detected: "+s.value)}}}}},{key:"maybeAddMutedLocalVideoTracksToSDP",value:function(e){if(!e)throw new Error("No local description passed in.");var t=new o.a(e.sdp);return this._addMutedLocalVideoTracksToSDP(t)?new RTCSessionDescription({type:e.type,sdp:t.toRawSDP()}):e}},{key:"transformStreamIdentifiers",value:function(e){if(!e||!e.sdp||!e.type)return e;var t=new o.a(e.sdp),n=t.selectMedia("audio");n&&this._transformMediaIdentifiers(n);var r=t.selectMedia("video");return r&&this._transformMediaIdentifiers(r),new RTCSessionDescription({type:e.type,sdp:t.toRawSDP()})}}]),e})()}).call(this,"modules/RTC/LocalSdpMunger.js")},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return c});var r=n(4),i=n(27),o=n(6),a=Object(r.getLogger)(e);function s(e,t,n){a.debug("Updating mline to associate "+n+"rtx ssrc with primary stream, "+t.id);var r=t.id,i=t.msid,o=t.cname,s=e.getRtxSSRC(r);s!==n?(s&&(a.debug(r+" was previously associated with rtx"+s+", removing all references to it"),e.removeSSRC(s),a.debug("groups before filtering for "+s),a.debug(e.dumpSSRCGroups()),e.removeGroupsWithSSRC(s)),e.addSSRCAttribute({id:n,attribute:"cname",value:o}),e.addSSRCAttribute({id:n,attribute:"msid",value:i}),e.addSSRCGroup({semantics:"FID",ssrcs:r+" "+n})):a.debug(n+" was already associated with "+r)}var c=(function(){function e(){_classCallCheck(this,e),this.correspondingRtxSsrcs=new Map}return _createClass(e,[{key:"clearSsrcCache",value:function(){this.correspondingRtxSsrcs.clear()}},{key:"setSsrcCache",value:function(e){a.debug("Setting ssrc cache to ",e),this.correspondingRtxSsrcs=e}},{key:"modifyRtxSsrcs",value:function(e){var t=new i.a(e),n=t.selectMedia("video");return n?this.modifyRtxSsrcs2(n)?t.toRawSDP():e:(a.debug("No 'video' media found in the sdp: "+e),e)}},{key:"modifyRtxSsrcs2",value:function(e){if("recvonly"===e.direction)return a.debug("RtxModifier doing nothing, video m line is recvonly"),!1;if(e.getSSRCCount()<1)return a.debug("RtxModifier doing nothing, no video ssrcs present"),!1;a.debug("Current ssrc mapping: ",this.correspondingRtxSsrcs);var t=e.getPrimaryVideoSSRCs();a.debug("Parsed primary video ssrcs ",t," making sure all have rtx streams");var n=t,r=Array.isArray(n),i=0;for(n=r?n:n["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var c;if(r){if(i>=n.length)break;c=n[i++]}else{if((i=n.next()).done)break;c=i.value}var u=c,d=e.getSSRCAttrValue(u,"msid"),l=e.getSSRCAttrValue(u,"cname"),h=this.correspondingRtxSsrcs.get(u);if(h)a.debug("Already have an associated rtx ssrc forvideo ssrc "+u+": "+h);else{a.debug("No previously associated rtx ssrc for video ssrc "+u);var p=e.getRtxSSRC(u);p?(a.debug("Rtx stream "+p+" already existed in the sdp as an rtx stream for "+u),h=p):(h=o.a.generateSsrc(),a.debug("Generated rtx ssrc "+h+" for ssrc "+u)),a.debug("Caching rtx ssrc "+h+" for video ssrc "+u),this.correspondingRtxSsrcs.set(u,h)}s(e,{id:u,cname:l,msid:d},h)}return!0}},{key:"stripRtx",value:function(e){var t=new i.a(e),n=t.selectMedia("video");if(!n)return a.debug("No 'video' media found in the sdp: "+e),e;if("recvonly"===n.direction)return a.debug("RtxModifier doing nothing, video m line is recvonly"),e;if(n.getSSRCCount()<1)return a.debug("RtxModifier doing nothing, no video ssrcs present"),e;if(!n.containsAnySSRCGroups())return a.debug("RtxModifier doing nothing, no video ssrcGroups present"),e;var r=n.findGroups("FID");n.removeGroupsBySemantics("FID");var o=r,s=Array.isArray(o),c=0;for(o=s?o:o["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var u;if(s){if(c>=o.length)break;u=o[c++]}else{if((c=o.next()).done)break;u=c.value}var d=u,l=Object(i.c)(d);n.removeSSRC(l)}return t.toRawSDP()}}]),e})()}).call(this,"modules/xmpp/RtxModifier.js")},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return a});var r=n(4),i=n(27),o=Object(r.getLogger)(e),a=(function(){function e(t){_classCallCheck(this,e),this.clearVideoSsrcCache(),this.logPrefix=t}return _createClass(e,[{key:"clearVideoSsrcCache",value:function(){this.cachedPrimarySsrc=null,this.injectRecvOnly=!1}},{key:"setPrimarySsrc",value:function(e){if("number"!=typeof e)throw new Error("Primary SSRC must be a number!");this.cachedPrimarySsrc=e}},{key:"hasPrimarySsrcCached",value:function(){return Boolean(this.cachedPrimarySsrc)}},{key:"makeVideoPrimarySsrcsConsistent",value:function(e){var t=new i.a(e),n=t.selectMedia("video");if(!n)return o.debug(this.logPrefix+" no 'video' media found in the sdp: "+e),e;if("recvonly"===n.direction)this.cachedPrimarySsrc&&this.injectRecvOnly?n.addSSRCAttribute({id:this.cachedPrimarySsrc,attribute:"cname",value:"recvonly-"+this.cachedPrimarySsrc}):o.info(this.logPrefix+" no SSRC found for the recvonly videostream!");else{var r=n.getPrimaryVideoSsrc();if(!r)return o.info(this.logPrefix+" sdp-consistency couldn't parse new primary ssrc"),e;if(this.cachedPrimarySsrc){o.info(this.logPrefix+" sdp-consistency replacing new ssrc"+r+" with cached "+this.cachedPrimarySsrc),n.replaceSSRC(r,this.cachedPrimarySsrc);var a=n.ssrcGroups,s=Array.isArray(a),c=0;for(a=s?a:a["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var u;if(s){if(c>=a.length)break;u=a[c++]}else{if((c=a.next()).done)break;u=c.value}var d=u;if("FID"===d.semantics){var l=Object(i.b)(d),h=Object(i.c)(d);l===r&&(d.ssrcs=this.cachedPrimarySsrc+" "+h)}}}else this.cachedPrimarySsrc=r,o.info(this.logPrefix+" sdp-consistency caching primary ssrc"+this.cachedPrimarySsrc);this.injectRecvOnly=!0}return t.toRawSDP()}}]),e})()}).call(this,"modules/xmpp/SdpConsistency.js")},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return a});var r=n(4),i=n(55),o=Object(r.getLogger)(e),a=(function(){function e(){_classCallCheck(this,e),this._started=!1,this._streamsToMix=[],this._streamMSSArray=[]}return _createClass(e,[{key:"addMediaStream",value:function(e){e.getAudioTracks()||o.warn("Added MediaStream doesn't contain audio tracks."),this._streamsToMix.push(e)}},{key:"start",value:function(){if(this._started)return this._mixedMSD.stream;if(this._audioContext=Object(i.a)(),!this._streamsToMix.length)return o.warn("No MediaStream's added to AudioMixer, nothing will happen."),null;this._started=!0,this._mixedMSD=this._audioContext.createMediaStreamDestination();var e=this._streamsToMix,t=Array.isArray(e),n=0;for(e=t?e:e["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var r;if(t){if(n>=e.length)break;r=e[n++]}else{if((n=e.next()).done)break;r=n.value}var a=r,s=this._audioContext.createMediaStreamSource(a);s.connect(this._mixedMSD),this._streamMSSArray.push(s)}return this._mixedMSD.stream}},{key:"reset",value:function(){this._started=!1,this._streamsToMix=[];var e=this._streamMSSArray,t=Array.isArray(e),n=0;for(e=t?e:e["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var r;if(t){if(n>=e.length)break;r=e[n++]}else{if((n=e.next()).done)break;r=n.value}r.disconnect()}this._streamMSSArray=[],this._audioContext&&(this._audioContext=void 0)}}]),e})()}).call(this,"modules/webaudio/AudioMixer.js")},function(e,t){e.exports={getTokenAuthUrl:function(e,t,n){return"string"!=typeof e?null:e.replace("{room}",t).replace("{roleUpgrade}",!0===n)}}},function(e,t,n){"use strict";n.d(t,"a",function(){return c});var r=n(7),i=n(88),o=n(25),a=n(5),s=n(37);function c(e,t,n){this.appID=e,this.token=t,this.options=n,this.xmpp=new s.c(n,t),this.addEventListener(o.CONNECTION_FAILED,function(e,t,n,i){a.a.sendAnalyticsAndLog(Object(r.B)(e,t,i))}),this.addEventListener(o.CONNECTION_DISCONNECTED,function(e){e&&a.a.sendAnalytics(r.m,{message:e}),a.a.sendLog(JSON.stringify({id:r.m,msg:e}))})}c.prototype.connect=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.xmpp.connect(e.id,e.password)},c.prototype.attach=function(e){this.xmpp.attach(e)},c.prototype.disconnect=function(){var e;return(e=this.xmpp).disconnect.apply(e,arguments)},c.prototype.getJid=function(){return this.xmpp.getJid()},c.prototype.setToken=function(e){this.token=e},c.prototype.initJitsiConference=function(e,t){return new i.a({name:e,config:t,connection:this})},c.prototype.addEventListener=function(e,t){this.xmpp.addListener(e,t)},c.prototype.removeEventListener=function(e,t){this.xmpp.removeListener(e,t)},c.prototype.getConnectionTimes=function(){return this.xmpp.connectionTimes},c.prototype.addFeature=function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return this.xmpp.caps.addFeature(e,t)},c.prototype.removeFeature=function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return this.xmpp.caps.removeFeature(e,t)}},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return oe});var r=n(3),i=n(20),o=n.n(i),a=n(4),s=n(58),c=n.n(s),u=n(19),d=n(89),l=n(2),h=n(91),p=n(17),f=n(14),m=n(15),v=n(92),g=n(110),y=n(12),_=n(111),S=n(112),E=n(113),b=n(66),C=n(21),T=n(114),A=n(1),R=n(115),k=n(116),w=n(44),I=n(117),P=n(119),D=n(120),O=n(121),N=n(122),M=n(34),L=n(123),x=n(124),F=n(125),j=n(5),U=n(126),H=n.n(U),J=n(11),B=n.n(J),G=n(35),V=n.n(G),q=n(127),K=n(128),z=n(23),W=n(37),Q=n(9),X=n(8),Y=n(13),Z=n.n(Y),ee=n(7),te=n(0);function ne(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:{};t.connection&&(this.connection=t.connection,this.xmpp=this.connection.xmpp,this.eventManager.setupXMPPListeners());var n=this.options.config;if(this._statsCurrentId=n.statisticsId?n.statisticsId:M.a.callStatsUserName,this.room=this.xmpp.createRoom(this.options.name,ne({},n,{statsId:this._statsCurrentId}),oe.resourceCreator),this._onIceConnectionInterrupted=this._onIceConnectionInterrupted.bind(this),this.room.addListener(te.CONNECTION_INTERRUPTED,this._onIceConnectionInterrupted),this._onIceConnectionRestored=this._onIceConnectionRestored.bind(this),this.room.addListener(te.CONNECTION_RESTORED,this._onIceConnectionRestored),this._onIceConnectionEstablished=this._onIceConnectionEstablished.bind(this),this.room.addListener(te.CONNECTION_ESTABLISHED,this._onIceConnectionEstablished),this._updateProperties=this._updateProperties.bind(this),this.room.addListener(te.CONFERENCE_PROPERTIES_CHANGED,this._updateProperties),this._sendConferenceJoinAnalyticsEvent=this._sendConferenceJoinAnalyticsEvent.bind(this),this.room.addListener(te.MEETING_ID_SET,this._sendConferenceJoinAnalyticsEvent),this.rttMonitor=new N.a(n.rttMonitor||{}),this.e2eping=new P.a(this,n,function(t,n){try{e.sendMessage(t,n,!0)}catch(t){ie.warn("Failed to send E2E ping request or response.",t&&t.msg)}}),this.rtc||(this.rtc=new y.a(this,t),this.eventManager.setupRTCListeners()),this.participantConnectionStatus=new w.b(this.rtc,this,{rtcMuteTimeout:n._peerConnStatusRtcMuteTimeout,outOfLastNTimeout:n._peerConnStatusOutOfLastNTimeout}),this.participantConnectionStatus.init(),this.statistics||(this.statistics=new j.a(this.xmpp,{aliasName:this._statsCurrentId,userName:n.statisticsDisplayName?n.statisticsDisplayName:this.myUserId(),callStatsConfIDNamespace:this.connection.options.hosts.domain,confID:n.confID||this.connection.options.hosts.domain+"/"+this.options.name,customScriptUrl:n.callStatsCustomScriptUrl,callStatsID:n.callStatsID,callStatsSecret:n.callStatsSecret,callStatsApplicationLogsDisabled:n.callStatsApplicationLogsDisabled,roomName:this.options.name,applicationName:n.applicationName,getWiFiStatsMethod:n.getWiFiStatsMethod}),j.a.analytics.addPermanentProperties({callstats_name:this._statsCurrentId})),this.eventManager.setupChatRoomListeners(),this.eventManager.setupStatisticsListeners(),n.enableTalkWhileMuted)if(n.createVADProcessor){ie.info("Using VAD detection for generating talk while muted events"),this._audioAnalyser||(this._audioAnalyser=new b.a(this,n.createVADProcessor));var r=new S.a;r.on(C.VAD_TALK_WHILE_MUTED,function(){return e.eventEmitter.emit(l.TALK_WHILE_MUTED)}),this._audioAnalyser.addVADDetectionService(r)}else ie.info("Using audio level based detection for generating talk while muted events"),this._talkWhileMutedDetection=new _.a(this,function(){return e.eventEmitter.emit(l.TALK_WHILE_MUTED)});if(n.enableNoisyMicDetection&&!A.a.isSafari())if(n.createVADProcessor){this._audioAnalyser||(this._audioAnalyser=new b.a(this,n.createVADProcessor));var i=new E.a;i.on(C.VAD_NOISY_DEVICE,function(){return e.eventEmitter.emit(l.NOISY_MIC)}),this._audioAnalyser.addVADDetectionService(i)}else ie.warn("No VAD Processor was provided. Noisy microphone detection service was not initialized!");n.enableNoAudioDetection&&(this._noAudioSignalDetection=new T.a(this),this._noAudioSignalDetection.on(C.NO_AUDIO_INPUT,function(){e.eventEmitter.emit(l.NO_AUDIO_INPUT)}),this._noAudioSignalDetection.on(C.AUDIO_INPUT_STATE_CHANGE,function(t){e.eventEmitter.emit(l.AUDIO_INPUT_STATE_CHANGE,t)})),"channelLastN"in n&&this.setLastN(n.channelLastN),this.jvb121Status=new D.a(this),this.p2pDominantSpeakerDetection=new g.a(this),n&&n.deploymentInfo&&n.deploymentInfo.userRegion&&this.setLocalParticipantProperty("region",n.deploymentInfo.userRegion)},oe.prototype.join=function(e){var t=this;this.room&&this.room.join(e).then(function(){return t._maybeSetSITimeout()})},oe.prototype.authenticateAndUpgradeRole=function(e){return v.a.call(this,ne({},e,{onCreateResource:oe.resourceCreator}))},oe.prototype.isJoined=function(){return this.room&&this.room.joined},oe.prototype.isP2PEnabled=function(){return Boolean(this.options.config.p2p&&this.options.config.p2p.enabled)||void 0===this.options.config.p2p},oe.prototype.isP2PTestModeEnabled=function(){return Boolean(this.options.config.testing&&this.options.config.testing.p2pTestMode)},oe.prototype.leave=function(){var e=this;if(this.participantConnectionStatus&&(this.participantConnectionStatus.dispose(),this.participantConnectionStatus=null),this.avgRtpStatsReporter&&(this.avgRtpStatsReporter.dispose(),this.avgRtpStatsReporter=null),this._audioOutputProblemDetector&&(this._audioOutputProblemDetector.dispose(),this._audioOutputProblemDetector=null),this.rttMonitor&&(this.rttMonitor.stop(),this.rttMonitor=null),this.e2eping&&(this.e2eping.stop(),this.e2eping=null),this.getLocalTracks().forEach(function(t){return e.onLocalTrackRemoved(t)}),this.rtc.closeBridgeChannel(),this.statistics&&this.statistics.dispose(),this._delayedIceFailed&&this._delayedIceFailed.cancel(),this.jvbJingleSession&&(this.jvbJingleSession.close(),this.jvbJingleSession=null),this.p2pJingleSession&&(this.p2pJingleSession.close(),this.p2pJingleSession=null),this.room){var t=this.room;return t.removeListener(te.CONNECTION_INTERRUPTED,this._onIceConnectionInterrupted),t.removeListener(te.CONNECTION_RESTORED,this._onIceConnectionRestored),t.removeListener(te.CONNECTION_ESTABLISHED,this._onIceConnectionEstablished),t.removeListener(te.CONFERENCE_PROPERTIES_CHANGED,this._updateProperties),t.removeListener(te.MEETING_ID_SET,this._sendConferenceJoinAnalyticsEvent),this.eventManager.removeXMPPListeners(),this.room=null,t.leave().then(function(){e.rtc&&e.rtc.destroy()}).catch(function(t){throw e.getParticipants().forEach(function(t){return e.onMemberLeft(t.getJid())}),t})}return Promise.reject(new Error("The conference is has been already left"))},oe.prototype.getName=function(){return this.options.name},oe.prototype.getConnection=function(){return this.connection},oe.prototype.isAuthEnabled=function(){return this.authEnabled},oe.prototype.isLoggedIn=function(){return Boolean(this.authIdentity)},oe.prototype.getAuthLogin=function(){return this.authIdentity},oe.prototype.isExternalAuthEnabled=function(){return this.room&&this.room.moderator.isExternalAuthEnabled()},oe.prototype.getExternalAuthUrl=function(e){var t=this;return new Promise(function(n,r){t.isExternalAuthEnabled()?e?t.room.moderator.getPopupLoginUrl(n,r):t.room.moderator.getLoginUrl(n,r):r()})},oe.prototype.getLocalTracks=function(e){var t=[];return this.rtc&&(t=this.rtc.getLocalTracks(e)),t},oe.prototype.getLocalAudioTrack=function(){return this.rtc?this.rtc.getLocalAudioTrack():null},oe.prototype.getLocalVideoTrack=function(){return this.rtc?this.rtc.getLocalVideoTrack():null},oe.prototype.on=function(e,t){this.eventEmitter&&this.eventEmitter.on(e,t)},oe.prototype.off=function(e,t){this.eventEmitter&&this.eventEmitter.removeListener(e,t)},oe.prototype.addEventListener=oe.prototype.on,oe.prototype.removeEventListener=oe.prototype.off,oe.prototype.addCommandListener=function(e,t){this.room&&this.room.addPresenceListener(e,t)},oe.prototype.removeCommandListener=function(e,t){this.room&&this.room.removePresenceListener(e,t)},oe.prototype.sendTextMessage=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"body";if(this.room){var n=(this.room.getFromPresence("nick")||{}).value;this.room.sendMessage(e,t,n)}},oe.prototype.sendPrivateTextMessage=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"body";this.room&&this.room.sendPrivateMessage(e,t,n)},oe.prototype.sendCommand=function(e,t){this.room?(this.room.addToPresence(e,t),this.room.sendPresence()):ie.warn("Not sending a command, room not initialized.")},oe.prototype.sendCommandOnce=function(e,t){this.sendCommand(e,t),this.removeCommand(e)},oe.prototype.removeCommand=function(e){this.room&&this.room.removeFromPresence(e)},oe.prototype.setDisplayName=function(e){this.room&&(this.room.removeFromPresence("nick"),this.room.addToPresence("nick",{attributes:{xmlns:"http://jabber.org/protocol/nick"},value:e}),this.room.sendPresence())},oe.prototype.setSubject=function(e){this.room&&this.isModerator()&&this.room.setSubject(e)},oe.prototype.getTranscriber=function(){if(void 0===this.transcriber){this.transcriber=new H.a;var e=this.getLocalTracks(Q.a),t=Array.isArray(e),n=0;for(e=t?e:e["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var r;if(t){if(n>=e.length)break;r=e[n++]}else{if((n=e.next()).done)break;r=n.value}var i=r;this.transcriber.addTrack(i)}var o=this.rtc.getRemoteTracks(Q.a),a=Array.isArray(o),s=0;for(o=a?o:o["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var c;if(a){if(s>=o.length)break;c=o[s++]}else{if((s=o.next()).done)break;c=s.value}var u=c;this.transcriber.addTrack(u)}}return this.transcriber},oe.prototype.getTranscriptionStatus=function(){return this.room.transcriptionStatus},oe.prototype.addTrack=function(e){if(e.isVideoTrack()){var t=this.rtc.getLocalVideoTrack();if(t)return e===t?Promise.resolve(e):Promise.reject(new Error("cannot add second video track to the conference"))}return this.replaceTrack(null,e)},oe.prototype._fireAudioLevelChangeEvent=function(e,t){var n=this.getActivePeerConnection();t&&n!==t||this.eventEmitter.emit(l.TRACK_AUDIO_LEVEL_CHANGED,this.myUserId(),e)},oe.prototype._fireMuteChangeEvent=function(e){var t;if(this.isMutedByFocus&&e.isAudioTrack()&&!e.isMuted()&&(this.isMutedByFocus=!1,this.room.muteParticipant(this.room.myroomjid,!1)),this.mutedByFocusActor){var n=r.Strophe.getResourceFromJid(this.mutedByFocusActor);t=this.participants[n]}this._e2eeCtx&&!e.isMuted()&&A.a.doesVideoMuteByStreamRemove()&&(this.p2pJingleSession&&this._setupSenderE2EEForTrack(this.p2pJingleSession,e),this.jvbJingleSession&&this._setupSenderE2EEForTrack(this.jvbJingleSession,e)),this.eventEmitter.emit(l.TRACK_MUTE_CHANGED,e,t)},oe.prototype.onLocalTrackRemoved=function(e){e._setConference(null),this.rtc.removeLocalTrack(e),e.removeEventListener(m.TRACK_MUTE_CHANGED,e.muteHandler),e.removeEventListener(m.TRACK_AUDIO_LEVEL_CHANGED,e.audioLevelHandler),e.isVideoTrack()&&e.videoType===Z.a.DESKTOP&&this.statistics.sendScreenSharingEvent(!1),this.eventEmitter.emit(l.TRACK_REMOVED,e)},oe.prototype.removeTrack=function(e){return this.replaceTrack(e,null)},oe.prototype.replaceTrack=function(e,t){var n=this;return e&&e.disposed?Promise.reject(new p.a(f.TRACK_IS_DISPOSED)):t&&t.disposed?Promise.reject(new p.a(f.TRACK_IS_DISPOSED)):this._doReplaceTrack(e,t).then(function(){return e&&n.onLocalTrackRemoved(e),t&&n._setupNewTrack(t),Promise.resolve()},function(e){return Promise.reject(new Error(e))})},oe.prototype._doReplaceTrack=function(e,t){var n=[];return this.jvbJingleSession?n.push(this.jvbJingleSession.replaceTrack(e,t)):ie.info("_doReplaceTrack - no JVB JingleSession"),this.p2pJingleSession?n.push(this.p2pJingleSession.replaceTrack(e,t)):ie.info("_doReplaceTrack - no P2P JingleSession"),Promise.all(n)},oe.prototype._setupNewTrack=function(e){if(e.isAudioTrack()||e.isVideoTrack()&&e.videoType!==Z.a.DESKTOP){var t=y.a.getCurrentlyAvailableMediaDevices().find(function(t){return t.kind===e.getTrack().kind+"input"&&t.label===e.getTrack().label});t&&j.a.sendActiveDeviceListEvent(y.a.getEventDataForActiveDevice(t))}e.isVideoTrack()&&(this.removeCommand("videoType"),this.sendCommand("videoType",{value:e.videoType,attributes:{xmlns:"http://jitsi.org/jitmeet/video"}})),this.rtc.addLocalTrack(e),e.isAudioTrack()?this.room.setAudioMute(e.isMuted()):this.room.setVideoMute(e.isMuted()),this._e2eeCtx&&(this.p2pJingleSession&&this._setupSenderE2EEForTrack(this.p2pJingleSession,e),this.jvbJingleSession&&this._setupSenderE2EEForTrack(this.jvbJingleSession,e)),e.muteHandler=this._fireMuteChangeEvent.bind(this,e),e.audioLevelHandler=this._fireAudioLevelChangeEvent.bind(this),e.addEventListener(m.TRACK_MUTE_CHANGED,e.muteHandler),e.addEventListener(m.TRACK_AUDIO_LEVEL_CHANGED,e.audioLevelHandler),e._setConference(this),this.eventEmitter.emit(l.TRACK_ADDED,e)},oe.prototype._addLocalTrackAsUnmute=function(e){var t=[];return this.jvbJingleSession?t.push(this.jvbJingleSession.addTrackAsUnmute(e)):ie.info("Add local MediaStream as unmute - no JVB Jingle session started yet"),this.p2pJingleSession?t.push(this.p2pJingleSession.addTrackAsUnmute(e)):ie.info("Add local MediaStream as unmute - no P2P Jingle session started yet"),Promise.all(t)},oe.prototype._removeLocalTrackAsMute=function(e){var t=[];return this.jvbJingleSession?t.push(this.jvbJingleSession.removeTrackAsMute(e)):ie.info("Remove local MediaStream - no JVB JingleSession started yet"),this.p2pJingleSession?t.push(this.p2pJingleSession.removeTrackAsMute(e)):ie.info("Remove local MediaStream - no P2P JingleSession started yet"),Promise.all(t)},oe.prototype.getRole=function(){return this.room.role},oe.prototype.isHidden=function(){return this.connection?r.Strophe.getDomainFromJid(this.connection.getJid())===this.options.config.hiddenDomain:null},oe.prototype.isModerator=function(){return this.room?this.room.isModerator():null},oe.prototype.lock=function(e){var t=this;return this.isModerator()?new Promise(function(n,r){t.room.lockRoom(e||"",function(){return n()},function(e){return r(e)},function(){return r(u.PASSWORD_NOT_SUPPORTED)})}):Promise.reject(new Error("You are not moderator."))},oe.prototype.unlock=function(){return this.lock()},oe.prototype.selectParticipant=function(e){this.selectParticipants([e])},oe.prototype.selectParticipants=function(e){if(!Array.isArray(e))throw new Error("Invalid argument; participantIds must be an array.");this.rtc.selectEndpoints(e)},oe.prototype.pinParticipant=function(e){this.rtc.pinEndpoint(e)},oe.prototype.getLastN=function(){return this.rtc.getLastN()},oe.prototype.setLastN=function(e){if(!Number.isInteger(e)&&!Number.parseInt(e,10))throw new Error("Invalid value for lastN: "+e);var t=Number(e);if(t<-1)throw new RangeError("lastN cannot be smaller than -1");if(this.rtc.setLastN(t),this.p2pJingleSession){var n=0!==t;this.p2pJingleSession.setMediaTransferActive(!0,n).catch(function(e){ie.error("Failed to adjust video transfer status ("+n+")",e)})}},oe.prototype.isInLastN=function(e){return this.rtc.isInLastN(e)},oe.prototype.getParticipants=function(){return Object.keys(this.participants).map(function(e){return this.participants[e]},this)},oe.prototype.getParticipantCount=function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],t=this.getParticipants();return e||(t=t.filter(function(e){return!e.isHidden()})),t.length+1},oe.prototype.getParticipantById=function(e){return this.participants[e]},oe.prototype.kickParticipant=function(e){var t=this.getParticipantById(e);t&&this.room.kick(t.getJid())},oe.prototype._maybeClearSITimeout=function(){this._sessionInitiateTimeout&&(this.jvbJingleSession||this.getParticipantCount()<2)&&(window.clearTimeout(this._sessionInitiateTimeout),this._sessionInitiateTimeout=null)},oe.prototype._maybeSetSITimeout=function(){var e=this;!this.jvbJingleSession&&this.getParticipantCount()>=2&&!this._sessionInitiateTimeout&&(this._sessionInitiateTimeout=window.setTimeout(function(){e._sessionInitiateTimeout=null,j.a.sendAnalytics(Object(ee.G)(ee.d,{p2p:!1,value:5e3}))},5e3))},oe.prototype.muteParticipant=function(e){var t=this.getParticipantById(e);t&&this.room.muteParticipant(t.getJid(),!0)},oe.prototype.onMemberJoined=function(e,t,n,i,o,a,s,c){var u=r.Strophe.getResourceFromJid(e);if("focus"!==u&&this.myUserId()!==u){var d=new h.a(e,this,t,i,o,a,s);d._role=n,d._botType=c,this.participants[u]=d,this.eventEmitter.emit(l.USER_JOINED,u,d),this._updateFeatures(d),this._maybeStartOrStopP2P(),this._maybeSetSITimeout()}},oe.prototype._updateFeatures=function(e){var t=this;e.getFeatures().then(function(n){e._supportsDTMF=n.has("urn:xmpp:jingle:dtmf:0"),t.updateDTMFSupport(),n.has("http://jitsi.org/protocol/jigasi")&&e.setProperty("features_jigasi",!0),n.has("https://jitsi.org/meet/e2ee")&&e.setProperty("features_e2ee",!0)}).catch(function(){return!1})},oe.prototype._onMemberBotTypeChanged=function(e,t){var n=this.getParticipants().find(function(t){return t.getJid()===e});if(n){n._botType=t;var i=r.Strophe.getResourceFromJid(e);this.eventEmitter.emit(l.BOT_TYPE_CHANGED,i,t)}n._botType||this._maybeStartOrStopP2P()},oe.prototype.onMemberLeft=function(e){var t=this,n=r.Strophe.getResourceFromJid(e);if("focus"!==n&&this.myUserId()!==n){var i=this.participants[n];delete this.participants[n],this.rtc.removeRemoteTracks(n).forEach(function(e){return t.eventEmitter.emit(l.TRACK_REMOVED,e)}),i&&this.eventEmitter.emit(l.USER_LEFT,n,i),this._maybeStartOrStopP2P(!0),this._maybeClearSITimeout()}},oe.prototype.onMemberKicked=function(e,t,n){var r=this.participants[t];if(e)return this.eventEmitter.emit(l.KICKED,r),void this.leave();var i=this.participants[n];this.eventEmitter.emit(l.PARTICIPANT_KICKED,r,i)},oe.prototype.onLocalRoleChanged=function(e){this.eventEmitter.emit(l.USER_ROLE_CHANGED,this.myUserId(),e)},oe.prototype.onUserRoleChanged=function(e,t){var n=r.Strophe.getResourceFromJid(e),i=this.getParticipantById(n);i&&(i._role=t,this.eventEmitter.emit(l.USER_ROLE_CHANGED,n,t))},oe.prototype.onDisplayNameChanged=function(e,t){var n=r.Strophe.getResourceFromJid(e),i=this.getParticipantById(n);i&&i._displayName!==t&&(i._displayName=t,this.eventEmitter.emit(l.DISPLAY_NAME_CHANGED,n,t))},oe.prototype.onRemoteTrackAdded=function(e){var t=this;if(!e.isP2P||this.isP2PActive())if(e.isP2P||!this.isP2PActive()){this._setupReceiverE2EEForTrack(e);var n=e.getParticipantId(),r=this.getParticipantById(n);if(r){r._tracks.push(e),this.transcriber&&this.transcriber.addTrack(e);var i=this.eventEmitter;e.addEventListener(m.TRACK_MUTE_CHANGED,function(){return i.emit(l.TRACK_MUTE_CHANGED,e)}),e.addEventListener(m.TRACK_AUDIO_LEVEL_CHANGED,function(e,r){t.getActivePeerConnection()===r&&i.emit(l.TRACK_AUDIO_LEVEL_CHANGED,n,e)}),i.emit(l.TRACK_ADDED,e)}else ie.error("No participant found for id: "+n)}else ie.info("Trying to add remote JVB track, when in P2P - IGNORED");else ie.info("Trying to add remote P2P track, when not in P2P - IGNORED")},oe.prototype.onCallAccepted=function(e,t){if(this.p2pJingleSession===e){ie.info("P2P setAnswer");var n=this.getLocalTracks(),r=Array.isArray(n),i=0;for(n=r?n:n["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var o;if(r){if(i>=n.length)break;o=n[i++]}else{if((i=n.next()).done)break;o=i.value}var a=o;this._setupSenderE2EEForTrack(e,a)}this.p2pJingleSession.setAnswer(t)}},oe.prototype.onTransportInfo=function(e,t){this.p2pJingleSession===e&&(ie.info("P2P addIceCandidates"),this.p2pJingleSession.addIceCandidates(t))},oe.prototype.onRemoteTrackRemoved=function(e){var t=this;this.getParticipants().forEach(function(n){for(var r=n.getTracks(),i=0;ibridge-session[xmlns="http://jitsi.org/protocol/focus"]').attr("region");this.eventEmitter.emit(l.SERVER_REGION_CHANGED,i),this._maybeClearSITimeout(),j.a.sendAnalytics(Object(ee.G)(ee.c,{p2p:!1,value:n}));try{e.initialize(this.room,this.rtc,this.options.config)}catch(e){B.a.callErrorHandler(e)}this._setBridgeChannel(t,e.peerconnection);var o=this.getLocalTracks();try{e.acceptOffer(t,function(){r.isP2PActive()&&r.jvbJingleSession?r._suspendMediaTransferForJvbConnection():r.jvbJingleSession&&r.maxFrameHeight&&r.jvbJingleSession.setSenderVideoConstraint(r.maxFrameHeight).catch(function(e){ie.error("Sender video constraints failed on jvb session - "+e)});var t=o,n=Array.isArray(t),i=0;for(t=n?t:t["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var a;if(n){if(i>=t.length)break;a=t[i++]}else{if((i=t.next()).done)break;a=i.value}var s=a;r._setupSenderE2EEForTrack(e,s)}},function(e){B.a.callErrorHandler(e),ie.error("Failed to accept incoming Jingle session",e)},o),ie.info("Starting CallStats for JVB connection..."),this.statistics.startCallStats(this.jvbJingleSession.peerconnection,"jitsi"),this.statistics.startRemoteStats(this.jvbJingleSession.peerconnection)}catch(e){B.a.callErrorHandler(e),ie.error(e)}},oe.prototype._setBridgeChannel=function(e,t){var n,r=null,i=$(e).find(">content>transport>web-socket").first();switch(1===i.length&&(r=i[0].getAttribute("url")),this.options.config.openBridgeChannel){case"datachannel":case!0:case void 0:n="datachannel";break;case"websocket":n="websocket"}"datachannel"===n?this.rtc.initializeBridgeChannel(t,null):"websocket"===n&&r&&this.rtc.initializeBridgeChannel(null,r)},oe.prototype._rejectIncomingCall=function(e,t){t&&t.errorMsg&&B.a.callErrorHandler(new Error(t.errorMsg)),e.terminate(null,function(e){ie.warn("An error occurred while trying to terminate invalid Jingle session",e)},{reason:t&&t.reason,reasonDescription:t&&t.reasonDescription,sendSessionTerminate:!0})},oe.prototype.onCallEnded=function(e,t,n){ie.info("Call ended: "+t+" - "+n+" P2P ?"+e.isP2P),e===this.jvbJingleSession?(this.wasStopped=!0,j.a.sendAnalytics(Object(ee.G)(ee.e,{p2p:!1})),this.statistics&&(this.statistics.stopRemoteStats(this.jvbJingleSession.peerconnection),ie.info("Stopping JVB CallStats"),this.statistics.stopCallStats(this.jvbJingleSession.peerconnection)),this.jvbJingleSession=null,this.rtc.onCallEnded()):e===this.p2pJingleSession?("decline"===t&&"force JVB121"===n?(ie.info("In forced JVB 121 mode..."),j.a.analytics.addPermanentProperties({forceJvb121:!0})):"connectivity-error"===t&&"ICE FAILED"===n&&j.a.analytics.addPermanentProperties({p2pFailed:!0}),this._stopP2PSession()):ie.error("Received onCallEnded for invalid session",e.sid,e.remoteJid,t,n)},oe.prototype.onSuspendDetected=function(e){e.isP2P||(this.leave(),this.eventEmitter.emit(l.SUSPEND_DETECTED))},oe.prototype.updateDTMFSupport=function(){for(var e=!1,t=this.getParticipants(),n=0;n1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],r=typeof e;if("object"===r||!n&&"string"===r)if(n)this.sendEndpointMessage(t,e);else{var i=e,o="body";if("object"===r){o="json-message",i.hasOwnProperty(W.b)||(i[W.b]="");try{i=JSON.stringify(i)}catch(e){return void ie.error("Can not send a message, stringify failed: ",e)}}t?this.sendPrivateTextMessage(t,i,o):this.sendTextMessage(i,o)}else ie.error("Can not send a message of type "+r)},oe.prototype.isConnectionInterrupted=function(){return this.isP2PActive()?this.isP2PConnectionInterrupted:this.isJvbConnectionInterrupted},oe.prototype._onIceConnectionInterrupted=function(e){e.isP2P?this.isP2PConnectionInterrupted=!0:this.isJvbConnectionInterrupted=!0,e.isP2P===this.isP2PActive()&&this.eventEmitter.emit(l.CONNECTION_INTERRUPTED)},oe.prototype._onIceConnectionFailed=function(e){if(e.isP2P)j.a.analytics.addPermanentProperties({p2pFailed:!0}),this.p2pJingleSession&&j.a.sendAnalyticsAndLog(Object(ee.I)(ee.j,{initiator:this.p2pJingleSession.isInitiator})),this._stopP2PSession("connectivity-error","ICE FAILED");else if(e&&this.jvbJingleSession===e){if(!this.options.config.enableIceRestart)return ie.info("ICE Failed and ICE restarts are disabled"),void this.eventEmitter.emit(l.CONFERENCE_FAILED,u.ICE_FAILED);this.xmpp.isPingSupported()?(this._delayedIceFailed=new k.a(this),this._delayedIceFailed.start(e)):(ie.info("PING not supported - sending ICE failed immediately"),e.sendIceFailedNotification())}},oe.prototype._onIceConnectionRestored=function(e){e.isP2P?this.isP2PConnectionInterrupted=!1:(this.isJvbConnectionInterrupted=!1,this._delayedIceFailed&&this._delayedIceFailed.cancel()),e.isP2P===this.isP2PActive()&&this.eventEmitter.emit(l.CONNECTION_RESTORED)},oe.prototype._acceptP2PIncomingCall=function(e,t){var n=this;this.isP2PConnectionInterrupted=!1,this.p2pJingleSession=e,this._sendConferenceJoinAnalyticsEvent(),this.p2pJingleSession.initialize(this.room,this.rtc,this.options.config),ie.info("Starting CallStats for P2P connection...");var i=r.Strophe.getResourceFromJid(this.p2pJingleSession.remoteJid),o=this.participants[i];o&&(i=o.getStatsID()||i),this.statistics.startCallStats(this.p2pJingleSession.peerconnection,i);var a=this.getLocalTracks();this.p2pJingleSession.acceptOffer(t,function(){ie.debug('Got RESULT for P2P "session-accept"'),n.pendingVideoConstraintsOnP2P&&n.p2pJingleSession.setSenderVideoConstraint(n.maxFrameHeight).catch(function(e){ie.error("Sender video constraints failed on p2p session - "+e)});var t=a,r=Array.isArray(t),i=0;for(t=r?t:t["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var o;if(r){if(i>=t.length)break;o=t[i++]}else{if((i=t.next()).done)break;o=i.value}var s=o;n._setupSenderE2EEForTrack(e,s)}},function(e){ie.error("Failed to accept incoming P2P Jingle session",e)},a)},oe.prototype._addRemoteJVBTracks=function(){this._addRemoteTracks("JVB",this.jvbJingleSession.peerconnection.getRemoteTracks())},oe.prototype._addRemoteP2PTracks=function(){this._addRemoteTracks("P2P",this.p2pJingleSession.peerconnection.getRemoteTracks())},oe.prototype._addRemoteTracks=function(e,t){var n=t,r=Array.isArray(n),i=0;for(n=r?n:n["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var o;if(r){if(i>=n.length)break;o=n[i++]}else{if((i=n.next()).done)break;o=i.value}var a=o;ie.info("Adding remote "+e+" track: "+a),this.rtc.eventEmitter.emit(X.REMOTE_TRACK_ADDED,a)}},oe.prototype._onIceConnectionEstablished=function(e){null!==this.p2pJingleSession&&(this.p2pEstablishmentDuration=this.p2pJingleSession.establishmentDuration),null!==this.jvbJingleSession&&(this.jvbEstablishmentDuration=this.jvbJingleSession.establishmentDuration);var t=!1,n=this.options.config.forceJVB121Ratio;if(e.isP2P?this.p2pJingleSession!==e?(ie.error("CONNECTION_ESTABLISHED - wrong P2P session instance ?!"),t=!0):!e.isInitiator&&"number"==typeof n&&Math.random()0&&void 0!==arguments[0]?arguments[0]:{},t=!c()(e,this.properties);this.properties=e,t&&(this.eventEmitter.emit(l.PROPERTIES_CHANGED,this.properties),["bridge-count","created-ms","octo-enabled"].forEach(function(t){void 0!==e[t]&&j.a.analytics.addPermanentProperties(_defineProperty({},t.replace("-","_"),e[t]))}))},oe.prototype.getProperty=function(e){return this.properties[e]},oe.prototype._maybeClearDeferredStartP2P=function(){this.deferredStartP2PTask&&(ie.info("Cleared deferred start P2P task"),clearTimeout(this.deferredStartP2PTask),this.deferredStartP2PTask=null)},oe.prototype._removeRemoteJVBTracks=function(){this._removeRemoteTracks("JVB",this.jvbJingleSession.peerconnection.getRemoteTracks())},oe.prototype._removeRemoteP2PTracks=function(){this._removeRemoteTracks("P2P",this.p2pJingleSession.peerconnection.getRemoteTracks())},oe.prototype._removeRemoteTracks=function(e,t){var n=t,r=Array.isArray(n),i=0;for(n=r?n:n["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var o;if(r){if(i>=n.length)break;o=n[i++]}else{if((i=n.next()).done)break;o=i.value}var a=o;ie.info("Removing remote "+e+" track: "+a),this.rtc.eventEmitter.emit(X.REMOTE_TRACK_REMOVED,a)}},oe.prototype._resumeMediaTransferForJvbConnection=function(){ie.info("Resuming media transfer over the JVB connection..."),this.jvbJingleSession.setMediaTransferActive(!0,!0).then(function(){ie.info("Resumed media transfer over the JVB connection!")},function(e){ie.error("Failed to resume media transfer over the JVB connection:",e)})},oe.prototype._setP2PStatus=function(e){if(this.p2p!==e){if(this.p2p=e,e){ie.info("Peer to peer connection established!"),j.a.analytics.addPermanentProperties({p2pFailed:!1,forceJvb121:!1});var t=0!==this.rtc.getLastN();this.p2pJingleSession.setMediaTransferActive(!0,t).catch(function(e){ie.error("Failed to sync up P2P video transfer status("+t+")",e)})}else ie.info("Peer to peer connection closed!");this.jvbJingleSession&&this.statistics.sendConnectionResumeOrHoldEvent(this.jvbJingleSession.peerconnection,!e),this.dtmfManager=null,this.eventEmitter.emit(l.P2P_STATUS,this,this.p2p),this.eventEmitter.emit(this.isConnectionInterrupted()?l.CONNECTION_INTERRUPTED:l.CONNECTION_RESTORED)}else ie.debug("Called _setP2PStatus with the same status: "+e)},oe.prototype._startP2PSession=function(e){if(this._maybeClearDeferredStartP2P(),this.p2pJingleSession)ie.error("P2P session already started!");else{this.isP2PConnectionInterrupted=!1,this.p2pJingleSession=this.xmpp.connection.jingle.newP2PJingleSession(this.room.myroomjid,e),ie.info("Created new P2P JingleSession",this.room.myroomjid,e),this._sendConferenceJoinAnalyticsEvent(),this.p2pJingleSession.initialize(this.room,this.rtc,this.options.config),ie.info("Starting CallStats for P2P connection...");var t=r.Strophe.getResourceFromJid(this.p2pJingleSession.remoteJid),n=this.participants[t];n&&(t=n.getStatsID()||t),this.statistics.startCallStats(this.p2pJingleSession.peerconnection,t);var i=this.getLocalTracks();this.p2pJingleSession.invite(i)}},oe.prototype._suspendMediaTransferForJvbConnection=function(){ie.info("Suspending media transfer over the JVB connection..."),this.jvbJingleSession.setMediaTransferActive(!1,!1).then(function(){ie.info("Suspended media transfer over the JVB connection !")},function(e){ie.error("Failed to suspend media transfer over the JVB connection:",e)})},oe.prototype._maybeStartOrStopP2P=function(e){if(A.a.supportsP2P()&&this.isP2PEnabled()&&!this.isP2PTestModeEnabled()){var t=this.getParticipants(),n=t.length,r=this._shouldBeInP2PMode();if(!r&&this.deferredStartP2PTask&&this._maybeClearDeferredStartP2P(),!this.p2pJingleSession&&r){var i=n&&t[0],o=this.myUserId(),a=i.getId();if(o>a)return void ie.debug("I'm the bigger peersId - the other peer should start P2P",o,a);if(o===a)return void ie.error("The same IDs ? ",o,a);var s=i.getJid();if(e){if(this.deferredStartP2PTask)return void ie.error("Deferred start P2P task's been set already!");ie.info("Will start P2P with: "+s+" after "+this.backToP2PDelay+" seconds..."),this.deferredStartP2PTask=setTimeout(this._startP2PSession.bind(this,s),1e3*this.backToP2PDelay)}else ie.info("Will start P2P with: "+s),this._startP2PSession(s)}else this.p2pJingleSession&&!r&&(ie.info("Will stop P2P with: "+this.p2pJingleSession.remoteJid),this.p2pJingleSession.isInitiator&&n>1&&j.a.sendAnalyticsAndLog(Object(ee.I)(ee.k)),this._stopP2PSession())}else ie.info("Auto P2P disabled")},oe.prototype._shouldBeInP2PMode=function(){var e=this.getParticipants(),t=e.length,n=void 0!==e.find(function(e){return"poltergeist"===e._botType}),r=1===t&&!n;return ie.debug("P2P? peerCount: "+t+", hasBotPeer: "+n+" => "+r),r},oe.prototype._stopP2PSession=function(e,t){if(this.p2pJingleSession){var n=this.isP2PActive();n&&(this.jvbJingleSession&&this._resumeMediaTransferForJvbConnection(),this._removeRemoteP2PTracks()),ie.info("Stopping remote stats for P2P connection"),this.statistics.stopRemoteStats(this.p2pJingleSession.peerconnection),ie.info("Stopping CallStats for P2P connection"),this.statistics.stopCallStats(this.p2pJingleSession.peerconnection),this.p2pJingleSession.terminate(function(){ie.info("P2P session terminate RESULT")},function(t){e&&ie.error("An error occurred while trying to terminate P2P Jingle session",t)},{reason:e||"success",reasonDescription:t||"Turing off P2P session",sendSessionTerminate:this.room&&this.getParticipantById(r.Strophe.getResourceFromJid(this.p2pJingleSession.remoteJid))}),this.p2pJingleSession=null,this._setP2PStatus(!1),n&&(this.jvbJingleSession?this._addRemoteJVBTracks():ie.info("Not adding remote JVB tracks - no session yet"))}else ie.error("No P2P session to be stopped!")},oe.prototype.isP2PActive=function(){return this.p2p},oe.prototype.getP2PConnectionState=function(){return this.isP2PActive()?this.p2pJingleSession.peerconnection.getConnectionState():null},oe.prototype.startP2PSession=function(){var e=this.getParticipants();if(1!==e.length)throw new Error("There must be exactly 1 participant to start the P2P session !");var t=e[0].getJid();this._startP2PSession(t)},oe.prototype.stopP2PSession=function(){this._stopP2PSession()},oe.prototype.getSpeakerStats=function(){return this.speakerStatsCollector.getStats()},oe.prototype.setReceiverVideoConstraint=function(e){this.rtc.setReceiverVideoConstraint(e)},oe.prototype.setSenderVideoConstraint=function(e){this.maxFrameHeight=e,this.pendingVideoConstraintsOnP2P=!0;var t=[];return this.jvbJingleSession&&t.push(this.jvbJingleSession.setSenderVideoConstraint(e)),this.p2pJingleSession&&(this.pendingVideoConstraintsOnP2P=!1,t.push(this.p2pJingleSession.setSenderVideoConstraint(e))),Promise.all(t)},oe.prototype.createVideoSIPGWSession=function(e,t){return this.room?this.videoSIPGWHandler.createVideoSIPGWSession(e,t):new Error(z.ERROR_NO_CONNECTION)},oe.prototype._sendConferenceJoinAnalyticsEvent=function(){var e=this.getMeetingUniqueId();!this._conferenceJoinAnalyticsEventSent&&e&&null!==this.getActivePeerConnection()&&(j.a.sendAnalytics(Object(ee.A)("joined",{meetingId:e,participantId:e+"."+this._statsCurrentId})),this._conferenceJoinAnalyticsEventSent=!0)},oe.prototype.isE2EESupported=function(){return Boolean(this._e2eeCtx)},oe.prototype.setE2EEKey=function(e){this._e2eeCtx?this._e2eeCtx.setKey(e):ie.warn("Cannot set E2EE key: there is no defined context, platform is likely unsupported.")},oe.prototype._setupSenderE2EEForTrack=function(e,t){if(this._e2eeCtx){var n=e.peerconnection.findSenderForTrack(t.track);n?this._e2eeCtx.handleSender(n,t.getType()):ie.warn("Could not handle E2EE for local "+t.getType()+" track: sender not found")}},oe.prototype._setupReceiverE2EEForTrack=function(e){if(this._e2eeCtx){var t=e.isP2P?this.p2pJingleSession:this.jvbJingleSession,n=t&&t.peerconnection;if(n){var r=n.findReceiverForTrack(e.track);r?this._e2eeCtx.handleReceiver(r,e.getType()):ie.warn("Could not handle E2EE for remote "+e.getType()+" track: receiver not found")}}}}).call(this,"JitsiConference.js")},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return E});var r=n(3),i=n(7),o=n(63),a=n.n(o),s=n(90),c=n.n(s),u=n(4),d=n(19),l=n(2),h=n(9),p=n(8),f=n.n(p),m=n(13),v=n.n(m),g=n(5),y=n(0),_=n.n(y),S=Object(u.getLogger)(e);function E(e){this.conference=e,this.xmppListeners={},e.on(l.TRACK_MUTE_CHANGED,function(t){if(t.isLocal()&&e.statistics){var n=t.isP2P?e.p2pJingleSession:e.jvbJingleSession,r=n&&n.peerconnection||null;e.statistics.sendMuteEvent(r,t.isMuted(),t.getType())}})}E.prototype.setupChatRoomListeners=function(){var e=this,t=this.conference,n=t.room;this.chatRoomForwarder=new c.a(n,this.conference.eventEmitter),n.addListener(_.a.ICE_RESTARTING,function(e){e.isP2P||t.rtc.closeBridgeChannel()}),n.addListener(_.a.ICE_RESTART_SUCCESS,function(e,n){!e.isP2P&&t._setBridgeChannel(n,e.peerconnection)}),n.addListener(_.a.AUDIO_MUTED_BY_FOCUS,function(e){g.a.sendAnalytics(Object(i.K)()),t.mutedByFocusActor=e,t.rtc.setAudioMute(!0).then(function(){t.isMutedByFocus=!0,t.mutedByFocusActor=null}).catch(function(e){t.mutedByFocusActor=null,S.warn("Error while audio muting due to focus request",e)})}),this.chatRoomForwarder.forward(_.a.SUBJECT_CHANGED,l.SUBJECT_CHANGED),this.chatRoomForwarder.forward(_.a.MUC_JOINED,l.CONFERENCE_JOINED),n.addListener(_.a.MUC_JOINED,function(){e.conference.isJvbConnectionInterrupted=!1,Object.keys(n.connectionTimes).forEach(function(e){var t=Object(i.C)("conference_"+e,{value:n.connectionTimes[e]});g.a.sendAnalytics(t)}),Object.keys(n.xmpp.connectionTimes).forEach(function(e){var t=Object(i.C)("xmpp_"+e,{value:n.xmpp.connectionTimes[e]});g.a.sendAnalytics(t)})}),n.addListener(_.a.RENEGOTIATION_FAILED,function(e,n){n.isP2P||t.eventEmitter.emit(l.CONFERENCE_FAILED,d.OFFER_ANSWER_FAILED,e)}),this.chatRoomForwarder.forward(_.a.ROOM_JOIN_ERROR,l.CONFERENCE_FAILED,d.CONNECTION_ERROR),this.chatRoomForwarder.forward(_.a.ROOM_CONNECT_ERROR,l.CONFERENCE_FAILED,d.CONNECTION_ERROR),this.chatRoomForwarder.forward(_.a.ROOM_CONNECT_NOT_ALLOWED_ERROR,l.CONFERENCE_FAILED,d.NOT_ALLOWED_ERROR),this.chatRoomForwarder.forward(_.a.ROOM_MAX_USERS_ERROR,l.CONFERENCE_FAILED,d.CONFERENCE_MAX_USERS),this.chatRoomForwarder.forward(_.a.PASSWORD_REQUIRED,l.CONFERENCE_FAILED,d.PASSWORD_REQUIRED),this.chatRoomForwarder.forward(_.a.AUTHENTICATION_REQUIRED,l.CONFERENCE_FAILED,d.AUTHENTICATION_REQUIRED),this.chatRoomForwarder.forward(_.a.BRIDGE_DOWN,l.CONFERENCE_FAILED,d.VIDEOBRIDGE_NOT_AVAILABLE),n.addListener(_.a.BRIDGE_DOWN,function(){return g.a.sendAnalytics(Object(i.z)())}),this.chatRoomForwarder.forward(_.a.RESERVATION_ERROR,l.CONFERENCE_FAILED,d.RESERVATION_ERROR),this.chatRoomForwarder.forward(_.a.GRACEFUL_SHUTDOWN,l.CONFERENCE_FAILED,d.GRACEFUL_SHUTDOWN),n.addListener(_.a.CONNECTION_ICE_FAILED,function(e){t._onIceConnectionFailed(e)}),this.chatRoomForwarder.forward(_.a.MUC_DESTROYED,l.CONFERENCE_FAILED,d.CONFERENCE_DESTROYED),this.chatRoomForwarder.forward(_.a.CHAT_ERROR_RECEIVED,l.CONFERENCE_ERROR,d.CHAT_ERROR),this.chatRoomForwarder.forward(_.a.FOCUS_DISCONNECTED,l.CONFERENCE_FAILED,d.FOCUS_DISCONNECTED),n.addListener(_.a.FOCUS_LEFT,function(){g.a.sendAnalytics(Object(i.E)()),t.eventEmitter.emit(l.CONFERENCE_FAILED,d.FOCUS_LEFT)}),n.addListener(_.a.SESSION_ACCEPT_TIMEOUT,function(e){g.a.sendAnalyticsAndLog(Object(i.G)(i.b,{p2p:e.isP2P}))}),n.addListener(_.a.RECORDER_STATE_CHANGED,function(e,n){if(n){var i=t.getParticipantById(r.Strophe.getResourceFromJid(n));"off"===e.getStatus()?e.setTerminator(i):"on"===e.getStatus()&&e.setInitiator(i)}t.eventEmitter.emit(l.RECORDER_STATE_CHANGED,e)}),this.chatRoomForwarder.forward(_.a.TRANSCRIPTION_STATUS_CHANGED,l.TRANSCRIPTION_STATUS_CHANGED),this.chatRoomForwarder.forward(_.a.VIDEO_SIP_GW_AVAILABILITY_CHANGED,l.VIDEO_SIP_GW_AVAILABILITY_CHANGED),this.chatRoomForwarder.forward(_.a.VIDEO_SIP_GW_SESSION_STATE_CHANGED,l.VIDEO_SIP_GW_SESSION_STATE_CHANGED),this.chatRoomForwarder.forward(_.a.PHONE_NUMBER_CHANGED,l.PHONE_NUMBER_CHANGED),n.setParticipantPropertyListener(function(e,n){var r=t.getParticipantById(n);r&&r.setProperty(e.tagName.substring("jitsi_participant_".length),e.value)}),n.addListener(_.a.KICKED,t.onMemberKicked.bind(t)),n.addListener(_.a.SUSPEND_DETECTED,t.onSuspendDetected.bind(t)),this.chatRoomForwarder.forward(_.a.MUC_LOCK_CHANGED,l.LOCK_STATE_CHANGED),n.addListener(_.a.MUC_MEMBER_JOINED,t.onMemberJoined.bind(t)),n.addListener(_.a.MUC_MEMBER_BOT_TYPE_CHANGED,t._onMemberBotTypeChanged.bind(t)),n.addListener(_.a.MUC_MEMBER_LEFT,t.onMemberLeft.bind(t)),this.chatRoomForwarder.forward(_.a.MUC_LEFT,l.CONFERENCE_LEFT),n.addListener(_.a.DISPLAY_NAME_CHANGED,t.onDisplayNameChanged.bind(t)),n.addListener(_.a.LOCAL_ROLE_CHANGED,function(e){t.onLocalRoleChanged(e),t.statistics&&t.isModerator()&&t.on(l.RECORDER_STATE_CHANGED,function(e){var t={error:e.getError(),id:"recorder_status",status:e.getStatus()};g.a.sendLog(JSON.stringify(t))})}),n.addListener(_.a.MUC_ROLE_CHANGED,t.onUserRoleChanged.bind(t)),n.addListener(a.a.IDENTITY_UPDATED,function(e,n){t.authEnabled=e,t.authIdentity=n,t.eventEmitter.emit(l.AUTH_STATUS_CHANGED,e,n)}),n.addListener(_.a.MESSAGE_RECEIVED,function(e,n,i,o,a){var s=r.Strophe.getResourceFromJid(e);t.eventEmitter.emit(l.MESSAGE_RECEIVED,s,i,a,n)}),n.addListener(_.a.PRIVATE_MESSAGE_RECEIVED,function(e,n,i,o,a){var s=r.Strophe.getResourceFromJid(e);t.eventEmitter.emit(l.PRIVATE_MESSAGE_RECEIVED,s,i,a)}),n.addListener(_.a.PRESENCE_STATUS,function(e,n){var i=r.Strophe.getResourceFromJid(e),o=t.getParticipantById(i);o&&o._status!==n&&(o._status=n,t.eventEmitter.emit(l.USER_STATUS_CHANGED,i,n))}),n.addListener(_.a.JSON_MESSAGE_RECEIVED,function(e,n){var i=r.Strophe.getResourceFromJid(e),o=t.getParticipantById(i);o?t.eventEmitter.emit(l.ENDPOINT_MESSAGE_RECEIVED,o,n):S.warn("Ignored XMPPEvents.JSON_MESSAGE_RECEIVED for not existing participant: "+e,n)}),n.addPresenceListener("startmuted",function(e,n){var r=!1;if(t.myUserId()===n&&t.isModerator())r=!0;else{var i=t.getParticipantById(n);i&&i.isModerator()&&(r=!0)}if(r){var o="true"===e.attributes.audio,a="true"===e.attributes.video,s=!1;o!==t.startMutedPolicy.audio&&(t.startMutedPolicy.audio=o,s=!0),a!==t.startMutedPolicy.video&&(t.startMutedPolicy.video=a,s=!0),s&&t.eventEmitter.emit(l.START_MUTED_POLICY_CHANGED,t.startMutedPolicy)}}),t.statistics&&(n.addListener(_.a.CONNECTION_ICE_FAILED,function(e){t.statistics.sendIceConnectionFailedEvent(e.peerconnection)}),n.addListener(_.a.ADD_ICE_CANDIDATE_FAILED,function(e,n){t.statistics.sendAddIceCandidateFailed(e,n)}))},E.prototype.setupRTCListeners=function(){var e=this.conference,t=e.rtc;t.addListener(f.a.REMOTE_TRACK_ADDED,e.onRemoteTrackAdded.bind(e)),t.addListener(f.a.REMOTE_TRACK_REMOVED,e.onRemoteTrackRemoved.bind(e)),t.addListener(f.a.DOMINANT_SPEAKER_CHANGED,function(t){e.lastDominantSpeaker!==t&&e.room&&(e.lastDominantSpeaker=t,e.eventEmitter.emit(l.DOMINANT_SPEAKER_CHANGED,t),e.statistics&&e.myUserId()===t&&e.statistics.sendDominantSpeakerEvent(e.room.roomjid))}),t.addListener(f.a.DATA_CHANNEL_OPEN,function(){var t=window.performance.now(),n="data.channel.opened";S.log("(TIME) data.channel.opened:\t",t),e.room.connectionTimes[n]=t,g.a.sendAnalytics(Object(i.C)(n,{value:t})),e.eventEmitter.emit(l.DATA_CHANNEL_OPENED)}),t.addListener(f.a.ENDPOINT_MESSAGE_RECEIVED,function(t,n){var r=e.getParticipantById(t);r?e.eventEmitter.emit(l.ENDPOINT_MESSAGE_RECEIVED,r,n):S.warn("Ignored ENDPOINT_MESSAGE_RECEIVED for not existing participant: "+t,n)}),t.addListener(f.a.LOCAL_UFRAG_CHANGED,function(e,t){e.isP2P||g.a.sendLog(JSON.stringify({id:"local_ufrag",value:t}))}),t.addListener(f.a.REMOTE_UFRAG_CHANGED,function(e,t){e.isP2P||g.a.sendLog(JSON.stringify({id:"remote_ufrag",value:t}))}),t.addListener(f.a.CREATE_ANSWER_FAILED,function(t,n){e.statistics.sendCreateAnswerFailed(t,n),n.isP2P||e.eventEmitter.emit(l.CONFERENCE_FAILED,d.OFFER_ANSWER_FAILED,t)}),t.addListener(f.a.CREATE_OFFER_FAILED,function(t,n){e.statistics.sendCreateOfferFailed(t,n),n.isP2P||e.eventEmitter.emit(l.CONFERENCE_FAILED,d.OFFER_ANSWER_FAILED,t)}),t.addListener(f.a.SET_LOCAL_DESCRIPTION_FAILED,function(t,n){e.statistics.sendSetLocalDescFailed(t,n),n.isP2P||e.eventEmitter.emit(l.CONFERENCE_FAILED,d.OFFER_ANSWER_FAILED,t)}),t.addListener(f.a.SET_REMOTE_DESCRIPTION_FAILED,function(t,n){e.statistics.sendSetRemoteDescFailed(t,n),n.isP2P||e.eventEmitter.emit(l.CONFERENCE_FAILED,d.OFFER_ANSWER_FAILED,t)}),t.addListener(f.a.LOCAL_TRACK_SSRC_UPDATED,function(t,n){t.isVideoTrack()&&t.videoType===v.a.DESKTOP&&e.statistics.sendScreenSharingEvent(!0,n)})},E.prototype.removeXMPPListeners=function(){var e=this,t=this.conference;t.xmpp.caps.removeListener(_.a.PARTCIPANT_FEATURES_CHANGED,this.xmppListeners[_.a.PARTCIPANT_FEATURES_CHANGED]),delete this.xmppListeners[_.a.PARTCIPANT_FEATURES_CHANGED],Object.keys(this.xmppListeners).forEach(function(n){t.xmpp.removeListener(n,e.xmppListeners[n])}),this.xmppListeners={}},E.prototype.setupXMPPListeners=function(){var e=this.conference,t=function(t){var n=e.getParticipantById(r.Strophe.getResourceFromJid(t));n&&e.eventEmitter.emit(l.PARTCIPANT_FEATURES_CHANGED,n)};e.xmpp.caps.addListener(_.a.PARTCIPANT_FEATURES_CHANGED,t),this.xmppListeners[_.a.PARTCIPANT_FEATURES_CHANGED]=t,this._addConferenceXMPPListener(_.a.CALL_INCOMING,e.onIncomingCall.bind(e)),this._addConferenceXMPPListener(_.a.CALL_ACCEPTED,e.onCallAccepted.bind(e)),this._addConferenceXMPPListener(_.a.TRANSPORT_INFO,e.onTransportInfo.bind(e)),this._addConferenceXMPPListener(_.a.CALL_ENDED,e.onCallEnded.bind(e)),this._addConferenceXMPPListener(_.a.START_MUTED_FROM_FOCUS,function(t,n){e.options.config.ignoreStartMuted||(e.startAudioMuted=t,e.startVideoMuted=n,e.getLocalTracks().forEach(function(t){switch(t.getType()){case h.a:e.startAudioMuted&&t.mute();break;case h.c:e.startVideoMuted&&t.mute()}}),e.eventEmitter.emit(l.STARTED_MUTED))}),this._addConferenceXMPPListener(_.a.CONFERENCE_TIMESTAMP_RECEIVED,function(t){e.eventEmitter.emit(l.CONFERENCE_CREATED_TIMESTAMP,t)})},E.prototype._addConferenceXMPPListener=function(e,t){this.xmppListeners[e]=t,this.conference.xmpp.addListener(e,t)},E.prototype.setupStatisticsListeners=function(){var e=this.conference;e.statistics&&(e.statistics.addAudioLevelListener(function(t,n,r,i){e.rtc.setAudioLevel(t,n,r,i)}),e.statistics.addBeforeDisposedListener(function(){e.eventEmitter.emit(l.BEFORE_STATISTICS_DISPOSED)}),e.options.config.startSilent||e.statistics.addByteSentStatsListener(function(t,n){e.getLocalTracks(h.a).forEach(function(e){var r=t.getLocalSSRC(e);r&&n.hasOwnProperty(r)&&e._onByteSentStatsReceived(t,n[r])})}))}}).call(this,"JitsiConferenceEventManager.js")},function(e,t){function n(e,t){if(!e||!t||"function"!=typeof e.addListener||"function"!=typeof t.emit)throw new Error("Invalid arguments passed to EventEmitterForwarder");this.src=e,this.dest=t}n.prototype.forward=function(){for(var e=arguments.length,t=new Array(e),n=0;n0&&void 0!==arguments[0]?arguments[0]:5e3;return this._getFeaturesPromise?this._getFeaturesPromise:(this._getFeaturesPromise=this._conference.xmpp.caps.getFeatures(this._jid,t).catch(function(n){return n===s.a?e._conference.xmpp.caps.getFeatures(e._jid,t):(u.warn("Failed to discover features of "+e._jid,n),Promise.reject(n))}),this._getFeaturesPromise.then(function(t){return e._getFeaturesPromise=void 0,t},function(t){throw e._getFeaturesPromise=void 0,t}))}},{key:"getBotType",value:function(){return this._botType}}]),e})()}).call(this,"JitsiParticipant.js")},function(e,t,n){"use strict";n.d(t,"a",function(){return o});var r=n(25),i=n(37);function o(e){var t,n=this,o=e.id,a=e.password,s=e.onCreateResource,c=e.onLoginSuccessful,u=e.roomPassword,d=!1,l=new i.c(this.connection.options),h=new Promise(function(e,i){t=i,l.addListener(r.CONNECTION_DISCONNECTED,function(){l=void 0}),l.addListener(r.CONNECTION_ESTABLISHED,function(){d||(c&&c(),l.createRoom(n.options.name,n.options.config,s).moderator.authenticate().then(function(){l&&l.disconnect(),d||(n.join(u),e())}).catch(function(e){var t=e.error,n=e.message;l.disconnect(),i({authenticationError:t,message:n})}))}),l.addListener(r.CONNECTION_FAILED,function(e,t,n){i({connectionError:e,credentials:n,message:t}),l=void 0}),d||l.connect(o,a)});return h.cancel=function(){d=!0,t({}),l&&l.disconnect()},h}},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return d});var r=n(4),i=n(3),o=n(94),a=n(36),s=n(0),c=n.n(s),u=Object(r.getLogger)(e),d=(function(e){function t(e){var n;return _classCallCheck(this,t),(n=_possibleConstructorReturn(this,_getPrototypeOf(t).call(this))).xmpp=e,n.rooms={},n}return _inherits(t,e),_createClass(t,[{key:"init",value:function(e){_get(_getPrototypeOf(t.prototype),"init",this).call(this,e),this.connection.addHandler(this.onPresence.bind(this),null,"presence",null,null,null,null),this.connection.addHandler(this.onPresenceUnavailable.bind(this),null,"presence","unavailable",null),this.connection.addHandler(this.onPresenceError.bind(this),null,"presence","error",null),this.connection.addHandler(this.onMessage.bind(this),null,"message",null,null),this.connection.addHandler(this.onMute.bind(this),"http://jitsi.org/jitmeet/audio","iq","set",null,null)}},{key:"createRoom",value:function(e,t,n){var r=i.Strophe.getBareJidFromJid(e);if(this.rooms[r]){var a="You are already in the room!";throw u.error(a),new Error(a)}return this.rooms[r]=new o.a(this.connection,e,t,this.xmpp,n),this.eventEmitter.emit(c.a.EMUC_ROOM_ADDED,this.rooms[r]),this.rooms[r]}},{key:"doLeave",value:function(e){this.eventEmitter.emit(c.a.EMUC_ROOM_REMOVED,this.rooms[e]),delete this.rooms[e]}},{key:"onPresence",value:function(e){var t=e.getAttribute("from");if(e.getAttribute("type"))return!0;var n=this.rooms[i.Strophe.getBareJidFromJid(t)];return!n||($(e).find('>x[xmlns="http://jabber.org/protocol/muc#user"]>status[code="201"]').length&&n.createNonAnonymousRoom(),n.onPresence(e),!0)}},{key:"onPresenceUnavailable",value:function(e){var t=e.getAttribute("from"),n=this.rooms[i.Strophe.getBareJidFromJid(t)];return!n||(n.onPresenceUnavailable(e,t),!0)}},{key:"onPresenceError",value:function(e){var t=e.getAttribute("from"),n=this.rooms[i.Strophe.getBareJidFromJid(t)];return!n||(n.onPresenceError(e,t),!0)}},{key:"onMessage",value:function(e){var t=e.getAttribute("from"),n=this.rooms[i.Strophe.getBareJidFromJid(t)];return!n||(n.onMessage(e,t),!0)}},{key:"onMute",value:function(e){var t=e.getAttribute("from"),n=this.rooms[i.Strophe.getBareJidFromJid(t)];return!n||(n.onMute(e),!0)}}]),t})(a.a)}).call(this,"modules/xmpp/strophe.emuc.js")},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return g});var r=n(4),i=n(3),o=n(11),a=n.n(o),s=n(60),c=n(24),u=n(9),d=n(0),l=n.n(d),h=n(95),p=n(40),f=Object(r.getLogger)(e),m={packet2JSON:function(e,t){for(var n=Array.from(e.children),r=0;r0&&void 0!==arguments[0]?arguments[0]:{};this.presMap.to=this.myroomjid,this.presMap.xns="http://jabber.org/protocol/muc",this.presMap.nodes=[],e.statsId&&this.presMap.nodes.push({tagName:"stats-id",value:e.statsId}),this.addVideoInfoToPresence(!1),e.deploymentInfo&&e.deploymentInfo.userRegion&&this.presMap.nodes.push({tagName:"region",attributes:{id:e.deploymentInfo.userRegion,xmlns:"http://jitsi.org/jitsi-meet"}})}},{key:"join",value:function(e){var t=this;return this.password=e,new Promise(function(e){t.options.disableFocus&&f.info("Conference focus disabled"),(t.options.disableFocus?Promise.resolve():t.moderator.allocateConferenceFocus()).then(function(){t.sendPresence(!0),t._removeConnListeners.push(t.connection.addEventListener(p.a.Events.CONN_STATUS_CHANGED,t.onConnStatusChanged.bind(t))),e()})})}},{key:"sendPresence",value:function(e){var t=this.presMap.to;if(this.connection&&this.connection.connected&&t&&(this.joined||e)){var n=Object(i.$pres)({to:t});e&&(n.c("x",{xmlns:this.presMap.xns}),this.password&&n.c("password").t(this.password).up(),n.up()),m.json2packet(this.presMap.nodes,n),this.connection.send(n),e&&this.connection.flush()}}},{key:"doLeave",value:function(){f.log("do leave",this.myroomjid);var e=Object(i.$pres)({to:this.myroomjid,type:"unavailable"});this.presMap.length=0,!this.connection.isUsingWebSocket&&this.connection.flush(),this.connection.send(e),this.connection.flush()}},{key:"discoRoomInfo",value:function(){var e=this,t=Object(i.$iq)({type:"get",to:this.roomjid}).c("query",{xmlns:i.Strophe.NS.DISCO_INFO});this.connection.sendIQ(t,function(t){var n=1===$(t).find('>query>feature[var="muc_passwordprotected"]').length;n!==e.locked&&(e.eventEmitter.emit(l.a.MUC_LOCK_CHANGED,n),e.locked=n);var r=$(t).find('>query>x[type="result"]>field[var="muc#roominfo_meetingId"]>value');r.length?e.setMeetingId(r.text()):f.trace("No meeting ID from backend")},function(e){a.a.callErrorHandler(e),f.error("Error getting room info: ",e)})}},{key:"setMeetingId",value:function(e){this.meetingId!==e&&(this.meetingId&&f.warn("Meeting Id changed from:"+this.meetingId+" to:"+e),this.meetingId=e,this.eventEmitter.emit(l.a.MEETING_ID_SET,e))}},{key:"createNonAnonymousRoom",value:function(){var e=Object(i.$iq)({type:"get",to:this.roomjid}).c("query",{xmlns:"http://jabber.org/protocol/muc#owner"}).c("x",{xmlns:"jabber:x:data",type:"submit"}),t=this;this.connection.sendIQ(e,function(e){if(!$(e).find('>query>x[xmlns="jabber:x:data"]>field[var="muc#roomconfig_whois"]').length){var n="non-anonymous rooms not supported";return a.a.callErrorHandler(new Error(n)),void f.error(n)}var r=Object(i.$iq)({to:t.roomjid,type:"set"}).c("query",{xmlns:"http://jabber.org/protocol/muc#owner"});r.c("x",{xmlns:"jabber:x:data",type:"submit"}),r.c("field",{var:"FORM_TYPE"}).c("value").t("http://jabber.org/protocol/muc#roomconfig").up().up(),r.c("field",{var:"muc#roomconfig_whois"}).c("value").t("anyone").up().up(),t.connection.sendIQ(r)},function(e){a.a.callErrorHandler(e),f.error("Error getting room configuration form: ",e)})}},{key:"onConnStatusChanged",value:function(e){e===p.a.Status.CONNECTED&&this.sendPresence()}},{key:"onPresence",value:function(e){var t=e.getAttribute("from"),n={},r=e.getElementsByTagName("status")[0];r&&(n.status=r.textContent||"");var o=!1,a=!1,s=e.getElementsByTagNameNS("http://jabber.org/protocol/muc#user","x")[0],c=s&&s.getElementsByTagName("item")[0];n.affiliation=c&&c.getAttribute("affiliation"),n.role=c&&c.getAttribute("role");var u=c&&c.getAttribute("jid");n.jid=u,n.isFocus=u&&0===u.indexOf(this.moderator.getFocusUserJid()+"/"),n.isHiddenDomain=u&&u.indexOf("@")>0&&this.options.hiddenDomain===u.substring(u.indexOf("@")+1,u.indexOf("/")),this.eventEmitter.emit(l.a.PRESENCE_RECEIVED,{fromHiddenDomain:n.isHiddenDomain,presence:e});var d=e.querySelector("x");d&&d.remove();var h=[];m.packet2JSON(e,h),this.lastPresences[t]=h;for(var p=function(e){var t={},n=e.children.find(function(e){return"user"===e.tagName});if(n){t.user={};for(var r=function(e){var r=n.children.find(function(t){return t.tagName===e});r&&(t.user[e]=r.value)},i=["id","name","avatar"],o=0;oignore[xmlns="http://jitsi.org/jitmeet/"]').length)return!0;if($(e).find('>x[xmlns="http://jabber.org/protocol/muc#user"]>destroy').length){var r,o=$(e).find('>x[xmlns="http://jabber.org/protocol/muc#user"]>destroy>reason');return o.length&&(r=o.text()),this.eventEmitter.emit(l.a.MUC_DESTROYED,r),this.connection.emuc.doLeave(this.roomjid),!0}var a=$(e).find('>x[xmlns="http://jabber.org/protocol/muc#user"]>status[code="110"]').length,s=$(e).find('>x[xmlns="http://jabber.org/protocol/muc#user"]>status[code="307"]').length,c=Object.keys(this.members);if(s){var u,d=$(e).find('>x[xmlns="http://jabber.org/protocol/muc#user"]>item>actor');d.length&&(u=d.attr("nick")),c.find(function(e){return i.Strophe.getResourceFromJid(e)===u})&&this.eventEmitter.emit(l.a.KICKED,a,u,i.Strophe.getResourceFromJid(t))}a?c.length>0&&(c.forEach(function(e){var t=n.members[e];delete n.members[e],n.onParticipantLeft(e,t.isFocus)}),this.connection.emuc.doLeave(this.roomjid),s||this.eventEmitter.emit(l.a.MUC_LEFT)):(delete this.members[t],this.onParticipantLeft(t,!1))}},{key:"onMessage",value:function(e,t){var n=$(e).find('>nick[xmlns="http://jabber.org/protocol/nick"]').text()||i.Strophe.getResourceFromJid(t),r=e.getAttribute("type");if("error"===r){var o=$(e).find(">error>text").text();return this.eventEmitter.emit(l.a.CHAT_ERROR_RECEIVED,o),!0}var a=$(e).find(">body").text(),s=$(e).find(">subject");if(s.length){var c=s.text();(c||""===c)&&(this.eventEmitter.emit(l.a.SUBJECT_CHANGED,c),f.log("Subject is changed to "+c))}var u=$(e).find(">delay").attr("stamp");if(!u&&(u=$(e).find('>[xmlns="jabber:x:delay"]').attr("stamp"))){var d=u.match(/(\d{4})(\d{2})(\d{2}T\d{2}:\d{2}:\d{2})/);u=d[1]+"-"+d[2]+"-"+d[3]+"Z"}t===this.roomjid&&$(e).find('>x[xmlns="http://jabber.org/protocol/muc#user"]>status[code="104"]').length&&this.discoRoomInfo();var h=$(e).find(">json-message").text(),p=this.xmpp.tryParseJSONAndVerify(h);p&&void 0===u?this.eventEmitter.emit(l.a.JSON_MESSAGE_RECEIVED,t,p):a&&("chat"===r?this.eventEmitter.emit(l.a.PRIVATE_MESSAGE_RECEIVED,t,n,a,this.myroomjid,u):"groupchat"===r&&this.eventEmitter.emit(l.a.MESSAGE_RECEIVED,t,n,a,this.myroomjid,u))}},{key:"onPresenceError",value:function(e,t){$(e).find('>error[type="auth"]>not-authorized[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]').length?(f.log("on password required",t),this.eventEmitter.emit(l.a.PASSWORD_REQUIRED)):$(e).find('>error[type="cancel"]>not-allowed[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]').length?i.Strophe.getDomainFromJid(e.getAttribute("to"))===this.xmpp.options.hosts.anonymousdomain?this.eventEmitter.emit(l.a.ROOM_JOIN_ERROR):(f.warn("onPresError ",e),this.eventEmitter.emit(l.a.ROOM_CONNECT_NOT_ALLOWED_ERROR)):$(e).find(">error>service-unavailable").length?(f.warn("Maximum users limit for the room has been reached",e),this.eventEmitter.emit(l.a.ROOM_MAX_USERS_ERROR)):(f.warn("onPresError ",e),this.eventEmitter.emit(l.a.ROOM_CONNECT_ERROR))}},{key:"kick",value:function(e){var t=Object(i.$iq)({to:this.roomjid,type:"set"}).c("query",{xmlns:"http://jabber.org/protocol/muc#admin"}).c("item",{nick:i.Strophe.getResourceFromJid(e),role:"none"}).c("reason").t("You have been kicked.").up().up().up();this.connection.sendIQ(t,function(t){return f.log("Kick participant with jid: ",e,t)},function(e){return f.log("Kick participant error: ",e)})}},{key:"lockRoom",value:function(e,t,n,r){var o=this;this.connection.sendIQ(Object(i.$iq)({to:this.roomjid,type:"get"}).c("query",{xmlns:"http://jabber.org/protocol/muc#owner"}),function(a){if($(a).find('>query>x[xmlns="jabber:x:data"]>field[var="muc#roomconfig_roomsecret"]').length){var s=Object(i.$iq)({to:o.roomjid,type:"set"}).c("query",{xmlns:"http://jabber.org/protocol/muc#owner"});s.c("x",{xmlns:"jabber:x:data",type:"submit"}),s.c("field",{var:"FORM_TYPE"}).c("value").t("http://jabber.org/protocol/muc#roomconfig").up().up(),s.c("field",{var:"muc#roomconfig_roomsecret"}).c("value").t(e).up().up(),s.c("field",{var:"muc#roomconfig_passwordprotectedroom"}).c("value").t(null===e||0===e.length?"0":"1").up().up(),s.c("field",{var:"muc#roomconfig_whois"}).c("value").t("anyone").up().up(),o.connection.sendIQ(s,t,n)}else r()},n)}},{key:"addToPresence",value:function(e,t){t.tagName=e,this.removeFromPresence(e),this.presMap.nodes.push(t)}},{key:"getFromPresence",value:function(e){return this.presMap.nodes.find(function(t){return e===t.tagName})}},{key:"removeFromPresence",value:function(e){var t=this.presMap.nodes.filter(function(t){return e!==t.tagName});this.presMap.nodes=t}},{key:"addPresenceListener",value:function(e,t){if("function"!=typeof t)throw new Error('"handler" is not a function');var n=this.presHandlers[e];n||(this.presHandlers[e]=n=[]),-1===n.indexOf(t)?n.push(t):f.warn("Trying to add the same handler more than once for: "+e)}},{key:"removePresenceListener",value:function(e,t){var n=this.presHandlers[e],r=n?n.indexOf(t):-1;-1!==r?n.splice(r,1):f.warn("Handler for: "+e+" was not registered")}},{key:"isFocus",value:function(e){var t=this.members[e];return t?t.isFocus:null}},{key:"isModerator",value:function(){return"moderator"===this.role}},{key:"getMemberRole",value:function(e){return this.members[e]?this.members[e].role:null}},{key:"setVideoMute",value:function(e,t){this.sendVideoInfoPresence(e),t&&t(e)}},{key:"setAudioMute",value:function(e,t){return this.sendAudioInfoPresence(e,t)}},{key:"addAudioInfoToPresence",value:function(e){this.removeFromPresence("audiomuted"),this.addToPresence("audiomuted",{attributes:{xmlns:"http://jitsi.org/jitmeet/audio"},value:e.toString()})}},{key:"sendAudioInfoPresence",value:function(e,t){this.addAudioInfoToPresence(e),this.sendPresence(),t&&t()}},{key:"addVideoInfoToPresence",value:function(e){this.removeFromPresence("videomuted"),this.addToPresence("videomuted",{attributes:{xmlns:"http://jitsi.org/jitmeet/video"},value:e.toString()})}},{key:"sendVideoInfoPresence",value:function(e){this.addVideoInfoToPresence(e),this.sendPresence()}},{key:"getMediaPresenceInfo",value:function(e,t){var n=this.lastPresences[this.roomjid+"/"+e];if(!n)return null;var r={muted:!1,videoType:void 0},i=null;if(t===u.a)i=v(n,"audiomuted");else{if(t!==u.c)return f.error("Unsupported media type: "+t),null;i=v(n,"videomuted");var o=v(n,"videoType");o.length>0&&(r.videoType=o[0].value)}return r.muted=i.length>0&&"true"===i[0].value,r}},{key:"isSIPCallingSupported",value:function(){return!!this.moderator&&this.moderator.isSipGatewayEnabled()}},{key:"dial",value:function(e){return this.connection.rayo.dial(e,"fromnumber",i.Strophe.getBareJidFromJid(this.myroomjid),this.password,this.focusMucJid)}},{key:"hangup",value:function(){return this.connection.rayo.hangup()}},{key:"getPhoneNumber",value:function(){return this.phoneNumber}},{key:"getPhonePin",value:function(){return this.phonePin}},{key:"getMeetingId",value:function(){return this.meetingId}},{key:"muteParticipant",value:function(e,t){f.info("set mute",t);var n=Object(i.$iq)({to:this.focusMucJid,type:"set"}).c("mute",{xmlns:"http://jitsi.org/jitmeet/audio",jid:e}).t(t.toString()).up();this.connection.sendIQ(n,function(e){return f.log("set mute",e)},function(e){return f.log("set mute error",e)})}},{key:"onMute",value:function(e){if(e.getAttribute("from")===this.focusMucJid){var t=$(e).find("mute");t.length&&"true"===t.text()?this.eventEmitter.emit(l.a.AUDIO_MUTED_BY_FOCUS,t.attr("actor")):f.warn("Ignoring a mute request which does not explicitly specify a positive mute command.")}else f.warn("Ignored mute from non focus peer")}},{key:"leave",value:function(){var e=this;return new Promise(function(t,n){var r=setTimeout(function(){return o(!0)},5e3),i=e.eventEmitter;function o(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];i.removeListener(l.a.MUC_LEFT,o),clearTimeout(r),e?n(new Error("The timeout for the confirmation about leaving the room expired.")):t()}e._removeConnListeners.forEach(function(e){return e()}),e._removeConnListeners=[],i.on(l.a.MUC_LEFT,o),e.doLeave()})}}]),t})(c.a)}).call(this,"modules/xmpp/ChatRoom.js")},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return d});var r=n(3),i=n(34),o=n(4).getLogger(e),a=n(0),s=n(63),c=n(11);function u(e){var t=1;return function(n){if(!n){var r=Math.pow(2,t-1);return t+=1,r*e}t=1}}function d(e,t,n,r){function a(e){if(e.data&&e.data.sessionId){if(e.origin!==window.location.origin)return void o.warn("Ignoring sessionId from different origin: "+e.origin);i.a.sessionId=e.data.sessionId}}this.roomName=e,this.xmppService=t,this.getNextTimeout=u(1e3),this.getNextErrorTimeout=u(1e3),this.externalAuthEnabled=!1,this.options=r,this.sipGatewayEnabled=this.options.connection.hosts&&void 0!==this.options.connection.hosts.call_control,this.eventEmitter=n,this.connection=this.xmppService.connection,window.addEventListener?window.addEventListener("message",a,!1):window.attachEvent("onmessage",a)}d.prototype.isExternalAuthEnabled=function(){return this.externalAuthEnabled},d.prototype.isSipGatewayEnabled=function(){return this.sipGatewayEnabled},d.prototype.onMucMemberLeft=function(e){o.info("Someone left is it focus ? "+e),"focus"===r.Strophe.getResourceFromJid(e)&&(o.info("Focus has left the room - leaving conference"),this.eventEmitter.emit(a.FOCUS_LEFT))},d.prototype.setFocusUserJid=function(e){this.focusUserJid||(this.focusUserJid=e,o.info("Focus jid set to: "+this.focusUserJid))},d.prototype.getFocusUserJid=function(){return this.focusUserJid},d.prototype.getFocusComponent=function(){var e=this.options.connection.hosts.focus;return e||(e="focus."+this.options.connection.hosts.domain),e},d.prototype.createConferenceIq=function(){var e,t=Object(r.$iq)({to:this.getFocusComponent(),type:"set"}),n=i.a.sessionId,a=i.a.machineId,s=this.options.conference;switch(o.info("Session ID: "+n+" machine UID: "+a),t.c("conference",{xmlns:"http://jitsi.org/protocol/focus",room:this.roomName,"machine-uid":a}),n&&t.attrs({"session-id":n}),void 0!==this.options.connection.enforcedBridge&&t.c("property",{name:"enforcedBridge",value:this.options.connection.enforcedBridge}).up(),void 0!==this.options.connection.hosts&&void 0!==this.options.connection.hosts.call_control&&t.c("property",{name:"call_control",value:this.options.connection.hosts.call_control}).up(),void 0!==s.channelLastN&&t.c("property",{name:"channelLastN",value:s.channelLastN}).up(),t.c("property",{name:"disableRtx",value:Boolean(s.disableRtx)}).up(),void 0!==s.enableTcc&&t.c("property",{name:"enableTcc",value:Boolean(s.enableTcc)}).up(),void 0!==s.enableRemb&&t.c("property",{name:"enableRemb",value:Boolean(s.enableRemb)}).up(),void 0!==s.minParticipants&&t.c("property",{name:"minParticipants",value:s.minParticipants}).up(),t.c("property",{name:"enableLipSync",value:!0===this.options.connection.enableLipSync}).up(),void 0!==s.audioPacketDelay&&t.c("property",{name:"audioPacketDelay",value:s.audioPacketDelay}).up(),s.startBitrate&&t.c("property",{name:"startBitrate",value:s.startBitrate}).up(),s.minBitrate&&t.c("property",{name:"minBitrate",value:s.minBitrate}).up(),s.testing&&s.testing.octo&&"number"==typeof s.testing.octo.probability&&Math.random()conference>property[name='authentication'][value='true']").length>0;o.info("Authentication enabled: "+t),this.externalAuthEnabled=$(e).find(">conference>property[name='externalAuth'][value='true']").length>0,o.info("External authentication enabled: "+this.externalAuthEnabled),this.externalAuthEnabled||this.parseSessionId(e);var n=$(e).find(">conference").attr("identity");this.eventEmitter.emit(s.IDENTITY_UPDATED,t,n),$(e).find(">conference>property[name='sipGatewayEnabled'][value='true']").length&&(this.sipGatewayEnabled=!0),o.info("Sip gateway enabled: "+this.sipGatewayEnabled)},d.prototype.allocateConferenceFocus=function(){var e=this;return new Promise(function(t){e.setFocusUserJid(e.options.connection.focusUserJid),e.connection.sendIQ(e.createConferenceIq(),function(n){return e._allocateConferenceFocusSuccess(n,t)},function(n){return e._allocateConferenceFocusError(n,t)}),e.connection.flush()})},d.prototype._allocateConferenceFocusError=function(e,t){var n=this,s=$(e).find(">error>session-invalid").length||$(e).find(">error>not-acceptable").length;if(s&&(o.info("Session expired! - removing"),i.a.sessionId=void 0),$(e).find(">error>graceful-shutdown").length)this.eventEmitter.emit(a.GRACEFUL_SHUTDOWN);else{var u=$(e).find(">error>reservation-error");if(u.length){var d,l=u.attr("error-code"),h=$(e).find(">error>text");return h&&(d=h.text()),void this.eventEmitter.emit(a.RESERVATION_ERROR,l,d)}if($(e).find(">error>not-authorized").length)return o.warn("Unauthorized to start the conference",e),r.Strophe.getDomainFromJid(e.getAttribute("to"))!==this.options.connection.hosts.anonymousdomain&&(this.externalAuthEnabled=!0),void this.eventEmitter.emit(a.AUTHENTICATION_REQUIRED);var p=this.getNextErrorTimeout(),f="Focus error, retry after "+p;c.callErrorHandler(new Error(f)),o.error(f,e);var m=this.getFocusComponent(),v=p/1e3;s||this.eventEmitter.emit(a.FOCUS_DISCONNECTED,m,v),this.getNextTimeout(!0),window.setTimeout(function(){return n.allocateConferenceFocus().then(t)},p)}},d.prototype._allocateConferenceFocusSuccess=function(e,t){var n=this;if(this.parseConfigOptions(e),this.getNextErrorTimeout(!0),"true"===$(e).find("conference").attr("ready"))this.getNextTimeout(!0),t();else{var r=this.getNextTimeout();o.info("Waiting for the focus... "+r),window.setTimeout(function(){return n.allocateConferenceFocus().then(t)},r)}},d.prototype.authenticate=function(){var e=this;return new Promise(function(t,n){e.connection.sendIQ(e.createConferenceIq(),function(n){e.parseSessionId(n),t()},function(e){return n({error:$(e).find("iq>error :first").prop("tagName"),message:$(e).find("iq>error>text").text()})})})},d.prototype.getLoginUrl=function(e,t){this._getLoginUrl(!1,e,t)},d.prototype._getLoginUrl=function(e,t,n){var a=Object(r.$iq)({to:this.getFocusComponent(),type:"get"}),s={xmlns:"http://jitsi.org/protocol/focus",room:this.roomName,"machine-uid":i.a.machineId},u="auth url";function d(e,t){c.callErrorHandler(new Error(e)),o.error(e,t),n(t)}e&&(s.popup=!0,u="POPUP "+u),a.c("login-url",s),this.connection.sendIQ(a,function(e){var n=$(e).find("login-url").attr("url");(n=decodeURIComponent(n))?(o.info("Got "+u+": "+n),t(n)):d("Failed to get "+u+" from the focus",e)},d.bind(void 0,"Get "+u+" error"))},d.prototype.getPopupLoginUrl=function(e,t){this._getLoginUrl(!0,e,t)},d.prototype.logout=function(e){var t=Object(r.$iq)({to:this.getFocusComponent(),type:"set"}),n=i.a.sessionId;n?(t.c("logout",{xmlns:"http://jitsi.org/protocol/focus","session-id":n}),this.connection.sendIQ(t,function(t){var n=$(t).find("logout").attr("logout-url");n&&(n=decodeURIComponent(n)),o.info("Log out OK, url: "+n,t),i.a.sessionId=void 0,e(n)},function(e){c.callErrorHandler(new Error("Logout error")),o.error("Logout error",e)})):e()}}).call(this,"modules/xmpp/moderator.js")},function(e,t,n){var r=n(35),i=["Aaliyah","Aaron","Abagail","Abbey","Abbie","Abbigail","Abby","Abdiel","Abdul","Abdullah","Abe","Abel","Abelardo","Abigail","Abigale","Abigayle","Abner","Abraham","Ada","Adah","Adalberto","Adaline","Adam","Adan","Addie","Addison","Adela","Adelbert","Adele","Adelia","Adeline","Adell","Adella","Adelle","Aditya","Adolf","Adolfo","Adolph","Adolphus","Adonis","Adrain","Adrian","Adriana","Adrianna","Adriel","Adrien","Adrienne","Afton","Aglae","Agnes","Agustin","Agustina","Ahmad","Ahmed","Aida","Aidan","Aiden","Aileen","Aisha","Aiyana","Akeem","Al","Alaina","Alan","Alana","Alanis","Alanna","Alayna","Alba","Albert","Alberta","Albertha","Alberto","Albin","Albina","Alda","Alden","Alec","Aleen","Alejandra","Alejandrin","Alek","Alena","Alene","Alessandra","Alessandro","Alessia","Aletha","Alex","Alexa","Alexander","Alexandra","Alexandre","Alexandrea","Alexandria","Alexandrine","Alexandro","Alexane","Alexanne","Alexie","Alexis","Alexys","Alexzander","Alf","Alfonso","Alfonzo","Alford","Alfred","Alfreda","Alfredo","Ali","Alia","Alice","Alicia","Alisa","Alisha","Alison","Alivia","Aliya","Aliyah","Aliza","Alize","Allan","Allen","Allene","Allie","Allison","Ally","Alphonso","Alta","Althea","Alva","Alvah","Alvena","Alvera","Alverta","Alvina","Alvis","Alyce","Alycia","Alysa","Alysha","Alyson","Alysson","Amalia","Amanda","Amani","Amara","Amari","Amaya","Amber","Ambrose","Amelia","Amelie","Amely","America","Americo","Amie","Amina","Amir","Amira","Amiya","Amos","Amparo","Amy","Amya","Ana","Anabel","Anabelle","Anahi","Anais","Anastacio","Anastasia","Anderson","Andre","Andreane","Andreanne","Andres","Andrew","Andy","Angel","Angela","Angelica","Angelina","Angeline","Angelita","Angelo","Angie","Angus","Anibal","Anika","Anissa","Anita","Aniya","Aniyah","Anjali","Anna","Annabel","Annabell","Annabelle","Annalise","Annamae","Annamarie","Anne","Annetta","Annette","Annie","Ansel","Ansley","Anthony","Antoinette","Antone","Antonetta","Antonette","Antonia","Antonietta","Antonina","Antonio","Antwan","Antwon","Anya","April","Ara","Araceli","Aracely","Arch","Archibald","Ardella","Arden","Ardith","Arely","Ari","Ariane","Arianna","Aric","Ariel","Arielle","Arjun","Arlene","Arlie","Arlo","Armand","Armando","Armani","Arnaldo","Arne","Arno","Arnold","Arnoldo","Arnulfo","Aron","Art","Arthur","Arturo","Arvel","Arvid","Arvilla","Aryanna","Asa","Asha","Ashlee","Ashleigh","Ashley","Ashly","Ashlynn","Ashton","Ashtyn","Asia","Assunta","Astrid","Athena","Aubree","Aubrey","Audie","Audra","Audreanne","Audrey","August","Augusta","Augustine","Augustus","Aurelia","Aurelie","Aurelio","Aurore","Austen","Austin","Austyn","Autumn","Ava","Avery","Avis","Axel","Ayana","Ayden","Ayla","Aylin","Baby","Bailee","Bailey","Barbara","Barney","Baron","Barrett","Barry","Bart","Bartholome","Barton","Baylee","Beatrice","Beau","Beaulah","Bell","Bella","Belle","Ben","Benedict","Benjamin","Bennett","Bennie","Benny","Benton","Berenice","Bernadette","Bernadine","Bernard","Bernardo","Berneice","Bernhard","Bernice","Bernie","Berniece","Bernita","Berry","Bert","Berta","Bertha","Bertram","Bertrand","Beryl","Bessie","Beth","Bethany","Bethel","Betsy","Bette","Bettie","Betty","Bettye","Beulah","Beverly","Bianka","Bill","Billie","Billy","Birdie","Blair","Blaise","Blake","Blanca","Blanche","Blaze","Bo","Bobbie","Bobby","Bonita","Bonnie","Boris","Boyd","Brad","Braden","Bradford","Bradley","Bradly","Brady","Braeden","Brain","Brandi","Brando","Brandon","Brandt","Brandy","Brandyn","Brannon","Branson","Brant","Braulio","Braxton","Brayan","Breana","Breanna","Breanne","Brenda","Brendan","Brenden","Brendon","Brenna","Brennan","Brennon","Brent","Bret","Brett","Bria","Brian","Briana","Brianne","Brice","Bridget","Bridgette","Bridie","Brielle","Brigitte","Brionna","Brisa","Britney","Brittany","Brock","Broderick","Brody","Brook","Brooke","Brooklyn","Brooks","Brown","Bruce","Bryana","Bryce","Brycen","Bryon","Buck","Bud","Buddy","Buford","Bulah","Burdette","Burley","Burnice","Buster","Cade","Caden","Caesar","Caitlyn","Cale","Caleb","Caleigh","Cali","Calista","Callie","Camden","Cameron","Camila","Camilla","Camille","Camren","Camron","Camryn","Camylle","Candace","Candelario","Candice","Candida","Candido","Cara","Carey","Carissa","Carlee","Carleton","Carley","Carli","Carlie","Carlo","Carlos","Carlotta","Carmel","Carmela","Carmella","Carmelo","Carmen","Carmine","Carol","Carolanne","Carole","Carolina","Caroline","Carolyn","Carolyne","Carrie","Carroll","Carson","Carter","Cary","Casandra","Casey","Casimer","Casimir","Casper","Cassandra","Cassandre","Cassidy","Cassie","Catalina","Caterina","Catharine","Catherine","Cathrine","Cathryn","Cathy","Cayla","Ceasar","Cecelia","Cecil","Cecile","Cecilia","Cedrick","Celestine","Celestino","Celia","Celine","Cesar","Chad","Chadd","Chadrick","Chaim","Chance","Chandler","Chanel","Chanelle","Charity","Charlene","Charles","Charley","Charlie","Charlotte","Chase","Chasity","Chauncey","Chaya","Chaz","Chelsea","Chelsey","Chelsie","Chesley","Chester","Chet","Cheyanne","Cheyenne","Chloe","Chris","Christ","Christa","Christelle","Christian","Christiana","Christina","Christine","Christop","Christophe","Christopher","Christy","Chyna","Ciara","Cicero","Cielo","Cierra","Cindy","Citlalli","Clair","Claire","Clara","Clarabelle","Clare","Clarissa","Clark","Claud","Claude","Claudia","Claudie","Claudine","Clay","Clemens","Clement","Clementina","Clementine","Clemmie","Cleo","Cleora","Cleta","Cletus","Cleve","Cleveland","Clifford","Clifton","Clint","Clinton","Clotilde","Clovis","Cloyd","Clyde","Coby","Cody","Colby","Cole","Coleman","Colin","Colleen","Collin","Colt","Colten","Colton","Columbus","Concepcion","Conner","Connie","Connor","Conor","Conrad","Constance","Constantin","Consuelo","Cooper","Cora","Coralie","Corbin","Cordelia","Cordell","Cordia","Cordie","Corene","Corine","Cornelius","Cornell","Corrine","Cortez","Cortney","Cory","Coty","Courtney","Coy","Craig","Crawford","Creola","Cristal","Cristian","Cristina","Cristobal","Cristopher","Cruz","Crystal","Crystel","Cullen","Curt","Curtis","Cydney","Cynthia","Cyril","Cyrus","Dagmar","Dahlia","Daija","Daisha","Daisy","Dakota","Dale","Dallas","Dallin","Dalton","Damaris","Dameon","Damian","Damien","Damion","Damon","Dan","Dana","Dandre","Dane","D'angelo","Dangelo","Danial","Daniela","Daniella","Danielle","Danika","Dannie","Danny","Dante","Danyka","Daphne","Daphnee","Daphney","Darby","Daren","Darian","Dariana","Darien","Dario","Darion","Darius","Darlene","Daron","Darrel","Darrell","Darren","Darrick","Darrin","Darrion","Darron","Darryl","Darwin","Daryl","Dashawn","Dasia","Dave","David","Davin","Davion","Davon","Davonte","Dawn","Dawson","Dax","Dayana","Dayna","Dayne","Dayton","Dean","Deangelo","Deanna","Deborah","Declan","Dedric","Dedrick","Dee","Deion","Deja","Dejah","Dejon","Dejuan","Delaney","Delbert","Delfina","Delia","Delilah","Dell","Della","Delmer","Delores","Delpha","Delphia","Delphine","Delta","Demarco","Demarcus","Demario","Demetris","Demetrius","Demond","Dena","Denis","Dennis","Deon","Deondre","Deontae","Deonte","Dereck","Derek","Derick","Deron","Derrick","Deshaun","Deshawn","Desiree","Desmond","Dessie","Destany","Destin","Destinee","Destiney","Destini","Destiny","Devan","Devante","Deven","Devin","Devon","Devonte","Devyn","Dewayne","Dewitt","Dexter","Diamond","Diana","Dianna","Diego","Dillan","Dillon","Dimitri","Dina","Dino","Dion","Dixie","Dock","Dolly","Dolores","Domenic","Domenica","Domenick","Domenico","Domingo","Dominic","Dominique","Don","Donald","Donato","Donavon","Donna","Donnell","Donnie","Donny","Dora","Dorcas","Dorian","Doris","Dorothea","Dorothy","Dorris","Dortha","Dorthy","Doug","Douglas","Dovie","Doyle","Drake","Drew","Duane","Dudley","Dulce","Duncan","Durward","Dustin","Dusty","Dwight","Dylan","Earl","Earlene","Earline","Earnest","Earnestine","Easter","Easton","Ebba","Ebony","Ed","Eda","Edd","Eddie","Eden","Edgar","Edgardo","Edison","Edmond","Edmund","Edna","Eduardo","Edward","Edwardo","Edwin","Edwina","Edyth","Edythe","Effie","Efrain","Efren","Eileen","Einar","Eino","Eladio","Elaina","Elbert","Elda","Eldon","Eldora","Eldred","Eldridge","Eleanora","Eleanore","Eleazar","Electa","Elena","Elenor","Elenora","Eleonore","Elfrieda","Eli","Elian","Eliane","Elias","Eliezer","Elijah","Elinor","Elinore","Elisa","Elisabeth","Elise","Eliseo","Elisha","Elissa","Eliza","Elizabeth","Ella","Ellen","Ellie","Elliot","Elliott","Ellis","Ellsworth","Elmer","Elmira","Elmo","Elmore","Elna","Elnora","Elody","Eloisa","Eloise","Elouise","Eloy","Elroy","Elsa","Else","Elsie","Elta","Elton","Elva","Elvera","Elvie","Elvis","Elwin","Elwyn","Elyse","Elyssa","Elza","Emanuel","Emelia","Emelie","Emely","Emerald","Emerson","Emery","Emie","Emil","Emile","Emilia","Emiliano","Emilie","Emilio","Emily","Emma","Emmalee","Emmanuel","Emmanuelle","Emmet","Emmett","Emmie","Emmitt","Emmy","Emory","Ena","Enid","Enoch","Enola","Enos","Enrico","Enrique","Ephraim","Era","Eriberto","Eric","Erica","Erich","Erick","Ericka","Erik","Erika","Erin","Erling","Erna","Ernest","Ernestina","Ernestine","Ernesto","Ernie","Ervin","Erwin","Eryn","Esmeralda","Esperanza","Esta","Esteban","Estefania","Estel","Estell","Estella","Estelle","Estevan","Esther","Estrella","Etha","Ethan","Ethel","Ethelyn","Ethyl","Ettie","Eudora","Eugene","Eugenia","Eula","Eulah","Eulalia","Euna","Eunice","Eusebio","Eva","Evalyn","Evan","Evangeline","Evans","Eve","Eveline","Evelyn","Everardo","Everett","Everette","Evert","Evie","Ewald","Ewell","Ezekiel","Ezequiel","Ezra","Fabian","Fabiola","Fae","Fannie","Fanny","Fatima","Faustino","Fausto","Favian","Fay","Faye","Federico","Felicia","Felicita","Felicity","Felipa","Felipe","Felix","Felton","Fermin","Fern","Fernando","Ferne","Fidel","Filiberto","Filomena","Finn","Fiona","Flavie","Flavio","Fleta","Fletcher","Flo","Florence","Florencio","Florian","Florida","Florine","Flossie","Floy","Floyd","Ford","Forest","Forrest","Foster","Frances","Francesca","Francesco","Francis","Francisca","Francisco","Franco","Frank","Frankie","Franz","Fred","Freda","Freddie","Freddy","Frederic","Frederick","Frederik","Frederique","Fredrick","Fredy","Freeda","Freeman","Freida","Frida","Frieda","Friedrich","Fritz","Furman","Gabe","Gabriel","Gabriella","Gabrielle","Gaetano","Gage","Gail","Gardner","Garett","Garfield","Garland","Garnet","Garnett","Garret","Garrett","Garrick","Garrison","Garry","Garth","Gaston","Gavin","Gay","Gayle","Gaylord","Gene","General","Genesis","Genevieve","Gennaro","Genoveva","Geo","Geoffrey","George","Georgette","Georgiana","Georgianna","Geovanni","Geovanny","Geovany","Gerald","Geraldine","Gerard","Gerardo","Gerda","Gerhard","Germaine","German","Gerry","Gerson","Gertrude","Gia","Gianni","Gideon","Gilbert","Gilberto","Gilda","Giles","Gillian","Gina","Gino","Giovani","Giovanna","Giovanni","Giovanny","Gisselle","Giuseppe","Gladyce","Gladys","Glen","Glenda","Glenna","Glennie","Gloria","Godfrey","Golda","Golden","Gonzalo","Gordon","Grace","Gracie","Graciela","Grady","Graham","Grant","Granville","Grayce","Grayson","Green","Greg","Gregg","Gregoria","Gregorio","Gregory","Greta","Gretchen","Greyson","Griffin","Grover","Guadalupe","Gudrun","Guido","Guillermo","Guiseppe","Gunnar","Gunner","Gus","Gussie","Gust","Gustave","Guy","Gwen","Gwendolyn","Hadley","Hailee","Hailey","Hailie","Hal","Haleigh","Haley","Halie","Halle","Hallie","Hank","Hanna","Hannah","Hans","Hardy","Harley","Harmon","Harmony","Harold","Harrison","Harry","Harvey","Haskell","Hassan","Hassie","Hattie","Haven","Hayden","Haylee","Hayley","Haylie","Hazel","Hazle","Heath","Heather","Heaven","Heber","Hector","Heidi","Helen","Helena","Helene","Helga","Hellen","Helmer","Heloise","Henderson","Henri","Henriette","Henry","Herbert","Herman","Hermann","Hermina","Herminia","Herminio","Hershel","Herta","Hertha","Hester","Hettie","Hilario","Hilbert","Hilda","Hildegard","Hillard","Hillary","Hilma","Hilton","Hipolito","Hiram","Hobart","Holden","Hollie","Hollis","Holly","Hope","Horace","Horacio","Hortense","Hosea","Houston","Howard","Howell","Hoyt","Hubert","Hudson","Hugh","Hulda","Humberto","Hunter","Hyman","Ian","Ibrahim","Icie","Ida","Idell","Idella","Ignacio","Ignatius","Ike","Ila","Ilene","Iliana","Ima","Imani","Imelda","Immanuel","Imogene","Ines","Irma","Irving","Irwin","Isaac","Isabel","Isabell","Isabella","Isabelle","Isac","Isadore","Isai","Isaiah","Isaias","Isidro","Ismael","Isobel","Isom","Israel","Issac","Itzel","Iva","Ivah","Ivory","Ivy","Izabella","Izaiah","Jabari","Jace","Jacey","Jacinthe","Jacinto","Jack","Jackeline","Jackie","Jacklyn","Jackson","Jacky","Jaclyn","Jacquelyn","Jacques","Jacynthe","Jada","Jade","Jaden","Jadon","Jadyn","Jaeden","Jaida","Jaiden","Jailyn","Jaime","Jairo","Jakayla","Jake","Jakob","Jaleel","Jalen","Jalon","Jalyn","Jamaal","Jamal","Jamar","Jamarcus","Jamel","Jameson","Jamey","Jamie","Jamil","Jamir","Jamison","Jammie","Jan","Jana","Janae","Jane","Janelle","Janessa","Janet","Janice","Janick","Janie","Janis","Janiya","Jannie","Jany","Jaquan","Jaquelin","Jaqueline","Jared","Jaren","Jarod","Jaron","Jarred","Jarrell","Jarret","Jarrett","Jarrod","Jarvis","Jasen","Jasmin","Jason","Jasper","Jaunita","Javier","Javon","Javonte","Jay","Jayce","Jaycee","Jayda","Jayde","Jayden","Jaydon","Jaylan","Jaylen","Jaylin","Jaylon","Jayme","Jayne","Jayson","Jazlyn","Jazmin","Jazmyn","Jazmyne","Jean","Jeanette","Jeanie","Jeanne","Jed","Jedediah","Jedidiah","Jeff","Jefferey","Jeffery","Jeffrey","Jeffry","Jena","Jenifer","Jennie","Jennifer","Jennings","Jennyfer","Jensen","Jerad","Jerald","Jeramie","Jeramy","Jerel","Jeremie","Jeremy","Jermain","Jermaine","Jermey","Jerod","Jerome","Jeromy","Jerrell","Jerrod","Jerrold","Jerry","Jess","Jesse","Jessica","Jessie","Jessika","Jessy","Jessyca","Jesus","Jett","Jettie","Jevon","Jewel","Jewell","Jillian","Jimmie","Jimmy","Jo","Joan","Joana","Joanie","Joanne","Joannie","Joanny","Joany","Joaquin","Jocelyn","Jodie","Jody","Joe","Joel","Joelle","Joesph","Joey","Johan","Johann","Johanna","Johathan","John","Johnathan","Johnathon","Johnnie","Johnny","Johnpaul","Johnson","Jolie","Jon","Jonas","Jonatan","Jonathan","Jonathon","Jordan","Jordane","Jordi","Jordon","Jordy","Jordyn","Jorge","Jose","Josefa","Josefina","Joseph","Josephine","Josh","Joshua","Joshuah","Josiah","Josiane","Josianne","Josie","Josue","Jovan","Jovani","Jovanny","Jovany","Joy","Joyce","Juana","Juanita","Judah","Judd","Jude","Judge","Judson","Judy","Jules","Julia","Julian","Juliana","Julianne","Julie","Julien","Juliet","Julio","Julius","June","Junior","Junius","Justen","Justice","Justina","Justine","Juston","Justus","Justyn","Juvenal","Juwan","Kacey","Kaci","Kacie","Kade","Kaden","Kadin","Kaela","Kaelyn","Kaia","Kailee","Kailey","Kailyn","Kaitlin","Kaitlyn","Kale","Kaleb","Kaleigh","Kaley","Kali","Kallie","Kameron","Kamille","Kamren","Kamron","Kamryn","Kane","Kara","Kareem","Karelle","Karen","Kari","Kariane","Karianne","Karina","Karine","Karl","Karlee","Karley","Karli","Karlie","Karolann","Karson","Kasandra","Kasey","Kassandra","Katarina","Katelin","Katelyn","Katelynn","Katharina","Katherine","Katheryn","Kathleen","Kathlyn","Kathryn","Kathryne","Katlyn","Katlynn","Katrina","Katrine","Kattie","Kavon","Kay","Kaya","Kaycee","Kayden","Kayla","Kaylah","Kaylee","Kayleigh","Kayley","Kayli","Kaylie","Kaylin","Keagan","Keanu","Keara","Keaton","Keegan","Keeley","Keely","Keenan","Keira","Keith","Kellen","Kelley","Kelli","Kellie","Kelly","Kelsi","Kelsie","Kelton","Kelvin","Ken","Kendall","Kendra","Kendrick","Kenna","Kennedi","Kennedy","Kenneth","Kennith","Kenny","Kenton","Kenya","Kenyatta","Kenyon","Keon","Keshaun","Keshawn","Keven","Kevin","Kevon","Keyon","Keyshawn","Khalid","Khalil","Kian","Kiana","Kianna","Kiara","Kiarra","Kiel","Kiera","Kieran","Kiley","Kim","Kimberly","King","Kip","Kira","Kirk","Kirsten","Kirstin","Kitty","Kobe","Koby","Kody","Kolby","Kole","Korbin","Korey","Kory","Kraig","Kris","Krista","Kristian","Kristin","Kristina","Kristofer","Kristoffer","Kristopher","Kristy","Krystal","Krystel","Krystina","Kurt","Kurtis","Kyla","Kyle","Kylee","Kyleigh","Kyler","Kylie","Kyra","Lacey","Lacy","Ladarius","Lafayette","Laila","Laisha","Lamar","Lambert","Lamont","Lance","Landen","Lane","Laney","Larissa","Laron","Larry","Larue","Laura","Laurel","Lauren","Laurence","Lauretta","Lauriane","Laurianne","Laurie","Laurine","Laury","Lauryn","Lavada","Lavern","Laverna","Laverne","Lavina","Lavinia","Lavon","Lavonne","Lawrence","Lawson","Layla","Layne","Lazaro","Lea","Leann","Leanna","Leanne","Leatha","Leda","Lee","Leif","Leila","Leilani","Lela","Lelah","Leland","Lelia","Lempi","Lemuel","Lenna","Lennie","Lenny","Lenora","Lenore","Leo","Leola","Leon","Leonard","Leonardo","Leone","Leonel","Leonie","Leonor","Leonora","Leopold","Leopoldo","Leora","Lera","Lesley","Leslie","Lesly","Lessie","Lester","Leta","Letha","Letitia","Levi","Lew","Lewis","Lexi","Lexie","Lexus","Lia","Liam","Liana","Libbie","Libby","Lila","Lilian","Liliana","Liliane","Lilla","Lillian","Lilliana","Lillie","Lilly","Lily","Lilyan","Lina","Lincoln","Linda","Lindsay","Lindsey","Linnea","Linnie","Linwood","Lionel","Lisa","Lisandro","Lisette","Litzy","Liza","Lizeth","Lizzie","Llewellyn","Lloyd","Logan","Lois","Lola","Lolita","Loma","Lon","London","Lonie","Lonnie","Lonny","Lonzo","Lora","Loraine","Loren","Lorena","Lorenz","Lorenza","Lorenzo","Lori","Lorine","Lorna","Lottie","Lou","Louie","Louisa","Lourdes","Louvenia","Lowell","Loy","Loyal","Loyce","Lucas","Luciano","Lucie","Lucienne","Lucile","Lucinda","Lucio","Lucious","Lucius","Lucy","Ludie","Ludwig","Lue","Luella","Luigi","Luis","Luisa","Lukas","Lula","Lulu","Luna","Lupe","Lura","Lurline","Luther","Luz","Lyda","Lydia","Lyla","Lynn","Lyric","Lysanne","Mabel","Mabelle","Mable","Mac","Macey","Maci","Macie","Mack","Mackenzie","Macy","Madaline","Madalyn","Maddison","Madeline","Madelyn","Madelynn","Madge","Madie","Madilyn","Madisen","Madison","Madisyn","Madonna","Madyson","Mae","Maegan","Maeve","Mafalda","Magali","Magdalen","Magdalena","Maggie","Magnolia","Magnus","Maia","Maida","Maiya","Major","Makayla","Makenna","Makenzie","Malachi","Malcolm","Malika","Malinda","Mallie","Mallory","Malvina","Mandy","Manley","Manuel","Manuela","Mara","Marc","Marcel","Marcelina","Marcelino","Marcella","Marcelle","Marcellus","Marcelo","Marcia","Marco","Marcos","Marcus","Margaret","Margarete","Margarett","Margaretta","Margarette","Margarita","Marge","Margie","Margot","Margret","Marguerite","Maria","Mariah","Mariam","Marian","Mariana","Mariane","Marianna","Marianne","Mariano","Maribel","Marie","Mariela","Marielle","Marietta","Marilie","Marilou","Marilyne","Marina","Mario","Marion","Marisa","Marisol","Maritza","Marjolaine","Marjorie","Marjory","Mark","Markus","Marlee","Marlen","Marlene","Marley","Marlin","Marlon","Marques","Marquis","Marquise","Marshall","Marta","Martin","Martina","Martine","Marty","Marvin","Mary","Maryam","Maryjane","Maryse","Mason","Mateo","Mathew","Mathias","Mathilde","Matilda","Matilde","Matt","Matteo","Mattie","Maud","Maude","Maudie","Maureen","Maurice","Mauricio","Maurine","Maverick","Mavis","Max","Maxie","Maxime","Maximilian","Maximillia","Maximillian","Maximo","Maximus","Maxine","Maxwell","May","Maya","Maybell","Maybelle","Maye","Maymie","Maynard","Mayra","Mazie","Mckayla","Mckenna","Mckenzie","Meagan","Meaghan","Meda","Megane","Meggie","Meghan","Mekhi","Melany","Melba","Melisa","Melissa","Mellie","Melody","Melvin","Melvina","Melyna","Melyssa","Mercedes","Meredith","Merl","Merle","Merlin","Merritt","Mertie","Mervin","Meta","Mia","Micaela","Micah","Michael","Michaela","Michale","Micheal","Michel","Michele","Michelle","Miguel","Mikayla","Mike","Mikel","Milan","Miles","Milford","Miller","Millie","Milo","Milton","Mina","Minerva","Minnie","Miracle","Mireille","Mireya","Misael","Missouri","Misty","Mitchel","Mitchell","Mittie","Modesta","Modesto","Mohamed","Mohammad","Mohammed","Moises","Mollie","Molly","Mona","Monica","Monique","Monroe","Monserrat","Monserrate","Montana","Monte","Monty","Morgan","Moriah","Morris","Mortimer","Morton","Mose","Moses","Moshe","Mossie","Mozell","Mozelle","Muhammad","Muriel","Murl","Murphy","Murray","Mustafa","Mya","Myah","Mylene","Myles","Myra","Myriam","Myrl","Myrna","Myron","Myrtice","Myrtie","Myrtis","Myrtle","Nadia","Nakia","Name","Nannie","Naomi","Naomie","Napoleon","Narciso","Nash","Nasir","Nat","Natalia","Natalie","Natasha","Nathan","Nathanael","Nathanial","Nathaniel","Nathen","Nayeli","Neal","Ned","Nedra","Neha","Neil","Nelda","Nella","Nelle","Nellie","Nels","Nelson","Neoma","Nestor","Nettie","Neva","Newell","Newton","Nia","Nicholas","Nicholaus","Nichole","Nick","Nicklaus","Nickolas","Nico","Nicola","Nicolas","Nicole","Nicolette","Nigel","Nikita","Nikki","Nikko","Niko","Nikolas","Nils","Nina","Noah","Noble","Noe","Noel","Noelia","Noemi","Noemie","Noemy","Nola","Nolan","Nona","Nora","Norbert","Norberto","Norene","Norma","Norris","Norval","Norwood","Nova","Novella","Nya","Nyah","Nyasia","Obie","Oceane","Ocie","Octavia","Oda","Odell","Odessa","Odie","Ofelia","Okey","Ola","Olaf","Ole","Olen","Oleta","Olga","Olin","Oliver","Ollie","Oma","Omari","Omer","Ona","Onie","Opal","Ophelia","Ora","Oral","Oran","Oren","Orie","Orin","Orion","Orland","Orlando","Orlo","Orpha","Orrin","Orval","Orville","Osbaldo","Osborne","Oscar","Osvaldo","Oswald","Oswaldo","Otha","Otho","Otilia","Otis","Ottilie","Ottis","Otto","Ova","Owen","Ozella","Pablo","Paige","Palma","Pamela","Pansy","Paolo","Paris","Parker","Pascale","Pasquale","Pat","Patience","Patricia","Patrick","Patsy","Pattie","Paul","Paula","Pauline","Paxton","Payton","Pearl","Pearlie","Pearline","Pedro","Peggie","Penelope","Percival","Percy","Perry","Pete","Peter","Petra","Peyton","Philip","Phoebe","Phyllis","Pierce","Pierre","Pietro","Pink","Pinkie","Piper","Polly","Porter","Precious","Presley","Preston","Price","Prince","Princess","Priscilla","Providenci","Prudence","Queen","Queenie","Quentin","Quincy","Quinn","Quinten","Quinton","Rachael","Rachel","Rachelle","Rae","Raegan","Rafael","Rafaela","Raheem","Rahsaan","Rahul","Raina","Raleigh","Ralph","Ramiro","Ramon","Ramona","Randal","Randall","Randi","Randy","Ransom","Raoul","Raphael","Raphaelle","Raquel","Rashad","Rashawn","Rasheed","Raul","Raven","Ray","Raymond","Raymundo","Reagan","Reanna","Reba","Rebeca","Rebecca","Rebeka","Rebekah","Reece","Reed","Reese","Regan","Reggie","Reginald","Reid","Reilly","Reina","Reinhold","Remington","Rene","Renee","Ressie","Reta","Retha","Retta","Reuben","Reva","Rex","Rey","Reyes","Reymundo","Reyna","Reynold","Rhea","Rhett","Rhianna","Rhiannon","Rhoda","Ricardo","Richard","Richie","Richmond","Rick","Rickey","Rickie","Ricky","Rico","Rigoberto","Riley","Rita","River","Robb","Robbie","Robert","Roberta","Roberto","Robin","Robyn","Rocio","Rocky","Rod","Roderick","Rodger","Rodolfo","Rodrick","Rodrigo","Roel","Rogelio","Roger","Rogers","Rolando","Rollin","Roma","Romaine","Roman","Ron","Ronaldo","Ronny","Roosevelt","Rory","Rosa","Rosalee","Rosalia","Rosalind","Rosalinda","Rosalyn","Rosamond","Rosanna","Rosario","Roscoe","Rose","Rosella","Roselyn","Rosemarie","Rosemary","Rosendo","Rosetta","Rosie","Rosina","Roslyn","Ross","Rossie","Rowan","Rowena","Rowland","Roxane","Roxanne","Roy","Royal","Royce","Rozella","Ruben","Rubie","Ruby","Rubye","Rudolph","Rudy","Rupert","Russ","Russel","Russell","Rusty","Ruth","Ruthe","Ruthie","Ryan","Ryann","Ryder","Rylan","Rylee","Ryleigh","Ryley","Sabina","Sabrina","Sabryna","Sadie","Sadye","Sage","Saige","Sallie","Sally","Salma","Salvador","Salvatore","Sam","Samanta","Samantha","Samara","Samir","Sammie","Sammy","Samson","Sandra","Sandrine","Sandy","Sanford","Santa","Santiago","Santina","Santino","Santos","Sarah","Sarai","Sarina","Sasha","Saul","Savanah","Savanna","Savannah","Savion","Scarlett","Schuyler","Scot","Scottie","Scotty","Seamus","Sean","Sebastian","Sedrick","Selena","Selina","Selmer","Serena","Serenity","Seth","Shad","Shaina","Shakira","Shana","Shane","Shanel","Shanelle","Shania","Shanie","Shaniya","Shanna","Shannon","Shanny","Shanon","Shany","Sharon","Shaun","Shawn","Shawna","Shaylee","Shayna","Shayne","Shea","Sheila","Sheldon","Shemar","Sheridan","Sherman","Sherwood","Shirley","Shyann","Shyanne","Sibyl","Sid","Sidney","Sienna","Sierra","Sigmund","Sigrid","Sigurd","Silas","Sim","Simeon","Simone","Sincere","Sister","Skye","Skyla","Skylar","Sofia","Soledad","Solon","Sonia","Sonny","Sonya","Sophia","Sophie","Spencer","Stacey","Stacy","Stan","Stanford","Stanley","Stanton","Stefan","Stefanie","Stella","Stephan","Stephania","Stephanie","Stephany","Stephen","Stephon","Sterling","Steve","Stevie","Stewart","Stone","Stuart","Summer","Sunny","Susan","Susana","Susanna","Susie","Suzanne","Sven","Syble","Sydnee","Sydney","Sydni","Sydnie","Sylvan","Sylvester","Sylvia","Tabitha","Tad","Talia","Talon","Tamara","Tamia","Tania","Tanner","Tanya","Tara","Taryn","Tate","Tatum","Tatyana","Taurean","Tavares","Taya","Taylor","Teagan","Ted","Telly","Terence","Teresa","Terrance","Terrell","Terrence","Terrill","Terry","Tess","Tessie","Tevin","Thad","Thaddeus","Thalia","Thea","Thelma","Theo","Theodora","Theodore","Theresa","Therese","Theresia","Theron","Thomas","Thora","Thurman","Tia","Tiana","Tianna","Tiara","Tierra","Tiffany","Tillman","Timmothy","Timmy","Timothy","Tina","Tito","Titus","Tobin","Toby","Tod","Tom","Tomas","Tomasa","Tommie","Toney","Toni","Tony","Torey","Torrance","Torrey","Toy","Trace","Tracey","Tracy","Travis","Travon","Tre","Tremaine","Tremayne","Trent","Trenton","Tressa","Tressie","Treva","Trever","Trevion","Trevor","Trey","Trinity","Trisha","Tristian","Tristin","Triston","Troy","Trudie","Trycia","Trystan","Turner","Twila","Tyler","Tyra","Tyree","Tyreek","Tyrel","Tyrell","Tyrese","Tyrique","Tyshawn","Tyson","Ubaldo","Ulices","Ulises","Una","Unique","Urban","Uriah","Uriel","Ursula","Vada","Valentin","Valentina","Valentine","Valerie","Vallie","Van","Vance","Vanessa","Vaughn","Veda","Velda","Vella","Velma","Velva","Vena","Verda","Verdie","Vergie","Verla","Verlie","Vern","Verna","Verner","Vernice","Vernie","Vernon","Verona","Veronica","Vesta","Vicenta","Vicente","Vickie","Vicky","Victor","Victoria","Vida","Vidal","Vilma","Vince","Vincent","Vincenza","Vincenzo","Vinnie","Viola","Violet","Violette","Virgie","Virgil","Virginia","Virginie","Vita","Vito","Viva","Vivian","Viviane","Vivianne","Vivien","Vivienne","Vladimir","Wade","Waino","Waldo","Walker","Wallace","Walter","Walton","Wanda","Ward","Warren","Watson","Wava","Waylon","Wayne","Webster","Weldon","Wellington","Wendell","Wendy","Werner","Westley","Weston","Whitney","Wilber","Wilbert","Wilburn","Wiley","Wilford","Wilfred","Wilfredo","Wilfrid","Wilhelm","Wilhelmine","Will","Willa","Willard","William","Willie","Willis","Willow","Willy","Wilma","Wilmer","Wilson","Wilton","Winfield","Winifred","Winnifred","Winona","Winston","Woodrow","Wyatt","Wyman","Xander","Xavier","Xzavier","Yadira","Yasmeen","Yasmin","Yasmine","Yazmin","Yesenia","Yessenia","Yolanda","Yoshiko","Yvette","Yvonne","Zachariah","Zachary","Zachery","Zack","Zackary","Zackery","Zakary","Zander","Zane","Zaria","Zechariah","Zelda","Zella","Zelma","Zena","Zetta","Zion","Zita","Zoe","Zoey","Zoie","Zoila","Zola","Zora","Zula"];e.exports={generateUsername:function(){return r.randomElement(i)+"-"+r.randomAlphanumStr(3)}}},function(e,t,n){"use strict";function r(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:500,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:2;return Math.floor(Math.random()*(1e3*Math.pow(n,e)-t)+t)}n.d(t,"a",function(){return r})},function(e,t,n){"use strict";n.d(t,"a",function(){return r});var r=(function(){function e(){_classCallCheck(this,e),this._lastSuccess=null}return _createClass(e,[{key:"startTracking",value:function(e){var t=e.rawInput;e.rawInput=function(){for(var n=arguments.length,r=new Array(n),i=0;istartmuted");if(f&&f.length>0){var v=f.attr("audio"),g=f.attr("video");this.eventEmitter.emit(s.a.START_MUTED_FROM_FOCUS,"true"===v,"true"===g)}m.info("Marking session from "+i+" as "+(l?"":"*not*")+" P2P");var y=l?this.p2pIceConfig:this.jvbIceConfig;c=new p.a($(e).find("jingle").attr("sid"),$(e).attr("to"),i,this.connection,this.mediaConstraints,JSON.parse(JSON.stringify(y)),l,!1),this.sessions[c.sid]=c,this.eventEmitter.emit(s.a.CALL_INCOMING,c,$(e).find(">jingle"),d);break;case"session-accept":this.eventEmitter.emit(s.a.CALL_ACCEPTED,c,$(e).find(">jingle"));break;case"content-modify":c.modifyContents($(e).find(">jingle"));break;case"transport-info":this.eventEmitter.emit(s.a.TRANSPORT_INFO,c,$(e).find(">jingle"));break;case"session-terminate":m.log("terminating...",c.sid);var _=null,S=null;$(e).find(">jingle>reason").length&&(_=$(e).find(">jingle>reason>:first")[0].tagName,S=$(e).find(">jingle>reason>text").text()),this.terminate(c.sid,_,S),this.eventEmitter.emit(s.a.CALL_ENDED,c,_,S);break;case"transport-replace":m.info("(TIME) Start transport replace:\t",d),h.a.sendAnalytics(Object(r.G)(r.f,{p2p:l,value:d})),c.replaceTransport($(e).find(">jingle"),function(){var e=window.performance.now();m.info("(TIME) Transport replace success:\t",e),h.a.sendAnalytics(Object(r.G)(r.g,{p2p:l,value:e}))},function(e){u.a.callErrorHandler(e),m.error("Transport replace failed",e),c.sendTransportReject()});break;case"addsource":case"source-add":c.addRemoteStream($(e).find(">jingle>content"));break;case"removesource":case"source-remove":c.removeRemoteStream($(e).find(">jingle>content"));break;default:m.warn("jingle action not implemented",n),a.attrs({type:"error"}),a.c("error",{type:"cancel"}).c("bad-request",{xmlns:"urn:ietf:params:xml:ns:xmpp-stanzas"}).up()}return this.connection.send(a),!0}},{key:"newP2PJingleSession",value:function(e,t){var n=new p.a(l.a.randomHexString(12),e,t,this.connection,this.mediaConstraints,this.p2pIceConfig,!0,!0);return this.sessions[n.sid]=n,n}},{key:"terminate",value:function(e,t,n){this.sessions.hasOwnProperty(e)&&("ended"!==this.sessions[e].state&&this.sessions[e].onTerminated(t,n),delete this.sessions[e])}},{key:"getStunAndTurnCredentials",value:function(){var e=this;this.connection.sendIQ(Object(o.$iq)({type:"get",to:this.connection.domain}).c("services",{xmlns:"urn:xmpp:extdisco:1"}),function(t){var n=[];$(t).find(">services>service").each(function(e,t){var r={},i=(t=$(t)).attr("type");switch(i){case"stun":r.urls="stun:"+t.attr("host"),t.attr("port")&&(r.urls+=":"+t.attr("port")),n.push(r);break;case"turn":case"turns":r.urls=i+":";var o=t.attr("username");if(o){var a=navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);a&&parseInt(a[2],10)<28?r.urls+=o+"@":r.username=o}r.urls+=t.attr("host"),t.attr("port")&&(r.urls+=":"+t.attr("port"));var s=t.attr("transport");s&&"udp"!==s&&(r.urls+="?transport="+s),r.credential=t.attr("password")||r.credential,n.push(r)}});var r=e.xmpp.options;r.useStunTurn&&(e.jvbIceConfig.iceServers=n.filter(function(e){return e.urls.startsWith("turns")})),r.p2p&&r.p2p.useStunTurn&&(e.p2pIceConfig.iceServers=n)},function(e){m.warn("getting turn credentials failed",e),m.warn("is mod_turncredentials or similar installed?")})}},{key:"getLog",value:function(){var e=this,t={};return Object.keys(this.sessions).forEach(function(n){var r=e.sessions[n].peerconnection;r&&r.updateLog&&(t["jingle_"+n]={updateLog:r.updateLog,stats:r.stats,url:window.location.href})}),t}}]),t})(f.b)}).call(this,"modules/xmpp/strophe.jingle.js")},function(e,t){e.exports={integerHash:function(e){if(!e)return 0;var t,n=0;for(t=0;t=e.length&&n()}l(e,function(e){t(e,c(i))})},s.forEach=s.each,s.eachSeries=function(e,t,n){if(n=n||function(){},!e.length)return n();var r=0;!(function i(){t(e[r],function(t){t?(n(t),n=function(){}):(r+=1)>=e.length?n():i()})})()},s.forEachSeries=s.eachSeries,s.eachLimit=function(e,t,n,r){f(t).apply(null,[e,n,r])},s.forEachLimit=s.eachLimit;var f=function(e){return function(t,n,r){if(r=r||function(){},!t.length||e<=0)return r();var i=0,o=0,a=0;!(function s(){if(i>=t.length)return r();for(;a=t.length?r():s())})})()}},m=function(e){return function(){var t=Array.prototype.slice.call(arguments);return e.apply(null,[s.each].concat(t))}},v=function(e){return function(){var t=Array.prototype.slice.call(arguments);return e.apply(null,[s.eachSeries].concat(t))}},g=function(e,t,n,r){if(t=h(t,function(e,t){return{index:t,value:e}}),r){var i=[];e(t,function(e,t){n(e.value,function(n,r){i[e.index]=r,t(n)})},function(e){r(e,i)})}else e(t,function(e,t){n(e.value,function(e){t(e)})})};s.map=m(g),s.mapSeries=v(g),s.mapLimit=function(e,t,n,r){return y(t)(e,n,r)};var y=function(e){return(function(e,t){return function(){var n=Array.prototype.slice.call(arguments);return t.apply(null,[f(e)].concat(n))}})(e,g)};s.reduce=function(e,t,n,r){s.eachSeries(e,function(e,r){n(t,e,function(e,n){t=n,r(e)})},function(e){r(e,t)})},s.inject=s.reduce,s.foldl=s.reduce,s.reduceRight=function(e,t,n,r){var i=h(e,function(e){return e}).reverse();s.reduce(i,t,n,r)},s.foldr=s.reduceRight;var _=function(e,t,n,r){var i=[];e(t=h(t,function(e,t){return{index:t,value:e}}),function(e,t){n(e.value,function(n){n&&i.push(e),t()})},function(e){r(h(i.sort(function(e,t){return e.index-t.index}),function(e){return e.value}))})};s.filter=m(_),s.filterSeries=v(_),s.select=s.filter,s.selectSeries=s.filterSeries;var S=function(e,t,n,r){var i=[];e(t=h(t,function(e,t){return{index:t,value:e}}),function(e,t){n(e.value,function(n){n||i.push(e),t()})},function(e){r(h(i.sort(function(e,t){return e.index-t.index}),function(e){return e.value}))})};s.reject=m(S),s.rejectSeries=v(S);var E=function(e,t,n,r){e(t,function(e,t){n(e,function(n){n?(r(e),r=function(){}):t()})},function(e){r()})};s.detect=m(E),s.detectSeries=v(E),s.some=function(e,t,n){s.each(e,function(e,r){t(e,function(e){e&&(n(!0),n=function(){}),r()})},function(e){n(!1)})},s.any=s.some,s.every=function(e,t,n){s.each(e,function(e,r){t(e,function(e){e||(n(!1),n=function(){}),r()})},function(e){n(!0)})},s.all=s.every,s.sortBy=function(e,t,n){s.map(e,function(e,n){t(e,function(t,r){t?n(t):n(null,{value:e,criteria:r})})},function(e,t){if(e)return n(e);n(null,h(t.sort(function(e,t){var n=e.criteria,r=t.criteria;return nr?1:0}),function(e){return e.value}))})},s.auto=function(e,t){t=t||function(){};var n=p(e),r=n.length;if(!r)return t();var i={},o=[],a=function(e){o.unshift(e)},c=function(){r--,l(o.slice(0),function(e){e()})};a(function(){if(!r){var e=t;t=function(){},e(null,i)}}),l(n,function(n){var r=d(e[n])?e[n]:[e[n]],u=function(e){var r=Array.prototype.slice.call(arguments,1);if(r.length<=1&&(r=r[0]),e){var o={};l(p(i),function(e){o[e]=i[e]}),o[n]=r,t(e,o),t=function(){}}else i[n]=r,s.setImmediate(c)},h=r.slice(0,Math.abs(r.length-1))||[],f=function(){return t=function(e,t){return e&&i.hasOwnProperty(t)},r=!0,((e=h).reduce?e.reduce(t,r):(l(e,function(e,n,i){r=t(r,e)}),r))&&!i.hasOwnProperty(n);var e,t,r};if(f())r[r.length-1](u,i);else{a(function e(){f()&&((function(e){for(var t=0;t>>1);n(t,e[o])>=0?r=o:i=o-1}return r})(e.tasks,o,n)+1,0,o),e.saturated&&e.tasks.length===e.concurrency&&e.saturated(),s.setImmediate(e.process)})})(r,e,t,i)},delete r.unshift,r},s.cargo=function(e,t){var n=!1,r=[],i={tasks:r,payload:t,saturated:null,empty:null,drain:null,drained:!0,push:function(e,n){d(e)||(e=[e]),l(e,function(e){r.push({data:e,callback:"function"==typeof n?n:null}),i.drained=!1,i.saturated&&r.length===t&&i.saturated()}),s.setImmediate(i.process)},process:function o(){if(!n){if(0===r.length)return i.drain&&!i.drained&&i.drain(),void(i.drained=!0);var a="number"==typeof t?r.splice(0,t):r.splice(0,r.length),s=h(a,function(e){return e.data});i.empty&&i.empty(),n=!0,e(s,function(){n=!1;var e=arguments;l(a,function(t){t.callback&&t.callback.apply(null,e)}),o()})}},length:function(){return r.length},running:function(){return n}};return i};var T=function(e){return function(t){var n=Array.prototype.slice.call(arguments,1);t.apply(null,n.concat([function(t){var n=Array.prototype.slice.call(arguments,1);"undefined"!=typeof console&&(t?console.error&&console.error(t):console[e]&&l(n,function(t){console[e](t)}))}]))}};s.log=T("log"),s.dir=T("dir"),s.memoize=function(e,t){var n={},r={};t=t||function(e){return e};var i=function(){var i=Array.prototype.slice.call(arguments),o=i.pop(),a=t.apply(null,i);a in n?s.nextTick(function(){o.apply(null,n[a])}):a in r?r[a].push(o):(r[a]=[o],e.apply(null,i.concat([function(){n[a]=arguments;var e=r[a];delete r[a];for(var t=0,i=e.length;t2){var r=Array.prototype.slice.call(arguments,2);return n.apply(this,r)}return n};s.applyEach=m(A),s.applyEachSeries=v(A),s.forever=function(e,t){!(function n(r){if(r){if(t)return t(r);throw r}e(n)})()},e.exports?e.exports=s:void 0===(i=function(){return s}.apply(t,[]))||(e.exports=i)})()}).call(this,n(51),n(146).setImmediate)},function(e,t,n){"use strict";(function(e){var r=n(4),i=n(3),o=n(11),a=n.n(o),s=Object(r.getLogger)(e),c=-1,u=/request id \d+.\d+ got 200/,d=/request errored, status: (\d+), number of errors: \d+/;t.a=function(){i.Strophe.log=function(e,t){switch(s.trace("Strophe",n,t),"string"==typeof t&&-1!==t.indexOf("Request ")&&-1!==t.indexOf("timed out (secondary), restarting")&&(_readOnlyError("e"),n=i.Strophe.LogLevel.WARN),n){case i.Strophe.LogLevel.DEBUG:-1!==c&&u.test(t)&&(s.debug("Reset lastErrorStatus"),c=-1);break;case i.Strophe.LogLevel.WARN:s.warn("Strophe: "+t);var n=d.exec(t);n&&2===n.length&&(c=parseInt(n[1],10),s.debug("lastErrorStatus set to: "+c));break;case i.Strophe.LogLevel.ERROR:case i.Strophe.LogLevel.FATAL:t="Strophe: "+t,a.a.callErrorHandler(new Error(t)),s.error(t)}},i.Strophe.getLastErrorStatus=function(){return c},i.Strophe.getStatusString=function(e){switch(e){case i.Strophe.Status.BINDREQUIRED:return"BINDREQUIRED";case i.Strophe.Status.ERROR:return"ERROR";case i.Strophe.Status.CONNECTING:return"CONNECTING";case i.Strophe.Status.CONNFAIL:return"CONNFAIL";case i.Strophe.Status.AUTHENTICATING:return"AUTHENTICATING";case i.Strophe.Status.AUTHFAIL:return"AUTHFAIL";case i.Strophe.Status.CONNECTED:return"CONNECTED";case i.Strophe.Status.DISCONNECTED:return"DISCONNECTED";case i.Strophe.Status.DISCONNECTING:return"DISCONNECTING";case i.Strophe.Status.ATTACHED:return"ATTACHED";default:return"unknown"}}}}).call(this,"modules/xmpp/strophe.util.js")},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return d});var r=n(4),i=n(3),o=n(11),a=n.n(o),s=n(36),c=Object(r.getLogger)(e),u=12,d=(function(e){function t(e){var n;return _classCallCheck(this,t),(n=_possibleConstructorReturn(this,_getPrototypeOf(t).call(this))).failedPings=0,n.xmpp=e,n.pingExecIntervals=new Array(u),n}return _inherits(t,e),_createClass(t,[{key:"init",value:function(e){_get(_getPrototypeOf(t.prototype),"init",this).call(this,e),i.Strophe.addNamespace("PING","urn:xmpp:ping")}},{key:"ping",value:function(e,t,n,r){this._addPingExecutionTimestamp();var o=Object(i.$iq)({type:"get",to:e});o.c("ping",{xmlns:i.Strophe.NS.PING}),this.connection.sendIQ2(o,{timeout:r}).then(t,n)}},{key:"startInterval",value:function(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1e4;clearInterval(this.intervalId),this.intervalId=window.setInterval(function(){t.ping(e,function(){t.failedPings=0},function(e){t.failedPings+=1;var n="Ping "+(e?"error":"timeout");t.failedPings>=3?(a.a.callErrorHandler(new Error(n)),c.error(n,e)):c.warn(n,e)},15e3)},n),c.info("XMPP pings will be sent every "+n+" ms")}},{key:"stopInterval",value:function(){this.intervalId&&(window.clearInterval(this.intervalId),this.intervalId=null,this.failedPings=0,c.info("Ping interval cleared"))}},{key:"_addPingExecutionTimestamp",value:function(){this.pingExecIntervals.push((new Date).getTime()),this.pingExecIntervals.length>u&&this.pingExecIntervals.shift()}},{key:"getPingSuspendTime",value:function(){var e=this.pingExecIntervals.slice();e.push((new Date).getTime());var t=0,n=e[0];return e.forEach(function(e){var r=e-n;r>t&&(t=r),n=e}),t-=1e4,Math.max(t,0)}}]),t})(s.b)}).call(this,"modules/xmpp/strophe.ping.js")},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return c});var r=n(4),i=n(3),o=n(36),a=Object(r.getLogger)(e),s="urn:xmpp:rayo:1",c=(function(e){function t(){return _classCallCheck(this,t),_possibleConstructorReturn(this,_getPrototypeOf(t).apply(this,arguments))}return _inherits(t,e),_createClass(t,[{key:"init",value:function(e){_get(_getPrototypeOf(t.prototype),"init",this).call(this,e),this.connection.addHandler(this.onRayo.bind(this),s,"iq","set",null,null)}},{key:"onRayo",value:function(e){a.info("Rayo IQ",e)}},{key:"dial",value:function(e,t,n,r,o){var c=this;return new Promise(function(u,d){if(o){var l=Object(i.$iq)({type:"set",to:o});l.c("dial",{xmlns:s,to:e,from:t}),l.c("header",{name:"JvbRoomName",value:n}).up(),r&&r.length&&l.c("header",{name:"JvbRoomPassword",value:r}).up(),c.connection.sendIQ(l,function(e){a.info("Dial result ",e);var t=$(e).find("ref").attr("uri");c.callResource=t.substr("xmpp:".length),a.info("Received call resource: "+c.callResource),u()},function(e){a.info("Dial error ",e),d(e)})}else d(new Error("Internal error!"))})}},{key:"hangup",value:function(){var e=this;return new Promise(function(t,n){if(!e.callResource)return n(new Error("No call in progress")),void a.warn("No call in progress");var r=Object(i.$iq)({type:"set",to:e.callResource});r.c("hangup",{xmlns:s}),e.connection.sendIQ(r,function(n){a.info("Hangup result ",n),e.callResource=null,t()},function(t){a.info("Hangup error ",t),e.callResource=null,n(new Error("Hangup error "))})})}}]),t})(o.b)}).call(this,"modules/xmpp/strophe.rayo.js")},function(e,t,n){"use strict";var r=n(3),i=(function(e){function t(){var e;return _classCallCheck(this,t),(e=_possibleConstructorReturn(this,_getPrototypeOf(t).call(this))).log=[],e}return _inherits(t,e),_createClass(t,[{key:"init",value:function(e){_get(_getPrototypeOf(t.prototype),"init",this).call(this,e),this.connection.rawInput=this.logIncoming.bind(this),this.connection.rawOutput=this.logOutgoing.bind(this)}},{key:"logIncoming",value:function(e){this.log.push([(new Date).getTime(),"incoming",e])}},{key:"logOutgoing",value:function(e){this.log.push([(new Date).getTime(),"outgoing",e])}}]),t})(n(36).b);t.a=function(){r.Strophe.addConnectionPlugin("logger",new i)}},function(e,t,n){"use strict";n.d(t,"a",function(){return a});var r=n(2),i=n(8),o=n.n(i),a=(function(){function e(t){_classCallCheck(this,e),this.conference=t,t.addEventListener(r.TRACK_AUDIO_LEVEL_CHANGED,this._audioLevel.bind(this)),this.myUserID=this.conference.myUserId()}return _createClass(e,[{key:"_audioLevel",value:function(e,t){!this.conference.isP2PActive()||t<=.6||e===this.myUserID&&this.conference.getLocalAudioTrack().isMuted()||this.conference.rtc.eventEmitter.emit(o.a.DOMINANT_SPEAKER_CHANGED,e)}}]),e})()},function(e,t,n){"use strict";n.d(t,"a",function(){return i});var r=n(2),i=(function(){function e(t,n){_classCallCheck(this,e),this._callback=n,this._eventFired=!1,t.statistics.addAudioLevelListener(this._audioLevel.bind(this)),t.on(r.TRACK_MUTE_CHANGED,this._trackMuteChanged.bind(this)),t.on(r.TRACK_ADDED,this._trackAdded.bind(this))}return _createClass(e,[{key:"_audioLevel",value:function(e,t,n,r){r&&this.audioTrack&&!this._eventFired&&this.audioTrack.isMuted()&&n>.6&&(this._eventFired=!0,this._callback())}},{key:"_isLocalAudioTrack",value:function(e){return e.isAudioTrack()&&e.isLocal()}},{key:"_trackAdded",value:function(e){this._isLocalAudioTrack(e)&&(this.audioTrack=e)}},{key:"_trackMuteChanged",value:function(e){this._isLocalAudioTrack(e)&&e.isMuted()&&(this._eventFired=!1)}}]),e})()},function(e,t,n){"use strict";n.d(t,"a",function(){return a});var r=n(20),i=n(29),o=n(21),a=(function(e){function t(){var e;return _classCallCheck(this,t),(e=_possibleConstructorReturn(this,_getPrototypeOf(t).call(this)))._processing=!1,e._scoreArray=[],e._active=!1,e._calculateVADScore=e._calculateVADScore.bind(_assertThisInitialized(_assertThisInitialized(e))),e}return _inherits(t,e),_createClass(t,[{key:"_calculateVADScore",value:function(){Object(i.a)(this._scoreArray)>.6&&(this.emit(o.VAD_TALK_WHILE_MUTED),this._setActiveState(!1)),this.reset()}},{key:"_setActiveState",value:function(e){this._active=e,this.emit(o.DETECTOR_STATE_CHANGE,this._active)}},{key:"changeMuteState",value:function(e){this._setActiveState(e),this.reset()}},{key:"isActive",value:function(){return this._active}},{key:"processVADScore",value:function(e){this._active&&(this._processing?this._scoreArray.push(e.score):e.score>.9&&(this._processing=!0,this._scoreArray.push(e.score),this._processTimeout=setTimeout(this._calculateVADScore,700)))}},{key:"reset",value:function(){this._processing=!1,this._scoreArray=[],clearTimeout(this._processTimeout)}}]),t})(r.EventEmitter)},function(e,t,n){"use strict";n.d(t,"a",function(){return a});var r=n(20),i=n(29),o=n(21),a=(function(e){function t(){var e;return _classCallCheck(this,t),(e=_possibleConstructorReturn(this,_getPrototypeOf(t).call(this)))._processing=!1,e._scoreArray=[],e._audioLvlArray=[],e._active=!1,e._calculateNoisyScore=e._calculateNoisyScore.bind(_assertThisInitialized(_assertThisInitialized(e))),e}return _inherits(t,e),_createClass(t,[{key:"_calculateNoisyScore",value:function(){var e=Object(i.a)(this._scoreArray),t=Object(i.a)(this._audioLvlArray);e<.2&&t>.04&&(this.emit(o.VAD_NOISY_DEVICE),this._setActiveState(!1)),this.reset()}},{key:"_recordValues",value:function(e,t){this._scoreArray.push(e),this._audioLvlArray.push(t)}},{key:"_setActiveState",value:function(e){this._active=e,this.emit(o.DETECTOR_STATE_CHANGE,this._active)}},{key:"changeMuteState",value:function(e){this._setActiveState(!e),this.reset()}},{key:"isActive",value:function(){return this._active}},{key:"reset",value:function(){this._processing=!1,this._scoreArray=[],this._audioLvlArray=[],clearTimeout(this._processTimeout)}},{key:"processVADScore",value:function(e){if(this._active)if(this._processing){var t=Object(i.b)(e.pcmData);this._recordValues(e.score,Object(i.a)(t))}else if(e.score<.2){var n=Object(i.b)(e.pcmData),r=Object(i.a)(n);r>.02&&(this._processing=!0,this._recordValues(e.score,r),this._processTimeout=setTimeout(this._calculateNoisyScore,1500))}}}]),t})(r.EventEmitter)},function(e,t,n){"use strict";n.d(t,"a",function(){return s});var r=n(20),i=n.n(r),o=n(2),a=n(21),s=(function(e){function t(e){var n;return _classCallCheck(this,t),(n=_possibleConstructorReturn(this,_getPrototypeOf(t).call(this)))._conference=e,n._timeoutTrigger=null,n._hasAudioInput=null,e.statistics.addAudioLevelListener(n._audioLevel.bind(_assertThisInitialized(_assertThisInitialized(n)))),e.on(o.TRACK_ADDED,n._trackAdded.bind(_assertThisInitialized(_assertThisInitialized(n)))),n}return _inherits(t,e),_createClass(t,[{key:"_clearTriggerTimeout",value:function(){clearTimeout(this._timeoutTrigger),this._timeoutTrigger=null}},{key:"_handleAudioInputStateChange",value:function(e){var t=0!==e;null!==this._hasAudioInput&&this._hasAudioInput===t||(this._hasAudioInput=t,this.emit(a.AUDIO_INPUT_STATE_CHANGE,this._hasAudioInput))}},{key:"_handleNoAudioInputDetection",value:function(e){var t=this;this._eventFired||(0!==e||this._timeoutTrigger?0!==e&&this._timeoutTrigger&&this._clearTriggerTimeout():this._timeoutTrigger=setTimeout(function(){t._eventFired=!0,t.emit(a.NO_AUDIO_INPUT)},4e3))}},{key:"_audioLevel",value:function(e,t,n,r){if(r&&this._audioTrack){var i=e.localSSRCs.get(this._audioTrack.rtcId);i&&i.ssrcs.includes(t)&&(this._handleAudioInputStateChange(n),this._handleNoAudioInputDetection(n))}}},{key:"_trackAdded",value:function(e){e.isLocalAudioTrack()&&(this._audioTrack=e,this._eventFired=!1,this._clearTriggerTimeout())}}]),t})(i.a)},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return m});var r=n(28),i=n(2),o=n(4),a=n(0),s=n(13),c=n(31),u=Object(o.getLogger)(e),d="stats",l=[{width:1920,height:1080,layers:3,max:5e3,target:4e3,min:800},{width:1280,height:720,layers:3,max:2500,target:2500,min:600},{width:960,height:540,layers:3,max:900,target:900,min:450},{width:640,height:360,layers:2,max:700,target:500,min:150},{width:480,height:270,layers:2,max:450,target:350,min:150},{width:320,height:180,layers:1,max:200,target:150,min:30}],h=800,p=null;function f(e,t,n){if(n<15e3)return 1;var r=0,i=Math.min(t.height,t.width);if(e){var o=l.find(function(e){return e.height<=i});if(o){var a=function(){var e=i;if(!(o=l.find(function(t){return t.height===e})))return"break";r+=o.target};for(i=o.height;i>=180;i/=2){if("break"===a())break}}}else{var s=t.width*t.height;r=s<=76800?600:s<=307200?1700:s<=518400?2e3:2500}return Math.min(r,(function(e){return e>6e4?Number.MAX_SAFE_INTEGER:h*Math.pow(1.08,e/1e3)})(Math.max(0,n-1e3)))}var m=(function(){function e(t,n,o){var s=this;_classCallCheck(this,e),this.eventEmitter=n,this._conference=t,this._localStats={connectionQuality:100,jvbRTT:void 0},this._lastConnectionQualityUpdate=-1,this._remoteStats={},this._timeIceConnected=-1,this._timeVideoUnmuted=-1,this._timeLastBwCapRemoved=-1,o.config.startBitrate&&o.config.startBitrate>0&&(h=o.config.startBitrate),t.on(i.CONNECTION_INTERRUPTED,function(){s._updateLocalConnectionQuality(0),s.eventEmitter.emit(r.LOCAL_STATS_UPDATED,s._localStats),s._broadcastLocalStats()}),t.room.addListener(a.ICE_CONNECTION_STATE_CHANGED,function(e,t){e.isP2P||"connected"!==t||(s._timeIceConnected=window.performance.now())}),t.on(i.ENDPOINT_MESSAGE_RECEIVED,function(e,t){t.type===d&&s._updateRemoteStats(e.getId(),t.values)}),t.statistics.addConnectionStatsListener(this._updateLocalStats.bind(this)),t.on(i.TRACK_MUTE_CHANGED,function(e){e.isVideoTrack()&&(e.isMuted()?s._timeVideoUnmuted=-1:s._maybeUpdateUnmuteTime())}),t.on(i.TRACK_ADDED,function(e){e.isVideoTrack()&&!e.isMuted()&&s._maybeUpdateUnmuteTime()}),t.on(i.SERVER_REGION_CHANGED,function(e){s._localStats.serverRegion=e}),t.on(i.PROPERTIES_CHANGED,function(e){s._localStats.bridgeCount=Number((e||{})["bridge-count"])})}return _createClass(e,[{key:"_maybeUpdateUnmuteTime",value:function(){this._timeVideoUnmuted<0&&(this._timeVideoUnmuted=window.performance.now())}},{key:"_calculateConnectionQuality",value:function(e,t,n){var r,i=c[n],o=100;if(this._localStats.packetLoss&&(r=this._localStats.packetLoss.upload,t&&(r*=.5)),t||!i||e===s.DESKTOP||this._timeIceConnected<0||this._timeVideoUnmuted<0)void 0===r?(u.error("Cannot calculate connection quality, unknown packet loss."),o=100):o=r<=2?100:r<=4?70:r<=6?50:r<=8?30:r<=12?10:0;else{var a=this._conference.getActivePeerConnection(),d=Boolean(a&&a.isSimulcastOn()),l=a&&a.bandwidthLimiter&&a.bandwidthLimiter.getBandwidthLimit("video");!l&&p&&(this._timeLastBwCapRemoved=window.performance.now(),h=p),p=l;var m=f(d,i,window.performance.now()-Math.max(this._timeVideoUnmuted,this._timeIceConnected,this._timeLastBwCapRemoved));m=Math.min(.9*m,2500),p&&(m=Math.min(m,p)),o=100*this._localStats.bitrate.upload/m,r&&r>=10&&(o=Math.min(o,30))}if(this._lastConnectionQualityUpdate>0){var v=this._localStats.connectionQuality,g=(window.performance.now()-this._lastConnectionQualityUpdate)/1e3;o=Math.min(o,v+2*g)}return Math.min(100,o)}},{key:"_updateLocalConnectionQuality",value:function(e){this._localStats.connectionQuality=e,this._lastConnectionQualityUpdate=window.performance.now()}},{key:"_broadcastLocalStats",value:function(){var e={bitrate:this._localStats.bitrate,packetLoss:this._localStats.packetLoss,connectionQuality:this._localStats.connectionQuality,jvbRTT:this._localStats.jvbRTT,serverRegion:this._localStats.serverRegion,avgAudioLevels:this._localStats.localAvgAudioLevels};try{this._conference.broadcastEndpointMessage({type:d,values:e})}catch(e){}}},{key:"_updateLocalStats",value:function(e,t){if(!e.isP2P){var n=t.transport&&t.transport.length&&t.transport[0].rtt;this._localStats.jvbRTT=n||void 0}if(e===this._conference.getActivePeerConnection()){var i,o=!this._conference.isConnectionInterrupted(),a=this._conference.getLocalVideoTrack(),s=a?a.videoType:void 0,c=!a||a.isMuted(),u=a?a.resolution:null;for(i in c||this._maybeUpdateUnmuteTime(),t)t.hasOwnProperty(i)&&(this._localStats[i]=t[i]);o&&this._updateLocalConnectionQuality(this._calculateConnectionQuality(s,c,u)),this.eventEmitter.emit(r.LOCAL_STATS_UPDATED,this._localStats),this._broadcastLocalStats()}}},{key:"_updateRemoteStats",value:function(e,t){this._remoteStats[e]={bitrate:t.bitrate,packetLoss:t.packetLoss,connectionQuality:t.connectionQuality,jvbRTT:t.jvbRTT,serverRegion:t.serverRegion,avgAudioLevels:t.avgAudioLevels},this.eventEmitter.emit(r.REMOTE_STATS_UPDATED,e,this._remoteStats[e])}},{key:"getStats",value:function(){return this._localStats}}]),e})()}).call(this,"modules/connectivity/ConnectionQuality.js")},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return o});var r=n(4),i=Object(r.getLogger)(e),o=(function(){function e(t){_classCallCheck(this,e),this._conference=t}return _createClass(e,[{key:"start",value:function(e){var t=this;this._conference.xmpp.ping(65e3).then(function(){if(!t._canceled){var n=t._conference.jvbJingleSession,r=n&&n.getIceConnectionState();n?"connected"===r?i.info("ICE connection restored - not sending ICE failed"):t._iceFailedTimeout=window.setTimeout(function(){i.info("Sending ICE failed - the connection has not recovered: "+r),t._iceFailedTimeout=void 0,e.sendIceFailedNotification()},2e3):i.warn("Not sending ICE failed - no JVB connection")}},function(e){i.error("PING error/timeout - not sending ICE failed",e)})}},{key:"cancel",value:function(){this._canceled=!0,this._iceFailedTimeout&&window.clearTimeout(this._iceFailedTimeout)}}]),e})()}).call(this,"modules/connectivity/IceFailedNotification.js")},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return s});var r=n(118),i=n(4),o=Object(i.getLogger)(e),a=Symbol("kJitsiE2EE"),s=(function(){function e(t){_classCallCheck(this,e),this._options=t,this._worker=new Worker(Object(r.a)(),{name:"E2EE Worker"}),this._worker.onerror=function(e){return o.onerror(e)};var n=new TextEncoder;this._worker.postMessage({operation:"initialize",salt:n.encode(t.salt)})}return _createClass(e,[{key:"handleReceiver",value:function(e,t){if(!e[a]){e[a]=!0;var n="video"===t?e.createEncodedVideoStreams():e.createEncodedAudioStreams();this._worker.postMessage({operation:"decode",readableStream:n.readableStream,writableStream:n.writableStream},[n.readableStream,n.writableStream])}}},{key:"handleSender",value:function(e,t){if(!e[a]){e[a]=!0;var n="video"===t?e.createEncodedVideoStreams():e.createEncodedAudioStreams();this._worker.postMessage({operation:"encode",readableStream:n.readableStream,writableStream:n.writableStream},[n.readableStream,n.writableStream])}}},{key:"setKey",value:function(e){var t;t=!!e&&(new TextEncoder).encode(e),this._worker.postMessage({operation:"setKey",key:t})}}]),e})()}).call(this,"modules/e2ee/E2EEContext.js")},function(e,t,n){"use strict";n.d(t,"a",function(){return r});var r=function(){return URL.createObjectURL(new Blob(["\n // We use a ringbuffer of keys so we can change them and still decode packets that were\n // encrypted with an old key.\n // In the future when we dont rely on a globally shared key we will actually use it. For\n // now set the size to 1 which means there is only a single key. This causes some\n // glitches when changing the key but its ok.\n const keyRingSize = 1;\n\n // We use a 96 bit IV for AES GCM. This is signalled in plain together with the\n // packet. See https://developer.mozilla.org/en-US/docs/Web/API/AesGcmParams\n const ivLength = 12;\n\n // We copy the first bytes of the VP8 payload unencrypted.\n // For keyframes this is 10 bytes, for non-keyframes (delta) 3. See\n // https://tools.ietf.org/html/rfc6386#section-9.1\n // This allows the bridge to continue detecting keyframes (only one byte needed in the JVB)\n // and is also a bit easier for the VP8 decoder (i.e. it generates funny garbage pictures\n // instead of being unable to decode).\n // This is a bit for show and we might want to reduce to 1 unconditionally in the final version.\n //\n // For audio (where frame.type is not set) we do not encrypt the opus TOC byte:\n // https://tools.ietf.org/html/rfc6716#section-3.1\n const unencryptedBytes = {\n key: 10,\n delta: 3,\n undefined: 1 // frame.type is not set on audio\n };\n\n // An array (ring) of keys that we use for sending and receiving.\n const cryptoKeyRing = new Array(keyRingSize);\n\n // A pointer to the currently used key.\n let currentKeyIndex = -1;\n\n // We keep track of how many frames we have sent per ssrc.\n // Starts with a random offset similar to the RTP sequence number.\n const sendCounts = new Map();\n\n // Salt used in key derivation\n // FIXME: We currently use the MUC room name for this which has the same lifetime\n // as this worker. While not (pseudo)random as recommended in\n // https://developer.mozilla.org/en-US/docs/Web/API/Pbkdf2Params\n // this is easily available and the same for all participants.\n // We currently do not enforce a minimum length of 16 bytes either.\n let salt;\n\n /**\n * Derives a AES-GCM key with 128 bits from the input using PBKDF2\n * The salt is configured in the constructor of this class.\n * @param {Uint8Array} keyBytes - Value to derive key from\n */\n async function deriveKey(keyBytes) {\n // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey\n const material = await crypto.subtle.importKey('raw', keyBytes,\n 'PBKDF2', false, [ 'deriveBits', 'deriveKey' ]);\n\n // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/deriveKey#PBKDF2\n return crypto.subtle.deriveKey({\n name: 'PBKDF2',\n salt,\n iterations: 100000,\n hash: 'SHA-256'\n }, material, {\n name: 'AES-GCM',\n length: 128\n }, false, [ 'encrypt', 'decrypt' ]);\n }\n\n /**\n * Construct the IV used for AES-GCM and sent (in plain) with the packet similar to\n * https://tools.ietf.org/html/rfc7714#section-8.1\n * It concatenates\n * - the 32 bit synchronization source (SSRC) given on the encoded frame,\n * - the 32 bit rtp timestamp given on the encoded frame,\n * - a send counter that is specific to the SSRC. Starts at a random number.\n * The send counter is essentially the pictureId but we currently have to implement this ourselves.\n * There is no XOR with a salt. Note that this IV leaks the SSRC to the receiver but since this is\n * randomly generated and SFUs may not rewrite this is considered acceptable.\n * The SSRC is used to allow demultiplexing multiple streams with the same key, as described in\n * https://tools.ietf.org/html/rfc3711#section-4.1.1\n * The RTP timestamp is 32 bits and advances by the codec clock rate (90khz for video, 48khz for\n * opus audio) every second. For video it rolls over roughly every 13 hours.\n * The send counter will advance at the frame rate (30fps for video, 50fps for 20ms opus audio)\n * every second. It will take a long time to roll over.\n *\n * See also https://developer.mozilla.org/en-US/docs/Web/API/AesGcmParams\n */\n function makeIV(synchronizationSource, timestamp) {\n const iv = new ArrayBuffer(ivLength);\n const ivView = new DataView(iv);\n\n // having to keep our own send count (similar to a picture id) is not ideal.\n if (!sendCounts.has(synchronizationSource)) {\n // Initialize with a random offset, similar to the RTP sequence number.\n sendCounts.set(synchronizationSource, Math.floor(Math.random() * 0xFFFF));\n }\n const sendCount = sendCounts.get(synchronizationSource);\n\n ivView.setUint32(0, synchronizationSource);\n ivView.setUint32(4, timestamp);\n ivView.setUint32(8, sendCount % 0xFFFF);\n\n sendCounts.set(synchronizationSource, sendCount + 1);\n\n return iv;\n }\n\n /**\n * Function that will be injected in a stream and will encrypt the given encoded frames.\n *\n * @param {RTCEncodedVideoFrame|RTCEncodedAudioFrame} encodedFrame - Encoded video frame.\n * @param {TransformStreamDefaultController} controller - TransportStreamController.\n *\n * The packet format is described below. One of the design goals was to not require\n * changes to the SFU which for video requires not encrypting the keyframe bit of VP8\n * as SFUs need to detect a keyframe (framemarking or the generic frame descriptor will\n * solve this eventually). This also \"hides\" that a client is using E2EE a bit.\n *\n * Note that this operates on the full frame, i.e. for VP8 the data described in\n * https://tools.ietf.org/html/rfc6386#section-9.1\n *\n * The VP8 payload descriptor described in\n * https://tools.ietf.org/html/rfc7741#section-4.2\n * is part of the RTP packet and not part of the frame and is not controllable by us.\n * This is fine as the SFU keeps having access to it for routing.\n *\n * The encrypted frame is formed as follows:\n * 1) Leave the first (10, 3, 1) bytes unencrypted, depending on the frame type and kind.\n * 2) Form the GCM IV for the frame as described above.\n * 3) Encrypt the rest of the frame using AES-GCM.\n * 4) Allocate space for the encrypted frame.\n * 5) Copy the unencrypted bytes to the start of the encrypted frame.\n * 6) Append the ciphertext to the encrypted frame.\n * 7) Append the IV.\n * 8) Append a single byte for the key identifier. TODO: we don't need all the bits.\n * 9) Enqueue the encrypted frame for sending.\n */\n function encodeFunction(encodedFrame, controller) {\n const keyIndex = currentKeyIndex % cryptoKeyRing.length;\n\n if (cryptoKeyRing[keyIndex]) {\n const iv = makeIV(encodedFrame.synchronizationSource, encodedFrame.timestamp);\n\n return crypto.subtle.encrypt({\n name: 'AES-GCM',\n iv,\n additionalData: new Uint8Array(encodedFrame.data, 0, unencryptedBytes[encodedFrame.type])\n }, cryptoKeyRing[keyIndex], new Uint8Array(encodedFrame.data, unencryptedBytes[encodedFrame.type]))\n .then(cipherText => {\n const newData = new ArrayBuffer(unencryptedBytes[encodedFrame.type] + cipherText.byteLength\n + iv.byteLength + 1);\n const newUint8 = new Uint8Array(newData);\n\n newUint8.set(\n new Uint8Array(encodedFrame.data, 0, unencryptedBytes[encodedFrame.type])); // copy first bytes.\n newUint8.set(\n new Uint8Array(cipherText), unencryptedBytes[encodedFrame.type]); // add ciphertext.\n newUint8.set(\n new Uint8Array(iv), unencryptedBytes[encodedFrame.type] + cipherText.byteLength); // append IV.\n newUint8[unencryptedBytes[encodedFrame.type] + cipherText.byteLength + ivLength]\n = keyIndex; // set key index.\n\n encodedFrame.data = newData;\n\n return controller.enqueue(encodedFrame);\n }, e => {\n console.error(e);\n\n // We are not enqueuing the frame here on purpose.\n });\n }\n\n /* NOTE WELL:\n * This will send unencrypted data (only protected by DTLS transport encryption) when no key is configured.\n * This is ok for demo purposes but should not be done once this becomes more relied upon.\n */\n controller.enqueue(encodedFrame);\n }\n\n /**\n * Function that will be injected in a stream and will decrypt the given encoded frames.\n *\n * @param {RTCEncodedVideoFrame|RTCEncodedAudioFrame} encodedFrame - Encoded video frame.\n * @param {TransformStreamDefaultController} controller - TransportStreamController.\n *\n * The decrypted frame is formed as follows:\n * 1) Extract the key index from the last byte of the encrypted frame.\n * If there is no key associated with the key index, the frame is enqueued for decoding\n * and these steps terminate.\n * 2) Determine the frame type in order to look up the number of unencrypted header bytes.\n * 2) Extract the 12-byte IV from its position near the end of the packet.\n * Note: the IV is treated as opaque and not reconstructed from the input.\n * 3) Decrypt the encrypted frame content after the unencrypted bytes using AES-GCM.\n * 4) Allocate space for the decrypted frame.\n * 5) Copy the unencrypted bytes from the start of the encrypted frame.\n * 6) Append the plaintext to the decrypted frame.\n * 7) Enqueue the decrypted frame for decoding.\n */\n function decodeFunction(encodedFrame, controller) {\n const data = new Uint8Array(encodedFrame.data);\n const keyIndex = data[encodedFrame.data.byteLength - 1];\n\n if (cryptoKeyRing[keyIndex]) {\n const iv = new Uint8Array(encodedFrame.data, encodedFrame.data.byteLength - ivLength - 1, ivLength);\n const cipherTextStart = unencryptedBytes[encodedFrame.type];\n const cipherTextLength = encodedFrame.data.byteLength - (unencryptedBytes[encodedFrame.type]\n + ivLength + 1);\n\n return crypto.subtle.decrypt({\n name: 'AES-GCM',\n iv,\n additionalData: new Uint8Array(encodedFrame.data, 0, unencryptedBytes[encodedFrame.type])\n }, cryptoKeyRing[keyIndex], new Uint8Array(encodedFrame.data, cipherTextStart, cipherTextLength))\n .then(plainText => {\n const newData = new ArrayBuffer(unencryptedBytes[encodedFrame.type] + plainText.byteLength);\n const newUint8 = new Uint8Array(newData);\n\n newUint8.set(new Uint8Array(encodedFrame.data, 0, unencryptedBytes[encodedFrame.type]));\n newUint8.set(new Uint8Array(plainText), unencryptedBytes[encodedFrame.type]);\n\n encodedFrame.data = newData;\n\n return controller.enqueue(encodedFrame);\n }, e => {\n // TODO: notify the application about error status.\n\n // TODO: For video we need a better strategy since we do not want to based any\n // non-error frames on a garbage keyframe.\n if (encodedFrame.type === undefined) { // audio, replace with silence.\n // audio, replace with silence.\n const newData = new ArrayBuffer(3);\n const newUint8 = new Uint8Array(newData);\n\n newUint8.set([ 0xd8, 0xff, 0xfe ]); // opus silence frame.\n encodedFrame.data = newData;\n controller.enqueue(encodedFrame);\n }\n });\n } else if (keyIndex >= cryptoKeyRing.length && cryptoKeyRing[currentKeyIndex % cryptoKeyRing.length]) {\n // If we are encrypting but don't have a key for the remote drop the frame.\n // This is a heuristic since we don't know whether a packet is encrypted,\n // do not have a checksum and do not have signaling for whether a remote participant does\n // encrypt or not.\n return;\n }\n\n // TODO: this just passes through to the decoder. Is that ok? If we don't know the key yet\n // we might want to buffer a bit but it is still unclear how to do that (and for how long etc).\n controller.enqueue(encodedFrame);\n }\n\n onmessage = async (event) => {\n const {operation} = event.data;\n if (operation === 'initialize') {\n salt = event.data.salt;\n } else if (operation === 'encode') {\n const {readableStream, writableStream} = event.data;\n const transformStream = new TransformStream({\n transform: encodeFunction,\n });\n readableStream\n .pipeThrough(transformStream)\n .pipeTo(writableStream);\n } else if (operation === 'decode') {\n const {readableStream, writableStream} = event.data;\n const transformStream = new TransformStream({\n transform: decodeFunction,\n });\n readableStream\n .pipeThrough(transformStream)\n .pipeTo(writableStream);\n } else if (operation === 'setKey') {\n const keyBytes = event.data.key;\n let key;\n if (keyBytes) {\n key = await deriveKey(keyBytes);\n } else {\n key = false;\n }\n currentKeyIndex++;\n cryptoKeyRing[currentKeyIndex % cryptoKeyRing.length] = key;\n } else {\n console.error('e2ee worker', operation);\n }\n };\n\n"],{type:"application/javascript"}))}},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return h});var r=n(4),i=n(7),o=n(57),a=n(2),s=n(5),c=Object(r.getLogger)(e),u="e2e-ping-request",d="e2e-ping-response",l=(function(){function e(t,n){_classCallCheck(this,e),this.participant=t,this.e2eping=n,this.id=t.getId(),this.requests={},this.lastRequestId=1,this.clearIntervals=this.clearIntervals.bind(this),this.sendRequest=this.sendRequest.bind(this),this.handleResponse=this.handleResponse.bind(this),this.maybeSendAnalytics=this.maybeSendAnalytics.bind(this),this.sendAnalytics=this.sendAnalytics.bind(this),n.isDataChannelOpen&&this.sendRequest(),this.pingInterval=window.setInterval(this.sendRequest,n.pingIntervalMs),this.analyticsInterval=window.setTimeout(this.maybeSendAnalytics,this.e2eping.analyticsIntervalMs)}return _createClass(e,[{key:"clearIntervals",value:function(){this.pingInterval&&window.clearInterval(this.pingInterval),this.analyticsInterval&&window.clearInterval(this.analyticsInterval)}},{key:"sendRequest",value:function(){var e=this.lastRequestId++,t={type:u,id:e};this.e2eping.sendMessage(t,this.id),this.requests[e]={id:e,timeSent:window.performance.now()}}},{key:"handleResponse",value:function(e){var t=this.requests[e.id];t&&(t.rtt=window.performance.now()-t.timeSent,this.e2eping.eventEmitter.emit(o.E2E_RTT_CHANGED,this.participant,t.rtt)),this.maybeSendAnalytics()}},{key:"maybeSendAnalytics",value:function(){var e,t,n=window.performance.now(),r=1/0;for(t in this.requests)this.requests.hasOwnProperty(t)&&((e=this.requests[t]).timeSent0&&this.analyticsIntervalMs "+t),this._conference.eventEmitter.emit(i.JVB121_STATUS,e,t))}}]),e})()}).call(this,"modules/event/Jvb121EventGenerator.js")},function(e,t,n){"use strict";(function(e){var r=n(4),i=n(0),o=n.n(i),a=n(67),s=n(46);function c(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var u=Object(r.getLogger)(e);t.a=(function(){function e(t){_classCallCheck(this,e),this._sessions={},this._chatRoom=t,this.onPresence=this.onPresence.bind(this),this._chatRoom.eventEmitter.addListener(o.a.PRESENCE_RECEIVED,this.onPresence)}return _createClass(e,[{key:"getSession",value:function(e){return this._sessions[e]}},{key:"onPresence",value:function(e){var t=e.fromHiddenDomain,n=e.presence;s.a.isFromFocus(n)?this._handleFocusPresence(n):t&&this._handleJibriPresence(n)}},{key:"startRecording",value:function(e){var t=this,n=new a.a((function(e){for(var t=1;t0){var a=i.stat("ipAddress")+"_"+i.stat("portNumber")+"_"+i.stat("priority");e.handleCandidateRtt(a,o,Number(i.stat("stunKeepaliveResponsesReceived")),Number(i.stat("stunKeepaliveRequestsSent")))}}var s=1/0;for(var c in e.candidates)e.candidates.hasOwnProperty(c)&&e.candidates[c].rtt>0&&(s=Math.min(s,e.candidates[c].rtt));e.rtts.push(s),e.rtts.length>6&&(e.rtts=e.rtts.splice(1,7)),e.rtt=Math.min.apply(Math,_toConsumableArray(e.rtts))})},this.getStatsIntervalMs)}},{key:"handleCandidateRtt",value:function(e,t,n,r){this.candidates[e]||(this.candidates[e]={rttTotal:0,responsesReceived:0,requestsSent:0,rtt:NaN});var i=t-this.candidates[e].rttTotal,o=n-this.candidates[e].responsesReceived,a=r-n-(this.candidates[e].requestsSent-this.candidates[e].responsesReceived),s=NaN;o>0&&0===a&&(s=i/o),this.candidates[e].rttTotal=t,this.candidates[e].responsesReceived=n,this.candidates[e].requestsSent=r,this.candidates[e].rtt=s}},{key:"stop",value:function(){this.getStatsInterval&&window.clearInterval(this.getStatsInterval),this.pc.close(),this.stopped=!0}}]),e})(),l=(function(){function e(t){var n=this;if(_classCallCheck(this,e),t&&t.enabled&&r.a.supportsLocalCandidateRttStatistics()){this.pcMonitors={},this.startPCMonitors=this.startPCMonitors.bind(this),this.sendAnalytics=this.sendAnalytics.bind(this),this.stop=this.stop.bind(this),this.analyticsInterval=null,this.stopped=!1;var i=t.initialDelay||6e4;c.info("Starting RTT monitor with an initial delay of "+i),window.setTimeout(function(){return n.startPCMonitors(t)},i)}}return _createClass(e,[{key:"startPCMonitors",value:function(e){var t=this;if(e.stunServers){if(!this.stopped){var n=e.getStatsInterval||1e4,r=e.analyticsInterval||n,i=n/Object.keys(e.stunServers).length,o=0;for(var a in e.stunServers)if(e.stunServers.hasOwnProperty(a)){var s=e.stunServers[a];this.pcMonitors[a]=new d(a,s,n,i*o),o++}window.setTimeout(function(){t.stopped||(t.analyticsInterval=window.setInterval(t.sendAnalytics,r))},1e3)}}else c.warn("No stun servers configured.")}},{key:"sendAnalytics",value:function(){var e={};for(var t in this.pcMonitors)if(this.pcMonitors.hasOwnProperty(t)){var n=this.pcMonitors[t].rtt;isNaN(n)||n===1/0||(e[t.replace("-","_")]=n)}s.a.sendAnalytics(Object(i.M)(e))}},{key:"stop",value:function(){for(var e in c.info("Stopping RttMonitor."),this.stopped=!0,this.pcMonitors)this.pcMonitors.hasOwnProperty(e)&&this.pcMonitors[e].stop();this.pcMonitors={},this.analyticsInterval&&window.clearInterval(this.analyticsInterval)}}]),e})()}).call(this,"modules/rttmonitor/rttmonitor.js")},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return v});var r=n(58),i=n.n(r),o=n(7),a=n(4),s=n(28),c=n(2),u=n(9),d=n(1),l=n(5),h=n(13),p=Object(a.getLogger)(e),f=(function(){function e(t){_classCallCheck(this,e),this.name=t,this.count=0,this.sum=0,this.samples=[]}return _createClass(e,[{key:"addNext",value:function(e){"number"!=typeof e?p.error(this.name+" - invalid value for idx: "+this.count,e):isNaN(e)||(this.sum+=e,this.samples.push(e),this.count+=1)}},{key:"calculate",value:function(){return this.sum/this.count}},{key:"appendReport",value:function(e){e[this.name+"_avg"]=this.calculate(),e[this.name+"_samples"]=JSON.stringify(this.samples)}},{key:"reset",value:function(){this.samples=[],this.sum=0,this.count=0}}]),e})(),m=(function(){function e(t,n,r){var i=this;_classCallCheck(this,e),this.isP2P=n,this._n=r,this._sampleIdx=0,this._avgRTT=new f("rtt"),this._avgRemoteRTTMap=new Map,this._avgRtpStatsReporter=t,this._avgEnd2EndRTT=void 0,this._onConnectionStats=function(e,t){i.isP2P===e.isP2P&&i._calculateAvgStats(t)};var o=t._conference;o.statistics.addConnectionStatsListener(this._onConnectionStats),this.isP2P||(this._onUserLeft=function(e){return i._avgRemoteRTTMap.delete(e)},o.on(c.USER_LEFT,this._onUserLeft),this._onRemoteStatsUpdated=function(e,t){return i._processRemoteStats(e,t)},o.on(s.REMOTE_STATS_UPDATED,this._onRemoteStatsUpdated))}return _createClass(e,[{key:"_calculateAvgStats",value:function(e){if(e){if(d.a.supportsRTTStatistics()&&e.transport&&e.transport.length&&this._avgRTT.addNext(e.transport[0].rtt),this._sampleIdx+=1,this._sampleIdx>=this._n){if(d.a.supportsRTTStatistics()){var t=this._avgRtpStatsReporter._conference,n={p2p:this.isP2P,conference_size:t.getParticipantCount()};if(e.transport&&e.transport.length&&_extends(n,{local_candidate_type:e.transport[0].localCandidateType,remote_candidate_type:e.transport[0].remoteCandidateType,transport_type:e.transport[0].type}),this._avgRTT.appendReport(n),this.isP2P){var r=this._avgRtpStatsReporter.jvbStatsMonitor._avgEnd2EndRTT;isNaN(r)||(n.rtt_diff=this._avgRTT.calculate()-r)}else{var i=this._calculateAvgRemoteRTT(),a=this._avgRTT.calculate();this._avgEnd2EndRTT=a+i,isNaN(a)||isNaN(i)||(n.end2end_rtt_avg=this._avgEnd2EndRTT)}l.a.sendAnalytics(Object(o.L)(n))}this._resetAvgStats()}}else p.error("No stats")}},{key:"_calculateAvgRemoteRTT",value:function(){var e=0,t=0,n=this._avgRemoteRTTMap.values(),r=Array.isArray(n),i=0;for(n=r?n:n["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var o;if(r){if(i>=n.length)break;o=n[i++]}else{if((i=n.next()).done)break;o=i.value}var a=o,s=a.calculate();isNaN(s)||(t+=s,e+=1,a.reset())}return t/e}},{key:"_processRemoteStats",value:function(e,t){var n="number"==typeof t.jvbRTT,r=this._avgRemoteRTTMap.get(e);!r&&n&&(r=new f(e+"_stat_rtt"),this._avgRemoteRTTMap.set(e,r)),n?r.addNext(t.jvbRTT):r&&this._avgRemoteRTTMap.delete(e)}},{key:"_resetAvgStats",value:function(){this._avgRTT.reset(),this._avgRemoteRTTMap&&this._avgRemoteRTTMap.clear(),this._sampleIdx=0}},{key:"dispose",value:function(){var e=this._avgRtpStatsReporter._conference;e.statistics.removeConnectionStatsListener(this._onConnectionStats),this.isP2P||(e.off(s.REMOTE_STATS_UPDATED,this._onRemoteStatsUpdated),e.off(c.USER_LEFT,this._onUserLeft))}}]),e})(),v=(function(){function e(t,n){var r=this;_classCallCheck(this,e),this._n=n,n>0?(p.info("Avg RTP stats will be calculated every "+n+" samples"),this._sampleIdx=0,this._conference=t,this._avgAudioBitrateUp=new f("bitrate_audio_upload"),this._avgAudioBitrateDown=new f("bitrate_audio_download"),this._avgVideoBitrateUp=new f("bitrate_video_upload"),this._avgVideoBitrateDown=new f("bitrate_video_download"),this._avgBandwidthUp=new f("bandwidth_upload"),this._avgBandwidthDown=new f("bandwidth_download"),this._avgPacketLossTotal=new f("packet_loss_total"),this._avgPacketLossUp=new f("packet_loss_upload"),this._avgPacketLossDown=new f("packet_loss_download"),this._avgRemoteFPS=new f("framerate_remote"),this._avgRemoteScreenFPS=new f("framerate_screen_remote"),this._avgLocalFPS=new f("framerate_local"),this._avgLocalScreenFPS=new f("framerate_screen_local"),this._avgRemoteCameraPixels=new f("pixels_remote"),this._avgRemoteScreenPixels=new f("pixels_screen_remote"),this._avgLocalCameraPixels=new f("pixels_local"),this._avgLocalScreenPixels=new f("pixels_screen_local"),this._avgCQ=new f("connection_quality"),this._cachedTransportStats=void 0,this._onLocalStatsUpdated=function(e){r._calculateAvgStats(e),r._maybeSendTransportAnalyticsEvent(e)},t.on(s.LOCAL_STATS_UPDATED,this._onLocalStatsUpdated),this._onP2PStatusChanged=function(){p.debug("Resetting average stats calculation"),r._resetAvgStats(),r.jvbStatsMonitor._resetAvgStats(),r.p2pStatsMonitor._resetAvgStats()},t.on(c.P2P_STATUS,this._onP2PStatusChanged),this._onJvb121StatusChanged=function(e,t){!0===t&&(p.info("Resetting JVB avg RTP stats"),r._resetAvgJvbStats())},t.on(c.JVB121_STATUS,this._onJvb121StatusChanged),this.jvbStatsMonitor=new m(this,!1,n),this.p2pStatsMonitor=new m(this,!0,n)):p.info("Avg RTP stats reports are disabled.")}return _createClass(e,[{key:"_calculateAvgStats",value:function(e){if(e){var t=this._conference.isP2PActive(),n=this._conference.getParticipantCount();if(t||!(n<2)){var r=e.bitrate,i=e.bandwidth,a=e.packetLoss,s=e.framerate,c=e.resolution;if(r)if(i)if(a)if(s)if(c){if(this._avgAudioBitrateUp.addNext(r.audio.upload),this._avgAudioBitrateDown.addNext(r.audio.download),this._avgVideoBitrateUp.addNext(r.video.upload),this._avgVideoBitrateDown.addNext(r.video.download),d.a.supportsBandwidthStatistics()&&(this._avgBandwidthUp.addNext(i.upload),this._avgBandwidthDown.addNext(i.download)),this._avgPacketLossUp.addNext(a.upload),this._avgPacketLossDown.addNext(a.download),this._avgPacketLossTotal.addNext(a.total),this._avgCQ.addNext(e.connectionQuality),s&&(this._avgRemoteFPS.addNext(this._calculateAvgVideoFps(s,!1,h.CAMERA)),this._avgRemoteScreenFPS.addNext(this._calculateAvgVideoFps(s,!1,h.DESKTOP)),this._avgLocalFPS.addNext(this._calculateAvgVideoFps(s,!0,h.CAMERA)),this._avgLocalScreenFPS.addNext(this._calculateAvgVideoFps(s,!0,h.DESKTOP))),c&&(this._avgRemoteCameraPixels.addNext(this._calculateAvgVideoPixels(c,!1,h.CAMERA)),this._avgRemoteScreenPixels.addNext(this._calculateAvgVideoPixels(c,!1,h.DESKTOP)),this._avgLocalCameraPixels.addNext(this._calculateAvgVideoPixels(c,!0,h.CAMERA)),this._avgLocalScreenPixels.addNext(this._calculateAvgVideoPixels(c,!0,h.DESKTOP))),this._sampleIdx+=1,this._sampleIdx>=this._n){var u={p2p:t,conference_size:n};e.transport&&e.transport.length&&_extends(u,{local_candidate_type:e.transport[0].localCandidateType,remote_candidate_type:e.transport[0].remoteCandidateType,transport_type:e.transport[0].type}),this._avgAudioBitrateUp.appendReport(u),this._avgAudioBitrateDown.appendReport(u),this._avgVideoBitrateUp.appendReport(u),this._avgVideoBitrateDown.appendReport(u),d.a.supportsBandwidthStatistics()&&(this._avgBandwidthUp.appendReport(u),this._avgBandwidthDown.appendReport(u)),this._avgPacketLossUp.appendReport(u),this._avgPacketLossDown.appendReport(u),this._avgPacketLossTotal.appendReport(u),this._avgRemoteFPS.appendReport(u),isNaN(this._avgRemoteScreenFPS.calculate())||this._avgRemoteScreenFPS.appendReport(u),this._avgLocalFPS.appendReport(u),isNaN(this._avgLocalScreenFPS.calculate())||this._avgLocalScreenFPS.appendReport(u),this._avgRemoteCameraPixels.appendReport(u),isNaN(this._avgRemoteScreenPixels.calculate())||this._avgRemoteScreenPixels.appendReport(u),this._avgLocalCameraPixels.appendReport(u),isNaN(this._avgLocalScreenPixels.calculate())||this._avgLocalScreenPixels.appendReport(u),this._avgCQ.appendReport(u),l.a.sendAnalytics(Object(o.L)(u)),this._resetAvgStats()}}else p.error("No resolution");else p.error('No "framerate"');else p.error('No "packetloss"');else p.error('No "bandwidth"');else p.error('No "bitrate"')}}else p.error("No stats")}},{key:"_calculateAvgVideoPixels",value:function(e,t,n){for(var r=0,i=0,o=this._conference.myUserId(),a=Object.keys(e),s=0;s=c.length)break;h=c[l++]}else{if((l=c.next()).done)break;h=l.value}var p=h,f=Number(e[p].height)*Number(e[p].width);!isNaN(f)&&f>0&&(a+=f,s+=1)}return a/s}},{key:"_calculateAvgVideoFps",value:function(e,t,n){for(var r=0,i=0,o=this._conference.myUserId(),a=Object.keys(e),s=0;s=c.length)break;h=c[l++]}else{if((l=c.next()).done)break;h=l.value}var p=Number(e[h]);!isNaN(p)&&p>0&&(a+=p,s+=1)}return a/s}},{key:"_maybeSendTransportAnalyticsEvent",value:function(e){if(e&&e.transport&&e.transport.length){var t={p2p:e.transport[0].p2p,local_candidate_type:e.transport[0].localCandidateType,remote_candidate_type:e.transport[0].remoteCandidateType,transport_type:e.transport[0].type};this._cachedTransportStats&&i()(t,this._cachedTransportStats)||(this._cachedTransportStats=t,l.a.sendAnalytics(Object(o.N)(t)))}}},{key:"_resetAvgJvbStats",value:function(){this._resetAvgStats(),this.jvbStatsMonitor._resetAvgStats()}},{key:"_resetAvgStats",value:function(){this._avgAudioBitrateUp.reset(),this._avgAudioBitrateDown.reset(),this._avgVideoBitrateUp.reset(),this._avgVideoBitrateDown.reset(),this._avgBandwidthUp.reset(),this._avgBandwidthDown.reset(),this._avgPacketLossUp.reset(),this._avgPacketLossDown.reset(),this._avgPacketLossTotal.reset(),this._avgRemoteFPS.reset(),this._avgRemoteScreenFPS.reset(),this._avgLocalFPS.reset(),this._avgLocalScreenFPS.reset(),this._avgRemoteCameraPixels.reset(),this._avgRemoteScreenPixels.reset(),this._avgLocalCameraPixels.reset(),this._avgLocalScreenPixels.reset(),this._avgCQ.reset(),this._sampleIdx=0}},{key:"dispose",value:function(){this._conference.off(c.P2P_STATUS,this._onP2PStatusChanged),this._conference.off(s.LOCAL_STATS_UPDATED,this._onLocalStatsUpdated),this._conference.off(c.JVB121_STATUS,this._onJvb121StatusChanged),this.jvbStatsMonitor.dispose(),this.p2pStatsMonitor.dispose()}}]),e})()}).call(this,"modules/statistics/AvgRTPStatsReporter.js")},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return d});var r=n(4),i=n(2),o=n(28),a=n(9),s=n(7),c=n(5),u=Object(r.getLogger)(e),d=(function(){function e(t){_classCallCheck(this,e),this._conference=t,this._localAudioLevelCache={},this._reportedParticipants=[],this._audioProblemCandidates={},this._numberOfRemoteAudioLevelsReceived={},this._onLocalAudioLevelsReport=this._onLocalAudioLevelsReport.bind(this),this._onRemoteAudioLevelReceived=this._onRemoteAudioLevelReceived.bind(this),this._clearUserData=this._clearUserData.bind(this),this._conference.on(o.REMOTE_STATS_UPDATED,this._onRemoteAudioLevelReceived),this._conference.statistics.addConnectionStatsListener(this._onLocalAudioLevelsReport),this._conference.on(i.USER_LEFT,this._clearUserData)}return _createClass(e,[{key:"_onRemoteAudioLevelReceived",value:function(e,t){var n=t.avgAudioLevels,r=this._numberOfRemoteAudioLevelsReceived[e]+1||0;if(this._numberOfRemoteAudioLevelsReceived[e]=r,!(-1!==this._reportedParticipants.indexOf(e)||e in this._audioProblemCandidates||n<=0||r<3)){var i=this._conference.getParticipantById(e);if(!(i&&i.getTracksByMediaType(a.a).length>0&&i.isAudioMuted())){var o=this._localAudioLevelCache[e];Array.isArray(o)&&!o.every(function(e){return 0===e})||(this._audioProblemCandidates[e]={remoteAudioLevels:n,localAudioLevels:[]})}}}},{key:"_onLocalAudioLevelsReport",value:function(e,t){var n=this,r=t.avgAudioLevels;e===this._conference.getActivePeerConnection()&&(Object.keys(r).forEach(function(e){if(-1===n._reportedParticipants.indexOf(e)){var t=n._localAudioLevelCache[e];Array.isArray(t)?t.length>=2&&t.shift():n._localAudioLevelCache[e]=[],n._localAudioLevelCache[e].push(r[e])}}),Object.keys(this._audioProblemCandidates).forEach(function(e){var t=n._audioProblemCandidates[e],i=t.localAudioLevels,o=t.remoteAudioLevels;if(i.push(r[e]),2===i.length){if(i.every(function(e){return void 0===e||0===e})){var a=JSON.stringify(i);c.a.sendAnalytics(Object(s.x)(e,a,o)),u.warn("A potential problem is detected with the audio output for participant "+e+", local audio levels: "+a+", remote audio levels: "+o),n._reportedParticipants.push(e),n._clearUserData(e)}delete n._audioProblemCandidates[e]}}))}},{key:"_clearUserData",value:function(e){delete this._localAudioLevelCache[e]}},{key:"dispose",value:function(){this._conference.off(o.REMOTE_STATS_UPDATED,this._onRemoteAudioLevelReceived),this._conference.off(i.USER_LEFT,this._clearUserData),this._conference.statistics.removeConnectionStatsListener(this._onLocalAudioLevelsReport),this._localAudioLevelCache=void 0,this._audioProblemCandidates=void 0,this._reportedParticipants=void 0,this._numberOfRemoteAudioLevelsReceived=void 0,this._conference=void 0}}]),e})()}).call(this,"modules/statistics/AudioOutputProblemDetector.js")},function(e,t,n){"use strict";n.d(t,"a",function(){return c});var r=n(2),i=n(62),o=n.n(i),a=n(0),s=n.n(a),c=(function(){function e(t){_classCallCheck(this,e),this.stats={users:{},dominantSpeakerId:null};var n=t.myUserId();this.stats.users[n]=new o.a(n,null,!0),this.conference=t,t.addEventListener(r.DOMINANT_SPEAKER_CHANGED,this._onDominantSpeaker.bind(this)),t.addEventListener(r.USER_JOINED,this._onUserJoin.bind(this)),t.addEventListener(r.USER_LEFT,this._onUserLeave.bind(this)),t.addEventListener(r.DISPLAY_NAME_CHANGED,this._onDisplayNameChange.bind(this)),t.xmpp&&t.xmpp.addListener(s.a.SPEAKER_STATS_RECEIVED,this._updateStats.bind(this))}return _createClass(e,[{key:"_onDominantSpeaker",value:function(e){var t=this.stats.users[this.stats.dominantSpeakerId],n=this.stats.users[e];t&&t.setDominantSpeaker(!1),n&&n.setDominantSpeaker(!0),this.stats.dominantSpeakerId=e}},{key:"_onUserJoin",value:function(e,t){t.isHidden()||this.stats.users[e]||(this.stats.users[e]=new o.a(e,t.getDisplayName()))}},{key:"_onUserLeave",value:function(e){var t=this.stats.users[e];t&&t.markAsHasLeft()}},{key:"_onDisplayNameChange",value:function(e,t){var n=this.stats.users[e];n&&n.setDisplayName(t)}},{key:"getStats",value:function(){return this.stats.users}},{key:"_updateStats",value:function(e){for(var t in e){var n=void 0,r=this.conference.getParticipantById(t);r&&r.isHidden()||(this.stats.users[t]?(n=this.stats.users[t]).getDisplayName()||n.setDisplayName(e[t].displayName):(n=new o.a(t,e[t].displayName),this.stats.users[t]=n,n.markAsHasLeft())),n.totalDominantSpeakerTime=e[t].totalDominantSpeakerTime}}}]),e})()},function(e,t,n){var r=n(72),i=n(149),o="before";function a(){this.audioRecorder=new r,this.transcriptionService=new i,this.counter=null,this.startTime=null,this.transcription=null,this.callback=null,this.results=[],this.state=o,this.lineLength=0}function s(e,t){if(console.log("retrieved an answer from the transcription service. The answer has an array of length: "+t.wordArray.length),t.wordArray.length>0){var n=t.startTime.getUTCMilliseconds()-e.startTime.getUTCMilliseconds();n<0&&(n=0);var r="[";t.wordArray.forEach(function(e){e.begin+=n,e.end+=n,r+=e.word+","}),r+="]",console.log(r),t.wordArray.name=t.name}e.results.push(t.wordArray),e.counter--,console.log("current counter: "+e.counter),e.maybeMerge()}function c(e){for(var t=0;t0}a.prototype.start=function(){if(this.state!==o)throw new Error("The transcription can only start when it's in the \"before\" state. It's currently in the \""+this.state+"\" state");this.state="recording",this.audioRecorder.start(),this.startTime=new Date},a.prototype.stop=function(e){var t=this;if("recording"!==this.state)throw new Error("The transcription can only stop when it's in the \"recording\" state. It's currently in the \""+this.state+"\" state");console.log("stopping recording and sending audio files"),this.audioRecorder.stop();var n=s.bind(null,this);this.audioRecorder.getRecordingResults().forEach(function(e){t.transcriptionService.send(e,n),t.counter++}),this.state="transcribing",this.callback=e},a.prototype.maybeMerge=function(){"transcribing"===this.state&&0===this.counter&&this.merge()},a.prototype.merge=function(){var e=this;console.log("starting merge process!\n The length of the array: "+this.results.length),this.transcription="";var t=this.results,n=[],r=function(){var n=t[0];t.forEach(function(e){e[0].begin0;){if("break"===i())break}};for(c(t),t.forEach(function(e){return(function(e,t){if(0===e.length)e.push(t);else{if(e[e.length-1].begin<=t.begin)return void e.push(t);for(var n=0;n80&&(this.transcription+="\n ",this.lineLength=4),this.transcription+=" "+e.word,this.lineLength+=e.word.length+1},a.prototype.addTrack=function(e){this.audioRecorder.addTrack(e)},a.prototype.removeTrack=function(e){this.audioRecorder.removeTrack(e)},a.prototype.getTranscription=function(){if("finished"!==this.state)throw new Error("The transcription can only be retrieved when it's in the \"finished\" state. It's currently in the \""+this.state+"\" state");return this.transcription},a.prototype.getState=function(){return this.state},a.prototype.reset=function(){this.state=o,this.counter=null,this.transcription=null,this.startTime=null,this.callback=null,this.results=[],this.lineLength=0},e.exports=a},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return o});var r=n(5),i=n(4).getLogger(e);function o(e){this.versions={},this.conference=e,this.conference.addCommandListener("versions",this.processVersions.bind(this))}o.prototype.processVersions=function(e,t,n){var o=this;if(this.conference._isFocus(n)){var a=[];e.children.forEach(function(e){var t=e.attributes.name,n=e.value;o.versions[t]!==n&&(o.versions[t]=n,i.info("Got "+t+" version: "+n),a.push({id:"component_version",component:t,version:n}))}),a.length>0&&r.a.sendLog(JSON.stringify(a))}else i.warn("Received versions not from the focus user: "+e,n)},o.prototype.getComponentVersion=function(e){return this.versions[e]}}).call(this,"modules/version/ComponentsVersions.js")},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return u});var r=n(4),i=n(129),o=n(23),a=n(0),s=n.n(a),c=Object(r.getLogger)(e),u=(function(){function e(t){_classCallCheck(this,e),this.chatRoom=t,this.eventEmitter=t.eventEmitter,c.debug("creating VideoSIPGW"),this.sessions={},this.sessionStateChangeListener=this.sessionStateChanged.bind(this),t.addPresenceListener("jibri-sip-call-state",this.handleJibriSIPState.bind(this))}return _createClass(e,[{key:"handleJibriSIPState",value:function(e){var t=e.attributes;if(t){c.debug("Handle video sip gw state : ",t);var n=t.state;if(n!==this.state)switch(n){case o.STATE_ON:case o.STATE_OFF:case o.STATE_PENDING:case o.STATE_RETRYING:case o.STATE_FAILED:var r=t.sipaddress;if(!r)return;var i=this.sessions[r];i?i.setState(n,t.failure_reason):c.warn("Video SIP GW session not found:",r)}}}},{key:"createVideoSIPGWSession",value:function(e,t){if(this.sessions[e])return c.warn("There was already a Video SIP GW session for address",e),new Error(o.ERROR_SESSION_EXISTS);var n=new i.a(e,t,this.chatRoom);return n.addStateListener(this.sessionStateChangeListener),this.sessions[e]=n,n}},{key:"sessionStateChanged",value:function(e){var t=e.address;if(e.newState===o.STATE_OFF||e.newState===o.STATE_FAILED){var n=this.sessions[t];if(!n)return void c.error("Missing Video SIP GW session with address:",t);n.removeStateListener(this.sessionStateChangeListener),delete this.sessions[t]}this.eventEmitter.emit(s.a.VIDEO_SIP_GW_SESSION_STATE_CHANGED,e)}}]),e})()}).call(this,"modules/videosipgw/VideoSIPGW.js")},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return u});var r=n(4),i=n(3),o=n(24),a=n(23),s=Object(r.getLogger)(e),c="STATE_CHANGED",u=(function(e){function t(e,n,r){var i;return _classCallCheck(this,t),(i=_possibleConstructorReturn(this,_getPrototypeOf(t).call(this))).sipAddress=e,i.displayName=n,i.chatRoom=r,i.state=void 0,i}return _inherits(t,e),_createClass(t,[{key:"stop",value:function(){this.state!==a.STATE_OFF&&this.state!==a.STATE_FAILED?this._sendJibriIQ("stop"):s.warn("Video SIP GW session already stopped or failed!")}},{key:"start",value:function(){this.state!==a.STATE_ON&&this.state!==a.STATE_OFF&&this.state!==a.STATE_PENDING&&this.state!==a.STATE_RETRYING?this._sendJibriIQ("start"):s.warn("Video SIP GW session already started!")}},{key:"setState",value:function(e,t){if(e!==this.state){var n=this.state;this.state=e,this.eventEmitter.emit(c,{address:this.sipAddress,failureReason:t,oldState:n,newState:this.state,displayName:this.displayName})}}},{key:"addStateListener",value:function(e){this.addListener(c,e)}},{key:"removeStateListener",value:function(e){this.removeListener(c,e)}},{key:"_sendJibriIQ",value:function(e){var t=this,n={xmlns:"http://jitsi.org/protocol/jibri",action:e,sipaddress:this.sipAddress};n.displayname=this.displayName;var r=Object(i.$iq)({to:this.chatRoom.focusMucJid,type:"set"}).c("jibri",n).up();s.debug(e+" video SIP GW session",r.nodeTree),this.chatRoom.connection.sendIQ(r,function(){},function(n){s.error("Failed to "+e+" video SIP GW session, error: ",n),t.setState(a.STATE_FAILED)})}}]),t})(o.a)}).call(this,"modules/videosipgw/JitsiVideoSIPGWSession.js")},function(e,t,n){"use strict";t.a={error:{BUSY:"busy",ERROR:"error",RESOURCE_CONSTRAINT:"resource-constraint",SERVICE_UNAVAILABLE:"service-unavailable"},mode:{FILE:"file",STREAM:"stream"},status:{OFF:"off",ON:"on",PENDING:"pending"}}},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return m});var r=n(4),i=n(3),o=n(9),a=n(13),s=n.n(a),c=n(12),u=n(132),d=n(30);function l(e){for(var t=1;t=0||(i[n]=e[n]);return i})(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var f=Object(r.getLogger)(e),m=(function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};_classCallCheck(this,e);var n=t.jitsiConnection,r=p(t,["jitsiConnection"]);this._options=l({iceConfig:n&&n.xmpp.connection.jingle.p2pIceConfig},r),this._peerConnection=null,this._onFatalError=this._onFatalError.bind(this),this._onSendMessage=this._onSendMessage.bind(this),this._onRemoteStream=this._onRemoteStream.bind(this)}return _createClass(e,[{key:"processMessage",value:function(e){var t=e.from;if(t)if(this._peerConnection&&this._peerConnection.getPeerJid()!==t)this._onFatalError(t,d.a.CONNECTION_ERROR,"rejected");else{var n=this._convertStringToXML(e.data.iq),r=n&&n.find("jingle"),i=r&&r.attr("action");i===d.a.INITIATE&&(this._peerConnection=this._createPeerConnection(t,{isInitiator:!1,receiveVideo:!0})),this._peerConnection&&this._peerConnection.processMessage(r),i!==d.a.CONNECTION_ERROR&&i!==d.a.UNAVAILABLE&&i!==d.a.TERMINATE||this._selfCloseConnection()}}},{key:"start",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[];this._peerConnection=this._createPeerConnection(e,{isInitiator:!0,receiveVideo:!1}),this._peerConnection.start(t)}},{key:"stop",value:function(){this._peerConnection&&this._peerConnection.stop(),this._peerConnection=null}},{key:"_convertStringToXML",value:function(e){try{var t=(new DOMParser).parseFromString(e,"text/xml");return $(t)}catch(e){return f.error("Attempted to convert incorrectly formatted xml"),null}}},{key:"_createPeerConnection",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!e)throw new Error("Cannot create ProxyConnectionPC without a peer.");var n=l({iceConfig:this._options.iceConfig,onError:this._onFatalError,onRemoteStream:this._onRemoteStream,onSendMessage:this._onSendMessage,peerJid:e},t);return new u.a(n)}},{key:"_onFatalError",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";f.error("Received a proxy connection error",e,t,n);var r=Object(i.$iq)({to:e,type:"set"}).c("jingle",{xmlns:"urn:xmpp:jingle:1",action:t}).c("details").t(n).up();this._onSendMessage(e,r),this._peerConnection&&this._peerConnection.getPeerJid()===e&&this._selfCloseConnection()}},{key:"_onRemoteStream",value:function(e){if(!this._options.onRemoteStream)return f.error("Remote track received without callback."),void e.dispose();var t,n=e.isVideoTrack();n&&(t=this._options.convertVideoToDesktop?s.a.DESKTOP:s.a.CAMERA);var r=e.getOriginalStream(),i=c.a.newCreateLocalTracks([{deviceId:"proxy:"+this._peerConnection.getPeerJid(),mediaType:n?o.c:o.a,sourceType:"proxy",stream:r,track:r.getVideoTracks()[0],videoType:t}]);this._options.onRemoteStream(i[0])}},{key:"_onSendMessage",value:function(e,t){if(this._options.onSendMessage)try{var n=(new XMLSerializer).serializeToString(t.nodeTree||t);this._options.onSendMessage(e,{iq:n})}catch(e){f.error("Attempted to send an incorrectly formatted iq.")}}},{key:"_selfCloseConnection",value:function(){this.stop(),this._options.onConnectionClosed&&this._options.onConnectionClosed()}}]),e})()}).call(this,"modules/proxyconnection/ProxyConnectionService.js")},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return m});var r=n(4),i=n(12),o=n(8),a=n.n(o),s=n(0),c=n.n(s),u=n(47),d=n(37),l=n(30);function h(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:{};_classCallCheck(this,e),this._options=h({iceConfig:{},isInitiator:!1,receiveAudio:!1,receiveVideo:!1},t),this._tracks=[],this._peerConnection=null,this._onError=this._onError.bind(this),this._onRemoteStream=this._onRemoteStream.bind(this),this._onSendMessage=this._onSendMessage.bind(this)}return _createClass(e,[{key:"getPeerJid",value:function(){return this._options.peerJid}},{key:"processMessage",value:function(e){switch(e.attr("action")){case l.a.ACCEPT:this._onSessionAccept(e);break;case l.a.INITIATE:this._onSessionInitiate(e);break;case l.a.TERMINATE:this._onSessionTerminate(e);break;case l.a.TRANSPORT_INFO:this._onTransportInfo(e)}}},{key:"start",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];this._peerConnection||(this._tracks=this._tracks.concat(e),this._peerConnection=this._createPeerConnection(),this._peerConnection.invite(e))}},{key:"stop",value:function(){this._peerConnection&&this._peerConnection.terminate(),this._onSessionTerminate()}},{key:"_createPeerConnection",value:function(){var e=this,t={connected:!0,jingle:{terminate:function(){}},sendIQ:this._onSendMessage,addEventListener:function(){return function(){}}},n=h({iceServers:d.a},this._options.iceConfig),r={addPresenceListener:function(){},connectionTimes:[],eventEmitter:{emit:function(t){switch(t){case c.a.CONNECTION_ICE_FAILED:case c.a.CONNECTION_FAILED:e._onError(l.a.CONNECTION_ERROR,t)}}},getMediaPresenceInfo:function(){return{}},removePresenceListener:function(){}};this._rtc=new i.a({on:function(){}},{}),this._rtc.addListener(a.a.REMOTE_TRACK_ADDED,this._onRemoteStream);var o=new u.a(void 0,void 0,this._options.peerJid,t,{offerToReceiveAudio:this._options.receiveAudio,offerToReceiveVideo:this._options.receiveVideo},n,!0,this._options.isInitiator);return o.initialize(r,this._rtc,{}),o}},{key:"_onError",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";this._options.onError(this._options.peerJid,e,t)}},{key:"_onRemoteStream",value:function(e){this._tracks.push(e),this._options.onRemoteStream(e)}},{key:"_onSendMessage",value:function(e){this._options.onSendMessage(this._options.peerJid,e)}},{key:"_onSessionAccept",value:function(e){this._peerConnection?this._peerConnection.setAnswer(e):f.error("Received an answer when no peer connection exists.")}},{key:"_onSessionInitiate",value:function(e){var t=this;this._peerConnection?f.error("Received an offer when an offer was already sent."):(this._peerConnection=this._createPeerConnection(),this._peerConnection.acceptOffer(e,function(){},function(){return t._onError(t._options.peerJid,l.a.CONNECTION_ERROR,"session initiate error")}))}},{key:"_onSessionTerminate",value:function(){this._tracks.forEach(function(e){return e.dispose()}),this._tracks=[],this._peerConnection&&this._peerConnection.onTerminated(),this._rtc&&(this._rtc.removeListener(a.a.REMOTE_TRACK_ADDED,this._onRemoteStream),this._rtc.destroy())}},{key:"_onTransportInfo",value:function(e){this._peerConnection.addIceCandidates(e)}}]),e})()}).call(this,"modules/proxyconnection/ProxyConnectionPC.js")},function(e,t,n){"use strict";var r=n(49),i=n.n(r),o=n(22),a=n.n(o),s=function(e,t){return void 0!==e&&void 0!==e.media&&Array.isArray(e.media)&&e.media.forEach(function(e){e.sources&&e.sources.length&&(e.ssrcs=[],e.sources.forEach(function(t){Object.keys(t).forEach(function(n){"id"!==n&&e.ssrcs.push({id:t.id,attribute:n,value:t[n]})})}),delete e.sources),e.ssrcGroups&&e.ssrcGroups.length&&e.ssrcGroups.forEach(function(e){void 0!==e.ssrcs&&Array.isArray(e.ssrcs)&&(e.ssrcs=e.ssrcs.join(" "))})}),a.a.write(e,t)},c=function(e){var t=a.a.parse(e);return void 0!==t&&void 0!==t.media&&Array.isArray(t.media)&&t.media.forEach(function(e){void 0!==e.ssrcs&&Array.isArray(e.ssrcs)&&(e.sources=[],e.ssrcs.forEach(function(t){var n=e.sources.findIndex(function(e){return e.id===t.id});if(n>-1)e.sources[n][t.attribute]=t.value;else{var r={id:t.id};r[t.attribute]=t.value,e.sources.push(r)}}),delete e.ssrcs),void 0!==e.ssrcGroups&&Array.isArray(e.ssrcGroups)&&e.ssrcGroups.forEach(function(e){"string"==typeof e.ssrcs&&(e.ssrcs=e.ssrcs.split(" "))})}),t},u=["audio","video","data"],d=function(e){return e.find(function(e){return"SIM"===e.semantics})},l=function(e){return e.find(function(e){return"FID"===e.semantics})};function h(e,t,n,r){if(e&&t){var i=function(e){return r.find(function(t){return t.id.toString()===e})};t.ssrcs.forEach(function(t){e.sources.push(i(t));var r=n[parseInt(t,10)].find(function(e){return"FID"===e.semantics});if(r){var o=r.ssrcs.find(function(e){return e!==t});e.sources.push(i(o)),e.ssrcGroups.push(r)}}),e.ssrcGroups.push(t)}}function p(e,t,n,r){if(e&&t){if(e.sources=[],e.ssrcGroups=[],!n[t.id])return e.sources.push(t),void(e.msid=t.msid);var i=d(n[t.id]),o=l(n[t.id]);if(i)h(e,i,n,r);else if(o){var a=o.ssrcs.find(function(e){return e!==t}),s=d(n[a]);s?h(e,s,n,r):(o.ssrcs.forEach(function(t){e.sources.push((function(e){return r.find(function(t){return t.id.toString()===e})})(t))}),e.ssrcGroups.push(o))}e.msid=e.sources[0].msid}}function f(e,t,n){if(!n.find(function(t){return!!t.sources&&t.sources.some(function(t){return t.id===e.id})})){if(!t[e.id])return!1;var r=d(t[e.id]),i=l(t[e.id]);return r?n.some(function(e){return e.sources&&e.sources.some(function(e){return e.id.toString()===r.ssrcs[0]})}):!(!i||e.id.toString()===i.ssrcs[0])&&f({id:i.ssrcs[0]},t,n)}return!0}var m=(function(){function e(){_classCallCheck(this,e)}return _createClass(e,[{key:"toPlanB",value:function(e){if(!e||"string"!=typeof e.sdp)return console.warn("An empty description was passed as an argument."),e;var t=c(e.sdp);if(!t.media||!t.media.length)return console.warn("The description has no media."),e;if(t.media.every(function(e){return-1!==u.indexOf(e.mid)}))return console.warn("The description does not look like unified plan sdp"),e;var n={},r=t.media;t.media=[],r.forEach(function(e){var t=e.type;if("application"===t)return e.mid="data",void(n[e.mid]=e);if(void 0===n[t]){var r=i()(e);r.sources&&Array.isArray(r.sources)&&r.sources.forEach(function(t){e.msid?t.msid=e.msid:delete t.msid}),r.ssrcGroups||(r.ssrcGroups=[]),delete r.msid,r.mid=t,n[t]=r}else e.msid&&(e.sources&&Array.isArray(e.sources)&&(n[t].sources=n[t].sources.concat(e.sources)),void 0!==e.ssrcGroups&&Array.isArray(e.ssrcGroups)&&(n[t].ssrcGroups=n[t].ssrcGroups.concat(e.ssrcGroups)))}),t.media=Object.values(n);var o=[];Object.values(n).forEach(function(e){"inactive"!==e.direction&&o.push(e.mid)}),t.groups.forEach(function(e){"BUNDLE"===e.type&&(e.mids=o.join(" "))}),t.msidSemantic={semantic:"WMS",token:"*"};var a=s(t);return new RTCSessionDescription({type:e.type,sdp:a})}},{key:"toUnifiedPlan",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;if(!e||"string"!=typeof e.sdp)return console.warn("An empty description was passed as an argument."),e;var n=c(e.sdp);if(!n.media||!n.media.length)return console.warn("The description has no media."),e;if(n.media.length>3||n.media.every(function(e){return-1===u.indexOf(e.mid)}))return console.warn("The description does not look like plan-b"),e;var r=t?c(t.sdp):null,o={};n.media.forEach(function(e){var t=e.type;if("application"!==t){var n=(function(e){var t={};return e&&Array.isArray(e)?(e.forEach(function(e){e.ssrcs&&Array.isArray(e.ssrcs)&&e.ssrcs.forEach(function(n){void 0===t[n]&&(t[n]=[]),t[n].push(e)})}),t):t})(e.ssrcGroups);e.sources&&e.sources.forEach(function(a,s){if(a.msid){if(!r||!r.media){if(f(a,n,Object.values(o)))return;var c=i()(e);return c.mid=Object.keys(o).length.toString(),c.direction=s?"sendonly":"sendonly"===e.direction?"sendonly":"sendrecv",c.bundleOnly=void 0,p(c,a,n,e.sources),void(o[c.mid]=c)}if(!f(a,n,r.media)){var u=r.media.findIndex(function(e){return e.direction&&"inactive"===e.direction&&e.type===t});if(u>-1)r.media[u].direction="sendonly",p(r.media[u],a,n,e.sources);else{var d=i()(e);d.mid=r.media.length.toString(),d.direction="sendonly",p(d,a,n,e.sources),r.media.push(d)}}}})}else{if(!r||!r.media){var a=i()(e);return a.mid=Object.keys(o).length.toString(),void(o[e.mid]=a)}var s=r.media.findIndex(function(e){return e.type===t});s&&(r.media[s]=e,r.media[s].mid=s)}}),n.media=r?r.media:Object.values(o);var a=[];n.media.forEach(function(e){a.push(e.mid)}),n.groups.forEach(function(e){"BUNDLE"===e.type&&(e.mids=a.join(" "))}),n.msidSemantic={semantic:"WMS",token:"*"},n.origin.sessionVersion++;var d=s(n);return new RTCSessionDescription({type:e.type,sdp:d})}}]),e})();n.d(t,"a",function(){return m})},function(e,t,n){e.exports=n(135).default},function(e,t,n){"use strict";n.r(t),function(e){var r=n(73),i=n(85),o=n(21),a=n(56),s=n(7),c=n(86),u=n.n(c),d=n(28),l=n(57),h=n(11),p=n.n(h),f=n(19),m=n(2),v=n(87),g=n(39),y=n(25),_=n(68),S=n(48),E=n(17),b=n(14),C=n(15),T=n(60),A=n(52),R=n(4),k=n.n(R),w=n(9),I=n(31),P=n.n(I),D=n(44),O=n(12),N=n(1),M=n(53),L=n.n(M),x=n(130),F=n(131),j=n(5),U=n(23),H=k.a.getLogger(e);function J(e){var t={audio_requested:e.devices.includes("audio"),video_requested:e.devices.includes("video"),screen_sharing_requested:e.devices.includes("desktop")};return t.video_requested&&(t.resolution=e.resolution),t}t.default=(function(e){return"object"==typeof window.JitsiMeetJS?_extends({},window.JitsiMeetJS,e):e})({version:"development",JitsiConnection:v.a,ProxyConnectionService:F.a,constants:{participantConnectionStatus:D.a,recording:x.a,sipVideoGW:U,transcriptionStatus:T},events:{conference:m,connection:y,detection:o,track:C,mediaDevices:S,connectionQuality:d,e2eping:l},errors:{conference:f,connection:g,track:b},errorTypes:{JitsiTrackError:E.a},logLevels:k.a.levels,mediaDevices:_.a,analytics:j.a.analytics,init:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};j.a.init(e),window.connectionTimes||(window.connectionTimes={}),!0!==e.enableAnalyticsLogging&&(H.warn("Analytics disabled, disposing."),this.analytics.dispose()),e.enableWindowOnErrorHandler&&p.a.addHandler(this.getGlobalOnErrorHandler.bind(this));var t=e.deploymentInfo;if(t&&Object.keys(t).length>0){var n={};for(var r in t)t.hasOwnProperty(r)&&(n[r]=t[r]);n.id="deployment_info",j.a.sendLog(JSON.stringify(n))}if(this.version){var i={id:"component_version",component:"lib-jitsi-meet",version:this.version};j.a.sendLog(JSON.stringify(i))}return O.a.init(e)},isDesktopSharingEnabled:function(){return O.a.isDesktopSharingEnabled()},isWebRtcSupported:function(){return O.a.isWebRtcSupported()},setLogLevel:function(e){k.a.setLogLevel(e)},setLogLevelById:function(e,t){k.a.setLogLevelById(e,t)},addGlobalLogTransport:function(e){k.a.addGlobalTransport(e)},removeGlobalLogTransport:function(e){k.a.removeGlobalTransport(e)},setGlobalLogOptions:function(e){k.a.setGlobalOptions(e)},createLocalTracks:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=arguments.length>1?arguments[1]:void 0,r=arguments.length>2?arguments[2]:void 0,i=!1;return!0===n&&window.setTimeout(function(){i||_.a.emitEvent(S.PERMISSION_PROMPT_IS_SHOWN,N.a.getName())},1e3),window.connectionTimes||(window.connectionTimes={}),window.connectionTimes["obtainPermissions.start"]=window.performance.now(),O.a.obtainAudioAndVideoPermissions(t).then(function(n){if(i=!0,window.connectionTimes["obtainPermissions.end"]=window.performance.now(),j.a.sendAnalytics(Object(s.F)("success",J(t))),!O.a.options.disableAudioLevels)for(var r=function(e){var t=n[e],r=t.getOriginalStream();t.getType()===w.a&&(j.a.startLocalStats(r,t.setAudioLevel.bind(t)),t.addEventListener(C.LOCAL_TRACK_STOPPED,function(){j.a.stopLocalStats(r)}))},o=0;o=u.length)break;h=u[l++]}else{if((l=u.next()).done)break;h=l.value}var p=h;p.type===w.c&&"desktop"===p.videoType&&e.setVideoTrackContentHints(p.track,"detail")}return n}).catch(function(n){if(i=!0,n.name===b.UNSUPPORTED_RESOLUTION&&!N.a.usesNewGumFlow()){var o=t.resolution||"720",a=(function(e){if(!P.a[e])return null;var t=P.a[e].order,n=null,r=null;return Object.keys(P.a).forEach(function(e){var i=P.a[e];(!n||n.order=this.maxEntryLength&&this._flush(!0,!0)},i.prototype.start=function(){this._reschedulePublishInterval()},i.prototype._reschedulePublishInterval=function(){this.storeLogsIntervalID&&(window.clearTimeout(this.storeLogsIntervalID),this.storeLogsIntervalID=null),this.storeLogsIntervalID=window.setTimeout(this._flush.bind(this,!1,!0),this.storeInterval)},i.prototype.flush=function(){this._flush(!1,!0)},i.prototype._flush=function(e,t){this.totalLen>0&&(this.logStorage.isReady()||e)&&(this.logStorage.isReady()?(this.outputCache.length&&(this.outputCache.forEach(function(e){this.logStorage.storeLogs(e)}.bind(this)),this.outputCache=[]),this.logStorage.storeLogs(this.queue)):this.outputCache.push(this.queue),this.queue=[],this.totalLen=0),t&&this._reschedulePublishInterval()},i.prototype.stop=function(){this._flush(!1,!1)},e.exports=i},function(e,t){(function(t){e.exports=t}).call(this,{})},function(e,t,n){var r,i;this||window,void 0===(i="function"==typeof(r=function(){var e=/^(interactive|loaded|complete)$/,t=window.location?window.location.href:null,n=t&&t.replace(/#.*$/,"").replace(/\?.*$/,"")||null,r=document.getElementsByTagName("script"),i="readyState"in(r[0]||document.createElement("script")),o=!window.opera||"[object Opera]"!==window.opera.toString(),a="currentScript"in document;"stackTraceLimit"in Error&&Error.stackTraceLimit!==1/0&&(Error.stackTraceLimit,Error.stackTraceLimit=1/0);var s=!1,c=!1;function u(){if(0===r.length)return null;var t,d,l,h,p,f=[],m=u.skipStackDepth||1;for(t=0;t0?e(t.slice(t.indexOf(r[0])+r[0].length),n-1):r[1])),i})(l,m),f))&&n&&h===n&&(p=(function(e){var t,n,i=null;for(t=0,n=(e=e||r).length;t=r)return e;var i=n[t];switch(t+=1,e){case"%%":return"%";case"%s":return String(i);case"%d":return Number(i);case"%v":return""}})},a=function(e,t,n){var r=[e+"="+(t.format instanceof Function?t.format(t.push?n:n[t.name]):t.format)];if(t.names)for(var i=0;i2)return e;if(2==n&&0===r)return e;if(1===n)t=e.ssrcs[0].id;else{var i=e.ssrcGroups.filter(function(e){return"FID"===e.semantics})[0];if(!i)return e;t=parseInt(i.ssrcs.split(" ")[0])}return console.log("SdpSimulcast: current ssrc cache: ",this.ssrcCache),console.log("SdpSimulcast: parsed primary ssrc "+t),-1!==this.ssrcCache.indexOf(t)?(console.log("SdpSimulcast: Have seen primary ssrc before, filling in data from cache"),e=this._fillInSourceDataFromCache(e)):(console.log("SdpSimulcast: Have not seen primary ssrc before, generating source data"),e=this._generateSourceData(e,t)),this.ssrcCache=this._parseSimLayers(e),e},u.prototype.mungeRemoteDescription=function(e){if(!l(e))return e;var t=r.parse(e.sdp),n=this;return d(t,function(e){n.options.explodeRemoteSimulcast?(function(e){if(e&&Array.isArray(e.ssrcGroups))for(var t=o(e),n=[],r=e.ssrcGroups.length;r--;)if("SIM"===e.ssrcGroups[r].semantics){for(var i=e.ssrcGroups[r].ssrcs.split(" "),s=0;s=0)){var i=e[r];Object.keys(i).forEach(function(e){n.push({id:r,attribute:e,value:i[e]})})}})}return n},t.parseSsrcs=function(e){var t={};return void 0!==e.ssrcs&&Array.isArray(e.ssrcs)&&e.ssrcs.forEach(function(e){t[e.id]||(t[e.id]={}),t[e.id][e.attribute]=e.value}),t}},function(e,t,n){!(function(e){"use strict";e.Strophe.addConnectionPlugin("disco",{_connection:null,_identities:[],_features:[],_items:[],init:function(t){this._connection=t,this._identities=[],this._features=[],this._items=[],t.addHandler(this._onDiscoInfo.bind(this),e.Strophe.NS.DISCO_INFO,"iq","get",null,null),t.addHandler(this._onDiscoItems.bind(this),e.Strophe.NS.DISCO_ITEMS,"iq","get",null,null)},addIdentity:function(e,t,n,r){for(var i=0;i0,this._originalOnStreamFeaturesAfterSASL.apply(this._c,arguments)},statusChanged:function(t){if(this.getResumeToken()||t!==e.Strophe.Status.CONNECTED&&t!==e.Strophe.Status.DISCONNECTED)if(t===e.Strophe.Status.BINDREQUIRED){for(var n in this._c.jid=this._storedJid,this._resumeState)this._c[n]=this._resumeState[n];this._c.send(e.$build("resume",{xmlns:this._NS,h:this._clientProcessedStanzasCounter,previd:this._resumeToken})),this._c.flush()}else t===e.Strophe.Status.ERROR&&(this.logging&&e.Strophe.debug("SM cleared resume token on error"),this._resumeToken=void 0);else this.logging&&e.Strophe.debug("SM reset state"),this._serverProcesssedStanzasCounter=0,this._clientProcessedStanzasCounter=0,this._clientSentStanzasCounter=0,this._isStreamManagementEnabled=!1,this._requestResponseIntervalCount=0,this._resuming=!1,t===e.Strophe.Status.DISCONNECTED&&(this._isSupported=!1),this._unacknowledgedStanzas=[],this._requestHandler&&this._c.deleteHandler(this._requestHandler),this._incomingHandler&&this._c.deleteHandler(this._incomingHandler),this._requestHandler=this._c.addHandler(this._handleServerRequestHandler.bind(this),this._NS,"r"),this._ackHandler=this._c.addHandler(this._handleServerAck.bind(this),this._NS,"a"),this._incomingHandler=this._c.addHandler(this._incomingStanzaHandler.bind(this)),this._enabledHandler=this._c._addSysHandler(this._handleEnabled.bind(this),this._NS,"enabled"),this._resumeFailedHandler=this._c._addSysHandler(this._handleResumeFailed.bind(this),this._NS,"failed"),this._resumedHandler=this._c._addSysHandler(this._handleResumed.bind(this),this._NS,"resumed")},xmlOutput:function(t){return(e.Strophe.isTagEqual(t,"iq")||e.Strophe.isTagEqual(t,"presence")||e.Strophe.isTagEqual(t,"message"))&&this._increaseSentStanzasCounter(t),this._originalXMLOutput.call(this._c,t)},_handleEnabled:function(e){return this._isStreamManagementEnabled=!0,this._resumeToken="true"===e.getAttribute("resume")&&e.getAttribute("id"),this._c.resume(),!0},_handleResumeFailed:function(t){var n=t&&t.firstElementChild&&t.firstElementChild.tagName;return this._c._changeConnectStatus(e.Strophe.Status.ERROR,n,t),this._c._doDisconnect(),!0},_handleResumed:function(t){var n=parseInt(t.getAttribute("h"));if(this._handleAcknowledgedStanzas(n,this._serverProcesssedStanzasCounter),this._resuming=!1,this._c.do_bind=!1,this._c.authenticated=!0,this._c.restored=!0,this._unacknowledgedStanzas.length>0){this.logging&&e.Strophe.debug("SM Sending unacknowledged stanzas",this._unacknowledgedStanzas);var r=this._unacknowledgedStanzas,i=Array.isArray(r),o=0;for(r=i?r:r["function"==typeof Symbol?Symbol.iterator:"@@iterator"]();;){var a;if(i){if(o>=r.length)break;a=r[o++]}else{if((o=r.next()).done)break;a=o.value}var s=a;this._c.send(s)}}else this.logging&&e.Strophe.debug("SM No unacknowledged stanzas",this._unacknowledgedStanzas);return this._c._changeConnectStatus(e.Strophe.Status.CONNECTED,null),!0},_incomingStanzaHandler:function(t){return(e.Strophe.isTagEqual(t,"iq")||e.Strophe.isTagEqual(t,"presence")||e.Strophe.isTagEqual(t,"message"))&&(this._increaseReceivedStanzasCounter(),this.autoSendCountOnEveryIncomingStanza&&this._answerProcessedStanzas()),!0},_handleAcknowledgedStanzas:function(t,n){var r=t-n;r<0&&this._throwError("New reported stanza count lower than previous. New: "+t+" - Previous: "+n),r>this._unacknowledgedStanzas.length&&this._throwError("Higher reported acknowledge count than unacknowledged stanzas. Reported Acknowledge Count: "+r+" - Unacknowledge Stanza Count: "+this._unacknowledgedStanzas.length+" - New: "+t+" - Previous: "+n);for(var i=0;i0&&e.Strophe.warn("SM Unacknowledged stanzas",this._unacknowledgedStanzas),this._serverProcesssedStanzasCounter=t,this.requestResponseInterval>0&&(this._requestResponseIntervalCount=0)},_handleServerRequestHandler:function(){return this._answerProcessedStanzas(),!0},_handleServerAck:function(e){var t=parseInt(e.getAttribute("h"));return this._handleAcknowledgedStanzas(t,this._serverProcesssedStanzasCounter),!0},_answerProcessedStanzas:function(){this._isStreamManagementEnabled&&this._c.send(e.$build("a",{xmlns:this._NS,h:this._clientProcessedStanzasCounter}))},_increaseSentStanzasCounter:function(e){var t=this;if(this._isStreamManagementEnabled){if(-1!==this._unacknowledgedStanzas.indexOf(e))return;this._unacknowledgedStanzas.push(e),this._clientSentStanzasCounter++,this.requestResponseInterval>0&&(this._requestResponseIntervalCount++,this._requestResponseIntervalCount===this.requestResponseInterval&&setTimeout(function(){t.requestAcknowledgement()},1))}},_increaseReceivedStanzasCounter:function(){this._isStreamManagementEnabled&&this._clientProcessedStanzasCounter++},_throwError:function(t){throw e.Strophe.error(t),new Error(t)}})})(n(3))},function(e,t,n){(function(e){var r=void 0!==e&&e||"undefined"!=typeof self&&self||window,i=Function.prototype.apply;function o(e,t){this._id=e,this._clearFn=t}t.setTimeout=function(){return new o(i.call(setTimeout,r,arguments),clearTimeout)},t.setInterval=function(){return new o(i.call(setInterval,r,arguments),clearInterval)},t.clearTimeout=t.clearInterval=function(e){e&&e.close()},o.prototype.unref=o.prototype.ref=function(){},o.prototype.close=function(){this._clearFn.call(r,this._id)},t.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},t.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},t._unrefActive=t.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;t>=0&&(e._idleTimeoutId=setTimeout(function(){e._onTimeout&&e._onTimeout()},t))},n(147),t.setImmediate="undefined"!=typeof self&&self.setImmediate||void 0!==e&&e.setImmediate||this&&this.setImmediate,t.clearImmediate="undefined"!=typeof self&&self.clearImmediate||void 0!==e&&e.clearImmediate||this&&this.clearImmediate}).call(this,n(43))},function(e,t,n){(function(e,t){!(function(e,n){"use strict";if(!e.setImmediate){var r,i,o,a,s,c=1,u={},d=!1,l=e.document,h=Object.getPrototypeOf&&Object.getPrototypeOf(e);h=h&&h.setTimeout?h:e,"[object process]"==={}.toString.call(e.process)?r=function(e){t.nextTick(function(){f(e)})}:(function(){if(e.postMessage&&!e.importScripts){var t=!0,n=e.onmessage;return e.onmessage=function(){t=!1},e.postMessage("","*"),e.onmessage=n,t}})()?(a="setImmediate$"+Math.random()+"$",s=function(t){t.source===e&&"string"==typeof t.data&&0===t.data.indexOf(a)&&f(+t.data.slice(a.length))},e.addEventListener?e.addEventListener("message",s,!1):e.attachEvent("onmessage",s),r=function(t){e.postMessage(a+t,"*")}):e.MessageChannel?((o=new MessageChannel).port1.onmessage=function(e){f(e.data)},r=function(e){o.port2.postMessage(e)}):l&&"onreadystatechange"in l.createElement("script")?(i=l.documentElement,r=function(e){var t=l.createElement("script");t.onreadystatechange=function(){f(e),t.onreadystatechange=null,i.removeChild(t),t=null},i.appendChild(t)}):r=function(e){setTimeout(f,0,e)},h.setImmediate=function(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),n=0;n=n&&parseInt(r[n],10)}function l(e,t,n){if(e.RTCPeerConnection){var r=e.RTCPeerConnection.prototype,i=r.addEventListener;r.addEventListener=function(e,r){if(e!==t)return i.apply(this,arguments);var o=function(e){var t=n(e);t&&r(t)};return this._eventMap=this._eventMap||{},this._eventMap[r]=o,i.apply(this,[e,o])};var o=r.removeEventListener;r.removeEventListener=function(e,n){if(e!==t||!this._eventMap||!this._eventMap[n])return o.apply(this,arguments);var r=this._eventMap[n];return delete this._eventMap[n],o.apply(this,[e,r])},Object.defineProperty(r,"on"+t,{get:function(){return this["_on"+t]},set:function(e){this["_on"+t]&&(this.removeEventListener(t,this["_on"+t]),delete this["_on"+t]),e&&this.addEventListener(t,this["_on"+t]=e)},enumerable:!0,configurable:!0})}}function h(e){return"boolean"!=typeof e?new Error("Argument type: "+typeof e+". Please use a boolean."):(c=e,e?"adapter.js logging disabled":"adapter.js logging enabled")}function p(e){return"boolean"!=typeof e?new Error("Argument type: "+typeof e+". Please use a boolean."):(u=!e,"adapter.js deprecation warnings "+(e?"disabled":"enabled"))}function f(){if("object"==typeof window){if(c)return;"undefined"!=typeof console&&"function"==typeof console.log&&console.log.apply(console,arguments)}}function m(e,t){u&&console.warn(e+" is deprecated, please use "+t+" instead.")}function v(e){var t=e.navigator,n={browser:null,version:null};if(void 0===e||!e.navigator)return n.browser="Not a browser.",n;if(t.mozGetUserMedia)n.browser="firefox",n.version=d(t.userAgent,/Firefox\/(\d+)\./,1);else if(t.webkitGetUserMedia||!1===e.isSecureContext&&e.webkitRTCPeerConnection&&!e.RTCIceGatherer)n.browser="chrome",n.version=d(t.userAgent,/Chrom(e|ium)\/(\d+)\./,2);else if(t.mediaDevices&&t.userAgent.match(/Edge\/(\d+).(\d+)$/))n.browser="edge",n.version=d(t.userAgent,/Edge\/(\d+).(\d+)$/,2);else{if(!e.RTCPeerConnection||!t.userAgent.match(/AppleWebKit\/(\d+)\./))return n.browser="Not a supported browser.",n;n.browser="safari",n.version=d(t.userAgent,/AppleWebKit\/(\d+)\./,1),n.supportsUnifiedPlan=e.RTCRtpTransceiver&&"currentDirection"in e.RTCRtpTransceiver.prototype}return n}function g(e){return"[object Object]"===Object.prototype.toString.call(e)}function y(e){return g(e)?Object.keys(e).reduce(function(t,n){var r=g(e[n]),i=r?y(e[n]):e[n],o=r&&!Object.keys(i).length;return void 0===i||o?t:_extends(t,_defineProperty({},n,i))},{}):e}function _(e,t,n){var r=n?"outbound-rtp":"inbound-rtp",i=new Map;if(null===t)return i;var o=[];return e.forEach(function(e){"track"===e.type&&e.trackIdentifier===t.id&&o.push(e)}),o.forEach(function(t){e.forEach(function(n){n.type===r&&n.trackId===t.id&&(function e(t,n,r){n&&!r.has(n.id)&&(r.set(n.id,n),Object.keys(n).forEach(function(i){i.endsWith("Id")?e(t,t.get(n[i]),r):i.endsWith("Ids")&&n[i].forEach(function(n){e(t,t.get(n),r)})}))})(e,n,i)})}),i}var S=f;function E(e){var t=e&&e.navigator;if(t.mediaDevices){var n=v(e),r=function(e){if("object"!=typeof e||e.mandatory||e.optional)return e;var t={};return Object.keys(e).forEach(function(n){if("require"!==n&&"advanced"!==n&&"mediaSource"!==n){var r="object"==typeof e[n]?e[n]:{ideal:e[n]};void 0!==r.exact&&"number"==typeof r.exact&&(r.min=r.max=r.exact);var i=function(e,t){return e?e+t.charAt(0).toUpperCase()+t.slice(1):"deviceId"===t?"sourceId":t};if(void 0!==r.ideal){t.optional=t.optional||[];var o={};"number"==typeof r.ideal?(o[i("min",n)]=r.ideal,t.optional.push(o),(o={})[i("max",n)]=r.ideal,t.optional.push(o)):(o[i("",n)]=r.ideal,t.optional.push(o))}void 0!==r.exact&&"number"!=typeof r.exact?(t.mandatory=t.mandatory||{},t.mandatory[i("",n)]=r.exact):["min","max"].forEach(function(e){void 0!==r[e]&&(t.mandatory=t.mandatory||{},t.mandatory[i(e,n)]=r[e])})}}),e.advanced&&(t.optional=(t.optional||[]).concat(e.advanced)),t},i=function(e,i){if(n.version>=61)return i(e);if((e=JSON.parse(JSON.stringify(e)))&&"object"==typeof e.audio){var o=function(e,t,n){t in e&&!(n in e)&&(e[n]=e[t],delete e[t])};o((e=JSON.parse(JSON.stringify(e))).audio,"autoGainControl","googAutoGainControl"),o(e.audio,"noiseSuppression","googNoiseSuppression"),e.audio=r(e.audio)}if(e&&"object"==typeof e.video){var a=e.video.facingMode;a=a&&("object"==typeof a?a:{ideal:a});var s,c=n.version<66;if(a&&("user"===a.exact||"environment"===a.exact||"user"===a.ideal||"environment"===a.ideal)&&(!t.mediaDevices.getSupportedConstraints||!t.mediaDevices.getSupportedConstraints().facingMode||c))if(delete e.video.facingMode,"environment"===a.exact||"environment"===a.ideal?s=["back","rear"]:"user"!==a.exact&&"user"!==a.ideal||(s=["front"]),s)return t.mediaDevices.enumerateDevices().then(function(t){var n=(t=t.filter(function(e){return"videoinput"===e.kind})).find(function(e){return s.some(function(t){return e.label.toLowerCase().includes(t)})});return!n&&t.length&&s.includes("back")&&(n=t[t.length-1]),n&&(e.video.deviceId=a.exact?{exact:n.deviceId}:{ideal:n.deviceId}),e.video=r(e.video),S("chrome: "+JSON.stringify(e)),i(e)});e.video=r(e.video)}return S("chrome: "+JSON.stringify(e)),i(e)},o=function(e){return n.version>=64?e:{name:{PermissionDeniedError:"NotAllowedError",PermissionDismissedError:"NotAllowedError",InvalidStateError:"NotAllowedError",DevicesNotFoundError:"NotFoundError",ConstraintNotSatisfiedError:"OverconstrainedError",TrackStartError:"NotReadableError",MediaDeviceFailedDueToShutdown:"NotAllowedError",MediaDeviceKillSwitchOn:"NotAllowedError",TabCaptureError:"AbortError",ScreenCaptureError:"AbortError",DeviceCaptureError:"AbortError"}[e.name]||e.name,message:e.message,constraint:e.constraint||e.constraintName,toString:function(){return this.name+(this.message&&": ")+this.message}}};if(t.getUserMedia=function(e,n,r){i(e,function(e){t.webkitGetUserMedia(e,n,function(e){r&&r(o(e))})})}.bind(t),t.mediaDevices.getUserMedia){var a=t.mediaDevices.getUserMedia.bind(t.mediaDevices);t.mediaDevices.getUserMedia=function(e){return i(e,function(e){return a(e).then(function(t){if(e.audio&&!t.getAudioTracks().length||e.video&&!t.getVideoTracks().length)throw t.getTracks().forEach(function(e){e.stop()}),new DOMException("","NotFoundError");return t},function(e){return Promise.reject(o(e))})})}}}}function b(e,t){e.navigator.mediaDevices&&"getDisplayMedia"in e.navigator.mediaDevices||e.navigator.mediaDevices&&("function"==typeof t?e.navigator.mediaDevices.getDisplayMedia=function(n){return t(n).then(function(t){var r=n.video&&n.video.width,i=n.video&&n.video.height,o=n.video&&n.video.frameRate;return n.video={mandatory:{chromeMediaSource:"desktop",chromeMediaSourceId:t,maxFrameRate:o||3}},r&&(n.video.mandatory.maxWidth=r),i&&(n.video.mandatory.maxHeight=i),e.navigator.mediaDevices.getUserMedia(n)})}:console.error("shimGetDisplayMedia: getSourceId argument is not a function"))}function C(e){e.MediaStream=e.MediaStream||e.webkitMediaStream}function T(e){if("object"!=typeof e||!e.RTCPeerConnection||"ontrack"in e.RTCPeerConnection.prototype)l(e,"track",function(e){return e.transceiver||Object.defineProperty(e,"transceiver",{value:{receiver:e.receiver}}),e});else{Object.defineProperty(e.RTCPeerConnection.prototype,"ontrack",{get:function(){return this._ontrack},set:function(e){this._ontrack&&this.removeEventListener("track",this._ontrack),this.addEventListener("track",this._ontrack=e)},enumerable:!0,configurable:!0});var t=e.RTCPeerConnection.prototype.setRemoteDescription;e.RTCPeerConnection.prototype.setRemoteDescription=function(){var n=this;return this._ontrackpoly||(this._ontrackpoly=function(t){t.stream.addEventListener("addtrack",function(r){var i;i=e.RTCPeerConnection.prototype.getReceivers?n.getReceivers().find(function(e){return e.track&&e.track.id===r.track.id}):{track:r.track};var o=new Event("track");o.track=r.track,o.receiver=i,o.transceiver={receiver:i},o.streams=[t.stream],n.dispatchEvent(o)}),t.stream.getTracks().forEach(function(r){var i;i=e.RTCPeerConnection.prototype.getReceivers?n.getReceivers().find(function(e){return e.track&&e.track.id===r.id}):{track:r};var o=new Event("track");o.track=r,o.receiver=i,o.transceiver={receiver:i},o.streams=[t.stream],n.dispatchEvent(o)})},this.addEventListener("addstream",this._ontrackpoly)),t.apply(this,arguments)}}}function A(e){if("object"==typeof e&&e.RTCPeerConnection&&!("getSenders"in e.RTCPeerConnection.prototype)&&"createDTMFSender"in e.RTCPeerConnection.prototype){var t=function(e,t){return{track:t,get dtmf(){return void 0===this._dtmf&&("audio"===t.kind?this._dtmf=e.createDTMFSender(t):this._dtmf=null),this._dtmf},_pc:e}};if(!e.RTCPeerConnection.prototype.getSenders){e.RTCPeerConnection.prototype.getSenders=function(){return this._senders=this._senders||[],this._senders.slice()};var n=e.RTCPeerConnection.prototype.addTrack;e.RTCPeerConnection.prototype.addTrack=function(e,r){var i=n.apply(this,arguments);return i||(i=t(this,e),this._senders.push(i)),i};var r=e.RTCPeerConnection.prototype.removeTrack;e.RTCPeerConnection.prototype.removeTrack=function(e){r.apply(this,arguments);var t=this._senders.indexOf(e);-1!==t&&this._senders.splice(t,1)}}var i=e.RTCPeerConnection.prototype.addStream;e.RTCPeerConnection.prototype.addStream=function(e){var n=this;this._senders=this._senders||[],i.apply(this,[e]),e.getTracks().forEach(function(e){n._senders.push(t(n,e))})};var o=e.RTCPeerConnection.prototype.removeStream;e.RTCPeerConnection.prototype.removeStream=function(e){var t=this;this._senders=this._senders||[],o.apply(this,[e]),e.getTracks().forEach(function(e){var n=t._senders.find(function(t){return t.track===e});n&&t._senders.splice(t._senders.indexOf(n),1)})}}else if("object"==typeof e&&e.RTCPeerConnection&&"getSenders"in e.RTCPeerConnection.prototype&&"createDTMFSender"in e.RTCPeerConnection.prototype&&e.RTCRtpSender&&!("dtmf"in e.RTCRtpSender.prototype)){var a=e.RTCPeerConnection.prototype.getSenders;e.RTCPeerConnection.prototype.getSenders=function(){var e=this,t=a.apply(this,[]);return t.forEach(function(t){return t._pc=e}),t},Object.defineProperty(e.RTCRtpSender.prototype,"dtmf",{get:function(){return void 0===this._dtmf&&("audio"===this.track.kind?this._dtmf=this._pc.createDTMFSender(this.track):this._dtmf=null),this._dtmf}})}}function R(e){if(e.RTCPeerConnection){var t=e.RTCPeerConnection.prototype.getStats;e.RTCPeerConnection.prototype.getStats=function(){var e=this,n=Array.prototype.slice.call(arguments),r=n[0],i=n[1],o=n[2];if(arguments.length>0&&"function"==typeof r)return t.apply(this,arguments);if(0===t.length&&(0===arguments.length||"function"!=typeof r))return t.apply(this,[]);var a=function(e){var t={};return e.result().forEach(function(e){var n={id:e.id,timestamp:e.timestamp,type:{localcandidate:"local-candidate",remotecandidate:"remote-candidate"}[e.type]||e.type};e.names().forEach(function(t){n[t]=e.stat(t)}),t[n.id]=n}),t},s=function(e){return new Map(Object.keys(e).map(function(t){return[t,e[t]]}))};if(arguments.length>=2){return t.apply(this,[function(e){i(s(a(e)))},r])}return new Promise(function(n,r){t.apply(e,[function(e){n(s(a(e)))},r])}).then(i,o)}}}function k(e){if("object"==typeof e&&e.RTCPeerConnection&&e.RTCRtpSender&&e.RTCRtpReceiver){if(!("getStats"in e.RTCRtpSender.prototype)){var t=e.RTCPeerConnection.prototype.getSenders;t&&(e.RTCPeerConnection.prototype.getSenders=function(){var e=this,n=t.apply(this,[]);return n.forEach(function(t){return t._pc=e}),n});var n=e.RTCPeerConnection.prototype.addTrack;n&&(e.RTCPeerConnection.prototype.addTrack=function(){var e=n.apply(this,arguments);return e._pc=this,e}),e.RTCRtpSender.prototype.getStats=function(){var e=this;return this._pc.getStats().then(function(t){return _(t,e.track,!0)})}}if(!("getStats"in e.RTCRtpReceiver.prototype)){var r=e.RTCPeerConnection.prototype.getReceivers;r&&(e.RTCPeerConnection.prototype.getReceivers=function(){var e=this,t=r.apply(this,[]);return t.forEach(function(t){return t._pc=e}),t}),l(e,"track",function(e){return e.receiver._pc=e.srcElement,e}),e.RTCRtpReceiver.prototype.getStats=function(){var e=this;return this._pc.getStats().then(function(t){return _(t,e.track,!1)})}}if("getStats"in e.RTCRtpSender.prototype&&"getStats"in e.RTCRtpReceiver.prototype){var i=e.RTCPeerConnection.prototype.getStats;e.RTCPeerConnection.prototype.getStats=function(){if(arguments.length>0&&arguments[0]instanceof e.MediaStreamTrack){var t,n,r,o=arguments[0];return this.getSenders().forEach(function(e){e.track===o&&(t?r=!0:t=e)}),this.getReceivers().forEach(function(e){return e.track===o&&(n?r=!0:n=e),e.track===o}),r||t&&n?Promise.reject(new DOMException("There are more than one sender or receiver for the track.","InvalidAccessError")):t?t.getStats():n?n.getStats():Promise.reject(new DOMException("There is no sender or receiver for the track.","InvalidAccessError"))}return i.apply(this,arguments)}}}}function w(e){e.RTCPeerConnection.prototype.getLocalStreams=function(){var e=this;return this._shimmedLocalStreams=this._shimmedLocalStreams||{},Object.keys(this._shimmedLocalStreams).map(function(t){return e._shimmedLocalStreams[t][0]})};var t=e.RTCPeerConnection.prototype.addTrack;e.RTCPeerConnection.prototype.addTrack=function(e,n){if(!n)return t.apply(this,arguments);this._shimmedLocalStreams=this._shimmedLocalStreams||{};var r=t.apply(this,arguments);return this._shimmedLocalStreams[n.id]?-1===this._shimmedLocalStreams[n.id].indexOf(r)&&this._shimmedLocalStreams[n.id].push(r):this._shimmedLocalStreams[n.id]=[n,r],r};var n=e.RTCPeerConnection.prototype.addStream;e.RTCPeerConnection.prototype.addStream=function(e){var t=this;this._shimmedLocalStreams=this._shimmedLocalStreams||{},e.getTracks().forEach(function(e){if(t.getSenders().find(function(t){return t.track===e}))throw new DOMException("Track already exists.","InvalidAccessError")});var r=this.getSenders();n.apply(this,arguments);var i=this.getSenders().filter(function(e){return-1===r.indexOf(e)});this._shimmedLocalStreams[e.id]=[e].concat(i)};var r=e.RTCPeerConnection.prototype.removeStream;e.RTCPeerConnection.prototype.removeStream=function(e){return this._shimmedLocalStreams=this._shimmedLocalStreams||{},delete this._shimmedLocalStreams[e.id],r.apply(this,arguments)};var i=e.RTCPeerConnection.prototype.removeTrack;e.RTCPeerConnection.prototype.removeTrack=function(e){var t=this;return this._shimmedLocalStreams=this._shimmedLocalStreams||{},e&&Object.keys(this._shimmedLocalStreams).forEach(function(n){var r=t._shimmedLocalStreams[n].indexOf(e);-1!==r&&t._shimmedLocalStreams[n].splice(r,1),1===t._shimmedLocalStreams[n].length&&delete t._shimmedLocalStreams[n]}),i.apply(this,arguments)}}function I(e){if(e.RTCPeerConnection){var t=v(e);if(e.RTCPeerConnection.prototype.addTrack&&t.version>=65)return w(e);var n=e.RTCPeerConnection.prototype.getLocalStreams;e.RTCPeerConnection.prototype.getLocalStreams=function(){var e=this,t=n.apply(this);return this._reverseStreams=this._reverseStreams||{},t.map(function(t){return e._reverseStreams[t.id]})};var r=e.RTCPeerConnection.prototype.addStream;e.RTCPeerConnection.prototype.addStream=function(t){var n=this;if(this._streams=this._streams||{},this._reverseStreams=this._reverseStreams||{},t.getTracks().forEach(function(e){if(n.getSenders().find(function(t){return t.track===e}))throw new DOMException("Track already exists.","InvalidAccessError")}),!this._reverseStreams[t.id]){var i=new e.MediaStream(t.getTracks());this._streams[t.id]=i,this._reverseStreams[i.id]=t,t=i}r.apply(this,[t])};var i=e.RTCPeerConnection.prototype.removeStream;e.RTCPeerConnection.prototype.removeStream=function(e){this._streams=this._streams||{},this._reverseStreams=this._reverseStreams||{},i.apply(this,[this._streams[e.id]||e]),delete this._reverseStreams[this._streams[e.id]?this._streams[e.id].id:e.id],delete this._streams[e.id]},e.RTCPeerConnection.prototype.addTrack=function(t,n){var r=this;if("closed"===this.signalingState)throw new DOMException("The RTCPeerConnection's signalingState is 'closed'.","InvalidStateError");var i=[].slice.call(arguments,1);if(1!==i.length||!i[0].getTracks().find(function(e){return e===t}))throw new DOMException("The adapter.js addTrack polyfill only supports a single stream which is associated with the specified track.","NotSupportedError");if(this.getSenders().find(function(e){return e.track===t}))throw new DOMException("Track already exists.","InvalidAccessError");this._streams=this._streams||{},this._reverseStreams=this._reverseStreams||{};var o=this._streams[n.id];if(o)o.addTrack(t),Promise.resolve().then(function(){r.dispatchEvent(new Event("negotiationneeded"))});else{var a=new e.MediaStream([t]);this._streams[n.id]=a,this._reverseStreams[a.id]=n,this.addStream(a)}return this.getSenders().find(function(e){return e.track===t})},["createOffer","createAnswer"].forEach(function(t){var n=e.RTCPeerConnection.prototype[t],r=_defineProperty({},t,function(){var e=this,t=arguments;return arguments.length&&"function"==typeof arguments[0]?n.apply(this,[function(n){var r=s(e,n);t[0].apply(null,[r])},function(e){t[1]&&t[1].apply(null,e)},arguments[2]]):n.apply(this,arguments).then(function(t){return s(e,t)})});e.RTCPeerConnection.prototype[t]=r[t]});var o=e.RTCPeerConnection.prototype.setLocalDescription;e.RTCPeerConnection.prototype.setLocalDescription=function(){return arguments.length&&arguments[0].type?(arguments[0]=(e=this,t=arguments[0],n=t.sdp,Object.keys(e._reverseStreams||[]).forEach(function(t){var r=e._reverseStreams[t],i=e._streams[r.id];n=n.replace(new RegExp(r.id,"g"),i.id)}),new RTCSessionDescription({type:t.type,sdp:n})),o.apply(this,arguments)):o.apply(this,arguments);var e,t,n};var a=Object.getOwnPropertyDescriptor(e.RTCPeerConnection.prototype,"localDescription");Object.defineProperty(e.RTCPeerConnection.prototype,"localDescription",{get:function(){var e=a.get.apply(this);return""===e.type?e:s(this,e)}}),e.RTCPeerConnection.prototype.removeTrack=function(e){var t,n=this;if("closed"===this.signalingState)throw new DOMException("The RTCPeerConnection's signalingState is 'closed'.","InvalidStateError");if(!e._pc)throw new DOMException("Argument 1 of RTCPeerConnection.removeTrack does not implement interface RTCRtpSender.","TypeError");if(e._pc!==this)throw new DOMException("Sender was not created by this connection.","InvalidAccessError");this._streams=this._streams||{},Object.keys(this._streams).forEach(function(r){n._streams[r].getTracks().find(function(t){return e.track===t})&&(t=n._streams[r])}),t&&(1===t.getTracks().length?this.removeStream(this._reverseStreams[t.id]):t.removeTrack(e.track),this.dispatchEvent(new Event("negotiationneeded")))}}function s(e,t){var n=t.sdp;return Object.keys(e._reverseStreams||[]).forEach(function(t){var r=e._reverseStreams[t],i=e._streams[r.id];n=n.replace(new RegExp(i.id,"g"),r.id)}),new RTCSessionDescription({type:t.type,sdp:n})}}function P(e){var t=v(e);if(!e.RTCPeerConnection&&e.webkitRTCPeerConnection&&(e.RTCPeerConnection=e.webkitRTCPeerConnection),e.RTCPeerConnection){var n=0===e.RTCPeerConnection.prototype.addIceCandidate.length;t.version<53&&["setLocalDescription","setRemoteDescription","addIceCandidate"].forEach(function(t){var n=e.RTCPeerConnection.prototype[t],r=_defineProperty({},t,function(){return arguments[0]=new("addIceCandidate"===t?e.RTCIceCandidate:e.RTCSessionDescription)(arguments[0]),n.apply(this,arguments)});e.RTCPeerConnection.prototype[t]=r[t]});var r=e.RTCPeerConnection.prototype.addIceCandidate;e.RTCPeerConnection.prototype.addIceCandidate=function(){return n||arguments[0]?t.version<78&&arguments[0]&&""===arguments[0].candidate?Promise.resolve():r.apply(this,arguments):(arguments[1]&&arguments[1].apply(null),Promise.resolve())}}}function D(e){l(e,"negotiationneeded",function(e){if("stable"===e.target.signalingState)return e})}var O=n(79),N=n.n(O);function M(e){var t=e&&e.navigator,n=t.mediaDevices.getUserMedia.bind(t.mediaDevices);t.mediaDevices.getUserMedia=function(e){return n(e).catch(function(e){return Promise.reject((function(e){return{name:{PermissionDeniedError:"NotAllowedError"}[e.name]||e.name,message:e.message,constraint:e.constraint,toString:function(){return this.name}}})(e))})}}function L(e){"getDisplayMedia"in e.navigator&&e.navigator.mediaDevices&&(e.navigator.mediaDevices&&"getDisplayMedia"in e.navigator.mediaDevices||(e.navigator.mediaDevices.getDisplayMedia=e.navigator.getDisplayMedia.bind(e.navigator)))}function x(e){var t=v(e);if(e.RTCIceGatherer&&(e.RTCIceCandidate||(e.RTCIceCandidate=function(e){return e}),e.RTCSessionDescription||(e.RTCSessionDescription=function(e){return e}),t.version<15025)){var n=Object.getOwnPropertyDescriptor(e.MediaStreamTrack.prototype,"enabled");Object.defineProperty(e.MediaStreamTrack.prototype,"enabled",{set:function(e){n.set.call(this,e);var t=new Event("enabled");t.enabled=e,this.dispatchEvent(t)}})}!e.RTCRtpSender||"dtmf"in e.RTCRtpSender.prototype||Object.defineProperty(e.RTCRtpSender.prototype,"dtmf",{get:function(){return void 0===this._dtmf&&("audio"===this.track.kind?this._dtmf=new e.RTCDtmfSender(this):"video"===this.track.kind&&(this._dtmf=null)),this._dtmf}}),e.RTCDtmfSender&&!e.RTCDTMFSender&&(e.RTCDTMFSender=e.RTCDtmfSender);var r=N()(e,t.version);e.RTCPeerConnection=function(e){return e&&e.iceServers&&(e.iceServers=(function(e,t){var n=!1;return(e=JSON.parse(JSON.stringify(e))).filter(function(e){if(e&&(e.urls||e.url)){var t=e.urls||e.url;e.url&&!e.urls&&m("RTCIceServer.url","RTCIceServer.urls");var r="string"==typeof t;return r&&(t=[t]),t=t.filter(function(e){if(0===e.indexOf("stun:"))return!1;var t=e.startsWith("turn")&&!e.startsWith("turn:[")&&e.includes("transport=udp");return t&&!n?(n=!0,!0):t&&!n}),delete e.url,e.urls=r?t[0]:t,!!t.length}})})(e.iceServers,t.version),f("ICE servers after filtering:",e.iceServers)),new r(e)},e.RTCPeerConnection.prototype=r.prototype}function F(e){!e.RTCRtpSender||"replaceTrack"in e.RTCRtpSender.prototype||(e.RTCRtpSender.prototype.replaceTrack=e.RTCRtpSender.prototype.setTrack)}function j(e){var t=v(e),n=e&&e.navigator,r=e&&e.MediaStreamTrack;if(n.getUserMedia=function(e,t,r){m("navigator.getUserMedia","navigator.mediaDevices.getUserMedia"),n.mediaDevices.getUserMedia(e).then(t,r)},!(t.version>55&&"autoGainControl"in n.mediaDevices.getSupportedConstraints())){var i=function(e,t,n){t in e&&!(n in e)&&(e[n]=e[t],delete e[t])},o=n.mediaDevices.getUserMedia.bind(n.mediaDevices);if(n.mediaDevices.getUserMedia=function(e){return"object"==typeof e&&"object"==typeof e.audio&&(e=JSON.parse(JSON.stringify(e)),i(e.audio,"autoGainControl","mozAutoGainControl"),i(e.audio,"noiseSuppression","mozNoiseSuppression")),o(e)},r&&r.prototype.getSettings){var a=r.prototype.getSettings;r.prototype.getSettings=function(){var e=a.apply(this,arguments);return i(e,"mozAutoGainControl","autoGainControl"),i(e,"mozNoiseSuppression","noiseSuppression"),e}}if(r&&r.prototype.applyConstraints){var s=r.prototype.applyConstraints;r.prototype.applyConstraints=function(e){return"audio"===this.kind&&"object"==typeof e&&(e=JSON.parse(JSON.stringify(e)),i(e,"autoGainControl","mozAutoGainControl"),i(e,"noiseSuppression","mozNoiseSuppression")),s.apply(this,[e])}}}}function U(e,t){e.navigator.mediaDevices&&"getDisplayMedia"in e.navigator.mediaDevices||e.navigator.mediaDevices&&(e.navigator.mediaDevices.getDisplayMedia=function(n){if(!n||!n.video){var r=new DOMException("getDisplayMedia without video constraints is undefined");return r.name="NotFoundError",r.code=8,Promise.reject(r)}return!0===n.video?n.video={mediaSource:t}:n.video.mediaSource=t,e.navigator.mediaDevices.getUserMedia(n)})}function H(e){"object"==typeof e&&e.RTCTrackEvent&&"receiver"in e.RTCTrackEvent.prototype&&!("transceiver"in e.RTCTrackEvent.prototype)&&Object.defineProperty(e.RTCTrackEvent.prototype,"transceiver",{get:function(){return{receiver:this.receiver}}})}function J(e){var t=v(e);if("object"==typeof e&&(e.RTCPeerConnection||e.mozRTCPeerConnection)){if(!e.RTCPeerConnection&&e.mozRTCPeerConnection&&(e.RTCPeerConnection=e.mozRTCPeerConnection),t.version<53&&["setLocalDescription","setRemoteDescription","addIceCandidate"].forEach(function(t){var n=e.RTCPeerConnection.prototype[t],r=_defineProperty({},t,function(){return arguments[0]=new("addIceCandidate"===t?e.RTCIceCandidate:e.RTCSessionDescription)(arguments[0]),n.apply(this,arguments)});e.RTCPeerConnection.prototype[t]=r[t]}),t.version<68){var n=e.RTCPeerConnection.prototype.addIceCandidate;e.RTCPeerConnection.prototype.addIceCandidate=function(){return arguments[0]?arguments[0]&&""===arguments[0].candidate?Promise.resolve():n.apply(this,arguments):(arguments[1]&&arguments[1].apply(null),Promise.resolve())}}var r={inboundrtp:"inbound-rtp",outboundrtp:"outbound-rtp",candidatepair:"candidate-pair",localcandidate:"local-candidate",remotecandidate:"remote-candidate"},i=e.RTCPeerConnection.prototype.getStats;e.RTCPeerConnection.prototype.getStats=function(){var e=Array.prototype.slice.call(arguments),n=e[0],o=e[1],a=e[2];return i.apply(this,[n||null]).then(function(e){if(t.version<53&&!o)try{e.forEach(function(e){e.type=r[e.type]||e.type})}catch(t){if("TypeError"!==t.name)throw t;e.forEach(function(t,n){e.set(n,_extends({},t,{type:r[t.type]||t.type}))})}return e}).then(o,a)}}}function B(e){if("object"==typeof e&&e.RTCPeerConnection&&e.RTCRtpSender&&!(e.RTCRtpSender&&"getStats"in e.RTCRtpSender.prototype)){var t=e.RTCPeerConnection.prototype.getSenders;t&&(e.RTCPeerConnection.prototype.getSenders=function(){var e=this,n=t.apply(this,[]);return n.forEach(function(t){return t._pc=e}),n});var n=e.RTCPeerConnection.prototype.addTrack;n&&(e.RTCPeerConnection.prototype.addTrack=function(){var e=n.apply(this,arguments);return e._pc=this,e}),e.RTCRtpSender.prototype.getStats=function(){return this.track?this._pc.getStats(this.track):Promise.resolve(new Map)}}}function G(e){if("object"==typeof e&&e.RTCPeerConnection&&e.RTCRtpSender&&!(e.RTCRtpSender&&"getStats"in e.RTCRtpReceiver.prototype)){var t=e.RTCPeerConnection.prototype.getReceivers;t&&(e.RTCPeerConnection.prototype.getReceivers=function(){var e=this,n=t.apply(this,[]);return n.forEach(function(t){return t._pc=e}),n}),l(e,"track",function(e){return e.receiver._pc=e.srcElement,e}),e.RTCRtpReceiver.prototype.getStats=function(){return this._pc.getStats(this.track)}}}function V(e){!e.RTCPeerConnection||"removeStream"in e.RTCPeerConnection.prototype||(e.RTCPeerConnection.prototype.removeStream=function(e){var t=this;m("removeStream","removeTrack"),this.getSenders().forEach(function(n){n.track&&e.getTracks().includes(n.track)&&t.removeTrack(n)})})}function q(e){e.DataChannel&&!e.RTCDataChannel&&(e.RTCDataChannel=e.DataChannel)}function K(e){if("object"==typeof e&&e.RTCPeerConnection){var t=e.RTCPeerConnection.prototype.addTransceiver;t&&(e.RTCPeerConnection.prototype.addTransceiver=function(){this.setParametersPromises=[];var e=arguments[1],n=e&&"sendEncodings"in e;n&&e.sendEncodings.forEach(function(e){if("rid"in e&&!/^[a-z0-9]{0,16}$/i.test(e.rid))throw new TypeError("Invalid RID value provided.");if("scaleResolutionDownBy"in e&&!(parseFloat(e.scaleResolutionDownBy)>=1))throw new RangeError("scale_resolution_down_by must be >= 1.0");if("maxFramerate"in e&&!(parseFloat(e.maxFramerate)>=0))throw new RangeError("max_framerate must be >= 0.0")});var r=t.apply(this,arguments);if(n){var i=r.sender,o=i.getParameters();"encodings"in o||(o.encodings=e.sendEncodings,this.setParametersPromises.push(i.setParameters(o).catch(function(){})))}return r})}}function z(e){if("object"==typeof e&&e.RTCPeerConnection){var t=e.RTCPeerConnection.prototype.createOffer;e.RTCPeerConnection.prototype.createOffer=function(){var e=this,n=arguments;return this.setParametersPromises&&this.setParametersPromises.length?Promise.all(this.setParametersPromises).then(function(){return t.apply(e,n)}).finally(function(){e.setParametersPromises=[]}):t.apply(this,arguments)}}}function W(e){if("object"==typeof e&&e.RTCPeerConnection){var t=e.RTCPeerConnection.prototype.createAnswer;e.RTCPeerConnection.prototype.createAnswer=function(){var e=this,n=arguments;return this.setParametersPromises&&this.setParametersPromises.length?Promise.all(this.setParametersPromises).then(function(){return t.apply(e,n)}).finally(function(){e.setParametersPromises=[]}):t.apply(this,arguments)}}}function $(e){if("object"==typeof e&&e.RTCPeerConnection){if("getLocalStreams"in e.RTCPeerConnection.prototype||(e.RTCPeerConnection.prototype.getLocalStreams=function(){return this._localStreams||(this._localStreams=[]),this._localStreams}),!("addStream"in e.RTCPeerConnection.prototype)){var t=e.RTCPeerConnection.prototype.addTrack;e.RTCPeerConnection.prototype.addStream=function(e){var n=this;this._localStreams||(this._localStreams=[]),this._localStreams.includes(e)||this._localStreams.push(e),e.getAudioTracks().forEach(function(r){return t.call(n,r,e)}),e.getVideoTracks().forEach(function(r){return t.call(n,r,e)})},e.RTCPeerConnection.prototype.addTrack=function(e){var n=arguments[1];return n&&(this._localStreams?this._localStreams.includes(n)||this._localStreams.push(n):this._localStreams=[n]),t.apply(this,arguments)}}"removeStream"in e.RTCPeerConnection.prototype||(e.RTCPeerConnection.prototype.removeStream=function(e){var t=this;this._localStreams||(this._localStreams=[]);var n=this._localStreams.indexOf(e);if(-1!==n){this._localStreams.splice(n,1);var r=e.getTracks();this.getSenders().forEach(function(e){r.includes(e.track)&&t.removeTrack(e)})}})}}function Q(e){if("object"==typeof e&&e.RTCPeerConnection&&("getRemoteStreams"in e.RTCPeerConnection.prototype||(e.RTCPeerConnection.prototype.getRemoteStreams=function(){return this._remoteStreams?this._remoteStreams:[]}),!("onaddstream"in e.RTCPeerConnection.prototype))){Object.defineProperty(e.RTCPeerConnection.prototype,"onaddstream",{get:function(){return this._onaddstream},set:function(e){var t=this;this._onaddstream&&(this.removeEventListener("addstream",this._onaddstream),this.removeEventListener("track",this._onaddstreampoly)),this.addEventListener("addstream",this._onaddstream=e),this.addEventListener("track",this._onaddstreampoly=function(e){e.streams.forEach(function(e){if(t._remoteStreams||(t._remoteStreams=[]),!t._remoteStreams.includes(e)){t._remoteStreams.push(e);var n=new Event("addstream");n.stream=e,t.dispatchEvent(n)}})})}});var t=e.RTCPeerConnection.prototype.setRemoteDescription;e.RTCPeerConnection.prototype.setRemoteDescription=function(){var e=this;return this._onaddstreampoly||this.addEventListener("track",this._onaddstreampoly=function(t){t.streams.forEach(function(t){if(e._remoteStreams||(e._remoteStreams=[]),!(e._remoteStreams.indexOf(t)>=0)){e._remoteStreams.push(t);var n=new Event("addstream");n.stream=t,e.dispatchEvent(n)}})}),t.apply(e,arguments)}}}function X(e){if("object"==typeof e&&e.RTCPeerConnection){var t=e.RTCPeerConnection.prototype,n=t.createOffer,r=t.createAnswer,i=t.setLocalDescription,o=t.setRemoteDescription,a=t.addIceCandidate;t.createOffer=function(e,t){var r=arguments.length>=2?arguments[2]:arguments[0],i=n.apply(this,[r]);return t?(i.then(e,t),Promise.resolve()):i},t.createAnswer=function(e,t){var n=arguments.length>=2?arguments[2]:arguments[0],i=r.apply(this,[n]);return t?(i.then(e,t),Promise.resolve()):i};var s=function(e,t,n){var r=i.apply(this,[e]);return n?(r.then(t,n),Promise.resolve()):r};t.setLocalDescription=s,s=function(e,t,n){var r=o.apply(this,[e]);return n?(r.then(t,n),Promise.resolve()):r},t.setRemoteDescription=s,s=function(e,t,n){var r=a.apply(this,[e]);return n?(r.then(t,n),Promise.resolve()):r},t.addIceCandidate=s}}function Y(e){var t=e&&e.navigator;if(t.mediaDevices&&t.mediaDevices.getUserMedia){var n=t.mediaDevices,r=n.getUserMedia.bind(n);t.mediaDevices.getUserMedia=function(e){return r(Z(e))}}!t.getUserMedia&&t.mediaDevices&&t.mediaDevices.getUserMedia&&(t.getUserMedia=function(e,n,r){t.mediaDevices.getUserMedia(e).then(n,r)}.bind(t))}function Z(e){return e&&void 0!==e.video?_extends({},e,{video:y(e.video)}):e}function ee(e){var t=e.RTCPeerConnection;e.RTCPeerConnection=function(e,n){if(e&&e.iceServers){for(var r=[],i=0;i0?r=parseInt(i[0].substr(19),10):"firefox"===t.browser&&-1!==n&&(r=2147483637),r},a=e.RTCPeerConnection.prototype.setRemoteDescription;e.RTCPeerConnection.prototype.setRemoteDescription=function(){(this._sctp=null,"chrome"===t.browser&&t.version>=76)&&("plan-b"===this.getConfiguration().sdpSemantics&&Object.defineProperty(this,"sctp",{get:function(){return void 0===this._sctp?null:this._sctp},enumerable:!0,configurable:!0}));if(n(arguments[0])){var e,s=r(arguments[0]),c=i(s),u=o(arguments[0],s);e=0===c&&0===u?Number.POSITIVE_INFINITY:0===c||0===u?Math.max(c,u):Math.min(c,u);var d={};Object.defineProperty(d,"maxMessageSize",{get:function(){return e}}),this._sctp=d}return a.apply(this,arguments)}}}function se(e){if(e.RTCPeerConnection&&"createDataChannel"in e.RTCPeerConnection.prototype){var t=e.RTCPeerConnection.prototype.createDataChannel;e.RTCPeerConnection.prototype.createDataChannel=function(){var e=t.apply(this,arguments);return n(e,this),e},l(e,"datachannel",function(e){return n(e.channel,e.target),e})}function n(e,t){var n=e.send;e.send=function(){var r=arguments[0],i=r.length||r.size||r.byteLength;if("open"===e.readyState&&t.sctp&&i>t.sctp.maxMessageSize)throw new TypeError("Message too large (can send a maximum of "+t.sctp.maxMessageSize+" bytes)");return n.apply(e,arguments)}}}function ce(e){if(e.RTCPeerConnection&&!("connectionState"in e.RTCPeerConnection.prototype)){var t=e.RTCPeerConnection.prototype;Object.defineProperty(t,"connectionState",{get:function(){return{completed:"connected",checking:"connecting"}[this.iceConnectionState]||this.iceConnectionState},enumerable:!0,configurable:!0}),Object.defineProperty(t,"onconnectionstatechange",{get:function(){return this._onconnectionstatechange||null},set:function(e){this._onconnectionstatechange&&(this.removeEventListener("connectionstatechange",this._onconnectionstatechange),delete this._onconnectionstatechange),e&&this.addEventListener("connectionstatechange",this._onconnectionstatechange=e)},enumerable:!0,configurable:!0}),["setLocalDescription","setRemoteDescription"].forEach(function(e){var n=t[e];t[e]=function(){return this._connectionstatechangepoly||(this._connectionstatechangepoly=function(e){var t=e.target;if(t._lastConnectionState!==t.connectionState){t._lastConnectionState=t.connectionState;var n=new Event("connectionstatechange",e);t.dispatchEvent(n)}return e},this.addEventListener("iceconnectionstatechange",this._connectionstatechangepoly)),n.apply(this,arguments)}})}}function ue(e){if(e.RTCPeerConnection){var t=v(e);if(!("chrome"===t.browser&&t.version>=71)){var n=e.RTCPeerConnection.prototype.setRemoteDescription;e.RTCPeerConnection.prototype.setRemoteDescription=function(e){return e&&e.sdp&&-1!==e.sdp.indexOf("\na=extmap-allow-mixed")&&(e.sdp=e.sdp.split("\n").filter(function(e){return"a=extmap-allow-mixed"!==e.trim()}).join("\n")),n.apply(this,arguments)}}}}var de=(function(){var e=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}).window,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{shimChrome:!0,shimFirefox:!0,shimEdge:!0,shimSafari:!0},n=f,c=v(e),u={browserDetails:c,commonShim:s,extractVersion:d,disableLog:h,disableWarnings:p};switch(c.browser){case"chrome":if(!P||!t.shimChrome)return n("Chrome shim is not included in this adapter release."),u;n("adapter.js shimming chrome."),u.browserShim=r,E(e),C(e),P(e),T(e),I(e),A(e),R(e),k(e),D(e),oe(e),ce(e),ae(e),se(e),ue(e);break;case"firefox":if(!J||!t.shimFirefox)return n("Firefox shim is not included in this adapter release."),u;n("adapter.js shimming firefox."),u.browserShim=o,j(e),J(e),H(e),V(e),B(e),G(e),q(e),K(e),z(e),W(e),oe(e),ce(e),ae(e),se(e);break;case"edge":if(!x||!t.shimEdge)return n("MS edge shim is not included in this adapter release."),u;n("adapter.js shimming edge."),u.browserShim=i,M(e),L(e),x(e),F(e),ae(e),se(e);break;case"safari":if(!t.shimSafari)return n("Safari shim is not included in this adapter release."),u;n("adapter.js shimming safari."),u.browserShim=a,ee(e),ne(e),X(e),$(e),Q(e),te(e),Y(e),oe(e),ae(e),se(e),ue(e);break;default:n("Unsupported browser!")}return u})({window:window});t.default=de}])},"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.JitsiMeetJS=t():e.JitsiMeetJS=t()},466,[467,24,46,25,54,8,4,5,6,9,10,31]); -__d(function(g,r,i,a,m,e,d){m.exports=function(n){throw new Error("\""+n+"\" is read-only")}},467,[]); -__d(function(e,t,n,r,i,o,a){!(function(e,t){"use strict";"object"==typeof i&&"object"==typeof i.exports?i.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)})("undefined"!=typeof window?window:this,function(e,t){"use strict";var n=[],r=e.document,i=Object.getPrototypeOf,o=n.slice,a=n.concat,s=n.push,u=n.indexOf,l={},c=l.toString,f=l.hasOwnProperty,p=f.toString,d=p.call(Object),h={},g=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},v=function(e){return null!=e&&e===e.window},y={type:!0,src:!0,nonce:!0,noModule:!0};function m(e,t,n){var i,o,a=(n=n||r).createElement("script");if(a.text=e,t)for(i in y)(o=t[i]||t.getAttribute&&t.getAttribute(i))&&a.setAttribute(i,o);n.head.appendChild(a).parentNode.removeChild(a)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[c.call(e)]||"object":typeof e}var b=function e(t,n){return new e.fn.init(t,n)},w=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function T(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!g(e)&&!v(e)&&("array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e)}b.fn=b.prototype={jquery:"3.4.0",constructor:b,length:0,toArray:function(){return o.call(this)},get:function(e){return null==e?o.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=b.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return b.each(this,e)},map:function(e){return this.pushStack(b.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(o.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n+~]|[\\x20\\t\\r\\n\\f])[\\x20\\t\\r\\n\\f]*"),F=new RegExp("[\\x20\\t\\r\\n\\f]|>"),B=new RegExp(R),_=new RegExp("^(?:\\\\.|[\\w-]|[^\0-\\xa0])+$"),z={ID:new RegExp("^#((?:\\\\.|[\\w-]|[^\0-\\xa0])+)"),CLASS:new RegExp("^\\.((?:\\\\.|[\\w-]|[^\0-\\xa0])+)"),TAG:new RegExp("^((?:\\\\.|[\\w-]|[^\0-\\xa0])+|[*])"),ATTR:new RegExp("^\\[[\\x20\\t\\r\\n\\f]*((?:\\\\.|[\\w-]|[^\0-\\xa0])+)(?:[\\x20\\t\\r\\n\\f]*([*^$|!~]?=)[\\x20\\t\\r\\n\\f]*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|((?:\\\\.|[\\w-]|[^\0-\\xa0])+))|)[\\x20\\t\\r\\n\\f]*\\]"),PSEUDO:new RegExp("^:((?:\\\\.|[\\w-]|[^\0-\\xa0])+)(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|\\[[\\x20\\t\\r\\n\\f]*((?:\\\\.|[\\w-]|[^\0-\\xa0])+)(?:[\\x20\\t\\r\\n\\f]*([*^$|!~]?=)[\\x20\\t\\r\\n\\f]*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|((?:\\\\.|[\\w-]|[^\0-\\xa0])+))|)[\\x20\\t\\r\\n\\f]*\\])*)|.*)\\)|)"),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\([\\x20\\t\\r\\n\\f]*(even|odd|(([+-]|)(\\d*)n|)[\\x20\\t\\r\\n\\f]*(?:([+-]|)[\\x20\\t\\r\\n\\f]*(\\d+)|))[\\x20\\t\\r\\n\\f]*\\)|)","i"),bool:new RegExp("^(?:checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped)$","i"),needsContext:new RegExp("^[\\x20\\t\\r\\n\\f]*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\([\\x20\\t\\r\\n\\f]*((?:-\\d)?\\d*)[\\x20\\t\\r\\n\\f]*\\)|)(?=[^-]|$)","i")},U=/HTML$/i,X=/^(?:input|select|textarea|button)$/i,V=/^h\d$/i,G=/^[^{]+\{\s*\[native \w/,Y=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,Q=/[+~]/,J=new RegExp("\\\\([\\da-f]{1,6}[\\x20\\t\\r\\n\\f]?|([\\x20\\t\\r\\n\\f])|.)","ig"),K=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},Z=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ee=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},te=function(){p()},ne=ve(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(j=O.call(w.childNodes),w.childNodes),j[w.childNodes.length].nodeType}catch(e){H={apply:j.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}function re(e,t,r,i){var o,s,l,c,f,h,y,m=t&&t.ownerDocument,T=t?t.nodeType:9;if(r=r||[],"string"!=typeof e||!e||1!==T&&9!==T&&11!==T)return r;if(!i&&((t?t.ownerDocument||t:w)!==d&&p(t),t=t||d,g)){if(11!==T&&(f=Y.exec(e)))if(o=f[1]){if(9===T){if(!(l=t.getElementById(o)))return r;if(l.id===o)return r.push(l),r}else if(m&&(l=m.getElementById(o))&&x(t,l)&&l.id===o)return r.push(l),r}else{if(f[2])return H.apply(r,t.getElementsByTagName(e)),r;if((o=f[3])&&n.getElementsByClassName&&t.getElementsByClassName)return H.apply(r,t.getElementsByClassName(o)),r}if(n.qsa&&!A[e+" "]&&(!v||!v.test(e))&&(1!==T||"object"!==t.nodeName.toLowerCase())){if(y=e,m=t,1===T&&F.test(e)){for((c=t.getAttribute("id"))?c=c.replace(Z,ee):t.setAttribute("id",c=b),s=(h=a(e)).length;s--;)h[s]="#"+c+" "+ge(h[s]);y=h.join(","),m=Q.test(e)&&de(t.parentNode)||t}try{return H.apply(r,m.querySelectorAll(y)),r}catch(t){A(e,!0)}finally{c===b&&t.removeAttribute("id")}}}return u(e.replace(I,"$1"),t,r,i)}function ie(){var e=[];return function t(n,i){return e.push(n+" ")>r.cacheLength&&delete t[e.shift()],t[n+" "]=i}}function oe(e){return e[b]=!0,e}function ae(e){var t=d.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function se(e,t){for(var n=e.split("|"),i=n.length;i--;)r.attrHandle[n[i]]=t}function ue(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function le(e){return function(t){return"input"===t.nodeName.toLowerCase()&&t.type===e}}function ce(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function fe(e){return function(t){return"form"in t?t.parentNode&&!1===t.disabled?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&ne(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function pe(e){return oe(function(t){return t=+t,oe(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function de(e){return e&&void 0!==e.getElementsByTagName&&e}for(t in n=re.support={},o=re.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!U.test(t||n&&n.nodeName||"HTML")},p=re.setDocument=function(e){var t,i,a=e?e.ownerDocument||e:w;return a!==d&&9===a.nodeType&&a.documentElement?(h=(d=a).documentElement,g=!o(d),w!==d&&(i=d.defaultView)&&i.top!==i&&(i.addEventListener?i.addEventListener("unload",te,!1):i.attachEvent&&i.attachEvent("onunload",te)),n.attributes=ae(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ae(function(e){return e.appendChild(d.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=G.test(d.getElementsByClassName),n.getById=ae(function(e){return h.appendChild(e).id=b,!d.getElementsByName||!d.getElementsByName(b).length}),n.getById?(r.filter.ID=function(e){var t=e.replace(J,K);return function(e){return e.getAttribute("id")===t}},r.find.ID=function(e,t){if(void 0!==t.getElementById&&g){var n=t.getElementById(e);return n?[n]:[]}}):(r.filter.ID=function(e){var t=e.replace(J,K);return function(e){var n=void 0!==e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}},r.find.ID=function(e,t){if(void 0!==t.getElementById&&g){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];for(i=t.getElementsByName(e),r=0;o=i[r++];)if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),r.find.TAG=n.getElementsByTagName?function(e,t){return void 0!==t.getElementsByTagName?t.getElementsByTagName(e):n.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},r.find.CLASS=n.getElementsByClassName&&function(e,t){if(void 0!==t.getElementsByClassName&&g)return t.getElementsByClassName(e)},y=[],v=[],(n.qsa=G.test(d.querySelectorAll))&&(ae(function(e){h.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]=[\\x20\\t\\r\\n\\f]*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\[[\\x20\\t\\r\\n\\f]*(?:value|checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped)"),e.querySelectorAll("[id~="+b+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+b+"+*").length||v.push(".#.+[+~]")}),ae(function(e){e.innerHTML="";var t=d.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name[\\x20\\t\\r\\n\\f]*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),h.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(n.matchesSelector=G.test(m=h.matches||h.webkitMatchesSelector||h.mozMatchesSelector||h.oMatchesSelector||h.msMatchesSelector))&&ae(function(e){n.disconnectedMatch=m.call(e,"*"),m.call(e,"[s!='']:x"),y.push("!=",R)}),v=v.length&&new RegExp(v.join("|")),y=y.length&&new RegExp(y.join("|")),t=G.test(h.compareDocumentPosition),x=t||G.test(h.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},N=t?function(e,t){if(e===t)return f=!0,0;var r=!e.compareDocumentPosition-!t.compareDocumentPosition;return r||(1&(r=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!n.sortDetached&&t.compareDocumentPosition(e)===r?e===d||e.ownerDocument===w&&x(w,e)?-1:t===d||t.ownerDocument===w&&x(w,t)?1:c?P(c,e)-P(c,t):0:4&r?-1:1)}:function(e,t){if(e===t)return f=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===d?-1:t===d?1:i?-1:o?1:c?P(c,e)-P(c,t):0;if(i===o)return ue(e,t);for(n=e;n=n.parentNode;)a.unshift(n);for(n=t;n=n.parentNode;)s.unshift(n);for(;a[r]===s[r];)r++;return r?ue(a[r],s[r]):a[r]===w?-1:s[r]===w?1:0},d):d},re.matches=function(e,t){return re(e,null,null,t)},re.matchesSelector=function(e,t){if((e.ownerDocument||e)!==d&&p(e),n.matchesSelector&&g&&!A[t+" "]&&(!y||!y.test(t))&&(!v||!v.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(e){A(t,!0)}return re(t,d,null,[e]).length>0},re.contains=function(e,t){return(e.ownerDocument||e)!==d&&p(e),x(e,t)},re.attr=function(e,t){(e.ownerDocument||e)!==d&&p(e);var i=r.attrHandle[t.toLowerCase()],o=i&&D.call(r.attrHandle,t.toLowerCase())?i(e,t,!g):void 0;return void 0!==o?o:n.attributes||!g?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null},re.escape=function(e){return(e+"").replace(Z,ee)},re.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},re.uniqueSort=function(e){var t,r=[],i=0,o=0;if(f=!n.detectDuplicates,c=!n.sortStable&&e.slice(0),e.sort(N),f){for(;t=e[o++];)t===e[o]&&(i=r.push(o));for(;i--;)e.splice(r[i],1)}return c=null,e},i=re.getText=function(e){var t,n="",r=0,o=e.nodeType;if(o){if(1===o||9===o||11===o){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=i(e)}else if(3===o||4===o)return e.nodeValue}else for(;t=e[r++];)n+=i(t);return n},(r=re.selectors={cacheLength:50,createPseudo:oe,match:z,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(J,K),e[3]=(e[3]||e[4]||e[5]||"").replace(J,K),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||re.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&re.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return z.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&B.test(n)&&(t=a(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(J,K).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=E[e+" "];return t||(t=new RegExp("(^|[\\x20\\t\\r\\n\\f])"+e+"([\\x20\\t\\r\\n\\f]|$)"))&&E(e,function(e){return t.test("string"==typeof e.className&&e.className||void 0!==e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=re.attr(r,e);return null==i?"!="===t:!t||(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i.replace(M," ")+" ").indexOf(n)>-1:"|="===t&&(i===n||i.slice(0,n.length+1)===n+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,p,d,h,g=o!==a?"nextSibling":"previousSibling",v=t.parentNode,y=s&&t.nodeName.toLowerCase(),m=!u&&!s,x=!1;if(v){if(o){for(;g;){for(p=t;p=p[g];)if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?v.firstChild:v.lastChild],a&&m){for(x=(d=(l=(c=(f=(p=v)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1])&&l[2],p=d&&v.childNodes[d];p=++d&&p&&p[g]||(x=d=0)||h.pop();)if(1===p.nodeType&&++x&&p===t){c[e]=[T,d,x];break}}else if(m&&(x=d=(l=(c=(f=(p=t)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1]),!1===x)for(;(p=++d&&p&&p[g]||(x=d=0)||h.pop())&&((s?p.nodeName.toLowerCase()!==y:1!==p.nodeType)||!++x||(m&&((c=(f=p[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]=[T,x]),p!==t)););return(x-=i)===r||x%r==0&&x/r>=0}}},PSEUDO:function(e,t){var n,i=r.pseudos[e]||r.setFilters[e.toLowerCase()]||re.error("unsupported pseudo: "+e);return i[b]?i(t):i.length>1?(n=[e,e,"",t],r.setFilters.hasOwnProperty(e.toLowerCase())?oe(function(e,n){for(var r,o=i(e,t),a=o.length;a--;)e[r=P(e,o[a])]=!(n[r]=o[a])}):function(e){return i(e,0,n)}):i}},pseudos:{not:oe(function(e){var t=[],n=[],r=s(e.replace(I,"$1"));return r[b]?oe(function(e,t,n,i){for(var o,a=r(e,null,i,[]),s=e.length;s--;)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),t[0]=null,!n.pop()}}),has:oe(function(e){return function(t){return re(e,t).length>0}}),contains:oe(function(e){return e=e.replace(J,K),function(t){return(t.textContent||i(t)).indexOf(e)>-1}}),lang:oe(function(e){return _.test(e||"")||re.error("unsupported lang: "+e),e=e.replace(J,K).toLowerCase(),function(t){var n;do{if(n=g?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return(n=n.toLowerCase())===e||0===n.indexOf(e+"-")}while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===h},focus:function(e){return e===d.activeElement&&(!d.hasFocus||d.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:fe(!1),disabled:fe(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!r.pseudos.empty(e)},header:function(e){return V.test(e.nodeName)},input:function(e){return X.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:pe(function(){return[0]}),last:pe(function(e,t){return[t-1]}),eq:pe(function(e,t,n){return[n<0?n+t:n]}),even:pe(function(e,t){for(var n=0;nt?t:n;--r>=0;)e.push(r);return e}),gt:pe(function(e,t,n){for(var r=n<0?n+t:n;++r1?function(t,n,r){for(var i=e.length;i--;)if(!e[i](t,n,r))return!1;return!0}:e[0]}function me(e,t,n){for(var r=0,i=t.length;r-1&&(o[l]=!(a[l]=f))}}else y=xe(y===a?y.splice(h,y.length):y),i?i(null,a,y,u):H.apply(a,y)})}function we(e){for(var t,n,i,o=e.length,a=r.relative[e[0].type],s=a||r.relative[" "],u=a?1:0,c=ve(function(e){return e===t},s,!0),f=ve(function(e){return P(t,e)>-1},s,!0),p=[function(e,n,r){var i=!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):f(e,n,r));return t=null,i}];u1&&ye(p),u>1&&ge(e.slice(0,u-1).concat({value:" "===e[u-2].type?"*":""})).replace(I,"$1"),n,u0,i=e.length>0,o=function(o,a,s,u,c){var f,h,v,y=0,m="0",x=o&&[],b=[],w=l,C=o||i&&r.find.TAG("*",c),E=T+=null==w?1:Math.random()||.1,k=C.length;for(c&&(l=a===d||a||c);m!==k&&null!=(f=C[m]);m++){if(i&&f){for(h=0,a||f.ownerDocument===d||(p(f),s=!g);v=e[h++];)if(v(f,a||d,s)){u.push(f);break}c&&(T=E)}n&&((f=!v&&f)&&y--,o&&x.push(f))}if(y+=m,n&&m!==y){for(h=0;v=t[h++];)v(x,b,a,s);if(o){if(y>0)for(;m--;)x[m]||b[m]||(b[m]=q.call(u));b=xe(b)}H.apply(u,b),c&&!o&&b.length>0&&y+t.length>1&&re.uniqueSort(u)}return c&&(T=E,l=w),x};return n?oe(o):o}return he.prototype=r.filters=r.pseudos,r.setFilters=new he,a=re.tokenize=function(e,t){var n,i,o,a,s,u,l,c=k[e+" "];if(c)return t?0:c.slice(0);for(s=e,u=[],l=r.preFilter;s;){for(a in n&&!(i=W.exec(s))||(i&&(s=s.slice(i[0].length)||s),u.push(o=[])),n=!1,(i=$.exec(s))&&(n=i.shift(),o.push({value:n,type:i[0].replace(I," ")}),s=s.slice(n.length)),r.filter)!(i=z[a].exec(s))||l[a]&&!(i=l[a](i))||(n=i.shift(),o.push({value:n,type:a,matches:i}),s=s.slice(n.length));if(!n)break}return t?s.length:s?re.error(e):k(e,u).slice(0)},s=re.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){for(t||(t=a(e)),n=t.length;n--;)(o=we(t[n]))[b]?r.push(o):i.push(o);(o=S(e,Te(i,r))).selector=e}return o},u=re.select=function(e,t,n,i){var o,u,l,c,f,p="function"==typeof e&&e,d=!i&&a(e=p.selector||e);if(n=n||[],1===d.length){if((u=d[0]=d[0].slice(0)).length>2&&"ID"===(l=u[0]).type&&9===t.nodeType&&g&&r.relative[u[1].type]){if(!(t=(r.find.ID(l.matches[0].replace(J,K),t)||[])[0]))return n;p&&(t=t.parentNode),e=e.slice(u.shift().value.length)}for(o=z.needsContext.test(e)?0:u.length;o--&&(l=u[o],!r.relative[c=l.type]);)if((f=r.find[c])&&(i=f(l.matches[0].replace(J,K),Q.test(u[0].type)&&de(t.parentNode)||t))){if(u.splice(o,1),!(e=i.length&&ge(u)))return H.apply(n,i),n;break}}return(p||s(e,d))(i,t,!g,n,!t||Q.test(e)&&de(t.parentNode)||t),n},n.sortStable=b.split("").sort(N).join("")===b,n.detectDuplicates=!!f,p(),n.sortDetached=ae(function(e){return 1&e.compareDocumentPosition(d.createElement("fieldset"))}),ae(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||se("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ae(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||se("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ae(function(e){return null==e.getAttribute("disabled")})||se("checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),re})(e);b.find=C,b.expr=C.selectors,b.expr[":"]=b.expr.pseudos,b.uniqueSort=b.unique=C.uniqueSort,b.text=C.getText,b.isXMLDoc=C.isXML,b.contains=C.contains,b.escapeSelector=C.escape;var E=function(e,t,n){for(var r=[],i=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(i&&b(e).is(n))break;r.push(e)}return r},k=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},S=b.expr.match.needsContext;function A(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var N=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function D(e,t,n){return g(t)?b.grep(e,function(e,r){return!!t.call(e,r,e)!==n}):t.nodeType?b.grep(e,function(e){return e===t!==n}):"string"!=typeof t?b.grep(e,function(e){return u.call(t,e)>-1!==n}):b.filter(t,e,n)}b.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?b.find.matchesSelector(r,e)?[r]:[]:b.find.matches(e,b.grep(t,function(e){return 1===e.nodeType}))},b.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(b(e).filter(function(){for(t=0;t1?b.uniqueSort(n):n},filter:function(e){return this.pushStack(D(this,e||[],!1))},not:function(e){return this.pushStack(D(this,e||[],!0))},is:function(e){return!!D(this,"string"==typeof e&&S.test(e)?b(e):e||[],!1).length}});var j,q=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(b.fn.init=function(e,t,n){var i,o;if(!e)return this;if(n=n||j,"string"==typeof e){if(!(i="<"===e[0]&&">"===e[e.length-1]&&e.length>=3?[null,e,null]:q.exec(e))||!i[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(i[1]){if(t=t instanceof b?t[0]:t,b.merge(this,b.parseHTML(i[1],t&&t.nodeType?t.ownerDocument||t:r,!0)),N.test(i[1])&&b.isPlainObject(t))for(i in t)g(this[i])?this[i](t[i]):this.attr(i,t[i]);return this}return(o=r.getElementById(i[2]))&&(this[0]=o,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):g(e)?void 0!==n.ready?n.ready(e):e(b):b.makeArray(e,this)}).prototype=b.fn,j=b(r);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}b.fn.extend({has:function(e){var t=b(e,this),n=t.length;return this.filter(function(){for(var e=0;e-1:1===n.nodeType&&b.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?b.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?u.call(b(e),this[0]):u.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(b.uniqueSort(b.merge(this.get(),b(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),b.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return E(e,"parentNode")},parentsUntil:function(e,t,n){return E(e,"parentNode",n)},next:function(e){return O(e,"nextSibling")},prev:function(e){return O(e,"previousSibling")},nextAll:function(e){return E(e,"nextSibling")},prevAll:function(e){return E(e,"previousSibling")},nextUntil:function(e,t,n){return E(e,"nextSibling",n)},prevUntil:function(e,t,n){return E(e,"previousSibling",n)},siblings:function(e){return k((e.parentNode||{}).firstChild,e)},children:function(e){return k(e.firstChild)},contents:function(e){return void 0!==e.contentDocument?e.contentDocument:(A(e,"template")&&(e=e.content||e),b.merge([],e.childNodes))}},function(e,t){b.fn[e]=function(n,r){var i=b.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=b.filter(r,i)),this.length>1&&(H[e]||b.uniqueSort(i),L.test(e)&&i.reverse()),this.pushStack(i)}});var P=/[^\x20\t\r\n\f]+/g;function R(e){var t={};return b.each(e.match(P)||[],function(e,n){t[n]=!0}),t}function M(e){return e}function I(e){throw e}function W(e,t,n,r){var i;try{e&&g(i=e.promise)?i.call(e).done(t).fail(n):e&&g(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}b.Callbacks=function(e){e="string"==typeof e?R(e):b.extend({},e);var t,n,r,i,o=[],a=[],s=-1,u=function(){for(i=i||e.once,r=t=!0;a.length;s=-1)for(n=a.shift();++s-1;)o.splice(n,1),n<=s&&s--}),this},has:function(e){return e?b.inArray(e,o)>-1:o.length>0},empty:function(){return o&&(o=[]),this},disable:function(){return i=a=[],o=n="",this},disabled:function(){return!o},lock:function(){return i=a=[],n||t||(o=n=""),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=[e,(n=n||[]).slice?n.slice():n],a.push(n),t||u()),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!r}};return l},b.extend({Deferred:function(t){var n=[["notify","progress",b.Callbacks("memory"),b.Callbacks("memory"),2],["resolve","done",b.Callbacks("once memory"),b.Callbacks("once memory"),0,"resolved"],["reject","fail",b.Callbacks("once memory"),b.Callbacks("once memory"),1,"rejected"]],r="pending",i={state:function(){return r},always:function(){return o.done(arguments).fail(arguments),this},catch:function(e){return i.then(null,e)},pipe:function(){var e=arguments;return b.Deferred(function(t){b.each(n,function(n,r){var i=g(e[r[4]])&&e[r[4]];o[r[1]](function(){var e=i&&i.apply(this,arguments);e&&g(e.promise)?e.promise().progress(t.notify).done(t.resolve).fail(t.reject):t[r[0]+"With"](this,i?[e]:arguments)})}),e=null}).promise()},then:function(t,r,i){var o=0;function a(t,n,r,i){return function(){var s=this,u=arguments,l=function(){var e,l;if(!(t=o&&(r!==I&&(s=void 0,u=[e]),n.rejectWith(s,u))}};t?c():(b.Deferred.getStackHook&&(c.stackTrace=b.Deferred.getStackHook()),e.setTimeout(c))}}return b.Deferred(function(e){n[0][3].add(a(0,e,g(i)?i:M,e.notifyWith)),n[1][3].add(a(0,e,g(t)?t:M)),n[2][3].add(a(0,e,g(r)?r:I))}).promise()},promise:function(e){return null!=e?b.extend(e,i):i}},o={};return b.each(n,function(e,t){var a=t[2],s=t[5];i[t[1]]=a.add,s&&a.add(function(){r=s},n[3-e][2].disable,n[3-e][3].disable,n[0][2].lock,n[0][3].lock),a.add(t[3].fire),o[t[0]]=function(){return o[t[0]+"With"](this===o?void 0:this,arguments),this},o[t[0]+"With"]=a.fireWith}),i.promise(o),t&&t.call(o,o),o},when:function(e){var t=arguments.length,n=t,r=Array(n),i=o.call(arguments),a=b.Deferred(),s=function(e){return function(n){r[e]=this,i[e]=arguments.length>1?o.call(arguments):n,--t||a.resolveWith(r,i)}};if(t<=1&&(W(e,a.done(s(n)).resolve,a.reject,!t),"pending"===a.state()||g(i[n]&&i[n].then)))return a.then();for(;n--;)W(i[n],s(n),a.reject);return a.promise()}});var $=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;b.Deferred.exceptionHook=function(t,n){e.console&&e.console.warn&&t&&$.test(t.name)&&e.console.warn("jQuery.Deferred exception: "+t.message,t.stack,n)},b.readyException=function(t){e.setTimeout(function(){throw t})};var F=b.Deferred();function B(){r.removeEventListener("DOMContentLoaded",B),e.removeEventListener("load",B),b.ready()}b.fn.ready=function(e){return F.then(e).catch(function(e){b.readyException(e)}),this},b.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--b.readyWait:b.isReady)||(b.isReady=!0,!0!==e&&--b.readyWait>0||F.resolveWith(r,[b]))}}),b.ready.then=F.then,"complete"===r.readyState||"loading"!==r.readyState&&!r.documentElement.doScroll?e.setTimeout(b.ready):(r.addEventListener("DOMContentLoaded",B),e.addEventListener("load",B));var _=function e(t,n,r,i,o,a,s){var u=0,l=t.length,c=null==r;if("object"===x(r))for(u in o=!0,r)e(t,n,u,r[u],!0,a,s);else if(void 0!==i&&(o=!0,g(i)||(s=!0),c&&(s?(n.call(t,i),n=null):(c=n,n=function(e,t,n){return c.call(b(e),n)})),n))for(;u1,null,!0)},removeData:function(e){return this.each(function(){J.remove(this,e)})}}),b.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=Q.get(e,t),n&&(!r||Array.isArray(n)?r=Q.access(e,t,b.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=b.queue(e,t),r=n.length,i=n.shift(),o=b._queueHooks(e,t);"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,function(){b.dequeue(e,t)},o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return Q.get(e,n)||Q.access(e,n,{empty:b.Callbacks("once memory").add(function(){Q.remove(e,[t+"queue",n])})})}}),b.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length\x20\t\r\n\f]*)/i,ve=/^$|^module$|\/(?:java|ecma)script/i,ye={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function me(e,t){var n;return n=void 0!==e.getElementsByTagName?e.getElementsByTagName(t||"*"):void 0!==e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?b.merge([e],n):n}function xe(e,t){for(var n=0,r=e.length;n-1)i&&i.push(o);else if(l=ae(o),a=me(f.appendChild(o),"script"),l&&xe(a),n)for(c=0;o=a[c++];)ve.test(o.type||"")&&n.push(o);return f}be=r.createDocumentFragment().appendChild(r.createElement("div")),(we=r.createElement("input")).setAttribute("type","radio"),we.setAttribute("checked","checked"),we.setAttribute("name","t"),be.appendChild(we),h.checkClone=be.cloneNode(!0).cloneNode(!0).lastChild.checked,be.innerHTML="",h.noCloneChecked=!!be.cloneNode(!0).lastChild.defaultValue;var Ee=/^key/,ke=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Se=/^([^.]*)(?:\.(.+)|)/;function Ae(){return!0}function Ne(){return!1}function De(e,t){return e===je()==("focus"===t)}function je(){try{return r.activeElement}catch(e){}}function qe(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)qe(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Ne;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return b().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=b.guid++)),e.each(function(){b.event.add(this,t,i,r,n)})}function Le(e,t,n){n?(Q.set(e,t,!1),b.event.add(e,t,{namespace:!1,handler:function(e){var r,i,a=Q.get(this,t);if(1&e.isTrigger&&this[t]){if(a)(b.event.special[t]||{}).delegateType&&e.stopPropagation();else if(a=o.call(arguments),Q.set(this,t,a),r=n(this,t),this[t](),a!==(i=Q.get(this,t))||r?Q.set(this,t,!1):i=void 0,a!==i)return e.stopImmediatePropagation(),e.preventDefault(),i}else a&&(Q.set(this,t,b.event.trigger(b.extend(a.shift(),b.Event.prototype),a,this)),e.stopImmediatePropagation())}})):b.event.add(e,t,Ae)}b.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(e);if(v)for(n.handler&&(n=(o=n).handler,i=o.selector),i&&b.find.matchesSelector(oe,i),n.guid||(n.guid=b.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(t){return void 0!==b&&b.event.triggered!==t.type?b.event.dispatch.apply(e,arguments):void 0}),l=(t=(t||"").match(P)||[""]).length;l--;)d=g=(s=Se.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=b.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=b.event.special[d]||{},c=b.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&b.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(e,r,h,a)||e.addEventListener&&e.addEventListener(d,a)),f.add&&(f.add.call(e,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),b.event.global[d]=!0)},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){for(l=(t=(t||"").match(P)||[""]).length;l--;)if(d=g=(s=Se.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){for(f=b.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;o--;)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||b.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)b.event.remove(e,d+t[l],n,r,!0);b.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=b.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=b.event.special[s.type]||{};for(u[0]=s,t=1;t=1))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n-1:b.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u\x20\t\r\n\f]*)[^>]*)\/>/gi,Oe=/\s*$/g;function Me(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&b(e).children("tbody")[0]||e}function Ie(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function We(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function $e(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n1&&"string"==typeof v&&!h.checkClone&&Pe.test(v))return e.each(function(i){var o=e.eq(i);y&&(t[0]=v.call(this,i,o.html())),Fe(o,t,n,r)});if(p&&(o=(i=Ce(t,e[0].ownerDocument,!1,e,r)).firstChild,1===i.childNodes.length&&(i=o),o||r)){for(u=(s=b.map(me(i,"script"),Ie)).length;f")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=ae(e);if(!(h.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||b.isXMLDoc(e)))for(a=me(c),r=0,i=(o=me(e)).length;r0&&xe(a,!f&&me(e,"script")),c},cleanData:function(e){for(var t,n,r,i=b.event.special,o=0;void 0!==(n=e[o]);o++)if(G(n)){if(t=n[Q.expando]){if(t.events)for(r in t.events)i[r]?b.event.remove(n,r):b.removeEvent(n,r,t.handle);n[Q.expando]=void 0}n[J.expando]&&(n[J.expando]=void 0)}}}),b.fn.extend({detach:function(e){return Be(this,e,!0)},remove:function(e){return Be(this,e)},text:function(e){return _(this,function(e){return void 0===e?b.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Fe(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Me(this,e).appendChild(e)})},prepend:function(){return Fe(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Me(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Fe(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Fe(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(b.cleanData(me(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return b.clone(this,e,t)})},html:function(e){return _(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!Oe.test(e)&&!ye[(ge.exec(e)||["",""])[1].toLowerCase()]){e=b.htmlPrefilter(e);try{for(;n=0&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))||0),u}function ot(e,t,n){var r=ze(e),i=(!h.boxSizingReliable()||n)&&"border-box"===b.css(e,"boxSizing",!1,r),o=i,a=Xe(e,t,r),s="offset"+t[0].toUpperCase()+t.slice(1);if(_e.test(a)){if(!n)return a;a="auto"}return(!h.boxSizingReliable()&&i||"auto"===a||!parseFloat(a)&&"inline"===b.css(e,"display",!1,r))&&e.getClientRects().length&&(i="border-box"===b.css(e,"boxSizing",!1,r),(o=s in e)&&(a=e[s])),(a=parseFloat(a)||0)+it(e,t,n||(i?"border":"content"),o,r,a)+"px"}function at(e,t,n,r,i){return new at.prototype.init(e,t,n,r,i)}b.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Xe(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=V(t),u=et.test(t),l=e.style;if(u||(t=Ke(s)),a=b.cssHooks[t]||b.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"===(o=typeof n)&&(i=re.exec(n))&&i[1]&&(n=ce(e,t,i),o="number"),null!=n&&n==n&&("number"!==o||u||(n+=i&&i[3]||(b.cssNumber[s]?"":"px")),h.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=V(t);return et.test(t)||(t=Ke(s)),(a=b.cssHooks[t]||b.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=Xe(e,t,r)),"normal"===i&&t in nt&&(i=nt[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),b.each(["height","width"],function(e,t){b.cssHooks[t]={get:function(e,n,r){if(n)return!Ze.test(b.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?ot(e,t,r):le(e,tt,function(){return ot(e,t,r)})},set:function(e,n,r){var i,o=ze(e),a=!h.scrollboxSize()&&"absolute"===o.position,s=(a||r)&&"border-box"===b.css(e,"boxSizing",!1,o),u=r?it(e,t,r,s,o):0;return s&&a&&(u-=Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-parseFloat(o[t])-it(e,t,"border",!1,o)-.5)),u&&(i=re.exec(n))&&"px"!==(i[3]||"px")&&(e.style[t]=n,n=b.css(e,t)),rt(0,n,u)}}}),b.cssHooks.marginLeft=Ve(h.reliableMarginLeft,function(e,t){if(t)return(parseFloat(Xe(e,"marginLeft"))||e.getBoundingClientRect().left-le(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),b.each({margin:"",padding:"",border:"Width"},function(e,t){b.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];r<4;r++)i[e+ie[r]+t]=o[r]||o[r-2]||o[0];return i}},"margin"!==e&&(b.cssHooks[e+t].set=rt)}),b.fn.extend({css:function(e,t){return _(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=ze(e),i=t.length;a1)}}),b.Tween=at,at.prototype={constructor:at,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||b.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(b.cssNumber[n]?"":"px")},cur:function(){var e=at.propHooks[this.prop];return e&&e.get?e.get(this):at.propHooks._default.get(this)},run:function(e){var t,n=at.propHooks[this.prop];return this.options.duration?this.pos=t=b.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):at.propHooks._default.set(this),this}},at.prototype.init.prototype=at.prototype,at.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=b.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){b.fx.step[e.prop]?b.fx.step[e.prop](e):1!==e.elem.nodeType||!b.cssHooks[e.prop]&&null==e.elem.style[Ke(e.prop)]?e.elem[e.prop]=e.now:b.style(e.elem,e.prop,e.now+e.unit)}}},at.propHooks.scrollTop=at.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},b.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},b.fx=at.prototype.init,b.fx.step={};var st,ut,lt=/^(?:toggle|show|hide)$/,ct=/queueHooks$/;function ft(){ut&&(!1===r.hidden&&e.requestAnimationFrame?e.requestAnimationFrame(ft):e.setTimeout(ft,b.fx.interval),b.fx.tick())}function pt(){return e.setTimeout(function(){st=void 0}),st=Date.now()}function dt(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=ie[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function ht(e,t,n){for(var r,i=(vt.tweeners[t]||[]).concat(vt.tweeners["*"]),o=0,a=i.length;o1)},removeAttr:function(e){return this.each(function(){b.removeAttr(this,e)})}}),b.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return void 0===e.getAttribute?b.prop(e,t,n):(1===o&&b.isXMLDoc(e)||(i=b.attrHooks[t.toLowerCase()]||(b.expr.match.bool.test(t)?yt:void 0)),void 0!==n?null===n?void b.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=b.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!h.radioValue&&"radio"===t&&A(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(P);if(i&&1===e.nodeType)for(;n=i[r++];)e.removeAttribute(n)}}),yt={set:function(e,t,n){return!1===t?b.removeAttr(e,n):e.setAttribute(n,n),n}},b.each(b.expr.match.bool.source.match(/\w+/g),function(e,t){var n=mt[t]||b.find.attr;mt[t]=function(e,t,r){var i,o,a=t.toLowerCase();return r||(o=mt[a],mt[a]=i,i=null!=n(e,t,r)?a:null,mt[a]=o),i}});var xt=/^(?:input|select|textarea|button)$/i,bt=/^(?:a|area)$/i;function wt(e){return(e.match(P)||[]).join(" ")}function Tt(e){return e.getAttribute&&e.getAttribute("class")||""}function Ct(e){return Array.isArray(e)?e:"string"==typeof e&&e.match(P)||[]}b.fn.extend({prop:function(e,t){return _(this,b.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[b.propFix[e]||e]})}}),b.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&b.isXMLDoc(e)||(t=b.propFix[t]||t,i=b.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=b.find.attr(e,"tabindex");return t?parseInt(t,10):xt.test(e.nodeName)||bt.test(e.nodeName)&&e.href?0:-1}}},propFix:{for:"htmlFor",class:"className"}}),h.optSelected||(b.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),b.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){b.propFix[this.toLowerCase()]=this}),b.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){b(this).addClass(e.call(this,t,Tt(this)))});if((t=Ct(e)).length)for(;n=this[u++];)if(i=Tt(n),r=1===n.nodeType&&" "+wt(i)+" "){for(a=0;o=t[a++];)r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=wt(r))&&n.setAttribute("class",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){b(this).removeClass(e.call(this,t,Tt(this)))});if(!arguments.length)return this.attr("class","");if((t=Ct(e)).length)for(;n=this[u++];)if(i=Tt(n),r=1===n.nodeType&&" "+wt(i)+" "){for(a=0;o=t[a++];)for(;r.indexOf(" "+o+" ")>-1;)r=r.replace(" "+o+" "," ");i!==(s=wt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(e,t){var n=typeof e,r="string"===n||Array.isArray(e);return"boolean"==typeof t&&r?t?this.addClass(e):this.removeClass(e):g(e)?this.each(function(n){b(this).toggleClass(e.call(this,n,Tt(this),t),t)}):this.each(function(){var t,i,o,a;if(r)for(i=0,o=b(this),a=Ct(e);t=a[i++];)o.hasClass(t)?o.removeClass(t):o.addClass(t);else void 0!==e&&"boolean"!==n||((t=Tt(this))&&Q.set(this,"__className__",t),this.setAttribute&&this.setAttribute("class",t||!1===e?"":Q.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;for(t=" "+e+" ";n=this[r++];)if(1===n.nodeType&&(" "+wt(Tt(n))+" ").indexOf(t)>-1)return!0;return!1}});var Et=/\r/g;b.fn.extend({val:function(e){var t,n,r,i=this[0];return arguments.length?(r=g(e),this.each(function(n){var i;1===this.nodeType&&(null==(i=r?e.call(this,n,b(this).val()):e)?i="":"number"==typeof i?i+="":Array.isArray(i)&&(i=b.map(i,function(e){return null==e?"":e+""})),(t=b.valHooks[this.type]||b.valHooks[this.nodeName.toLowerCase()])&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))})):i?(t=b.valHooks[i.type]||b.valHooks[i.nodeName.toLowerCase()])&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:"string"==typeof(n=i.value)?n.replace(Et,""):null==n?"":n:void 0}}),b.extend({valHooks:{option:{get:function(e){var t=b.find.attr(e,"value");return null!=t?t:wt(b.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r-1)&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),b.each(["radio","checkbox"],function(){b.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=b.inArray(b(e).val(),t)>-1}},h.checkOn||(b.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),h.focusin="onfocusin"in e;var kt=/^(?:focusinfocus|focusoutblur)$/,St=function(e){e.stopPropagation()};b.extend(b.event,{trigger:function(t,n,i,o){var a,s,u,l,c,p,d,h,y=[i||r],m=f.call(t,"type")?t.type:t,x=f.call(t,"namespace")?t.namespace.split("."):[];if(s=h=u=i=i||r,3!==i.nodeType&&8!==i.nodeType&&!kt.test(m+b.event.triggered)&&(m.indexOf(".")>-1&&(m=(x=m.split(".")).shift(),x.sort()),c=m.indexOf(":")<0&&"on"+m,(t=t[b.expando]?t:new b.Event(m,"object"==typeof t&&t)).isTrigger=o?2:3,t.namespace=x.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+x.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=i),n=null==n?[t]:b.makeArray(n,[t]),d=b.event.special[m]||{},o||!d.trigger||!1!==d.trigger.apply(i,n))){if(!o&&!d.noBubble&&!v(i)){for(l=d.delegateType||m,kt.test(l+m)||(s=s.parentNode);s;s=s.parentNode)y.push(s),u=s;u===(i.ownerDocument||r)&&y.push(u.defaultView||u.parentWindow||e)}for(a=0;(s=y[a++])&&!t.isPropagationStopped();)h=s,t.type=a>1?l:d.bindType||m,(p=(Q.get(s,"events")||{})[t.type]&&Q.get(s,"handle"))&&p.apply(s,n),(p=c&&s[c])&&p.apply&&G(s)&&(t.result=p.apply(s,n),!1===t.result&&t.preventDefault());return t.type=m,o||t.isDefaultPrevented()||d._default&&!1!==d._default.apply(y.pop(),n)||!G(i)||c&&g(i[m])&&!v(i)&&((u=i[c])&&(i[c]=null),b.event.triggered=m,t.isPropagationStopped()&&h.addEventListener(m,St),i[m](),t.isPropagationStopped()&&h.removeEventListener(m,St),b.event.triggered=void 0,u&&(i[c]=u)),t.result}},simulate:function(e,t,n){var r=b.extend(new b.Event,n,{type:e,isSimulated:!0});b.event.trigger(r,null,t)}}),b.fn.extend({trigger:function(e,t){return this.each(function(){b.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return b.event.trigger(e,t,n,!0)}}),h.focusin||b.each({focus:"focusin",blur:"focusout"},function(e,t){var n=function(e){b.event.simulate(t,e.target,b.event.fix(e))};b.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=Q.access(r,t);i||r.addEventListener(e,n,!0),Q.access(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=Q.access(r,t)-1;i?Q.access(r,t,i):(r.removeEventListener(e,n,!0),Q.remove(r,t))}}});var At=e.location,Nt=Date.now(),Dt=/\?/;b.parseXML=function(t){var n;if(!t||"string"!=typeof t)return null;try{n=(new e.DOMParser).parseFromString(t,"text/xml")}catch(e){n=void 0}return n&&!n.getElementsByTagName("parsererror").length||b.error("Invalid XML: "+t),n};var jt=/\[\]$/,qt=/\r?\n/g,Lt=/^(?:submit|button|image|reset|file)$/i,Ht=/^(?:input|select|textarea|keygen)/i;function Ot(e,t,n,r){var i;if(Array.isArray(t))b.each(t,function(t,i){n||jt.test(e)?r(e,i):Ot(e+"["+("object"==typeof i&&null!=i?t:"")+"]",i,n,r)});else if(n||"object"!==x(t))r(e,t);else for(i in t)Ot(e+"["+i+"]",t[i],n,r)}b.param=function(e,t){var n,r=[],i=function(e,t){var n=g(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(null==e)return"";if(Array.isArray(e)||e.jquery&&!b.isPlainObject(e))b.each(e,function(){i(this.name,this.value)});else for(n in e)Ot(n,e[n],t,i);return r.join("&")},b.fn.extend({serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=b.prop(this,"elements");return e?b.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!b(this).is(":disabled")&&Ht.test(this.nodeName)&&!Lt.test(e)&&(this.checked||!he.test(e))}).map(function(e,t){var n=b(this).val();return null==n?null:Array.isArray(n)?b.map(n,function(e){return{name:t.name,value:e.replace(qt,"\r\n")}}):{name:t.name,value:n.replace(qt,"\r\n")}}).get()}});var Pt=/%20/g,Rt=/#.*$/,Mt=/([?&])_=[^&]*/,It=/^(.*?):[ \t]*([^\r\n]*)$/gm,Wt=/^(?:GET|HEAD)$/,$t=/^\/\//,Ft={},Bt={},_t="*/".concat("*"),zt=r.createElement("a");function Ut(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(P)||[];if(g(n))for(;r=o[i++];)"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function Xt(e,t,n,r){var i={},o=e===Bt;function a(s){var u;return i[s]=!0,b.each(e[s]||[],function(e,s){var l=s(t,n,r);return"string"!=typeof l||o||i[l]?o?!(u=l):void 0:(t.dataTypes.unshift(l),a(l),!1)}),u}return a(t.dataTypes[0])||!i["*"]&&a("*")}function Vt(e,t){var n,r,i=b.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&b.extend(!0,e,r),e}function Gt(e,t,n){for(var r,i,o,a,s=e.contents,u=e.dataTypes;"*"===u[0];)u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}function Yt(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];for(o=c.shift();o;)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e.throws)t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}zt.href=At.href,b.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:At.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(At.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":_t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":b.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Vt(Vt(e,b.ajaxSettings),t):Vt(b.ajaxSettings,e)},ajaxPrefilter:Ut(Ft),ajaxTransport:Ut(Bt),ajax:function(t,n){"object"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,p,d,h=b.ajaxSetup({},n),g=h.context||h,v=h.context&&(g.nodeType||g.jquery)?b(g):b.event,y=b.Deferred(),m=b.Callbacks("once memory"),x=h.statusCode||{},w={},T={},C="canceled",E={readyState:0,getResponseHeader:function(e){var t;if(c){if(!s)for(s={};t=It.exec(a);)s[t[1].toLowerCase()+" "]=(s[t[1].toLowerCase()+" "]||[]).concat(t[2]);t=s[e.toLowerCase()+" "]}return null==t?null:t.join(", ")},getAllResponseHeaders:function(){return c?a:null},setRequestHeader:function(e,t){return null==c&&(e=T[e.toLowerCase()]=T[e.toLowerCase()]||e,w[e]=t),this},overrideMimeType:function(e){return null==c&&(h.mimeType=e),this},statusCode:function(e){var t;if(e)if(c)E.always(e[E.status]);else for(t in e)x[t]=[x[t],e[t]];return this},abort:function(e){var t=e||C;return i&&i.abort(t),k(0,t),this}};if(y.promise(E),h.url=((t||h.url||At.href)+"").replace($t,At.protocol+"//"),h.type=n.method||n.type||h.method||h.type,h.dataTypes=(h.dataType||"*").toLowerCase().match(P)||[""],null==h.crossDomain){l=r.createElement("a");try{l.href=h.url,l.href=l.href,h.crossDomain=zt.protocol+"//"+zt.host!=l.protocol+"//"+l.host}catch(e){h.crossDomain=!0}}if(h.data&&h.processData&&"string"!=typeof h.data&&(h.data=b.param(h.data,h.traditional)),Xt(Ft,h,n,E),c)return E;for(p in(f=b.event&&h.global)&&0==b.active++&&b.event.trigger("ajaxStart"),h.type=h.type.toUpperCase(),h.hasContent=!Wt.test(h.type),o=h.url.replace(Rt,""),h.hasContent?h.data&&h.processData&&0===(h.contentType||"").indexOf("application/x-www-form-urlencoded")&&(h.data=h.data.replace(Pt,"+")):(d=h.url.slice(o.length),h.data&&(h.processData||"string"==typeof h.data)&&(o+=(Dt.test(o)?"&":"?")+h.data,delete h.data),!1===h.cache&&(o=o.replace(Mt,"$1"),d=(Dt.test(o)?"&":"?")+"_="+Nt+++d),h.url=o+d),h.ifModified&&(b.lastModified[o]&&E.setRequestHeader("If-Modified-Since",b.lastModified[o]),b.etag[o]&&E.setRequestHeader("If-None-Match",b.etag[o])),(h.data&&h.hasContent&&!1!==h.contentType||n.contentType)&&E.setRequestHeader("Content-Type",h.contentType),E.setRequestHeader("Accept",h.dataTypes[0]&&h.accepts[h.dataTypes[0]]?h.accepts[h.dataTypes[0]]+("*"!==h.dataTypes[0]?", */*; q=0.01":""):h.accepts["*"]),h.headers)E.setRequestHeader(p,h.headers[p]);if(h.beforeSend&&(!1===h.beforeSend.call(g,E,h)||c))return E.abort();if(C="abort",m.add(h.complete),E.done(h.success),E.fail(h.error),i=Xt(Bt,h,n,E)){if(E.readyState=1,f&&v.trigger("ajaxSend",[E,h]),c)return E;h.async&&h.timeout>0&&(u=e.setTimeout(function(){E.abort("timeout")},h.timeout));try{c=!1,i.send(w,k)}catch(e){if(c)throw e;k(-1,e)}}else k(-1,"No Transport");function k(t,n,r,s){var l,p,d,w,T,C=n;c||(c=!0,u&&e.clearTimeout(u),i=void 0,a=s||"",E.readyState=t>0?4:0,l=t>=200&&t<300||304===t,r&&(w=Gt(h,E,r)),w=Yt(h,w,E,l),l?(h.ifModified&&((T=E.getResponseHeader("Last-Modified"))&&(b.lastModified[o]=T),(T=E.getResponseHeader("etag"))&&(b.etag[o]=T)),204===t||"HEAD"===h.type?C="nocontent":304===t?C="notmodified":(C=w.state,p=w.data,l=!(d=w.error))):(d=C,!t&&C||(C="error",t<0&&(t=0))),E.status=t,E.statusText=(n||C)+"",l?y.resolveWith(g,[p,C,E]):y.rejectWith(g,[E,C,d]),E.statusCode(x),x=void 0,f&&v.trigger(l?"ajaxSuccess":"ajaxError",[E,h,l?p:d]),m.fireWith(g,[E,C]),f&&(v.trigger("ajaxComplete",[E,h]),--b.active||b.event.trigger("ajaxStop")))}return E},getJSON:function(e,t,n){return b.get(e,t,n,"json")},getScript:function(e,t){return b.get(e,void 0,t,"script")}}),b.each(["get","post"],function(e,t){b[t]=function(e,n,r,i){return g(n)&&(i=i||r,r=n,n=void 0),b.ajax(b.extend({url:e,type:t,dataType:i,data:n,success:r},b.isPlainObject(e)&&e))}}),b._evalUrl=function(e,t){return b.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,converters:{"text script":function(){}},dataFilter:function(e){b.globalEval(e,t)}})},b.fn.extend({wrapAll:function(e){var t;return this[0]&&(g(e)&&(e=e.call(this[0])),t=b(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstElementChild;)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(e){return g(e)?this.each(function(t){b(this).wrapInner(e.call(this,t))}):this.each(function(){var t=b(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=g(e);return this.each(function(n){b(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){b(this).replaceWith(this.childNodes)}),this}}),b.expr.pseudos.hidden=function(e){return!b.expr.pseudos.visible(e)},b.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},b.ajaxSettings.xhr=function(){try{return new e.XMLHttpRequest}catch(e){}};var Qt={0:200,1223:204},Jt=b.ajaxSettings.xhr();h.cors=!!Jt&&"withCredentials"in Jt,h.ajax=Jt=!!Jt,b.ajaxTransport(function(t){var n,r;if(h.cors||Jt&&!t.crossDomain)return{send:function(i,o){var a,s=t.xhr();if(s.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(a in t.xhrFields)s[a]=t.xhrFields[a];for(a in t.mimeType&&s.overrideMimeType&&s.overrideMimeType(t.mimeType),t.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest"),i)s.setRequestHeader(a,i[a]);n=function(e){return function(){n&&(n=r=s.onload=s.onerror=s.onabort=s.ontimeout=s.onreadystatechange=null,"abort"===e?s.abort():"error"===e?"number"!=typeof s.status?o(0,"error"):o(s.status,s.statusText):o(Qt[s.status]||s.status,s.statusText,"text"!==(s.responseType||"text")||"string"!=typeof s.responseText?{binary:s.response}:{text:s.responseText},s.getAllResponseHeaders()))}},s.onload=n(),r=s.onerror=s.ontimeout=n("error"),void 0!==s.onabort?s.onabort=r:s.onreadystatechange=function(){4===s.readyState&&e.setTimeout(function(){n&&r()})},n=n("abort");try{s.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}},abort:function(){n&&n()}}}),b.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),b.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return b.globalEval(e),e}}}),b.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),b.ajaxTransport("script",function(e){var t,n;if(e.crossDomain||e.scriptAttrs)return{send:function(i,o){t=b("