Full Code of NullVoxPopuli/emberclear for AI

master 92881d22cfad cached
1168 files
1.2 MB
357.1k tokens
1578 symbols
1 requests
Download .txt
Showing preview only (1,524K chars total). Download the full file or copy to clipboard to get everything.
Repository: NullVoxPopuli/emberclear
Branch: master
Commit: 92881d22cfad
Files: 1168
Total size: 1.2 MB

Directory structure:
gitextract_de_b7zvl/

├── .codeclimate.yml
├── .editorconfig
├── .github/
│   ├── renovate.json5
│   └── workflows/
│       ├── web-addon-crypto.yml
│       ├── web-addon-encoding.yml
│       ├── web-addon-local-account.yml
│       ├── web-addon-networking.yml
│       ├── web-addon-test-helpers.yml
│       ├── web-addon-tracked-local-storage.yml
│       ├── web-addon-ui.yml
│       ├── web-app-deploy.yml
│       ├── web-app-quality.yml
│       ├── web-app-tests.yml
│       ├── web-pinochle-deploy.yml
│       ├── web-pinochle-quality.yml
│       ├── web-pinochle-tests.yml
│       └── web-smoke-tests.yml
├── .gitignore
├── .gitmodules
├── .sonarcloud.properties
├── .vscode/
│   └── launch.json
├── .whitesource
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── benchmarks/
│   ├── crypto/
│   │   ├── .babelrc.js
│   │   ├── .gitignore
│   │   ├── package.json
│   │   ├── run
│   │   ├── src/
│   │   │   ├── bench/
│   │   │   │   ├── base64.ts
│   │   │   │   ├── hex.ts
│   │   │   │   ├── key-generation.ts
│   │   │   │   ├── nonce-generation.ts
│   │   │   │   ├── round-trip-long.ts
│   │   │   │   ├── round-trip.ts
│   │   │   │   └── stringConvension.ts
│   │   │   ├── index.ts
│   │   │   ├── lib/
│   │   │   │   ├── js-nacl.ts
│   │   │   │   ├── libsodium.ts
│   │   │   │   ├── round-trip-implementations.ts
│   │   │   │   ├── tweet-nacl.ts
│   │   │   │   └── utils.ts
│   │   │   └── utils.ts
│   │   └── tsconfig.json
│   └── emoji-replace/
│       ├── .babelrc.js
│       ├── .gitignore
│       ├── package.json
│       ├── run
│       ├── src/
│       │   ├── bench/
│       │   │   ├── -utils.ts
│       │   │   ├── long.ts
│       │   │   ├── micro.ts
│       │   │   └── short.ts
│       │   └── index.ts
│       ├── tsconfig.json
│       └── types/
│           └── emojis.d.ts
├── client/
│   ├── android-wrapper/
│   │   ├── .gitignore
│   │   ├── CONTRIBUTING.md
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── app/
│   │   │   ├── build.gradle
│   │   │   └── src/
│   │   │       └── main/
│   │   │           ├── AndroidManifest.xml
│   │   │           └── res/
│   │   │               └── values/
│   │   │                   └── styles.xml
│   │   ├── build.gradle
│   │   ├── enable-debug.sh
│   │   ├── gradle/
│   │   │   └── wrapper/
│   │   │       ├── gradle-wrapper.jar
│   │   │       ├── gradle-wrapper.properties
│   │   │       └── gradle.properties
│   │   ├── gradle.properties
│   │   ├── gradlew
│   │   ├── gradlew.bat
│   │   └── settings.gradle
│   └── web/
│       ├── .eslintignore
│       ├── .eslintrc.js
│       ├── .gitignore
│       ├── .prettierignore
│       ├── .prettierrc.js
│       ├── .stylelintignore
│       ├── .template-lintrc.js
│       ├── .vim/
│       │   └── coc-settings.json
│       ├── .vscode/
│       │   └── settings.json
│       ├── addons/
│       │   ├── crypto/
│       │   │   ├── .editorconfig
│       │   │   ├── .ember-cli
│       │   │   ├── .eslintignore
│       │   │   ├── .eslintrc.js
│       │   │   ├── .gitignore
│       │   │   ├── .npmignore
│       │   │   ├── .template-lintrc.js
│       │   │   ├── .watchmanconfig
│       │   │   ├── CONTRIBUTING.md
│       │   │   ├── LICENSE.md
│       │   │   ├── README.md
│       │   │   ├── addon/
│       │   │   │   ├── -private/
│       │   │   │   │   └── types.ts
│       │   │   │   ├── connector.ts
│       │   │   │   ├── index.ts
│       │   │   │   ├── services/
│       │   │   │   │   └── workers.ts
│       │   │   │   ├── tsconfig.json
│       │   │   │   ├── types.ts
│       │   │   │   └── workers/
│       │   │   │       └── crypto/
│       │   │   │           ├── actions.ts
│       │   │   │           ├── index.ts
│       │   │   │           ├── messages.ts
│       │   │   │           └── utils/
│       │   │   │               ├── array.ts
│       │   │   │               ├── bip39/
│       │   │   │               │   └── wordlists/
│       │   │   │               │       ├── english.ts
│       │   │   │               │       └── index.ts
│       │   │   │               ├── mnemonic.ts
│       │   │   │               ├── nacl.ts
│       │   │   │               ├── socket.ts
│       │   │   │               └── string-encoding.ts
│       │   │   ├── addon-test-support/
│       │   │   │   ├── index.ts
│       │   │   │   ├── setup.ts
│       │   │   │   └── tsconfig.json
│       │   │   ├── app/
│       │   │   │   └── services/
│       │   │   │       └── workers.ts
│       │   │   ├── config/
│       │   │   │   ├── ember-try.js
│       │   │   │   └── environment.js
│       │   │   ├── ember-cli-build.js
│       │   │   ├── index.js
│       │   │   ├── lib/
│       │   │   │   └── worker-build.js
│       │   │   ├── package.json
│       │   │   ├── testem.js
│       │   │   ├── tests/
│       │   │   │   ├── dummy/
│       │   │   │   │   ├── app/
│       │   │   │   │   │   ├── app.ts
│       │   │   │   │   │   ├── components/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── config/
│       │   │   │   │   │   │   └── environment.d.ts
│       │   │   │   │   │   ├── controllers/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── helpers/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── index.html
│       │   │   │   │   │   ├── models/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── router.js
│       │   │   │   │   │   ├── routes/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── styles/
│       │   │   │   │   │   │   └── app.css
│       │   │   │   │   │   └── templates/
│       │   │   │   │   │       └── application.hbs
│       │   │   │   │   ├── config/
│       │   │   │   │   │   ├── ember-cli-update.json
│       │   │   │   │   │   ├── environment.js
│       │   │   │   │   │   ├── optional-features.json
│       │   │   │   │   │   └── targets.js
│       │   │   │   │   └── public/
│       │   │   │   │       └── robots.txt
│       │   │   │   ├── helpers/
│       │   │   │   │   └── .gitkeep
│       │   │   │   ├── index.html
│       │   │   │   ├── integration/
│       │   │   │   │   └── .gitkeep
│       │   │   │   ├── test-helper.ts
│       │   │   │   ├── tsconfig.json
│       │   │   │   ├── unit/
│       │   │   │   │   └── services/
│       │   │   │   │       └── workers-test.js
│       │   │   │   └── workers/
│       │   │   │       └── crypto/
│       │   │   │           ├── mnemonic-test.ts
│       │   │   │           ├── nacl-test.ts
│       │   │   │           └── string-encoding-test.ts
│       │   │   ├── tsconfig.compiler-options.json
│       │   │   ├── tsconfig.json
│       │   │   ├── types/
│       │   │   │   └── overrides.d.ts
│       │   │   └── vendor/
│       │   │       └── .gitkeep
│       │   ├── encoding/
│       │   │   ├── .editorconfig
│       │   │   ├── .ember-cli
│       │   │   ├── .eslintignore
│       │   │   ├── .eslintrc.js
│       │   │   ├── .gitignore
│       │   │   ├── .npmignore
│       │   │   ├── .template-lintrc.js
│       │   │   ├── .travis.yml
│       │   │   ├── .watchmanconfig
│       │   │   ├── CONTRIBUTING.md
│       │   │   ├── LICENSE.md
│       │   │   ├── README.md
│       │   │   ├── addon/
│       │   │   │   ├── string.ts
│       │   │   │   └── tsconfig.json
│       │   │   ├── config/
│       │   │   │   ├── ember-try.js
│       │   │   │   └── environment.js
│       │   │   ├── ember-cli-build.js
│       │   │   ├── index.js
│       │   │   ├── package.json
│       │   │   ├── testem.js
│       │   │   ├── tests/
│       │   │   │   ├── dummy/
│       │   │   │   │   ├── app/
│       │   │   │   │   │   ├── app.ts
│       │   │   │   │   │   ├── components/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── config/
│       │   │   │   │   │   │   └── environment.d.ts
│       │   │   │   │   │   ├── controllers/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── helpers/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── index.html
│       │   │   │   │   │   ├── models/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── router.js
│       │   │   │   │   │   ├── routes/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── styles/
│       │   │   │   │   │   │   └── app.css
│       │   │   │   │   │   └── templates/
│       │   │   │   │   │       └── application.hbs
│       │   │   │   │   ├── config/
│       │   │   │   │   │   ├── ember-cli-update.json
│       │   │   │   │   │   ├── environment.js
│       │   │   │   │   │   ├── optional-features.json
│       │   │   │   │   │   └── targets.js
│       │   │   │   │   └── public/
│       │   │   │   │       └── robots.txt
│       │   │   │   ├── helpers/
│       │   │   │   │   └── .gitkeep
│       │   │   │   ├── index.html
│       │   │   │   ├── integration/
│       │   │   │   │   └── .gitkeep
│       │   │   │   ├── test-helper.js
│       │   │   │   ├── tsconfig.json
│       │   │   │   └── unit/
│       │   │   │       ├── .gitkeep
│       │   │   │       └── string-test.ts
│       │   │   ├── tsconfig.compiler-options.json
│       │   │   ├── tsconfig.json
│       │   │   └── vendor/
│       │   │       └── .gitkeep
│       │   ├── local-account/
│       │   │   ├── .editorconfig
│       │   │   ├── .ember-cli
│       │   │   ├── .eslintignore
│       │   │   ├── .eslintrc.js
│       │   │   ├── .gitignore
│       │   │   ├── .npmignore
│       │   │   ├── .template-lintrc.js
│       │   │   ├── .travis.yml
│       │   │   ├── .watchmanconfig
│       │   │   ├── CONTRIBUTING.md
│       │   │   ├── LICENSE.md
│       │   │   ├── README.md
│       │   │   ├── addon/
│       │   │   │   ├── adapters/
│       │   │   │   │   └── application.js
│       │   │   │   ├── index.ts
│       │   │   │   ├── models/
│       │   │   │   │   ├── README.md
│       │   │   │   │   ├── channel-context-chain.ts
│       │   │   │   │   ├── channel.ts
│       │   │   │   │   ├── contact.ts
│       │   │   │   │   ├── identity.ts
│       │   │   │   │   ├── user.ts
│       │   │   │   │   ├── vote-chain.ts
│       │   │   │   │   └── vote.ts
│       │   │   │   ├── serializers/
│       │   │   │   │   └── application.js
│       │   │   │   ├── services/
│       │   │   │   │   ├── channel-manager.ts
│       │   │   │   │   ├── contact-manager.ts
│       │   │   │   │   └── current-user.ts
│       │   │   │   ├── tsconfig.json
│       │   │   │   ├── types.ts
│       │   │   │   └── utils.ts
│       │   │   ├── addon-test-support/
│       │   │   │   ├── -private/
│       │   │   │   │   ├── contact.ts
│       │   │   │   │   ├── current-user.ts
│       │   │   │   │   ├── storage.ts
│       │   │   │   │   ├── user.ts
│       │   │   │   │   └── utils.ts
│       │   │   │   ├── index.ts
│       │   │   │   └── tsconfig.json
│       │   │   ├── app/
│       │   │   │   ├── adapters/
│       │   │   │   │   └── application.js
│       │   │   │   ├── models/
│       │   │   │   │   ├── channel-context-chain.js
│       │   │   │   │   ├── channel.js
│       │   │   │   │   ├── contact.js
│       │   │   │   │   ├── identity.js
│       │   │   │   │   ├── user.js
│       │   │   │   │   ├── vote-chain.js
│       │   │   │   │   └── vote.js
│       │   │   │   ├── serializers/
│       │   │   │   │   └── application.js
│       │   │   │   └── services/
│       │   │   │       ├── channel-manager.js
│       │   │   │       ├── contact-manager.js
│       │   │   │       ├── current-user.js
│       │   │   │       └── store.js
│       │   │   ├── config/
│       │   │   │   ├── ember-try.js
│       │   │   │   └── environment.js
│       │   │   ├── ember-cli-build.js
│       │   │   ├── index.js
│       │   │   ├── package.json
│       │   │   ├── testem.js
│       │   │   ├── tests/
│       │   │   │   ├── dummy/
│       │   │   │   │   ├── app/
│       │   │   │   │   │   ├── app.ts
│       │   │   │   │   │   ├── components/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── config/
│       │   │   │   │   │   │   └── environment.d.ts
│       │   │   │   │   │   ├── controllers/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── helpers/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── index.html
│       │   │   │   │   │   ├── models/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── router.js
│       │   │   │   │   │   ├── routes/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── styles/
│       │   │   │   │   │   │   └── app.css
│       │   │   │   │   │   └── templates/
│       │   │   │   │   │       └── application.hbs
│       │   │   │   │   ├── config/
│       │   │   │   │   │   ├── ember-cli-update.json
│       │   │   │   │   │   ├── environment.js
│       │   │   │   │   │   ├── optional-features.json
│       │   │   │   │   │   └── targets.js
│       │   │   │   │   └── public/
│       │   │   │   │       └── robots.txt
│       │   │   │   ├── helpers/
│       │   │   │   │   └── .gitkeep
│       │   │   │   ├── index.html
│       │   │   │   ├── integration/
│       │   │   │   │   └── .gitkeep
│       │   │   │   ├── test-helper.ts
│       │   │   │   ├── tsconfig.json
│       │   │   │   └── unit/
│       │   │   │       ├── create-current-user-test.ts
│       │   │   │       ├── models/
│       │   │   │       │   ├── contact-test.ts
│       │   │   │       │   └── user-test.ts
│       │   │   │       └── services/
│       │   │   │           └── current-user-test.ts
│       │   │   ├── tsconfig.compiler-options.json
│       │   │   ├── tsconfig.json
│       │   │   ├── types/
│       │   │   │   └── overrides.d.ts
│       │   │   └── vendor/
│       │   │       └── .gitkeep
│       │   ├── networking/
│       │   │   ├── .editorconfig
│       │   │   ├── .ember-cli
│       │   │   ├── .eslintignore
│       │   │   ├── .eslintrc.js
│       │   │   ├── .gitignore
│       │   │   ├── .npmignore
│       │   │   ├── .template-lintrc.js
│       │   │   ├── .watchmanconfig
│       │   │   ├── CONTRIBUTING.md
│       │   │   ├── LICENSE.md
│       │   │   ├── README.md
│       │   │   ├── addon/
│       │   │   │   ├── errors.ts
│       │   │   │   ├── index.ts
│       │   │   │   ├── models/
│       │   │   │   │   ├── message/
│       │   │   │   │   │   └── utils.ts
│       │   │   │   │   ├── message.ts
│       │   │   │   │   └── relay.ts
│       │   │   │   ├── required-data.ts
│       │   │   │   ├── services/
│       │   │   │   │   ├── connection/
│       │   │   │   │   │   ├── ephemeral/
│       │   │   │   │   │   │   └── ephemeral-connection.ts
│       │   │   │   │   │   ├── manager.ts
│       │   │   │   │   │   └── status.ts
│       │   │   │   │   ├── connection.ts
│       │   │   │   │   ├── contacts/
│       │   │   │   │   │   └── online-checker.ts
│       │   │   │   │   ├── messages/
│       │   │   │   │   │   ├── -utils/
│       │   │   │   │   │   │   └── builder.ts
│       │   │   │   │   │   ├── auto-responder.ts
│       │   │   │   │   │   ├── dispatcher.ts
│       │   │   │   │   │   ├── factory.ts
│       │   │   │   │   │   ├── handler.ts
│       │   │   │   │   │   └── processor.ts
│       │   │   │   │   └── status-manager.ts
│       │   │   │   ├── tsconfig.json
│       │   │   │   ├── type-support.ts
│       │   │   │   ├── types.ts
│       │   │   │   └── utils/
│       │   │   │       └── connection/
│       │   │   │           ├── connection-pool.ts
│       │   │   │           └── connection.ts
│       │   │   ├── addon-test-support/
│       │   │   │   ├── index.ts
│       │   │   │   └── tsconfig.json
│       │   │   ├── app/
│       │   │   │   ├── models/
│       │   │   │   │   ├── message.js
│       │   │   │   │   └── relay.js
│       │   │   │   └── services/
│       │   │   │       ├── connection/
│       │   │   │       │   ├── manager.js
│       │   │   │       │   └── status.js
│       │   │   │       ├── connection.js
│       │   │   │       ├── contacts/
│       │   │   │       │   └── online-checker.js
│       │   │   │       ├── messages/
│       │   │   │       │   ├── auto-responder.js
│       │   │   │       │   ├── dispatcher.js
│       │   │   │       │   ├── factory.js
│       │   │   │       │   ├── handler.js
│       │   │   │       │   └── processor.js
│       │   │   │       └── status-manager.js
│       │   │   ├── config/
│       │   │   │   ├── ember-try.js
│       │   │   │   └── environment.js
│       │   │   ├── ember-cli-build.js
│       │   │   ├── index.js
│       │   │   ├── package.json
│       │   │   ├── testem.js
│       │   │   ├── tests/
│       │   │   │   ├── dummy/
│       │   │   │   │   ├── app/
│       │   │   │   │   │   ├── app.ts
│       │   │   │   │   │   ├── components/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── config/
│       │   │   │   │   │   │   └── environment.d.ts
│       │   │   │   │   │   ├── controllers/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── helpers/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── index.html
│       │   │   │   │   │   ├── models/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── router.ts
│       │   │   │   │   │   ├── routes/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── styles/
│       │   │   │   │   │   │   └── app.css
│       │   │   │   │   │   ├── templates/
│       │   │   │   │   │   │   └── application.hbs
│       │   │   │   │   │   └── with-test-waiter.js
│       │   │   │   │   ├── config/
│       │   │   │   │   │   ├── ember-cli-update.json
│       │   │   │   │   │   ├── environment.js
│       │   │   │   │   │   ├── optional-features.json
│       │   │   │   │   │   └── targets.js
│       │   │   │   │   └── public/
│       │   │   │   │       └── robots.txt
│       │   │   │   ├── helpers/
│       │   │   │   │   └── .gitkeep
│       │   │   │   ├── index.html
│       │   │   │   ├── integration/
│       │   │   │   │   └── .gitkeep
│       │   │   │   ├── test-helper.ts
│       │   │   │   ├── tsconfig.json
│       │   │   │   └── unit/
│       │   │   │       └── services/
│       │   │   │           ├── connection/
│       │   │   │           │   └── status-test.js
│       │   │   │           └── messages/
│       │   │   │               ├── auto-responder-test.ts
│       │   │   │               ├── handler-test.ts
│       │   │   │               └── utils/
│       │   │   │                   └── -encryption-test.ts
│       │   │   ├── tsconfig.compiler-options.json
│       │   │   ├── tsconfig.json
│       │   │   ├── types/
│       │   │   │   └── overrides.d.ts
│       │   │   └── vendor/
│       │   │       └── .gitkeep
│       │   ├── prism/
│       │   │   └── README.md
│       │   ├── test-helpers/
│       │   │   ├── .editorconfig
│       │   │   ├── .ember-cli
│       │   │   ├── .eslintignore
│       │   │   ├── .eslintrc.js
│       │   │   ├── .gitignore
│       │   │   ├── .npmignore
│       │   │   ├── .template-lintrc.js
│       │   │   ├── .travis.yml
│       │   │   ├── .watchmanconfig
│       │   │   ├── CONTRIBUTING.md
│       │   │   ├── LICENSE.md
│       │   │   ├── README.md
│       │   │   ├── addon-test-support/
│       │   │   │   ├── -private/
│       │   │   │   │   ├── get-service.ts
│       │   │   │   │   ├── get-store.ts
│       │   │   │   │   ├── refresh.ts
│       │   │   │   │   ├── setup-router.ts
│       │   │   │   │   ├── stub-service.ts
│       │   │   │   │   ├── visit.ts
│       │   │   │   │   └── wait-until.ts
│       │   │   │   ├── index.ts
│       │   │   │   └── tsconfig.json
│       │   │   ├── app/
│       │   │   │   └── .gitkeep
│       │   │   ├── config/
│       │   │   │   ├── ember-try.js
│       │   │   │   └── environment.js
│       │   │   ├── ember-cli-build.js
│       │   │   ├── index.js
│       │   │   ├── package.json
│       │   │   ├── testem.js
│       │   │   ├── tests/
│       │   │   │   ├── dummy/
│       │   │   │   │   ├── app/
│       │   │   │   │   │   ├── app.ts
│       │   │   │   │   │   ├── components/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── config/
│       │   │   │   │   │   │   └── environment.d.ts
│       │   │   │   │   │   ├── controllers/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── helpers/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── index.html
│       │   │   │   │   │   ├── models/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── router.js
│       │   │   │   │   │   ├── routes/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── styles/
│       │   │   │   │   │   │   └── app.css
│       │   │   │   │   │   └── templates/
│       │   │   │   │   │       └── application.hbs
│       │   │   │   │   ├── config/
│       │   │   │   │   │   ├── ember-cli-update.json
│       │   │   │   │   │   ├── environment.js
│       │   │   │   │   │   ├── optional-features.json
│       │   │   │   │   │   └── targets.js
│       │   │   │   │   └── public/
│       │   │   │   │       └── robots.txt
│       │   │   │   ├── helpers/
│       │   │   │   │   └── .gitkeep
│       │   │   │   ├── index.html
│       │   │   │   ├── integration/
│       │   │   │   │   └── .gitkeep
│       │   │   │   ├── test-helper.js
│       │   │   │   └── unit/
│       │   │   │       └── .gitkeep
│       │   │   ├── tsconfig.compiler-options.json
│       │   │   ├── tsconfig.json
│       │   │   ├── types/
│       │   │   │   └── overrides.d.ts
│       │   │   └── vendor/
│       │   │       └── .gitkeep
│       │   ├── tracked-local-storage/
│       │   │   ├── .editorconfig
│       │   │   ├── .ember-cli
│       │   │   ├── .eslintignore
│       │   │   ├── .eslintrc.js
│       │   │   ├── .gitignore
│       │   │   ├── .npmignore
│       │   │   ├── .template-lintrc.js
│       │   │   ├── .watchmanconfig
│       │   │   ├── CONTRIBUTING.md
│       │   │   ├── LICENSE.md
│       │   │   ├── README.md
│       │   │   ├── addon/
│       │   │   │   ├── index.ts
│       │   │   │   └── tsconfig.json
│       │   │   ├── config/
│       │   │   │   ├── ember-try.js
│       │   │   │   └── environment.js
│       │   │   ├── ember-cli-build.js
│       │   │   ├── index.js
│       │   │   ├── package.json
│       │   │   ├── testem.js
│       │   │   ├── tests/
│       │   │   │   ├── dummy/
│       │   │   │   │   ├── app/
│       │   │   │   │   │   ├── app.ts
│       │   │   │   │   │   ├── components/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── config/
│       │   │   │   │   │   │   └── environment.d.ts
│       │   │   │   │   │   ├── controllers/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── helpers/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── index.html
│       │   │   │   │   │   ├── models/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── router.js
│       │   │   │   │   │   ├── routes/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── styles/
│       │   │   │   │   │   │   └── app.css
│       │   │   │   │   │   └── templates/
│       │   │   │   │   │       └── application.hbs
│       │   │   │   │   ├── config/
│       │   │   │   │   │   ├── ember-cli-update.json
│       │   │   │   │   │   ├── environment.js
│       │   │   │   │   │   ├── optional-features.json
│       │   │   │   │   │   └── targets.js
│       │   │   │   │   └── public/
│       │   │   │   │       └── robots.txt
│       │   │   │   ├── index.html
│       │   │   │   ├── test-helper.ts
│       │   │   │   ├── tsconfig.json
│       │   │   │   └── unit/
│       │   │   │       └── in-local-storage-test.ts
│       │   │   ├── tsconfig.compiler-options.json
│       │   │   ├── tsconfig.json
│       │   │   └── vendor/
│       │   │       └── .gitkeep
│       │   ├── tsconfig.json
│       │   └── ui/
│       │       ├── .editorconfig
│       │       ├── .ember-cli
│       │       ├── .eslintignore
│       │       ├── .eslintrc.js
│       │       ├── .gitignore
│       │       ├── .template-lintrc.js
│       │       ├── README.md
│       │       ├── addon/
│       │       │   ├── components/
│       │       │   │   ├── backdrop.hbs
│       │       │   │   ├── collapsible/
│       │       │   │   │   ├── icon.hbs
│       │       │   │   │   └── index.ts
│       │       │   │   ├── dropdown/
│       │       │   │   │   ├── index.hbs
│       │       │   │   │   └── index.ts
│       │       │   │   ├── ellipsis-loader.hbs
│       │       │   │   ├── external-link.hbs
│       │       │   │   ├── field.ts
│       │       │   │   ├── focus-card.hbs
│       │       │   │   ├── hamburger-button.hbs
│       │       │   │   ├── hover-tip.hbs
│       │       │   │   ├── media-info-card.ts
│       │       │   │   ├── modal.hbs
│       │       │   │   └── switch.ts
│       │       │   ├── helpers/
│       │       │   │   ├── and.ts
│       │       │   │   ├── eq.ts
│       │       │   │   ├── not.ts
│       │       │   │   └── prevent-default.ts
│       │       │   └── tsconfig.json
│       │       ├── addon-test-support/
│       │       │   ├── key-events.ts
│       │       │   ├── page-objects.ts
│       │       │   └── tsconfig.json
│       │       ├── app/
│       │       │   ├── components/
│       │       │   │   ├── backdrop.js
│       │       │   │   ├── collapsible/
│       │       │   │   │   └── icon.js
│       │       │   │   ├── collapsible.js
│       │       │   │   ├── dropdown.js
│       │       │   │   ├── ellipsis-loader.js
│       │       │   │   ├── external-link.js
│       │       │   │   ├── field.js
│       │       │   │   ├── focus-card.js
│       │       │   │   ├── hamburger-button.js
│       │       │   │   ├── hover-tip.js
│       │       │   │   ├── media-info-card.js
│       │       │   │   ├── modal.js
│       │       │   │   └── switch.js
│       │       │   ├── helpers/
│       │       │   │   ├── and.js
│       │       │   │   ├── eq.js
│       │       │   │   ├── not.js
│       │       │   │   └── prevent-default.js
│       │       │   └── styles/
│       │       │       └── @emberclear/
│       │       │           ├── animation.css
│       │       │           ├── buttons.css
│       │       │           ├── defaults.css
│       │       │           ├── layout.css
│       │       │           ├── mixins.css
│       │       │           ├── shoelace-overrides.css
│       │       │           ├── sizes.css
│       │       │           ├── spacing.css
│       │       │           ├── themes/
│       │       │           │   ├── default.css
│       │       │           │   └── midnight.css
│       │       │           └── ui.css
│       │       ├── config/
│       │       │   └── environment.js
│       │       ├── ember-cli-build.js
│       │       ├── index.js
│       │       ├── package.json
│       │       ├── testem.js
│       │       ├── tests/
│       │       │   ├── dummy/
│       │       │   │   ├── app/
│       │       │   │   │   ├── app.ts
│       │       │   │   │   ├── components/
│       │       │   │   │   │   └── .gitkeep
│       │       │   │   │   ├── config/
│       │       │   │   │   │   └── environment.d.ts
│       │       │   │   │   ├── controllers/
│       │       │   │   │   │   └── .gitkeep
│       │       │   │   │   ├── helpers/
│       │       │   │   │   │   └── .gitkeep
│       │       │   │   │   ├── index.html
│       │       │   │   │   ├── models/
│       │       │   │   │   │   └── .gitkeep
│       │       │   │   │   ├── router.js
│       │       │   │   │   ├── routes/
│       │       │   │   │   │   └── .gitkeep
│       │       │   │   │   ├── styles/
│       │       │   │   │   │   └── app.css
│       │       │   │   │   └── templates/
│       │       │   │   │       └── application.hbs
│       │       │   │   ├── config/
│       │       │   │   │   ├── environment.js
│       │       │   │   │   ├── optional-features.json
│       │       │   │   │   └── targets.js
│       │       │   │   └── public/
│       │       │   │       └── robots.txt
│       │       │   ├── helpers/
│       │       │   │   └── .gitkeep
│       │       │   ├── index.html
│       │       │   ├── integration/
│       │       │   │   ├── .gitkeep
│       │       │   │   ├── components/
│       │       │   │   │   ├── backdrop-test.js
│       │       │   │   │   ├── collapsible-test.js
│       │       │   │   │   ├── dropdown-test.js
│       │       │   │   │   ├── ellipsis-loader-test.js
│       │       │   │   │   ├── external-link-test.js
│       │       │   │   │   ├── field-test.js
│       │       │   │   │   ├── focus-card-test.ts
│       │       │   │   │   ├── hamburger-button-test.js
│       │       │   │   │   ├── hover-tip-test.js
│       │       │   │   │   ├── media-info-card-test.ts
│       │       │   │   │   ├── modal-test.ts
│       │       │   │   │   └── switch-test.ts
│       │       │   │   └── helpers/
│       │       │   │       ├── and-test.ts
│       │       │   │       ├── eq-test.ts
│       │       │   │       └── not-test.ts
│       │       │   ├── test-helper.ts
│       │       │   ├── tsconfig.json
│       │       │   └── unit/
│       │       │       └── .gitkeep
│       │       ├── tsconfig.compiler-options.json
│       │       ├── tsconfig.json
│       │       ├── types/
│       │       │   ├── dummy/
│       │       │   │   └── index.d.ts
│       │       │   ├── global.d.ts
│       │       │   └── overrides.d.ts
│       │       └── vendor/
│       │           └── .gitkeep
│       ├── config/
│       │   ├── .eslintrc.js
│       │   ├── .template-lintrc.js
│       │   ├── package.json
│       │   ├── testem.js
│       │   ├── tsconfig.compiler-options.json
│       │   └── utils/
│       │       ├── ember-build.js
│       │       └── log.js
│       ├── emberclear/
│       │   ├── .dockerignore
│       │   ├── .editorconfig
│       │   ├── .ember-cli
│       │   ├── .eslintignore
│       │   ├── .eslintrc.js
│       │   ├── .gitignore
│       │   ├── .template-lintrc.js
│       │   ├── Dockerfile
│       │   ├── Dockerfile.release
│       │   ├── README.md
│       │   ├── app/
│       │   │   ├── app.ts
│       │   │   ├── components/
│       │   │   │   ├── app/
│       │   │   │   │   ├── app-shell-remover.ts
│       │   │   │   │   ├── container/
│       │   │   │   │   │   ├── hero.hbs
│       │   │   │   │   │   ├── main.hbs
│       │   │   │   │   │   └── primary-hero.hbs
│       │   │   │   │   ├── modals.hbs
│       │   │   │   │   ├── off-canvas/
│       │   │   │   │   │   ├── -page.ts
│       │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   └── index.ts
│       │   │   │   │   ├── sidebar/
│       │   │   │   │   │   ├── actions/
│       │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   ├── index.ts
│       │   │   │   │   │   │   ├── response-action/
│       │   │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   │   └── response-panel/
│       │   │   │   │   │   │       ├── index.hbs
│       │   │   │   │   │   │       └── index.ts
│       │   │   │   │   │   ├── chats/
│       │   │   │   │   │   │   ├── -page.ts
│       │   │   │   │   │   │   ├── channel/
│       │   │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   │   ├── channel-form/
│       │   │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   │   ├── contact/
│       │   │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   │   ├── data/
│       │   │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   ├── index.ts
│       │   │   │   │   │   │   ├── list.hbs
│       │   │   │   │   │   │   └── offline-counter.hbs
│       │   │   │   │   │   ├── footer.hbs
│       │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   ├── index.ts
│       │   │   │   │   │   └── unread-indicator.hbs
│       │   │   │   │   ├── top-nav/
│       │   │   │   │   │   ├── connection-status/
│       │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   ├── current-chat-name/
│       │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   ├── index.ts
│       │   │   │   │   │   ├── install/
│       │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   ├── locale-select/
│       │   │   │   │   │   │   ├── -page.ts
│       │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   └── user-drop-menu/
│       │   │   │   │   │       ├── -page.ts
│       │   │   │   │   │       ├── index.hbs
│       │   │   │   │   │       └── index.ts
│       │   │   │   │   └── update-checker.ts
│       │   │   │   ├── app-footer.hbs
│       │   │   │   ├── copy-text-button.ts
│       │   │   │   ├── embedded-media.hbs
│       │   │   │   ├── error-card/
│       │   │   │   │   └── index.hbs
│       │   │   │   ├── fetch-open-graph.ts
│       │   │   │   ├── file-chooser/
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   └── index.ts
│       │   │   │   ├── keyboard-shortcuts/
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   └── key/
│       │   │   │   │       └── index.hbs
│       │   │   │   ├── mnemonic-display.ts
│       │   │   │   ├── modal-static/
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   └── index.ts
│       │   │   │   ├── pod/
│       │   │   │   │   ├── add-friend/
│       │   │   │   │   │   └── add-contact/
│       │   │   │   │   │       ├── index.hbs
│       │   │   │   │   │       └── index.ts
│       │   │   │   │   ├── chat/
│       │   │   │   │   │   ├── chat-entry/
│       │   │   │   │   │   │   ├── embeds-menu/
│       │   │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   │   └── snippet/
│       │   │   │   │   │   │   │       ├── -page.ts
│       │   │   │   │   │   │   │       ├── index.hbs
│       │   │   │   │   │   │   │       └── index.ts
│       │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   └── chat-history/
│       │   │   │   │   │       ├── connection-status/
│       │   │   │   │   │       │   ├── index.hbs
│       │   │   │   │   │       │   └── index.ts
│       │   │   │   │   │       ├── index.hbs
│       │   │   │   │   │       ├── message/
│       │   │   │   │   │       │   ├── delivery-confirmations/
│       │   │   │   │   │       │   │   ├── index.hbs
│       │   │   │   │   │       │   │   └── index.ts
│       │   │   │   │   │       │   ├── embedded-resource/
│       │   │   │   │   │       │   │   ├── index.hbs
│       │   │   │   │   │       │   │   └── metadata-preview/
│       │   │   │   │   │       │   │       ├── index.hbs
│       │   │   │   │   │       │   │       └── index.ts
│       │   │   │   │   │       │   ├── header/
│       │   │   │   │   │       │   │   ├── index.hbs
│       │   │   │   │   │       │   │   └── index.ts
│       │   │   │   │   │       │   ├── index.hbs
│       │   │   │   │   │       │   ├── index.ts
│       │   │   │   │   │       │   └── linked-media.hbs
│       │   │   │   │   │       ├── new-messages/
│       │   │   │   │   │       │   ├── index.hbs
│       │   │   │   │   │       │   └── index.ts
│       │   │   │   │   │       ├── notification-prompt/
│       │   │   │   │   │       │   ├── index.hbs
│       │   │   │   │   │       │   └── index.ts
│       │   │   │   │   │       └── unread-management/
│       │   │   │   │   │           ├── -page.ts
│       │   │   │   │   │           ├── index.hbs
│       │   │   │   │   │           └── index.ts
│       │   │   │   │   ├── contacts/
│       │   │   │   │   │   ├── contact-table/
│       │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   └── header/
│       │   │   │   │   │       ├── index.hbs
│       │   │   │   │   │       └── index.ts
│       │   │   │   │   ├── faq/
│       │   │   │   │   │   └── q-and-a.hbs
│       │   │   │   │   ├── index/
│       │   │   │   │   │   ├── begin-button.ts
│       │   │   │   │   │   └── compatibility/
│       │   │   │   │   │       ├── -utils/
│       │   │   │   │   │       │   └── detection.ts
│       │   │   │   │   │       ├── feature/
│       │   │   │   │   │       │   ├── boolean-icon.hbs
│       │   │   │   │   │       │   └── index.hbs
│       │   │   │   │   │       ├── index.hbs
│       │   │   │   │   │       └── index.ts
│       │   │   │   │   ├── login/
│       │   │   │   │   │   ├── -machine.ts
│       │   │   │   │   │   ├── login-form/
│       │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   ├── index.ts
│       │   │   │   │   │   │   └── transfer-prompt/
│       │   │   │   │   │   │       ├── index.hbs
│       │   │   │   │   │   │       └── index.ts
│       │   │   │   │   │   └── template.hbs
│       │   │   │   │   ├── q-r/
│       │   │   │   │   │   ├── -machine.ts
│       │   │   │   │   │   ├── -types.ts
│       │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   ├── index.ts
│       │   │   │   │   │   └── login/
│       │   │   │   │   │       └── ask.hbs
│       │   │   │   │   ├── settings/
│       │   │   │   │   │   ├── danger-zone/
│       │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   ├── interface/
│       │   │   │   │   │   │   ├── -page.ts
│       │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   ├── navigation.hbs
│       │   │   │   │   │   ├── profile/
│       │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   └── relays/
│       │   │   │   │   │       ├── new-relay-form/
│       │   │   │   │   │       │   ├── index.hbs
│       │   │   │   │   │       │   └── index.ts
│       │   │   │   │   │       └── relay-table/
│       │   │   │   │   │           ├── index.hbs
│       │   │   │   │   │           └── row/
│       │   │   │   │   │               ├── index.hbs
│       │   │   │   │   │               └── index.ts
│       │   │   │   │   └── setup/
│       │   │   │   │       ├── -machine.ts
│       │   │   │   │       ├── completed/
│       │   │   │   │       │   ├── index.hbs
│       │   │   │   │       │   └── index.ts
│       │   │   │   │       ├── creating/
│       │   │   │   │       │   ├── index.hbs
│       │   │   │   │       │   └── index.ts
│       │   │   │   │       ├── index.hbs
│       │   │   │   │       ├── index.ts
│       │   │   │   │       └── overwrite.hbs
│       │   │   │   ├── q-r-code.hbs
│       │   │   │   ├── q-r-scanner/
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   └── index.ts
│       │   │   │   ├── search/
│       │   │   │   │   ├── -page.ts
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   ├── index.ts
│       │   │   │   │   └── result.hbs
│       │   │   │   └── status-icon/
│       │   │   │       ├── index.hbs
│       │   │   │       └── index.ts
│       │   │   ├── config/
│       │   │   │   └── environment.d.ts
│       │   │   ├── controllers/
│       │   │   │   ├── application.ts
│       │   │   │   ├── chat/
│       │   │   │   │   ├── in-channel.ts
│       │   │   │   │   └── privately-with.ts
│       │   │   │   ├── invite.ts
│       │   │   │   └── logout.ts
│       │   │   ├── formats.js
│       │   │   ├── helpers/
│       │   │   │   ├── first-8.ts
│       │   │   │   ├── handle-sidebar-click.ts
│       │   │   │   ├── has-feature-flag.ts
│       │   │   │   ├── includes.ts
│       │   │   │   ├── is-channel.js
│       │   │   │   ├── is-contact.js
│       │   │   │   ├── is-current-user.js
│       │   │   │   ├── is-present.ts
│       │   │   │   ├── or.ts
│       │   │   │   ├── queue.ts
│       │   │   │   └── sub.ts
│       │   │   ├── index.html
│       │   │   ├── models/
│       │   │   │   ├── action.ts
│       │   │   │   ├── invitation-result.ts
│       │   │   │   ├── invitation.ts
│       │   │   │   └── message-media.ts
│       │   │   ├── modifiers/
│       │   │   │   ├── format-code.ts
│       │   │   │   ├── has-unread.ts
│       │   │   │   ├── maybe-nudge-to-bottom.ts
│       │   │   │   ├── message-scroll-listener.ts
│       │   │   │   ├── qr-image.ts
│       │   │   │   ├── read-watcher.ts
│       │   │   │   ├── unread-message-list-observer.ts
│       │   │   │   ├── unread-messages-intersection-observer.ts
│       │   │   │   └── update-document-title.ts
│       │   │   ├── router.js
│       │   │   ├── routes/
│       │   │   │   ├── add-friend.ts
│       │   │   │   ├── application.ts
│       │   │   │   ├── chat/
│       │   │   │   │   ├── in-channel.ts
│       │   │   │   │   └── privately-with.ts
│       │   │   │   ├── chat.ts
│       │   │   │   ├── contacts.ts
│       │   │   │   ├── invite.ts
│       │   │   │   ├── login.ts
│       │   │   │   ├── logout.ts
│       │   │   │   ├── qr.js
│       │   │   │   ├── settings/
│       │   │   │   │   └── relays.ts
│       │   │   │   ├── settings.ts
│       │   │   │   └── setup.ts
│       │   │   ├── services/
│       │   │   │   ├── channels/
│       │   │   │   │   ├── -utils/
│       │   │   │   │   │   ├── channel-factory.ts
│       │   │   │   │   │   └── vote-sorter.ts
│       │   │   │   │   ├── channel-verifier.ts
│       │   │   │   │   └── vote-verifier.ts
│       │   │   │   ├── chat-scroller.ts
│       │   │   │   ├── connection/
│       │   │   │   │   └── ephemeral/
│       │   │   │   │       └── login/
│       │   │   │   │           ├── receive-data.ts
│       │   │   │   │           └── send-data.ts
│       │   │   │   ├── current-chat.ts
│       │   │   │   ├── locale.ts
│       │   │   │   ├── modals.ts
│       │   │   │   ├── notifications.ts
│       │   │   │   ├── prism-manager.ts
│       │   │   │   ├── qr-manager.ts
│       │   │   │   ├── redirect-manager.ts
│       │   │   │   ├── session.ts
│       │   │   │   ├── settings.ts
│       │   │   │   ├── sidebar.ts
│       │   │   │   ├── toast.ts
│       │   │   │   └── window.ts
│       │   │   ├── styles/
│       │   │   │   ├── app.css
│       │   │   │   ├── components/
│       │   │   │   │   ├── backdrop.css
│       │   │   │   │   ├── card.css
│       │   │   │   │   ├── chat-entry.css
│       │   │   │   │   ├── connection-status.css
│       │   │   │   │   ├── contacts.css
│       │   │   │   │   ├── dismissable-warning.css
│       │   │   │   │   ├── ellipses-loader.css
│       │   │   │   │   ├── embedded-resource.css
│       │   │   │   │   ├── hover-tip.css
│       │   │   │   │   ├── key.css
│       │   │   │   │   ├── logout.css
│       │   │   │   │   ├── message.css
│       │   │   │   │   ├── messages.css
│       │   │   │   │   ├── metadata-preview.css
│       │   │   │   │   ├── modal.css
│       │   │   │   │   ├── notification-prompt.css
│       │   │   │   │   ├── q-r-code.css
│       │   │   │   │   ├── q-r-scanner.css
│       │   │   │   │   ├── search.css
│       │   │   │   │   ├── settings-nav.css
│       │   │   │   │   ├── sidebar-contact.css
│       │   │   │   │   ├── sidebar-nav.css
│       │   │   │   │   ├── sidebar.css
│       │   │   │   │   ├── snippet.css
│       │   │   │   │   ├── toastify-overrides.css
│       │   │   │   │   ├── top-nav.css
│       │   │   │   │   └── unread-management.css
│       │   │   │   └── utility/
│       │   │   │       ├── height.css
│       │   │   │       └── transitions.css
│       │   │   ├── templates/
│       │   │   │   ├── add-friend.hbs
│       │   │   │   ├── application.hbs
│       │   │   │   ├── chat/
│       │   │   │   │   ├── in-channel.hbs
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   └── privately-with.hbs
│       │   │   │   ├── chat.hbs
│       │   │   │   ├── contacts.hbs
│       │   │   │   ├── faq.hbs
│       │   │   │   ├── index.hbs
│       │   │   │   ├── invite.hbs
│       │   │   │   ├── login.hbs
│       │   │   │   ├── logout.hbs
│       │   │   │   ├── not-found.hbs
│       │   │   │   ├── qr.hbs
│       │   │   │   ├── settings/
│       │   │   │   │   ├── danger-zone.hbs
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   ├── interface.hbs
│       │   │   │   │   └── relays.hbs
│       │   │   │   ├── settings.hbs
│       │   │   │   └── setup.hbs
│       │   │   ├── tsconfig.json
│       │   │   └── utils/
│       │   │       ├── README.md
│       │   │       ├── breakpoints.ts
│       │   │       ├── dom/
│       │   │       │   ├── css.ts
│       │   │       │   └── utils.ts
│       │   │       ├── ember-concurrency.ts
│       │   │       ├── errors.ts
│       │   │       ├── identity-comparison.ts
│       │   │       ├── normalized-meta.ts
│       │   │       ├── route-matchers.ts
│       │   │       ├── string/
│       │   │       │   └── utils.ts
│       │   │       └── uint8array-equality.ts
│       │   ├── config/
│       │   │   ├── addons.js
│       │   │   ├── build/
│       │   │   │   ├── addons.js
│       │   │   │   └── static.js
│       │   │   ├── coverage.js
│       │   │   ├── dependency-lint.js
│       │   │   ├── ember-intl.js
│       │   │   ├── emberclear-local.crt
│       │   │   ├── emberclear-local.csr
│       │   │   ├── emberclear-local.key
│       │   │   ├── environment.js
│       │   │   ├── icons.js
│       │   │   ├── manifest.js
│       │   │   ├── netlify/
│       │   │   │   └── _redirects
│       │   │   ├── optional-features.json
│       │   │   └── targets.js
│       │   ├── ember-cli-build.js
│       │   ├── jsconfig.json
│       │   ├── package.json
│       │   ├── public/
│       │   │   ├── .well-known/
│       │   │   │   └── assetlinks.json
│       │   │   ├── assets/
│       │   │   │   └── images/
│       │   │   │       ├── .gitkeep
│       │   │   │       └── icons/
│       │   │   │           └── .gitkeep
│       │   │   ├── bundle.html
│       │   │   └── robots.txt
│       │   ├── scripts/
│       │   │   ├── analyze-broccoli.js
│       │   │   ├── analyze.sh
│       │   │   ├── docker/
│       │   │   │   ├── nginx.conf
│       │   │   │   └── run-nginx.sh
│       │   │   ├── generate-self-signed-cert.sh
│       │   │   ├── node_modules-to-ramdisk.sh
│       │   │   └── test-with-coverage.sh
│       │   ├── testem.js
│       │   ├── tests/
│       │   │   ├── -temp/
│       │   │   │   └── qunit-xstate-test.ts
│       │   │   ├── acceptance/
│       │   │   │   ├── chat/
│       │   │   │   │   ├── -unread-acceptance-test.ts
│       │   │   │   │   ├── acceptance-test.ts
│       │   │   │   │   ├── in-channel/
│       │   │   │   │   │   └── -acceptance-test.ts
│       │   │   │   │   └── privately-with/
│       │   │   │   │       ├── -acceptance-test.ts
│       │   │   │   │       └── format-code-test.ts
│       │   │   │   ├── compatibility-test.ts
│       │   │   │   ├── contacts/
│       │   │   │   │   └── acceptance-test.ts
│       │   │   │   ├── invite/
│       │   │   │   │   └── acceptance-test.ts
│       │   │   │   ├── login/
│       │   │   │   │   └── acceptance-test.ts
│       │   │   │   ├── logout/
│       │   │   │   │   └── acceptance-test.ts
│       │   │   │   ├── logout-test.ts
│       │   │   │   ├── navigation-scroll-to-top-test.ts
│       │   │   │   ├── notification-permission-prompt-test.ts
│       │   │   │   ├── notifications-test.ts
│       │   │   │   ├── qr/
│       │   │   │   │   └── login/
│       │   │   │   │       ├── receiver-test.ts
│       │   │   │   │       └── sender-test.ts
│       │   │   │   ├── search-test.ts
│       │   │   │   ├── settings/
│       │   │   │   │   ├── acceptance-test.ts
│       │   │   │   │   ├── danger-zone/
│       │   │   │   │   │   └── -acceptance-test.ts
│       │   │   │   │   ├── interface/
│       │   │   │   │   │   └── -acceptance-test.ts
│       │   │   │   │   └── relays/
│       │   │   │   │       └── -acceptance-test.ts
│       │   │   │   ├── setup/
│       │   │   │   │   └── acceptance-test.ts
│       │   │   │   ├── sidebar-test.ts
│       │   │   │   ├── sidebar-visibility-test.ts
│       │   │   │   └── update-banner-test.ts
│       │   │   ├── helpers/
│       │   │   │   ├── factories/
│       │   │   │   │   ├── channel-factory.ts
│       │   │   │   │   └── message-factory.ts
│       │   │   │   ├── index.ts
│       │   │   │   ├── page-objects.ts
│       │   │   │   ├── pages/
│       │   │   │   │   ├── app.ts
│       │   │   │   │   ├── chat.ts
│       │   │   │   │   ├── components/
│       │   │   │   │   │   └── chat.ts
│       │   │   │   │   ├── contacts.ts
│       │   │   │   │   ├── login.ts
│       │   │   │   │   ├── logout.ts
│       │   │   │   │   ├── qr.ts
│       │   │   │   │   ├── settings.ts
│       │   │   │   │   ├── setup.ts
│       │   │   │   │   └── toast.ts
│       │   │   │   ├── setup-relay-connection-mocks.ts
│       │   │   │   ├── setup-test.ts
│       │   │   │   └── track-async-data.ts
│       │   │   ├── index.html
│       │   │   ├── integration/
│       │   │   │   ├── components/
│       │   │   │   │   ├── embedded-media-test.js
│       │   │   │   │   ├── error-card-test.js
│       │   │   │   │   ├── fetch-open-graph-test.js
│       │   │   │   │   ├── pod/
│       │   │   │   │   │   ├── application/
│       │   │   │   │   │   │   └── top-nav/
│       │   │   │   │   │   │       └── locale-select-test.ts
│       │   │   │   │   │   └── chat/
│       │   │   │   │   │       ├── chat-entry/
│       │   │   │   │   │       │   ├── embeds-menu/
│       │   │   │   │   │       │   │   └── component-test.ts
│       │   │   │   │   │       │   └── emoji-test.ts
│       │   │   │   │   │       └── chat-history/
│       │   │   │   │   │           ├── message/
│       │   │   │   │   │           │   ├── embedded-resource-test.ts
│       │   │   │   │   │           │   └── metadata-preview-test.ts
│       │   │   │   │   │           └── new-messages-test.js
│       │   │   │   │   └── settings/
│       │   │   │   │       └── interface-test.ts
│       │   │   │   ├── pods/
│       │   │   │   │   └── components/
│       │   │   │   │       ├── collapsible/
│       │   │   │   │       │   └── component-test.ts
│       │   │   │   │       ├── copy-text-button/
│       │   │   │   │       │   └── component-test.ts
│       │   │   │   │       ├── keyboard-shortcuts/
│       │   │   │   │       │   └── component-test.ts
│       │   │   │   │       ├── modal-static/
│       │   │   │   │       │   └── component-test.ts
│       │   │   │   │       ├── q-r-scanner/
│       │   │   │   │       │   └── component-test.ts
│       │   │   │   │       └── status-icon/
│       │   │   │   │           └── component-test.ts
│       │   │   │   └── routing/
│       │   │   │       └── feature-flags-test.ts
│       │   │   ├── test-helper.ts
│       │   │   ├── tsconfig.json
│       │   │   └── unit/
│       │   │       ├── routes/
│       │   │       │   ├── add-friend/
│       │   │       │   │   └── route-test.ts
│       │   │       │   ├── chat/
│       │   │       │   │   └── route-unit-test.ts
│       │   │       │   └── qr-test.js
│       │   │       ├── service/
│       │   │       │   ├── channels/
│       │   │       │   │   ├── channel-verifier-test.ts
│       │   │       │   │   ├── utils/
│       │   │       │   │   │   └── -vote-sorter-test.ts
│       │   │       │   │   └── vote-verifier-test.ts
│       │   │       │   ├── contacts/
│       │   │       │   │   └── online-checker-test.ts
│       │   │       │   ├── notifications-test.ts
│       │   │       │   └── redirect-manager-test.ts
│       │   │       ├── services/
│       │   │       │   ├── session-test.js
│       │   │       │   └── store-test.js
│       │   │       └── utils/
│       │   │           ├── dom-test.ts
│       │   │           └── string-test.ts
│       │   ├── translations/
│       │   │   ├── de-DE.yaml
│       │   │   ├── en-AU.yaml
│       │   │   ├── en-us.yaml
│       │   │   ├── es-ES.yaml
│       │   │   ├── fr-FR.yaml
│       │   │   ├── ko-KR.yaml
│       │   │   ├── pt-PT.yaml
│       │   │   └── ru-RU.yaml
│       │   ├── tsconfig.compiler-options.json
│       │   ├── tsconfig.json
│       │   ├── types/
│       │   │   ├── dom-purify.d.ts
│       │   │   ├── ember-a11y-testing/
│       │   │   │   └── test-support/
│       │   │   │       └── audit-if.d.ts
│       │   │   ├── ember-cli-clipboard/
│       │   │   │   └── test-support/
│       │   │   │       └── index.d.ts
│       │   │   ├── ember-could-get-used-to-this.d.ts
│       │   │   ├── ember-intl/
│       │   │   │   └── services/
│       │   │   │       └── intl.d.ts
│       │   │   ├── ember-localforage-adapter/
│       │   │   │   ├── adapters/
│       │   │   │   │   └── localforage.d.ts
│       │   │   │   └── serializers/
│       │   │   │       └── localforage.d.ts
│       │   │   ├── ember-modifier.d.ts
│       │   │   ├── ember-service-worker-update-notify/
│       │   │   │   └── test-support/
│       │   │   │       └── updater.d.ts
│       │   │   ├── ember-usable.d.ts
│       │   │   ├── emberclear/
│       │   │   │   ├── addon-services.d.ts
│       │   │   │   ├── ember-data.d.ts
│       │   │   │   └── index.d.ts
│       │   │   ├── emojis.d.ts
│       │   │   ├── global.d.ts
│       │   │   ├── index.d.ts
│       │   │   ├── overrides.d.ts
│       │   │   ├── prismjs/
│       │   │   │   └── index.d.ts
│       │   │   ├── qr-scanner.d.ts
│       │   │   ├── qunit-xstate-test.d.ts
│       │   │   └── toastify-js.d.ts
│       │   └── vendor/
│       │       └── shims/
│       │           ├── libsodium-wrappers.js
│       │           ├── libsodium.js
│       │           ├── localforage.js
│       │           └── qrcode.js
│       ├── libraries/
│       │   ├── questionably-typed/
│       │   │   ├── .eslintignore
│       │   │   ├── .eslintrc.js
│       │   │   ├── .gitignore
│       │   │   ├── package.json
│       │   │   ├── tsconfig.json
│       │   │   └── types/
│       │   │       ├── globals.ts
│       │   │       ├── libraries/
│       │   │       │   ├── blakejs.ts
│       │   │       │   ├── ember.ts
│       │   │       │   └── promise-worker-bi.ts
│       │   │       ├── overrides.ts
│       │   │       ├── package-augmentations.ts
│       │   │       └── tsconfig.json
│       │   └── tsconfig.json
│       ├── package.json
│       ├── pinochle/
│       │   ├── .editorconfig
│       │   ├── .ember-cli
│       │   ├── .eslintignore
│       │   ├── .eslintrc.js
│       │   ├── .gitignore
│       │   ├── .template-lintrc.js
│       │   ├── .watchmanconfig
│       │   ├── README.md
│       │   ├── app/
│       │   │   ├── app.ts
│       │   │   ├── components/
│       │   │   │   ├── back-of-cards.hbs
│       │   │   │   ├── back-of-cards.ts
│       │   │   │   ├── hand/
│       │   │   │   │   ├── -animation/
│       │   │   │   │   │   ├── card-chart.ts
│       │   │   │   │   │   ├── card.ts
│       │   │   │   │   │   ├── hand-chart.ts
│       │   │   │   │   │   ├── hand.ts
│       │   │   │   │   │   └── key-frames.ts
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   └── index.ts
│       │   │   │   ├── host-game/
│       │   │   │   │   ├── -statechart.ts
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   └── index.ts
│       │   │   │   ├── join-game/
│       │   │   │   │   ├── -statechart.ts
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   └── index.ts
│       │   │   │   ├── lazy/
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   └── index.ts
│       │   │   │   ├── loader/
│       │   │   │   │   ├── ellipsis.hbs
│       │   │   │   │   └── indeterminate.hbs
│       │   │   │   ├── name-entry/
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   └── index.ts
│       │   │   │   ├── options.hbs
│       │   │   │   ├── options.ts
│       │   │   │   ├── play/
│       │   │   │   │   └── as-guest/
│       │   │   │   │       ├── -statechart.ts
│       │   │   │   │       ├── index.hbs
│       │   │   │   │       ├── index.ts
│       │   │   │   │       ├── overlay-info.hbs
│       │   │   │   │       └── players-offline.hbs
│       │   │   │   ├── player-list.hbs
│       │   │   │   ├── player-order/
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   └── index.ts
│       │   │   │   ├── playing-card/
│       │   │   │   │   ├── corner-value.hbs
│       │   │   │   │   ├── face-value.hbs
│       │   │   │   │   └── index.hbs
│       │   │   │   ├── share-link.hbs
│       │   │   │   └── share-link.ts
│       │   │   ├── config/
│       │   │   │   └── environment.d.ts
│       │   │   ├── game/
│       │   │   │   ├── card.ts
│       │   │   │   ├── deck.ts
│       │   │   │   ├── meld.ts
│       │   │   │   ├── networking/
│       │   │   │   │   ├── -requirements.ts
│       │   │   │   │   ├── constants.ts
│       │   │   │   │   ├── guest/
│       │   │   │   │   │   ├── display-info.ts
│       │   │   │   │   │   ├── game-round.ts
│       │   │   │   │   │   └── utils.ts
│       │   │   │   │   ├── guest.ts
│       │   │   │   │   ├── host/
│       │   │   │   │   │   ├── game-round.ts
│       │   │   │   │   │   ├── game-state.ts
│       │   │   │   │   │   ├── types.ts
│       │   │   │   │   │   └── utils.ts
│       │   │   │   │   ├── host.ts
│       │   │   │   │   └── types.ts
│       │   │   │   ├── trick.ts
│       │   │   │   └── utils/
│       │   │   │       └── move-validation.ts
│       │   │   ├── helpers/
│       │   │   │   ├── and.ts
│       │   │   │   ├── contains.ts
│       │   │   │   ├── english-list.ts
│       │   │   │   ├── eq.ts
│       │   │   │   ├── is-number.ts
│       │   │   │   ├── not.ts
│       │   │   │   ├── or.ts
│       │   │   │   └── suit-to-symbol.ts
│       │   │   ├── index.html
│       │   │   ├── modifiers/
│       │   │   │   ├── fit-text.ts
│       │   │   │   ├── resize.ts
│       │   │   │   └── stack.ts
│       │   │   ├── router.ts
│       │   │   ├── routes/
│       │   │   │   ├── game.ts
│       │   │   │   └── join.ts
│       │   │   ├── services/
│       │   │   │   ├── game-manager.ts
│       │   │   │   ├── guest/
│       │   │   │   │   ├── dispatcher.ts
│       │   │   │   │   └── handler.ts
│       │   │   │   └── player-info.ts
│       │   │   ├── styles/
│       │   │   │   ├── -variables.css
│       │   │   │   ├── app.css
│       │   │   │   ├── game.css
│       │   │   │   ├── loading.css
│       │   │   │   ├── page/
│       │   │   │   │   └── ask-game-type.css
│       │   │   │   ├── playing-card.css
│       │   │   │   ├── resets.css
│       │   │   │   ├── synthwave.css
│       │   │   │   ├── transitions.css
│       │   │   │   ├── utils.css
│       │   │   │   └── z-indexes.css
│       │   │   ├── templates/
│       │   │   │   ├── application.hbs
│       │   │   │   ├── game-full.hbs
│       │   │   │   ├── game.hbs
│       │   │   │   ├── host.hbs
│       │   │   │   ├── index.hbs
│       │   │   │   ├── join.hbs
│       │   │   │   └── not-recognized.hbs
│       │   │   ├── tsconfig.json
│       │   │   └── utils/
│       │   │       ├── array.ts
│       │   │       ├── container.ts
│       │   │       ├── dom.ts
│       │   │       ├── trig.ts
│       │   │       └── use-machine.ts
│       │   ├── config/
│       │   │   ├── ember-cli-update.json
│       │   │   ├── environment.js
│       │   │   ├── netlify/
│       │   │   │   └── _redirects
│       │   │   ├── optional-features.json
│       │   │   └── targets.js
│       │   ├── ember-cli-build.js
│       │   ├── package.json
│       │   ├── public/
│       │   │   └── robots.txt
│       │   ├── testem.js
│       │   ├── tests/
│       │   │   ├── -pages/
│       │   │   │   └── join.ts
│       │   │   ├── acceptance/
│       │   │   │   ├── game-test.ts
│       │   │   │   └── join-test.ts
│       │   │   ├── helpers/
│       │   │   │   ├── .gitkeep
│       │   │   │   └── index.ts
│       │   │   ├── index.html
│       │   │   ├── integration/
│       │   │   │   ├── components/
│       │   │   │   │   ├── host-game-test.ts
│       │   │   │   │   ├── lazy-test.ts
│       │   │   │   │   ├── playing-card-test.ts
│       │   │   │   │   └── share-link-test.js
│       │   │   │   └── modifiers/
│       │   │   │       ├── fit-text-test.js
│       │   │   │       ├── resize-test.js
│       │   │   │       └── stack-test.js
│       │   │   ├── test-helper.ts
│       │   │   ├── tsconfig.json
│       │   │   ├── type-support.ts
│       │   │   └── unit/
│       │   │       ├── game/
│       │   │       │   ├── deck-test.ts
│       │   │       │   ├── meld-test.ts
│       │   │       │   ├── state-test.ts
│       │   │       │   ├── trick-test.ts
│       │   │       │   └── utils/
│       │   │       │       ├── availableMoves-test.ts
│       │   │       │       └── isValidMove-test.ts
│       │   │       └── helpers/
│       │   │           ├── contains-test.ts
│       │   │           ├── eq-test.ts
│       │   │           ├── is-number-test.ts
│       │   │           └── suit-to-symbol-test.ts
│       │   ├── translations/
│       │   │   └── en-us.yaml
│       │   ├── tsconfig.compiler-options.json
│       │   ├── tsconfig.json
│       │   ├── types/
│       │   │   ├── libraries.d.ts
│       │   │   └── overrides.d.ts
│       │   └── vendor/
│       │       └── .gitkeep
│       ├── scripts/
│       │   └── clean.sh
│       ├── smoke-tests/
│       │   ├── .eslintrc.js
│       │   ├── .faltestrc.js
│       │   ├── .prettierrc.js
│       │   ├── helpers/
│       │   │   └── start-server.js
│       │   ├── package.json
│       │   ├── page-objects/
│       │   │   ├── add-friend.js
│       │   │   ├── chat.js
│       │   │   └── login.js
│       │   └── tests/
│       │       └── smoke-test.js
│       ├── stylelint.config.js
│       └── tsconfig.json
├── crowdin.yml
├── images/
│   └── icon.xcf
└── scripts/
    ├── deploy
    ├── docker-compose.yml
    ├── dockerhub
    ├── install-chrome-apt
    └── publish

================================================
FILE CONTENTS
================================================

================================================
FILE: .codeclimate.yml
================================================
version: 2
plugins:
  duplication:
    enabled: true
    config:
      languages:
        javascript:
          mass_threshold: 50

  # TODO: errors
  fixme:
    enabled: false

exclude_patterns:
- '**/english.ts'
- '**/benchmarks/'
- '**/ember-cli-build.js'
- 'benchmarks/'
- 'client/android-wrapper/'
- 'relays/'
- 'client/web/emberclear/config/'
- 'client/web/emberclear/tests/'
- 'client/web/emberclear/vendor/'
- 'client/web/emberclear/dist/'
- 'client/web/emberclear/types/'
- '**/node_modules/'
- '**/dist/'
- '**/tests/'
- '**/config/'
- '**/script/'
- '**/vendor/'
- '**/*.d.ts'


================================================
FILE: .editorconfig
================================================
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org

root = true


[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = space
indent_size = 2

[*.hbs]
insert_final_newline = false

[*.{diff,md}]
trim_trailing_whitespace = false


================================================
FILE: .github/renovate.json5
================================================
// Docs:
// https://docs.renovatebot.com/configuration-options/
{
  "extends": [
    "config:base",
    "github>NullVoxPopuli/renovate:weekly.json5",
    "github>NullVoxPopuli/renovate:npm-groups.json5"
  ],
  "automerge": false,
  "masterIssue": true,
  "ignorePaths": [
      // Deployed once and forgotten
      "client/android-wrapper"
  ],
  "packageRules": [
    {
      // These are one-time experiements and don't need to be kept up to date
      "paths": ["benchmarks/**"],
      "enabled": false
    },
    {
      // libraries and addons aka "non-apps"
      "paths": ["client/web/addons/**/package.json", "client/web/libraries/**/package.json"],
      "rangeStrategy": "bump",
      "schedule": ["after 9pm on sunday"]
    },
    {
      "paths": ["client/web/emberclear/package.json", "client/web/pinochle/package.json"],
      // Pin requires more package.json/lockfile churn,
      // but it allows us to determine if an otherwise floating dep
      // introduced a regression
      "rangeStrategy": "pin",
      // then setting a schedule reduces the churn and allows for PRs to be combined with the groups below
      "schedule": ["after 9pm on sunday"]
    },
    {
      "paths": ["client/web/emberclear/Dockerfile"],
      "enabled": false
    },
    ////////////////////////////////////////
    // Grouping namespaced packages together
    ////////////////////////////////////////
    {
      "packagePatterns": ["^@babel*"],
      "schedule": ["after 9pm on sunday"],
      "groupName": "Babel Transpilation"
    },
    {
      "packagePatterns": ["^@ember-data*"],
      "schedule": ["after 9pm on sunday"],
      "groupName": "Ember Data"
    },
    {
      "packagePatterns": ["^@faltest*"],
      "schedule": ["after 9pm on sunday"],
      "groupName": "FalTest Smoke Testing by CrowdStrike"
    },
    {
      "packagePatterns": ["^@types\/*"],
      "schedule": ["after 9pm on sunday"],
      "groupName": "Type Definitions"
    },
    {
      "packagePatterns": ["^@embroider*"],
      "schedule": ["after 9pm on sunday"],
      "groupName": "embroider"
    },
    {
      "groupName": "Lint Dependencies",
      "schedule": ["after 9pm on sunday"],
      "packageNames": [
        "eslint",
        "babel-eslint",
        "ember-template-lint",
        "prettier"
      ],
      "packagePatterns": [
        "eslint-plugin-.*",
        "eslint-config-.*",
        ".*typescript-eslint.*",
        "^@commitlint\/*",
        "^remark-*"
      ],
    },
     // These are dependencies that come default when
    // generating a new ember addon
    {
      "groupName": "Framework Dependencies",
      "packageNames": [
        "@ember/optional-features",
        "@glimmer/component",
        "@glimmer/tracking",
        "ember-disable-prototype-extensions",
        "ember-export-application-global",
        "ember-load-initializers",
        "ember-maybe-import-regenerator",
        "ember-resolver",
        "ember-source",
        "ember-cli-page-title"
      ]
    },
    {
      "groupName": "CLI Dependencies",
      "schedule": ["after 9pm on sunday"],
      "packageNames": [
        "broccoli-asset-rev",
        "ember-cli",
        "ember-auto-import",
        "ember-cli-dependency-checker",
        "ember-cli-inject-live-reload",
        "ember-cli-sri",
        "ember-cli-terser",
        "ember-cli-htmlbars"
      ]
    },
    {
      "groupName": "Testing Dependencies",
      "schedule": ["after 9pm on sunday"],
      "packageNames": [
        "qunit-dom",
        "ember-try",
        "ember-source-channel-url",
        "ember-qunit",
        "qunit",
        "npm-run-all",
        "@xstate/test",
        "ember-cli-page-object",
        "fractal-page-object"
      ]
    }
  ]
}


================================================
FILE: .github/workflows/web-addon-crypto.yml
================================================
name: '@emberclear/crypto'

# Inspiration:
# https://github.com/alexdiliberto/ember-transformicons/blob/master/.github/workflows/ci.yml
on:
  pull_request:
  push:
    # filtering branches here prevents duplicate builds from pull_request and push
    branches:
      - master
    paths:
      - 'client/web/addons/crypto/'

env:
  CI: true
  root: client/web/
  addon: addons/crypto/
  full: client/web/addons/crypto/

jobs:
  lint:
    if: "! contains(toJSON(github.event.commits.*.message), '[skip ci]')"
    name: 'Lint'
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1
    - name: Install
      working-directory: ${{ env.root }}
      run: yarn install

    - name: "JS/TS"
      working-directory: ${{ env.full }}
      run: yarn eslint . --ext js,ts

    - name: "Templates"
      working-directory: ${{ env.full }}
      run: yarn ember-template-lint .

    - name: 'Type Correctness'
      working-directory: ${{ env.full }}
      run: yarn tsc --build

    # - uses: wagoid/commitlint-github-action@v1
    #   env:
    #     GITHUB_TOKEN: ${{ secrets.GH_PAT }}

  tests_ember_compat:
    if: "! contains(toJSON(github.event.commits.*.message), '[skip ci]')"
    name: Ember Compatability
    runs-on: ubuntu-latest
    timeout-minutes: 5
    strategy:
      matrix:
        scenario:
        # - "ember-lts-3.16"
        - "ember-lts-3.20"
        # - "ember-release"
        # - "ember-beta"
        # - "ember-canary"
    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1

    - name: Install
      run: yarn install
      working-directory: ${{ env.root }}

    - name: "Test: ${{ matrix.scenario }}"
      working-directory: ${{ env.full }}
      run: yarn test:try-one ${{ matrix.scenario }}



================================================
FILE: .github/workflows/web-addon-encoding.yml
================================================
name: '@emberclear/encoding'

# Inspiration:
# https://github.com/alexdiliberto/ember-transformicons/blob/master/.github/workflows/ci.yml
on:
  pull_request:
  push:
    # filtering branches here prevents duplicate builds from pull_request and push
    branches:
      - master
    paths:
      - 'client/web/addons/encoding/'


env:
  CI: true
  root: client/web/
  addon: addons/encoding/
  full: client/web/addons/encoding/

jobs:
  lint:
    if: "! contains(toJSON(github.event.commits.*.message), '[skip ci]')"
    name: 'Lint'
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1
    - name: Install
      working-directory: ${{ env.root }}
      run: yarn install

    - name: "JS/TS"
      working-directory: ${{ env.full }}
      run: yarn eslint . --ext js,ts

    - name: "Templates"
      working-directory: ${{ env.full }}
      run: yarn ember-template-lint .

    - name: 'Type Correctness'
      working-directory: ${{ env.full }}
      run: yarn tsc --build

    # - uses: wagoid/commitlint-github-action@v1
    #   env:
    #     GITHUB_TOKEN: ${{ secrets.GH_PAT }}

  tests_ember_compat:
    if: "! contains(toJSON(github.event.commits.*.message), '[skip ci]')"
    name: Ember Compatability
    runs-on: ubuntu-latest
    timeout-minutes: 5
    strategy:
      matrix:
        scenario:
        # - "ember-lts-3.16"
        - "ember-lts-3.20"
        # - "ember-release"
        # - "ember-beta"
        # - "ember-canary"
    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1

    - name: Install
      run: yarn install
      working-directory: ${{ env.root }}

    - name: "Test: ${{ matrix.scenario }}"
      working-directory: ${{ env.full }}
      run: yarn test:try-one ${{ matrix.scenario }}



================================================
FILE: .github/workflows/web-addon-local-account.yml
================================================
name: '@emberclear/local-account'

# Inspiration:
# https://github.com/alexdiliberto/ember-transformicons/blob/master/.github/workflows/ci.yml
on:
  pull_request:
  push:
    # filtering branches here prevents duplicate builds from pull_request and push
    branches:
      - master
    paths:
      - 'client/web/addons/local-account/'

env:
  CI: true
  root: client/web/
  addon: addons/local-account/
  full: client/web/addons/local-account/

jobs:
  lint:
    if: "! contains(toJSON(github.event.commits.*.message), '[skip ci]')"
    name: 'Lint'
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1
    - name: Install
      working-directory: ${{ env.root }}
      run: yarn install

    - name: "JS/TS"
      working-directory: ${{ env.full }}
      run: yarn eslint . --ext js,ts

    - name: "Templates"
      working-directory: ${{ env.full }}
      run: yarn ember-template-lint .

    - name: 'Type Correctness'
      working-directory: ${{ env.full }}
      run: yarn tsc --build

    # - uses: wagoid/commitlint-github-action@v1
    #   env:
    #     GITHUB_TOKEN: ${{ secrets.GH_PAT }}

  tests_ember_compat:
    if: "! contains(toJSON(github.event.commits.*.message), '[skip ci]')"
    name: Ember Compatability
    runs-on: ubuntu-latest
    timeout-minutes: 5
    strategy:
      matrix:
        scenario:
        # - "ember-lts-3.16"
        - "ember-lts-3.20"
        # - "ember-release"
        # - "ember-beta"
        # - "ember-canary"
    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1

    - name: Install
      run: yarn install
      working-directory: ${{ env.root }}

    - name: "Test: ${{ matrix.scenario }}"
      working-directory: ${{ env.full }}
      run: yarn test:try-one ${{ matrix.scenario }}



================================================
FILE: .github/workflows/web-addon-networking.yml
================================================
name: '@emberclear/networking'

# Inspiration:
# https://github.com/alexdiliberto/ember-transformicons/blob/master/.github/workflows/ci.yml
on:
  pull_request:
  push:
    # filtering branches here prevents duplicate builds from pull_request and push
    branches:
      - master
    paths:
      - 'client/web/addons/networking/'

env:
  CI: true
  root: client/web/
  addon: addons/networking/
  full: client/web/addons/networking/

jobs:
  lint:
    if: "! contains(toJSON(github.event.commits.*.message), '[skip ci]')"
    name: 'Lint'
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1
    - name: Install
      working-directory: ${{ env.root }}
      run: yarn install

    - name: "JS/TS"
      working-directory: ${{ env.full }}
      run: yarn eslint . --ext js,ts

    - name: "Templates"
      working-directory: ${{ env.full }}
      run: yarn ember-template-lint .

    - name: 'Type Correctness'
      working-directory: ${{ env.full }}
      run: yarn tsc --build

    # - uses: wagoid/commitlint-github-action@v1
    #   env:
    #     GITHUB_TOKEN: ${{ secrets.GH_PAT }}

  tests_ember_compat:
    if: "! contains(toJSON(github.event.commits.*.message), '[skip ci]')"
    name: Ember Compatability
    runs-on: ubuntu-latest
    timeout-minutes: 5
    strategy:
      matrix:
        scenario:
        # - "ember-lts-3.16"
        - "ember-lts-3.20"
        # - "ember-release"
        # - "ember-beta"
        # - "ember-canary"
    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1

    - name: Install
      run: yarn install
      working-directory: ${{ env.root }}

    - name: "Test: ${{ matrix.scenario }}"
      working-directory: ${{ env.full }}
      run: yarn test:try-one ${{ matrix.scenario }}



================================================
FILE: .github/workflows/web-addon-test-helpers.yml
================================================
name: '@emberclear/test-helpers'

# Inspiration:
# https://github.com/alexdiliberto/ember-transformicons/blob/master/.github/workflows/ci.yml
on:
  pull_request:
  push:
    # filtering branches here prevents duplicate builds from pull_request and push
    branches:
      - master
    paths:
      - 'client/web/addons/test-helpers/'

env:
  CI: true
  root: client/web/
  addon: addons/test-helpers/
  full: client/web/addons/test-helpers/

jobs:
  lint:
    if: "! contains(toJSON(github.event.commits.*.message), '[skip ci]')"
    name: 'Lint'
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1
    - name: Install
      working-directory: ${{ env.root }}
      run: yarn install

    - name: "JS/TS"
      working-directory: ${{ env.full }}
      run: yarn eslint . --ext js,ts

    - name: "Templates"
      working-directory: ${{ env.full }}
      run: yarn ember-template-lint .

    - name: 'Type Correctness'
      working-directory: ${{ env.full }}
      run: yarn tsc --build

    # - uses: wagoid/commitlint-github-action@v1
    #   env:
    #     GITHUB_TOKEN: ${{ secrets.GH_PAT }}

  tests_ember_compat:
    if: "! contains(toJSON(github.event.commits.*.message), '[skip ci]')"
    name: Ember Compatability
    runs-on: ubuntu-latest
    timeout-minutes: 5
    strategy:
      matrix:
        scenario:
        # - "ember-lts-3.16"
        - "ember-lts-3.20"
        # - "ember-release"
        # - "ember-beta"
        # - "ember-canary"
    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1

    - name: Install
      run: yarn install
      working-directory: ${{ env.root }}

    - name: "Test: ${{ matrix.scenario }}"
      working-directory: ${{ env.full }}
      run: yarn test:try-one ${{ matrix.scenario }}



================================================
FILE: .github/workflows/web-addon-tracked-local-storage.yml
================================================
name: 'ember-tracked-local-storage'

# Inspiration:
# https://github.com/alexdiliberto/ember-transformicons/blob/master/.github/workflows/ci.yml
on:
  pull_request:
  push:
    # filtering branches here prevents duplicate builds from pull_request and push
    branches:
      - master
    paths:
      - 'client/web/addons/tracked-local-storage/'

env:
  CI: true
  root: client/web/
  addon: addons/tracked-local-storage/
  full: client/web/addons/tracked-local-storage/

jobs:
  lint:
    if: "! contains(toJSON(github.event.commits.*.message), '[skip ci]')"
    name: 'Lint'
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1
    - name: Install
      working-directory: ${{ env.root }}
      run: yarn install

    - name: "JS/TS"
      working-directory: ${{ env.full }}
      run: yarn eslint . --ext js,ts

    - name: "Templates"
      working-directory: ${{ env.full }}
      run: yarn ember-template-lint .

    - name: 'Type Correctness'
      working-directory: ${{ env.full }}
      run: yarn tsc --build

    # - uses: wagoid/commitlint-github-action@v1
    #   env:
    #     GITHUB_TOKEN: ${{ secrets.GH_PAT }}

  tests_ember_compat:
    if: "! contains(toJSON(github.event.commits.*.message), '[skip ci]')"
    name: Ember Compatability
    runs-on: ubuntu-latest
    timeout-minutes: 5
    strategy:
      matrix:
        scenario:
        - "ember-lts-3.16"
        - "ember-lts-3.20"
        - "ember-release"
        - "ember-beta"
        - "ember-canary"
    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1

    - name: Install
      run: yarn install
      working-directory: ${{ env.root }}

    - name: "Test: ${{ matrix.scenario }}"
      working-directory: ${{ env.full }}
      run: yarn test:try-one ${{ matrix.scenario }}

  # TODO: figure out if this supports working-directory
  # publish:
  #   name: Release
  #   runs-on: ubuntu-latest
  #   if: github.ref == 'refs/heads/master'
  #   needs: [tests_ember_compat, lint]

  #   steps:
  #     - uses: actions/checkout@v1
  #     - uses: volta-cli/action@v1

  #     - run: yarn install
  #       working-directory: ${{ env.root }}

  #     - name: Release
  #       working-directory: ${{ env.root }}
  #       env:
  #         GITHUB_TOKEN: ${{ secrets.GH_PAT }}
  #         NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
  #       run: yarn semantic-release


================================================
FILE: .github/workflows/web-addon-ui.yml
================================================
name: 'Web @emberclear/ui'
on:
  pull_request:
    branches: [master]
    paths:
    - 'client/web/addons/ui/**'
    - 'client/web/package.json'

env:
  root: client/web/
  addon: addons/ui/
  full: client/web/addons/ui/

jobs:
  lint:
    name: 'Lint'
    runs-on: ubuntu-latest
    timeout-minutes: 5

    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1

    - name: Install
      working-directory: ${{ env.root }}
      run: yarn install

    - name: "JS/TS"
      working-directory: ${{ env.root }}
      run: yarn eslint ${{ env.addon }} --ext js,ts

    - name: "Templates"
      working-directory: ${{ env.full }}
      run: yarn ember-template-lint .

    - name: "Styles"
      working-directory: ${{ env.root }}
      run: yarn stylelint ${{ env.addon }}**/*.css

    - name: 'Type Correctness'
      working-directory: ${{ env.full }}
      run: yarn tsc --build

  test:
    name: 'Test'
    runs-on: ubuntu-latest
    timeout-minutes: 5

    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1

    - name: Install
      working-directory: ${{ env.root }}
      run: yarn install

    - name: Ember
      working-directory: "${{ env.root }}/${{ env.addon }}"
      run: yarn test







================================================
FILE: .github/workflows/web-app-deploy.yml
================================================
name: Web App Deploy
on:
  push:
    branches: [master]
    paths:
    - 'client/web/**'

env:
  cwd: client/web/emberclear

jobs:
  tests:
    name: Tests
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1

    - name: Install
      working-directory: ${{ env.cwd }}
      run: yarn install

    - name: Test
      working-directory: ${{ env.cwd }}
      env:
        PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }}
      # run: ./scripts/test-with-coverage.sh
      run: yarn ember test

    # Coverage Disabled while these are worked out:
    # https://github.com/babel/ember-cli-babel/issues/350
    # https://github.com/kategengler/ember-cli-code-coverage/issues/265
    # - name: Upload Coverage to Coveralls
    #   uses: coverallsapp/github-action@v1.0.1
    #   with:
    #     github-token: ${{ secrets.github_token }}
    #     path-to-lcov: ./client/web/emberclear/coverage/lcov.info

    # - name: Upload Coverage Artifacts
    #   uses: actions/upload-artifact@v1
    #   with:
    #     name: coverage
    #     path: client/web/emberclear/coverage/

  deploy:
    name: Deploy to Netlify
    runs-on: ubuntu-latest
    timeout-minutes: 15
    needs:
    - tests

    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1

    # - name: Download Coverage Artifacts
    #   uses: actions/download-artifact@v1
    #   with:
    #     name: coverage
    #     path: client/web/emberclear/coverage/

    - name: Install
      working-directory: ${{ env.cwd }}
      run: yarn install

    - run: yarn global add netlify-cli
    - name: Deploy to Netlify
      env:
        FRONTEND: client/web/emberclear
        NETLIFY_ACCESS_TOKEN: ${{ secrets.NETLIFY_ACCESS_TOKEN }}
        NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
      run: |
        COVERAGE_DIR="client/web/emberclear/coverage"

        if [ -d "$COVERAGE_DIR" ]; then
          mv $COVERAGE_DIR client/web/emberclear/public/
        fi

        ( cd client/web/emberclear \
          && time yarn analyze \
          && time yarn build:production
        )

        time ./scripts/publish

    - name: Upload Built Asset Artifacts
      uses: actions/upload-artifact@master
      with:
        name: frontend-assets
        path: client/web/emberclear/dist/

  deploy_docker:
    name: Deploy Docker Image
    runs-on: ubuntu-latest
    needs: [tests, deploy]
    timeout-minutes: 5

    steps:
    - uses: actions/checkout@v2
    - name: Download Built Asset Artifacts
      uses: actions/download-artifact@master
      with:
        name: frontend-assets
        path: client/web/emberclear/dist/

    - name: Publish to Registry
      uses: elgohr/Publish-Docker-Github-Action@master
      with:
        name: nullvoxpopuli/emberclear
        username: ${{ secrets.DOCKERHUB_USER }}
        password: ${{ secrets.DOCKERHUB_PASSWORD }}
        snapshot: true
        workdir: client/web/emberclear
        dockerfile: Dockerfile.release

  tests_e2e:
    name: E2E Tests
    runs-on: ubuntu-latest
    timeout-minutes: 15
    needs: [deploy]

    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1

    - name: Test
      run: |
        cd client/web/smoke-tests \
        && yarn \
        && yarn test --headless


# Deploy via Script (requires docker environment on VM)
#     - uses: actions/docker/cli@master
#     - name: Publish to DockerHub
#       env:
#         DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
#         DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }}
#         # DOCKER_HOST: tcp://docker:2375/
#         # DOCKER_DRIVER: overlay2
#       run: sh ./scripts/dockerhub





================================================
FILE: .github/workflows/web-app-quality.yml
================================================
name: Web App Quality
on:
  pull_request:
    branches: [master]
    paths:
    - 'client/web/emberclear/**'
    - 'client/web/package.json'

env:
  root: client/web/
  app: emberclear/
  full: client/web/emberclear/

jobs:
  security:
    name: Dependency Security
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1

    - name: Install
      run: volta install node && volta install snyk

    - name: Snyk
      working-directory: ${{ env.root }}
      if: github.event == 'pull_request'
      env:
        SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
      run: snyk test --severity-threshold=high

  lint:
    name: "Lint JS/TS & Type Checking"
    runs-on: ubuntu-latest
    timeout-minutes: 5

    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1

    - name: Install
      working-directory: ${{ env.root }}
      run: yarn install

    - name: "JS/TS"
      working-directory: ${{ env.root }}
      run: yarn eslint ${{ env.app }} --ext js,ts

    - name: "Templates"
      working-directory: ${{ env.full }}
      run: yarn ember-template-lint .

    - name: "Styles"
      working-directory: ${{ env.root }}
      run: yarn stylelint ${{ env.app }}**/*.css

    - name: "Translations"
      working-directory: ${{ env.full }}
      run: yarn lint:i18n
      continue-on-error: true

    - name: 'Type Correctness'
      working-directory: ${{ env.full }}
      run: yarn tsc --build



================================================
FILE: .github/workflows/web-app-tests.yml
================================================
name: Web App Tests
on:
  pull_request:
    branches: [master]
    paths:
    - 'client/web/**'

env:
  cwd: client/web/emberclear
  name: emberclear

##############################################################

jobs:
  tests:
    name: Tests
    strategy:
      matrix:
        # os: [ubuntu-latest, macOS-latest, windows-latest]
        # browsers: [chrome, firefox, safari, edge]
        ci_browser:
        - Chrome
        # Firefox is flaky in Github........
        # - Firefox

    runs-on: ubuntu-latest
    timeout-minutes: 15

    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1
    - uses: actions/cache@v2
      with:
        path: '**/node_modules'
        key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}

    - name: Install
      working-directory: ${{ env.cwd }}
      run: yarn install

    - name: Test
      working-directory: ${{ env.cwd }}
      env:
        PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }}
        CI_BROWSER: ${{ matrix.ci_browser }}
      # run: ./scripts/test-with-coverage.sh
      run: yarn ember test

    # Coverage Disabled while these are worked out:
    # https://github.com/babel/ember-cli-babel/issues/350
    # https://github.com/kategengler/ember-cli-code-coverage/issues/265
    #
    # - name: Upload Coverage to Coveralls
    #   uses: coverallsapp/github-action@v1.0.1
    #   with:
    #     github-token: ${{ secrets.github_token }}
    #     path-to-lcov: ./client/web/emberclear/coverage/lcov.info

    # - name: Upload Coverage Artifacts
    #   uses: actions/upload-artifact@v1
    #   with:
    #     name: coverage
    #     path: client/web/emberclear/coverage/


##############################################################
#
  bundle_analysis:
    name: Bundle Analysis
    runs-on: ubuntu-latest
    timeout-minutes: 15

    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1
    - uses: actions/cache@v2
      with:
        path: '**/node_modules'
        key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}

    - name: Install
      working-directory: ${{ env.cwd }}
      run: yarn install

    - name: Analyze Bundle
      working-directory: ${{ env.cwd }}
      run: yarn analyze

    - name: Upload Bundle Analysis Artifacts
      uses: actions/upload-artifact@v2
      with:
        name: built_bundle_analysis
        path: client/web/emberclear/public/bundle


  build_app:
    name: Build App
    runs-on: ubuntu-latest
    timeout-minutes: 10

    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1
    - uses: actions/cache@v2
      with:
        path: '**/node_modules'
        key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
    - name: Install and Build
      run: |
        ( cd client/web/emberclear && yarn install && yarn build:production )
        cp ${{ env.cwd }}/config/netlify/_redirects ${{ env.cwd }}/dist

    - name: Upload App Artifacts
      uses: actions/upload-artifact@v2
      with:
        name: built_app
        path: client/web/emberclear/dist/

##############################################################

  tests_e2e:
    name: E2E Tests
    runs-on: ubuntu-latest
    timeout-minutes: 15
    needs: [deploy_preview]

    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1

    - name: Get Deploy URL
      uses: actions/download-artifact@master
      with:
        name: deploy-url
        path: ./

    - name: Test
      run: |
        export DEPLOY_URL=$(cat ./deploy-url.txt)
        cd client/web/smoke-tests
        DETECT_CHROMEDRIVER_VERSION=true yarn
        yarn test --target pull-request --headless


##############################################################

  deploy_preview:
    name: Deploy Preview
    runs-on: ubuntu-latest
    timeout-minutes: 15
    needs: [bundle_analysis, build_app]

    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1

    - name: Download Built Bundle Analysis Artifacts
      uses: actions/download-artifact@master
      with:
        name: built_bundle_analysis
        path: ./deploy/bundle-analysis/

    - name: Download Built App Artifacts
      uses: actions/download-artifact@master
      with:
        name: built_app
        path: ./deploy/app/

    - name: Combine Bundle Analysis with App
      run: |
        mkdir -p ./deploy/dist/bundle/
        mv ./deploy/app/* ./deploy/dist/
        cp ./deploy/bundle-analysis/* ./deploy/dist/bundle/
        cp ${{ env.cwd }}/config/netlify/_redirects ./deploy/dist/

    - name: Deploy to Netlify
      id: deploy
      uses: nwtgck/actions-netlify@v1.2.2
      with:
        publish-dir: './deploy/dist'
        production-branch: __handled_separately__
        github-token: ${{ secrets.GITHUB_TOKEN }}
      env:
        NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_ACCESS_TOKEN }}
        NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}

    - run: echo "${{ steps.deploy.outputs.deploy-url }}" > deploy-url.txt

    - name: Upload URL as Artifact
      uses: actions/upload-artifact@v2
      with:
        name: deploy-url
        path: deploy-url.txt


##############################################################

  lhci:
    name: Lighthouse CI
    runs-on: ubuntu-latest
    needs: [build_app]

    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1

    - name: Download Built App Artifacts
      uses: actions/download-artifact@master
      with:
        name: built_app
        path: client/web/emberclear/dist/

    - name: run Lighthouse
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
      run: |
        volta install node
        volta install @lhci/cli@0.3.x
        cd client/web/emberclear

        lhci collect \
          --upload.target=temporary-public-storage \
          --staticDistDir=./dist \
          --githubToken $GITHUB_TOKEN \
          --githubAppToken $LHCI_GITHUB_APP_TOKEN


================================================
FILE: .github/workflows/web-pinochle-deploy.yml
================================================
name: Web Pinochle Deploy
on:
  push:
    branches: [master]
    paths:
    - 'client/web/pinochle/**'
    - '.github/workflows/web-pinochle-*'

env:
  cwd: client/web/pinochle

jobs:
  tests:
    name: Tests
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1

    - name: Install
      working-directory: ${{ env.cwd }}
      run: yarn install

    - name: Test
      working-directory: ${{ env.cwd }}
      # run: ./scripts/test-with-coverage.sh
      run: yarn ember test

    # Coverage Disabled while these are worked out:
    # https://github.com/babel/ember-cli-babel/issues/350
    # https://github.com/kategengler/ember-cli-code-coverage/issues/265
    # - name: Upload Coverage to Coveralls
    #   uses: coverallsapp/github-action@v1.0.1
    #   with:
    #     github-token: ${{ secrets.github_token }}
    #     path-to-lcov: ./client/web/emberclear/coverage/lcov.info

    # - name: Upload Coverage Artifacts
    #   uses: actions/upload-artifact@v1
    #   with:
    #     name: coverage
    #     path: client/web/emberclear/coverage/

  deploy:
    name: Deploy to Netlify
    runs-on: ubuntu-latest
    timeout-minutes: 15
    needs:
    - tests

    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1

    # - name: Download Coverage Artifacts
    #   uses: actions/download-artifact@v1
    #   with:
    #     name: coverage
    #     path: client/web/emberclear/coverage/

    - name: Install
      working-directory: ${{ env.cwd }}
      run: yarn install

    - run: yarn global add netlify-cli
    - name: Deploy to Netlify
      env:
        FRONTEND: ${{ env.cwd }}
        NETLIFY_ACCESS_TOKEN: ${{ secrets.NETLIFY_ACCESS_TOKEN }}
        NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID_PINOCHLE }}
        NETLIFY_CLI_VERSION: 0.4.0
      run: |
        COVERAGE_DIR="${{ env.cwd }}/coverage"

        if [ -d "$COVERAGE_DIR" ]; then
          mv $COVERAGE_DIR ${{ env.cwd }}/public/
        fi

        ( cd ${{ env.cwd }} \
          && time yarn build:production
        )

        time ./scripts/publish

    - name: Upload Built Asset Artifacts
      uses: actions/upload-artifact@master
      with:
        name: frontend-assets
        path: ${{ env.cwd }}/dist/

  # tests_e2e:
  #   name: E2E Tests
  #   runs-on: ubuntu-latest
  #   timeout-minutes: 15
  #   needs:
  #   - deploy

  #   steps:
  #   - name: 'Wait for status checks'
  #     id: waitforstatuschecks
  #     uses: "wyrihaximus/github-action-wait-for-status@v2"
  #     with:
  #       ignoreActions: tests_e2e,"E2E Tests"
  #       checkInterval: 30

  #   - uses: actions/checkout@v2
  #   - uses: volta-cli/action@v1

  #   - name: Test
  #     run: |
  #       cd client/web/smoke-tests \
  #       && yarn \
  #       && yarn test --headless


# Deploy via Script (requires docker environment on VM)
#     - uses: actions/docker/cli@master
#     - name: Publish to DockerHub
#       env:
#         DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
#         DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }}
#         # DOCKER_HOST: tcp://docker:2375/
#         # DOCKER_DRIVER: overlay2
#       run: sh ./scripts/dockerhub





================================================
FILE: .github/workflows/web-pinochle-quality.yml
================================================
name: Web Pinochle Quality
on:
  pull_request:
    branches: [master]
    paths:
    - 'client/web/pinochle/**'
    - 'client/web/package.json'

env:
  root: client/web/
  app: pinochle/
  full: client/web/pinochle/

jobs:
  security:
    name: Dependency Security
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1

    - name: Install
      run: volta install node && volta install snyk

    - name: Snyk
      working-directory: ${{ env.root }}
      if: github.event == 'pull_request'
      env:
        SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
      run: snyk test --severity-threshold=high

  lint:
    name: "Lint JS/TS & Type Checking"
    runs-on: ubuntu-latest
    timeout-minutes: 5

    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1

    - name: Install
      working-directory: ${{ env.root }}
      run: yarn install

    - name: "JS/TS"
      working-directory: ${{ env.root }}
      run: yarn eslint ${{ env.app }} --ext js,ts

    - name: "Templates"
      working-directory: ${{ env.full }}
      run: yarn ember-template-lint .

    - name: "Styles"
      working-directory: ${{ env.root }}
      run: yarn stylelint ${{ env.app }}**/*.css

    - name: 'Type Correctness'
      working-directory: ${{ env.full }}
      run: yarn tsc --build



================================================
FILE: .github/workflows/web-pinochle-tests.yml
================================================
name: Web Pinochle Tests
on:
  pull_request:
    branches: [master]
    paths:
    - 'client/web/pinochle/**'

env:
  cwd: client/web/pinochle
  name: pinochle

##############################################################

jobs:
  tests:
    name: Tests
    strategy:
      matrix:
        # os: [ubuntu-latest, macOS-latest, windows-latest]
        # browsers: [chrome, firefox, safari, edge]
        ci_browser:
        - Chrome
        - Firefox
        # - Safari

    runs-on: ubuntu-latest
    timeout-minutes: 15

    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1
    - uses: actions/cache@v2
      with:
        path: '**/node_modules'
        key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}

    - name: Install
      working-directory: ${{ env.cwd }}
      run: yarn install

    - name: Test
      working-directory: ${{ env.cwd }}
      env:
        CI_BROWSER: ${{ matrix.ci_browser }}
      # run: ./scripts/test-with-coverage.sh
      run: yarn ember test

    # Coverage Disabled while these are worked out:
    # https://github.com/babel/ember-cli-babel/issues/350
    # https://github.com/kategengler/ember-cli-code-coverage/issues/265
    #
    # - name: Upload Coverage to Coveralls
    #   uses: coverallsapp/github-action@v1.0.1
    #   with:
    #     github-token: ${{ secrets.github_token }}
    #     path-to-lcov: ./client/web/emberclear/coverage/lcov.info

    # - name: Upload Coverage Artifacts
    #   uses: actions/upload-artifact@v1
    #   with:
    #     name: coverage
    #     path: client/web/emberclear/coverage/


##############################################################
#
  # bundle_analysis:
  #   name: Bundle Analysis
  #   runs-on: ubuntu-latest
  #   timeout-minutes: 15

  #   steps:
  #   - uses: actions/checkout@v2
  #   - uses: volta-cli/action@v1
  #   - uses: actions/cache@v2
  #     with:
  #       path: '**/node_modules'
  #       key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}

  #   - name: Install
  #     working-directory: ${{ env.cwd }}
  #     run: yarn install

  #   - name: Analyze Bundle
  #     working-directory: ${{ env.cwd }}
  #     run: yarn analyze

  #   - name: Upload Bundle Analysis Artifacts
  #     uses: actions/upload-artifact@v2
  #     with:
  #       name: built_bundle_analysis
  #       path: client/web/emberclear/public/bundle


  build_app:
    name: Build App
    runs-on: ubuntu-latest
    timeout-minutes: 10

    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1
    - uses: actions/cache@v2
      with:
        path: '**/node_modules'
        key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
    - name: Install and Build
      run: |
        ( cd ${{ env.cwd }} && yarn install && yarn build:production )
        cp ${{ env.cwd }}/config/netlify/_redirects ${{ env.cwd }}/dist

    - name: Upload App Artifacts
      uses: actions/upload-artifact@v2
      with:
        name: built_${{ env.name }}
        path: ${{ env.cwd }}/dist/

##############################################################
# TODO: scope e2e tests to app

  # tests_e2e:
  #   name: E2E Tests
  #   runs-on: ubuntu-latest
  #   timeout-minutes: 15
  #   needs: [deploy_preview]

  #   steps:
  #   - uses: actions/checkout@v2
  #   - uses: volta-cli/action@v1

  #   - name: Get Deploy URL
  #     uses: actions/download-artifact@master
  #     with:
  #       name: deploy-url
  #       path: ./

  #   - name: Test
  #     run: |
  #       export DEPLOY_URL=$(cat ./deploy-url.txt)
  #       cd client/web/smoke-tests
  #       DETECT_CHROMEDRIVER_VERSION=true yarn
  #       yarn test --target pull-request --headless


##############################################################

  deploy_preview:
    name: Deploy Preview
    runs-on: ubuntu-latest
    timeout-minutes: 15
    needs:
    # - bundle_analysis
    - build_app

    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1

    # - name: Download Built Bundle Analysis Artifacts
    #   uses: actions/download-artifact@master
    #   with:
    #     name: built_bundle_analysis
    #     path: ./deploy/bundle-analysis/

    - name: Download Built App Artifacts
      uses: actions/download-artifact@master
      with:
        name: built_${{ env.name }}
        path: ./deploy/app/

    - name: Combine Bundle Analysis with App
      run: |
        mkdir -p ./deploy/dist/bundle/
        mv ./deploy/app/* ./deploy/dist/
        cp ${{ env.cwd }}/config/netlify/_redirects ./deploy/dist/
    #     cp ./deploy/bundle-analysis/* ./deploy/dist/bundle/

    - name: Deploy to Netlify
      id: deploy
      uses: nwtgck/actions-netlify@v1.2.2
      with:
        publish-dir: './deploy/dist'
        production-branch: __handled_separately__
        github-token: ${{ secrets.GITHUB_TOKEN }}
      env:
        NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_ACCESS_TOKEN }}
        NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID_PINOCHLE }}

    - run: echo "${{ steps.deploy.outputs.deploy-url }}" > deploy-url.txt

    - name: Upload URL as Artifact
      uses: actions/upload-artifact@v2
      with:
        name: deploy-url
        path: deploy-url.txt


##############################################################

  # lhci:
  #   name: Lighthouse CI
  #   runs-on: ubuntu-latest
  #   needs: [build_app]

  #   steps:
  #   - uses: actions/checkout@v2
  #   - uses: volta-cli/action@v1

  #   - name: Download Built App Artifacts
  #     uses: actions/download-artifact@master
  #     with:
  #       name: built_app
  #       path: ${{ env.cwd }}/dist/

  #   - name: run Lighthouse
  #     env:
  #       GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  #       LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
  #     run: |
  #       volta install node
  #       volta install @lhci/cli@0.3.x
  #       cd ${{ env.cwd }}

  #       lhci collect \
  #         --upload.target=temporary-public-storage \
  #         --staticDistDir=./dist \
  #         --githubToken $GITHUB_TOKEN \
  #         --githubAppToken $LHCI_GITHUB_APP_TOKEN


================================================
FILE: .github/workflows/web-smoke-tests.yml
================================================
name: Web Smoke Tests
on:
  pull_request:
    branches: [master]
    paths:
    - 'client/web/smoke-tests/**'
    - 'client/web/package.json'

env:
  root: client/web/
  dir: smoke-tests/
  full: client/web/addons/ui/

##############################################################

jobs:
  lint:
    name: 'Lint'
    runs-on: ubuntu-latest
    timeout-minutes: 5

    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1

    - name: Install
      working-directory: ${{ env.root }}
      run: yarn install

    - name: "JS/TS"
      working-directory: ${{ env.root }}
      run: yarn eslint ${{ env.dir }} --ext js,ts

    # No TypeScript (yet)
    # - name: 'Type Correctness'
    #   working-directory: ${{ env.full }}
    #   run: yarn tsc --skipLibCheck --noEmit

##############################################################

  tests:
    name: E2E Tests
    runs-on: ubuntu-latest
    timeout-minutes: 15

    steps:
    - uses: actions/checkout@v2
    - uses: volta-cli/action@v1

    - name: Test Production
      run: |
        cd client/web/smoke-tests
        DETECT_CHROMEDRIVER_VERSION=true yarn
        yarn test --headless




================================================
FILE: .gitignore
================================================
node_modules
declarations/
tmp
dist
_build
deps
*.log
.idea/
.DS_Store

client/keystore.jks
client/upload_certificate.pem
client/Google Play Store Info

# Local Netlify folder
.netlify

# Local lighthouse ci
.lighthouseci


================================================
FILE: .gitmodules
================================================
[submodule "relays/phoenix-relay"]
	path = relays/phoenix-relay
	url = https://github.com/NullVoxPopuli/mesh-relay-phoenix.git


================================================
FILE: .sonarcloud.properties
================================================
sonar.exclusions=**/*-test.{ts,js}


================================================
FILE: .vscode/launch.json
================================================
{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
          "type": "node",
          "request": "launch",
          "name": "emberclear UI",
          "skipFiles": ["<node_internals>/**"],
          "cwd": "${workspaceFolder}/client/web/emberclear/",
          "runtimeExecutable": "yarn",
          "runtimeArgs": ["start"],
        },
        {
            "type": "node",
            "request": "launch",
            "name": "Frontend E2E Tests",
            "skipFiles": ["<node_internals>/**"],
            "cwd": "${workspaceFolder}/client/web/smoke-tests/",
            "program": "${workspaceFolder}/client/web/smoke-tests/node_modules/@faltest/cli/bin/index.js",
            "args": [
              "--browsers", "2",
              "--timeouts-override", "900000",
              "--target",
              "ember",
              // "local",
            ]

        }
    ]
}


================================================
FILE: .whitesource
================================================
{
  "checkRunSettings": {
    "vulnerableCheckRunConclusionLevel": "failure"
  },
  "issueSettings": {
    "minSeverityLevel": "LOW"
  }
}

================================================
FILE: CHANGELOG.md
================================================
## Change Log

### 2019-01
 
 - Bugfix: configurable relays did not correctly implement relay selection during app boot

### 2018-12

 - Enhancement: Split out the settings screen for future expandability.
 - Enhancement: Allow the relays to be configured.
 - Enhancement: Ensure that the default relays always exist as configuration options.
 - Bugfix: Sometimes the toast messages would not have a background color, making them very hard to read.
 - Chore: Reorganize some toplevel components to be a part of the application route's private collection.
 - Enhancement: for browsers that are not compatible, show a compatibility message.
 - Bugfix: Regression where notification prompt would not hide
 - Enhancement: Can mark a message for automatic resend. When the recipient isn't online, a message cannot be sent to them. With a message marked for automatic resend, the next time the recipient comes online, the message will be immediately sent, without the need to interact with the Chat.


 - Chore: Change Log Created. Tagged releases will be monthly.
 - See git log for prior enhancements, bugfixes, etc


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing

## Building
emberclear can be built and run with
```
cd client/web/emberclear
yarn install
yarn start:dev
```
and then can be visited at `https://localhost:4201/`.

## Testing
Run the tests locally with
```
cd client/web/emberclear
yarn test
```

## For working with the Relay
```bash
git submodule update --init --recursive
cd client/web/emberclear && yarn start:dev
```


#### Debugging

Module Resolution:
```js
// shows all detected services
Object.keys(window.requirejs.entries).filter(b => b.includes("service"))
```

File Watch Problems?
```bash
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
```


================================================
FILE: LICENSE
================================================

GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007

Copyright (C) 2007 Free Software Foundation, Inc.

Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.

Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works.

The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.

When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.

To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.

For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.

Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.

For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.

Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.

Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.

The precise terms and conditions for copying, distribution and modification follow.

TERMS AND CONDITIONS 0. Definitions. “This License” refers to version 3 of the GNU General Public License.

“Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.

“The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations.

To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work.

A “covered work” means either the unmodified Program or a work based on the Program.

To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.

To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.

An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.

1. Source Code. The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work.

A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.

The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.

The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.

The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.

The Corresponding Source for a work in source code form is that same work.

2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.

You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.

Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.

3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.

When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.

4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.

You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.

5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:

a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”. c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.

6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:

a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.

A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.

“Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.

If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).

The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.

Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.

7. Additional Terms. “Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.

When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.

Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:

a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.

If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.

Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.

8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).

However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.

Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.

Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.

9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.

10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.

An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.

You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.

11. Patents. A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's “contributor version”.

A contributor's “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.

Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.

In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.

If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.

If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.

A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.

Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.

12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.

13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.

14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.

Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.

If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.

Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.

15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.

END OF TERMS AND CONDITIONS

How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.

To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found.

Copyright (C)

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail.

If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode:

Copyright (C)

This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an “about box”.

You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see .

The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read .


================================================
FILE: README.md
================================================
# [emberclear](https://emberclear.io)

emberclear is published at: https://emberclear.io
and can be run locally with docker via
```
docker run -d -p 4201:80 nullvoxpopuli/emberclear
```
and then can be visited at `http://localhost:4201`.

## Project Directory

- [Browser Client](https://github.com/NullVoxPopuli/emberclear/tree/master/client/web/emberclear)
- [Phoenix Relay](https://github.com/NullVoxPopuli/mesh-relay-phoenix)
- [Benchmarks](https://github.com/NullVoxPopuli/emberclear/tree/master/benchmarks)

## Another Chat App?

Yes, there is a lack of trust that manifests when existing chat apps are closed source and centralized. Emberclear, by design, is trustless -- meaning that, while there is a server component, the server knows nothing more than your "_public_ key".  The server(s) are also meant to be a hot-swappable member of a mesh network, so no one implementation matters, as long as the same protocol is used.

<a href='https://docs.google.com/spreadsheets/d/116MpTXfga_f8N0tLSY_Glt_fd4GIag9T5-P_mag7RlQ/edit#gid=0'  target='_blank'>
  Here is a table of detailing out some differences between emberclear and other chat apps:
  <img src='https://gitlab.com/NullVoxPopuli/emberclear/raw/master/images/comparison.png'>
</a>

## Development

See: [CONTRIBUTING.md](https://github.com/NullVoxPopuli/emberclear/blob/master/CONTRIBUTING.md)

## Special Thanks

<a href='http://browserstack.com' target='_blank'><img src='https://p14.zdusercontent.com/attachment/1015988/tPHKnEGj5UmlAZin6VBzV2PXP?token=eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.._iQRaP0Z2EIo_bydcVxYgw.a45ScjGVDLEUj-eKschCJj2H2GnIwrb3H7fcFAHZsJIhdlVh2SLlVb3_DQcig6s1S4osAt-jNocejQdDlB-jq4DotpLlG2xXvIOO-MssjlDu5QQbCU5XwPyT2hk_0fHTVyCznoiup70QSnwfUm-xcl0bbxZI8ljgy1wQtzoqTd2CRovrOwfzQNXFg_MQ6TWkx5tkQDzhV0GbxIffZwN6s-4f5AHRNRP-3rbxtuEy6Lkz3WdQXbdynMcL2ElOS4h_zt7hEj0XRs1xNIQQhTsnjay4ZQvYSVfH13_aY3jVgVI.n_nXLbZaW3gj-FJcQxKD4A' width=100></a>
 - Cross-Browser / Cross-Platform Testing and Automation

## License

[GNU General Public License version 3](https://tldrlegal.com/license/gnu-general-public-license-v3-(gpl-3)#summary)


================================================
FILE: benchmarks/crypto/.babelrc.js
================================================
module.exports = {
  presets: [
    ['@babel/env', {
      targets: {
        node: '10'
      }
    }],
    '@babel/preset-typescript',
  ],
  plugins: [
    '@babel/plugin-transform-modules-commonjs',
    '@babel/plugin-syntax-dynamic-import',
    '@babel/plugin-proposal-class-properties',
    ['@babel/plugin-proposal-decorators', { legacy: true }],
    '@babel/plugin-transform-runtime',
  ]
};


================================================
FILE: benchmarks/crypto/.gitignore
================================================
/build


================================================
FILE: benchmarks/crypto/package.json
================================================
{
  "name": "crypto-benchmarks",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "build": "babel ./src --out-dir ./build --extensions '.ts'",
    "start": "node build/index.js",
    "bench": "yarn build && yarn start",
    "debug": "node --inspect-brk=9229 build/index.js"
  },
  "dependencies": {
    "js-nacl": "^1.3.2",
    "libsodium-wrappers": "^0.7.3",
    "tweetnacl": "^1.0.0",
    "tweetnacl-util": "^0.15.0"
  },
  "devDependencies": {
    "@babel/cli": "7.6.2",
    "@babel/core": "7.6.2",
    "@babel/node": "7.6.2",
    "@babel/plugin-proposal-class-properties": "7.5.5",
    "@babel/plugin-proposal-decorators": "7.6.0",
    "@babel/plugin-syntax-dynamic-import": "7.2.0",
    "@babel/plugin-transform-modules-commonjs": "7.6.0",
    "@babel/plugin-transform-runtime": "7.6.2",
    "@babel/preset-env": "7.6.2",
    "@babel/preset-typescript": "7.6.0",
    "@babel/register": "7.6.2",
    "@babel/runtime": "7.6.2",
    "@types/js-nacl": "1.2.0",
    "@types/libsodium-wrappers": "0.7.5",
    "@types/node": "12.7.12",
    "asyncmark": "0.3.1",
    "typescript": "3.6.3"
  }
}


================================================
FILE: benchmarks/crypto/run
================================================
#!/bin/bash

yarn
yarn build
yarn start


================================================
FILE: benchmarks/crypto/src/bench/base64.ts
================================================
import { Suite } from "asyncmark";
import libsodiumWrapper from "libsodium-wrappers";

import * as jsNaCl from "../lib/js-nacl";
import {
  libsodium,
  tweetnacl,
} from "../lib/utils";

const msg = Uint8Array.from([104, 101, 108, 101, 111]); // hello

export const base64 = new Suite({
  async before() {
    await libsodiumWrapper.ready;
    await jsNaCl.setInstance();

    console.log("\nround trip base64 encode + decode");
  }
});

base64.add({
  name: "libsodium",
  fun: async () => {
    libsodium.fromBase64(await libsodium.toBase64(msg));
  }
});

base64.add({
  name: "tweetnacl",
  fun: async () => {
    tweetnacl.fromBase64(await tweetnacl.toBase64(msg));
  }
});


================================================
FILE: benchmarks/crypto/src/bench/hex.ts
================================================
import { Suite } from "asyncmark";
import libsodiumWrapper from "libsodium-wrappers";

import * as jsNaCl from "../lib/js-nacl";

import {
  libsodium,
  tweetnacl,
  jsnacl,
} from "../lib/utils";
import { Buffer } from "buffer";

const msg = Uint8Array.from([104, 101, 108, 101, 111]); // hello

export const hex = new Suite({
  async before() {
    await libsodiumWrapper.ready;
    await jsNaCl.setInstance();

    console.log("\nround trip uint8 <-> string encode + decode");
  }
});

hex.add({
  name: "libsodium",
  fun: async () => {
    libsodium.fromHex(await libsodium.toHex(msg));
  }
});

// hex.add({
//   name: "tweet-nacl",
//   fun: async () => {
//     tweetnacl.fromString(await tweetnacl.toString(msg));
//   }
// });

hex.add({
  name: "js-nacl",
  fun: async () => {
    jsnacl.fromHex(await jsnacl.toHex(msg));
  }
});

hex.add({
  name: "native ",
  fun: async() => {
    const hex = Array.from(msg).map (b => b.toString(16).padStart(2, "0")).join("");
    return new Uint8Array(hex.match(/.{1,2}/g)!.map(byte => parseInt(byte, 16)));
  }
});

================================================
FILE: benchmarks/crypto/src/bench/key-generation.ts
================================================
import { Suite } from 'asyncmark';

import * as libsodiumjs from '../lib/libsodium';
import * as tweetNaCl from  '../lib/tweet-nacl';
import * as jsNaCl from '../lib/js-nacl';

export const keyGeneration = new Suite({
  async before() {
    console.log('\nKey Generation');
    await jsNaCl.setInstance();
  }
});

keyGeneration.add({
  name: 'libsodium',
  fun: libsodiumjs.generateAsymmetricKeys,

});

keyGeneration.add({
  name: 'tweetnacl',
  fun: tweetNaCl.generateAsymmetricKeys,
});

keyGeneration.add({
  name: 'js-nacl',
  fun: jsNaCl.generateAsymmetricKeys,
})


================================================
FILE: benchmarks/crypto/src/bench/nonce-generation.ts
================================================
import { Suite } from 'asyncmark';

import * as libsodiumjs from '../lib/libsodium';
import * as tweetNaCl from  '../lib/tweet-nacl';
import * as jsNaCl from '../lib/js-nacl';

export const nonceGeneration = new Suite({
  async before() {
    console.log('\nNonce Generation');
    await jsNaCl.setInstance();
  }
});

nonceGeneration.add({
  name: 'libsodium',
  fun: libsodiumjs.generateNonce,

});

nonceGeneration.add({
  name: 'tweetnacl',
  fun: tweetNaCl.generateNonce,
});

nonceGeneration.add({
  name: 'js-nacl',
  fun: jsNaCl.generateNonce,
});


================================================
FILE: benchmarks/crypto/src/bench/round-trip-long.ts
================================================
import { Suite } from 'asyncmark';
import libsodiumWrapper from 'libsodium-wrappers';

import { fromString } from '../utils';
import * as jsNaCl from '../lib/js-nacl';
import { libsodium, jsnacl, tweetnacl } from '../lib/round-trip-implementations';

const lorem = `
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse libero risus, porttitor nec urna ut, pellentesque feugiat ex. Integer viverra enim at pulvinar congue. Nunc et turpis vitae nisi maximus laoreet. Mauris malesuada lorem arcu, ut suscipit ante dictum nec. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Maecenas eget ex at ligula accumsan tincidunt ac vel erat. Nunc non nunc et dui feugiat finibus. Fusce efficitur, tortor a viverra consequat, sem nulla viverra quam, imperdiet malesuada dui justo vel lacus. Aenean malesuada gravida eros ut dictum. In vehicula vestibulum lacus vel auctor. Proin rutrum ut felis sit amet sagittis.

Vivamus quis sapien vel sapien rutrum posuere eu nec nulla. Fusce fermentum nulla et vehicula pharetra. Duis tempor libero cursus, accumsan tellus id, accumsan nulla. Nulla facilisi. In aliquet hendrerit pulvinar. Mauris nulla nibh, vulputate vitae malesuada at, pulvinar id magna. Aliquam eget elit maximus, pretium nunc sit amet, molestie felis. Mauris in dolor imperdiet metus lobortis vestibulum non ac risus. Nunc pretium mattis sapien, a scelerisque libero pharetra nec. Pellentesque nisi est, sollicitudin vitae feugiat ac, fringilla vitae lacus. Donec ullamcorper fringilla dolor, commodo vulputate metus accumsan mollis. Morbi maximus vehicula velit, in congue neque vestibulum sed. Nam volutpat, urna eu posuere consequat, leo metus mollis enim, ut scelerisque lectus leo eu urna. Aliquam porttitor sapien ut risus vehicula imperdiet. Sed nunc nisi, cursus quis porta ac, ultricies non erat. Sed tristique ante at accumsan malesuada.

Proin ante urna, lacinia at lacinia quis, condimentum in nunc. Proin ultricies velit nisl, at gravida lectus ultricies in. Aliquam laoreet, purus at commodo feugiat, felis nisl dignissim augue, non dapibus turpis nisi non lacus. In sit amet libero ut risus laoreet tristique eget sit amet erat. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Integer varius dolor eu pharetra lobortis. Nam non risus eu lectus congue maximus.

Proin mauris justo, condimentum eu rutrum at, lacinia nec urna. Vivamus vitae tristique tortor, non ultrices ante. Aliquam quis tortor et eros dapibus posuere sed non enim. Fusce a dui fringilla, imperdiet neque vel, vestibulum erat. Praesent mi lectus, dignissim posuere vulputate a, tempus et quam. Pellentesque ornare congue neque sit amet rutrum. Ut convallis ac dolor id hendrerit. Duis placerat est sit amet orci egestas congue. Donec sed nunc id leo vestibulum blandit eu eu mauris. Nam eget tempus arcu, ac lobortis metus.

Sed dolor nibh, pulvinar sit amet dui at, dictum aliquam quam. Nulla condimentum iaculis arcu. Maecenas vel metus egestas, placerat magna in, mattis massa. Cras et hendrerit purus. Nullam id porta ligula, eget feugiat risus. Nam varius nunc eu elit sodales, congue molestie turpis bibendum. Aenean eu diam dapibus, luctus odio vitae, laoreet ipsum. In vehicula purus id suscipit tristique. Praesent ultrices risus risus, eget imperdiet est rutrum et. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam ac ante non turpis interdum sodales. Fusce a ligula eget enim cursus mollis. Maecenas et est magna. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent consectetur tempus viverra. Sed ultricies molestie blandit.

Praesent eu dictum sem. Proin porta elit lacus, vel ornare arcu cursus eu. Integer a dolor ut arcu pellentesque fringilla. Nunc eget suscipit sem, sed pellentesque elit. Nam arcu nisi, condimentum at quam pretium, semper hendrerit massa. Fusce maximus turpis velit, vel molestie est volutpat rhoncus. Praesent finibus lacinia feugiat. Sed in nulla luctus, imperdiet urna et, sodales neque. Mauris commodo mattis sapien id pulvinar.

Nulla in nisi eget sem tempus placerat. Nunc at mi sit amet tellus pulvinar imperdiet. Sed consequat efficitur felis, at aliquam est imperdiet quis. In in scelerisque lectus. Suspendisse luctus pretium tortor tincidunt interdum. Nullam ornare arcu vel magna auctor aliquam. Sed ut rutrum nunc. Pellentesque dignissim mattis iaculis. Morbi facilisis interdum neque, eu pulvinar est venenatis at. Fusce lobortis varius justo, in finibus turpis tincidunt ac. Suspendisse et ornare enim, vel placerat mauris.

Aliquam laoreet nunc eget ligula convallis, eget aliquet ipsum pulvinar. Praesent tempor nulla non magna dictum lobortis. Praesent eleifend, velit eu semper tristique, tortor velit pharetra metus, nec dignissim mi nibh ut sem. Nulla in finibus ipsum, vitae ullamcorper lorem. Donec ac ligula lacinia, placerat massa ac, mollis odio. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus imperdiet, ante sed pretium vestibulum, orci dui vulputate lacus, vel sodales metus ipsum ut velit.

Integer tempus lobortis metus, eu vulputate leo fermentum id. Praesent ut velit ultricies, maximus risus eu, lobortis ante. Nam interdum finibus fermentum. Maecenas in semper purus. Fusce ac enim ac ligula aliquet egestas. In hac habitasse platea dictumst. Morbi purus enim, pellentesque eu sagittis ac, pharetra in leo. Phasellus fermentum felis vitae nisi pulvinar semper. Sed consequat ligula tortor, et posuere orci laoreet vitae. Ut ultrices, urna et volutpat scelerisque, justo neque porta ipsum, ac mollis urna nunc vitae eros. Sed rhoncus nunc et purus finibus, ut pretium libero finibus. Nulla condimentum, nulla ac mattis commodo, est mi imperdiet odio, sed elementum orci velit quis est. Vestibulum quis justo nibh. Ut egestas tellus eu diam commodo vulputate. Vestibulum suscipit, tellus non auctor bibendum, metus nisi hendrerit elit, ut euismod magna ipsum sed tellus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;

Proin varius mi augue, sed auctor eros sagittis sed. Phasellus vehicula ex ut venenatis sagittis. Vivamus volutpat euismod lorem. Aliquam tempor quam orci. Cras ut nulla metus. Donec tempor, leo a tempor venenatis, enim ipsum aliquam tellus, id faucibus turpis magna quis ante. Ut sit amet volutpat nisl, at venenatis tellus. Praesent auctor ut risus at accumsan. Vestibulum venenatis viverra tristique. Duis a velit ornare, ultricies ipsum eu, vehicula felis. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec et purus consequat, fringilla augue ut, rhoncus nisi. Duis semper metus nunc, non egestas tellus semper et. Suspendisse congue tempus nunc, id vulputate neque consectetur in. Pellentesque rhoncus, justo at dignissim feugiat, ex ligula gravida lacus, ut varius augue libero eget ante.
`;
console.log(lorem.length);
const msg = fromString(
  `${lorem}`
);


export const roundTrip = new Suite({
  async before() {
    await libsodiumWrapper.ready;
    await jsNaCl.setInstance();
    console.log('\nRound-trip Box Encryption (long message)');
  }
});

roundTrip.add({
  name: "libsodium",
  fun: () => libsodium(msg)
});

roundTrip.add({
  name: "tweetnacl",
  fun: () => tweetnacl(msg)
});

roundTrip.add({
  name: "js-nacl",
  fun: () => jsnacl(msg)
});


================================================
FILE: benchmarks/crypto/src/bench/round-trip.ts
================================================
import { Suite } from "asyncmark";
import libsodiumWrapper from "libsodium-wrappers";

import * as jsNaCl from "../lib/js-nacl";
import {
  libsodium,
  tweetnacl,
  jsnacl
} from "../lib/round-trip-implementations";

const msg = Uint8Array.from([104, 101, 108, 101, 111]); // hello

export const roundTrip = new Suite({
  async before() {
    await libsodiumWrapper.ready;
    await jsNaCl.setInstance();

    console.log("\nRound-trip Box Encryption (short message)");
  }
});

roundTrip.add({
  name: "libsodium",
  fun: () => libsodium(msg)
});

roundTrip.add({
  name: "tweetnacl",
  fun: () => tweetnacl(msg)
});

roundTrip.add({
  name: "js-nacl",
  fun: () => jsnacl(msg)
});


================================================
FILE: benchmarks/crypto/src/bench/stringConvension.ts
================================================
import { Suite } from "asyncmark";
import libsodiumWrapper from "libsodium-wrappers";

import * as jsNaCl from "../lib/js-nacl";

import {
  libsodium,
  tweetnacl,
  jsnacl,
} from "../lib/utils";

const msg = Uint8Array.from([104, 101, 108, 101, 111]); // hello

export const stringConversion = new Suite({
  async before() {
    await libsodiumWrapper.ready;
    await jsNaCl.setInstance();

    console.log("\nround trip uint8 <-> string encode + decode");
  }
});

stringConversion.add({
  name: "libsodium",
  fun: async () => {
    libsodium.fromString(await libsodium.toString(msg));
  }
});

stringConversion.add({
  name: "tweet-nacl",
  fun: async () => {
    tweetnacl.fromString(await tweetnacl.toString(msg));
  }
});

stringConversion.add({
  name: "js-nacl",
  fun: async () => {
    jsnacl.fromString(await jsnacl.toString(msg));
  }
});


================================================
FILE: benchmarks/crypto/src/index.ts
================================================
import { roundTrip } from './bench/round-trip';
import { keyGeneration } from './bench/key-generation';
import { nonceGeneration } from './bench/nonce-generation';
import { roundTrip as roundTripLong } from './bench/round-trip-long';
import { base64 } from './bench/base64';
import { stringConversion } from './bench/stringConvension';
import { hex } from './bench/hex';

async function runBenchmark() {
  // encryption-related things
  await roundTrip.run();
  await keyGeneration.run();
  await nonceGeneration.run();
  await roundTripLong.run();

  // conversion
  await base64.run();
  await stringConversion.run();
  await hex.run();
}

console.log(`
  Box Encryption Libraries:

        Name     | Size (min + gzip)
    -------------|------------------
    tweet-nacl   | 10.4  kB
    libsodium    | 192.1 kB
    js-nacl      | 212.9 kB
`);

runBenchmark();


================================================
FILE: benchmarks/crypto/src/lib/js-nacl.ts
================================================

import NaClFactory, { Nacl } from 'js-nacl';

import { concat } from '../utils';


export let nacl: Nacl;
export function setInstance(): Promise<Nacl> {
  return new Promise((resolve, reject) => {
    // These apis are.... not good
    NaClFactory.instantiate((instance: Nacl) => {
      nacl = instance;
      resolve(nacl);
    });
  });
}

export function generateAsymmetricKeys() {
  return nacl.crypto_box_keypair();
}

export function generateNonce(): Uint8Array {
  return nacl.crypto_box_random_nonce();
}

export function encryptFor(
  message: Uint8Array,
  recipientPublicKey: Uint8Array,
  senderPrivateKey: Uint8Array
): Uint8Array {
  const nonce = generateNonce();

  const ciphertext = nacl.crypto_box(message, nonce, recipientPublicKey, senderPrivateKey);

  return concat(nonce, ciphertext);
}

export function decryptFrom(
  ciphertextWithNonce: Uint8Array,
  senderPublicKey: Uint8Array,
  recipientPrivateKey: Uint8Array
): Uint8Array {
  const [nonce, ciphertext] = splitNonceFromMessage(ciphertextWithNonce);
  const decrypted = nacl.crypto_box_open(ciphertext, nonce, senderPublicKey, recipientPrivateKey);

  return decrypted as Uint8Array;
}


export function splitNonceFromMessage(
  messageWithNonce: Uint8Array
): [Uint8Array, Uint8Array] {
  const bytes = nacl.crypto_box_NONCEBYTES;

  const nonce = messageWithNonce.slice(0, bytes);
  const message = messageWithNonce.slice(bytes, messageWithNonce.length);

  return [nonce, message];
}



export function toHex(array: Uint8Array): string {
  return nacl.to_hex(array);
}

export function fromHex(hex: string): Uint8Array {
  return nacl.from_hex(hex);
}

// export async function toBase64(array: Uint8Array): Promise<string> {
//   return utils.encodeBase64(array);
// }

// export async function fromBase64(base64: string): Promise<Uint8Array> {
//   return utils.decodeBase64(base64);
// }

export function fromString(str: string): Uint8Array {
  return nacl.encode_utf8(str);
}

export const toUint8Array = fromString;

export function toString(uint8Array: Uint8Array): string {
  return nacl.decode_utf8(uint8Array);
}



================================================
FILE: benchmarks/crypto/src/lib/libsodium.ts
================================================
import libsodiumWrapper, { KeyPair } from 'libsodium-wrappers';

import { concat } from '../utils';

export async function libsodium(): Promise<typeof libsodiumWrapper> {
  const sodium = (libsodiumWrapper as any);
  await sodium.ready;

  return sodium as typeof libsodiumWrapper;
}

export async function genericHash(arr: Uint8Array): Promise<Uint8Array> {
  const sodium = await libsodium();

  return sodium.crypto_generichash(32, arr);
}

export async function derivePublicKey(privateKey: Uint8Array): Promise<Uint8Array> {
  const sodium = await libsodium();

  return sodium.crypto_scalarmult_base(privateKey);
}

export async function randomBytes(length: number): Promise<Uint8Array> {
  const sodium = await libsodium();

  return sodium.randombytes_buf(length);
}

export async function generateNonce(): Promise<Uint8Array> {
  const sodium = await libsodium();

  return await randomBytes(sodium.crypto_box_NONCEBYTES);
}

export async function generateAsymmetricKeys(): Promise<KeyPair> {
  const sodium = await libsodium();

  return sodium.crypto_box_keypair();
}

export async function generateSymmetricKey(): Promise<Uint8Array> {
  const sodium = await libsodium();

  return await randomBytes(sodium.crypto_box_SECRETKEYBYTES);
}

export async function encryptFor(
  message: Uint8Array,
  recipientPublicKey: Uint8Array,
  senderPrivateKey: Uint8Array
): Promise<Uint8Array> {
  const sodium = await libsodium();
  const nonce = await generateNonce();

  const ciphertext = sodium.crypto_box_easy(message, nonce, recipientPublicKey, senderPrivateKey);

  return concat(nonce, ciphertext);
}

export async function decryptFrom(
  ciphertextWithNonce: Uint8Array,
  senderPublicKey: Uint8Array,
  recipientPrivateKey: Uint8Array
): Promise<Uint8Array> {
  const sodium = await libsodium();

  const [nonce, ciphertext] = await splitNonceFromMessage(ciphertextWithNonce);
  const decrypted = sodium.crypto_box_open_easy(
    ciphertext,
    nonce,
    senderPublicKey,
    recipientPrivateKey
  );

  return decrypted;
}

export async function splitNonceFromMessage(
  messageWithNonce: Uint8Array
): Promise<[Uint8Array, Uint8Array]> {
  const sodium = await libsodium();
  const bytes = sodium.crypto_box_NONCEBYTES;

  const nonce = messageWithNonce.slice(0, bytes);
  const message = messageWithNonce.slice(bytes, messageWithNonce.length);

  return [nonce, message];
}

export function toHex(array: Uint8Array): string {
  return libsodiumWrapper.to_hex(array);
}

export function fromHex(hex: string): Uint8Array {
  return libsodiumWrapper.from_hex(hex);
}

export async function toBase64(array: Uint8Array): Promise<string> {
  const sodium = await libsodium();

  return sodium.to_base64(array, sodium.base64_variants.ORIGINAL);
}

export async function fromBase64(base64: string): Promise<Uint8Array> {
  const sodium = await libsodium();

  return sodium.from_base64(base64, sodium.base64_variants.ORIGINAL);
}

export function fromString(str: string): Uint8Array {
  return libsodiumWrapper.from_string(str);
}

export const toUint8Array = fromString;

export function toString(uint8Array: Uint8Array): string {
  return libsodiumWrapper.to_string(uint8Array);
}



================================================
FILE: benchmarks/crypto/src/lib/round-trip-implementations.ts
================================================
import * as libsodiumjs from "../lib/libsodium";
import * as tweetNaCl from "../lib/tweet-nacl";
import * as jsNaCl from "../lib/js-nacl";

export async function libsodium(msg: Uint8Array) {
  const receiver = await libsodiumjs.generateAsymmetricKeys();
  const sender = await libsodiumjs.generateAsymmetricKeys();

  const cipherText = await libsodiumjs.encryptFor(
    msg,
    receiver.publicKey,
    sender.privateKey
  );
  const decrypted = await libsodiumjs.decryptFrom(
    cipherText,
    sender.publicKey,
    receiver.privateKey
  );

  ensureEquality("libsodium", msg, decrypted, libsodiumjs.toString);
}

export async function tweetnacl(msg: Uint8Array) {
  const receiver = tweetNaCl.generateAsymmetricKeys();
  const sender = tweetNaCl.generateAsymmetricKeys();

  const cipherText = await tweetNaCl.encryptFor(
    msg,
    receiver.publicKey,
    sender.secretKey
  );
  const decrypted = await tweetNaCl.decryptFrom(
    cipherText,
    sender.publicKey,
    receiver.secretKey
  );

  ensureEquality("tweetnacl", msg, decrypted, tweetNaCl.toString);
}

export async function jsnacl(msg: Uint8Array) {
  const receiver = jsNaCl.generateAsymmetricKeys();
  const sender = jsNaCl.generateAsymmetricKeys();

  const cipherText = jsNaCl.encryptFor(msg, receiver.boxPk, sender.boxSk);
  const decrypted = await jsNaCl.decryptFrom(
    cipherText,
    sender.boxPk,
    receiver.boxSk
  );

  ensureEquality("jsnacl", msg, decrypted, jsNaCl.nacl.decode_utf8);
}

function ensureEquality(
  label: string,
  a: Uint8Array,
  b: Uint8Array,
  toString: any
) {
  const as = toString(a);
  const bs = toString(b);
  if (as !== bs) {
    throw new Error(`
      message was not encrypted and/or decrypted properly.

      Expected ${as}
      to equal ${bs}

    `);
  }
}


================================================
FILE: benchmarks/crypto/src/lib/tweet-nacl.ts
================================================
import * as nacl from 'tweetnacl';
import * as utils from 'tweetnacl-util';

import { concat } from '../utils';

export function generateAsymmetricKeys() {
  return nacl.box.keyPair();
}

export function generateNonce(): Uint8Array {
  return nacl.randomBytes(nacl.box.nonceLength);
}

export function encryptFor(
  message: Uint8Array,
  recipientPublicKey: Uint8Array,
  senderPrivateKey: Uint8Array
): Uint8Array {

  const nonce = generateNonce();

  const ciphertext = nacl.box(message, nonce, recipientPublicKey, senderPrivateKey);

  return concat(nonce, ciphertext);
}

export function decryptFrom(
  ciphertextWithNonce: Uint8Array,
  senderPublicKey: Uint8Array,
  recipientPrivateKey: Uint8Array
): Uint8Array {

  const [nonce, ciphertext] = splitNonceFromMessage(ciphertextWithNonce);
  const decrypted = nacl.box.open(ciphertext, nonce, senderPublicKey, recipientPrivateKey);

  return decrypted as Uint8Array;
}


export function splitNonceFromMessage(
  messageWithNonce: Uint8Array
): [Uint8Array, Uint8Array] {
  const bytes = nacl.box.nonceLength;

  const nonce = messageWithNonce.slice(0, bytes);
  const message = messageWithNonce.slice(bytes, messageWithNonce.length);

  return [nonce, message];
}

// export function toHex(array: Uint8Array): string {
//   return libsodiumWrapper.to_hex(array);
// }

// export function fromHex(hex: string): Uint8Array {
//   return libsodiumWrapper.from_hex(hex);
// }

export async function toBase64(array: Uint8Array): Promise<string> {
  return utils.encodeBase64(array);
}

export async function fromBase64(base64: string): Promise<Uint8Array> {
  return utils.decodeBase64(base64);
}

export function fromString(str: string): Uint8Array {
  return utils.decodeUTF8(str);
}

export const toUint8Array = fromString;

export function toString(uint8Array: Uint8Array): string {
  return utils.encodeUTF8(uint8Array);
}



================================================
FILE: benchmarks/crypto/src/lib/utils.ts
================================================
import * as libsodumFns from './libsodium';
import * as tweetnaclFns from './tweet-nacl';
import * as jsNaclFns from './js-nacl';

export const libsodium = {
    toHex: libsodumFns.toHex,
    fromHex: libsodumFns.fromHex,
    toBase64: libsodumFns.toBase64,
    fromBase64: libsodumFns.fromBase64,
    fromString: libsodumFns.fromString,
    toString: libsodumFns.toString,
};

export const tweetnacl = {
    toBase64: tweetnaclFns.toBase64,
    fromBase64: tweetnaclFns.fromBase64,
    fromString: tweetnaclFns.fromString,
    toString: tweetnaclFns.toString,
}

export const jsnacl = {
    toHex: jsNaclFns.toHex,
    fromHex: jsNaclFns.fromHex,
    fromString: jsNaclFns.fromString,
    toString: jsNaclFns.toString,
}

================================================
FILE: benchmarks/crypto/src/utils.ts
================================================
import libsodiumWrapper from 'libsodium-wrappers';

export async function wrapCatch(task) {
  try {
    await task();
  } catch(e) {
    console.error(e);
    throw e;
  }
}

export function fromString(str: string): Uint8Array {
  // return new TextEncoder().encode(str);
  return libsodiumWrapper.from_string(str);
}

export function toString(data: Uint8Array): string {
  return libsodiumWrapper.to_string(data);
}

export function concat(arr1: Uint8Array, arr2: Uint8Array): Uint8Array {
  const result = new Uint8Array(arr1.length + arr2.length);

  result.set(arr1, 0);
  result.set(arr2, arr1.length);

  return result;
}


================================================
FILE: benchmarks/crypto/tsconfig.json
================================================
{
  "compilerOptions": {
    "target": "ES2017",
    "allowJs": true,
    "experimentalDecorators": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "noEmitOnError": false,
    "noEmit": true,
    "inlineSourceMap": true,
    "inlineSources": true,
    "noImplicitAny": true,
    "noImplicitThis": true,
    "noImplicitReturns": false,
    "alwaysStrict": true,
    "strictNullChecks": true,
    "strictPropertyInitialization": true,
    "noFallthroughCasesInSwitch": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "baseUrl": ".",
    "module": "es6",
    "paths": {
      "lib/*": [
        "src/lib/*"
      ],
      "bench/*": [
        "src/bench/*"
      ],
      "*": [
        "src*"
      ]
    }
  },
  "include": [
    "src"
  ]
}


================================================
FILE: benchmarks/emoji-replace/.babelrc.js
================================================
module.exports = {
  presets: [
    ['@babel/env', {
      targets: {
        node: '10'
      }
    }],
    '@babel/preset-typescript',
  ],
  plugins: [
    '@babel/plugin-transform-modules-commonjs',
    '@babel/plugin-syntax-dynamic-import',
    '@babel/plugin-proposal-class-properties',
    ['@babel/plugin-proposal-decorators', { legacy: true }],
    '@babel/plugin-transform-runtime',
  ]
};


================================================
FILE: benchmarks/emoji-replace/.gitignore
================================================
/build


================================================
FILE: benchmarks/emoji-replace/package.json
================================================
{
  "name": "emoji-replace-benchmarks",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "build": "babel ./src --out-dir ./build --extensions '.ts'",
    "start": "node build/index.js",
    "bench": "yarn build && yarn start",
    "debug": "node --inspect-brk=9229 build/index.js"
  },
  "dependencies": {
    "emojis": "^1.0.10"
  },
  "devDependencies": {
    "@babel/cli": "7.6.2",
    "@babel/core": "7.6.2",
    "@babel/node": "7.6.2",
    "@babel/plugin-proposal-class-properties": "7.5.5",
    "@babel/plugin-proposal-decorators": "7.6.0",
    "@babel/plugin-syntax-dynamic-import": "7.2.0",
    "@babel/plugin-transform-modules-commonjs": "7.6.0",
    "@babel/plugin-transform-runtime": "7.6.2",
    "@babel/preset-env": "7.6.2",
    "@babel/preset-typescript": "7.6.0",
    "@babel/register": "7.6.2",
    "@babel/runtime": "7.6.2",
    "@types/js-nacl": "1.2.0",
    "@types/libsodium-wrappers": "0.7.5",
    "@types/node": "12.7.11",
    "asyncmark": "0.3.1",
    "typescript": "3.6.3"
  }
}


================================================
FILE: benchmarks/emoji-replace/run
================================================
#!/bin/bash

yarn
yarn build
yarn start


================================================
FILE: benchmarks/emoji-replace/src/bench/-utils.ts
================================================
import { Suite } from "asyncmark";
import { unicode } from "emojis";

export function assertEq<T>(expected: T, actual: T, msg: string) {
  if (expected !== actual) {
    throw new Error(`
      ${ msg }

      expected:

        ${actual}

        to equal

        ${expected}
    `);
  }
}

interface Args {
  originalString: string;
  expected: string;
  benchName: string;
}

export function generateEmojisBench({
  originalString,
  expected,
  benchName
}: Args) {

  function directReplace(str: string) {
    return unicode(str);
  }

  function condition(str: string) {
    if (str.includes(":")) {
      return unicode(str);
    }

    return str;
  }

  const EMOJI_REGEX = /:[^:]+:/;

  function regexTest(str: string) {
    if (EMOJI_REGEX.test(str)) {
      return unicode(str);
    }

    return str;
  }

  function regexMatch(str: string) {
    if (str.match(EMOJI_REGEX)) {
      return unicode(str);
    }

    return str;
  }

  const bench = new Suite({
    async before() {
      assertEq(
        expected, directReplace(originalString),
        `${benchName}: direct replace failed`
      );
      assertEq(expected, condition(originalString), `${benchName}: condition failed`);
      assertEq(expected, regexTest(originalString), `${benchName}: condition failed`);

      console.log(`\n -- ${benchName} -- `);
    }
  });

  bench.add({
    name: "direct replace  ",
    fun: () => {
      directReplace(directReplace(originalString))
    }
  });

  bench.add({
    name: "condition for   ",
    fun: () => {
      condition(condition(originalString))
    }
  });

  bench.add({
    name: "regex test      ",
    fun: () => {
      regexTest(regexTest(originalString))
    }
  });

  bench.add({
    name: "regex match     ",
    fun: () => {
      regexMatch(regexMatch(originalString))
    }
  });

  return bench;
}



================================================
FILE: benchmarks/emoji-replace/src/bench/long.ts
================================================
import { generateEmojisBench } from "./-utils";

const benchName = "long";
const originalString = `
  I :heart: the :scream: emoji.

Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

:smile:

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident,
sunt in culpa qui officia deserunt mollit anim id est laborum.

I :heart: the :scream: emoji.
`;

const expected = `
  I ❤️ the 😱 emoji.

Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

😄

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident,
sunt in culpa qui officia deserunt mollit anim id est laborum.

I ❤️ the 😱 emoji.
`;

export const bench = generateEmojisBench({
  originalString,
  expected,
  benchName
});


================================================
FILE: benchmarks/emoji-replace/src/bench/micro.ts
================================================
import { generateEmojisBench } from "./-utils";

const originalString = ":scream:";
const expected = "😱";
const benchName = "micro";

export const bench = generateEmojisBench({
  originalString,
  expected,
  benchName
});


================================================
FILE: benchmarks/emoji-replace/src/bench/short.ts
================================================
import { generateEmojisBench } from "./-utils";

const originalString = "I :heart: the :scream: emoji.";
const expected = "I ❤️ the 😱 emoji.";
const benchName = "short";

export const bench = generateEmojisBench({
  originalString,
  expected,
  benchName
});


================================================
FILE: benchmarks/emoji-replace/src/index.ts
================================================
import { bench as short } from "./bench/short";
import { bench as micro } from "./bench/micro";
import { bench as long } from "./bench/long";

async function runBenchmark() {
  await micro.run();
  await short.run();
  await long.run();
}

console.log(`
  Emoji Libraries:

        Name     | Size (min + gzip)
    -------------|------------------
    emojis       | 376 Bytes
`);

runBenchmark();


================================================
FILE: benchmarks/emoji-replace/tsconfig.json
================================================
{
  "compilerOptions": {
    "target": "ES2017",
    "allowJs": true,
    "experimentalDecorators": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "noEmitOnError": false,
    "noEmit": true,
    "inlineSourceMap": true,
    "inlineSources": true,
    "noImplicitAny": true,
    "noImplicitThis": true,
    "noImplicitReturns": false,
    "alwaysStrict": true,
    "strictNullChecks": true,
    "strictPropertyInitialization": true,
    "noFallthroughCasesInSwitch": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "baseUrl": ".",
    "module": "es6",
    "paths": {
      "lib/*": [
        "src/lib/*"
      ],
      "bench/*": [
        "src/bench/*"
      ],
      "*": [
        "src*"
      ]
    }
  },
  "include": [
    "src"
  ]
}


================================================
FILE: benchmarks/emoji-replace/types/emojis.d.ts
================================================
export function unicode(input: string): string;
export function html(input: string): string;


================================================
FILE: client/android-wrapper/.gitignore
================================================
# Built application files
*.apk
*.ap_
*.aab

# Files for the ART/Dalvik VM
*.dex

# Java class files
*.class

# Generated files
bin/
gen/
out/

# Gradle files
.gradle/
build/
release/
appmaker.keystore

# Local configuration file (sdk path, etc)
local.properties

# Proguard folder generated by Eclipse
proguard/

# Log Files
*.log

# Android Studio Navigation editor temp files
.navigation/

# Android Studio captures folder
captures/

# IntelliJ
*.iml
.idea/workspace.xml
.idea/tasks.xml
.idea/gradle.xml
.idea/assetWizardSettings.xml
.idea/dictionaries
.idea/libraries
.idea/caches
# Android Studio 3 in .gitignore file.
.idea/caches/build_file_checksums.ser
.idea/modules.xml

# Keystore files
# Uncomment the following lines if you do not want to check your keystore files in.
#*.jks
#*.keystore

# External native build folder generated in Android Studio 2.2 and later
.externalNativeBuild

# Google Services (e.g. APIs or Firebase)
# google-services.json

# Freeline
freeline.py
freeline/
freeline_project_description.json

# fastlane
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
fastlane/readme.md

# Version control
vcs.xml

# lint
lint/intermediates/
lint/generated/
lint/outputs/
lint/tmp/
# lint/reports/


================================================
FILE: client/android-wrapper/CONTRIBUTING.md
================================================
# How to become a contributor and submit your own code

## Contributor License Agreements

We'd love to accept your sample apps and patches! Before we can take them, we
have to jump a couple of legal hurdles.

Please fill out either the individual or corporate Contributor License Agreement
(CLA).

  * If you are an individual writing original source code and you're sure you
    own the intellectual property, then you'll need to sign an [individual CLA]
    (https://developers.google.com/open-source/cla/individual).
  * If you work for a company that wants to allow you to contribute your work,
    then you'll need to sign a [corporate CLA]
    (https://developers.google.com/open-source/cla/corporate).

Follow either of the two links above to access the appropriate CLA and
instructions for how to sign and return it. Once we receive it, we'll be able to
accept your pull requests.

## Contributing A Patch

1. Submit an issue describing your proposed change to the repo in question.
1. The repo owner will respond to your issue promptly.
1. If your proposed change is accepted, and you haven't already done so, sign a
   Contributor License Agreement (see details above).
1. Fork the desired repo, develop and test your code changes.
1. Ensure that your code adheres to the existing style in the sample to which
   you are contributing. Refer to the
   [Google Cloud Platform Samples Style Guide]
   (https://github.com/GoogleCloudPlatform/Template/wiki/style.html) for the
   recommended coding standards for this organization.
1. Ensure that your code has an appropriate set of unit tests which all pass.
1. Submit a pull request.



================================================
FILE: client/android-wrapper/LICENSE
================================================

                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

================================================
FILE: client/android-wrapper/README.md
================================================
# SVGOMG / Trusted Web Activity

This project uses the
[Trusted Web Activities](https://developers.google.com/web/updates/2017/10/using-twa) technology
to wrap [SVGOMG](https://jakearchibald.github.io/svgomg/) in an Android Application.

## Running the Demo

1. Clone the project
``
git clone https://github.com/GoogleChromeLabs/svgomg-twa.git
``

2. Import the Project into Android Studio, using File > New > Import Project, and select the folder
to which the project was cloned.

3. Run the Project (Ctrl+R)

### Enabling Debug

TWAs require [Digital AssetLinks](https://developers.google.com/digital-asset-links/) to be setup
on both the application and on the website, in order to enable the validation that allows Chrome to
open the page in full-screen.

For security reasons, the signing key compatible with the setup on
https://svgomg.firebaseapp.com/ is not committed with the sample code.

It is possible to setup Chrome to skip validation on device to enable testing.

Here are the 2 steps required to achieve this:

1. Enable Chrome to accept command-line parameters:

On the Android Device, go to the Chrome version being used to test the TWA and navigate to
`chrome://flags`. Search for a setting called `Enable commmand line on non-rooted devices` and
change it to `Enabled`. Restarting the browser *multiple* times may be required.

2. Create an Android file with the command-line parameters that allow skipping the TWA validation.

Add a file at `/data/local/tmp/chrome-command-line`, with the content
`_ --disable-digital-asset-link-verification-for-url="https://svgomg.firebaseapp.com"`. Make sure
there's not newline at the end of the line, or it may break the launcher.

For convenience, a shell script that creates this file is available in this repository. Run it
by executing `./enable-debug.sh https://svgomg.firebaseapp.com`.

To debug a different PWA, execute the script with a different host:
`./enable-debug.sh https://example.com`

## License

```
Copyright 2015 Google, Inc.

Licensed to the Apache Software Foundation (ASF) under one or more contributor
license agreements. See the NOTICE file distributed with this work for
additional information regarding copyright ownership. The ASF licenses this
file to you under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance with the License. You may obtain a copy of
the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
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: client/android-wrapper/app/build.gradle
================================================
/*
 * Copyright 2019 Google 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.
 * appicon_ios_android.png
 */

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "io.emberclear"
        minSdkVersion 16
        targetSdkVersion 28
        versionCode 343
        versionName "1"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        manifestPlaceholders = [
                // The hostname is used when building the intent-filter, so the TWA is able to
                // handle Intents to open https://svgomg.firebaseapp.com.
                hostName: "io.emberclear",
                defaultUrl: "https://emberclear.io",
                launcherName: "emberclear",
                // This variable below expresses the relationship between the app and the site,
                // as documented in the TWA documentation at
                // https://developers.google.com/web/updates/2017/10/using-twa#set_up_digital_asset_links_in_an_android_app
                // and is injected into the AndroidManifest.xml
                assetStatements: '[{ "relation": ["delegate_permission/common.handle_all_urls"], ' +
                        '"target": {"namespace": "web", "site": "https://emberclear.io"}}]'
        ]
    }
    signingConfigs {
        release {
            if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) {
                storeFile file(MYAPP_RELEASE_STORE_FILE)
                storePassword MYAPP_RELEASE_STORE_PASSWORD
                keyAlias MYAPP_RELEASE_KEY_ALIAS
                keyPassword MYAPP_RELEASE_KEY_PASSWORD
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            signingConfig signingConfigs.release
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.github.GoogleChrome:custom-tabs-client:e446d08014'
}


================================================
FILE: client/android-wrapper/app/src/main/AndroidManifest.xml
================================================
<!--
    Copyright 2019 Google Inc. All Rights Reserved.

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT 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 "package" attribute is rewritten by the Gradle build with the value of applicationId.
     It is still required here, as it is used to derive paths, for instance when referring
     to an Activity by ".MyActivity" instead of the full name. If more Activities are added to the
     application, the package attribute will need to reflect the correct path in order to use
     the abbreviated format. -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.placeholder">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="${launcherName}"
        android:supportsRtl="true"
        android:theme="@style/Theme.TwaSplash">

        <meta-data
            android:name="asset_statements"
            android:value="${assetStatements}" />

        <activity android:name="android.support.customtabs.trusted.LauncherActivity"
            android:label="${launcherName}">
            <meta-data android:name="android.support.customtabs.trusted.DEFAULT_URL"
                android:value="${defaultUrl}" />

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE"/>
                <data android:scheme="https"
                    android:host="${hostName}"/>
            </intent-filter>
        </activity>
    </application>
</manifest>


================================================
FILE: client/android-wrapper/app/src/main/res/values/styles.xml
================================================
<!--
    Copyright 2019 Google Inc. All Rights Reserved.

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->
<resources>
    <!-- Theme to create a blank screen while the TWA is opening -->
    <style name="Theme.TwaSplash" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:windowNoTitle">true</item>
        <item name="android:backgroundDimEnabled">false</item>
    </style>
</resources>


================================================
FILE: client/android-wrapper/build.gradle
================================================
/*
 * Copyright 2015 Google 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.
 */

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.3.2'
        

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
        // Jitpack is currently being used to publish beta versions of the TWA Support Library.
        // This will change in the future to use the same approach as other Android Support
        // Libraries.
        maven { url "https://jitpack.io" }
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}


================================================
FILE: client/android-wrapper/enable-debug.sh
================================================
#!/usr/bin/env bash

#
# Copyright 2019 Google 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.
#

# Check if at least 1 argument is provided
if [[ $# -eq 0 ]]
    then
        echo "Usage: 'enable-debug.sh <host>'"
        exit 1
    fi

# Invokes ADB and creates the file with the command line
adb shell "echo '_ --disable-digital-asset-link-verification-for-url=\"$1\"' > /data/local/tmp/chrome-command-line"


================================================
FILE: client/android-wrapper/gradle/wrapper/gradle-wrapper.properties
================================================
#Mon Feb 18 11:18:13 EST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip


================================================
FILE: client/android-wrapper/gradle/wrapper/gradle.properties
================================================


================================================
FILE: client/android-wrapper/gradle.properties
================================================
MYAPP_RELEASE_STORE_FILE=appmaker.keystore
MYAPP_RELEASE_KEY_ALIAS=appmaker-store-Uy9EZlEN6ZDfet5g0KRX
MYAPP_RELEASE_STORE_PASSWORD=oz963614f
MYAPP_RELEASE_KEY_PASSWORD=n7kqya6cy

================================================
FILE: client/android-wrapper/gradlew
================================================
#!/usr/bin/env sh

##############################################################################
##
##  Gradle start up script for UN*X
##
##############################################################################

# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
    ls=`ls -ld "$PRG"`
    link=`expr "$ls" : '.*-> \(.*\)$'`
    if expr "$link" : '/.*' > /dev/null; then
        PRG="$link"
    else
        PRG=`dirname "$PRG"`"/$link"
    fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null

APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"

warn () {
    echo "$*"
}

die () {
    echo
    echo "$*"
    echo
    exit 1
}

# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
  CYGWIN* )
    cygwin=true
    ;;
  Darwin* )
    darwin=true
    ;;
  MINGW* )
    msys=true
    ;;
  NONSTOP* )
    nonstop=true
    ;;
esac

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar

# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
        # IBM's JDK on AIX uses strange locations for the executables
        JAVACMD="$JAVA_HOME/jre/sh/java"
    else
        JAVACMD="$JAVA_HOME/bin/java"
    fi
    if [ ! -x "$JAVACMD" ] ; then
        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
    fi
else
    JAVACMD="java"
    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi

# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
    MAX_FD_LIMIT=`ulimit -H -n`
    if [ $? -eq 0 ] ; then
        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
            MAX_FD="$MAX_FD_LIMIT"
        fi
        ulimit -n $MAX_FD
        if [ $? -ne 0 ] ; then
            warn "Could not set maximum file descriptor limit: $MAX_FD"
        fi
    else
        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
    fi
fi

# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi

# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
    JAVACMD=`cygpath --unix "$JAVACMD"`

    # We build the pattern for arguments to be converted via cygpath
    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
    SEP=""
    for dir in $ROOTDIRSRAW ; do
        ROOTDIRS="$ROOTDIRS$SEP$dir"
        SEP="|"
    done
    OURCYGPATTERN="(^($ROOTDIRS))"
    # Add a user-defined pattern to the cygpath arguments
    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
    fi
    # Now convert the arguments - kludge to limit ourselves to /bin/sh
    i=0
    for arg in "$@" ; do
        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option

        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
        else
            eval `echo args$i`="\"$arg\""
        fi
        i=$((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" ;;
    esac
fi

# Escape application args
save () {
    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
    echo " "
}
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" "$@"


================================================
FILE: client/android-wrapper/gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem  Gradle startup script for Windows
@rem
@rem ##########################################################################

@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal

set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@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=

@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto init

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:init
@rem Get command-line arguments, handling Windows variants

if not "%OS%" == "Windows_NT" goto win9xME_args

:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2

:win9xME_args_slurp
if "x%~1" == "x" goto execute

set CMD_LINE_ARGS=%*

:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1

:mainEnd
if "%OS%"=="Windows_NT" endlocal

:omega


================================================
FILE: client/android-wrapper/settings.gradle
================================================
include ':app'


================================================
FILE: client/web/.eslintignore
================================================
**/declarations/
**/concat-stats-for/
**/dist/
**/tmp/
/node_modules/
**/node_modules/
**/public/
**/vendor/


================================================
FILE: client/web/.eslintrc.js
================================================
'use strict';

const { configs } = require('@nullvoxpopuli/eslint-configs');

module.exports = configs.node();


================================================
FILE: client/web/.gitignore
================================================
.eslintcache
.stylelintcache
tsconfig.tsbuildinfo


================================================
FILE: client/web/.prettierignore
================================================
**/blueprints/*/files/**/*.js
**/bip39/wordlists/english.ts


================================================
FILE: client/web/.prettierrc.js
================================================
'use strict';

module.exports = {
  singleQuote: true,
  trailingComma: 'es5',
  printWidth: 100,
  semi: true,
  bracketSpacing: true,
  endOfLine: 'lf',
  tabs: false,
  tabWidth: 2,
};


================================================
FILE: client/web/.stylelintignore
================================================
# Projects without CSS
smoke-tests/

# Ignore supporting directories to improve scan time
**/concat-stats-for/**
**/dummy/**
**/dist/**
**/node_modules/**
node_modules/**
**/tmp/**
**/public/**
**/vendor/**



================================================
FILE: client/web/.template-lintrc.js
================================================
'use strict';

module.exports = require('@emberclear/config/.template-lintrc');


================================================
FILE: client/web/.vim/coc-settings.json
================================================
{
  "cSpell.words": [
    "Encryptable",
    "Parallelizable",
    "REFAN",
    "REFLAT",
    "Serializable",
    "Synthwave",
    "ciphertext",
    "cond",
    "emberclear",
    "esbuild",
    "keypair",
    "klass",
    "nacl",
    "outfile",
    "prismjs",
    "sourcemap",
    "tmpl"
  ]
}

================================================
FILE: client/web/.vscode/settings.json
================================================
{
    "typescript.tsdk": "node_modules/typescript/lib"
}

================================================
FILE: client/web/addons/crypto/.editorconfig
================================================
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org

root = true

[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = space
indent_size = 2

[*.hbs]
insert_final_newline = false

[*.{diff,md}]
trim_trailing_whitespace = false


================================================
FILE: client/web/addons/crypto/.ember-cli
================================================
{
  /**
    Ember CLI sends analytics information by default. The data is completely
    anonymous, but there are times when you might want to disable this behavior.

    Setting `disableAnalytics` to true will prevent any data from being sent.
  */
  "disableAnalytics": false
}


================================================
FILE: client/web/addons/crypto/.eslintignore
================================================
# unconventional js
/blueprints/*/files/
/vendor/

# compiled output
/dist/
/tmp/

# TypeScript output
declarations/
tsconfig.tsbuildinfo


# dependencies
/bower_components/
/node_modules/

# misc
/coverage/
!.*

# ember-try
/.node_modules.ember-try/
/bower.json.ember-try
/package.json.ember-try


================================================
FILE: client/web/addons/crypto/.eslintrc.js
================================================
'use strict';

const { configs } = require('@nullvoxpopuli/eslint-configs');

module.exports = configs.ember();


================================================
FILE: client/web/addons/crypto/.gitignore
================================================
# See https://help.github.com/ignore-files/ for more about ignoring files.

# compiled output
/dist/
/tmp/

# TypeScript output
declarations/
tsconfig.tsbuildinfo

# dependencies
/bower_components/
/node_modules/

# misc
/.env*
/.pnp*
/.sass-cache
/connect.lock
/coverage/
/libpeerconnection.log
/npm-debug.log*
/testem.log
/yarn-error.log

# ember-try
/.node_modules.ember-try/
/bower.json.ember-try
/package.json.ember-try


================================================
FILE: client/web/addons/crypto/.npmignore
================================================
# compiled output
/dist/
/tmp/

# dependencies
/bower_components/

# misc
/.bowerrc
/.editorconfig
/.ember-cli
/.env*
/.eslintignore
/.eslintrc.js
/.git/
/.gitignore
/.template-lintrc.js
/.travis.yml
/.watchmanconfig
/bower.json
/config/ember-try.js
/CONTRIBUTING.md
/ember-cli-build.js
/testem.js
/tests/
/yarn.lock
.gitkeep

# ember-try
/.node_modules.ember-try/
/bower.json.ember-try
/package.json.ember-try


================================================
FILE: client/web/addons/crypto/.template-lintrc.js
================================================
'use strict';

module.exports = require('@emberclear/config/.template-lintrc');


================================================
FILE: client/web/addons/crypto/.watchmanconfig
================================================
{
  "ignore_dirs": ["tmp", "dist"]
}


================================================
FILE: client/web/addons/crypto/CONTRIBUTING.md
================================================
# How To Contribute

## Installation

* `git clone <repository-url>`
* `cd crypto`
* `yarn install`

## Linting

* `yarn lint:hbs`
* `yarn lint:js`
* `yarn lint:js --fix`

## Running tests

* `ember test` – Runs the test suite on the current Ember version
* `ember test --server` – Runs the test suite in "watch mode"
* `ember try:each` – Runs the test suite against multiple Ember versions

## Running the dummy application

* `ember serve`
* Visit the dummy application at [http://localhost:4200](http://localhost:4200).

For more information on using ember-cli, visit [https://ember-cli.com/](https://ember-cli.com/).


================================================
FILE: client/web/addons/crypto/LICENSE.md
================================================
The MIT License (MIT)

Copyright (c) 2020

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.


================================================
FILE: client/web/addons/crypto/README.md
================================================
crypto
==============================================================================

[Short description of the addon.]


Compatibility
------------------------------------------------------------------------------

* Ember.js v3.16 or above
* Ember CLI v2.13 or above
* Node.js v10 or above


Installation
------------------------------------------------------------------------------

```
ember install crypto
```


Usage
------------------------------------------------------------------------------

[Longer description of how to use the addon in apps.]


Contributing
------------------------------------------------------------------------------

See the [Contributing](CONTRIBUTING.md) guide for details.


License
------------------------------------------------------------------------------

This project is licensed under the [MIT License](LICENSE.md).


================================================
FILE: client/web/addons/crypto/addon/-private/types.ts
================================================
import type { handleMessage } from '../workers/crypto/messages';

export interface WorkerLike {
  postMessage: typeof handleMessage;
  _worker?: Worker;
}

export type WorkerRegistry = { [path: string]: WorkerLike };


================================================
FILE: client/web/addons/crypto/addon/connector.ts
================================================
import type { WorkersService } from '@emberclear/crypto';
import type { WorkerLike } from '@emberclear/crypto/-private/types';
import type { EncryptedMessage, KeyPair, KeyPublic, Serializable } from '@emberclear/crypto/types';

type Args = {
  workerService: WorkersService;
  keys?: KeyPair;
};

const Action = {
  // Generation
  LOGIN: 0,
  GENERATE_KEYS: 1,
  DECRYPT_FROM_SOCKET: 2,
  ENCRYPT_FOR_SOCKET: 3,
  GENERATE_SIGNING_KEYS: 4,
  SIGN: 5,
  OPEN_SIGNED: 6,
  HASH: 7,

  // Conversions
  MNEMONIC_FROM_PRIVATE_KEY: 50,

  // TODO: should find a way to not need these
  DERIVE_PUBLIC_KEY: 100,
  DERIVE_PUBLIC_SIGNING_KEY: 101,
} as const;

export default class CryptoConnector {
  getWorker: () => WorkerLike;
  keys: KeyPair;

  constructor({ workerService, keys }: Args) {
    let { privateKey, publicKey } = keys || ({} as KeyPair);

    this.getWorker = workerService.getCryptoWorker;
    this.keys = { privateKey, publicKey };
  }

  async login(mnemonic: string) {
    let worker = this.getWorker();

    return await worker.postMessage({
      action: Action.LOGIN,
      args: [mnemonic],
    });
  }

  async mnemonicFromNaClBoxPrivateKey(key?: Uint8Array) {
    let worker = this.getWorker();

    return await worker.postMessage({
      action: Action.MNEMONIC_FROM_PRIVATE_KEY,
      args: [key || this.keys.publicKey],
    });
  }

  async generateKeys() {
    let worker = this.getWorker();

    return await worker.postMessage({
      action: Action.GENERATE_KEYS,
      args: [],
    });
  }

  async generateSigningKeys() {
    let worker = this.getWorker();

    return await worker.postMessage({
      action: Action.GENERATE_SIGNING_KEYS,
      args: [],
    });
  }

  async derivePublicKey(privateKey: Uint8Array) {
    let worker = this.getWorker();

    return await worker.postMessage({
      action: Action.DERIVE_PUBLIC_KEY,
      args: [privateKey],
    });
  }

  async derivePublicSigningKey(privateSigningKey: Uint8Array) {
    let worker = this.getWorker();

    return await worker.postMessage({
      action: Action.DERIVE_PUBLIC_SIGNING_KEY,
      args: [privateSigningKey],
    });
  }

  async encryptForSocket(payload: Serializable, { publicKey }: KeyPublic) {
    let worker = this.getWorker();

    return await worker.postMessage({
      action: Action.ENCRYPT_FOR_SOCKET,
      args: [payload, { publicKey }, { privateKey: this.keys.privateKey }],
    });
  }

  async decryptFromSocket<ExpectedReturn = unknown>(socketData: EncryptedMessage) {
    let worker = this.getWorker();

    return (await worker.postMessage({
      action: Action.DECRYPT_FROM_SOCKET,
      args: [socketData, this.keys.privateKey],
    })) as Promise<ExpectedReturn>;
  }

  async sign(message: Uint8Array, senderPrivateKey: Uint8Array) {
    let worker = this.getWorker();

    return await worker.postMessage({
      action: Action.SIGN,
      args: [message, senderPrivateKey],
    });
  }

  async openSigned(signedMessage: Uint8Array, senderPublicKey: Uint8Array) {
    let worker = this.getWorker();

    return await worker.postMessage({
      action: Action.OPEN_SIGNED,
      args: [signedMessage, senderPublicKey],
    });
  }

  async hash(message: Uint8Array) {
    let worker = this.getWorker();

    return await worker.postMessage({
      action: Action.HASH,
      args: [message],
    });
  }
}


================================================
FILE: client/web/addons/crypto/addon/index.ts
================================================
export { default as CryptoConnector } from './connector';
export { default as WorkersService } from './services/workers';
export type {
  KeyPair,
  KeyPrivate,
  KeyPublic,
  SigningKeyPair,
  SigningKeyPrivate,
  SigningKeyPublic,
} from './types';


================================================
FILE: client/web/addons/crypto/addon/services/workers.ts
================================================
import { action } from '@ember/object';
import Service from '@ember/service';

import { PWBHost } from 'promise-worker-bi';

import type { WorkerLike, WorkerRegistry } from '@emberclear/crypto/-private/types';

export const CRYPTO_PATH = '/workers/crypto';
export const NETWORKING_PATH = '/workers/networking';

export default class WorkersService extends Service {
  registry: WorkerRegistry = {};

  @action
  getCryptoWorker() {
    return this.getWorker(CRYPTO_PATH);
  }

  @action
  getNetworkingWorker() {
    return this.getWorker(NETWORKING_PATH);
  }

  protected getWorker(path: string): WorkerLike {
    if (this.registry[path]) return this.registry[path];

    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    let worker = new Worker(`${path}${(window as any).ASSET_FINGERPRINT_HASH || ''}.js`);
    let promiseWorker = new PWBHost(worker);
    // promiseWorker._hostIDQueue = undefined;

    if (!promiseWorker) {
      throw new Error('failed to create promiseWorker?');
    }

    promiseWorker.register(function (message: string) {
      console.info(`Received message in ${path}: `, message);
    });

    promiseWorker.registerError(function (err: Error) {
      console.error(`Error in ${path}: `, err);
    });

    this.registry[path] = promiseWorker as WorkerLike;

    return this.registry[path];
  }

  willDestroy() {
    Object.values(this.registry).forEach((promiseWorker) => {
      promiseWorker._worker?.terminate();
    });
  }
}

// DO NOT DELETE: this is how TypeScript knows how to look up your services.
declare module '@ember/service' {
  interface Registry {
    workers: WorkersService;
  }
}


================================================
FILE: client/web/addons/crypto/addon/tsconfig.json
================================================
{
  "extends": "../tsconfig.compiler-options.json",
  "compilerOptions": {
    "baseUrl": ".",
    "declarationDir": "../declarations",
    "paths": {
      "@emberclear/crypto": ["."],
      "@emberclear/crypto/*": ["./*"],

      "*": ["../types/*"]
    }
  },
  "include": [".", "../types"],
  "references": [
    { "path": "../../../libraries/questionably-typed" }
  ]
}


================================================
FILE: client/web/addons/crypto/addon/types.ts
================================================
export type KeyPublic = { publicKey: Uint8Array };
export type KeyPrivate = { privateKey: Uint8Array };
export type KeyPair = KeyPublic & KeyPrivate;

export type SigningKeyPublic = { publicSigningKey: Uint8Array };
export type SigningKeyPrivate = { privateSigningKey: Uint8Array };
export type SigningKeyPair = SigningKeyPublic & SigningKeyPrivate;

export interface EncryptedMessage {
  // recipient
  uid: string;
  // ciphertext
  message: string;
}

export type Serializable =
  | string
  | number
  | boolean
  | null
  | undefined
  | Date
  | Serializable[]
  | { [key: string]: Serializable };

export interface EncryptableObject {
  [key: string]: Serializable;
}


================================================
FILE: client/web/addons/crypto/addon/workers/crypto/actions.ts
================================================
import { naclBoxPrivateKeyFromMnemonic } from './utils/mnemonic';
import { derivePublicKey, generateSigningKeys } from './utils/nacl';

import type { KeyPair, SigningKeyPair } from '@emberclear/crypto/types';

export async function login(mnemonic: string): Promise<KeyPair & SigningKeyPair> {
  let privateKey = await naclBoxPrivateKeyFromMnemonic(mnemonic);
  let publicKey = await derivePublicKey(privateKey);

  let { publicSigningKey, privateSigningKey } = await generateSigningKeys();

  return { publicKey, privateKey, publicSigningKey, privateSigningKey };
}


================================================
FILE: client/web/addons/crypto/addon/workers/crypto/index.ts
================================================
import { PWBWorker } from 'promise-worker-bi';

import { handleMessage } from './messages';

import type { CryptoMessage } from './messages';

let promiseWorker = new PWBWorker();

promiseWorker.register(function (message: CryptoMessage) {
  return handleMessage(message);
});


================================================
FILE: client/web/addons/crypto/addon/workers/crypto/messages.ts
================================================
import { login } from './actions';
import { mnemonicFromNaClBoxPrivateKey } from './utils/mnemonic';
import {
  derivePublicKey,
  derivePublicSigningKey,
  generateAsymmetricKeys,
  generateSigningKeys,
  hash,
  openSigned,
  sign,
} from './utils/nacl';
import { decryptFromSocket, encryptForSocket } from './utils/socket';

const Action = {
  // Generation
  LOGIN: 0,
  GENERATE_KEYS: 1,
  DECRYPT_FROM_SOCKET: 2,
  ENCRYPT_FOR_SOCKET: 3,
  GENERATE_SIGNING_KEYS: 4,
  SIGN: 5,
  OPEN_SIGNED: 6,
  HASH: 7,

  // Conversions
  MNEMONIC_FROM_PRIVATE_KEY: 50,

  // TODO: should find a way to not need these
  DERIVE_PUBLIC_KEY: 100,
  DERIVE_PUBLIC_SIGNING_KEY: 101,
} as const;

export type API = {
  [Action.LOGIN]: typeof login;
  [Action.GENERATE_KEYS]: typeof generateAsymmetricKeys;
  [Action.GENERATE_SIGNING_KEYS]: typeof generateSigningKeys;
  [Action.DECRYPT_FROM_SOCKET]: typeof decryptFromSocket;
  [Action.ENCRYPT_FOR_SOCKET]: typeof encryptForSocket;
  [Action.SIGN]: typeof sign;
  [Action.OPEN_SIGNED]: typeof openSigned;
  [Action.HASH]: typeof hash;
  [Action.DERIVE_PUBLIC_KEY]: typeof derivePublicKey;
  [Action.DERIVE_PUBLIC_SIGNING_KEY]: typeof derivePublicSigningKey;
  [Action.MNEMONIC_FROM_PRIVATE_KEY]: typeof mnemonicFromNaClBoxPrivateKey;
};

export type CryptoMessage = {
  action: keyof API;
  args: Parameters<API[keyof API]>;
};

export type Message<Action, Args> = { action: Action; args: Args };

export function handleMessage<Action extends keyof API>(
  message: Message<Action, Parameters<API[Action]>>
): ReturnType<API[Action]> {
  const { action, args } = message as TODO;

  switch (action) {
    case Action.LOGIN:
      return (login as TODO)(...args);
    case Action.GENERATE_KEYS:
      return (generateAsymmetricKeys as TODO)();
    case Action.GENERATE_SIGNING_KEYS:
      return (generateSigningKeys as TODO)();
    case Action.DECRYPT_FROM_SOCKET:
      return (decryptFromSocket as TODO)(...args);
    case Action.ENCRYPT_FOR_SOCKET:
      return (encryptForSocket as TODO)(...args);
    case Action.SIGN:
      return (sign as TODO)(...args);
    case Action.OPEN_SIGNED:
      return (openSigned as TODO)(...args);
    case Action.HASH:
      return (hash as TODO)(...args);
    case Action.DERIVE_PUBLIC_KEY:
      return (derivePublicKey as TODO)(...args);
    case Action.DERIVE_PUBLIC_SIGNING_KEY:
      return (derivePublicSigningKey as TODO)(...args);
    case Action.MNEMONIC_FROM_PRIVATE_KEY:
      return (mnemonicFromNaClBoxPrivateKey as TODO)(...args);
    default:
      throw new Error(`unknown message for crypto worker: ${action}`);
  }
}


================================================
FILE: client/web/addons/crypto/addon/workers/crypto/utils/array.ts
================================================
export function concat(arr1: Uint8Array, arr2: Uint8Array): Uint8Array {
  const result = new Uint8Array(arr1.length + arr2.length);

  result.set(arr1, 0);
  result.set(arr2, arr1.length);

  return result;
}


================================================
FILE: client/web/addons/crypto/addon/workers/crypto/utils/bip39/wordlists/english.ts
================================================
export const wordlist = [
  'abandon',
  'ability',
  'able',
  'about',
  'above',
  'absent',
  'absorb',
  'abstract',
  'absurd',
  'abuse',
  'access',
  'accident',
  'account',
  'accuse',
  'achieve',
  'acid',
  'acoustic',
  'acquire',
  'across',
  'act',
  'action',
  'actor',
  'actress',
  'actual',
  'adapt',
  'add',
  'addict',
  'address',
  'adjust',
  'admit',
  'adult',
  'advance',
  'advice',
  'aerobic',
  'affair',
  'afford',
  'afraid',
  'again',
  'age',
  'agent',
  'agree',
  'ahead',
  'aim',
  'air',
  'airport',
  'aisle',
  'alarm',
  'album',
  'alcohol',
  'alert',
  'alien',
  'all',
  'alley',
  'allow',
  'almost',
  'alone',
  'alpha',
  'already',
  'also',
  'alter',
  'always',
  'amateur',
  'amazing',
  'among',
  'amount',
  'amused',
  'analyst',
  'anchor',
  'ancient',
  'anger',
  'angle',
  'angry',
  'animal',
  'ankle',
  'announce',
  'annual',
  'another',
  'answer',
  'antenna',
  'antique',
  'anxiety',
  'any',
  'apart',
  'apology',
  'appear',
  'apple',
  'approve',
  'april',
  'arch',
  'arctic',
  'area',
  'arena',
  'argue',
  'arm',
  'armed',
  'armor',
  'army',
  'around',
  'arrange',
  'arrest',
  'arrive',
  'arrow',
  'art',
  'artefact',
  'artist',
  'artwork',
  'ask',
  'aspect',
  'assault',
  'asset',
  'assist',
  'assume',
  'asthma',
  'athlete',
  'atom',
  'attack',
  'attend',
  'attitude',
  'attract',
  'auction',
  'audit',
  'august',
  'aunt',
  'author',
  'auto',
  'autumn',
  'average',
  'avocado',
  'avoid',
  'awake',
  'aware',
  'away',
  'awesome',
  'awful',
  'awkward',
  'axis',
  'baby',
  'bachelor',
  'bacon',
  'badge',
  'bag',
  'balance',
  'balcony',
  'ball',
  'bamboo',
  'banana',
  'banner',
  'bar',
  'barely',
  'bargain',
  'barrel',
  'base',
  'basic',
  'basket',
  'battle',
  'beach',
  'bean',
  'beauty',
  'because',
  'become',
  'beef',
  'before',
  'begin',
  'behave',
  'behind',
  'believe',
  'below',
  'belt',
  'bench',
  'benefit',
  'best',
  'betray',
  'better',
  'between',
  'beyond',
  'bicycle',
  'bid',
  'bike',
  'bind',
  'biology',
  'bird',
  'birth',
  'bitter',
  'black',
  'blade',
  'blame',
  'blanket',
  'blast',
  'bleak',
  'bless',
  'blind',
  'blood',
  'blossom',
  'blouse',
  'blue',
  'blur',
  'blush',
  'board',
  'boat',
  'body',
  'boil',
  'bomb',
  'bone',
  'bonus',
  'book',
  'boost',
  'border',
  'boring',
  'borrow',
  'boss',
  'bottom',
  'bounce',
  'box',
  'boy',
  'bracket',
  'brain',
  'brand',
  'brass',
  'brave',
  'bread',
  'breeze',
  'brick',
  'bridge',
  'brief',
  'bright',
  'bring',
  'brisk',
  'broccoli',
  'broken',
  'bronze',
  'broom',
  'brother',
  'brown',
  'brush',
  'bubble',
  'buddy',
  'budget',
  'buffalo',
  'build',
  'bulb',
  'bulk',
  'bullet',
  'bundle',
  'bunker',
  'burden',
  'burger',
  'burst',
  'bus',
  'business',
  'busy',
  'butter',
  'buyer',
  'buzz',
  'cabbage',
  'cabin',
  'cable',
  'cactus',
  'cage',
  'cake',
  'call',
  'calm',
  'camera',
  'camp',
  'can',
  'canal',
  'cancel',
  'candy',
  'cannon',
  'canoe',
  'canvas',
  'canyon',
  'capable',
  'capital',
  'captain',
  'car',
  'carbon',
  'card',
  'cargo',
  'carpet',
  'carry',
  'cart',
  'case',
  'cash',
  'casino',
  'castle',
  'casual',
  'cat',
  'catalog',
  'catch',
  'category',
  'cattle',
  'caught',
  'cause',
  'caution',
  'cave',
  'ceiling',
  'celery',
  'cement',
  'census',
  'century',
  'cereal',
  'certain',
  'chair',
  'chalk',
  'champion',
  'change',
  'chaos',
  'chapter',
  'charge',
  'chase',
  'chat',
  'cheap',
  'check',
  'cheese',
  'chef',
  'cherry',
  'chest',
  'chicken',
  'chief',
  'child',
  'chimney',
  'choice',
  'choose',
  'chronic',
  'chuckle',
  'chunk',
  'churn',
  'cigar',
  'cinnamon',
  'circle',
  'citizen',
  'city',
  'civil',
  'claim',
  'clap',
  'clarify',
  'claw',
  'clay',
  'clean',
  'clerk',
  'clever',
  'click',
  'client',
  'cliff',
  'climb',
  'clinic',
  'clip',
  'clock',
  'clog',
  'close',
  'cloth',
  'cloud',
  'clown',
  'club',
  'clump',
  'cluster',
  'clutch',
  'coach',
  'coast',
  'coconut',
  'code',
  'coffee',
  'coil',
  'coin',
  'collect',
  'color',
  'column',
  'combine',
  'come',
  'comfort',
  'comic',
  'common',
  'company',
  'concert',
  'conduct',
  'confirm',
  'congress',
  'connect',
  'consider',
  'control',
  'convince',
  'cook',
  'cool',
  'copper',
  'copy',
  'coral',
  'core',
  'corn',
  'correct',
  'cost',
  'cotton',
  'couch',
  'country',
  'couple',
  'course',
  'cousin',
  'cover',
  'coyote',
  'crack',
  'cradle',
  'craft',
  'cram',
  'crane',
  'crash',
  'crater',
  'crawl',
  'crazy',
  'cream',
  'credit',
  'creek',
  'crew',
  'cricket',
  'crime',
  'crisp',
  'critic',
  'crop',
  'cross',
  'crouch',
  'crowd',
  'crucial',
  'cruel',
  'cruise',
  'crumble',
  'crunch',
  'crush',
  'cry',
  'crystal',
  'cube',
  'culture',
  'cup',
  'cupboard',
  'curious',
  'current',
  'curtain',
  'curve',
  'cushion',
  'custom',
  'cute',
  'cycle',
  'dad',
  'damage',
  'damp',
  'dance',
  'danger',
  'daring',
  'dash',
  'daughter',
  'dawn',
  'day',
  'deal',
  'debate',
  'debris',
  'decade',
  'december',
  'decide',
  'decline',
  'decorate',
  'decrease',
  'deer',
  'defense',
  'define',
  'defy',
  'degree',
  'delay',
  'deliver',
  'demand',
  'demise',
  'denial',
  'dentist',
  'deny',
  'depart',
  'depend',
  'deposit',
  'depth',
  'deputy',
  'derive',
  'describe',
  'desert',
  'design',
  'desk',
  'despair',
  'destroy',
  'detail',
  'detect',
  'develop',
  'device',
  'devote',
  'diagram',
  'dial',
  'diamond',
  'diary',
  'dice',
  'diesel',
  'diet',
  'differ',
  'digital',
  'dignity',
  'dilemma',
  'dinner',
  'dinosaur',
  'direct',
  'dirt',
  'disagree',
  'discover',
  'disease',
  'dish',
  'dismiss',
  'disorder',
  'display',
  'distance',
  'divert',
  'divide',
  'divorce',
  'dizzy',
  'doctor',
  'document',
  'dog',
  'doll',
  'dolphin',
  'domain',
  'donate',
  'donkey',
  'donor',
  'door',
  'dose',
  'double',
  'dove',
  'draft',
  'dragon',
  'drama',
  'drastic',
  'draw',
  'dream',
  'dress',
  'drift',
  'drill',
  'drink',
  'drip',
  'drive',
  'drop',
  'drum',
  'dry',
  'duck',
  'dumb',
  'dune',
  'during',
  'dust',
  'dutch',
  'duty',
  'dwarf',
  'dynamic',
  'eager',
  'eagle',
  'early',
  'earn',
  'earth',
  'easily',
  'east',
  'easy',
  'echo',
  'ecology',
  'economy',
  'edge',
  'edit',
  'educate',
  'effort',
  'egg',
  'eight',
  'either',
  'elbow',
  'elder',
  'electric',
  'elegant',
  'element',
  'elephant',
  'elevator',
  'elite',
  'else',
  'embark',
  'embody',
  'embrace',
  'emerge',
  'emotion',
  'employ',
  'empower',
  'empty',
  'enable',
  'enact',
  'end',
  'endless',
  'endorse',
  'enemy',
  'energy',
  'enforce',
  'engage',
  'engine',
  'enhance',
  'enjoy',
  'enlist',
  'enough',
  'enrich',
  'enroll',
  'ensure',
  'enter',
  'entire',
  'entry',
  'envelope',
  'episode',
  'equal',
  'equip',
  'era',
  'erase',
  'erode',
  'erosion',
  'error',
  'erupt',
  'escape',
  'essay',
  'essence',
  'estate',
  'eternal',
  'ethics',
  'evidence',
  'evil',
  'evoke',
  'evolve',
  'exact',
  'example',
  'excess',
  'exchange',
  'excite',
  'exclude',
  'excuse',
  'execute',
  'exercise',
  'exhaust',
  'exhibit',
  'exile',
  'exist',
  'exit',
  'exotic',
  'expand',
  'expect',
  'expire',
  'explain',
  'expose',
  'express',
  'extend',
  'extra',
  'eye',
  'eyebrow',
  'fabric',
  'face',
  'faculty',
  'fade',
  'faint',
  'faith',
  'fall',
  'false',
  'fame',
  'family',
  'famous',
  'fan',
  'fancy',
  'fantasy',
  'farm',
  'fashion',
  'fat',
  'fatal',
  'father',
  'fatigue',
  'fault',
  'favorite',
  'feature',
  'february',
  'federal',
  'fee',
  'feed',
  'feel',
  'female',
  'fence',
  'festival',
  'fetch',
  'fever',
  'few',
  'fiber',
  'fiction',
  'field',
  'figure',
  'file',
  'film',
  'filter',
  'final',
  'find',
  'fine',
  'finger',
  'finish',
  'fire',
  'firm',
  'first',
  'fiscal',
  'fish',
  'fit',
  'fitness',
  'fix',
  'flag',
  'flame',
  'flash',
  'flat',
  'flavor',
  'flee',
  'flight',
  'flip',
  'float',
  'flock',
  'floor',
  'flower',
  'fluid',
  'flush',
  'fly',
  'foam',
  'focus',
  'fog',
  'foil',
  'fold',
  'follow',
  'food',
  'foot',
  'force',
  'forest',
  'forget',
  'fork',
  'fortune',
  'forum',
  'forward',
  'fossil',
  'foster',
  'found',
  'fox',
  'fragile',
  'frame',
  'frequent',
  'fresh',
  'friend',
  'fringe',
  'frog',
  'front',
  'frost',
  'frown',
  'frozen',
  'fruit',
  'fuel',
  'fun',
  'funny',
  'furnace',
  'fury',
  'future',
  'gadget',
  'gain',
  'galaxy',
  'gallery',
  'game',
  'gap',
  'garage',
  'garbage',
  'garden',
  'garlic',
  'garment',
  'gas',
  'gasp',
  'gate',
  'gather',
  'gauge',
  'gaze',
  'general',
  'genius',
  'genre',
  'gentle',
  'genuine',
  'gesture',
  'ghost',
  'giant',
  'gift',
  'giggle',
  'ginger',
  'giraffe',
  'girl',
  'give',
  'glad',
  'glance',
  'glare',
  'glass',
  'glide',
  'glimpse',
  'globe',
  'gloom',
  'glory',
  'glove',
  'glow',
  'glue',
  'goat',
  'goddess',
  'gold',
  'good',
  'goose',
  'gorilla',
  'gospel',
  'gossip',
  'govern',
  'gown',
  'grab',
  'grace',
  'grain',
  'grant',
  'grape',
  'grass',
  'gravity',
  'great',
  'green',
  'grid',
  'grief',
  'grit',
  'grocery',
  'group',
  'grow',
  'grunt',
  'guard',
  'guess',
  'guide',
  'guilt',
  'guitar',
  'gun',
  'gym',
  'habit',
  'hair',
  'half',
  'hammer',
  'hamster',
  'hand',
  'happy',
  'harbor',
  'hard',
  'harsh',
  'harvest',
  'hat',
  'have',
  'hawk',
  'hazard',
  'head',
  'health',
  'heart',
  'heavy',
  'hedgehog',
  'height',
  'hello',
  'helmet',
  'help',
  'hen',
  'hero',
  'hidden',
  'high',
  'hill',
  'hint',
  'hip',
  'hire',
  'history',
  'hobby',
  'hockey',
  'hold',
  'hole',
  'holiday',
  'hollow',
  'home',
  'honey',
  'hood',
  'hope',
  'horn',
  'horror',
  'horse',
  'hospital',
  'host',
  'hotel',
  'hour',
  'hover',
  'hub',
  'huge',
  'human',
  'humble',
  'humor',
  'hundred',
  'hungry',
  'hunt',
  'hurdle',
  'hurry',
  'hurt',
  'husband',
  'hybrid',
  'ice',
  'icon',
  'idea',
  'identify',
  'idle',
  'ignore',
  'ill',
  'illegal',
  'illness',
  'image',
  'imitate',
  'immense',
  'immune',
  'impact',
  'impose',
  'improve',
  'impulse',
  'inch',
  'include',
  'income',
  'increase',
  'index',
  'indicate',
  'indoor',
  'industry',
  'infant',
  'inflict',
  'inform',
  'inhale',
  'inherit',
  'initial',
  'inject',
  'injury',
  'inmate',
  'inner',
  'innocent',
  'input',
  'inquiry',
  'insane',
  'insect',
  'inside',
  'inspire',
  'install',
  'intact',
  'interest',
  'into',
  'invest',
  'invite',
  'involve',
  'iron',
  'island',
  'isolate',
  'issue',
  'item',
  'ivory',
  'jacket',
  'jaguar',
  'jar',
  'jazz',
  'jealous',
  'jeans',
  'jelly',
  'jewel',
  'job',
  'join',
  'joke',
  'journey',
  'joy',
  'judge',
  'juice',
  'jump',
  'jungle',
  'junior',
  'junk',
  'just',
  'kangaroo',
  'keen',
  'keep',
  'ketchup',
  'key',
  'kick',
  'kid',
  'kidney',
  'kind',
  'kingdom',
  'kiss',
  'kit',
  'kitchen',
  'kite',
  'kitten',
  'kiwi',
  'knee',
  'knife',
  'knock',
  'know',
  'lab',
  'label',
  'labor',
  'ladder',
  'lady',
  'lake',
  'lamp',
  'language',
  'laptop',
  'large',
  'later',
  'latin',
  'laugh',
  'laundry',
  'lava',
  'law',
  'lawn',
  'lawsuit',
  'layer',
  'lazy',
  'leader',
  'leaf',
  'learn',
  'leave',
  'lecture',
  'left',
  'leg',
  'legal',
  'legend',
  'leisure',
  'lemon',
  'lend',
  'length',
  'lens',
  'leopard',
  'lesson',
  'letter',
  'level',
  'liar',
  'liberty',
  'library',
  'license',
  'life',
  'lift',
  'light',
  'like',
  'limb',
  'limit',
  'link',
  'lion',
  'liquid',
  'list',
  'little',
  'live',
  'lizard',
  'load',
  'loan',
  'lobster',
  'local',
  'lock',
  'logic',
  'lonely',
  'long',
  'loop',
  'lottery',
  'loud',
  'lounge',
  'love',
  'loyal',
  'lucky',
  'luggage',
  'lumber',
  'lunar',
  'lunch',
  'luxury',
  'lyrics',
  'machine',
  'mad',
  'magic',
  'magnet',
  'maid',
  'mail',
  'main',
  'major',
  'make',
  'mammal',
  'man',
  'manage',
  'mandate',
  'mango',
  'mansion',
  'manual',
  'maple',
  'marble',
  'march',
  'margin',
  'marine',
  'market',
  'marriage',
  'mask',
  'mass',
  'master',
  'match',
  'material',
  'math',
  'matrix',
  'matter',
  'maximum',
  'maze',
  'meadow',
  'mean',
  'measure',
  'meat',
  'mechanic',
  'medal',
  'media',
  'melody',
  'melt',
  'member',
  'memory',
  'mention',
  'menu',
  'mercy',
  'merge',
  'merit',
  'merry',
  'mesh',
  'message',
  'metal',
  'method',
  'middle',
  'midnight',
  'milk',
  'million',
  'mimic',
  'mind',
  'minimum',
  'minor',
  'minute',
  'miracle',
  'mirror',
  'misery',
  'miss',
  'mistake',
  'mix',
  'mixed',
  'mixture',
  'mobile',
  'model',
  'modify',
  'mom',
  'moment',
  'monitor',
  'monkey',
  'monster',
  'month',
  'moon',
  'moral',
  'more',
  'morning',
  'mosquito',
  'mother',
  'motion',
  'motor',
  'mountain',
  'mouse',
  'move',
  'movie',
  'much',
  'muffin',
  'mule',
  'multiply',
  'muscle',
  'museum',
  'mushroom',
  'music',
  'must',
  'mutual',
  'myself',
  'mystery',
  'myth',
  'naive',
  'name',
  'napkin',
  'narrow',
  'nasty',
  'nation',
  'nature',
  'near',
  'neck',
  'need',
  'negative',
  'neglect',
  'neither',
  'nephew',
  'nerve',
  'nest',
  'net',
  'network',
  'neutral',
  'never',
  'news',
  'next',
  'nice',
  'night',
  'noble',
  'noise',
  'nominee',
  'noodle',
  'normal',
  'north',
  'nose',
  'notable',
  'note',
  'nothing',
  'notice',
  'novel',
  'now',
  'nuclear',
  'number',
  'nurse',
  'nut',
  'oak',
  'obey',
  'object',
  'oblige',
  'obscure',
  'observe',
  'obtain',
  'obvious',
  'occur',
  'ocean',
  'october',
  'odor',
  'off',
  'offer',
  'office',
  'often',
  'oil',
  'okay',
  'old',
  'olive',
  'olympic',
  'omit',
  'once',
  'one',
  'onion',
  'online',
  'only',
  'open',
  'opera',
  'opinion',
  'oppose',
  'option',
  'orange',
  'orbit',
  'orchard',
  'order',
  'ordinary',
  'organ',
  'orient',
  'original',
  'orphan',
  'ostrich',
  'other',
  'outdoor',
  'outer',
  'output',
  'outside',
  'oval',
  'oven',
  'over',
  'own',
  'owner',
  'oxygen',
  'oyster',
  'ozone',
  'pact',
  'paddle',
  'page',
  'pair',
  'palace',
  'palm',
  'panda',
  'panel',
  'panic',
  'panther',
  'paper',
  'parade',
  'parent',
  'park',
  'parrot',
  'party',
  'pass',
  'patch',
  'path',
  'patient',
  'patrol',
  'pattern',
  'pause',
  'pave',
  'payment',
  'peace',
  'peanut',
  'pear',
  'peasant',
  'pelican',
  'pen',
  'penalty',
  'pencil',
  'people',
  'pepper',
  'perfect',
  'permit',
  'person',
  'pet',
  'phone',
  'photo',
  'phrase',
  'physical',
  'piano',
  'picnic',
  'picture',
  'piece',
  'pig',
  'pigeon',
  'pill',
  'pilot',
  'pink',
  'pioneer',
  'pipe',
  'pistol',
  'pitch',
  'pizza',
  'place',
  'planet',
  'plastic',
  'plate',
  'play',
  'please',
  'pledge',
  'pluck',
  'plug',
  'plunge',
  'poem',
  'poet',
  'point',
  'polar',
  'pole',
  'police',
  'pond',
  'pony',
  'pool',
  'popular',
  'portion',
  'position',
  'possible',
  'post',
  'potato',
  'pottery',
  'poverty',
  'powder',
  'power',
  'practice',
  'praise',
  'predict',
  'prefer',
  'prepare',
  'present',
  'pretty',
  'prevent',
  'price',
  'pride',
  'primary',
  'print',
  'priority',
  'prison',
  'private',
  'prize',
  'problem',
  'process',
  'produce',
  'profit',
  'program',
  'project',
  'promote',
  'proof',
  'property',
  'prosper',
  'protect',
  'proud',
  'provide',
  'public',
  'pudding',
  'pull',
  'pulp',
  'pulse',
  'pumpkin',
  'punch',
  'pupil',
  'puppy',
  'purchase',
  'purity',
  'purpose',
  'purse',
  'push',
  'put',
  'puzzle',
  'pyramid',
  'quality',
  'quantum',
  'quarter',
  'question',
  'quick',
  'quit',
  'quiz',
  'quote',
  'rabbit',
  'raccoon',
  'race',
  'rack',
  'radar',
  'radio',
  'rail',
  'rain',
  'raise',
  'rally',
  'ramp',
  'ranch',
  'random',
  'range',
  'rapid',
  'rare',
  'rate',
  'rather',
  'raven',
  'raw',
  'razor',
  'ready',
  'real',
  'reason',
  'rebel',
  'rebuild',
  'recall',
  'receive',
  'recipe',
  'record',
  'recycle',
  'reduce',
  'reflect',
  'reform',
  'refuse',
  'region',
  'regret',
  'regular',
  'reject',
  'relax',
  'release',
  'relief',
  'rely',
  'remain',
  'remember',
  'remind',
  'remove',
  'render',
  'renew',
  'rent',
  'reopen',
  'repair',
  'repeat',
  'replace',
  'report',
  'require',
  'rescue',
  'resemble',
  'resist',
  'resource',
  'response',
  'result',
  'retire',
  'retreat',
  'return',
  'reunion',
  'reveal',
  'review',
  'reward',
  'rhythm',
  'rib',
  'ribbon',
  'rice',
  'rich',
  'ride',
  'ridge',
  'rifle',
  'right',
  'rigid',
  'ring',
  'riot',
  'ripple',
  'risk',
  'ritual',
  'rival',
  'river',
  'road',
  'roast',
  'robot',
  'robust',
  'rocket',
  'romance',
  'roof',
  'rookie',
  'room',
  'rose',
  'rotate',
  'rough',
  'round',
  'route',
  'royal',
  'rubber',
  'rude',
  'rug',
  'rule',
  'run',
  'runway',
  'rural',
  'sad',
  'saddle',
  'sadness',
  'safe',
  'sail',
  'salad',
  'salmon',
  'salon',
  'salt',
  'salute',
  'same',
  'sample',
  'sand',
  'satisfy',
  'satoshi',
  'sauce',
  'sausage',
  'save',
  'say',
  'scale',
  'scan',
  'scare',
  'scatter',
  'scene',
  'scheme',
  'school',
  'science',
  'scissors',
  'scorpion',
  'scout',
  'scrap',
  'screen',
  'script',
  'scrub',
  'sea',
  'search',
  'season',
  'seat',
  'second',
  'secret',
  'section',
  'security',
  'seed',
  'seek',
  'segment',
  'select',
  'sell',
  'seminar',
  'senior',
  'sense',
  'sentence',
  'series',
  'service',
  'session',
  'settle',
  'setup',
  'seven',
  'shadow',
  'shaft',
  'shallow',
  'share',
  'shed',
  'shell',
  'sheriff',
  'shield',
  'shift',
  'shine',
  'ship',
  'shiver',
  'shock',
  'shoe',
  'shoot',
  'shop',
  'short',
  'shoulder',
  'shove',
  'shrimp',
  'shrug',
  'shuffle',
  'shy',
  'sibling',
  'sick',
  'side',
  'siege',
  'sight',
  'sign',
  'silent',
  'silk',
  'silly',
  'silver',
  'similar',
  'simple',
  'since',
  'sing',
  'siren',
  'sister',
  'situate',
  'six',
  'size',
  'skate',
  'sketch',
  'ski',
  'skill',
  'skin',
  'skirt',
  'skull',
  'slab',
  'slam',
  'sleep',
  'slender',
  'slice',
  'slide',
  'slight',
  'slim',
  'slogan',
  'slot',
  'slow',
  'slush',
  'small',
  'smart',
  'smile',
  'smoke',
  'smooth',
  'snack',
  'snake',
  'snap',
  'sniff',
  'snow',
  'soap',
  'soccer',
  'social',
  'sock',
  'soda',
  'soft',
  'solar',
  'soldier',
  'solid',
  'solution',
  'solve',
  'someone',
  'song',
  'soon',
  'sorry',
  'sort',
  'soul',
  'sound',
  'soup',
  'source',
  'south',
  'space',
  'spare',
  'spatial',
  'spawn',
  'speak',
  'special',
  'speed',
  'spell',
  'spend',
  'sphere',
  'spice',
  'spider',
  'spike',
  'spin',
  'spirit',
  'split',
  'spoil',
  'sponsor',
  'spoon',
  'sport',
  'spot',
  'spray',
  'spread',
  'spring',
  'spy',
  'square',
  'squeeze',
  'squirrel',
  'stable',
  'stadium',
  'staff',
  'stage',
  'stairs',
  'stamp',
  'stand',
  'start',
  'state',
  'stay',
  'steak',
  'steel',
  'stem',
  'step',
  'stereo',
  'stick',
  'still',
  'sting',
  'stock',
  'stomach',
  'stone',
  'stool',
  'story',
  'stove',
  'strategy',
  'street',
  'strike',
  'strong',
  'struggle',
  'student',
  'stuff',
  'stumble',
  'style',
  'subject',
  'submit',
  'subway',
  'success',
  'such',
  'sudden',
  'suffer',
  'sugar',
  'suggest',
  'suit',
  'summer',
  'sun',
  'sunny',
  'sunset',
  'super',
  'supply',
  'supreme',
  'sure',
  'surface',
  'surge',
  'surprise',
  'surround',
  'survey',
  'suspect',
  'sustain',
  'swallow',
  'swamp',
  'swap',
  'swarm',
  'swear',
  'sweet',
  'swift',
  'swim',
  'swing',
  'switch',
  'sword',
  'symbol',
  'symptom',
  'syrup',
  'system',
  'table',
  'tackle',
  'tag',
  'tail',
  'talent',
  'talk',
  'tank',
  'tape',
  'target',
  'task',
  'taste',
  'tattoo',
  'taxi',
  'teach',
  'team',
  'tell',
  'ten',
  'tenant',
  'tennis',
  'tent',
  'term',
  'test',
  'text',
  'thank',
  'that',
  'theme',
  'then',
  'theory',
  'there',
  'they',
  'thing',
  'this',
  'thought',
  'three',
  'thrive',
  'throw',
  'thumb',
  'thunder',
  'ticket',
  'tide',
  'tiger',
  'tilt',
  'timber',
  'time',
  'tiny',
  'tip',
  'tired',
  'tissue',
  'title',
  'toast',
  'tobacco',
  'today',
  'toddler',
  'toe',
  'together',
  'toilet',
  'token',
  'tomato',
  'tomorrow',
  'tone',
  'tongue',
  'tonight',
  'tool',
  'tooth',
  'top',
  'topic',
  'topple',
  'torch',
  'tornado',
  'tortoise',
  'toss',
  'total',
  'tourist',
  'toward',
  'tower',
  'town',
  'toy',
  'track',
  'trade',
  'traffic',
  'tragic',
  'train',
  'transfer',
  'trap',
  'trash',
  'travel',
  'tray',
  'treat',
  'tree',
  'trend',
  'trial',
  'tribe',
  'trick',
  'trigger',
  'trim',
  'trip',
  'trophy',
  'trouble',
  'truck',
  'true',
  'truly',
  'trumpet',
  'trust',
  'truth',
  'try',
  'tube',
  'tuition',
  'tumble',
  'tuna',
  'tunnel',
  'turkey',
  'turn',
  'turtle',
  'twelve',
  'twenty',
  'twice',
  'twin',
  'twist',
  'two',
  'type',
  'typical',
  'ugly',
  'umbrella',
  'unable',
  'unaware',
  'uncle',
  'uncover',
  'under',
  'undo',
  'unfair',
  'unfold',
  'unhappy',
  'uniform',
  'unique',
  'unit',
  'universe',
  'unknown',
  'unlock',
  'until',
  'unusual',
  'unveil',
  'update',
  'upgrade',
  'uphold',
  'upon',
  'upper',
  'upset',
  'urban',
  'urge',
  'usage',
  'use',
  'used',
  'useful',
  'useless',
  'usual',
  'utility',
  'vacant',
  'vacuum',
  'vague',
  'valid',
  'valley',
  'valve',
  'van',
  'vanish',
  'vapor',
  'various',
  'vast',
  'vault',
  'vehicle',
  'velvet',
  'vendor',
  'venture',
  'venue',
  'verb',
  'verify',
  'version',
  'very',
  'vessel',
  'veteran',
  'viable',
  'vibrant',
  'vicious',
  'victory',
  'video',
  'view',
  'village',
  'vintage',
  'violin',
  'virtual',
  'virus',
  'visa',
  'visit',
  'visual',
  'vital',
  'vivid',
  'vocal',
  'voice',
  'void',
  'volcano',
  'volume',
  'vote',
  'voyage',
  'wage',
  'wagon',
  'wait',
  'walk',
  'wall',
  'walnut',
  'want',
  'warfare',
  'warm',
  'warrior',
  'wash',
  'wasp',
  'waste',
  'water',
  'wave',
  'way',
  'wealth',
  'weapon',
  'wear',
  'weasel',
  'weather',
  'web',
  'wedding',
  'weekend',
  'weird',
  'welcome',
  'west',
  'wet',
  'whale',
  'what',
  'wheat',
  'wheel',
  'when',
  'where',
  'whip',
  'whisper',
  'wide',
  'width',
  'wife',
  'wild',
  'will',
  'win',
  'window',
  'wine',
  'wing',
  'wink',
  'winner',
  'winter',
  'wire',
  'wisdom',
  'wise',
  'wish',
  'witness',
  'wolf',
  'woman',
  'wonder',
  'wood',
  'wool',
  'word',
  'work',
  'world',
  'worry',
  'worth',
  'wrap',
  'wreck',
  'wrestle',
  'wrist',
  'write',
  'wrong',
  'yard',
  'year',
  'yellow',
  'you',
  'young',
  'youth',
  'zebra',
  'zero',
  'zone',
  'zoo',
];


================================================
FILE: client/web/addons/crypto/addon/workers/crypto/utils/bip39/wordlists/index.ts
================================================
export { wordlist as english } from './english';


================================================
FILE: client/web/addons/crypto/addon/workers/crypto/utils/mnemonic.ts
================================================
import { english } from './bip39/wordlists';
import { genericHash } from './nacl';

// https://crypto.stackexchange.com/a/50759/8245
// BIP 39 describes the implementation of a mnemonic code or mnemonic sentence
// -- a group of easy to remember words --
// for the generation of deterministic wallets.
//
// Bitcoin private key is not stored in this way, rather seed to prng
// which generated the private and public key pair is converted into
// mnemonic so that its easy for human to type or remember.
//
// A list of 2048 words, which is indexed from 0-2047(11 bit information) is used.
// 132 bit value (128 bit seed + 4 bit checksum) is divided into 12 chunks of 11 bits each,
// then each 11 bit is used to select a word from dictionary.
//
// for more details see BIP39
//
// NOTE: 2^11 = 2048
// NOTE: 2048 = how many words in a bip39 wordlist
// NOTE: list is range 0 - 2047
export async function mnemonicFromNaClBoxPrivateKey(privateKey: Uint8Array): Promise<string> {
  const uint11Array = toUint11Array(privateKey);
  const words = applyWords(uint11Array);

  const checksumWord = await computeChecksum(privateKey);

  return words.join(' ') + ' ' + checksumWord;
}

export async function naclBoxPrivateKeyFromMnemonic(mnemonic: string): Promise<Uint8Array> {
  const words = mnemonic.split(' ');
  const key = words.slice(0, 24);
  const checksum = words[words.length - 1];
  const nums = key.map((word) => english.indexOf(word));

  // verify with the checksum, to see if we need to chop off the last
  // byte or something
  const fullResult = toUint8Array(nums);
  const fullCheck = await computeChecksum(fullResult);
  // because 256bits doesn't divide by 11, we will sometimes
  // have a stray 0 at the end of the conversion
  const shortResult = fullResult.slice(0, fullResult.length - 1);
  const shortCheck = await computeChecksum(shortResult);

  // success!
  if (shortCheck === fullCheck) return shortResult;
  if (fullCheck === checksum) return fullResult;

  throw 'Checksum could not validate private key';
}

export async function computeChecksum(nums: Uint8Array): Promise<string> {
  cons
Download .txt
gitextract_de_b7zvl/

├── .codeclimate.yml
├── .editorconfig
├── .github/
│   ├── renovate.json5
│   └── workflows/
│       ├── web-addon-crypto.yml
│       ├── web-addon-encoding.yml
│       ├── web-addon-local-account.yml
│       ├── web-addon-networking.yml
│       ├── web-addon-test-helpers.yml
│       ├── web-addon-tracked-local-storage.yml
│       ├── web-addon-ui.yml
│       ├── web-app-deploy.yml
│       ├── web-app-quality.yml
│       ├── web-app-tests.yml
│       ├── web-pinochle-deploy.yml
│       ├── web-pinochle-quality.yml
│       ├── web-pinochle-tests.yml
│       └── web-smoke-tests.yml
├── .gitignore
├── .gitmodules
├── .sonarcloud.properties
├── .vscode/
│   └── launch.json
├── .whitesource
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── benchmarks/
│   ├── crypto/
│   │   ├── .babelrc.js
│   │   ├── .gitignore
│   │   ├── package.json
│   │   ├── run
│   │   ├── src/
│   │   │   ├── bench/
│   │   │   │   ├── base64.ts
│   │   │   │   ├── hex.ts
│   │   │   │   ├── key-generation.ts
│   │   │   │   ├── nonce-generation.ts
│   │   │   │   ├── round-trip-long.ts
│   │   │   │   ├── round-trip.ts
│   │   │   │   └── stringConvension.ts
│   │   │   ├── index.ts
│   │   │   ├── lib/
│   │   │   │   ├── js-nacl.ts
│   │   │   │   ├── libsodium.ts
│   │   │   │   ├── round-trip-implementations.ts
│   │   │   │   ├── tweet-nacl.ts
│   │   │   │   └── utils.ts
│   │   │   └── utils.ts
│   │   └── tsconfig.json
│   └── emoji-replace/
│       ├── .babelrc.js
│       ├── .gitignore
│       ├── package.json
│       ├── run
│       ├── src/
│       │   ├── bench/
│       │   │   ├── -utils.ts
│       │   │   ├── long.ts
│       │   │   ├── micro.ts
│       │   │   └── short.ts
│       │   └── index.ts
│       ├── tsconfig.json
│       └── types/
│           └── emojis.d.ts
├── client/
│   ├── android-wrapper/
│   │   ├── .gitignore
│   │   ├── CONTRIBUTING.md
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── app/
│   │   │   ├── build.gradle
│   │   │   └── src/
│   │   │       └── main/
│   │   │           ├── AndroidManifest.xml
│   │   │           └── res/
│   │   │               └── values/
│   │   │                   └── styles.xml
│   │   ├── build.gradle
│   │   ├── enable-debug.sh
│   │   ├── gradle/
│   │   │   └── wrapper/
│   │   │       ├── gradle-wrapper.jar
│   │   │       ├── gradle-wrapper.properties
│   │   │       └── gradle.properties
│   │   ├── gradle.properties
│   │   ├── gradlew
│   │   ├── gradlew.bat
│   │   └── settings.gradle
│   └── web/
│       ├── .eslintignore
│       ├── .eslintrc.js
│       ├── .gitignore
│       ├── .prettierignore
│       ├── .prettierrc.js
│       ├── .stylelintignore
│       ├── .template-lintrc.js
│       ├── .vim/
│       │   └── coc-settings.json
│       ├── .vscode/
│       │   └── settings.json
│       ├── addons/
│       │   ├── crypto/
│       │   │   ├── .editorconfig
│       │   │   ├── .ember-cli
│       │   │   ├── .eslintignore
│       │   │   ├── .eslintrc.js
│       │   │   ├── .gitignore
│       │   │   ├── .npmignore
│       │   │   ├── .template-lintrc.js
│       │   │   ├── .watchmanconfig
│       │   │   ├── CONTRIBUTING.md
│       │   │   ├── LICENSE.md
│       │   │   ├── README.md
│       │   │   ├── addon/
│       │   │   │   ├── -private/
│       │   │   │   │   └── types.ts
│       │   │   │   ├── connector.ts
│       │   │   │   ├── index.ts
│       │   │   │   ├── services/
│       │   │   │   │   └── workers.ts
│       │   │   │   ├── tsconfig.json
│       │   │   │   ├── types.ts
│       │   │   │   └── workers/
│       │   │   │       └── crypto/
│       │   │   │           ├── actions.ts
│       │   │   │           ├── index.ts
│       │   │   │           ├── messages.ts
│       │   │   │           └── utils/
│       │   │   │               ├── array.ts
│       │   │   │               ├── bip39/
│       │   │   │               │   └── wordlists/
│       │   │   │               │       ├── english.ts
│       │   │   │               │       └── index.ts
│       │   │   │               ├── mnemonic.ts
│       │   │   │               ├── nacl.ts
│       │   │   │               ├── socket.ts
│       │   │   │               └── string-encoding.ts
│       │   │   ├── addon-test-support/
│       │   │   │   ├── index.ts
│       │   │   │   ├── setup.ts
│       │   │   │   └── tsconfig.json
│       │   │   ├── app/
│       │   │   │   └── services/
│       │   │   │       └── workers.ts
│       │   │   ├── config/
│       │   │   │   ├── ember-try.js
│       │   │   │   └── environment.js
│       │   │   ├── ember-cli-build.js
│       │   │   ├── index.js
│       │   │   ├── lib/
│       │   │   │   └── worker-build.js
│       │   │   ├── package.json
│       │   │   ├── testem.js
│       │   │   ├── tests/
│       │   │   │   ├── dummy/
│       │   │   │   │   ├── app/
│       │   │   │   │   │   ├── app.ts
│       │   │   │   │   │   ├── components/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── config/
│       │   │   │   │   │   │   └── environment.d.ts
│       │   │   │   │   │   ├── controllers/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── helpers/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── index.html
│       │   │   │   │   │   ├── models/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── router.js
│       │   │   │   │   │   ├── routes/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── styles/
│       │   │   │   │   │   │   └── app.css
│       │   │   │   │   │   └── templates/
│       │   │   │   │   │       └── application.hbs
│       │   │   │   │   ├── config/
│       │   │   │   │   │   ├── ember-cli-update.json
│       │   │   │   │   │   ├── environment.js
│       │   │   │   │   │   ├── optional-features.json
│       │   │   │   │   │   └── targets.js
│       │   │   │   │   └── public/
│       │   │   │   │       └── robots.txt
│       │   │   │   ├── helpers/
│       │   │   │   │   └── .gitkeep
│       │   │   │   ├── index.html
│       │   │   │   ├── integration/
│       │   │   │   │   └── .gitkeep
│       │   │   │   ├── test-helper.ts
│       │   │   │   ├── tsconfig.json
│       │   │   │   ├── unit/
│       │   │   │   │   └── services/
│       │   │   │   │       └── workers-test.js
│       │   │   │   └── workers/
│       │   │   │       └── crypto/
│       │   │   │           ├── mnemonic-test.ts
│       │   │   │           ├── nacl-test.ts
│       │   │   │           └── string-encoding-test.ts
│       │   │   ├── tsconfig.compiler-options.json
│       │   │   ├── tsconfig.json
│       │   │   ├── types/
│       │   │   │   └── overrides.d.ts
│       │   │   └── vendor/
│       │   │       └── .gitkeep
│       │   ├── encoding/
│       │   │   ├── .editorconfig
│       │   │   ├── .ember-cli
│       │   │   ├── .eslintignore
│       │   │   ├── .eslintrc.js
│       │   │   ├── .gitignore
│       │   │   ├── .npmignore
│       │   │   ├── .template-lintrc.js
│       │   │   ├── .travis.yml
│       │   │   ├── .watchmanconfig
│       │   │   ├── CONTRIBUTING.md
│       │   │   ├── LICENSE.md
│       │   │   ├── README.md
│       │   │   ├── addon/
│       │   │   │   ├── string.ts
│       │   │   │   └── tsconfig.json
│       │   │   ├── config/
│       │   │   │   ├── ember-try.js
│       │   │   │   └── environment.js
│       │   │   ├── ember-cli-build.js
│       │   │   ├── index.js
│       │   │   ├── package.json
│       │   │   ├── testem.js
│       │   │   ├── tests/
│       │   │   │   ├── dummy/
│       │   │   │   │   ├── app/
│       │   │   │   │   │   ├── app.ts
│       │   │   │   │   │   ├── components/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── config/
│       │   │   │   │   │   │   └── environment.d.ts
│       │   │   │   │   │   ├── controllers/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── helpers/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── index.html
│       │   │   │   │   │   ├── models/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── router.js
│       │   │   │   │   │   ├── routes/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── styles/
│       │   │   │   │   │   │   └── app.css
│       │   │   │   │   │   └── templates/
│       │   │   │   │   │       └── application.hbs
│       │   │   │   │   ├── config/
│       │   │   │   │   │   ├── ember-cli-update.json
│       │   │   │   │   │   ├── environment.js
│       │   │   │   │   │   ├── optional-features.json
│       │   │   │   │   │   └── targets.js
│       │   │   │   │   └── public/
│       │   │   │   │       └── robots.txt
│       │   │   │   ├── helpers/
│       │   │   │   │   └── .gitkeep
│       │   │   │   ├── index.html
│       │   │   │   ├── integration/
│       │   │   │   │   └── .gitkeep
│       │   │   │   ├── test-helper.js
│       │   │   │   ├── tsconfig.json
│       │   │   │   └── unit/
│       │   │   │       ├── .gitkeep
│       │   │   │       └── string-test.ts
│       │   │   ├── tsconfig.compiler-options.json
│       │   │   ├── tsconfig.json
│       │   │   └── vendor/
│       │   │       └── .gitkeep
│       │   ├── local-account/
│       │   │   ├── .editorconfig
│       │   │   ├── .ember-cli
│       │   │   ├── .eslintignore
│       │   │   ├── .eslintrc.js
│       │   │   ├── .gitignore
│       │   │   ├── .npmignore
│       │   │   ├── .template-lintrc.js
│       │   │   ├── .travis.yml
│       │   │   ├── .watchmanconfig
│       │   │   ├── CONTRIBUTING.md
│       │   │   ├── LICENSE.md
│       │   │   ├── README.md
│       │   │   ├── addon/
│       │   │   │   ├── adapters/
│       │   │   │   │   └── application.js
│       │   │   │   ├── index.ts
│       │   │   │   ├── models/
│       │   │   │   │   ├── README.md
│       │   │   │   │   ├── channel-context-chain.ts
│       │   │   │   │   ├── channel.ts
│       │   │   │   │   ├── contact.ts
│       │   │   │   │   ├── identity.ts
│       │   │   │   │   ├── user.ts
│       │   │   │   │   ├── vote-chain.ts
│       │   │   │   │   └── vote.ts
│       │   │   │   ├── serializers/
│       │   │   │   │   └── application.js
│       │   │   │   ├── services/
│       │   │   │   │   ├── channel-manager.ts
│       │   │   │   │   ├── contact-manager.ts
│       │   │   │   │   └── current-user.ts
│       │   │   │   ├── tsconfig.json
│       │   │   │   ├── types.ts
│       │   │   │   └── utils.ts
│       │   │   ├── addon-test-support/
│       │   │   │   ├── -private/
│       │   │   │   │   ├── contact.ts
│       │   │   │   │   ├── current-user.ts
│       │   │   │   │   ├── storage.ts
│       │   │   │   │   ├── user.ts
│       │   │   │   │   └── utils.ts
│       │   │   │   ├── index.ts
│       │   │   │   └── tsconfig.json
│       │   │   ├── app/
│       │   │   │   ├── adapters/
│       │   │   │   │   └── application.js
│       │   │   │   ├── models/
│       │   │   │   │   ├── channel-context-chain.js
│       │   │   │   │   ├── channel.js
│       │   │   │   │   ├── contact.js
│       │   │   │   │   ├── identity.js
│       │   │   │   │   ├── user.js
│       │   │   │   │   ├── vote-chain.js
│       │   │   │   │   └── vote.js
│       │   │   │   ├── serializers/
│       │   │   │   │   └── application.js
│       │   │   │   └── services/
│       │   │   │       ├── channel-manager.js
│       │   │   │       ├── contact-manager.js
│       │   │   │       ├── current-user.js
│       │   │   │       └── store.js
│       │   │   ├── config/
│       │   │   │   ├── ember-try.js
│       │   │   │   └── environment.js
│       │   │   ├── ember-cli-build.js
│       │   │   ├── index.js
│       │   │   ├── package.json
│       │   │   ├── testem.js
│       │   │   ├── tests/
│       │   │   │   ├── dummy/
│       │   │   │   │   ├── app/
│       │   │   │   │   │   ├── app.ts
│       │   │   │   │   │   ├── components/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── config/
│       │   │   │   │   │   │   └── environment.d.ts
│       │   │   │   │   │   ├── controllers/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── helpers/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── index.html
│       │   │   │   │   │   ├── models/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── router.js
│       │   │   │   │   │   ├── routes/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── styles/
│       │   │   │   │   │   │   └── app.css
│       │   │   │   │   │   └── templates/
│       │   │   │   │   │       └── application.hbs
│       │   │   │   │   ├── config/
│       │   │   │   │   │   ├── ember-cli-update.json
│       │   │   │   │   │   ├── environment.js
│       │   │   │   │   │   ├── optional-features.json
│       │   │   │   │   │   └── targets.js
│       │   │   │   │   └── public/
│       │   │   │   │       └── robots.txt
│       │   │   │   ├── helpers/
│       │   │   │   │   └── .gitkeep
│       │   │   │   ├── index.html
│       │   │   │   ├── integration/
│       │   │   │   │   └── .gitkeep
│       │   │   │   ├── test-helper.ts
│       │   │   │   ├── tsconfig.json
│       │   │   │   └── unit/
│       │   │   │       ├── create-current-user-test.ts
│       │   │   │       ├── models/
│       │   │   │       │   ├── contact-test.ts
│       │   │   │       │   └── user-test.ts
│       │   │   │       └── services/
│       │   │   │           └── current-user-test.ts
│       │   │   ├── tsconfig.compiler-options.json
│       │   │   ├── tsconfig.json
│       │   │   ├── types/
│       │   │   │   └── overrides.d.ts
│       │   │   └── vendor/
│       │   │       └── .gitkeep
│       │   ├── networking/
│       │   │   ├── .editorconfig
│       │   │   ├── .ember-cli
│       │   │   ├── .eslintignore
│       │   │   ├── .eslintrc.js
│       │   │   ├── .gitignore
│       │   │   ├── .npmignore
│       │   │   ├── .template-lintrc.js
│       │   │   ├── .watchmanconfig
│       │   │   ├── CONTRIBUTING.md
│       │   │   ├── LICENSE.md
│       │   │   ├── README.md
│       │   │   ├── addon/
│       │   │   │   ├── errors.ts
│       │   │   │   ├── index.ts
│       │   │   │   ├── models/
│       │   │   │   │   ├── message/
│       │   │   │   │   │   └── utils.ts
│       │   │   │   │   ├── message.ts
│       │   │   │   │   └── relay.ts
│       │   │   │   ├── required-data.ts
│       │   │   │   ├── services/
│       │   │   │   │   ├── connection/
│       │   │   │   │   │   ├── ephemeral/
│       │   │   │   │   │   │   └── ephemeral-connection.ts
│       │   │   │   │   │   ├── manager.ts
│       │   │   │   │   │   └── status.ts
│       │   │   │   │   ├── connection.ts
│       │   │   │   │   ├── contacts/
│       │   │   │   │   │   └── online-checker.ts
│       │   │   │   │   ├── messages/
│       │   │   │   │   │   ├── -utils/
│       │   │   │   │   │   │   └── builder.ts
│       │   │   │   │   │   ├── auto-responder.ts
│       │   │   │   │   │   ├── dispatcher.ts
│       │   │   │   │   │   ├── factory.ts
│       │   │   │   │   │   ├── handler.ts
│       │   │   │   │   │   └── processor.ts
│       │   │   │   │   └── status-manager.ts
│       │   │   │   ├── tsconfig.json
│       │   │   │   ├── type-support.ts
│       │   │   │   ├── types.ts
│       │   │   │   └── utils/
│       │   │   │       └── connection/
│       │   │   │           ├── connection-pool.ts
│       │   │   │           └── connection.ts
│       │   │   ├── addon-test-support/
│       │   │   │   ├── index.ts
│       │   │   │   └── tsconfig.json
│       │   │   ├── app/
│       │   │   │   ├── models/
│       │   │   │   │   ├── message.js
│       │   │   │   │   └── relay.js
│       │   │   │   └── services/
│       │   │   │       ├── connection/
│       │   │   │       │   ├── manager.js
│       │   │   │       │   └── status.js
│       │   │   │       ├── connection.js
│       │   │   │       ├── contacts/
│       │   │   │       │   └── online-checker.js
│       │   │   │       ├── messages/
│       │   │   │       │   ├── auto-responder.js
│       │   │   │       │   ├── dispatcher.js
│       │   │   │       │   ├── factory.js
│       │   │   │       │   ├── handler.js
│       │   │   │       │   └── processor.js
│       │   │   │       └── status-manager.js
│       │   │   ├── config/
│       │   │   │   ├── ember-try.js
│       │   │   │   └── environment.js
│       │   │   ├── ember-cli-build.js
│       │   │   ├── index.js
│       │   │   ├── package.json
│       │   │   ├── testem.js
│       │   │   ├── tests/
│       │   │   │   ├── dummy/
│       │   │   │   │   ├── app/
│       │   │   │   │   │   ├── app.ts
│       │   │   │   │   │   ├── components/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── config/
│       │   │   │   │   │   │   └── environment.d.ts
│       │   │   │   │   │   ├── controllers/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── helpers/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── index.html
│       │   │   │   │   │   ├── models/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── router.ts
│       │   │   │   │   │   ├── routes/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── styles/
│       │   │   │   │   │   │   └── app.css
│       │   │   │   │   │   ├── templates/
│       │   │   │   │   │   │   └── application.hbs
│       │   │   │   │   │   └── with-test-waiter.js
│       │   │   │   │   ├── config/
│       │   │   │   │   │   ├── ember-cli-update.json
│       │   │   │   │   │   ├── environment.js
│       │   │   │   │   │   ├── optional-features.json
│       │   │   │   │   │   └── targets.js
│       │   │   │   │   └── public/
│       │   │   │   │       └── robots.txt
│       │   │   │   ├── helpers/
│       │   │   │   │   └── .gitkeep
│       │   │   │   ├── index.html
│       │   │   │   ├── integration/
│       │   │   │   │   └── .gitkeep
│       │   │   │   ├── test-helper.ts
│       │   │   │   ├── tsconfig.json
│       │   │   │   └── unit/
│       │   │   │       └── services/
│       │   │   │           ├── connection/
│       │   │   │           │   └── status-test.js
│       │   │   │           └── messages/
│       │   │   │               ├── auto-responder-test.ts
│       │   │   │               ├── handler-test.ts
│       │   │   │               └── utils/
│       │   │   │                   └── -encryption-test.ts
│       │   │   ├── tsconfig.compiler-options.json
│       │   │   ├── tsconfig.json
│       │   │   ├── types/
│       │   │   │   └── overrides.d.ts
│       │   │   └── vendor/
│       │   │       └── .gitkeep
│       │   ├── prism/
│       │   │   └── README.md
│       │   ├── test-helpers/
│       │   │   ├── .editorconfig
│       │   │   ├── .ember-cli
│       │   │   ├── .eslintignore
│       │   │   ├── .eslintrc.js
│       │   │   ├── .gitignore
│       │   │   ├── .npmignore
│       │   │   ├── .template-lintrc.js
│       │   │   ├── .travis.yml
│       │   │   ├── .watchmanconfig
│       │   │   ├── CONTRIBUTING.md
│       │   │   ├── LICENSE.md
│       │   │   ├── README.md
│       │   │   ├── addon-test-support/
│       │   │   │   ├── -private/
│       │   │   │   │   ├── get-service.ts
│       │   │   │   │   ├── get-store.ts
│       │   │   │   │   ├── refresh.ts
│       │   │   │   │   ├── setup-router.ts
│       │   │   │   │   ├── stub-service.ts
│       │   │   │   │   ├── visit.ts
│       │   │   │   │   └── wait-until.ts
│       │   │   │   ├── index.ts
│       │   │   │   └── tsconfig.json
│       │   │   ├── app/
│       │   │   │   └── .gitkeep
│       │   │   ├── config/
│       │   │   │   ├── ember-try.js
│       │   │   │   └── environment.js
│       │   │   ├── ember-cli-build.js
│       │   │   ├── index.js
│       │   │   ├── package.json
│       │   │   ├── testem.js
│       │   │   ├── tests/
│       │   │   │   ├── dummy/
│       │   │   │   │   ├── app/
│       │   │   │   │   │   ├── app.ts
│       │   │   │   │   │   ├── components/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── config/
│       │   │   │   │   │   │   └── environment.d.ts
│       │   │   │   │   │   ├── controllers/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── helpers/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── index.html
│       │   │   │   │   │   ├── models/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── router.js
│       │   │   │   │   │   ├── routes/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── styles/
│       │   │   │   │   │   │   └── app.css
│       │   │   │   │   │   └── templates/
│       │   │   │   │   │       └── application.hbs
│       │   │   │   │   ├── config/
│       │   │   │   │   │   ├── ember-cli-update.json
│       │   │   │   │   │   ├── environment.js
│       │   │   │   │   │   ├── optional-features.json
│       │   │   │   │   │   └── targets.js
│       │   │   │   │   └── public/
│       │   │   │   │       └── robots.txt
│       │   │   │   ├── helpers/
│       │   │   │   │   └── .gitkeep
│       │   │   │   ├── index.html
│       │   │   │   ├── integration/
│       │   │   │   │   └── .gitkeep
│       │   │   │   ├── test-helper.js
│       │   │   │   └── unit/
│       │   │   │       └── .gitkeep
│       │   │   ├── tsconfig.compiler-options.json
│       │   │   ├── tsconfig.json
│       │   │   ├── types/
│       │   │   │   └── overrides.d.ts
│       │   │   └── vendor/
│       │   │       └── .gitkeep
│       │   ├── tracked-local-storage/
│       │   │   ├── .editorconfig
│       │   │   ├── .ember-cli
│       │   │   ├── .eslintignore
│       │   │   ├── .eslintrc.js
│       │   │   ├── .gitignore
│       │   │   ├── .npmignore
│       │   │   ├── .template-lintrc.js
│       │   │   ├── .watchmanconfig
│       │   │   ├── CONTRIBUTING.md
│       │   │   ├── LICENSE.md
│       │   │   ├── README.md
│       │   │   ├── addon/
│       │   │   │   ├── index.ts
│       │   │   │   └── tsconfig.json
│       │   │   ├── config/
│       │   │   │   ├── ember-try.js
│       │   │   │   └── environment.js
│       │   │   ├── ember-cli-build.js
│       │   │   ├── index.js
│       │   │   ├── package.json
│       │   │   ├── testem.js
│       │   │   ├── tests/
│       │   │   │   ├── dummy/
│       │   │   │   │   ├── app/
│       │   │   │   │   │   ├── app.ts
│       │   │   │   │   │   ├── components/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── config/
│       │   │   │   │   │   │   └── environment.d.ts
│       │   │   │   │   │   ├── controllers/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── helpers/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── index.html
│       │   │   │   │   │   ├── models/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── router.js
│       │   │   │   │   │   ├── routes/
│       │   │   │   │   │   │   └── .gitkeep
│       │   │   │   │   │   ├── styles/
│       │   │   │   │   │   │   └── app.css
│       │   │   │   │   │   └── templates/
│       │   │   │   │   │       └── application.hbs
│       │   │   │   │   ├── config/
│       │   │   │   │   │   ├── ember-cli-update.json
│       │   │   │   │   │   ├── environment.js
│       │   │   │   │   │   ├── optional-features.json
│       │   │   │   │   │   └── targets.js
│       │   │   │   │   └── public/
│       │   │   │   │       └── robots.txt
│       │   │   │   ├── index.html
│       │   │   │   ├── test-helper.ts
│       │   │   │   ├── tsconfig.json
│       │   │   │   └── unit/
│       │   │   │       └── in-local-storage-test.ts
│       │   │   ├── tsconfig.compiler-options.json
│       │   │   ├── tsconfig.json
│       │   │   └── vendor/
│       │   │       └── .gitkeep
│       │   ├── tsconfig.json
│       │   └── ui/
│       │       ├── .editorconfig
│       │       ├── .ember-cli
│       │       ├── .eslintignore
│       │       ├── .eslintrc.js
│       │       ├── .gitignore
│       │       ├── .template-lintrc.js
│       │       ├── README.md
│       │       ├── addon/
│       │       │   ├── components/
│       │       │   │   ├── backdrop.hbs
│       │       │   │   ├── collapsible/
│       │       │   │   │   ├── icon.hbs
│       │       │   │   │   └── index.ts
│       │       │   │   ├── dropdown/
│       │       │   │   │   ├── index.hbs
│       │       │   │   │   └── index.ts
│       │       │   │   ├── ellipsis-loader.hbs
│       │       │   │   ├── external-link.hbs
│       │       │   │   ├── field.ts
│       │       │   │   ├── focus-card.hbs
│       │       │   │   ├── hamburger-button.hbs
│       │       │   │   ├── hover-tip.hbs
│       │       │   │   ├── media-info-card.ts
│       │       │   │   ├── modal.hbs
│       │       │   │   └── switch.ts
│       │       │   ├── helpers/
│       │       │   │   ├── and.ts
│       │       │   │   ├── eq.ts
│       │       │   │   ├── not.ts
│       │       │   │   └── prevent-default.ts
│       │       │   └── tsconfig.json
│       │       ├── addon-test-support/
│       │       │   ├── key-events.ts
│       │       │   ├── page-objects.ts
│       │       │   └── tsconfig.json
│       │       ├── app/
│       │       │   ├── components/
│       │       │   │   ├── backdrop.js
│       │       │   │   ├── collapsible/
│       │       │   │   │   └── icon.js
│       │       │   │   ├── collapsible.js
│       │       │   │   ├── dropdown.js
│       │       │   │   ├── ellipsis-loader.js
│       │       │   │   ├── external-link.js
│       │       │   │   ├── field.js
│       │       │   │   ├── focus-card.js
│       │       │   │   ├── hamburger-button.js
│       │       │   │   ├── hover-tip.js
│       │       │   │   ├── media-info-card.js
│       │       │   │   ├── modal.js
│       │       │   │   └── switch.js
│       │       │   ├── helpers/
│       │       │   │   ├── and.js
│       │       │   │   ├── eq.js
│       │       │   │   ├── not.js
│       │       │   │   └── prevent-default.js
│       │       │   └── styles/
│       │       │       └── @emberclear/
│       │       │           ├── animation.css
│       │       │           ├── buttons.css
│       │       │           ├── defaults.css
│       │       │           ├── layout.css
│       │       │           ├── mixins.css
│       │       │           ├── shoelace-overrides.css
│       │       │           ├── sizes.css
│       │       │           ├── spacing.css
│       │       │           ├── themes/
│       │       │           │   ├── default.css
│       │       │           │   └── midnight.css
│       │       │           └── ui.css
│       │       ├── config/
│       │       │   └── environment.js
│       │       ├── ember-cli-build.js
│       │       ├── index.js
│       │       ├── package.json
│       │       ├── testem.js
│       │       ├── tests/
│       │       │   ├── dummy/
│       │       │   │   ├── app/
│       │       │   │   │   ├── app.ts
│       │       │   │   │   ├── components/
│       │       │   │   │   │   └── .gitkeep
│       │       │   │   │   ├── config/
│       │       │   │   │   │   └── environment.d.ts
│       │       │   │   │   ├── controllers/
│       │       │   │   │   │   └── .gitkeep
│       │       │   │   │   ├── helpers/
│       │       │   │   │   │   └── .gitkeep
│       │       │   │   │   ├── index.html
│       │       │   │   │   ├── models/
│       │       │   │   │   │   └── .gitkeep
│       │       │   │   │   ├── router.js
│       │       │   │   │   ├── routes/
│       │       │   │   │   │   └── .gitkeep
│       │       │   │   │   ├── styles/
│       │       │   │   │   │   └── app.css
│       │       │   │   │   └── templates/
│       │       │   │   │       └── application.hbs
│       │       │   │   ├── config/
│       │       │   │   │   ├── environment.js
│       │       │   │   │   ├── optional-features.json
│       │       │   │   │   └── targets.js
│       │       │   │   └── public/
│       │       │   │       └── robots.txt
│       │       │   ├── helpers/
│       │       │   │   └── .gitkeep
│       │       │   ├── index.html
│       │       │   ├── integration/
│       │       │   │   ├── .gitkeep
│       │       │   │   ├── components/
│       │       │   │   │   ├── backdrop-test.js
│       │       │   │   │   ├── collapsible-test.js
│       │       │   │   │   ├── dropdown-test.js
│       │       │   │   │   ├── ellipsis-loader-test.js
│       │       │   │   │   ├── external-link-test.js
│       │       │   │   │   ├── field-test.js
│       │       │   │   │   ├── focus-card-test.ts
│       │       │   │   │   ├── hamburger-button-test.js
│       │       │   │   │   ├── hover-tip-test.js
│       │       │   │   │   ├── media-info-card-test.ts
│       │       │   │   │   ├── modal-test.ts
│       │       │   │   │   └── switch-test.ts
│       │       │   │   └── helpers/
│       │       │   │       ├── and-test.ts
│       │       │   │       ├── eq-test.ts
│       │       │   │       └── not-test.ts
│       │       │   ├── test-helper.ts
│       │       │   ├── tsconfig.json
│       │       │   └── unit/
│       │       │       └── .gitkeep
│       │       ├── tsconfig.compiler-options.json
│       │       ├── tsconfig.json
│       │       ├── types/
│       │       │   ├── dummy/
│       │       │   │   └── index.d.ts
│       │       │   ├── global.d.ts
│       │       │   └── overrides.d.ts
│       │       └── vendor/
│       │           └── .gitkeep
│       ├── config/
│       │   ├── .eslintrc.js
│       │   ├── .template-lintrc.js
│       │   ├── package.json
│       │   ├── testem.js
│       │   ├── tsconfig.compiler-options.json
│       │   └── utils/
│       │       ├── ember-build.js
│       │       └── log.js
│       ├── emberclear/
│       │   ├── .dockerignore
│       │   ├── .editorconfig
│       │   ├── .ember-cli
│       │   ├── .eslintignore
│       │   ├── .eslintrc.js
│       │   ├── .gitignore
│       │   ├── .template-lintrc.js
│       │   ├── Dockerfile
│       │   ├── Dockerfile.release
│       │   ├── README.md
│       │   ├── app/
│       │   │   ├── app.ts
│       │   │   ├── components/
│       │   │   │   ├── app/
│       │   │   │   │   ├── app-shell-remover.ts
│       │   │   │   │   ├── container/
│       │   │   │   │   │   ├── hero.hbs
│       │   │   │   │   │   ├── main.hbs
│       │   │   │   │   │   └── primary-hero.hbs
│       │   │   │   │   ├── modals.hbs
│       │   │   │   │   ├── off-canvas/
│       │   │   │   │   │   ├── -page.ts
│       │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   └── index.ts
│       │   │   │   │   ├── sidebar/
│       │   │   │   │   │   ├── actions/
│       │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   ├── index.ts
│       │   │   │   │   │   │   ├── response-action/
│       │   │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   │   └── response-panel/
│       │   │   │   │   │   │       ├── index.hbs
│       │   │   │   │   │   │       └── index.ts
│       │   │   │   │   │   ├── chats/
│       │   │   │   │   │   │   ├── -page.ts
│       │   │   │   │   │   │   ├── channel/
│       │   │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   │   ├── channel-form/
│       │   │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   │   ├── contact/
│       │   │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   │   ├── data/
│       │   │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   ├── index.ts
│       │   │   │   │   │   │   ├── list.hbs
│       │   │   │   │   │   │   └── offline-counter.hbs
│       │   │   │   │   │   ├── footer.hbs
│       │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   ├── index.ts
│       │   │   │   │   │   └── unread-indicator.hbs
│       │   │   │   │   ├── top-nav/
│       │   │   │   │   │   ├── connection-status/
│       │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   ├── current-chat-name/
│       │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   ├── index.ts
│       │   │   │   │   │   ├── install/
│       │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   ├── locale-select/
│       │   │   │   │   │   │   ├── -page.ts
│       │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   └── user-drop-menu/
│       │   │   │   │   │       ├── -page.ts
│       │   │   │   │   │       ├── index.hbs
│       │   │   │   │   │       └── index.ts
│       │   │   │   │   └── update-checker.ts
│       │   │   │   ├── app-footer.hbs
│       │   │   │   ├── copy-text-button.ts
│       │   │   │   ├── embedded-media.hbs
│       │   │   │   ├── error-card/
│       │   │   │   │   └── index.hbs
│       │   │   │   ├── fetch-open-graph.ts
│       │   │   │   ├── file-chooser/
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   └── index.ts
│       │   │   │   ├── keyboard-shortcuts/
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   └── key/
│       │   │   │   │       └── index.hbs
│       │   │   │   ├── mnemonic-display.ts
│       │   │   │   ├── modal-static/
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   └── index.ts
│       │   │   │   ├── pod/
│       │   │   │   │   ├── add-friend/
│       │   │   │   │   │   └── add-contact/
│       │   │   │   │   │       ├── index.hbs
│       │   │   │   │   │       └── index.ts
│       │   │   │   │   ├── chat/
│       │   │   │   │   │   ├── chat-entry/
│       │   │   │   │   │   │   ├── embeds-menu/
│       │   │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   │   └── snippet/
│       │   │   │   │   │   │   │       ├── -page.ts
│       │   │   │   │   │   │   │       ├── index.hbs
│       │   │   │   │   │   │   │       └── index.ts
│       │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   └── chat-history/
│       │   │   │   │   │       ├── connection-status/
│       │   │   │   │   │       │   ├── index.hbs
│       │   │   │   │   │       │   └── index.ts
│       │   │   │   │   │       ├── index.hbs
│       │   │   │   │   │       ├── message/
│       │   │   │   │   │       │   ├── delivery-confirmations/
│       │   │   │   │   │       │   │   ├── index.hbs
│       │   │   │   │   │       │   │   └── index.ts
│       │   │   │   │   │       │   ├── embedded-resource/
│       │   │   │   │   │       │   │   ├── index.hbs
│       │   │   │   │   │       │   │   └── metadata-preview/
│       │   │   │   │   │       │   │       ├── index.hbs
│       │   │   │   │   │       │   │       └── index.ts
│       │   │   │   │   │       │   ├── header/
│       │   │   │   │   │       │   │   ├── index.hbs
│       │   │   │   │   │       │   │   └── index.ts
│       │   │   │   │   │       │   ├── index.hbs
│       │   │   │   │   │       │   ├── index.ts
│       │   │   │   │   │       │   └── linked-media.hbs
│       │   │   │   │   │       ├── new-messages/
│       │   │   │   │   │       │   ├── index.hbs
│       │   │   │   │   │       │   └── index.ts
│       │   │   │   │   │       ├── notification-prompt/
│       │   │   │   │   │       │   ├── index.hbs
│       │   │   │   │   │       │   └── index.ts
│       │   │   │   │   │       └── unread-management/
│       │   │   │   │   │           ├── -page.ts
│       │   │   │   │   │           ├── index.hbs
│       │   │   │   │   │           └── index.ts
│       │   │   │   │   ├── contacts/
│       │   │   │   │   │   ├── contact-table/
│       │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   └── header/
│       │   │   │   │   │       ├── index.hbs
│       │   │   │   │   │       └── index.ts
│       │   │   │   │   ├── faq/
│       │   │   │   │   │   └── q-and-a.hbs
│       │   │   │   │   ├── index/
│       │   │   │   │   │   ├── begin-button.ts
│       │   │   │   │   │   └── compatibility/
│       │   │   │   │   │       ├── -utils/
│       │   │   │   │   │       │   └── detection.ts
│       │   │   │   │   │       ├── feature/
│       │   │   │   │   │       │   ├── boolean-icon.hbs
│       │   │   │   │   │       │   └── index.hbs
│       │   │   │   │   │       ├── index.hbs
│       │   │   │   │   │       └── index.ts
│       │   │   │   │   ├── login/
│       │   │   │   │   │   ├── -machine.ts
│       │   │   │   │   │   ├── login-form/
│       │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   ├── index.ts
│       │   │   │   │   │   │   └── transfer-prompt/
│       │   │   │   │   │   │       ├── index.hbs
│       │   │   │   │   │   │       └── index.ts
│       │   │   │   │   │   └── template.hbs
│       │   │   │   │   ├── q-r/
│       │   │   │   │   │   ├── -machine.ts
│       │   │   │   │   │   ├── -types.ts
│       │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   ├── index.ts
│       │   │   │   │   │   └── login/
│       │   │   │   │   │       └── ask.hbs
│       │   │   │   │   ├── settings/
│       │   │   │   │   │   ├── danger-zone/
│       │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   ├── interface/
│       │   │   │   │   │   │   ├── -page.ts
│       │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   ├── navigation.hbs
│       │   │   │   │   │   ├── profile/
│       │   │   │   │   │   │   ├── index.hbs
│       │   │   │   │   │   │   └── index.ts
│       │   │   │   │   │   └── relays/
│       │   │   │   │   │       ├── new-relay-form/
│       │   │   │   │   │       │   ├── index.hbs
│       │   │   │   │   │       │   └── index.ts
│       │   │   │   │   │       └── relay-table/
│       │   │   │   │   │           ├── index.hbs
│       │   │   │   │   │           └── row/
│       │   │   │   │   │               ├── index.hbs
│       │   │   │   │   │               └── index.ts
│       │   │   │   │   └── setup/
│       │   │   │   │       ├── -machine.ts
│       │   │   │   │       ├── completed/
│       │   │   │   │       │   ├── index.hbs
│       │   │   │   │       │   └── index.ts
│       │   │   │   │       ├── creating/
│       │   │   │   │       │   ├── index.hbs
│       │   │   │   │       │   └── index.ts
│       │   │   │   │       ├── index.hbs
│       │   │   │   │       ├── index.ts
│       │   │   │   │       └── overwrite.hbs
│       │   │   │   ├── q-r-code.hbs
│       │   │   │   ├── q-r-scanner/
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   └── index.ts
│       │   │   │   ├── search/
│       │   │   │   │   ├── -page.ts
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   ├── index.ts
│       │   │   │   │   └── result.hbs
│       │   │   │   └── status-icon/
│       │   │   │       ├── index.hbs
│       │   │   │       └── index.ts
│       │   │   ├── config/
│       │   │   │   └── environment.d.ts
│       │   │   ├── controllers/
│       │   │   │   ├── application.ts
│       │   │   │   ├── chat/
│       │   │   │   │   ├── in-channel.ts
│       │   │   │   │   └── privately-with.ts
│       │   │   │   ├── invite.ts
│       │   │   │   └── logout.ts
│       │   │   ├── formats.js
│       │   │   ├── helpers/
│       │   │   │   ├── first-8.ts
│       │   │   │   ├── handle-sidebar-click.ts
│       │   │   │   ├── has-feature-flag.ts
│       │   │   │   ├── includes.ts
│       │   │   │   ├── is-channel.js
│       │   │   │   ├── is-contact.js
│       │   │   │   ├── is-current-user.js
│       │   │   │   ├── is-present.ts
│       │   │   │   ├── or.ts
│       │   │   │   ├── queue.ts
│       │   │   │   └── sub.ts
│       │   │   ├── index.html
│       │   │   ├── models/
│       │   │   │   ├── action.ts
│       │   │   │   ├── invitation-result.ts
│       │   │   │   ├── invitation.ts
│       │   │   │   └── message-media.ts
│       │   │   ├── modifiers/
│       │   │   │   ├── format-code.ts
│       │   │   │   ├── has-unread.ts
│       │   │   │   ├── maybe-nudge-to-bottom.ts
│       │   │   │   ├── message-scroll-listener.ts
│       │   │   │   ├── qr-image.ts
│       │   │   │   ├── read-watcher.ts
│       │   │   │   ├── unread-message-list-observer.ts
│       │   │   │   ├── unread-messages-intersection-observer.ts
│       │   │   │   └── update-document-title.ts
│       │   │   ├── router.js
│       │   │   ├── routes/
│       │   │   │   ├── add-friend.ts
│       │   │   │   ├── application.ts
│       │   │   │   ├── chat/
│       │   │   │   │   ├── in-channel.ts
│       │   │   │   │   └── privately-with.ts
│       │   │   │   ├── chat.ts
│       │   │   │   ├── contacts.ts
│       │   │   │   ├── invite.ts
│       │   │   │   ├── login.ts
│       │   │   │   ├── logout.ts
│       │   │   │   ├── qr.js
│       │   │   │   ├── settings/
│       │   │   │   │   └── relays.ts
│       │   │   │   ├── settings.ts
│       │   │   │   └── setup.ts
│       │   │   ├── services/
│       │   │   │   ├── channels/
│       │   │   │   │   ├── -utils/
│       │   │   │   │   │   ├── channel-factory.ts
│       │   │   │   │   │   └── vote-sorter.ts
│       │   │   │   │   ├── channel-verifier.ts
│       │   │   │   │   └── vote-verifier.ts
│       │   │   │   ├── chat-scroller.ts
│       │   │   │   ├── connection/
│       │   │   │   │   └── ephemeral/
│       │   │   │   │       └── login/
│       │   │   │   │           ├── receive-data.ts
│       │   │   │   │           └── send-data.ts
│       │   │   │   ├── current-chat.ts
│       │   │   │   ├── locale.ts
│       │   │   │   ├── modals.ts
│       │   │   │   ├── notifications.ts
│       │   │   │   ├── prism-manager.ts
│       │   │   │   ├── qr-manager.ts
│       │   │   │   ├── redirect-manager.ts
│       │   │   │   ├── session.ts
│       │   │   │   ├── settings.ts
│       │   │   │   ├── sidebar.ts
│       │   │   │   ├── toast.ts
│       │   │   │   └── window.ts
│       │   │   ├── styles/
│       │   │   │   ├── app.css
│       │   │   │   ├── components/
│       │   │   │   │   ├── backdrop.css
│       │   │   │   │   ├── card.css
│       │   │   │   │   ├── chat-entry.css
│       │   │   │   │   ├── connection-status.css
│       │   │   │   │   ├── contacts.css
│       │   │   │   │   ├── dismissable-warning.css
│       │   │   │   │   ├── ellipses-loader.css
│       │   │   │   │   ├── embedded-resource.css
│       │   │   │   │   ├── hover-tip.css
│       │   │   │   │   ├── key.css
│       │   │   │   │   ├── logout.css
│       │   │   │   │   ├── message.css
│       │   │   │   │   ├── messages.css
│       │   │   │   │   ├── metadata-preview.css
│       │   │   │   │   ├── modal.css
│       │   │   │   │   ├── notification-prompt.css
│       │   │   │   │   ├── q-r-code.css
│       │   │   │   │   ├── q-r-scanner.css
│       │   │   │   │   ├── search.css
│       │   │   │   │   ├── settings-nav.css
│       │   │   │   │   ├── sidebar-contact.css
│       │   │   │   │   ├── sidebar-nav.css
│       │   │   │   │   ├── sidebar.css
│       │   │   │   │   ├── snippet.css
│       │   │   │   │   ├── toastify-overrides.css
│       │   │   │   │   ├── top-nav.css
│       │   │   │   │   └── unread-management.css
│       │   │   │   └── utility/
│       │   │   │       ├── height.css
│       │   │   │       └── transitions.css
│       │   │   ├── templates/
│       │   │   │   ├── add-friend.hbs
│       │   │   │   ├── application.hbs
│       │   │   │   ├── chat/
│       │   │   │   │   ├── in-channel.hbs
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   └── privately-with.hbs
│       │   │   │   ├── chat.hbs
│       │   │   │   ├── contacts.hbs
│       │   │   │   ├── faq.hbs
│       │   │   │   ├── index.hbs
│       │   │   │   ├── invite.hbs
│       │   │   │   ├── login.hbs
│       │   │   │   ├── logout.hbs
│       │   │   │   ├── not-found.hbs
│       │   │   │   ├── qr.hbs
│       │   │   │   ├── settings/
│       │   │   │   │   ├── danger-zone.hbs
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   ├── interface.hbs
│       │   │   │   │   └── relays.hbs
│       │   │   │   ├── settings.hbs
│       │   │   │   └── setup.hbs
│       │   │   ├── tsconfig.json
│       │   │   └── utils/
│       │   │       ├── README.md
│       │   │       ├── breakpoints.ts
│       │   │       ├── dom/
│       │   │       │   ├── css.ts
│       │   │       │   └── utils.ts
│       │   │       ├── ember-concurrency.ts
│       │   │       ├── errors.ts
│       │   │       ├── identity-comparison.ts
│       │   │       ├── normalized-meta.ts
│       │   │       ├── route-matchers.ts
│       │   │       ├── string/
│       │   │       │   └── utils.ts
│       │   │       └── uint8array-equality.ts
│       │   ├── config/
│       │   │   ├── addons.js
│       │   │   ├── build/
│       │   │   │   ├── addons.js
│       │   │   │   └── static.js
│       │   │   ├── coverage.js
│       │   │   ├── dependency-lint.js
│       │   │   ├── ember-intl.js
│       │   │   ├── emberclear-local.crt
│       │   │   ├── emberclear-local.csr
│       │   │   ├── emberclear-local.key
│       │   │   ├── environment.js
│       │   │   ├── icons.js
│       │   │   ├── manifest.js
│       │   │   ├── netlify/
│       │   │   │   └── _redirects
│       │   │   ├── optional-features.json
│       │   │   └── targets.js
│       │   ├── ember-cli-build.js
│       │   ├── jsconfig.json
│       │   ├── package.json
│       │   ├── public/
│       │   │   ├── .well-known/
│       │   │   │   └── assetlinks.json
│       │   │   ├── assets/
│       │   │   │   └── images/
│       │   │   │       ├── .gitkeep
│       │   │   │       └── icons/
│       │   │   │           └── .gitkeep
│       │   │   ├── bundle.html
│       │   │   └── robots.txt
│       │   ├── scripts/
│       │   │   ├── analyze-broccoli.js
│       │   │   ├── analyze.sh
│       │   │   ├── docker/
│       │   │   │   ├── nginx.conf
│       │   │   │   └── run-nginx.sh
│       │   │   ├── generate-self-signed-cert.sh
│       │   │   ├── node_modules-to-ramdisk.sh
│       │   │   └── test-with-coverage.sh
│       │   ├── testem.js
│       │   ├── tests/
│       │   │   ├── -temp/
│       │   │   │   └── qunit-xstate-test.ts
│       │   │   ├── acceptance/
│       │   │   │   ├── chat/
│       │   │   │   │   ├── -unread-acceptance-test.ts
│       │   │   │   │   ├── acceptance-test.ts
│       │   │   │   │   ├── in-channel/
│       │   │   │   │   │   └── -acceptance-test.ts
│       │   │   │   │   └── privately-with/
│       │   │   │   │       ├── -acceptance-test.ts
│       │   │   │   │       └── format-code-test.ts
│       │   │   │   ├── compatibility-test.ts
│       │   │   │   ├── contacts/
│       │   │   │   │   └── acceptance-test.ts
│       │   │   │   ├── invite/
│       │   │   │   │   └── acceptance-test.ts
│       │   │   │   ├── login/
│       │   │   │   │   └── acceptance-test.ts
│       │   │   │   ├── logout/
│       │   │   │   │   └── acceptance-test.ts
│       │   │   │   ├── logout-test.ts
│       │   │   │   ├── navigation-scroll-to-top-test.ts
│       │   │   │   ├── notification-permission-prompt-test.ts
│       │   │   │   ├── notifications-test.ts
│       │   │   │   ├── qr/
│       │   │   │   │   └── login/
│       │   │   │   │       ├── receiver-test.ts
│       │   │   │   │       └── sender-test.ts
│       │   │   │   ├── search-test.ts
│       │   │   │   ├── settings/
│       │   │   │   │   ├── acceptance-test.ts
│       │   │   │   │   ├── danger-zone/
│       │   │   │   │   │   └── -acceptance-test.ts
│       │   │   │   │   ├── interface/
│       │   │   │   │   │   └── -acceptance-test.ts
│       │   │   │   │   └── relays/
│       │   │   │   │       └── -acceptance-test.ts
│       │   │   │   ├── setup/
│       │   │   │   │   └── acceptance-test.ts
│       │   │   │   ├── sidebar-test.ts
│       │   │   │   ├── sidebar-visibility-test.ts
│       │   │   │   └── update-banner-test.ts
│       │   │   ├── helpers/
│       │   │   │   ├── factories/
│       │   │   │   │   ├── channel-factory.ts
│       │   │   │   │   └── message-factory.ts
│       │   │   │   ├── index.ts
│       │   │   │   ├── page-objects.ts
│       │   │   │   ├── pages/
│       │   │   │   │   ├── app.ts
│       │   │   │   │   ├── chat.ts
│       │   │   │   │   ├── components/
│       │   │   │   │   │   └── chat.ts
│       │   │   │   │   ├── contacts.ts
│       │   │   │   │   ├── login.ts
│       │   │   │   │   ├── logout.ts
│       │   │   │   │   ├── qr.ts
│       │   │   │   │   ├── settings.ts
│       │   │   │   │   ├── setup.ts
│       │   │   │   │   └── toast.ts
│       │   │   │   ├── setup-relay-connection-mocks.ts
│       │   │   │   ├── setup-test.ts
│       │   │   │   └── track-async-data.ts
│       │   │   ├── index.html
│       │   │   ├── integration/
│       │   │   │   ├── components/
│       │   │   │   │   ├── embedded-media-test.js
│       │   │   │   │   ├── error-card-test.js
│       │   │   │   │   ├── fetch-open-graph-test.js
│       │   │   │   │   ├── pod/
│       │   │   │   │   │   ├── application/
│       │   │   │   │   │   │   └── top-nav/
│       │   │   │   │   │   │       └── locale-select-test.ts
│       │   │   │   │   │   └── chat/
│       │   │   │   │   │       ├── chat-entry/
│       │   │   │   │   │       │   ├── embeds-menu/
│       │   │   │   │   │       │   │   └── component-test.ts
│       │   │   │   │   │       │   └── emoji-test.ts
│       │   │   │   │   │       └── chat-history/
│       │   │   │   │   │           ├── message/
│       │   │   │   │   │           │   ├── embedded-resource-test.ts
│       │   │   │   │   │           │   └── metadata-preview-test.ts
│       │   │   │   │   │           └── new-messages-test.js
│       │   │   │   │   └── settings/
│       │   │   │   │       └── interface-test.ts
│       │   │   │   ├── pods/
│       │   │   │   │   └── components/
│       │   │   │   │       ├── collapsible/
│       │   │   │   │       │   └── component-test.ts
│       │   │   │   │       ├── copy-text-button/
│       │   │   │   │       │   └── component-test.ts
│       │   │   │   │       ├── keyboard-shortcuts/
│       │   │   │   │       │   └── component-test.ts
│       │   │   │   │       ├── modal-static/
│       │   │   │   │       │   └── component-test.ts
│       │   │   │   │       ├── q-r-scanner/
│       │   │   │   │       │   └── component-test.ts
│       │   │   │   │       └── status-icon/
│       │   │   │   │           └── component-test.ts
│       │   │   │   └── routing/
│       │   │   │       └── feature-flags-test.ts
│       │   │   ├── test-helper.ts
│       │   │   ├── tsconfig.json
│       │   │   └── unit/
│       │   │       ├── routes/
│       │   │       │   ├── add-friend/
│       │   │       │   │   └── route-test.ts
│       │   │       │   ├── chat/
│       │   │       │   │   └── route-unit-test.ts
│       │   │       │   └── qr-test.js
│       │   │       ├── service/
│       │   │       │   ├── channels/
│       │   │       │   │   ├── channel-verifier-test.ts
│       │   │       │   │   ├── utils/
│       │   │       │   │   │   └── -vote-sorter-test.ts
│       │   │       │   │   └── vote-verifier-test.ts
│       │   │       │   ├── contacts/
│       │   │       │   │   └── online-checker-test.ts
│       │   │       │   ├── notifications-test.ts
│       │   │       │   └── redirect-manager-test.ts
│       │   │       ├── services/
│       │   │       │   ├── session-test.js
│       │   │       │   └── store-test.js
│       │   │       └── utils/
│       │   │           ├── dom-test.ts
│       │   │           └── string-test.ts
│       │   ├── translations/
│       │   │   ├── de-DE.yaml
│       │   │   ├── en-AU.yaml
│       │   │   ├── en-us.yaml
│       │   │   ├── es-ES.yaml
│       │   │   ├── fr-FR.yaml
│       │   │   ├── ko-KR.yaml
│       │   │   ├── pt-PT.yaml
│       │   │   └── ru-RU.yaml
│       │   ├── tsconfig.compiler-options.json
│       │   ├── tsconfig.json
│       │   ├── types/
│       │   │   ├── dom-purify.d.ts
│       │   │   ├── ember-a11y-testing/
│       │   │   │   └── test-support/
│       │   │   │       └── audit-if.d.ts
│       │   │   ├── ember-cli-clipboard/
│       │   │   │   └── test-support/
│       │   │   │       └── index.d.ts
│       │   │   ├── ember-could-get-used-to-this.d.ts
│       │   │   ├── ember-intl/
│       │   │   │   └── services/
│       │   │   │       └── intl.d.ts
│       │   │   ├── ember-localforage-adapter/
│       │   │   │   ├── adapters/
│       │   │   │   │   └── localforage.d.ts
│       │   │   │   └── serializers/
│       │   │   │       └── localforage.d.ts
│       │   │   ├── ember-modifier.d.ts
│       │   │   ├── ember-service-worker-update-notify/
│       │   │   │   └── test-support/
│       │   │   │       └── updater.d.ts
│       │   │   ├── ember-usable.d.ts
│       │   │   ├── emberclear/
│       │   │   │   ├── addon-services.d.ts
│       │   │   │   ├── ember-data.d.ts
│       │   │   │   └── index.d.ts
│       │   │   ├── emojis.d.ts
│       │   │   ├── global.d.ts
│       │   │   ├── index.d.ts
│       │   │   ├── overrides.d.ts
│       │   │   ├── prismjs/
│       │   │   │   └── index.d.ts
│       │   │   ├── qr-scanner.d.ts
│       │   │   ├── qunit-xstate-test.d.ts
│       │   │   └── toastify-js.d.ts
│       │   └── vendor/
│       │       └── shims/
│       │           ├── libsodium-wrappers.js
│       │           ├── libsodium.js
│       │           ├── localforage.js
│       │           └── qrcode.js
│       ├── libraries/
│       │   ├── questionably-typed/
│       │   │   ├── .eslintignore
│       │   │   ├── .eslintrc.js
│       │   │   ├── .gitignore
│       │   │   ├── package.json
│       │   │   ├── tsconfig.json
│       │   │   └── types/
│       │   │       ├── globals.ts
│       │   │       ├── libraries/
│       │   │       │   ├── blakejs.ts
│       │   │       │   ├── ember.ts
│       │   │       │   └── promise-worker-bi.ts
│       │   │       ├── overrides.ts
│       │   │       ├── package-augmentations.ts
│       │   │       └── tsconfig.json
│       │   └── tsconfig.json
│       ├── package.json
│       ├── pinochle/
│       │   ├── .editorconfig
│       │   ├── .ember-cli
│       │   ├── .eslintignore
│       │   ├── .eslintrc.js
│       │   ├── .gitignore
│       │   ├── .template-lintrc.js
│       │   ├── .watchmanconfig
│       │   ├── README.md
│       │   ├── app/
│       │   │   ├── app.ts
│       │   │   ├── components/
│       │   │   │   ├── back-of-cards.hbs
│       │   │   │   ├── back-of-cards.ts
│       │   │   │   ├── hand/
│       │   │   │   │   ├── -animation/
│       │   │   │   │   │   ├── card-chart.ts
│       │   │   │   │   │   ├── card.ts
│       │   │   │   │   │   ├── hand-chart.ts
│       │   │   │   │   │   ├── hand.ts
│       │   │   │   │   │   └── key-frames.ts
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   └── index.ts
│       │   │   │   ├── host-game/
│       │   │   │   │   ├── -statechart.ts
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   └── index.ts
│       │   │   │   ├── join-game/
│       │   │   │   │   ├── -statechart.ts
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   └── index.ts
│       │   │   │   ├── lazy/
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   └── index.ts
│       │   │   │   ├── loader/
│       │   │   │   │   ├── ellipsis.hbs
│       │   │   │   │   └── indeterminate.hbs
│       │   │   │   ├── name-entry/
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   └── index.ts
│       │   │   │   ├── options.hbs
│       │   │   │   ├── options.ts
│       │   │   │   ├── play/
│       │   │   │   │   └── as-guest/
│       │   │   │   │       ├── -statechart.ts
│       │   │   │   │       ├── index.hbs
│       │   │   │   │       ├── index.ts
│       │   │   │   │       ├── overlay-info.hbs
│       │   │   │   │       └── players-offline.hbs
│       │   │   │   ├── player-list.hbs
│       │   │   │   ├── player-order/
│       │   │   │   │   ├── index.hbs
│       │   │   │   │   └── index.ts
│       │   │   │   ├── playing-card/
│       │   │   │   │   ├── corner-value.hbs
│       │   │   │   │   ├── face-value.hbs
│       │   │   │   │   └── index.hbs
│       │   │   │   ├── share-link.hbs
│       │   │   │   └── share-link.ts
│       │   │   ├── config/
│       │   │   │   └── environment.d.ts
│       │   │   ├── game/
│       │   │   │   ├── card.ts
│       │   │   │   ├── deck.ts
│       │   │   │   ├── meld.ts
│       │   │   │   ├── networking/
│       │   │   │   │   ├── -requirements.ts
│       │   │   │   │   ├── constants.ts
│       │   │   │   │   ├── guest/
│       │   │   │   │   │   ├── display-info.ts
│       │   │   │   │   │   ├── game-round.ts
│       │   │   │   │   │   └── utils.ts
│       │   │   │   │   ├── guest.ts
│       │   │   │   │   ├── host/
│       │   │   │   │   │   ├── game-round.ts
│       │   │   │   │   │   ├── game-state.ts
│       │   │   │   │   │   ├── types.ts
│       │   │   │   │   │   └── utils.ts
│       │   │   │   │   ├── host.ts
│       │   │   │   │   └── types.ts
│       │   │   │   ├── trick.ts
│       │   │   │   └── utils/
│       │   │   │       └── move-validation.ts
│       │   │   ├── helpers/
│       │   │   │   ├── and.ts
│       │   │   │   ├── contains.ts
│       │   │   │   ├── english-list.ts
│       │   │   │   ├── eq.ts
│       │   │   │   ├── is-number.ts
│       │   │   │   ├── not.ts
│       │   │   │   ├── or.ts
│       │   │   │   └── suit-to-symbol.ts
│       │   │   ├── index.html
│       │   │   ├── modifiers/
│       │   │   │   ├── fit-text.ts
│       │   │   │   ├── resize.ts
│       │   │   │   └── stack.ts
│       │   │   ├── router.ts
│       │   │   ├── routes/
│       │   │   │   ├── game.ts
│       │   │   │   └── join.ts
│       │   │   ├── services/
│       │   │   │   ├── game-manager.ts
│       │   │   │   ├── guest/
│       │   │   │   │   ├── dispatcher.ts
│       │   │   │   │   └── handler.ts
│       │   │   │   └── player-info.ts
│       │   │   ├── styles/
│       │   │   │   ├── -variables.css
│       │   │   │   ├── app.css
│       │   │   │   ├── game.css
│       │   │   │   ├── loading.css
│       │   │   │   ├── page/
│       │   │   │   │   └── ask-game-type.css
│       │   │   │   ├── playing-card.css
│       │   │   │   ├── resets.css
│       │   │   │   ├── synthwave.css
│       │   │   │   ├── transitions.css
│       │   │   │   ├── utils.css
│       │   │   │   └── z-indexes.css
│       │   │   ├── templates/
│       │   │   │   ├── application.hbs
│       │   │   │   ├── game-full.hbs
│       │   │   │   ├── game.hbs
│       │   │   │   ├── host.hbs
│       │   │   │   ├── index.hbs
│       │   │   │   ├── join.hbs
│       │   │   │   └── not-recognized.hbs
│       │   │   ├── tsconfig.json
│       │   │   └── utils/
│       │   │       ├── array.ts
│       │   │       ├── container.ts
│       │   │       ├── dom.ts
│       │   │       ├── trig.ts
│       │   │       └── use-machine.ts
│       │   ├── config/
│       │   │   ├── ember-cli-update.json
│       │   │   ├── environment.js
│       │   │   ├── netlify/
│       │   │   │   └── _redirects
│       │   │   ├── optional-features.json
│       │   │   └── targets.js
│       │   ├── ember-cli-build.js
│       │   ├── package.json
│       │   ├── public/
│       │   │   └── robots.txt
│       │   ├── testem.js
│       │   ├── tests/
│       │   │   ├── -pages/
│       │   │   │   └── join.ts
│       │   │   ├── acceptance/
│       │   │   │   ├── game-test.ts
│       │   │   │   └── join-test.ts
│       │   │   ├── helpers/
│       │   │   │   ├── .gitkeep
│       │   │   │   └── index.ts
│       │   │   ├── index.html
│       │   │   ├── integration/
│       │   │   │   ├── components/
│       │   │   │   │   ├── host-game-test.ts
│       │   │   │   │   ├── lazy-test.ts
│       │   │   │   │   ├── playing-card-test.ts
│       │   │   │   │   └── share-link-test.js
│       │   │   │   └── modifiers/
│       │   │   │       ├── fit-text-test.js
│       │   │   │       ├── resize-test.js
│       │   │   │       └── stack-test.js
│       │   │   ├── test-helper.ts
│       │   │   ├── tsconfig.json
│       │   │   ├── type-support.ts
│       │   │   └── unit/
│       │   │       ├── game/
│       │   │       │   ├── deck-test.ts
│       │   │       │   ├── meld-test.ts
│       │   │       │   ├── state-test.ts
│       │   │       │   ├── trick-test.ts
│       │   │       │   └── utils/
│       │   │       │       ├── availableMoves-test.ts
│       │   │       │       └── isValidMove-test.ts
│       │   │       └── helpers/
│       │   │           ├── contains-test.ts
│       │   │           ├── eq-test.ts
│       │   │           ├── is-number-test.ts
│       │   │           └── suit-to-symbol-test.ts
│       │   ├── translations/
│       │   │   └── en-us.yaml
│       │   ├── tsconfig.compiler-options.json
│       │   ├── tsconfig.json
│       │   ├── types/
│       │   │   ├── libraries.d.ts
│       │   │   └── overrides.d.ts
│       │   └── vendor/
│       │       └── .gitkeep
│       ├── scripts/
│       │   └── clean.sh
│       ├── smoke-tests/
│       │   ├── .eslintrc.js
│       │   ├── .faltestrc.js
│       │   ├── .prettierrc.js
│       │   ├── helpers/
│       │   │   └── start-server.js
│       │   ├── package.json
│       │   ├── page-objects/
│       │   │   ├── add-friend.js
│       │   │   ├── chat.js
│       │   │   └── login.js
│       │   └── tests/
│       │       └── smoke-test.js
│       ├── stylelint.config.js
│       └── tsconfig.json
├── crowdin.yml
├── images/
│   └── icon.xcf
└── scripts/
    ├── deploy
    ├── docker-compose.yml
    ├── dockerhub
    ├── install-chrome-apt
    └── publish
Download .txt
SYMBOL INDEX (1578 symbols across 355 files)

FILE: benchmarks/crypto/src/bench/base64.ts
  method before (line 13) | async before() {

FILE: benchmarks/crypto/src/bench/hex.ts
  method before (line 16) | async before() {

FILE: benchmarks/crypto/src/bench/key-generation.ts
  method before (line 8) | async before() {

FILE: benchmarks/crypto/src/bench/nonce-generation.ts
  method before (line 8) | async before() {

FILE: benchmarks/crypto/src/bench/round-trip-long.ts
  method before (line 36) | async before() {

FILE: benchmarks/crypto/src/bench/round-trip.ts
  method before (line 14) | async before() {

FILE: benchmarks/crypto/src/bench/stringConvension.ts
  method before (line 15) | async before() {

FILE: benchmarks/crypto/src/index.ts
  function runBenchmark (line 9) | async function runBenchmark() {

FILE: benchmarks/crypto/src/lib/js-nacl.ts
  function setInstance (line 8) | function setInstance(): Promise<Nacl> {
  function generateAsymmetricKeys (line 18) | function generateAsymmetricKeys() {
  function generateNonce (line 22) | function generateNonce(): Uint8Array {
  function encryptFor (line 26) | function encryptFor(
  function decryptFrom (line 38) | function decryptFrom(
  function splitNonceFromMessage (line 50) | function splitNonceFromMessage(
  function toHex (line 63) | function toHex(array: Uint8Array): string {
  function fromHex (line 67) | function fromHex(hex: string): Uint8Array {
  function fromString (line 79) | function fromString(str: string): Uint8Array {
  function toString (line 85) | function toString(uint8Array: Uint8Array): string {

FILE: benchmarks/crypto/src/lib/libsodium.ts
  function libsodium (line 5) | async function libsodium(): Promise<typeof libsodiumWrapper> {
  function genericHash (line 12) | async function genericHash(arr: Uint8Array): Promise<Uint8Array> {
  function derivePublicKey (line 18) | async function derivePublicKey(privateKey: Uint8Array): Promise<Uint8Arr...
  function randomBytes (line 24) | async function randomBytes(length: number): Promise<Uint8Array> {
  function generateNonce (line 30) | async function generateNonce(): Promise<Uint8Array> {
  function generateAsymmetricKeys (line 36) | async function generateAsymmetricKeys(): Promise<KeyPair> {
  function generateSymmetricKey (line 42) | async function generateSymmetricKey(): Promise<Uint8Array> {
  function encryptFor (line 48) | async function encryptFor(
  function decryptFrom (line 61) | async function decryptFrom(
  function splitNonceFromMessage (line 79) | async function splitNonceFromMessage(
  function toHex (line 91) | function toHex(array: Uint8Array): string {
  function fromHex (line 95) | function fromHex(hex: string): Uint8Array {
  function toBase64 (line 99) | async function toBase64(array: Uint8Array): Promise<string> {
  function fromBase64 (line 105) | async function fromBase64(base64: string): Promise<Uint8Array> {
  function fromString (line 111) | function fromString(str: string): Uint8Array {
  function toString (line 117) | function toString(uint8Array: Uint8Array): string {

FILE: benchmarks/crypto/src/lib/round-trip-implementations.ts
  function libsodium (line 5) | async function libsodium(msg: Uint8Array) {
  function tweetnacl (line 23) | async function tweetnacl(msg: Uint8Array) {
  function jsnacl (line 41) | async function jsnacl(msg: Uint8Array) {
  function ensureEquality (line 55) | function ensureEquality(

FILE: benchmarks/crypto/src/lib/tweet-nacl.ts
  function generateAsymmetricKeys (line 6) | function generateAsymmetricKeys() {
  function generateNonce (line 10) | function generateNonce(): Uint8Array {
  function encryptFor (line 14) | function encryptFor(
  function decryptFrom (line 27) | function decryptFrom(
  function splitNonceFromMessage (line 40) | function splitNonceFromMessage(
  function toBase64 (line 59) | async function toBase64(array: Uint8Array): Promise<string> {
  function fromBase64 (line 63) | async function fromBase64(base64: string): Promise<Uint8Array> {
  function fromString (line 67) | function fromString(str: string): Uint8Array {
  function toString (line 73) | function toString(uint8Array: Uint8Array): string {

FILE: benchmarks/crypto/src/utils.ts
  function wrapCatch (line 3) | async function wrapCatch(task) {
  function fromString (line 12) | function fromString(str: string): Uint8Array {
  function toString (line 17) | function toString(data: Uint8Array): string {
  function concat (line 21) | function concat(arr1: Uint8Array, arr2: Uint8Array): Uint8Array {

FILE: benchmarks/emoji-replace/src/bench/-utils.ts
  function assertEq (line 4) | function assertEq<T>(expected: T, actual: T, msg: string) {
  type Args (line 20) | interface Args {
  function generateEmojisBench (line 26) | function generateEmojisBench({

FILE: benchmarks/emoji-replace/src/index.ts
  function runBenchmark (line 5) | async function runBenchmark() {

FILE: client/web/addons/crypto/addon-test-support/index.ts
  function newCrypto (line 20) | async function newCrypto() {

FILE: client/web/addons/crypto/addon-test-support/setup.ts
  function setupWorkers (line 14) | function setupWorkers(hooks: NestedHooks) {

FILE: client/web/addons/crypto/addon/-private/types.ts
  type WorkerLike (line 3) | interface WorkerLike {
  type WorkerRegistry (line 8) | type WorkerRegistry = { [path: string]: WorkerLike };

FILE: client/web/addons/crypto/addon/connector.ts
  type Args (line 5) | type Args = {
  class CryptoConnector (line 29) | class CryptoConnector {
    method constructor (line 33) | constructor({ workerService, keys }: Args) {
    method login (line 40) | async login(mnemonic: string) {
    method mnemonicFromNaClBoxPrivateKey (line 49) | async mnemonicFromNaClBoxPrivateKey(key?: Uint8Array) {
    method generateKeys (line 58) | async generateKeys() {
    method generateSigningKeys (line 67) | async generateSigningKeys() {
    method derivePublicKey (line 76) | async derivePublicKey(privateKey: Uint8Array) {
    method derivePublicSigningKey (line 85) | async derivePublicSigningKey(privateSigningKey: Uint8Array) {
    method encryptForSocket (line 94) | async encryptForSocket(payload: Serializable, { publicKey }: KeyPublic) {
    method decryptFromSocket (line 103) | async decryptFromSocket<ExpectedReturn = unknown>(socketData: Encrypte...
    method sign (line 112) | async sign(message: Uint8Array, senderPrivateKey: Uint8Array) {
    method openSigned (line 121) | async openSigned(signedMessage: Uint8Array, senderPublicKey: Uint8Arra...
    method hash (line 130) | async hash(message: Uint8Array) {

FILE: client/web/addons/crypto/addon/services/workers.ts
  constant CRYPTO_PATH (line 8) | const CRYPTO_PATH = '/workers/crypto';
  constant NETWORKING_PATH (line 9) | const NETWORKING_PATH = '/workers/networking';
  class WorkersService (line 11) | class WorkersService extends Service {
    method getCryptoWorker (line 15) | getCryptoWorker() {
    method getNetworkingWorker (line 20) | getNetworkingWorker() {
    method getWorker (line 24) | protected getWorker(path: string): WorkerLike {
    method willDestroy (line 49) | willDestroy() {
  type Registry (line 58) | interface Registry {

FILE: client/web/addons/crypto/addon/types.ts
  type KeyPublic (line 1) | type KeyPublic = { publicKey: Uint8Array };
  type KeyPrivate (line 2) | type KeyPrivate = { privateKey: Uint8Array };
  type KeyPair (line 3) | type KeyPair = KeyPublic & KeyPrivate;
  type SigningKeyPublic (line 5) | type SigningKeyPublic = { publicSigningKey: Uint8Array };
  type SigningKeyPrivate (line 6) | type SigningKeyPrivate = { privateSigningKey: Uint8Array };
  type SigningKeyPair (line 7) | type SigningKeyPair = SigningKeyPublic & SigningKeyPrivate;
  type EncryptedMessage (line 9) | interface EncryptedMessage {
  type Serializable (line 16) | type Serializable =
  type EncryptableObject (line 26) | interface EncryptableObject {

FILE: client/web/addons/crypto/addon/workers/crypto/actions.ts
  function login (line 6) | async function login(mnemonic: string): Promise<KeyPair & SigningKeyPair> {

FILE: client/web/addons/crypto/addon/workers/crypto/messages.ts
  type API (line 33) | type API = {
  type CryptoMessage (line 47) | type CryptoMessage = {
  type Message (line 52) | type Message<Action, Args> = { action: Action; args: Args };
  function handleMessage (line 54) | function handleMessage<Action extends keyof API>(

FILE: client/web/addons/crypto/addon/workers/crypto/utils/array.ts
  function concat (line 1) | function concat(arr1: Uint8Array, arr2: Uint8Array): Uint8Array {

FILE: client/web/addons/crypto/addon/workers/crypto/utils/mnemonic.ts
  function mnemonicFromNaClBoxPrivateKey (line 22) | async function mnemonicFromNaClBoxPrivateKey(privateKey: Uint8Array): Pr...
  function naclBoxPrivateKeyFromMnemonic (line 31) | async function naclBoxPrivateKeyFromMnemonic(mnemonic: string): Promise<...
  function computeChecksum (line 53) | async function computeChecksum(nums: Uint8Array): Promise<string> {
  function applyWords (line 65) | function applyWords(nums: number[]): string[] {
  function toUint11Array (line 70) | function toUint11Array(input: Uint8Array): number[] {
  function toUint8Array (line 99) | function toUint8Array(input: number[]): Uint8Array {

FILE: client/web/addons/crypto/addon/workers/crypto/utils/nacl.ts
  function genericHash (line 6) | async function genericHash(arr: Uint8Array): Promise<Uint8Array> {
  function derivePublicKey (line 10) | async function derivePublicKey(privateKey: Uint8Array) {
  function derivePublicSigningKey (line 16) | async function derivePublicSigningKey(privateSigningKey: Uint8Array) {
  function randomBytes (line 22) | async function randomBytes(length: number) {
  function sign (line 26) | async function sign(message: Uint8Array, senderPrivateKey: Uint8Array): ...
  function openSigned (line 30) | async function openSigned(
  function hash (line 37) | async function hash(message: Uint8Array): Promise<Uint8Array> {
  function generateNonce (line 41) | async function generateNonce() {
  function generateAsymmetricKeys (line 45) | async function generateAsymmetricKeys() {
  function generateSymmetricKeys (line 54) | async function generateSymmetricKeys() {
  function generateSigningKeys (line 58) | async function generateSigningKeys() {
  function encryptFor (line 67) | async function encryptFor(
  function decryptFrom (line 79) | async function decryptFrom(
  function splitNonceFromMessage (line 90) | function splitNonceFromMessage(messageWithNonce: Uint8Array): [Uint8Arra...

FILE: client/web/addons/crypto/addon/workers/crypto/utils/socket.ts
  function encryptForSocket (line 11) | async function encryptForSocket(payload: Serializable, to: KeyPublic, fr...
  function decryptFromSocket (line 20) | async function decryptFromSocket(socketData: EncryptedMessage, privateKe...
  function decryptMessage (line 30) | async function decryptMessage(

FILE: client/web/addons/crypto/addon/workers/crypto/utils/string-encoding.ts
  function toHex (line 3) | function toHex(array: Uint8Array): string {
  function fromHex (line 9) | function fromHex(hex: string): Uint8Array {
  function toBase64 (line 19) | async function toBase64(array: Uint8Array): Promise<string> {
  function fromBase64 (line 23) | async function fromBase64(base64: string): Promise<Uint8Array> {
  function fromString (line 27) | function fromString(str: string): Uint8Array {
  function toString (line 33) | function toString(uint8Array: Uint8Array): string {
  function ensureUint8Array (line 37) | function ensureUint8Array(text: string | Uint8Array): Uint8Array {
  function base64ToHex (line 46) | function base64ToHex(base64: string): string | undefined {

FILE: client/web/addons/crypto/index.js
  method isDevelopingAddon (line 21) | isDevelopingAddon() {
  method treeForPublic (line 26) | treeForPublic() {

FILE: client/web/addons/crypto/lib/worker-build.js
  function detectWorkers (line 10) | function detectWorkers() {
  function configureWorkerTree (line 23) | function configureWorkerTree({ isProduction, buildDir }) {
  function buildWorkers (line 39) | function buildWorkers(env) {

FILE: client/web/addons/crypto/tests/dummy/app/app.ts
  class App (line 7) | class App extends Application {

FILE: client/web/addons/crypto/tests/dummy/app/router.js
  class Router (line 5) | class Router extends EmberRouter {

FILE: client/web/addons/encoding/addon/string.ts
  function toHex (line 3) | function toHex(array: Uint8Array): string {
  function fromHex (line 9) | function fromHex(hex: string): Uint8Array {
  type Serializable (line 19) | type Serializable =
  function convertObjectToQRCodeDataURL (line 29) | async function convertObjectToQRCodeDataURL<T extends Record<string, unk...
  function convertObjectToUint8Array (line 37) | function convertObjectToUint8Array<T>(object: T): Uint8Array {
  function convertUint8ArrayToObject (line 43) | function convertUint8ArrayToObject<T>(array: Uint8Array): T {
  function convertObjectToBase64String (line 49) | function convertObjectToBase64String(object: Serializable): string {
  function convertBase64StringToObject (line 56) | function convertBase64StringToObject(base64: string): Serializable {
  function objectToDataURL (line 63) | function objectToDataURL(obj: Serializable): string {
  function base64ToHex (line 70) | function base64ToHex(base64: string): string | undefined {

FILE: client/web/addons/encoding/index.js
  method isDevelopingAddon (line 13) | isDevelopingAddon() {

FILE: client/web/addons/encoding/tests/dummy/app/app.ts
  class App (line 7) | class App extends Application {

FILE: client/web/addons/encoding/tests/dummy/app/router.js
  class Router (line 5) | class Router extends EmberRouter {

FILE: client/web/addons/local-account/addon-test-support/-private/contact.ts
  function attributesForContact (line 10) | async function attributesForContact() {
  function buildContact (line 17) | async function buildContact(name: string, attributes = {}): Promise<Cont...
  function createContact (line 32) | async function createContact(name: string, attributes = {}): Promise<Con...

FILE: client/web/addons/local-account/addon-test-support/-private/current-user.ts
  function createCurrentUser (line 8) | async function createCurrentUser(): Promise<User> {
  function setupCurrentUser (line 31) | function setupCurrentUser(hooks: NestedHooks) {
  function getCurrentUser (line 37) | function getCurrentUser() {

FILE: client/web/addons/local-account/addon-test-support/-private/storage.ts
  function cleanEverything (line 6) | async function cleanEverything(owner: Ember.ApplicationInstance) {
  function clearLocalStorage (line 16) | function clearLocalStorage(hooks: NestedHooks) {

FILE: client/web/addons/local-account/addon-test-support/-private/user.ts
  function attributesForUser (line 12) | async function attributesForUser() {
  function buildUser (line 20) | async function buildUser(name: string, attributes = {}): Promise<User> {
  function createUser (line 34) | async function createUser(name: string, attributes = {}): Promise<User> {

FILE: client/web/addons/local-account/addon-test-support/-private/utils.ts
  type ModelRegistry (line 4) | interface ModelRegistry {
  function createRecord (line 18) | function createRecord<Key extends keyof ModelRegistry>(

FILE: client/web/addons/local-account/addon/adapters/application.js
  method attach (line 16) | attach(callback) {
  method clear (line 35) | clear() {
  method get (line 39) | get(namespace) {
  method set (line 49) | set(namespace, objects) {
  method replace (line 53) | replace(data) {
  method groupRecordsForFindMany (line 69) | groupRecordsForFindMany(store, snapshots) {
  method shouldBackgroundReloadRecord (line 73) | shouldBackgroundReloadRecord() {
  method shouldReloadAll (line 77) | shouldReloadAll() {
  method findRecord (line 90) | findRecord(store, type, id) {
  method findAll (line 102) | findAll(store, type) {
  method findMany (line 114) | findMany(store, type, ids) {
  method queryRecord (line 130) | queryRecord(store, type, query) {
  method query (line 155) | query(store, type, query) {
  method _query (line 164) | _query(records, query, singleMatch) {
  method deleteRecord (line 202) | deleteRecord(store, type, snapshot) {
  method generateIdForRecord (line 214) | generateIdForRecord() {
  method _setNamespaceData (line 220) | _setNamespaceData(type, namespaceData) {
  method _getNamespaceData (line 234) | _getNamespaceData(type) {
  method _loadData (line 260) | _loadData() {
  method _modelNamespace (line 266) | _modelNamespace(type) {
  method _adapterNamespace (line 270) | _adapterNamespace() {
  function updateOrCreate (line 275) | function updateOrCreate(store, type, snapshot) {
  method shouldBackgroundReloadRecord (line 297) | shouldBackgroundReloadRecord() {
  method shouldBackgroundReloadAll (line 301) | shouldBackgroundReloadAll() {

FILE: client/web/addons/local-account/addon/models/channel-context-chain.ts
  class ChannelContextChain (line 9) | class ChannelContextChain extends Model {
  type ModelRegistry (line 24) | interface ModelRegistry {

FILE: client/web/addons/local-account/addon/models/channel.ts
  class Channel (line 8) | class Channel extends Model {
  type ModelRegistry (line 25) | interface ModelRegistry {

FILE: client/web/addons/local-account/addon/models/contact.ts
  type StatusKeys (line 12) | type StatusKeys = keyof typeof Status;
  type STATUS (line 13) | type STATUS = typeof Status[StatusKeys];
  class Contact (line 15) | class Contact extends Identity {
  type ModelRegistry (line 22) | interface ModelRegistry {

FILE: client/web/addons/local-account/addon/models/identity.ts
  class Identity (line 13) | class Identity extends Model implements Partial<KeyPublic & SigningKeyPu...
    method publicKeyAsHex (line 22) | get publicKeyAsHex() {
    method publicSigningKeyAsHex (line 26) | get publicSigningKeyAsHex() {
    method uid (line 34) | get uid() {
    method displayName (line 38) | get displayName() {
  type ModelRegistry (line 63) | interface ModelRegistry {

FILE: client/web/addons/local-account/addon/models/user.ts
  class User (line 7) | class User extends Identity implements Partial<KeyPair>, Partial<Signing...
  type ModelRegistry (line 14) | interface ModelRegistry {

FILE: client/web/addons/local-account/addon/models/vote-chain.ts
  type VOTE_ACTION (line 7) | enum VOTE_ACTION {
  class VoteChain (line 15) | class VoteChain extends Model {
  type ModelRegistry (line 36) | interface ModelRegistry {

FILE: client/web/addons/local-account/addon/models/vote.ts
  class Vote (line 8) | class Vote extends Model {
  type ModelRegistry (line 17) | interface ModelRegistry {

FILE: client/web/addons/local-account/addon/serializers/application.js
  function enforceSingularTypesInDocument (line 13) | function enforceSingularTypesInDocument(document) {
  function singularizeResource (line 27) | function singularizeResource(resource) {
  function singularize (line 44) | function singularize(str) {
  class ApplicationSerializer (line 48) | class ApplicationSerializer {
    method create (line 49) | static create() {
    method normalizeResponse (line 53) | normalizeResponse(_store, _schema, jsonApiDocument) {
    method serialize (line 59) | serialize(snapshot /*, options */) {

FILE: client/web/addons/local-account/addon/services/channel-manager.ts
  class ChannelManager (line 8) | class ChannelManager extends Service {
    method findOrCreate (line 11) | async findOrCreate(id: string, name: string): Promise<Channel> {
    method findAndSetName (line 19) | async findAndSetName(id: string, name: string): Promise<Channel> {
    method create (line 29) | async create(id: string, name: string): Promise<Channel> {
    method allChannels (line 37) | async allChannels(): Promise<ArrayProxy<Channel>> {
    method find (line 43) | async find(uid: string) {

FILE: client/web/addons/local-account/addon/services/contact-manager.ts
  class ContactManager (line 12) | class ContactManager extends Service {
    method find (line 17) | find(uid: string) {
    method import (line 21) | async import(contacts: Partial<ImportableIdentity>[]) {
    method findOrCreate (line 35) | async findOrCreate(uid: string, name: string): Promise<Contact> {
    method allContacts (line 44) | async allContacts(): Promise<ArrayProxy<Contact>> {
    method create (line 50) | async create(uid: string, name: string): Promise<Contact> {
    method addContact (line 64) | async addContact(/* _info: any */) {
    method findAndSetName (line 74) | private async findAndSetName(uid: string, name: string): Promise<Conta...
  type Registry (line 87) | interface Registry {

FILE: client/web/addons/local-account/addon/services/current-user.ts
  class CurrentUserService (line 29) | class CurrentUserService extends Service {
    method record (line 37) | get record() {
    method crypto (line 43) | get crypto() {
    method id (line 52) | get id() {
    method name (line 58) | get name() {
    method publicKey (line 64) | get publicKey() {
    method privateKey (line 70) | get privateKey() {
    method publicSigningKey (line 76) | get publicSigningKey() {
    method privateSigningKey (line 82) | get privateSigningKey() {
    method isLoggedIn (line 88) | get isLoggedIn(): boolean {
    method uid (line 96) | get uid(): string {
    method shareUrl (line 102) | get shareUrl(): string {
    method create (line 108) | async create(name: string): Promise<void> {
    method setIdentity (line 124) | async setIdentity(name: string, keys: KeyPair & Partial<SigningKeyPair...
    method exists (line 138) | async exists(): Promise<boolean> {
    method load (line 146) | async load(): Promise<User | null> {
    method currentUser (line 173) | async currentUser(): Promise<User | null> {
    method migrate (line 180) | async migrate() {
    method hydrateCrypto (line 202) | hydrateCrypto(user?: KeyPair) {
    method importFromKey (line 217) | async importFromKey(name: string, privateKey: Uint8Array, privateSigni...
  type Registry (line 241) | interface Registry {

FILE: client/web/addons/local-account/addon/types.ts
  type ImportableIdentity (line 1) | interface ImportableIdentity {

FILE: client/web/addons/local-account/addon/utils.ts
  function isContact (line 3) | function isContact(maybe: unknown): maybe is Contact {

FILE: client/web/addons/local-account/app/services/store.js
  class StoreService (line 5) | class StoreService extends Store {
    method createRecordDataFor (line 6) | createRecordDataFor(modelName, id, clientId, storeWrapper) {

FILE: client/web/addons/local-account/tests/dummy/app/app.ts
  class App (line 7) | class App extends Application {

FILE: client/web/addons/local-account/tests/dummy/app/router.js
  class Router (line 5) | class Router extends EmberRouter {

FILE: client/web/addons/networking/addon-test-support/index.ts
  type Callback (line 9) | type Callback = (...args: unknown[]) => void;
  function setupSocketServer (line 16) | function setupSocketServer(hooks: NestedHooks) {
  type Options (line 158) | type Options = {

FILE: client/web/addons/networking/addon/errors.ts
  class UnknownMessageError (line 1) | class UnknownMessageError extends Error {}
  class DataTransferFailed (line 2) | class DataTransferFailed extends Error {}
  class CurrentUserMustHaveAName (line 3) | class CurrentUserMustHaveAName extends Error {}

FILE: client/web/addons/networking/addon/models/message.ts
  constant MESSAGE_LIMIT (line 5) | const MESSAGE_LIMIT = 75;
  type TYPE (line 50) | enum TYPE {
  type TARGET (line 61) | enum TARGET {
  class Message (line 73) | class Message extends Model {
    method unread (line 138) | get unread() {
  type ModelRegistry (line 148) | interface ModelRegistry {

FILE: client/web/addons/networking/addon/models/message/utils.ts
  type RecordArray (line 5) | type RecordArray<T> = Array<T>;
  function selectUnreadDirectMessages (line 7) | function selectUnreadDirectMessages(
  function selectUnreadMessages (line 18) | function selectUnreadMessages(messages: Message[] | RecordArray<Message>...
  function markAsRead (line 35) | async function markAsRead(message: Message) {
  function messagesForDM (line 41) | function messagesForDM(
  function isMessageDMBetween (line 53) | function isMessageDMBetween(message: Message, me: string, chattingWithId...

FILE: client/web/addons/networking/addon/models/relay.ts
  class Relay (line 4) | class Relay extends Model {
  type ModelRegistry (line 16) | interface ModelRegistry {

FILE: client/web/addons/networking/addon/required-data.ts
  function ensureRelays (line 24) | async function ensureRelays(applicationInstance: ApplicationInstance) {

FILE: client/web/addons/networking/addon/services/connection.ts
  type ConnectionHooks (line 13) | type ConnectionHooks = {
  class ConnectionService (line 17) | class ConnectionService extends Service {
    method connect (line 25) | connect() {
    method disconnect (line 29) | disconnect() {
    method getOpenGraph (line 33) | async getOpenGraph(url: string) {
    method send (line 37) | async send(payload: OutgoingPayload) {
    method _connect (line 46) | private async _connect() {
    method canConnect (line 58) | private canConnect(): Promise<boolean> {
  type Registry (line 64) | interface Registry {

FILE: client/web/addons/networking/addon/services/connection/ephemeral/ephemeral-connection.ts
  type Target (line 26) | type Target = {
  type GetEndpoints (line 33) | type GetEndpoints = () => EndpointInfo[] | Promise<EndpointInfo[]>;
  type Options (line 35) | interface Options {
  class EphemeralConnection (line 41) | class EphemeralConnection {
    method build (line 80) | static async build<SubClass extends EphemeralConnection>(
    method constructor (line 107) | constructor(publicKeyAsHex?: string) {
    method setTarget (line 111) | setTarget(publicKeyAsHex?: string) {
    method setCrypto (line 120) | setCrypto(keys: KeyPair) {
    method disconnect (line 125) | disconnect() {
    method teardown (line 131) | teardown() {
    method onData (line 135) | onData(_data: EncryptedMessage) {
    method hydrateCrypto (line 141) | async hydrateCrypto(keys?: KeyPair) {
    method sendToHex (line 150) | sendToHex(message: EncryptableObject, hexPub: string) {
    method send (line 156) | async send(message: EncryptableObject, target?: Target) {
    method establishConnection (line 184) | async establishConnection() {
  function generateEphemeralKeys (line 200) | async function generateEphemeralKeys(workers: WorkersService, keys?: Key...
  function createConnection (line 214) | async function createConnection(

FILE: client/web/addons/networking/addon/services/connection/manager.ts
  class ConnectionManager (line 18) | class ConnectionManager extends Service {
    method getOpenGraph (line 26) | async getOpenGraph(url: string): Promise<OpenGraphData> {
    method acquire (line 53) | acquire() {
    method setup (line 61) | async setup() {
    method disconnect (line 87) | disconnect() {
    method willDestroy (line 93) | willDestroy() {
    method updateStatus (line 99) | private updateStatus(status: STATUS) {
    method createConnection (line 103) | private async createConnection(relay: Relay) {
  type Registry (line 124) | interface Registry {

FILE: client/web/addons/networking/addon/services/connection/status.ts
  constant STATUS_LEVEL_MAP (line 18) | const STATUS_LEVEL_MAP = {
  class ConnectionStatusService (line 26) | class ConnectionStatusService extends Service {
    method isConnected (line 33) | get isConnected() {
    method isConnecting (line 43) | get isConnecting() {
    method updateStatus (line 47) | updateStatus(text: STATUS) {
    method showStatusChange (line 56) | async showStatusChange() {
  type Registry (line 70) | interface Registry {

FILE: client/web/addons/networking/addon/services/contacts/online-checker.ts
  constant THIRTY_SECONDS (line 15) | const THIRTY_SECONDS = 30000;
  class ContactsOnlineChecker (line 17) | class ContactsOnlineChecker extends Service {
    method checkOnlineStatus (line 23) | async checkOnlineStatus() {
  type Registry (line 43) | interface Registry {

FILE: client/web/addons/networking/addon/services/messages/-utils/builder.ts
  type Sender (line 3) | interface Sender {
  function buildSender (line 8) | function buildSender(sender: Sender) {
  function buildMessage (line 16) | function buildMessage(msg: Message) {
  function build (line 25) | function build(msg: Message, sender: Sender) {

FILE: client/web/addons/networking/addon/services/messages/auto-responder.ts
  class MessageAutoResponder (line 16) | class MessageAutoResponder extends Service {
    method messageReceived (line 21) | async messageReceived(respondToMessage: Message) {
    method cameOnline (line 31) | async cameOnline(contact: Contact) {
  type Registry (line 47) | interface Registry {

FILE: client/web/addons/networking/addon/services/messages/dispatcher.ts
  class MessageDispatcher (line 18) | class MessageDispatcher extends Service {
    method send (line 25) | async send(text: string, to: Contact | Channel) {
    method sendTo (line 38) | sendTo(message: Message, to: Contact | Channel) {
    method pingAll (line 55) | async pingAll() {
    method sendToAll (line 67) | async sendToAll(msg: Message) {
    method sendToChannel (line 75) | sendToChannel(msg: Message, channel: Channel) {
    method sendToUser (line 86) | async sendToUser(msg: Message, to: Contact) {
  type Registry (line 130) | interface Registry {

FILE: client/web/addons/networking/addon/services/messages/factory.ts
  class MessageFactory (line 17) | class MessageFactory extends Service {
    method buildNewReceivedMessage (line 21) | buildNewReceivedMessage(json: P2PMessage, sender: Identity) {
    method buildChat (line 41) | buildChat(text: string, to: Identity | Channel) {
    method buildPing (line 91) | buildPing() {
    method buildDeliveryConfirmation (line 95) | buildDeliveryConfirmation(forMessage: Message): Message {
    method build (line 103) | private build(attributes = {}) {
  type Registry (line 115) | interface Registry {

FILE: client/web/addons/networking/addon/services/messages/handler.ts
  class ReceivedMessageHandler (line 16) | class ReceivedMessageHandler extends Service {
    method handle (line 24) | async handle(raw: P2PMessage) {
    method handleDeliveryConfirmation (line 62) | private async handleDeliveryConfirmation(message: Message, raw: P2PMes...
    method handleInfoChannelInfo (line 76) | private async handleInfoChannelInfo(message: Message, _raw: P2PMessage) {
    method handleDisconnect (line 80) | private async handleDisconnect(message: Message) {
    method handleChat (line 86) | private async handleChat(message: Message, raw: P2PMessage) {
    method handleWhisperChat (line 105) | private async handleWhisperChat(message: Message) {
    method handleChannelChat (line 116) | private async handleChannelChat(message: Message, _raw: P2PMessage) {
    method decomposeMessage (line 122) | private async decomposeMessage(json: P2PMessage) {
    method trimMessages (line 159) | private async trimMessages(lastReceived: Message): Promise<void> {
    method findOrCreateSender (line 180) | private async findOrCreateSender(senderData: { uid: string; name: stri...
  type Registry (line 192) | interface Registry {

FILE: client/web/addons/networking/addon/services/messages/processor.ts
  class MessageProcessor (line 13) | class MessageProcessor extends Service {
    method receive (line 28) | receive(socketData: EncryptedMessage) {
    method _receive (line 34) | async _receive(socketData: EncryptedMessage) {
  type Registry (line 46) | interface Registry {

FILE: client/web/addons/networking/addon/services/status-manager.ts
  class StatusManager (line 12) | class StatusManager extends Service {
    method markOffline (line 16) | async markOffline(uid: string) {
    method markOnline (line 26) | async markOnline(uid: string | Contact) {
  type Registry (line 40) | interface Registry {

FILE: client/web/addons/networking/addon/types.ts
  type EndpointInfo (line 1) | interface EndpointInfo {
  type P2PMessage (line 6) | interface P2PMessage {
  type RelayStateJson (line 26) | interface RelayStateJson {
  type RelayState (line 33) | interface RelayState {
  type OpenGraphData (line 40) | interface OpenGraphData {
  type RelayOpenGraphResponse (line 64) | interface RelayOpenGraphResponse {

FILE: client/web/addons/networking/addon/utils/connection/connection-pool.ts
  constant STATUS_CONNECTED (line 4) | const STATUS_CONNECTED = 'connected';
  constant STATUS_CONNECTING (line 6) | const STATUS_CONNECTING = 'connecting';
  constant STATUS_DEGRADED (line 8) | const STATUS_DEGRADED = 'degraded';
  constant STATUS_DISCONNECTED (line 10) | const STATUS_DISCONNECTED = 'disconnected';
  constant STATUS_UNKNOWN (line 13) | const STATUS_UNKNOWN = 'unknown';
  type STATUS (line 15) | type STATUS =
  type PoolConfig (line 22) | interface PoolConfig<Connectable> {
  function pool (line 62) | async function pool<Connectable>(
  class ConnectionPool (line 72) | class ConnectionPool<Connectable> {
    method constructor (line 77) | constructor(config: PoolConfig<Connectable>) {
    method activeConnections (line 81) | get activeConnections() {
    method status (line 85) | get status(): STATUS {
    method minConnections (line 99) | get minConnections() {
    method minimumMet (line 103) | get minimumMet() {
    method acquire (line 108) | async acquire(): Promise<Connectable> {
    method hydrate (line 118) | async hydrate(): Promise<void> {
    method drain (line 139) | drain() {
    method notifyOfStatusChange (line 143) | private notifyOfStatusChange(status?: STATUS) {
    method nextEndpoint (line 151) | private nextEndpoint(): EndpointInfo {

FILE: client/web/addons/networking/addon/utils/connection/connection.ts
  constant NAME (line 7) | const NAME = Symbol('__PHOENIX_SOCKET__');
  type Args (line 15) | interface Args {
  type OutgoingPayload (line 22) | interface OutgoingPayload {
  function phoenixSocket (line 27) | function phoenixSocket(): typeof Socket {
  class Connection (line 32) | class Connection {
    method constructor (line 50) | constructor({ relay, publicKey, onData, onInfo }: Args) {
    method connect (line 59) | async connect() {
    method setupSocket (line 66) | private async setupSocket() {
    method setupChannels (line 87) | private async setupChannels() {
    method setupStatsChannel (line 92) | private async setupStatsChannel() {
    method setupChatChannel (line 113) | private async setupChatChannel() {
    method send (line 146) | send(payload: OutgoingPayload) {
    method destroy (line 162) | destroy() {

FILE: client/web/addons/networking/index.js
  method isDevelopingAddon (line 13) | isDevelopingAddon() {

FILE: client/web/addons/networking/tests/dummy/app/app.ts
  class App (line 9) | class App extends Application {

FILE: client/web/addons/networking/tests/dummy/app/router.ts
  class Router (line 5) | class Router extends EmberRouter {

FILE: client/web/addons/networking/tests/unit/services/messages/auto-responder-test.ts
  method perform (line 47) | perform(/* _response: Message, _to: Identity */) {
  method perform (line 102) | perform(_response: Message, to: Identity) {
  method perform (line 152) | perform(response: Message, to: Identity) {

FILE: client/web/addons/networking/tests/unit/services/messages/handler-test.ts
  method messageReceived (line 29) | messageReceived() {}
  method cameOnline (line 30) | cameOnline() {}

FILE: client/web/addons/test-helpers/addon-test-support/-private/get-service.ts
  function getService (line 6) | function getService<K extends keyof Registry>(name: K): Registry[K] {

FILE: client/web/addons/test-helpers/addon-test-support/-private/get-store.ts
  function getStore (line 5) | function getStore(): StoreService {

FILE: client/web/addons/test-helpers/addon-test-support/-private/refresh.ts
  function refresh (line 5) | async function refresh<T = unknown>(mocking: () => T | Promise<T>) {

FILE: client/web/addons/test-helpers/addon-test-support/-private/setup-router.ts
  function setupRouter (line 5) | function setupRouter(hooks: NestedHooks) {

FILE: client/web/addons/test-helpers/addon-test-support/-private/visit.ts
  function visit (line 3) | async function visit(url: string) {

FILE: client/web/addons/test-helpers/addon-test-support/-private/wait-until.ts
  function waitUntil (line 4) | async function waitUntil(func: () => Promise<boolean>, timeoutMs = 500) {

FILE: client/web/addons/test-helpers/index.js
  method isDevelopingAddon (line 7) | isDevelopingAddon() {

FILE: client/web/addons/test-helpers/tests/dummy/app/app.ts
  class App (line 7) | class App extends Application {

FILE: client/web/addons/test-helpers/tests/dummy/app/router.js
  class Router (line 5) | class Router extends EmberRouter {

FILE: client/web/addons/tracked-local-storage/addon/index.ts
  type WhyCantTSGetDecoratorsRight (line 4) | interface WhyCantTSGetDecoratorsRight<InitializedValue> {
  function inLocalStorage (line 16) | function inLocalStorage<T = boolean, Klass extends Object = Object>(

FILE: client/web/addons/tracked-local-storage/index.js
  method isDevelopingAddon (line 7) | isDevelopingAddon() {

FILE: client/web/addons/tracked-local-storage/tests/dummy/app/app.ts
  class App (line 7) | class App extends Application {

FILE: client/web/addons/tracked-local-storage/tests/dummy/app/router.js
  class Router (line 5) | class Router extends EmberRouter {

FILE: client/web/addons/tracked-local-storage/tests/unit/in-local-storage-test.ts
  class Foo (line 15) | class Foo {
  class Foo (line 31) | class Foo {
  class Foo (line 47) | class Foo {
  function storedValueOf (line 101) | function storedValueOf(value: unknown) {

FILE: client/web/addons/ui/addon-test-support/key-events.ts
  function keyPressFor (line 5) | async function keyPressFor(
  function keyEvents (line 15) | function keyEvents(selector: string) {

FILE: client/web/addons/ui/addon/components/collapsible/index.ts
  class Collapsible (line 7) | class Collapsible extends Component {
    method toggle (line 11) | toggle() {

FILE: client/web/addons/ui/addon/components/dropdown/index.ts
  type Args (line 5) | interface Args {
  class Dropdown (line 11) | class Dropdown extends Component<Args> {
    method hasButtonText (line 14) | get hasButtonText() {
    method hasButtonIcon (line 18) | get hasButtonIcon() {
    method toggleMenu (line 23) | toggleMenu() {
    method closeMenu (line 28) | closeMenu() {

FILE: client/web/addons/ui/addon/components/field.ts
  class Field (line 7) | class Field extends Component {

FILE: client/web/addons/ui/addon/components/media-info-card.ts
  class MediaInfoCard (line 7) | class MediaInfoCard extends Component {
    method isOpen (line 10) | get isOpen() {
    method toggleShow (line 15) | toggleShow() {

FILE: client/web/addons/ui/addon/components/switch.ts
  class Field (line 7) | class Field extends Component {

FILE: client/web/addons/ui/addon/helpers/and.ts
  function and (line 3) | function and(params: unknown[] /*, hash*/) {

FILE: client/web/addons/ui/addon/helpers/eq.ts
  function eq (line 3) | function eq(params: unknown[] /*, hash*/) {

FILE: client/web/addons/ui/addon/helpers/not.ts
  function not (line 4) | function not(params: unknown[] /*, hash*/) {

FILE: client/web/addons/ui/addon/helpers/prevent-default.ts
  type PositionalArgs (line 3) | type PositionalArgs = [(...args: unknown[]) => void];
  function preventDefault (line 5) | function preventDefault([fn]: PositionalArgs /*, hash*/) {

FILE: client/web/addons/ui/index.js
  method isDevelopingAddon (line 31) | isDevelopingAddon() {

FILE: client/web/addons/ui/tests/dummy/app/app.ts
  class App (line 8) | class App extends Application {

FILE: client/web/addons/ui/tests/dummy/app/router.js
  class Router (line 5) | class Router extends EmberRouter {

FILE: client/web/config/testem.js
  constant CI_BROWSER (line 5) | const CI_BROWSER = process.env.CI_BROWSER || 'Chrome';

FILE: client/web/config/utils/ember-build.js
  function configureBabel (line 9) | function configureBabel(appConfig) {
  function applyEnvironmentVariables (line 27) | function applyEnvironmentVariables(appOptions) {

FILE: client/web/config/utils/log.js
  function logWithAttention (line 4) | function logWithAttention(...thingsToLog) {

FILE: client/web/emberclear/app/app.ts
  class App (line 9) | class App extends Application {

FILE: client/web/emberclear/app/components/app/app-shell-remover.ts
  method constructor (line 4) | constructor(owner: any, args: any) {
  method removeAppLoader (line 10) | private removeAppLoader() {

FILE: client/web/emberclear/app/components/app/off-canvas/index.ts
  type Args (line 12) | type Args = Record<string, unknown>;
  class OffCanvasContainer (line 14) | class OffCanvasContainer extends Component<Args> {
    method mode (line 18) | get mode() {
    method isTabletOrSmaller (line 37) | get isTabletOrSmaller() {
    method updateWidth (line 42) | updateWidth() {
    method constructor (line 46) | constructor(owner: unknown, args: Args) {
    method willDestroy (line 54) | willDestroy() {

FILE: client/web/emberclear/app/components/app/sidebar/actions/index.ts
  type IArgs (line 21) | interface IArgs {
  class ActionsSidebar (line 26) | class ActionsSidebar extends Component<IArgs> {
    method allActions (line 33) | get allActions(): Action[] {
    method newActions (line 41) | get newActions(): Action[] {
    method addAction (line 46) | async addAction() {
  function sortByOldest (line 51) | function sortByOldest(action1: Action, action2: Action) {

FILE: client/web/emberclear/app/components/app/sidebar/actions/response-action/index.ts
  type IArgs (line 5) | interface IArgs {
  class ResponseAction (line 9) | class ResponseAction extends Component<IArgs> {
    method header (line 10) | get header() {

FILE: client/web/emberclear/app/components/app/sidebar/actions/response-panel/index.ts
  type IArgs (line 6) | interface IArgs {
  class ResponsePanel (line 10) | class ResponsePanel extends Component<IArgs> {
    method yes (line 12) | yes() {
    method no (line 17) | no() {
    method dismiss (line 22) | dismiss() {

FILE: client/web/emberclear/app/components/app/sidebar/chats/channel-form/index.ts
  type Args (line 12) | type Args = {
  class ChannelForm (line 16) | class ChannelForm extends Component<Args> {
    method onFormSubmit (line 23) | onFormSubmit() {
    method onInput (line 28) | onInput({ target = {} as HTMLInputElement }) {
    method onKeyPress (line 33) | onKeyPress(this: ChannelForm, event: KeyboardEvent) {
    method didSubmitChannelName (line 48) | async didSubmitChannelName() {
    method createChannel (line 56) | private async createChannel() {

FILE: client/web/emberclear/app/components/app/sidebar/chats/channel/index.ts
  type Args (line 11) | type Args = {
  class SidebarChannel (line 15) | class SidebarChannel extends Component<Args> {
    method onClickChannel (line 20) | async onClickChannel(channel: Channel) {

FILE: client/web/emberclear/app/components/app/sidebar/chats/contact/index.ts
  type IArgs (line 15) | interface IArgs {
  class SidebarContact (line 21) | class SidebarContact extends Component<IArgs> {
    method isActive (line 27) | get isActive() {
    method hasUnread (line 31) | get hasUnread() {
    method onClick (line 36) | async onClick() {
    method togglePin (line 47) | togglePin() {
    method canBePinned (line 55) | get canBePinned() {

FILE: client/web/emberclear/app/components/app/sidebar/chats/data/index.ts
  type Args (line 15) | type Args = {
  class SidebarChatData (line 19) | class SidebarChatData extends Component<Args> {
    method allContacts (line 27) | get allContacts() {
    method allChannels (line 31) | get allChannels() {
    method channels (line 35) | get channels() {
    method contacts (line 46) | get contacts() {
    method chats (line 73) | get chats() {
    method displayedChats (line 77) | get displayedChats() {
    method displayedChannels (line 81) | get displayedChannels() {
    method idFromURL (line 85) | get idFromURL() {
    method hideOfflineContacts (line 91) | get hideOfflineContacts() {
    method offlineContacts (line 95) | get offlineContacts() {
    method numberOffline (line 103) | get numberOffline() {
    method showOfflineCounter (line 107) | get showOfflineCounter() {
  function sortByPinned (line 112) | function sortByPinned(contact1: Contact, contact2: Contact) {
  function searchByName (line 122) | function searchByName<T extends Contact | Channel>(text: string) {

FILE: client/web/emberclear/app/components/app/sidebar/chats/index.ts
  constant REQUIRED_CHARACTERS_TO_SEARCH (line 8) | const REQUIRED_CHARACTERS_TO_SEARCH = 2;
  class ContactsSidebar (line 10) | class ContactsSidebar extends Component {
    method handleSearch (line 19) | handleSearch(e: Event) {
    method hasEnoughToSearch (line 33) | get hasEnoughToSearch() {
    method remainingCharacters (line 37) | get remainingCharacters() {

FILE: client/web/emberclear/app/components/app/sidebar/index.ts
  type TabKeys (line 18) | type TabKeys = keyof typeof Tab;
  type TAB (line 19) | type TAB = typeof Tab[TabKeys];
  class Sidebar (line 21) | class Sidebar extends Component {
    method isShown (line 29) | get isShown() {
    method hasUnreadAbove (line 33) | get hasUnreadAbove() {
    method hasUnreadBelow (line 37) | get hasUnreadBelow() {
    method name (line 41) | get name() {
    method isLoggedIn (line 45) | get isLoggedIn() {
    method scrollDownToNearestUnread (line 50) | scrollDownToNearestUnread() {
    method scrollUpToNearestUnread (line 59) | scrollUpToNearestUnread() {
    method switchToTab (line 68) | switchToTab(tab: TAB) {
    method isTabContacts (line 72) | get isTabContacts(): boolean {
    method isTabChannels (line 76) | get isTabChannels(): boolean {
    method isTabActions (line 80) | get isTabActions(): boolean {

FILE: client/web/emberclear/app/components/app/top-nav/connection-status/index.ts
  class ConnectionStatus (line 8) | class ConnectionStatus extends Component {

FILE: client/web/emberclear/app/components/app/top-nav/current-chat-name/index.ts
  method isChatVisible (line 10) | get isChatVisible() {

FILE: client/web/emberclear/app/components/app/top-nav/index.ts
  class TopNav (line 11) | class TopNav extends Component {
    method isInverted (line 17) | get isInverted(): boolean {
    method allMessages (line 21) | get allMessages() {
    method hasUnread (line 25) | get hasUnread() {
    method unreadMessageCount (line 29) | get unreadMessageCount() {
    method unreadMessageText (line 37) | get unreadMessageText() {

FILE: client/web/emberclear/app/components/app/top-nav/install/index.ts
  class Install (line 7) | class Install extends Component {
    method install (line 11) | install() {

FILE: client/web/emberclear/app/components/app/top-nav/locale-select/-page.ts
  method optionFor (line 10) | optionFor(lang: string) {

FILE: client/web/emberclear/app/components/app/top-nav/locale-select/index.ts
  class LocaleSwitcher (line 8) | class LocaleSwitcher extends Component {
    method currentLanguage (line 24) | get currentLanguage() {
    method didInsert (line 35) | didInsert(element: HTMLDivElement) {
    method toggleMenu (line 40) | toggleMenu() {
    method closeMenu (line 45) | closeMenu() {
    method chooseLanguage (line 50) | chooseLanguage(locale: string) {

FILE: client/web/emberclear/app/components/app/top-nav/user-drop-menu/index.ts
  class UserDropMenu (line 6) | class UserDropMenu extends Component {

FILE: client/web/emberclear/app/components/app/update-checker.ts
  class UpdateChecker (line 8) | class UpdateChecker extends Component {

FILE: client/web/emberclear/app/components/copy-text-button.ts
  class CopyTextButton (line 11) | class CopyTextButton extends Component {
    method copySuccess (line 15) | async copySuccess() {

FILE: client/web/emberclear/app/components/fetch-open-graph.ts
  type Args (line 14) | type Args = {
  class FetchOpenGraphComponent (line 18) | class FetchOpenGraphComponent extends Component<Args> {
    method constructor (line 22) | constructor(owner: any, args: Args) {
    method meta (line 31) | get meta() {
    method request (line 41) | async request() {
  function waitUntil (line 70) | function waitUntil(callback: () => boolean): Promise<void> {

FILE: client/web/emberclear/app/components/file-chooser/index.ts
  type IArgs (line 4) | interface IArgs {
  class FileChooser (line 8) | class FileChooser extends Component<IArgs> {
    method bindInput (line 12) | bindInput(element: HTMLInputElement) {
    method openFileChooser (line 17) | openFileChooser() {
    method didChooseFile (line 22) | didChooseFile(e: Event) {

FILE: client/web/emberclear/app/components/mnemonic-display.ts
  type Args (line 10) | type Args = {
  class Mnemonic (line 14) | class Mnemonic extends Component<Args> {
    method updateMnemonic (line 22) | async updateMnemonic() {

FILE: client/web/emberclear/app/components/modal-static/index.ts
  type IArgs (line 7) | interface IArgs {
  class ModalStatic (line 12) | class ModalStatic extends Component<IArgs> {
    method constructor (line 15) | constructor(owner: any, args: any) {
    method modal (line 25) | get modal() {
    method isActive (line 29) | get isActive() {
    method toggle (line 34) | toggle() {
    method close (line 43) | close() {
    method open (line 48) | open() {

FILE: client/web/emberclear/app/components/pod/add-friend/add-contact/index.ts
  class AddModal (line 14) | class AddModal extends Component {
    method isLoggedIn (line 22) | get isLoggedIn() {
    method publicIdentity (line 26) | get publicIdentity() {
    method url (line 34) | get url() {
    method toggleScanning (line 39) | toggleScanning() {
    method handleScan (line 44) | async handleScan(identityJson: string) {
    method onScan (line 57) | onScan(json: string) {
    method tryCreate (line 62) | async tryCreate(identity: ImportableIdentity) {

FILE: client/web/emberclear/app/components/pod/chat/chat-entry/embeds-menu/snippet/-page.ts
  method selectLanguage (line 14) | selectLanguage(language: string) {

FILE: client/web/emberclear/app/components/pod/chat/chat-entry/embeds-menu/snippet/index.ts
  type Args (line 14) | interface Args {
  class SnippetModal (line 20) | class SnippetModal extends Component<Args> {
    method sendMessage (line 30) | sendMessage() {
    method chooseLanguage (line 50) | chooseLanguage({ target = {} as HTMLSelectElement }) {

FILE: client/web/emberclear/app/components/pod/chat/chat-entry/index.ts
  constant EMOJI_REGEX (line 15) | const EMOJI_REGEX = /:[^:]+:/g;
  type IArgs (line 17) | interface IArgs {
  class ChatEntry (line 21) | class ChatEntry extends Component<IArgs> {
    method placeholder (line 31) | get placeholder() {
    method sendMessage (line 43) | async sendMessage() {
    method updateText (line 55) | updateText(text: string) {
    method onInput (line 62) | onInput(event: KeyboardEvent) {
    method onKeyPress (line 75) | onKeyPress(event: KeyboardEvent) {
    method dispatchMessage (line 91) | async dispatchMessage(text: string) {

FILE: client/web/emberclear/app/components/pod/chat/chat-history/connection-status/index.ts
  class ConnectionStatus (line 6) | class ConnectionStatus extends Component {

FILE: client/web/emberclear/app/components/pod/chat/chat-history/message/delivery-confirmations/index.ts
  constant TIMEOUT_MS (line 16) | const TIMEOUT_MS = 1000;
  type IArgs (line 18) | interface IArgs {
  class DeliveryConfirmation (line 22) | class DeliveryConfirmation extends Component<IArgs> {
    method wasReceived (line 29) | get wasReceived() {
    method wasSent (line 33) | get wasSent() {
    method hasDeliveryConfirmations (line 37) | get hasDeliveryConfirmations() {
    method waitForConfirmation (line 52) | async waitForConfirmation() {
    method resend (line 63) | async resend() {
    method deleteMessage (line 87) | async deleteMessage() {
    method resendAutomatically (line 94) | async resendAutomatically() {
    method doDelete (line 104) | doDelete() {
    method doResend (line 110) | doResend() {
    method doQueue (line 116) | doQueue() {
    method doWait (line 122) | doWait() {

FILE: client/web/emberclear/app/components/pod/chat/chat-history/message/embedded-resource/metadata-preview/index.ts
  type Args (line 9) | type Args = {
  class MetadataPreview (line 13) | class MetadataPreview extends Component<Args> {
    method hasOgData (line 16) | get hasOgData() {
    method hasImage (line 20) | get hasImage() {
    method title (line 24) | get title() {
    method description (line 32) | get description() {

FILE: client/web/emberclear/app/components/pod/chat/chat-history/message/header/index.ts
  type IArgs (line 5) | interface IArgs {
  class MessageHeader (line 9) | class MessageHeader extends Component<IArgs> {
    method sender (line 10) | get sender() {
    method hasSender (line 14) | get hasSender() {
    method senderName (line 18) | get senderName() {

FILE: client/web/emberclear/app/components/pod/chat/chat-history/message/index.ts
  type IArgs (line 10) | interface IArgs {
  class MessageDisplay (line 14) | class MessageDisplay extends Component<IArgs> {
    method messageBody (line 17) | get messageBody() {
    method direction (line 23) | get direction() {
    method urls (line 31) | get urls() {

FILE: client/web/emberclear/app/components/pod/chat/chat-history/new-messages/index.ts
  class ChatNewMessages (line 9) | class ChatNewMessages extends Component {
    method scrollToBottom (line 13) | scrollToBottom() {

FILE: client/web/emberclear/app/components/pod/chat/chat-history/notification-prompt/index.ts
  class NotificationPrompt (line 7) | class NotificationPrompt extends Component {
    method isVisible (line 10) | get isVisible() {
    method enableNotifications (line 15) | enableNotifications() {
    method neverAskAgain (line 20) | neverAskAgain() {
    method askNextTime (line 25) | askNextTime() {

FILE: client/web/emberclear/app/components/pod/chat/chat-history/unread-management/index.ts
  type IArgs (line 15) | interface IArgs {
  class UnreadManagement (line 20) | class UnreadManagement extends Component<IArgs> {
    method findMessagesContainer (line 24) | findMessagesContainer() {
    method unreadMessages (line 30) | get unreadMessages() {
    method numberOfUnread (line 37) | get numberOfUnread() {
    method hasUnreadMessages (line 41) | get hasUnreadMessages() {
    method shouldRender (line 45) | get shouldRender() {
    method firstUnreadMessage (line 51) | get firstUnreadMessage(): Message | undefined {
    method dateOfFirstUnreadMessage (line 55) | get dateOfFirstUnreadMessage(): Date | undefined {
    method markAllAsRead (line 64) | markAllAsRead() {
    method scrollToFirstUnread (line 73) | scrollToFirstUnread() {
    method hasUnreadOffScreen (line 81) | private hasUnreadOffScreen() {

FILE: client/web/emberclear/app/components/pod/contacts/contact-table/index.ts
  class ContactsTable (line 8) | class ContactsTable extends Component {
    method contacts (line 11) | get contacts() {
    method remove (line 16) | async remove(contact: Contact) {

FILE: client/web/emberclear/app/components/pod/contacts/header/index.ts
  method contacts (line 9) | get contacts() {

FILE: client/web/emberclear/app/components/pod/index/begin-button.ts
  class BeginButton (line 8) | class BeginButton extends Component {

FILE: client/web/emberclear/app/components/pod/index/compatibility/-utils/detection.ts
  function hasCamera (line 21) | function hasCamera() {
  function hasNotifications (line 25) | function hasNotifications() {
  function hasServiceWorker (line 29) | function hasServiceWorker() {
  function hasWebWorker (line 33) | function hasWebWorker() {
  function hasIndexedDb (line 37) | function hasIndexedDb() {

FILE: client/web/emberclear/app/components/pod/index/compatibility/index.ts
  class Compatibility (line 16) | class Compatibility extends Component {
    method isNotCompatible (line 29) | get isNotCompatible() {
    method constructor (line 33) | constructor(owner: any, args: any) {
    method detectFeatures (line 40) | async detectFeatures() {
    method checkSuccess (line 54) | private checkSuccess(value: boolean, { required = false }: { required?...

FILE: client/web/emberclear/app/components/pod/login/-machine.ts
  type Context (line 5) | type Context = Record<string, unknown>;
  type Events (line 7) | type Events =
  type EmptySubState (line 18) | type EmptySubState = Record<string, unknown>;
  type Schema (line 20) | interface Schema {

FILE: client/web/emberclear/app/components/pod/login/login-form/index.ts
  class LoginForm (line 19) | class LoginForm extends Component {
    method contacts (line 31) | get contacts() {
    method isLoggedIn (line 35) | get isLoggedIn() {
    method login (line 40) | async login() {
    method uploadSettings (line 56) | async uploadSettings(data: string) {
    method updateTransferStatus (line 68) | updateTransferStatus(nextValue: boolean) {
    method onChooseFile (line 73) | onChooseFile(data: string) {
    method onSubmit (line 78) | onSubmit() {

FILE: client/web/emberclear/app/components/pod/login/login-form/transfer-prompt/index.ts
  type Args (line 10) | type Args = {
  class TransferPrompt (line 14) | class TransferPrompt extends Component<Args> {
    method constructor (line 15) | constructor(owner: unknown, args: Args) {
    method verification (line 24) | get verification() {
    method fromUser (line 28) | get fromUser() {
    method qrData (line 32) | get qrData() {
    method taskMessage (line 36) | get taskMessage() {
    method isLoading (line 43) | get isLoading() {
    method result (line 47) | get result() {
    method cancel (line 52) | cancel() {
    method setupEphemeralConnection (line 64) | async setupEphemeralConnection() {
  function randomFourLetters (line 80) | function randomFourLetters() {

FILE: client/web/emberclear/app/components/pod/q-r/-machine.ts
  function parseScannedData (line 8) | function parseScannedData(_: Context, event: ScanEvent) {

FILE: client/web/emberclear/app/components/pod/q-r/-types.ts
  type Context (line 3) | interface Context {
  type LoginQRData (line 9) | type LoginQRData = [
  type QRData (line 17) | type QRData = LoginQRData;
  type ErrorEvent (line 19) | type ErrorEvent = { type: 'error.execution'; data: string };
  type ScanEvent (line 20) | type ScanEvent = { type: 'SCAN'; data: string };
  type AllowEvent (line 21) | type AllowEvent = { type: 'ALLOW' };
  type RetryEvent (line 22) | type RetryEvent = { type: 'RETRY' };
  type DenyEvent (line 23) | type DenyEvent = { type: 'DENY' };
  type HandleExistenceEvent (line 24) | type HandleExistenceEvent = { type: 'HANDLE_EXISTENCE' };
  type ParsedEvent (line 26) | type ParsedEvent = { type: 'PARSED' };
  type EmptySubState (line 28) | type EmptySubState = Record<string, unknown>;
  type ScannerSubMachine (line 30) | interface ScannerSubMachine {
  type LoginSubMachine (line 42) | interface LoginSubMachine {
  type AddContactSubMachine (line 56) | interface AddContactSubMachine {
  type Schema (line 68) | interface Schema {
  type Events (line 85) | type Events =

FILE: client/web/emberclear/app/components/pod/q-r/index.ts
  class QRScan (line 17) | class QRScan extends Component {
    method state (line 42) | get state() {
    method ctx (line 46) | get ctx() {
    method handleScan (line 51) | handleScan(data: string) {
    method transition (line 56) | transition(transitionName: string) {
    method setupConnection (line 60) | async setupConnection() {
    method transferData (line 73) | async transferData() {
    method addContact (line 81) | addContact() {

FILE: client/web/emberclear/app/components/pod/settings/danger-zone/index.ts
  class DangerSettings (line 9) | class DangerSettings extends Component {
    method togglePrivateKey (line 19) | togglePrivateKey() {
    method deleteMessages (line 24) | async deleteMessages() {

FILE: client/web/emberclear/app/components/pod/settings/interface/index.ts
  class InterfaceSettings (line 9) | class InterfaceSettings extends Component {
    method useDarkTheme (line 13) | useDarkTheme(e: any) {
    method toggleHideOffline (line 22) | toggleHideOffline() {

FILE: client/web/emberclear/app/components/pod/settings/profile/index.ts
  class ProfileSettings (line 8) | class ProfileSettings extends Component {
    method name (line 13) | get name() {
    method save (line 18) | async save(e: Event) {
    method downloadSettings (line 27) | async downloadSettings() {

FILE: client/web/emberclear/app/components/pod/settings/relays/new-relay-form/index.ts
  class NewRelayForm (line 14) | class NewRelayForm extends Component {
    method submit (line 22) | submit() {
    method save (line 28) | async save() {
    method toggleForm (line 45) | toggleForm() {
    method reset (line 50) | private reset() {

FILE: client/web/emberclear/app/components/pod/settings/relays/relay-table/row/index.ts
  type Args (line 10) | interface Args {
  class RelayTableRow (line 14) | class RelayTableRow extends Component<Args> {
    method isActive (line 18) | get isActive() {
    method remove (line 31) | remove() {
    method makeDefault (line 40) | async makeDefault() {

FILE: client/web/emberclear/app/components/pod/setup/-machine.ts
  type Context (line 5) | interface Context {
  type EmptySubState (line 10) | type EmptySubState = Record<string, unknown>;
  type Schema (line 12) | interface Schema {
  type Event (line 28) | type Event = { type: 'NEXT' } | { type: 'PREV' } | EventObject;

FILE: client/web/emberclear/app/components/pod/setup/completed/index.ts
  class SetupCompleted (line 6) | class SetupCompleted extends Component {

FILE: client/web/emberclear/app/components/pod/setup/creating/index.ts
  type Args (line 12) | type Args = {
  class NameEntry (line 16) | class NameEntry extends Component<Args> {
    method nameIsBlank (line 21) | get nameIsBlank(): boolean {
    method createIdentity (line 26) | createIdentity(e: Event) {
    method create (line 34) | async create() {

FILE: client/web/emberclear/app/components/pod/setup/index.ts
  class SetupWizard (line 13) | class SetupWizard extends Component {

FILE: client/web/emberclear/app/components/q-r-scanner/index.ts
  type IArgs (line 8) | interface IArgs {
  class QRScanner (line 12) | class QRScanner extends Component<IArgs> {
    method isCameraActive (line 20) | get isCameraActive() {
    method toggleCamera (line 25) | async toggleCamera() {
    method handleData (line 30) | handleData(data: string) {
    method start (line 35) | async start() {
    method stop (line 50) | private stop() {
    method willDestroy (line 55) | willDestroy() {

FILE: client/web/emberclear/app/components/search/index.ts
  type IArgs (line 14) | interface IArgs {
  constant MAX_RESULTS (line 19) | const MAX_RESULTS = 5;
  class SearchModal (line 21) | class SearchModal extends Component<IArgs> {
    method numContacts (line 29) | get numContacts() {
    method hasResults (line 33) | get hasResults() {
    method submitSearch (line 38) | submitSearch() {
    method onInput (line 44) | onInput(e: Event) {
    method search (line 50) | async search(searchTerm: string) {

FILE: client/web/emberclear/app/components/status-icon/index.ts
  type IArgs (line 5) | interface IArgs {
  class StatusIcon (line 9) | class StatusIcon extends Component<IArgs> {
    method color (line 10) | get color() {

FILE: client/web/emberclear/app/controllers/application.ts
  class ApplicationController (line 3) | class ApplicationController extends Controller {

FILE: client/web/emberclear/app/controllers/chat/in-channel.ts
  method id (line 11) | get id() {
  method messages (line 15) | get messages() {

FILE: client/web/emberclear/app/controllers/chat/privately-with.ts
  method uid (line 14) | get uid() {
  method messages (line 18) | get messages() {

FILE: client/web/emberclear/app/controllers/invite.ts
  type IQueryParams (line 3) | interface IQueryParams {
  class InviteController (line 8) | class InviteController extends Controller {
  type Registry (line 13) | interface Registry {

FILE: client/web/emberclear/app/controllers/logout.ts
  class LogoutController (line 8) | class LogoutController extends Controller {
    method logout (line 13) | async logout() {

FILE: client/web/emberclear/app/helpers/first-8.ts
  function first8 (line 3) | function first8(params: any[] /*, hash*/) {

FILE: client/web/emberclear/app/helpers/handle-sidebar-click.ts
  type Args (line 8) | type Args = [() => void];
  class HandleSidebarClick (line 10) | class HandleSidebarClick extends Helper {
    method compute (line 13) | compute([handler]: Args) {

FILE: client/web/emberclear/app/helpers/has-feature-flag.ts
  method compute (line 9) | compute([flag]: string[]) {

FILE: client/web/emberclear/app/helpers/includes.ts
  type PositionalArgs (line 3) | type PositionalArgs<T> = [T[], T];
  function includes (line 5) | function includes<T>([collection, element]: PositionalArgs<T> /*, hash*/) {

FILE: client/web/emberclear/app/helpers/is-channel.js
  function isChannel (line 5) | function isChannel([record] /*, hash*/) {

FILE: client/web/emberclear/app/helpers/is-contact.js
  function isContact (line 5) | function isContact([record] /*, hash*/) {

FILE: client/web/emberclear/app/helpers/is-current-user.js
  function isContact (line 5) | function isContact([record] /*, hash*/) {

FILE: client/web/emberclear/app/helpers/is-present.ts
  function isPresent (line 4) | function isPresent(params: any[] /*, hash*/) {

FILE: client/web/emberclear/app/helpers/or.ts
  function or (line 3) | function or(params: any[] /*, hash*/) {

FILE: client/web/emberclear/app/helpers/queue.ts
  type Action (line 3) | type Action = (...args: any[]) => any;
  function queue (line 8) | function queue(actions: Action[] = []) {

FILE: client/web/emberclear/app/helpers/sub.ts
  function sub (line 3) | function sub(params: any[] /*, hash*/) {

FILE: client/web/emberclear/app/models/action.ts
  type ACTION_RESPONSE (line 5) | enum ACTION_RESPONSE {
  class Action (line 12) | class Action extends Model {
  type ModelRegistry (line 20) | interface ModelRegistry {

FILE: client/web/emberclear/app/models/invitation-result.ts
  class InvitationResult (line 5) | class InvitationResult extends Model {
  type ModelRegistry (line 15) | interface ModelRegistry {

FILE: client/web/emberclear/app/models/invitation.ts
  class Invitation (line 6) | class Invitation extends Model {
  type ModelRegistry (line 15) | interface ModelRegistry {

FILE: client/web/emberclear/app/models/message-media.ts
  class MessageMedia (line 5) | class MessageMedia extends Model {
  type ModelRegistry (line 14) | interface ModelRegistry {

FILE: client/web/emberclear/app/modifiers/format-code.ts
  type Args (line 10) | interface Args {
  class FormatCode (line 15) | class FormatCode extends Modifier<Args> {
    method didInstall (line 18) | didInstall() {
    method makeCodeBlocksFancy (line 29) | private makeCodeBlocksFancy() {
    method addLanguages (line 39) | private async addLanguages(text: string) {

FILE: client/web/emberclear/app/modifiers/has-unread.ts
  type Args (line 13) | interface Args {
  class HasUnread (line 18) | class HasUnread extends Modifier<Args> {
    method contact (line 21) | get contact() {
    method didReceiveArguments (line 25) | didReceiveArguments() {
    method findUnread (line 31) | async findUnread() {

FILE: client/web/emberclear/app/modifiers/maybe-nudge-to-bottom.ts
  type Args (line 9) | type Args = {
  class MaybeNudgeToBottom (line 14) | class MaybeNudgeToBottom extends Modifier<Args> {
    method messages (line 17) | get messages() {
    method appendedMessage (line 21) | get appendedMessage() {
    method lastMessage (line 25) | get lastMessage() {
    method didInstall (line 31) | didInstall() {

FILE: client/web/emberclear/app/modifiers/message-scroll-listener.ts
  type Args (line 8) | interface Args {
  class MessageScrollListener (line 13) | class MessageScrollListener extends Modifier<Args> {
    method messages (line 19) | get messages() {
    method didInstall (line 23) | didInstall() {
    method didReceiveArguments (line 39) | didReceiveArguments() {
    method willRemove (line 52) | willRemove() {
    method determineIfLastIsVisible (line 58) | private determineIfLastIsVisible() {

FILE: client/web/emberclear/app/modifiers/qr-image.ts
  type Args (line 7) | type Args = {
  class QRImageModifier (line 12) | class QRImageModifier extends Modifier<Args> {
    method didReceiveArguments (line 13) | didReceiveArguments() {
    method dataToQR (line 19) | async dataToQR() {
  function isImage (line 30) | function isImage(element?: Element | null): element is HTMLImageElement {

FILE: client/web/emberclear/app/modifiers/read-watcher.ts
  type Args (line 12) | interface Args {
  class ReadWatcher (line 17) | class ReadWatcher extends Modifier<Args> {
    method didInstall (line 21) | didInstall() {
    method didUpdateArguments (line 31) | didUpdateArguments() {
    method willRemove (line 36) | willRemove() {
    method disconnect (line 43) | private disconnect() {
    method markRead (line 55) | private markRead() {
    method maybeSetupReadWatcher (line 64) | private maybeSetupReadWatcher() {
    method setupIntersectionObserver (line 74) | private setupIntersectionObserver() {
    method markReadTask (line 97) | async markReadTask() {

FILE: client/web/emberclear/app/modifiers/unread-message-list-observer.ts
  class UnreadMessagesIntersectionObserver (line 16) | class UnreadMessagesIntersectionObserver extends Modifier {
    method didInstall (line 22) | didInstall() {
    method willRemove (line 28) | willRemove() {
    method respondToWindowFocus (line 32) | private respondToWindowFocus() {
    method markRead (line 52) | async markRead(message: Message) {

FILE: client/web/emberclear/app/modifiers/unread-messages-intersection-observer.ts
  class UnreadMessagesIntersectionObserver (line 7) | class UnreadMessagesIntersectionObserver extends Modifier {
    method didInstall (line 10) | didInstall() {
    method willRemove (line 18) | willRemove() {

FILE: client/web/emberclear/app/modifiers/update-document-title.ts
  class UpdateDocumentTitle (line 7) | class UpdateDocumentTitle extends Modifier {
    method constructor (line 14) | constructor(owner: any, args: any) {
    method tokens (line 20) | get tokens() {
    method willDestroy (line 24) | willDestroy() {
    method didReceiveArguments (line 28) | didReceiveArguments() {

FILE: client/web/emberclear/app/router.js
  class Router (line 8) | class Router extends EmberRouter {
    method constructor (line 12) | constructor() {

FILE: client/web/emberclear/app/routes/add-friend.ts
  class AddFriendRoute (line 7) | class AddFriendRoute extends Route {
    method beforeModel (line 11) | async beforeModel() {

FILE: client/web/emberclear/app/routes/application.ts
  type Model (line 17) | interface Model {
  class ApplicationRoute (line 22) | class ApplicationRoute extends Route {
    method beforeModel (line 31) | async beforeModel() {
    method model (line 43) | async model(): Promise<Model> {
    method afterModel (line 55) | afterModel() {

FILE: client/web/emberclear/app/routes/chat.ts
  type Model (line 10) | interface Model {
  class ChatRoute (line 14) | class ChatRoute extends Route {
    method beforeModel (line 20) | async beforeModel() {
    method model (line 32) | async model(): Promise<Model> {
    method afterModel (line 41) | afterModel() {

FILE: client/web/emberclear/app/routes/chat/in-channel.ts
  type IModelParams (line 7) | interface IModelParams {
  class ChatInChannelRoute (line 11) | class ChatInChannelRoute extends Route {
    method model (line 17) | async model(params: IModelParams) {

FILE: client/web/emberclear/app/routes/chat/privately-with.ts
  type IModelParams (line 10) | interface IModelParams {
  class ChatPrivatelyRoute (line 14) | class ChatPrivatelyRoute extends Route {
    method beforeModel (line 21) | async beforeModel(transition: any) {
    method model (line 34) | async model(params: IModelParams) {

FILE: client/web/emberclear/app/routes/contacts.ts
  class ContactsRoute (line 6) | class ContactsRoute extends Route {
    method beforeModel (line 9) | async beforeModel() {

FILE: client/web/emberclear/app/routes/invite.ts
  class InviteRoute (line 11) | class InviteRoute extends Route {
    method beforeModel (line 18) | async beforeModel(transition: any) {
    method acceptInvite (line 36) | async acceptInvite(transition: any) {
    method acceptContactInvite (line 52) | private async acceptContactInvite(name: string, publicKey: string) {
    method hasParams (line 72) | private hasParams({ name, publicKey }: IQueryParams) {

FILE: client/web/emberclear/app/routes/login.ts
  class SettingsRoute (line 7) | class SettingsRoute extends Route {
    method beforeModel (line 11) | async beforeModel() {

FILE: client/web/emberclear/app/routes/logout.ts
  class LogoutRoute (line 7) | class LogoutRoute extends Route {
    method beforeModel (line 12) | async beforeModel() {

FILE: client/web/emberclear/app/routes/qr.js
  class QrRoute (line 3) | class QrRoute extends Route {}

FILE: client/web/emberclear/app/routes/settings.ts
  class SettingsRoute (line 6) | class SettingsRoute extends Route {
    method beforeModel (line 9) | async beforeModel() {

FILE: client/web/emberclear/app/routes/settings/relays.ts
  type Model (line 8) | interface Model {
  class SettingsRelayRoute (line 12) | class SettingsRelayRoute extends Route {
    method model (line 15) | async model(): Promise<Model> {

FILE: client/web/emberclear/app/routes/setup.ts
  class SetupRoute (line 3) | class SetupRoute extends Route {
    method beforeModel (line 4) | async beforeModel() {

FILE: client/web/emberclear/app/services/channels/-utils/channel-factory.ts
  function buildChannelInfo (line 9) | function buildChannelInfo(channel: Channel): StandardMessage['channelInf...
  function buildChannelContextChain (line 18) | function buildChannelContextChain(
  function buildChannelMember (line 36) | function buildChannelMember(member: Identity): ChannelMember {
  function buildVote (line 44) | function buildVote(vote: Vote): StandardVote {
  function buildVoteChain (line 51) | function buildVoteChain(voteChain: VoteChain): StandardVoteChain {

FILE: client/web/emberclear/app/services/channels/-utils/vote-sorter.ts
  constant VOTE_ORDERING (line 7) | const VOTE_ORDERING = {
  type SortedVote (line 17) | type SortedVote = [
  type SortedVoteHex (line 27) | type SortedVoteHex = [
  function generateSortedVote (line 37) | function generateSortedVote(vote: VoteChain): Uint8Array {
  function toSortedPublicKeys (line 51) | function toSortedPublicKeys(identities: Identity[]): string[] {

FILE: client/web/emberclear/app/services/channels/channel-verifier.ts
  class ChannelVerifier (line 12) | class ChannelVerifier extends Service {
    method isValidChain (line 15) | async isValidChain(channel: ChannelContextChain): Promise<boolean> {
    method isValidSingleChain (line 43) | private isValidSingleChain(channel: ChannelContextChain): boolean {
    method isVoteCompletedPositive (line 51) | private isVoteCompletedPositive(vote: VoteChain, admin: Identity): boo...
    method getDiffs (line 63) | private getDiffs(previousMembers: Identity[], currentMembers: Identity...
    method isAddValid (line 74) | private isAddValid(channel: ChannelContextChain): boolean {
    method isPromoteValid (line 96) | private isPromoteValid(channel: ChannelContextChain): boolean {
    method isRemoveValid (line 114) | private isRemoveValid(channel: ChannelContextChain): boolean {
  type Registry (line 138) | interface Registry {

FILE: client/web/emberclear/app/services/channels/vote-verifier.ts
  class VoteVerifier (line 15) | class VoteVerifier extends Service {
    method isValid (line 19) | async isValid(voteToVerify: VoteChain): Promise<boolean> {
    method connectCrypto (line 54) | private connectCrypto() {
    method isTargetAndActionUnchanged (line 63) | private isTargetAndActionUnchanged(vote: VoteChain): boolean {
    method isKeyMatchingVoteDiff (line 76) | private isKeyMatchingVoteDiff(vote: VoteChain): boolean {
    method isProperMove (line 119) | private isProperMove(
    method getVoterDiffs (line 154) | private getVoterDiffs(previousVoters: Identity[], currentVoters: Ident...
    method isProperMoveBase (line 166) | private isProperMoveBase(vote: VoteChain): boolean {
    method isInOneButNotBoth (line 175) | private isInOneButNotBoth(arr1: Identity[], arr2: Identity[], key: Ide...
  type VoterDiffs (line 183) | type VoterDiffs = {
  type Registry (line 190) | interface Registry {

FILE: client/web/emberclear/app/services/chat-scroller.ts
  constant SCROLL_DELAY (line 11) | const SCROLL_DELAY = 100;
  class ChatScroller (line 13) | class ChatScroller extends Service {
    method isViewingOlderMessages (line 16) | get isViewingOlderMessages() {
    method _isLastVisible (line 20) | _isLastVisible(message: Message) {
    method maybeNudge (line 30) | async maybeNudge(appendedMessage: HTMLElement) {
    method scrollToBottom (line 39) | async scrollToBottom() {
    method shouldScroll (line 47) | private shouldScroll(appendedMessage: HTMLElement) {
  function isLastVisible (line 71) | function isLastVisible(id: string) {
  function isBottomOfMessageVisible (line 91) | function isBottomOfMessageVisible(element: HTMLElement, container: HTMLE...
  type Registry (line 101) | interface Registry {

FILE: client/web/emberclear/app/services/connection/ephemeral/login/receive-data.ts
  type UpdateStatus (line 17) | type UpdateStatus = (status: boolean) => void;
  class ReceiveDataConnection (line 19) | class ReceiveDataConnection extends EphemeralConnection {
    method wait (line 32) | wait(updateTransferStatus: UpdateStatus) {
    method _wait (line 41) | async _wait(updateTransferStatus: UpdateStatus) {
    method onData (line 81) | async onData(data: EncryptedMessage) {

FILE: client/web/emberclear/app/services/connection/ephemeral/login/send-data.ts
  class SendDataConnection (line 19) | class SendDataConnection extends EphemeralConnection {
    method establishContact (line 27) | establishContact() {
    method transferToDevice (line 34) | transferToDevice() {
    method _establishContact (line 41) | async _establishContact() {
    method _transferToDevice (line 51) | async _transferToDevice() {
    method onData (line 65) | async onData(data: EncryptedMessage) {

FILE: client/web/emberclear/app/services/current-chat.ts
  class CurrentChatService (line 11) | class CurrentChatService extends Service {
    method name (line 16) | get name() {
    method record (line 32) | get record() {
    method recordId (line 42) | get recordId() {
    method recordType (line 46) | get recordType() {
    method contactId (line 50) | get contactId() {
    method channelId (line 54) | get channelId() {
  function contactIdFrom (line 59) | function contactIdFrom(url: string) {
  function channelIdFrom (line 70) | function channelIdFrom(url: string) {
  type Registry (line 83) | interface Registry {

FILE: client/web/emberclear/app/services/locale.ts
  constant DEFAULT_LOCALE (line 8) | const DEFAULT_LOCALE = 'en-us';
  class LocaleService (line 10) | class LocaleService extends Service {
    method setLocale (line 15) | async setLocale(locale: string = DEFAULT_LOCALE) {

FILE: client/web/emberclear/app/services/modals.ts
  type IModalArgs (line 4) | interface IModalArgs {
  class ModalState (line 9) | class ModalState {
    method constructor (line 13) | constructor(args: IModalArgs) {
    method open (line 18) | open() {
    method close (line 22) | close() {
    method toggle (line 26) | toggle() {
  class Modals (line 31) | class Modals extends Service {
    method toggle (line 34) | toggle(name: string) {
    method close (line 38) | close(name: string) {
    method open (line 42) | open(name: string) {
    method isVisible (line 46) | isVisible(name: string) {
    method find (line 50) | find(name: string) {

FILE: client/web/emberclear/app/services/notifications.ts
  class Notifications (line 12) | class Notifications extends Service {
    method showInAppPrompt (line 24) | get showInAppPrompt() {
    method isOnRouteThatDoesNotShowNotifications (line 39) | get isOnRouteThatDoesNotShowNotifications() {
    method info (line 47) | info(msg: string, title = '', options = {}) {
    method display (line 51) | async display(msg: string, title: string, options = {}) {
    method isPermissionGranted (line 65) | get isPermissionGranted() {
    method isPermissionDenied (line 73) | get isPermissionDenied() {
    method askPermission (line 77) | askPermission() {
    method isBrowserCapableOfNotifications (line 90) | get isBrowserCapableOfNotifications() {
    method showNotification (line 94) | showNotification(msg: string, title = '', options = {}) {
  type Registry (line 110) | interface Registry {

FILE: client/web/emberclear/app/services/prism-manager.ts
  class PrismManager (line 23) | class PrismManager extends Service {
    method addLanguage (line 29) | async addLanguage(language: string, element?: HTMLElement) {
    method ensureLanguage (line 38) | async ensureLanguage(language: string) {
    method addEssentials (line 61) | async addEssentials() {
  function addScripts (line 73) | async function addScripts() {
  function addStyles (line 94) | function addStyles() {
  function addStyle (line 101) | function addStyle(path: string) {

FILE: client/web/emberclear/app/services/qr-manager.ts
  class QRManager (line 9) | class QRManager extends Service {
    method setupConnection (line 12) | async setupConnection(context: object, publicKeyAsHex: string) {
  type Registry (line 24) | interface Registry {

FILE: client/web/emberclear/app/services/redirect-manager.ts
  class RedirectManager (line 8) | class RedirectManager extends Service {
    method hasPendingRedirect (line 13) | get hasPendingRedirect() {
    method persistURL (line 17) | persistURL(path: string) {
    method evaluate (line 21) | async evaluate() {
  type Registry (line 40) | interface Registry {

FILE: client/web/emberclear/app/services/session.ts
  constant FLAG_KEY (line 13) | const FLAG_KEY = '_features';
  class SessionService (line 15) | class SessionService extends Service {
    method logout (line 23) | async logout() {
    method hasFeatureFlag (line 35) | hasFeatureFlag(flag: string) {
  type Registry (line 46) | interface Registry {

FILE: client/web/emberclear/app/services/settings.ts
  type IContactJson (line 15) | interface IContactJson {
  type IChannelJson (line 20) | interface IChannelJson {
  type ISettingsJson (line 25) | interface ISettingsJson {
  constant THEMES (line 34) | const THEMES = {
  class Settings (line 44) | class Settings extends Service {
    method selectTheme (line 52) | selectTheme(themeKey: string) {
    method applyTheme (line 57) | applyTheme() {
    method import (line 68) | async import(settings: string) {
    method importData (line 74) | async importData(json: ISettingsJson) {
    method buildData (line 102) | async buildData(): Promise<string | undefined> {
    method buildSettings (line 108) | async buildSettings(): Promise<Serializable> {
  type Registry (line 144) | interface Registry {

FILE: client/web/emberclear/app/services/sidebar.ts
  class Sidebar (line 9) | class Sidebar extends Service {
    method hasUnreadAbove (line 17) | get hasUnreadAbove() {
    method hasUnreadBelow (line 21) | get hasUnreadBelow() {
    method show (line 28) | show() {
    method hide (line 33) | hide() {
    method toggle (line 38) | toggle() {
    method clearUnreadBelow (line 42) | clearUnreadBelow() {
    method clearUnreadAbove (line 46) | clearUnreadAbove() {
    method ensureUnreadIntersectionObserverExists (line 50) | ensureUnreadIntersectionObserverExists() {
    method createUnreadObserver (line 56) | private createUnreadObserver(): IntersectionObserver {
    method handleIntersectionEvent (line 66) | private handleIntersectionEvent(entries: IntersectionObserverEntry[]) {

FILE: client/web/emberclear/app/services/toast.ts
  class Toast (line 8) | class Toast extends Service {
    method info (line 9) | info(msg: string, title = '', options = {}) {
    method success (line 13) | success(msg: string, title = '', options = {}) {
    method warning (line 17) | warning(msg: string, title = '', options = {}) {
    method error (line 21) | error(msg: string, title = '', options = {}) {
    method createToast (line 25) | createToast(status: string, msg: string, title: string, options: any) {
  function createToast (line 32) | function createToast(status: string, message: string, options: any) {

FILE: client/web/emberclear/app/services/window.ts
  class WindowService (line 4) | class WindowService extends Service {
    method constructor (line 14) | constructor(...args: any[]) {
    method location (line 20) | get location() {
    method willDestroy (line 24) | willDestroy() {
    method checkForDeferredInstall (line 28) | checkForDeferredInstall() {
    method canInstall (line 45) | get canInstall() {
    method promptInstall (line 49) | async promptInstall() {
    method evaluateInstallPrompt (line 57) | async evaluateInstallPrompt() {
  type Registry (line 72) | interface Registry {

FILE: client/web/emberclear/app/utils/breakpoints.ts
  constant TABLET_WIDTH (line 1) | const TABLET_WIDTH = 832;

FILE: client/web/emberclear/app/utils/dom/utils.ts
  function isElementWithin (line 4) | function isElementWithin(element: HTMLElement, container: HTMLElement): ...
  function isInElementWithinViewport (line 17) | function isInElementWithinViewport(element: Element, container: Element)...
  function keepInViewPort (line 37) | function keepInViewPort(element: HTMLElement, margin = 20 /* px */) {
  function convertAndSanitizeMarkdown (line 73) | function convertAndSanitizeMarkdown(markdown: string) {
  function scrollIntoViewOfParent (line 81) | function scrollIntoViewOfParent(parent: Element, child: Element) {

FILE: client/web/emberclear/app/utils/ember-concurrency.ts
  function taskService (line 35) | function taskService<TEvent extends Event<any>, Args extends unknown[], ...

FILE: client/web/emberclear/app/utils/errors.ts
  class ConnectionDoesNotExistError (line 1) | class ConnectionDoesNotExistError extends Error {}
  class MalformedQRCodeError (line 2) | class MalformedQRCodeError extends Error {}
  class UnrecognizedQRCodeError (line 3) | class UnrecognizedQRCodeError extends Error {}
  class NoCameraError (line 5) | class NoCameraError extends Error {
    method constructor (line 6) | constructor(...props: any[]) {
  class ConnectionError (line 13) | class ConnectionError extends Error {}
  class RelayNotSetError (line 14) | class RelayNotSetError extends Error {
  class CurrentUserNotFound (line 18) | class CurrentUserNotFound extends Error {

FILE: client/web/emberclear/app/utils/identity-comparison.ts
  function identitiesIncludes (line 5) | function identitiesIncludes(identities: Identity[], identity: Identity):...
  function identityEquals (line 9) | function identityEquals(identity1: Identity, identity2: Identity): boole...

FILE: client/web/emberclear/app/utils/normalized-meta.ts
  type Args (line 3) | type Args = {
  constant YT_PATTERN (line 9) | const YT_PATTERN = /^.*(youtu.be\/|\/v\/|u\/\w\/|embed\/|watch\?v=|&v=)(...
  constant IMAGE_PATTERN (line 10) | const IMAGE_PATTERN = /(jpg|png|gif|webp)/;
  constant VIDEO_PATTERN (line 11) | const VIDEO_PATTERN = /(\.(mp4)$)/;
  constant EXT_PATTERN (line 12) | const EXT_PATTERN = /\.[\w]{2,4}$/;
  type NormalizedMeta (line 14) | type NormalizedMeta = {
  function normalizeMeta (line 31) | function normalizeMeta(data: Args): NormalizedMeta {
  function embedUrlFrom (line 58) | function embedUrlFrom(url: string) {

FILE: client/web/emberclear/app/utils/route-matchers.ts
  constant PRIVATE_CHAT_REGEX (line 1) | const PRIVATE_CHAT_REGEX = /chat\/privately-with\/(.+)/;
  constant CHANNEL_REGEX (line 2) | const CHANNEL_REGEX = /chat\/in-channel\/(.+)/;
  function idFrom (line 4) | function idFrom(regex: RegExp, url: string) {

FILE: client/web/emberclear/app/utils/string/utils.ts
  function matchAll (line 1) | function matchAll(str: string, regex: RegExp) {
  function parseLanguages (line 12) | function parseLanguages(text: string): string[] {
  constant URL_PATTERN (line 23) | const URL_PATTERN = /(((http|https):\/\/)|(www)){1}[a-zA-Z0-9./?:@\-_=#]...
  function parseURLs (line 25) | function parseURLs(text: string): string[] {
  constant HOST_FROM_URL_REGEX (line 33) | const HOST_FROM_URL_REGEX = /\/\/(.+)\//;
  function hostFromURL (line 35) | function hostFromURL(url: string) {

FILE: client/web/emberclear/app/utils/uint8array-equality.ts
  function equalsUint8Array (line 1) | function equalsUint8Array(arr1: Uint8Array, arr2: Uint8Array): boolean {

FILE: client/web/emberclear/config/addons.js
  constant ENV (line 1) | const ENV = {};

FILE: client/web/emberclear/config/build/addons.js
  function serviceWorkerConfig (line 9) | function serviceWorkerConfig({ version }) {
  function addonConfig (line 39) | function addonConfig(env) {

FILE: client/web/emberclear/config/build/static.js
  method buildStaticTrees (line 10) | buildStaticTrees({ isProduction, hash }) {

FILE: client/web/emberclear/config/environment.js
  constant ADDON_ENV (line 3) | const ADDON_ENV = require('./addons');

FILE: client/web/emberclear/scripts/analyze-broccoli.js
  function analyzeBroccoli (line 12) | async function analyzeBroccoli() {

FILE: client/web/emberclear/tests/-temp/qunit-xstate-test.ts
  type TestCallbackFn (line 7) | type TestCallbackFn<TestContext, TContext, TReturn> = (

FILE: client/web/emberclear/tests/acceptance/chat/privately-with/-acceptance-test.ts
  method send (line 167) | send() {
  method send (line 260) | send() {

FILE: client/web/emberclear/tests/acceptance/chat/privately-with/format-code-test.ts
  function submitCodeTo (line 28) | async function submitCodeTo(code: string, to: Contact, assert: Assert) {
  method send (line 46) | send() {

FILE: client/web/emberclear/tests/acceptance/login/acceptance-test.ts
  method clickLogin (line 18) | clickLogin() {

FILE: client/web/emberclear/tests/acceptance/logout-test.ts
  method load (line 24) | load() {}

FILE: client/web/emberclear/tests/acceptance/qr/login/sender-test.ts
  type TestMachineContext (line 22) | interface TestMachineContext {
  method test (line 45) | async test({ assert, t }: TestMachineContext) {
  method test (line 62) | async test({ assert, t }: TestMachineContext) {
  method test (line 79) | async test({ assert, t }: TestMachineContext) {
  method test (line 93) | async test({ assert }: TestMachineContext) {
  method test (line 109) | async test({ assert, t }: TestMachineContext) {
  method test (line 116) | async test({ assert }: TestMachineContext) {
  method test (line 128) | async test({ assert, t }: TestMachineContext) {
  method test (line 142) | async test({ assert }: TestMachineContext) {
  method exec (line 158) | async exec({ owner }) {
  method exec (line 163) | async exec({ owner }) {
  method exec (line 168) | async exec({ owner }) {
  method exec (line 176) | async exec({ connection }) {
  method exec (line 181) | async exec({ connection }) {
  method exec (line 189) | async exec() {
  method exec (line 194) | async exec() {
  method exec (line 202) | async exec({ connection }) {
  method exec (line 207) | async exec({ connection }) {
  method transferToDevice (line 227) | transferToDevice() {
  class TestNavigator (line 232) | class TestNavigator extends Service {
    method mediaDevices (line 233) | get mediaDevices(): any {
  class TestQRManager (line 246) | class TestQRManager extends Service {
    method setupConnection (line 248) | async setupConnection() {

FILE: client/web/emberclear/tests/acceptance/sidebar-test.ts
  function setupOfflineContactsTest (line 414) | async function setupOfflineContactsTest() {
  function onlyCurrentUserIsShownTest (line 420) | function onlyCurrentUserIsShownTest(assert: Assert) {

FILE: client/web/emberclear/tests/acceptance/sidebar-visibility-test.ts
  method load (line 23) | load() {}

FILE: client/web/emberclear/tests/helpers/factories/channel-factory.ts
  function createChannel (line 3) | async function createChannel(name: string, attributes = {}) {

FILE: client/web/emberclear/tests/helpers/factories/message-factory.ts
  function createMessage (line 6) | async function createMessage(to: Identity, from: Identity, body: string,...

FILE: client/web/emberclear/tests/helpers/index.ts
  function assertExternal (line 8) | function assertExternal(assert: any) {

FILE: client/web/emberclear/tests/helpers/pages/app.ts
  method open (line 25) | async open() {

FILE: client/web/emberclear/tests/helpers/pages/chat.ts
  method isScrollable (line 29) | isScrollable() {
  method scroll (line 35) | scroll(amountInPx: number) {
  method typeIn (line 49) | typeIn(substring: string) {
  function isScrollable (line 83) | function isScrollable(element: Element) {

FILE: client/web/emberclear/tests/helpers/pages/toast.ts
  function findToast (line 10) | function findToast(): Element {
  method isVisible (line 19) | get isVisible() {
  method text (line 22) | get text() {
  method dismiss (line 26) | dismiss() {
  method waitForToast (line 29) | waitForToast() {

FILE: client/web/emberclear/tests/helpers/setup-relay-connection-mocks.ts
  function stubConnection (line 3) | function stubConnection(overrides = {}) {
  function setupRelayConnectionMocks (line 24) | function setupRelayConnectionMocks(hooks: NestedHooks, overrides = {}) {

FILE: client/web/emberclear/tests/helpers/setup-test.ts
  function setupEmberclearTest (line 10) | function setupEmberclearTest(hooks: NestedHooks) {
  function setupWindow (line 19) | function setupWindow(hooks: NestedHooks) {

FILE: client/web/emberclear/tests/helpers/track-async-data.ts
  function trackAsyncDataRequests (line 3) | function trackAsyncDataRequests(hooks: NestedHooks) {

FILE: client/web/emberclear/tests/integration/components/fetch-open-graph-test.js
  constant LINKS (line 11) | const LINKS = {
  method getOpenGraph (line 46) | getOpenGraph(...args) {

FILE: client/web/emberclear/tests/unit/service/channels/channel-verifier-test.ts
  function signatureOf (line 580) | async function signatureOf(vote: VoteChain, user: User): Promise<Uint8Ar...

FILE: client/web/emberclear/tests/unit/service/channels/utils/-vote-sorter-test.ts
  function sortedVoteHexToSortedVote (line 135) | function sortedVoteHexToSortedVote(sortedVoteHex: SortedVoteHex): Sorted...

FILE: client/web/emberclear/tests/unit/service/channels/vote-verifier-test.ts
  function signatureOf (line 467) | async function signatureOf(vote: VoteChain, user: User): Promise<Uint8Ar...

FILE: client/web/emberclear/tests/unit/utils/dom-test.ts
  method getBoundingClientRect (line 21) | getBoundingClientRect() {

FILE: client/web/emberclear/types/ember-could-get-used-to-this.d.ts
  class Resource (line 2) | class Resource {

FILE: client/web/emberclear/types/ember-intl/services/intl.d.ts
  class IntlService (line 3) | class IntlService extends Service {

FILE: client/web/emberclear/types/ember-modifier.d.ts
  type ModifierArgs (line 1) | interface ModifierArgs {
  type IModifier (line 6) | interface IModifier<Args extends ModifierArgs = ModifierArgs> {
  type Owner (line 18) | type Owner = unknown;
  class Modifier (line 21) | class Modifier<Args extends ModifierArgs = ModifierArgs>

FILE: client/web/emberclear/types/emberclear/addon-services.d.ts
  type Toast (line 5) | interface Toast {
  type Intl (line 14) | interface Intl {
  type Registry (line 20) | interface Registry {

FILE: client/web/emberclear/types/emberclear/ember-data.d.ts
  type ModelRegistry (line 5) | interface ModelRegistry {

FILE: client/web/emberclear/types/emberclear/index.d.ts
  type EmptyRecord (line 15) | type EmptyRecord = Record<string, unknown>;
  type Prism (line 17) | interface Prism {
  type PublicIdentity (line 21) | interface PublicIdentity {
  type Array (line 26) | interface Array<T> extends Ember.ArrayPrototypeExtensions<T> {
  type UserIdentifier (line 32) | interface UserIdentifier {
  type NamedUser (line 36) | interface NamedUser {
  type ChannelMember (line 41) | interface ChannelMember {
  type MemberResult (line 47) | interface MemberResult {
  type StandardVoteChain (line 53) | interface StandardVoteChain {
  type StandardVote (line 65) | interface StandardVote {
  type StandardChannelContextChain (line 70) | interface StandardChannelContextChain {
  type StandardMessage (line 78) | interface StandardMessage {
  type LoginSYN (line 104) | type LoginSYN = { type: 'SYN'; data: PublicIdentity };
  type LoginACK (line 105) | type LoginACK = { type: 'ACK' };
  type LoginHash (line 106) | type LoginHash = { type: 'HASH'; data: string };
  type LoginData (line 107) | type LoginData = {
  type LoginMessage (line 120) | type LoginMessage = LoginData | LoginACK | LoginSYN | LoginHash;
  type RelayJson (line 122) | type RelayJson = StandardMessage | LoginMessage;

FILE: client/web/emberclear/types/index.d.ts
  type Dict (line 1) | type Dict<T = string> = { [key: string]: T };
  type Window (line 6) | interface Window {
  type UserChoice (line 15) | interface UserChoice {
  type FakeBeforeInstallPromptEvent (line 19) | interface FakeBeforeInstallPromptEvent {

FILE: client/web/emberclear/types/qr-scanner.d.ts
  class QrScanner (line 2) | class QrScanner {

FILE: client/web/emberclear/types/toastify-js.d.ts
  type ToastifyToast (line 1) | interface ToastifyToast {
  type ToastifyOptions (line 7) | interface ToastifyOptions {

FILE: client/web/emberclear/vendor/shims/libsodium-wrappers.js
  function vendorModule (line 2) | function vendorModule() {

FILE: client/web/emberclear/vendor/shims/libsodium.js
  function vendorModule (line 2) | function vendorModule() {

FILE: client/web/emberclear/vendor/shims/localforage.js
  function vendorModule (line 2) | function vendorModule() {

FILE: client/web/emberclear/vendor/shims/qrcode.js
  function vendorModule (line 2) | function vendorModule() {

FILE: client/web/libraries/questionably-typed/types/globals.ts
  type LIES (line 1) | type LIES<T> = T;
  type TODO (line 3) | type TODO<T = any> = T;

FILE: client/web/libraries/questionably-typed/types/libraries/ember.ts
  type TF (line 9) | type TF = TemplateFactory;

FILE: client/web/libraries/questionably-typed/types/libraries/promise-worker-bi.ts
  class PWBWorker (line 2) | class PWBWorker {
  class PWBHost (line 7) | class PWBHost {

FILE: client/web/pinochle/app/app.ts
  class App (line 11) | class App extends Application {

FILE: client/web/pinochle/app/components/back-of-cards.ts
  type Args (line 5) | type Args = {
  class BackOfCards (line 9) | class BackOfCards extends Component<Args> {
    method isOffline (line 10) | get isOffline() {

FILE: client/web/pinochle/app/components/hand/-animation/card-chart.ts
  type Keyframes (line 6) | type Keyframes = {
  type Context (line 13) | type Context = {
  type AdjustEvent (line 26) | type AdjustEvent = {
  type ToggleEvent (line 31) | type ToggleEvent = {
  type Event (line 36) | type Event =
  type Schema (line 48) | interface Schema extends StateSchema<Context> {
  constant SMALL_SCREEN (line 57) | const SMALL_SCREEN = 1000;
  constant ANIMATION_DURATION (line 58) | const ANIMATION_DURATION = 250;
  constant DEFAULT_ANIMATION_OPTIONS (line 59) | const DEFAULT_ANIMATION_OPTIONS: KeyframeAnimationOptions = {
  function isBigScreen (line 65) | function isBigScreen() {
  function isSmallScreen (line 69) | function isSmallScreen() {
  function animate (line 73) | function animate(context: Context, next: Keyframe, options: KeyframeAnim...
  function toSelection (line 93) | function toSelection(ctx: Context) {
  function toFlat (line 99) | function toFlat(ctx: Context) {
  function toStack (line 105) | function toStack(ctx: Context) {
  function toFan (line 109) | function toFan(ctx: Context) {

FILE: client/web/pinochle/app/components/hand/-animation/card.ts
  constant SELECTED_TRANSFORM (line 11) | const SELECTED_TRANSFORM = {
  class CardAnimation (line 17) | class CardAnimation {
    method constructor (line 18) | constructor(public element: HTMLElement, public frames: Keyframes) {}
    method select (line 43) | select() {
    method deselect (line 48) | deselect() {
    method toggle (line 53) | toggle(delay: number) {
    method adjust (line 58) | adjust(frames: Keyframes) {

FILE: client/web/pinochle/app/components/hand/-animation/hand-chart.ts
  type Context (line 9) | type Context = {
  type SelectEvent (line 17) | type SelectEvent = { type: 'SELECT'; card: Card };
  type Event (line 18) | type Event =
  type Schema (line 26) | interface Schema extends StateSchema<Context> {
  function canPlayCard (line 47) | function canPlayCard() {
  function isClosed (line 51) | function isClosed(context: Context) {
  function isOpen (line 55) | function isOpen(context: Context) {

FILE: client/web/pinochle/app/components/hand/-animation/hand.ts
  function getAnimations (line 15) | function getAnimations(points: ReturnType<typeof getPoints>, cards: Card...
  type ToggleOptions (line 44) | type ToggleOptions = {
  function adjustHand (line 49) | function adjustHand({ cards, animations }: ToggleOptions) {
  class HandAnimation (line 72) | class HandAnimation {
    method constructor (line 73) | constructor(_owner: unknown, public cards: Card[]) {}
    method toggle (line 96) | toggle() {
    method send (line 101) | send(...args: Parameters<Statechart<Context, Schema, Event>['send']>) {
    method context (line 108) | get context() {
    method _fanOpen (line 121) | _fanOpen({ cards, animations }: Context) {
    method _closeHand (line 137) | _closeHand(context: Context) {
    method _adjustHand (line 143) | _adjustHand({ cards, animations }: Context) {
    method _showSelected (line 148) | _showSelected({ animations, cards }: Context, { card }: SelectEvent) {
    method _returnSelected (line 164) | _returnSelected({ animations, selected }: Context) {

FILE: client/web/pinochle/app/components/hand/-animation/key-frames.ts
  function stackedKeyframes (line 4) | function stackedKeyframes({ path, positions }: ReturnType<typeof getPoin...
  function fannedKeyframes (line 13) | function fannedKeyframes({ path, positions }: ReturnType<typeof getPoint...
  function flatKeyframes (line 29) | function flatKeyframes({ path, positions }: ReturnType<typeof getPoints>) {
  function getPoints (line 64) | function getPoints(num: number) {

FILE: client/web/pinochle/app/components/hand/index.ts
  type Args (line 12) | type Args = {
  class HandComponent (line 17) | class HandComponent extends Component<Args> {
    method hand (line 19) | get hand() {
    method meld (line 27) | get meld() {
    method toggle (line 32) | toggle() {
    method selectCard (line 37) | selectCard(card: Card) {
    method adjust (line 42) | adjust() {

FILE: client/web/pinochle/app/components/host-game/-statechart.ts
  type Context (line 5) | type Context = {
  type SubmitNameEvent (line 11) | type SubmitNameEvent = { type: 'SUBMIT_NAME'; name: string };
  type Event (line 12) | type Event =
  type Schema (line 18) | interface Schema extends StateSchema<Context> {

FILE: client/web/pinochle/app/components/host-game/index.ts
  type Args (line 18) | type Args = {
  class HostGame (line 22) | class HostGame extends Component<Args> {
    method state (line 45) | get state() {
    method context (line 49) | get context() {
    method connectedPlayers (line 53) | get connectedPlayers() {
    method joinUrl (line 57) | get joinUrl() {
    method canStartGame (line 61) | get canStartGame() {
    method numRemaining (line 65) | get numRemaining() {
    method handleSubmit (line 70) | handleSubmit(name: string) {
    method start (line 75) | start() {
    method _startGame (line 84) | _startGame() {
    method _establishConnection (line 100) | async _establishConnection({ name }: Context) {

FILE: client/web/pinochle/app/components/join-game/-statechart.ts
  type Context (line 7) | type Context = {
  type SubmitNameEvent (line 12) | type SubmitNameEvent = { type: 'SUBMIT_NAME'; name: string };
  type Event (line 14) | type Event =
  type Schema (line 23) | interface Schema extends StateSchema<Context> {

FILE: client/web/pinochle/app/components/join-game/index.ts
  type Args (line 23) | type Args = {
  class JoinGame (line 28) | class JoinGame extends Component<Args> {
    method state (line 54) | get state() {
    method isJoining (line 58) | get isJoining() {
    method isWaiting (line 62) | get isWaiting() {
    method isPending (line 66) | get isPending() {
    method handleSubmit (line 71) | handleSubmit(name: string) {
    method _establishConnection (line 79) | async _establishConnection() {
    method _joinGame (line 109) | _joinGame({ name }: Context) {
    method _startGame (line 114) | _startGame() {

FILE: client/web/pinochle/app/components/lazy/index.ts
  type Args (line 5) | type Args = {
  class LazyComponent (line 10) | class LazyComponent extends Component<Args> {
    method constructor (line 13) | constructor(owner: unknown, args: Args) {
    method isShowing (line 21) | get isShowing() {
    method cond (line 25) | get cond() {
    method toggleContent (line 29) | toggleContent() {

FILE: client/web/pinochle/app/components/name-entry/index.ts
  type Args (line 8) | type Args = {
  class NameEntry (line 12) | class NameEntry extends Component<Args> {
    method hasName (line 15) | get hasName() {
    method isNameMissing (line 19) | get isNameMissing() {
    method updateName (line 24) | updateName(e: KeyboardEvent) {
    method submitName (line 31) | submitName(e: Event) {

FILE: client/web/pinochle/app/components/options.ts
  class Options (line 7) | class Options extends Component {
    method toggle (line 13) | toggle() {
    method poorMansEffect (line 17) | get poorMansEffect() {
    method willDestroy (line 29) | willDestroy() {

FILE: client/web/pinochle/app/components/play/as-guest/-statechart.ts
  type Context (line 3) | type Context = {
  type Event (line 7) | type Event = { type: 'START_GAME_FAILED' } | { type: 'CONNECTED' };
  type Schema (line 9) | interface Schema extends StateSchema<Context> {

FILE: client/web/pinochle/app/components/play/as-guest/index.ts
  type Args (line 14) | type Args = {
  class PlayAsGuest (line 19) | class PlayAsGuest extends Component<Args> {
    method hand (line 21) | get hand() {
    method hasHand (line 25) | get hasHand() {
    method chooseCard (line 43) | chooseCard(card: Card) {
    method getHand (line 51) | getHand() {

FILE: client/web/pinochle/app/components/player-order/index.ts
  type Args (line 8) | type Args = {
  class PlayerOrder (line 12) | class PlayerOrder extends Component<Args> {
    method gameInfo (line 16) | get gameInfo() {
    method currentPlayer (line 24) | get currentPlayer() {
    method players (line 28) | get players() {

FILE: client/web/pinochle/app/components/share-link.ts
  type Args (line 5) | type Args = {
  class ShareLink (line 9) | class ShareLink extends Component<Args> {
    method copy (line 11) | copy() {
    method highlight (line 18) | highlight(event: MouseEvent) {

FILE: client/web/pinochle/app/game/card.ts
  type Suit (line 3) | type Suit = 'hearts' | 'spades' | 'diamonds' | 'clubs';
  type Value (line 4) | type Value = 9 | 'jack' | 'queen' | 'king' | 10 | 'ace';
  constant VALUES (line 6) | const VALUES: Value[] = [9, 'jack', 'queen', 'king', 10, 'ace'];
  constant SUITS (line 7) | const SUITS: Suit[] = ['hearts', 'spades', 'diamonds', 'clubs'];
  class Card (line 13) | class Card {
    method constructor (line 15) | constructor(public suit: Suit, public value: Value) {}
    method toString (line 17) | toString() {
  constant VALUE_TO_NUMBER (line 22) | const VALUE_TO_NUMBER = {
  function isEqualOrHigherValue (line 31) | function isEqualOrHigherValue(a: Card, b: Card) {

FILE: client/web/pinochle/app/game/deck.ts
  function newDeck (line 11) | function newDeck() {
  function splitDeck (line 31) | function splitDeck(deck: Card[], splits: number) {
  function sortHand (line 67) | function sortHand(hand: Card[]) {
  function hasSuit (line 91) | function hasSuit(hand: Card[], suit: Suit) {
  function shuffle (line 98) | function shuffle<T>(array: T[]) {

FILE: client/web/pinochle/app/game/meld.ts
  type MeldResultMatch (line 5) | interface MeldResultMatch {
  type MeldResult (line 10) | type MeldResult = {
  type SuitInfo (line 19) | type SuitInfo = {
  type ValueInfo (line 24) | type ValueInfo = {
  class Meld (line 29) | class Meld {
    method constructor (line 33) | constructor(public cards: Card[], public trump?: Suit) {
    method score (line 38) | get score() {
    method matches (line 49) | get matches(): MeldResult {
  type CalculatorArgs (line 81) | type CalculatorArgs = [Card[], Map<Suit, SuitInfo>, Map<Value, ValueInfo...
  constant ROYAL_MULTIPLIER (line 96) | const ROYAL_MULTIPLIER = 10;
  method run (line 103) | run(...[, bySuit, _, trump]: CalculatorArgs) {
  method aces (line 135) | aces(...[, , byValue]: CalculatorArgs) {
  method kings (line 157) | kings(...[, , byValue]: CalculatorArgs) {
  method queens (line 177) | queens(...[, , byValue]: CalculatorArgs) {
  method jacks (line 197) | jacks(...[, , byValue]: CalculatorArgs) {
  method pinochle (line 217) | pinochle(...[, bySuit]: CalculatorArgs) {
  method marriage (line 235) | marriage(...[, bySuit, _, trump]: CalculatorArgs) {
  method nineOfTrump (line 265) | nineOfTrump(...[, , byValue, trump]: CalculatorArgs) {
  function groupBySuit (line 291) | function groupBySuit(cards: Card[]) {
  function groupByValue (line 306) | function groupByValue(cards: Card[]) {

FILE: client/web/pinochle/app/game/networking/-requirements.ts
  function ensureRequirementsAreMet (line 5) | async function ensureRequirementsAreMet(owner: ApplicationInstance) {

FILE: client/web/pinochle/app/game/networking/constants.ts
  constant GAME_PHASES (line 1) | const GAME_PHASES = {
  type GamePhase (line 6) | type GamePhase = typeof GAME_PHASES[keyof typeof GAME_PHASES];

FILE: client/web/pinochle/app/game/networking/guest.ts
  type SerializedGuest (line 28) | type SerializedGuest = {
  class GameGuest (line 42) | class GameGuest extends EphemeralConnection {
    method constructor (line 61) | constructor(publicKeyAsHex: string) {
    method playerOrder (line 67) | get playerOrder() {
    method joinUrl (line 71) | get joinUrl() {
    method me (line 78) | get me() {
    method checkHost (line 85) | async checkHost() {
    method joinHost (line 123) | async joinHost(name: string) {
    method waitForStart (line 130) | waitForStart() {
    method onData (line 136) | async onData(data: EncryptedMessage) {
    method playCard (line 198) | async playCard(card: Card) {
    method startGame (line 203) | startGame(decrypted: GameState) {
    method updateGameState (line 209) | updateGameState(decrypted: GameState) {
    method handleWelcome (line 219) | handleWelcome(decrypted: WelcomeMessage) {
    method redirectToGame (line 225) | redirectToGame() {
    method serialize (line 239) | serialize() {

FILE: client/web/pinochle/app/game/networking/guest/display-info.ts
  class DisplayInfo (line 8) | class DisplayInfo {
    method constructor (line 11) | constructor(public currentPlayerId: string, public state: GuestGameRou...
    method update (line 13) | update(info: GameInfo, state?: GuestGameRound) {
    method offlinePlayers (line 21) | get offlinePlayers() {
    method offlinePlayerNames (line 25) | get offlinePlayerNames() {
    method hasOfflinePlayers (line 29) | get hasOfflinePlayers() {
    method left (line 33) | get left() {
    method right (line 39) | get right() {
    method top (line 45) | get top() {

FILE: client/web/pinochle/app/game/networking/guest/game-round.ts
  class GuestGameRound (line 12) | class GuestGameRound {
    method playerList (line 21) | get playerList() {
    method playerOrder (line 26) | get playerOrder() {
    method update (line 37) | update({ currentPlayer, hand, scoreHistory, info, gamePhase }: GameSta...
    method _updatePlayers (line 50) | _updatePlayers(msg: { players: SerializablePlayer[] }) {

FILE: client/web/pinochle/app/game/networking/guest/utils.ts
  function verifyMessage (line 3) | function verifyMessage(msg: FromHostMessage) {

FILE: client/web/pinochle/app/game/networking/host.ts
  constant MAX_PLAYERS (line 24) | const MAX_PLAYERS = 4;
  class GameHost (line 35) | class GameHost extends EphemeralConnection {
    method teardown (line 42) | teardown() {
    method players (line 50) | get players() {
    method otherPlayers (line 54) | get otherPlayers() {
    method numConnected (line 58) | get numConnected() {
    method joinUrl (line 62) | get joinUrl() {
    method onData (line 80) | async onData(data: EncryptedMessage) {
    method startGame (line 158) | startGame() {
    method _broadcastStart (line 169) | _broadcastStart() {
    method _broadcastState (line 182) | _broadcastState() {
    method _sendState (line 189) | _sendState(id: string) {
    method _notRecognized (line 206) | _notRecognized(id: string) {
    method _ack (line 211) | _ack(id: string) {
    method _gameFull (line 216) | _gameFull(id: string) {
    method _isPlayerKnown (line 221) | _isPlayerKnown(id: string) {
    method _addPlayer (line 228) | _addPlayer({ name }: { name: string }, publicKeyAsHex: string) {
    method _broadcastPlayerList (line 246) | _broadcastPlayerList() {
    method _markOnline (line 259) | _markOnline(uid: string) {
    method serialize (line 271) | serialize() {

FILE: client/web/pinochle/app/game/networking/host/game-round.ts
  type SerializedRound (line 18) | type SerializedRound = {
  class GameRound (line 30) | class GameRound {
    method loadFrom (line 31) | static loadFrom(players: Record<string, PlayerInfo>, data: SerializedR...
    method constructor (line 43) | constructor(protected playersById: Record<string, PlayerInfo>, state?:...
    method context (line 77) | get context() {
    method currentPlayer (line 81) | get currentPlayer() {
    method info (line 85) | get info() {
    method stateForPlayer (line 97) | stateForPlayer(id: string) {
    method bid (line 115) | bid({ bid }: Pick<Bid, 'bid'>) {
    method toJSON (line 126) | toJSON() {

FILE: client/web/pinochle/app/game/networking/host/game-state.ts
  type Bid (line 11) | type Bid = {
  type Pass (line 15) | type Pass = { type: 'PASS' };
  type DeclareTrump (line 16) | type DeclareTrump = { type: 'DECLARE_TRUMP'; trump: Suit };
  type StartEvent (line 18) | type StartEvent = { type: 'START' } & Context;
  type Event (line 19) | type Event =
  type Context (line 37) | interface Context {
  type Schema (line 52) | interface Schema extends StateSchema<Context> {
  function didPass (line 72) | function didPass(ctx: Context) {
  function _nextPlayer (line 76) | function _nextPlayer(ctx: Pick<Context, 'currentPlayer' | 'playerOrder'>) {
  function nextPlayer (line 86) | function nextPlayer() {
  function nextBiddingPlayer (line 92) | function nextBiddingPlayer({ currentPlayer, playerOrder, bids }: Context) {
  function setTrump (line 117) | function setTrump() {
  function playersWithBids (line 121) | function playersWithBids(ctx: Context) {
  function isBiddingOver (line 133) | function isBiddingOver(ctx: Context) {
  function setBidWinnerInfo (line 141) | function setBidWinnerInfo() {
  function hasEveryoneSubmittedMeld (line 160) | function hasEveryoneSubmittedMeld() {
  function hasBlind (line 166) | function hasBlind(ctx: Context) {
  function deal (line 170) | function deal(context: Context) {
  function nextPlayerOrder (line 186) | function nextPlayerOrder(context: Context) {

FILE: client/web/pinochle/app/game/networking/host/types.ts
  type PlayerInfo (line 5) | type PlayerInfo = {
  type SerializedHost (line 14) | type SerializedHost = {

FILE: client/web/pinochle/app/game/networking/host/utils.ts
  type HasHand (line 4) | type HasHand = { hand: Card[] };
  function serializePlayer (line 6) | function serializePlayer(player: PlayerInfo) {
  function handById (line 15) | function handById(playersById: Record<string, HasHand>) {
  function unwrapObject (line 23) | function unwrapObject<T = unknown>(obj: Record<string, T>) {

FILE: client/web/pinochle/app/game/networking/types.ts
  type GuestPlayer (line 4) | type GuestPlayer = {
  type SerializablePlayer (line 12) | type SerializablePlayer = {
  type GameInfo (line 18) | type GameInfo = {
  type GameResult (line 26) | type GameResult = {
  type GameState (line 40) | type GameState = {
  type JoinMessage (line 50) | type JoinMessage = { type: 'JOIN'; name: string };
  type Syn (line 51) | type Syn = { type: 'SYN' };
  type Ack (line 52) | type Ack = { type: 'ACK' };
  type GameFull (line 53) | type GameFull = { type: 'GAME_FULL' };
  type ConnectivityCheck (line 54) | type ConnectivityCheck = { type: 'CONNECTIVITY_CHECK' };
  type Present (line 55) | type Present = { type: 'PRESENT' };
  type NotRecognized (line 56) | type NotRecognized = { type: 'NOT_RECOGNIZED' };
  type RequestState (line 57) | type RequestState = { type: 'REQUEST_STATE' };
  type Start (line 59) | type Start = { type: 'START' } & GameState;
  type UpdateForGuest (line 60) | type UpdateForGuest = { type: 'GUEST_UPDATE' } & GameState;
  type WelcomeMessage (line 61) | type WelcomeMessage = { type: 'WELCOME'; players: SerializablePlayer[] };
  type PlayCard (line 63) | type PlayCard = { type: 'PLAY_CARD'; id: string };
  type Bid (line 64) | type Bid = { type: 'BID'; bid: number };
  type DeclareTrump (line 65) | type DeclareTrump = { type: 'DECLARE_TRUMP'; trump: Suit };
  type DeclareMeld (line 66) | type DeclareMeld = { type: 'DECLARE_MELD'; meld: unknown };
  type FromHostMessage (line 68) | type FromHostMessage =
  type FromGuestMessage (line 77) | type FromGuestMessage =
  type GameMessage (line 87) | type GameMessage = FromHostMessage | FromGuestMessage;

FILE: client/web/pinochle/app/game/trick.ts
  constant POINTS (line 3) | const POINTS = ['king', 'ace', 10];
  class Trick (line 5) | class Trick {
    method from (line 8) | static from(stack: Card[]) {
    method constructor (line 18) | constructor(public maxSize: number) {}
    method points (line 20) | get points() {
    method suit (line 24) | get suit() {
    method last (line 28) | get last() {
    method isEmpty (line 32) | get isEmpty() {
    method add (line 36) | add(card: Card) {

FILE: client/web/pinochle/app/game/utils/move-validation.ts
  function isValidMove (line 15) | function isValidMove(trick: Trick, card: Card, trump: Suit) {
  function availableMoves (line 19) | function availableMoves(trick: Trick, hand: Card[], trump: Suit) {

FILE: client/web/pinochle/app/helpers/and.ts
  function and (line 1) | function and<T = unknown>(a: T, b: T) {

FILE: client/web/pinochle/app/helpers/contains.ts
  type PositionalArgs (line 3) | type PositionalArgs = [unknown[], unknown];
  function contains (line 5) | function contains([list, element]: PositionalArgs /*, hash*/) {

FILE: client/web/pinochle/app/helpers/english-list.ts
  function englishList (line 1) | function englishList(list: string[]) {

FILE: client/web/pinochle/app/helpers/eq.ts
  type PositionalParams (line 3) | type PositionalParams = unknown[];
  function eq (line 5) | function eq([a, b]: PositionalParams /*, hash*/) {

FILE: client/web/pinochle/app/helpers/is-number.ts
  type PositionalParams (line 3) | type PositionalParams = [unknown];
  function isNumber (line 5) | function isNumber([maybe]: PositionalParams /*, hash*/) {

FILE: client/web/pinochle/app/helpers/not.ts
  function not (line 1) | function not<T = unknown>([element]: T[]) {

FILE: client/web/pinochle/app/helpers/or.ts
  function or (line 1) | function or<T = unknown>(...elements: T[]) {

FILE: client/web/pinochle/app/helpers/suit-to-symbol.ts
  constant NAME_MAP (line 3) | const NAME_MAP = {
  function suitToSymbol (line 10) | function suitToSymbol(name: Suit) {

FILE: client/web/pinochle/app/modifiers/fit-text.ts
  type Args (line 7) | type Args = {
  class FitTextModifier (line 12) | class FitTextModifier extends Modifier<Args> {
    method didInstall (line 13) | didInstall() {
    method willRemove (line 18) | willRemove() {
    method resizeText (line 23) | resizeText() {
    method _resizeText (line 28) | _resizeText() {

FILE: client/web/pinochle/app/modifiers/resize.ts
  type Args (line 6) | type Args = {
  class ResizeModifier (line 11) | class ResizeModifier extends Modifier<Args> {
    method didInstall (line 12) | didInstall() {
    method willRemove (line 16) | willRemove() {
    method callback (line 21) | callback() {
    method _callback (line 26) | _callback() {

FILE: client/web/pinochle/app/modifiers/stack.ts
  type Args (line 8) | type Args = {
  class StackModifier (line 17) | class StackModifier extends Modifier<Args> {
    method didInstall (line 18) | didInstall() {
    method stack (line 23) | stack() {

FILE: client/web/pinochle/app/router.ts
  class Router (line 5) | class Router extends EmberRouter {

FILE: client/web/pinochle/app/routes/game.ts
  type Transition (line 8) | type Transition = ReturnType<RouterService['transitionTo']>;
  type Params (line 10) | interface Params {
  class GameRoute (line 23) | class GameRoute extends Route {
    method beforeModel (line 28) | async beforeModel(transition: Transition) {
    method model (line 45) | async model(params: Params) {
    method afterModel (line 58) | async afterModel() {

FILE: client/web/pinochle/app/routes/join.ts
  type Transition (line 8) | type Transition = ReturnType<RouterService['transitionTo']>;
  type Params (line 10) | interface Params {
  class JoinRoute (line 14) | class JoinRoute extends Route {
    method beforeModel (line 18) | async beforeModel(transition: Transition) {
    method model (line 35) | async model(params: Params) {

FILE: client/web/pinochle/app/services/game-manager.ts
  class GameManager (line 17) | class GameManager extends Service {
    method createHost (line 24) | async createHost(keys?: KeyPair) {
    method connectToHost (line 34) | async connectToHost(publicKeyAsHex: string, keys?: KeyPair) {
    method storeAll (line 44) | storeAll() {
    method loadHosts (line 63) | async loadHosts() {
    method loadGuests (line 76) | async loadGuests() {
    method loadHost (line 89) | async loadHost(id: string) {
    method _loadHosts (line 115) | async _loadHosts() {
    method _loadGuests (line 123) | async _loadGuests() {
  type Registry (line 152) | interface Registry {
  function loadWithDefault (line 157) | function loadWithDefault<T>(key: string, defaultValue?: T) {
  function store (line 167) | function store<T>(key: string, value: T) {

FILE: client/web/pinochle/app/services/guest/dispatcher.ts
  class GuestDispatcher (line 3) | class GuestDispatcher extends Service {}
  type Registry (line 7) | interface Registry {

FILE: client/web/pinochle/app/services/guest/handler.ts
  class GuestMessageHandler (line 10) | class GuestMessageHandler extends Service {
  type Registry (line 50) | interface Registry {

FILE: client/web/pinochle/app/services/player-info.ts
  class PlayerInfo (line 5) | class PlayerInfo extends Service {
  type Registry (line 11) | interface Registry {

FILE: client/web/pinochle/app/utils/array.ts
  function prev (line 1) | function prev<T>(arr: T[], value: T) {
  function next (line 10) | function next<T>(arr: T[], value: T) {

FILE: client/web/pinochle/app/utils/container.ts
  function isDestroyed (line 8) | function isDestroyed(context: object) {

FILE: client/web/pinochle/app/utils/dom.ts
  function isHTMLElement (line 7) | function isHTMLElement(

FILE: client/web/pinochle/app/utils/trig.ts
  type XYPoint (line 1) | type XYPoint = { x: number; y: number };
  function degreesToRadians (line 3) | function degreesToRadians(degrees: number) {
  function radiansToDegrees (line 7) | function radiansToDegrees(radians: number) {
  function circleFromThreePoints (line 16) | function circleFromThreePoints(p1: XYPoint, p2: XYPoint, p3: XYPoint) {

FILE: client/web/pinochle/app/utils/use-machine.ts
  constant INTERPRETER (line 22) | const INTERPRETER = Symbol('interpreter');
  constant CONFIG (line 23) | const CONFIG = Symbol('config');
  constant MACHINE (line 24) | const MACHINE = Symbol('machine');
  constant ERROR_CANT_RECONFIGURE (line 26) | const ERROR_CANT_RECONFIGURE = `Cannot re-invoke withContext after the i...
  constant ERROR_CHART_MISSING (line 27) | const ERROR_CHART_MISSING = `A statechart was not passed`;
  type Args (line 29) | type Args<Context, Schema extends StateSchema, Event extends EventObject...
  type SendArgs (line 40) | type SendArgs<Context, Schema extends StateSchema, Event extends EventOb...
  class Statechart (line 59) | class Statechart<
    method value (line 73) | get value(): {
    method withContext (line 109) | protected withContext(context?: Context) {
    method withConfig (line 120) | protected withConfig(config?: Partial<MachineOptions<Context, Event>>) {
    method onTransition (line 136) | protected onTransition(fn?: StateListener<Context, Event, Schema, Type...
    method [CONFIG] (line 152) | private get [CONFIG]() {
    method send (line 157) | send(...args: SendArgs<Context, Schema, Event>) {
    method _setupMachine (line 162) | private _setupMachine() {
    method setup (line 198) | protected setup() {
    method teardown (line 207) | protected teardown() {

FILE: client/web/pinochle/tests/-pages/join.ts
  class NameEntryPage (line 7) | class NameEntryPage extends PageObject {
    method typeName (line 8) | typeName(name: string) {
    method submit (line 14) | submit() {
  class JoinPage (line 28) | class JoinPage extends PageObject {
    method waitFor (line 37) | async waitFor(url: string) {
    method joinGame (line 43) | async joinGame(gameId: string, name?: string) {
    method submit (line 57) | async submit(name: string) {
    method rejoin (line 62) | async rejoin(gameId: string) {
    method typeName (line 78) | typeName(name: string) {
    method submitName (line 81) | submitName() {

FILE: client/web/pinochle/tests/helpers/index.ts
  function setupGameHost (line 11) | function setupGameHost(hooks: NestedHooks, onDone: (host: GameHost) => v...
  function createHost (line 30) | async function createHost() {
  function setupPlayer (line 43) | function setupPlayer(hooks: NestedHooks, host: GameHost, name: string) {
  function addPlayerToHost (line 55) | async function addPlayerToHost(host: GameHost, name?: string) {
  function clearGuests (line 66) | function clearGuests() {
  function clearHosts (line 76) | function clearHosts() {
  function stopConnectivityChecking (line 86) | function stopConnectivityChecking(hexId: string) {
  function setupPlayerTest (line 97) | async function setupPlayerTest(hooks: NestedHooks) {

FILE: client/web/pinochle/tests/unit/game/state-test.ts
  function debugAssert (line 13) | function debugAssert(str: string, cond: unknown): asserts cond {

FILE: client/web/pinochle/types/libraries.d.ts
  class TrackedMap (line 3) | class TrackedMap<K, V> extends Map<K, V> {}
  class TrackedWeakMap (line 4) | class TrackedWeakMap<K extends object, V> extends WeakMap<K, V> {}
  class TrackedSet (line 5) | class TrackedSet<T> extends Set<T> {}
  class TrackedWeakSet (line 6) | class TrackedWeakSet<T extends object> extends WeakSet<T> {}
  type LazyTrackedArgs (line 11) | type LazyTrackedArgs = {
  class Resource (line 18) | class Resource<Args extends LazyTrackedArgs> {

FILE: client/web/smoke-tests/helpers/start-server.js
  function startServer (line 6) | async function startServer() {

FILE: client/web/smoke-tests/page-objects/add-friend.js
  class AddFriend (line 5) | class AddFriend extends BasePageObject {
    method constructor (line 6) | constructor(host, ...args) {
    method addFriendButton (line 12) | get addFriendButton() {
    method addFriend (line 25) | async addFriend(user) {

FILE: client/web/smoke-tests/page-objects/chat.js
  class Chat (line 5) | class Chat extends BasePageObject {
    method input (line 6) | get input() {
    method sendButton (line 10) | get sendButton() {
    method messages (line 15) | get messages() {
    method sendMessage (line 24) | async sendMessage(message) {
    method waitForResponse (line 33) | async waitForResponse(user) {

FILE: client/web/smoke-tests/page-objects/login.js
  class Login (line 5) | class Login extends BasePageObject {
    method beginButton (line 6) | get beginButton() {
    method logInInsteadButton (line 10) | get logInInsteadButton() {
    method name (line 22) | get name() {
    method mnemonic (line 26) | get mnemonic() {
    method logInButton (line 33) | get logInButton() {
    method logIn (line 37) | async logIn(user) {
Condensed preview — 1168 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,401K chars).
[
  {
    "path": ".codeclimate.yml",
    "chars": 588,
    "preview": "version: 2\nplugins:\n  duplication:\n    enabled: true\n    config:\n      languages:\n        javascript:\n          mass_thr"
  },
  {
    "path": ".editorconfig",
    "chars": 368,
    "preview": "# EditorConfig helps developers define and maintain consistent\n# coding styles between different editors and IDEs\n# edit"
  },
  {
    "path": ".github/renovate.json5",
    "chars": 3738,
    "preview": "// Docs:\n// https://docs.renovatebot.com/configuration-options/\n{\n  \"extends\": [\n    \"config:base\",\n    \"github>NullVoxP"
  },
  {
    "path": ".github/workflows/web-addon-crypto.yml",
    "chars": 1782,
    "preview": "name: '@emberclear/crypto'\n\n# Inspiration:\n# https://github.com/alexdiliberto/ember-transformicons/blob/master/.github/w"
  },
  {
    "path": ".github/workflows/web-addon-encoding.yml",
    "chars": 1791,
    "preview": "name: '@emberclear/encoding'\n\n# Inspiration:\n# https://github.com/alexdiliberto/ember-transformicons/blob/master/.github"
  },
  {
    "path": ".github/workflows/web-addon-local-account.yml",
    "chars": 1810,
    "preview": "name: '@emberclear/local-account'\n\n# Inspiration:\n# https://github.com/alexdiliberto/ember-transformicons/blob/master/.g"
  },
  {
    "path": ".github/workflows/web-addon-networking.yml",
    "chars": 1798,
    "preview": "name: '@emberclear/networking'\n\n# Inspiration:\n# https://github.com/alexdiliberto/ember-transformicons/blob/master/.gith"
  },
  {
    "path": ".github/workflows/web-addon-test-helpers.yml",
    "chars": 1806,
    "preview": "name: '@emberclear/test-helpers'\n\n# Inspiration:\n# https://github.com/alexdiliberto/ember-transformicons/blob/master/.gi"
  },
  {
    "path": ".github/workflows/web-addon-tracked-local-storage.yml",
    "chars": 2408,
    "preview": "name: 'ember-tracked-local-storage'\n\n# Inspiration:\n# https://github.com/alexdiliberto/ember-transformicons/blob/master/"
  },
  {
    "path": ".github/workflows/web-addon-ui.yml",
    "chars": 1241,
    "preview": "name: 'Web @emberclear/ui'\non:\n  pull_request:\n    branches: [master]\n    paths:\n    - 'client/web/addons/ui/**'\n    - '"
  },
  {
    "path": ".github/workflows/web-app-deploy.yml",
    "chars": 3684,
    "preview": "name: Web App Deploy\non:\n  push:\n    branches: [master]\n    paths:\n    - 'client/web/**'\n\nenv:\n  cwd: client/web/embercl"
  },
  {
    "path": ".github/workflows/web-app-quality.yml",
    "chars": 1483,
    "preview": "name: Web App Quality\non:\n  pull_request:\n    branches: [master]\n    paths:\n    - 'client/web/emberclear/**'\n    - 'clie"
  },
  {
    "path": ".github/workflows/web-app-tests.yml",
    "chars": 5971,
    "preview": "name: Web App Tests\non:\n  pull_request:\n    branches: [master]\n    paths:\n    - 'client/web/**'\n\nenv:\n  cwd: client/web/"
  },
  {
    "path": ".github/workflows/web-pinochle-deploy.yml",
    "chars": 3227,
    "preview": "name: Web Pinochle Deploy\non:\n  push:\n    branches: [master]\n    paths:\n    - 'client/web/pinochle/**'\n    - '.github/wo"
  },
  {
    "path": ".github/workflows/web-pinochle-quality.yml",
    "chars": 1357,
    "preview": "name: Web Pinochle Quality\non:\n  pull_request:\n    branches: [master]\n    paths:\n    - 'client/web/pinochle/**'\n    - 'c"
  },
  {
    "path": ".github/workflows/web-pinochle-tests.yml",
    "chars": 6096,
    "preview": "name: Web Pinochle Tests\non:\n  pull_request:\n    branches: [master]\n    paths:\n    - 'client/web/pinochle/**'\n\nenv:\n  cw"
  },
  {
    "path": ".github/workflows/web-smoke-tests.yml",
    "chars": 1161,
    "preview": "name: Web Smoke Tests\non:\n  pull_request:\n    branches: [master]\n    paths:\n    - 'client/web/smoke-tests/**'\n    - 'cli"
  },
  {
    "path": ".gitignore",
    "chars": 222,
    "preview": "node_modules\ndeclarations/\ntmp\ndist\n_build\ndeps\n*.log\n.idea/\n.DS_Store\n\nclient/keystore.jks\nclient/upload_certificate.pe"
  },
  {
    "path": ".gitmodules",
    "chars": 127,
    "preview": "[submodule \"relays/phoenix-relay\"]\n\tpath = relays/phoenix-relay\n\turl = https://github.com/NullVoxPopuli/mesh-relay-phoen"
  },
  {
    "path": ".sonarcloud.properties",
    "chars": 35,
    "preview": "sonar.exclusions=**/*-test.{ts,js}\n"
  },
  {
    "path": ".vscode/launch.json",
    "chars": 1094,
    "preview": "{\n    // Use IntelliSense to learn about possible attributes.\n    // Hover to view descriptions of existing attributes.\n"
  },
  {
    "path": ".whitesource",
    "chars": 138,
    "preview": "{\n  \"checkRunSettings\": {\n    \"vulnerableCheckRunConclusionLevel\": \"failure\"\n  },\n  \"issueSettings\": {\n    \"minSeverityL"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 1112,
    "preview": "## Change Log\n\n### 2019-01\n \n - Bugfix: configurable relays did not correctly implement relay selection during app boot\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 662,
    "preview": "# Contributing\n\n## Building\nemberclear can be built and run with\n```\ncd client/web/emberclear\nyarn install\nyarn start:de"
  },
  {
    "path": "LICENSE",
    "chars": 34111,
    "preview": "\nGNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007\n\nCopyright (C) 2007 Free Software Foundation, Inc.\n\nEveryone is perm"
  },
  {
    "path": "README.md",
    "chars": 2117,
    "preview": "# [emberclear](https://emberclear.io)\n\nemberclear is published at: https://emberclear.io\nand can be run locally with doc"
  },
  {
    "path": "benchmarks/crypto/.babelrc.js",
    "chars": 400,
    "preview": "module.exports = {\n  presets: [\n    ['@babel/env', {\n      targets: {\n        node: '10'\n      }\n    }],\n    '@babel/pre"
  },
  {
    "path": "benchmarks/crypto/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "benchmarks/crypto/package.json",
    "chars": 1126,
    "preview": "{\n  \"name\": \"crypto-benchmarks\",\n  \"version\": \"1.0.0\",\n  \"main\": \"index.js\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"bui"
  },
  {
    "path": "benchmarks/crypto/run",
    "chars": 40,
    "preview": "#!/bin/bash\n\nyarn\nyarn build\nyarn start\n"
  },
  {
    "path": "benchmarks/crypto/src/bench/base64.ts",
    "chars": 680,
    "preview": "import { Suite } from \"asyncmark\";\nimport libsodiumWrapper from \"libsodium-wrappers\";\n\nimport * as jsNaCl from \"../lib/j"
  },
  {
    "path": "benchmarks/crypto/src/bench/hex.ts",
    "chars": 1066,
    "preview": "import { Suite } from \"asyncmark\";\nimport libsodiumWrapper from \"libsodium-wrappers\";\n\nimport * as jsNaCl from \"../lib/j"
  },
  {
    "path": "benchmarks/crypto/src/bench/key-generation.ts",
    "chars": 572,
    "preview": "import { Suite } from 'asyncmark';\n\nimport * as libsodiumjs from '../lib/libsodium';\nimport * as tweetNaCl from  '../lib"
  },
  {
    "path": "benchmarks/crypto/src/bench/nonce-generation.ts",
    "chars": 556,
    "preview": "import { Suite } from 'asyncmark';\n\nimport * as libsodiumjs from '../lib/libsodium';\nimport * as tweetNaCl from  '../lib"
  },
  {
    "path": "benchmarks/crypto/src/bench/round-trip-long.ts",
    "chars": 7398,
    "preview": "import { Suite } from 'asyncmark';\nimport libsodiumWrapper from 'libsodium-wrappers';\n\nimport { fromString } from '../ut"
  },
  {
    "path": "benchmarks/crypto/src/bench/round-trip.ts",
    "chars": 684,
    "preview": "import { Suite } from \"asyncmark\";\nimport libsodiumWrapper from \"libsodium-wrappers\";\n\nimport * as jsNaCl from \"../lib/j"
  },
  {
    "path": "benchmarks/crypto/src/bench/stringConvension.ts",
    "chars": 855,
    "preview": "import { Suite } from \"asyncmark\";\nimport libsodiumWrapper from \"libsodium-wrappers\";\n\nimport * as jsNaCl from \"../lib/j"
  },
  {
    "path": "benchmarks/crypto/src/index.ts",
    "chars": 864,
    "preview": "import { roundTrip } from './bench/round-trip';\nimport { keyGeneration } from './bench/key-generation';\nimport { nonceGe"
  },
  {
    "path": "benchmarks/crypto/src/lib/js-nacl.ts",
    "chars": 2108,
    "preview": "\nimport NaClFactory, { Nacl } from 'js-nacl';\n\nimport { concat } from '../utils';\n\n\nexport let nacl: Nacl;\nexport functi"
  },
  {
    "path": "benchmarks/crypto/src/lib/libsodium.ts",
    "chars": 3192,
    "preview": "import libsodiumWrapper, { KeyPair } from 'libsodium-wrappers';\n\nimport { concat } from '../utils';\n\nexport async functi"
  },
  {
    "path": "benchmarks/crypto/src/lib/round-trip-implementations.ts",
    "chars": 1781,
    "preview": "import * as libsodiumjs from \"../lib/libsodium\";\nimport * as tweetNaCl from \"../lib/tweet-nacl\";\nimport * as jsNaCl from"
  },
  {
    "path": "benchmarks/crypto/src/lib/tweet-nacl.ts",
    "chars": 1882,
    "preview": "import * as nacl from 'tweetnacl';\nimport * as utils from 'tweetnacl-util';\n\nimport { concat } from '../utils';\n\nexport "
  },
  {
    "path": "benchmarks/crypto/src/lib/utils.ts",
    "chars": 721,
    "preview": "import * as libsodumFns from './libsodium';\nimport * as tweetnaclFns from './tweet-nacl';\nimport * as jsNaclFns from './"
  },
  {
    "path": "benchmarks/crypto/src/utils.ts",
    "chars": 628,
    "preview": "import libsodiumWrapper from 'libsodium-wrappers';\n\nexport async function wrapCatch(task) {\n  try {\n    await task();\n  "
  },
  {
    "path": "benchmarks/crypto/tsconfig.json",
    "chars": 828,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"allowJs\": true,\n    \"experimentalDecorators\": true,\n    \"moduleRes"
  },
  {
    "path": "benchmarks/emoji-replace/.babelrc.js",
    "chars": 400,
    "preview": "module.exports = {\n  presets: [\n    ['@babel/env', {\n      targets: {\n        node: '10'\n      }\n    }],\n    '@babel/pre"
  },
  {
    "path": "benchmarks/emoji-replace/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "benchmarks/emoji-replace/package.json",
    "chars": 1037,
    "preview": "{\n  \"name\": \"emoji-replace-benchmarks\",\n  \"version\": \"1.0.0\",\n  \"main\": \"index.js\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n "
  },
  {
    "path": "benchmarks/emoji-replace/run",
    "chars": 40,
    "preview": "#!/bin/bash\n\nyarn\nyarn build\nyarn start\n"
  },
  {
    "path": "benchmarks/emoji-replace/src/bench/-utils.ts",
    "chars": 1845,
    "preview": "import { Suite } from \"asyncmark\";\nimport { unicode } from \"emojis\";\n\nexport function assertEq<T>(expected: T, actual: T"
  },
  {
    "path": "benchmarks/emoji-replace/src/bench/long.ts",
    "chars": 1226,
    "preview": "import { generateEmojisBench } from \"./-utils\";\n\nconst benchName = \"long\";\nconst originalString = `\n  I :heart: the :scr"
  },
  {
    "path": "benchmarks/emoji-replace/src/bench/micro.ts",
    "chars": 223,
    "preview": "import { generateEmojisBench } from \"./-utils\";\n\nconst originalString = \":scream:\";\nconst expected = \"😱\";\nconst benchNam"
  },
  {
    "path": "benchmarks/emoji-replace/src/bench/short.ts",
    "chars": 260,
    "preview": "import { generateEmojisBench } from \"./-utils\";\n\nconst originalString = \"I :heart: the :scream: emoji.\";\nconst expected "
  },
  {
    "path": "benchmarks/emoji-replace/src/index.ts",
    "chars": 398,
    "preview": "import { bench as short } from \"./bench/short\";\nimport { bench as micro } from \"./bench/micro\";\nimport { bench as long }"
  },
  {
    "path": "benchmarks/emoji-replace/tsconfig.json",
    "chars": 828,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"allowJs\": true,\n    \"experimentalDecorators\": true,\n    \"moduleRes"
  },
  {
    "path": "benchmarks/emoji-replace/types/emojis.d.ts",
    "chars": 93,
    "preview": "export function unicode(input: string): string;\nexport function html(input: string): string;\n"
  },
  {
    "path": "client/android-wrapper/.gitignore",
    "chars": 1256,
    "preview": "# Built application files\n*.apk\n*.ap_\n*.aab\n\n# Files for the ART/Dalvik VM\n*.dex\n\n# Java class files\n*.class\n\n# Generate"
  },
  {
    "path": "client/android-wrapper/CONTRIBUTING.md",
    "chars": 1643,
    "preview": "# How to become a contributor and submit your own code\n\n## Contributor License Agreements\n\nWe'd love to accept your samp"
  },
  {
    "path": "client/android-wrapper/LICENSE",
    "chars": 10141,
    "preview": "\n                                 Apache License\n                           Version 2.0, January 2004\n                  "
  },
  {
    "path": "client/android-wrapper/README.md",
    "chars": 2759,
    "preview": "# SVGOMG / Trusted Web Activity\n\nThis project uses the\n[Trusted Web Activities](https://developers.google.com/web/update"
  },
  {
    "path": "client/android-wrapper/app/build.gradle",
    "chars": 2613,
    "preview": "/*\n * Copyright 2019 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
  },
  {
    "path": "client/android-wrapper/app/src/main/AndroidManifest.xml",
    "chars": 2370,
    "preview": "<!--\n    Copyright 2019 Google Inc. All Rights Reserved.\n\n     Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "client/android-wrapper/app/src/main/res/values/styles.xml",
    "chars": 934,
    "preview": "<!--\n    Copyright 2019 Google Inc. All Rights Reserved.\n\n     Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "client/android-wrapper/build.gradle",
    "chars": 1396,
    "preview": "/*\n * Copyright 2015 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
  },
  {
    "path": "client/android-wrapper/enable-debug.sh",
    "chars": 915,
    "preview": "#!/usr/bin/env bash\n\n#\n# Copyright 2019 Google Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "client/android-wrapper/gradle/wrapper/gradle-wrapper.properties",
    "chars": 232,
    "preview": "#Mon Feb 18 11:18:13 EST 2019\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
  },
  {
    "path": "client/android-wrapper/gradle/wrapper/gradle.properties",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "client/android-wrapper/gradle.properties",
    "chars": 178,
    "preview": "MYAPP_RELEASE_STORE_FILE=appmaker.keystore\nMYAPP_RELEASE_KEY_ALIAS=appmaker-store-Uy9EZlEN6ZDfet5g0KRX\nMYAPP_RELEASE_STO"
  },
  {
    "path": "client/android-wrapper/gradlew",
    "chars": 5296,
    "preview": "#!/usr/bin/env sh\n\n##############################################################################\n##\n##  Gradle start up"
  },
  {
    "path": "client/android-wrapper/gradlew.bat",
    "chars": 2176,
    "preview": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem "
  },
  {
    "path": "client/android-wrapper/settings.gradle",
    "chars": 15,
    "preview": "include ':app'\n"
  },
  {
    "path": "client/web/.eslintignore",
    "chars": 109,
    "preview": "**/declarations/\n**/concat-stats-for/\n**/dist/\n**/tmp/\n/node_modules/\n**/node_modules/\n**/public/\n**/vendor/\n"
  },
  {
    "path": "client/web/.eslintrc.js",
    "chars": 111,
    "preview": "'use strict';\n\nconst { configs } = require('@nullvoxpopuli/eslint-configs');\n\nmodule.exports = configs.node();\n"
  },
  {
    "path": "client/web/.gitignore",
    "chars": 50,
    "preview": ".eslintcache\n.stylelintcache\ntsconfig.tsbuildinfo\n"
  },
  {
    "path": "client/web/.prettierignore",
    "chars": 60,
    "preview": "**/blueprints/*/files/**/*.js\n**/bip39/wordlists/english.ts\n"
  },
  {
    "path": "client/web/.prettierrc.js",
    "chars": 188,
    "preview": "'use strict';\n\nmodule.exports = {\n  singleQuote: true,\n  trailingComma: 'es5',\n  printWidth: 100,\n  semi: true,\n  bracke"
  },
  {
    "path": "client/web/.stylelintignore",
    "chars": 208,
    "preview": "# Projects without CSS\nsmoke-tests/\n\n# Ignore supporting directories to improve scan time\n**/concat-stats-for/**\n**/dumm"
  },
  {
    "path": "client/web/.template-lintrc.js",
    "chars": 80,
    "preview": "'use strict';\n\nmodule.exports = require('@emberclear/config/.template-lintrc');\n"
  },
  {
    "path": "client/web/.vim/coc-settings.json",
    "chars": 293,
    "preview": "{\n  \"cSpell.words\": [\n    \"Encryptable\",\n    \"Parallelizable\",\n    \"REFAN\",\n    \"REFLAT\",\n    \"Serializable\",\n    \"Synth"
  },
  {
    "path": "client/web/.vscode/settings.json",
    "chars": 56,
    "preview": "{\n    \"typescript.tsdk\": \"node_modules/typescript/lib\"\n}"
  },
  {
    "path": "client/web/addons/crypto/.editorconfig",
    "chars": 367,
    "preview": "# EditorConfig helps developers define and maintain consistent\n# coding styles between different editors and IDEs\n# edit"
  },
  {
    "path": "client/web/addons/crypto/.ember-cli",
    "chars": 280,
    "preview": "{\n  /**\n    Ember CLI sends analytics information by default. The data is completely\n    anonymous, but there are times "
  },
  {
    "path": "client/web/addons/crypto/.eslintignore",
    "chars": 297,
    "preview": "# unconventional js\n/blueprints/*/files/\n/vendor/\n\n# compiled output\n/dist/\n/tmp/\n\n# TypeScript output\ndeclarations/\ntsc"
  },
  {
    "path": "client/web/addons/crypto/.eslintrc.js",
    "chars": 112,
    "preview": "'use strict';\n\nconst { configs } = require('@nullvoxpopuli/eslint-configs');\n\nmodule.exports = configs.ember();\n"
  },
  {
    "path": "client/web/addons/crypto/.gitignore",
    "chars": 425,
    "preview": "# See https://help.github.com/ignore-files/ for more about ignoring files.\n\n# compiled output\n/dist/\n/tmp/\n\n# TypeScript"
  },
  {
    "path": "client/web/addons/crypto/.npmignore",
    "chars": 411,
    "preview": "# compiled output\n/dist/\n/tmp/\n\n# dependencies\n/bower_components/\n\n# misc\n/.bowerrc\n/.editorconfig\n/.ember-cli\n/.env*\n/."
  },
  {
    "path": "client/web/addons/crypto/.template-lintrc.js",
    "chars": 80,
    "preview": "'use strict';\n\nmodule.exports = require('@emberclear/config/.template-lintrc');\n"
  },
  {
    "path": "client/web/addons/crypto/.watchmanconfig",
    "chars": 37,
    "preview": "{\n  \"ignore_dirs\": [\"tmp\", \"dist\"]\n}\n"
  },
  {
    "path": "client/web/addons/crypto/CONTRIBUTING.md",
    "chars": 621,
    "preview": "# How To Contribute\n\n## Installation\n\n* `git clone <repository-url>`\n* `cd crypto`\n* `yarn install`\n\n## Linting\n\n* `yarn"
  },
  {
    "path": "client/web/addons/crypto/LICENSE.md",
    "chars": 1066,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2020\n\nPermission is hereby granted, free of charge, to any person obtaining a copy "
  },
  {
    "path": "client/web/addons/crypto/README.md",
    "chars": 865,
    "preview": "crypto\n==============================================================================\n\n[Short description of the addon.]"
  },
  {
    "path": "client/web/addons/crypto/addon/-private/types.ts",
    "chars": 217,
    "preview": "import type { handleMessage } from '../workers/crypto/messages';\n\nexport interface WorkerLike {\n  postMessage: typeof ha"
  },
  {
    "path": "client/web/addons/crypto/addon/connector.ts",
    "chars": 3345,
    "preview": "import type { WorkersService } from '@emberclear/crypto';\nimport type { WorkerLike } from '@emberclear/crypto/-private/t"
  },
  {
    "path": "client/web/addons/crypto/addon/index.ts",
    "chars": 251,
    "preview": "export { default as CryptoConnector } from './connector';\nexport { default as WorkersService } from './services/workers'"
  },
  {
    "path": "client/web/addons/crypto/addon/services/workers.ts",
    "chars": 1650,
    "preview": "import { action } from '@ember/object';\nimport Service from '@ember/service';\n\nimport { PWBHost } from 'promise-worker-b"
  },
  {
    "path": "client/web/addons/crypto/addon/tsconfig.json",
    "chars": 375,
    "preview": "{\n  \"extends\": \"../tsconfig.compiler-options.json\",\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"declarationDir\": \".."
  },
  {
    "path": "client/web/addons/crypto/addon/types.ts",
    "chars": 675,
    "preview": "export type KeyPublic = { publicKey: Uint8Array };\nexport type KeyPrivate = { privateKey: Uint8Array };\nexport type KeyP"
  },
  {
    "path": "client/web/addons/crypto/addon/workers/crypto/actions.ts",
    "chars": 566,
    "preview": "import { naclBoxPrivateKeyFromMnemonic } from './utils/mnemonic';\nimport { derivePublicKey, generateSigningKeys } from '"
  },
  {
    "path": "client/web/addons/crypto/addon/workers/crypto/index.ts",
    "chars": 277,
    "preview": "import { PWBWorker } from 'promise-worker-bi';\n\nimport { handleMessage } from './messages';\n\nimport type { CryptoMessage"
  },
  {
    "path": "client/web/addons/crypto/addon/workers/crypto/messages.ts",
    "chars": 2611,
    "preview": "import { login } from './actions';\nimport { mnemonicFromNaClBoxPrivateKey } from './utils/mnemonic';\nimport {\n  derivePu"
  },
  {
    "path": "client/web/addons/crypto/addon/workers/crypto/utils/array.ts",
    "chars": 210,
    "preview": "export function concat(arr1: Uint8Array, arr2: Uint8Array): Uint8Array {\n  const result = new Uint8Array(arr1.length + a"
  },
  {
    "path": "client/web/addons/crypto/addon/workers/crypto/utils/bip39/wordlists/english.ts",
    "chars": 23385,
    "preview": "export const wordlist = [\n  'abandon',\n  'ability',\n  'able',\n  'about',\n  'above',\n  'absent',\n  'absorb',\n  'abstract'"
  },
  {
    "path": "client/web/addons/crypto/addon/workers/crypto/utils/bip39/wordlists/index.ts",
    "chars": 49,
    "preview": "export { wordlist as english } from './english';\n"
  },
  {
    "path": "client/web/addons/crypto/addon/workers/crypto/utils/mnemonic.ts",
    "chars": 3779,
    "preview": "import { english } from './bip39/wordlists';\nimport { genericHash } from './nacl';\n\n// https://crypto.stackexchange.com/"
  },
  {
    "path": "client/web/addons/crypto/addon/workers/crypto/utils/nacl.ts",
    "chars": 2608,
    "preview": "import { blake2b } from 'blakejs';\nimport nacl from 'tweetnacl';\n\nimport { concat } from './array';\n\nexport async functi"
  },
  {
    "path": "client/web/addons/crypto/addon/workers/crypto/utils/socket.ts",
    "chars": 1371,
    "preview": "import { decryptFrom, encryptFor } from './nacl';\nimport { fromBase64, fromHex, toBase64, toString, toUint8Array } from "
  },
  {
    "path": "client/web/addons/crypto/addon/workers/crypto/utils/string-encoding.ts",
    "chars": 1528,
    "preview": "import utils from 'tweetnacl-util';\n\nexport function toHex(array: Uint8Array): string {\n  return Array.from(array)\n    ."
  },
  {
    "path": "client/web/addons/crypto/addon-test-support/index.ts",
    "chars": 1005,
    "preview": "import { getContext } from '@ember/test-helpers';\n\nimport { CryptoConnector } from '@emberclear/crypto';\nimport { toHex "
  },
  {
    "path": "client/web/addons/crypto/addon-test-support/setup.ts",
    "chars": 958,
    "preview": "import WorkersService, { CRYPTO_PATH } from '@emberclear/crypto/services/workers';\nimport { handleMessage } from '@ember"
  },
  {
    "path": "client/web/addons/crypto/addon-test-support/tsconfig.json",
    "chars": 427,
    "preview": "{\n  \"extends\": \"../tsconfig.compiler-options.json\",\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"declarationDir\": \".."
  },
  {
    "path": "client/web/addons/crypto/app/services/workers.ts",
    "chars": 63,
    "preview": "export { default } from '@emberclear/crypto/services/workers';\n"
  },
  {
    "path": "client/web/addons/crypto/config/ember-try.js",
    "chars": 1686,
    "preview": "'use strict';\n\nconst getChannelURL = require('ember-source-channel-url');\n\nmodule.exports = async function () {\n  return"
  },
  {
    "path": "client/web/addons/crypto/config/environment.js",
    "chars": 90,
    "preview": "'use strict';\n\nmodule.exports = function (/* environment, appConfig */) {\n  return {};\n};\n"
  },
  {
    "path": "client/web/addons/crypto/ember-cli-build.js",
    "chars": 566,
    "preview": "'use strict';\n\nconst EmberAddon = require('ember-cli/lib/broccoli/ember-addon');\n\nmodule.exports = function (defaults) {"
  },
  {
    "path": "client/web/addons/crypto/index.js",
    "chars": 735,
    "preview": "'use strict';\n\nconst path = require('path');\nconst os = require('os');\nconst fs = require('fs');\n\nconst Funnel = require"
  },
  {
    "path": "client/web/addons/crypto/lib/worker-build.js",
    "chars": 1147,
    "preview": "'use strict';\n\nconst path = require('path');\nconst fs = require('fs');\nconst esbuild = require('esbuild');\n\nconst addonF"
  },
  {
    "path": "client/web/addons/crypto/package.json",
    "chars": 2510,
    "preview": "{\n  \"name\": \"@emberclear/crypto\",\n  \"version\": \"0.0.0\",\n  \"description\": \"Crypto workers for emberclear-related projects"
  },
  {
    "path": "client/web/addons/crypto/testem.js",
    "chars": 70,
    "preview": "'use strict';\n\nmodule.exports = require('@emberclear/config/testem');\n"
  },
  {
    "path": "client/web/addons/crypto/tests/dummy/app/app.ts",
    "chars": 389,
    "preview": "import Application from '@ember/application';\n\nimport config from 'dummy/config/environment';\nimport loadInitializers fr"
  },
  {
    "path": "client/web/addons/crypto/tests/dummy/app/components/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "client/web/addons/crypto/tests/dummy/app/config/environment.d.ts",
    "chars": 446,
    "preview": "export default config;\n\n/**\n * Type declarations for\n *    import config from './config/environment'\n *\n * For now these"
  },
  {
    "path": "client/web/addons/crypto/tests/dummy/app/controllers/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "client/web/addons/crypto/tests/dummy/app/helpers/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "client/web/addons/crypto/tests/dummy/app/index.html",
    "chars": 684,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n   "
  },
  {
    "path": "client/web/addons/crypto/tests/dummy/app/models/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "client/web/addons/crypto/tests/dummy/app/router.js",
    "chars": 241,
    "preview": "import EmberRouter from '@ember/routing/router';\n\nimport config from 'dummy/config/environment';\n\nexport default class R"
  },
  {
    "path": "client/web/addons/crypto/tests/dummy/app/routes/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "client/web/addons/crypto/tests/dummy/app/styles/app.css",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "client/web/addons/crypto/tests/dummy/app/templates/application.hbs",
    "chars": 10,
    "preview": "{{outlet}}"
  },
  {
    "path": "client/web/addons/crypto/tests/dummy/config/ember-cli-update.json",
    "chars": 424,
    "preview": "{\n  \"schemaVersion\": \"1.0.0\",\n  \"packages\": [\n    {\n      \"name\": \"ember-cli\",\n      \"version\": \"3.21.2\",\n      \"bluepri"
  },
  {
    "path": "client/web/addons/crypto/tests/dummy/config/environment.js",
    "chars": 1242,
    "preview": "'use strict';\n\nmodule.exports = function (environment) {\n  let ENV = {\n    modulePrefix: 'dummy',\n    environment,\n    r"
  },
  {
    "path": "client/web/addons/crypto/tests/dummy/config/optional-features.json",
    "chars": 154,
    "preview": "{\n  \"application-template-wrapper\": false,\n  \"default-async-observers\": true,\n  \"jquery-integration\": false,\n  \"template"
  },
  {
    "path": "client/web/addons/crypto/tests/dummy/config/targets.js",
    "chars": 305,
    "preview": "'use strict';\n\nconst browsers = ['last 1 Chrome versions', 'last 1 Firefox versions', 'last 1 Safari versions'];\n\nconst "
  },
  {
    "path": "client/web/addons/crypto/tests/dummy/public/robots.txt",
    "chars": 51,
    "preview": "# http://www.robotstxt.org\nUser-agent: *\nDisallow:\n"
  },
  {
    "path": "client/web/addons/crypto/tests/helpers/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "client/web/addons/crypto/tests/index.html",
    "chars": 1045,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n   "
  },
  {
    "path": "client/web/addons/crypto/tests/integration/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "client/web/addons/crypto/tests/test-helper.ts",
    "chars": 235,
    "preview": "import { setApplication } from '@ember/test-helpers';\nimport { start } from 'ember-qunit';\n\nimport Application from 'dum"
  },
  {
    "path": "client/web/addons/crypto/tests/tsconfig.json",
    "chars": 695,
    "preview": "{\n  \"extends\": \"../tsconfig.compiler-options.json\",\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    // Question: what's t"
  },
  {
    "path": "client/web/addons/crypto/tests/unit/services/workers-test.js",
    "chars": 326,
    "preview": "import { module, test } from 'qunit';\nimport { setupTest } from 'ember-qunit';\n\nmodule('Unit | Service | workers', funct"
  },
  {
    "path": "client/web/addons/crypto/tests/workers/crypto/mnemonic-test.ts",
    "chars": 3252,
    "preview": "import { module, test } from 'qunit';\n\nimport { samplePrivateKey } from '@emberclear/crypto/test-support';\nimport {\n  mn"
  },
  {
    "path": "client/web/addons/crypto/tests/workers/crypto/nacl-test.ts",
    "chars": 3544,
    "preview": "import { module, skip, test } from 'qunit';\n\nimport * as nacl from '@emberclear/crypto/workers/crypto/utils/nacl';\n\nmodu"
  },
  {
    "path": "client/web/addons/crypto/tests/workers/crypto/string-encoding-test.ts",
    "chars": 1582,
    "preview": "import { module, test } from 'qunit';\n\nimport * as stringEncoding from '@emberclear/crypto/workers/crypto/utils/string-e"
  },
  {
    "path": "client/web/addons/crypto/tsconfig.compiler-options.json",
    "chars": 111,
    "preview": "{\n  // Alias to reduce the number of ../ in paths\n  \"extends\": \"../../config/tsconfig.compiler-options.json\"\n}\n"
  },
  {
    "path": "client/web/addons/crypto/tsconfig.json",
    "chars": 209,
    "preview": "{\n  \"files\": [],\n  \"compilerOptions\": {\n    \"composite\": true\n  },\n  \"exclude\": [\"declarations\"],\n  \"references\": [\n    "
  },
  {
    "path": "client/web/addons/crypto/types/overrides.d.ts",
    "chars": 51,
    "preview": "import '@emberclear/questionably-typed/overrides';\n"
  },
  {
    "path": "client/web/addons/crypto/vendor/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "client/web/addons/encoding/.editorconfig",
    "chars": 367,
    "preview": "# EditorConfig helps developers define and maintain consistent\n# coding styles between different editors and IDEs\n# edit"
  },
  {
    "path": "client/web/addons/encoding/.ember-cli",
    "chars": 280,
    "preview": "{\n  /**\n    Ember CLI sends analytics information by default. The data is completely\n    anonymous, but there are times "
  },
  {
    "path": "client/web/addons/encoding/.eslintignore",
    "chars": 240,
    "preview": "# unconventional js\n/blueprints/*/files/\n/vendor/\n\n# compiled output\n/dist/\n/tmp/\n\n# dependencies\n/bower_components/\n/no"
  },
  {
    "path": "client/web/addons/encoding/.eslintrc.js",
    "chars": 112,
    "preview": "'use strict';\n\nconst { configs } = require('@nullvoxpopuli/eslint-configs');\n\nmodule.exports = configs.ember();\n"
  },
  {
    "path": "client/web/addons/encoding/.gitignore",
    "chars": 369,
    "preview": "# See https://help.github.com/ignore-files/ for more about ignoring files.\n\n# compiled output\n/dist/\n/tmp/\n\n# dependenci"
  },
  {
    "path": "client/web/addons/encoding/.npmignore",
    "chars": 411,
    "preview": "# compiled output\n/dist/\n/tmp/\n\n# dependencies\n/bower_components/\n\n# misc\n/.bowerrc\n/.editorconfig\n/.ember-cli\n/.env*\n/."
  },
  {
    "path": "client/web/addons/encoding/.template-lintrc.js",
    "chars": 80,
    "preview": "'use strict';\n\nmodule.exports = require('@emberclear/config/.template-lintrc');\n"
  },
  {
    "path": "client/web/addons/encoding/.travis.yml",
    "chars": 1445,
    "preview": "---\nlanguage: node_js\nnode_js:\n  # we recommend testing addons with the same minimum supported node version as Ember CLI"
  },
  {
    "path": "client/web/addons/encoding/.watchmanconfig",
    "chars": 37,
    "preview": "{\n  \"ignore_dirs\": [\"tmp\", \"dist\"]\n}\n"
  },
  {
    "path": "client/web/addons/encoding/CONTRIBUTING.md",
    "chars": 623,
    "preview": "# How To Contribute\n\n## Installation\n\n* `git clone <repository-url>`\n* `cd encoding`\n* `yarn install`\n\n## Linting\n\n* `ya"
  },
  {
    "path": "client/web/addons/encoding/LICENSE.md",
    "chars": 1066,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2020\n\nPermission is hereby granted, free of charge, to any person obtaining a copy "
  },
  {
    "path": "client/web/addons/encoding/README.md",
    "chars": 869,
    "preview": "encoding\n==============================================================================\n\n[Short description of the addon"
  },
  {
    "path": "client/web/addons/encoding/addon/string.ts",
    "chars": 2008,
    "preview": "import QRCode from 'qrcode';\n\nexport function toHex(array: Uint8Array): string {\n  return Array.from(array)\n    .map((b)"
  },
  {
    "path": "client/web/addons/encoding/addon/tsconfig.json",
    "chars": 379,
    "preview": "{\n  \"extends\": \"../tsconfig.compiler-options.json\",\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"declarationDir\": \".."
  },
  {
    "path": "client/web/addons/encoding/config/ember-try.js",
    "chars": 1686,
    "preview": "'use strict';\n\nconst getChannelURL = require('ember-source-channel-url');\n\nmodule.exports = async function () {\n  return"
  },
  {
    "path": "client/web/addons/encoding/config/environment.js",
    "chars": 90,
    "preview": "'use strict';\n\nmodule.exports = function (/* environment, appConfig */) {\n  return {};\n};\n"
  },
  {
    "path": "client/web/addons/encoding/ember-cli-build.js",
    "chars": 566,
    "preview": "'use strict';\n\nconst EmberAddon = require('ember-cli/lib/broccoli/ember-addon');\n\nmodule.exports = function (defaults) {"
  },
  {
    "path": "client/web/addons/encoding/index.js",
    "chars": 223,
    "preview": "'use strict';\n\nmodule.exports = {\n  name: require('./package').name,\n\n  options: {\n    'ember-cli-babel': {\n      enable"
  },
  {
    "path": "client/web/addons/encoding/package.json",
    "chars": 2421,
    "preview": "{\n  \"name\": \"@emberclear/encoding\",\n  \"version\": \"0.0.0\",\n  \"description\": \"The default blueprint for ember-cli addons.\""
  },
  {
    "path": "client/web/addons/encoding/testem.js",
    "chars": 589,
    "preview": "'use strict';\n\nmodule.exports = {\n  test_page: 'tests/index.html?hidepassed',\n  disable_watching: true,\n  launch_in_ci: "
  },
  {
    "path": "client/web/addons/encoding/tests/dummy/app/app.ts",
    "chars": 389,
    "preview": "import Application from '@ember/application';\n\nimport config from 'dummy/config/environment';\nimport loadInitializers fr"
  },
  {
    "path": "client/web/addons/encoding/tests/dummy/app/components/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "client/web/addons/encoding/tests/dummy/app/config/environment.d.ts",
    "chars": 446,
    "preview": "export default config;\n\n/**\n * Type declarations for\n *    import config from './config/environment'\n *\n * For now these"
  },
  {
    "path": "client/web/addons/encoding/tests/dummy/app/controllers/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "client/web/addons/encoding/tests/dummy/app/helpers/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "client/web/addons/encoding/tests/dummy/app/index.html",
    "chars": 684,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n   "
  },
  {
    "path": "client/web/addons/encoding/tests/dummy/app/models/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "client/web/addons/encoding/tests/dummy/app/router.js",
    "chars": 241,
    "preview": "import EmberRouter from '@ember/routing/router';\n\nimport config from 'dummy/config/environment';\n\nexport default class R"
  },
  {
    "path": "client/web/addons/encoding/tests/dummy/app/routes/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "client/web/addons/encoding/tests/dummy/app/styles/app.css",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "client/web/addons/encoding/tests/dummy/app/templates/application.hbs",
    "chars": 10,
    "preview": "{{outlet}}"
  },
  {
    "path": "client/web/addons/encoding/tests/dummy/config/ember-cli-update.json",
    "chars": 424,
    "preview": "{\n  \"schemaVersion\": \"1.0.0\",\n  \"packages\": [\n    {\n      \"name\": \"ember-cli\",\n      \"version\": \"3.23.0\",\n      \"bluepri"
  },
  {
    "path": "client/web/addons/encoding/tests/dummy/config/environment.js",
    "chars": 1242,
    "preview": "'use strict';\n\nmodule.exports = function (environment) {\n  let ENV = {\n    modulePrefix: 'dummy',\n    environment,\n    r"
  },
  {
    "path": "client/web/addons/encoding/tests/dummy/config/optional-features.json",
    "chars": 154,
    "preview": "{\n  \"application-template-wrapper\": false,\n  \"default-async-observers\": true,\n  \"jquery-integration\": false,\n  \"template"
  },
  {
    "path": "client/web/addons/encoding/tests/dummy/config/targets.js",
    "chars": 305,
    "preview": "'use strict';\n\nconst browsers = ['last 1 Chrome versions', 'last 1 Firefox versions', 'last 1 Safari versions'];\n\nconst "
  },
  {
    "path": "client/web/addons/encoding/tests/dummy/public/robots.txt",
    "chars": 51,
    "preview": "# http://www.robotstxt.org\nUser-agent: *\nDisallow:\n"
  },
  {
    "path": "client/web/addons/encoding/tests/helpers/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "client/web/addons/encoding/tests/index.html",
    "chars": 1045,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n   "
  },
  {
    "path": "client/web/addons/encoding/tests/integration/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "client/web/addons/encoding/tests/test-helper.js",
    "chars": 235,
    "preview": "import { setApplication } from '@ember/test-helpers';\nimport { start } from 'ember-qunit';\n\nimport Application from 'dum"
  },
  {
    "path": "client/web/addons/encoding/tests/tsconfig.json",
    "chars": 705,
    "preview": "{\n  \"extends\": \"../tsconfig.compiler-options.json\",\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    // Question: what's t"
  },
  {
    "path": "client/web/addons/encoding/tests/unit/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "client/web/addons/encoding/tests/unit/string-test.ts",
    "chars": 1159,
    "preview": "import { module, test } from 'qunit';\n\nimport * as stringEncoding from '@emberclear/encoding/string';\n\nmodule('Unit | Ut"
  },
  {
    "path": "client/web/addons/encoding/tsconfig.compiler-options.json",
    "chars": 111,
    "preview": "{\n  // Alias to reduce the number of ../ in paths\n  \"extends\": \"../../config/tsconfig.compiler-options.json\"\n}\n"
  },
  {
    "path": "client/web/addons/encoding/tsconfig.json",
    "chars": 184,
    "preview": "{\n  \"files\": [],\n  \"compilerOptions\": {\n    \"composite\": true\n  },\n  \"references\": [\n    { \"path\": \"addon\" },\n    /* { \""
  },
  {
    "path": "client/web/addons/encoding/vendor/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "client/web/addons/local-account/.editorconfig",
    "chars": 367,
    "preview": "# EditorConfig helps developers define and maintain consistent\n# coding styles between different editors and IDEs\n# edit"
  },
  {
    "path": "client/web/addons/local-account/.ember-cli",
    "chars": 280,
    "preview": "{\n  /**\n    Ember CLI sends analytics information by default. The data is completely\n    anonymous, but there are times "
  },
  {
    "path": "client/web/addons/local-account/.eslintignore",
    "chars": 296,
    "preview": "# unconventional js\n/blueprints/*/files/\n/vendor/\n\n# compiled output\n/dist/\n/tmp/\n\n# TypeScript output\ndeclarations/\ntsc"
  },
  {
    "path": "client/web/addons/local-account/.eslintrc.js",
    "chars": 112,
    "preview": "'use strict';\n\nconst { configs } = require('@nullvoxpopuli/eslint-configs');\n\nmodule.exports = configs.ember();\n"
  },
  {
    "path": "client/web/addons/local-account/.gitignore",
    "chars": 369,
    "preview": "# See https://help.github.com/ignore-files/ for more about ignoring files.\n\n# compiled output\n/dist/\n/tmp/\n\n# dependenci"
  },
  {
    "path": "client/web/addons/local-account/.npmignore",
    "chars": 411,
    "preview": "# compiled output\n/dist/\n/tmp/\n\n# dependencies\n/bower_components/\n\n# misc\n/.bowerrc\n/.editorconfig\n/.ember-cli\n/.env*\n/."
  },
  {
    "path": "client/web/addons/local-account/.template-lintrc.js",
    "chars": 80,
    "preview": "'use strict';\n\nmodule.exports = require('@emberclear/config/.template-lintrc');\n"
  }
]

// ... and 968 more files (download for full content)

About this extraction

This page contains the full source code of the NullVoxPopuli/emberclear GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1168 files (1.2 MB), approximately 357.1k tokens, and a symbol index with 1578 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!