diff --git a/.gitignore b/.gitignore index cf637b16..ec47060a 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,8 @@ .pub-cache/ .pub/ /build/ +*.g.dart +*.gr.dart # Web related lib/generated_plugin_registrant.dart diff --git a/analysis_options.yaml b/analysis_options.yaml index b7d958af..f8dc16c8 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -7,7 +7,7 @@ # The following line activates a set of recommended lints for Flutter apps, # packages, and plugins designed to encourage good coding practices. -include: package:lints/recommended.yaml +include: package:flutter_lints/flutter.yaml analyzer: strong-mode: @@ -15,6 +15,7 @@ analyzer: implicit-dynamic: false exclude: - 'lib/**/*.g.dart' + - 'lib/**/*.gr.dart' linter: # The lint rules applied to this project can be customized in the @@ -32,6 +33,7 @@ linter: # avoid_print: false # Uncomment to disable the `avoid_print` rule prefer_single_quotes: true directives_ordering: true + use_build_context_synchronously: false # Additional information about this file can be found at # https://dart.dev/guides/language/analysis-options diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index a92fbf4c..582b1d2b 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -23,6 +23,14 @@ + + + + + + + + diff --git a/assets/raxys.png b/assets/raxys.png new file mode 100644 index 00000000..3133b792 Binary files /dev/null and b/assets/raxys.png differ diff --git a/assets/raxys_dark.png b/assets/raxys_dark.png deleted file mode 100644 index 20958051..00000000 Binary files a/assets/raxys_dark.png and /dev/null differ diff --git a/assets/raxys_light.png b/assets/raxys_light.png deleted file mode 100644 index 9d456880..00000000 Binary files a/assets/raxys_light.png and /dev/null differ diff --git a/functions/package-lock.json b/functions/package-lock.json index a27da24b..638b5255 100644 --- a/functions/package-lock.json +++ b/functions/package-lock.json @@ -24,118 +24,118 @@ } }, "node_modules/@algolia/cache-browser-local-storage": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.13.0.tgz", - "integrity": "sha512-nj1vHRZauTqP/bluwkRIgEADEimqojJgoTRCel5f6q8WCa9Y8QeI4bpDQP28FoeKnDRYa3J5CauDlN466jqRhg==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.13.1.tgz", + "integrity": "sha512-UAUVG2PEfwd/FfudsZtYnidJ9eSCpS+LW9cQiesePQLz41NAcddKxBak6eP2GErqyFagSlnVXe/w2E9h2m2ttg==", "dependencies": { - "@algolia/cache-common": "4.13.0" + "@algolia/cache-common": "4.13.1" } }, "node_modules/@algolia/cache-common": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.13.0.tgz", - "integrity": "sha512-f9mdZjskCui/dA/fA/5a+6hZ7xnHaaZI5tM/Rw9X8rRB39SUlF/+o3P47onZ33n/AwkpSbi5QOyhs16wHd55kA==" + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.13.1.tgz", + "integrity": "sha512-7Vaf6IM4L0Jkl3sYXbwK+2beQOgVJ0mKFbz/4qSxKd1iy2Sp77uTAazcX+Dlexekg1fqGUOSO7HS4Sx47ZJmjA==" }, "node_modules/@algolia/cache-in-memory": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.13.0.tgz", - "integrity": "sha512-hHdc+ahPiMM92CQMljmObE75laYzNFYLrNOu0Q3/eyvubZZRtY2SUsEEgyUEyzXruNdzrkcDxFYa7YpWBJYHAg==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.13.1.tgz", + "integrity": "sha512-pZzybCDGApfA/nutsFK1P0Sbsq6fYJU3DwIvyKg4pURerlJM4qZbB9bfLRef0FkzfQu7W11E4cVLCIOWmyZeuQ==", "dependencies": { - "@algolia/cache-common": "4.13.0" + "@algolia/cache-common": "4.13.1" } }, "node_modules/@algolia/client-account": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.13.0.tgz", - "integrity": "sha512-FzFqFt9b0g/LKszBDoEsW+dVBuUe1K3scp2Yf7q6pgHWM1WqyqUlARwVpLxqyc+LoyJkTxQftOKjyFUqddnPKA==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.13.1.tgz", + "integrity": "sha512-TFLiZ1KqMiir3FNHU+h3b0MArmyaHG+eT8Iojio6TdpeFcAQ1Aiy+2gb3SZk3+pgRJa/BxGmDkRUwE5E/lv3QQ==", "dependencies": { - "@algolia/client-common": "4.13.0", - "@algolia/client-search": "4.13.0", - "@algolia/transporter": "4.13.0" + "@algolia/client-common": "4.13.1", + "@algolia/client-search": "4.13.1", + "@algolia/transporter": "4.13.1" } }, "node_modules/@algolia/client-analytics": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.13.0.tgz", - "integrity": "sha512-klmnoq2FIiiMHImkzOm+cGxqRLLu9CMHqFhbgSy9wtXZrqb8BBUIUE2VyBe7azzv1wKcxZV2RUyNOMpFqmnRZA==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.13.1.tgz", + "integrity": "sha512-iOS1JBqh7xaL5x00M5zyluZ9+9Uy9GqtYHv/2SMuzNW1qP7/0doz1lbcsP3S7KBbZANJTFHUOfuqyRLPk91iFA==", "dependencies": { - "@algolia/client-common": "4.13.0", - "@algolia/client-search": "4.13.0", - "@algolia/requester-common": "4.13.0", - "@algolia/transporter": "4.13.0" + "@algolia/client-common": "4.13.1", + "@algolia/client-search": "4.13.1", + "@algolia/requester-common": "4.13.1", + "@algolia/transporter": "4.13.1" } }, "node_modules/@algolia/client-common": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.13.0.tgz", - "integrity": "sha512-GoXfTp0kVcbgfSXOjfrxx+slSipMqGO9WnNWgeMmru5Ra09MDjrcdunsiiuzF0wua6INbIpBQFTC2Mi5lUNqGA==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.13.1.tgz", + "integrity": "sha512-LcDoUE0Zz3YwfXJL6lJ2OMY2soClbjrrAKB6auYVMNJcoKZZ2cbhQoFR24AYoxnGUYBER/8B+9sTBj5bj/Gqbg==", "dependencies": { - "@algolia/requester-common": "4.13.0", - "@algolia/transporter": "4.13.0" + "@algolia/requester-common": "4.13.1", + "@algolia/transporter": "4.13.1" } }, "node_modules/@algolia/client-personalization": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.13.0.tgz", - "integrity": "sha512-KneLz2WaehJmNfdr5yt2HQETpLaCYagRdWwIwkTqRVFCv4DxRQ2ChPVW9jeTj4YfAAhfzE6F8hn7wkQ/Jfj6ZA==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.13.1.tgz", + "integrity": "sha512-1CqrOW1ypVrB4Lssh02hP//YxluoIYXAQCpg03L+/RiXJlCs+uIqlzC0ctpQPmxSlTK6h07kr50JQoYH/TIM9w==", "dependencies": { - "@algolia/client-common": "4.13.0", - "@algolia/requester-common": "4.13.0", - "@algolia/transporter": "4.13.0" + "@algolia/client-common": "4.13.1", + "@algolia/requester-common": "4.13.1", + "@algolia/transporter": "4.13.1" } }, "node_modules/@algolia/client-search": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.13.0.tgz", - "integrity": "sha512-blgCKYbZh1NgJWzeGf+caKE32mo3j54NprOf0LZVCubQb3Kx37tk1Hc8SDs9bCAE8hUvf3cazMPIg7wscSxspA==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.13.1.tgz", + "integrity": "sha512-YQKYA83MNRz3FgTNM+4eRYbSmHi0WWpo019s5SeYcL3HUan/i5R09VO9dk3evELDFJYciiydSjbsmhBzbpPP2A==", "dependencies": { - "@algolia/client-common": "4.13.0", - "@algolia/requester-common": "4.13.0", - "@algolia/transporter": "4.13.0" + "@algolia/client-common": "4.13.1", + "@algolia/requester-common": "4.13.1", + "@algolia/transporter": "4.13.1" } }, "node_modules/@algolia/logger-common": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.13.0.tgz", - "integrity": "sha512-8yqXk7rMtmQJ9wZiHOt/6d4/JDEg5VCk83gJ39I+X/pwUPzIsbKy9QiK4uJ3aJELKyoIiDT1hpYVt+5ia+94IA==" + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.13.1.tgz", + "integrity": "sha512-L6slbL/OyZaAXNtS/1A8SAbOJeEXD5JcZeDCPYDqSTYScfHu+2ePRTDMgUTY4gQ7HsYZ39N1LujOd8WBTmM2Aw==" }, "node_modules/@algolia/logger-console": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.13.0.tgz", - "integrity": "sha512-YepRg7w2/87L0vSXRfMND6VJ5d6699sFJBRWzZPOlek2p5fLxxK7O0VncYuc/IbVHEgeApvgXx0WgCEa38GVuQ==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.13.1.tgz", + "integrity": "sha512-7jQOTftfeeLlnb3YqF8bNgA2GZht7rdKkJ31OCeSH2/61haO0tWPoNRjZq9XLlgMQZH276pPo0NdiArcYPHjCA==", "dependencies": { - "@algolia/logger-common": "4.13.0" + "@algolia/logger-common": "4.13.1" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.13.0.tgz", - "integrity": "sha512-Dj+bnoWR5MotrnjblzGKZ2kCdQi2cK/VzPURPnE616NU/il7Ypy6U6DLGZ/ZYz+tnwPa0yypNf21uqt84fOgrg==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.13.1.tgz", + "integrity": "sha512-oa0CKr1iH6Nc7CmU6RE7TnXMjHnlyp7S80pP/LvZVABeJHX3p/BcSCKovNYWWltgTxUg0U1o+2uuy8BpMKljwA==", "dependencies": { - "@algolia/requester-common": "4.13.0" + "@algolia/requester-common": "4.13.1" } }, "node_modules/@algolia/requester-common": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.13.0.tgz", - "integrity": "sha512-BRTDj53ecK+gn7ugukDWOOcBRul59C4NblCHqj4Zm5msd5UnHFjd/sGX+RLOEoFMhetILAnmg6wMrRrQVac9vw==" + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.13.1.tgz", + "integrity": "sha512-eGVf0ID84apfFEuXsaoSgIxbU3oFsIbz4XiotU3VS8qGCJAaLVUC5BUJEkiFENZIhon7hIB4d0RI13HY4RSA+w==" }, "node_modules/@algolia/requester-node-http": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.13.0.tgz", - "integrity": "sha512-9b+3O4QFU4azLhGMrZAr/uZPydvzOR4aEZfSL8ZrpLZ7fbbqTO0S/5EVko+QIgglRAtVwxvf8UJ1wzTD2jvKxQ==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.13.1.tgz", + "integrity": "sha512-7C0skwtLdCz5heKTVe/vjvrqgL/eJxmiEjHqXdtypcE5GCQCYI15cb+wC4ytYioZDMiuDGeVYmCYImPoEgUGPw==", "dependencies": { - "@algolia/requester-common": "4.13.0" + "@algolia/requester-common": "4.13.1" } }, "node_modules/@algolia/transporter": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.13.0.tgz", - "integrity": "sha512-8tSQYE+ykQENAdeZdofvtkOr5uJ9VcQSWgRhQ9h01AehtBIPAczk/b2CLrMsw5yQZziLs5cZ3pJ3478yI+urhA==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.13.1.tgz", + "integrity": "sha512-pICnNQN7TtrcYJqqPEXByV8rJ8ZRU2hCiIKLTLRyNpghtQG3VAFk6fVtdzlNfdUGZcehSKGarPIZEHlQXnKjgw==", "dependencies": { - "@algolia/cache-common": "4.13.0", - "@algolia/logger-common": "4.13.0", - "@algolia/requester-common": "4.13.0" + "@algolia/cache-common": "4.13.1", + "@algolia/logger-common": "4.13.1", + "@algolia/requester-common": "4.13.1" } }, "node_modules/@babel/code-frame": { @@ -148,21 +148,21 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.12.tgz", - "integrity": "sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", + "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -208,13 +208,13 @@ "node_modules/@babel/highlight/node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, "node_modules/@babel/highlight/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, "engines": { "node": ">=0.8.0" @@ -223,7 +223,7 @@ "node_modules/@babel/highlight/node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, "engines": { "node": ">=4" @@ -261,30 +261,15 @@ "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/@firebase/app": { - "version": "0.7.24", - "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.7.24.tgz", - "integrity": "sha512-HIbAhayEykbCez1Rl6pmzAWbIx63Mc9+t3ngWKqZdkMnBNAAJvYaUdx7Krus7O9XHUKNw/gzBUETAEYt93jusA==", - "peer": true, - "dependencies": { - "@firebase/component": "0.5.14", - "@firebase/logger": "0.3.2", - "@firebase/util": "1.6.0", - "idb": "7.0.1", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/app-compat": { - "version": "0.1.25", - "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.1.25.tgz", - "integrity": "sha512-FdCnYwIM3R+OuRE7nrAdVT5oNlvSAHQHN1ictB/gjCFs58lXMCe0DCIRDrA7zxaOFIKeWPtx35ZNXv3EdPFNpQ==", - "peer": true, + "node_modules/@fastify/busboy": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-1.1.0.tgz", + "integrity": "sha512-Fv854f94v0CzIDllbY3i/0NJPNBRNLDawf3BTYVGCe9VrIIs3Wi7AFx24F9NzCxdf0wyx/x0Q9kEVnvDOPnlxA==", "dependencies": { - "@firebase/app": "0.7.24", - "@firebase/component": "0.5.14", - "@firebase/logger": "0.3.2", - "@firebase/util": "1.6.0", - "tslib": "^2.1.0" + "text-decoding": "^1.0.0" + }, + "engines": { + "node": ">=10.17.0" } }, "node_modules/@firebase/app-types": { @@ -302,108 +287,61 @@ } }, "node_modules/@firebase/component": { - "version": "0.5.14", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.14.tgz", - "integrity": "sha512-ct2p1MTMV5P/nGIlkC3XjAVwHwjsIZaeo8JVyDAkJCNTROu5mYX3FBK16hjIUIIVJDpgnnzFh9nP74gciL4WrA==", - "peer": true, + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.16.tgz", + "integrity": "sha512-/pkl77mN9PT7dTSzNu1CrvIvd+z1CdePnEl+VITaeSBs9Ko7ZVvSIlzQLbSwqksXX3bAHpxej0Mg6mVKQiRVSw==", "dependencies": { - "@firebase/util": "1.6.0", + "@firebase/util": "1.6.2", "tslib": "^2.1.0" } }, "node_modules/@firebase/database": { - "version": "0.12.8", - "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.12.8.tgz", - "integrity": "sha512-JBQVfFLzfhxlQbl4OU6ov9fdsddkytBQdtSSR49cz48homj38ccltAhK6seum+BI7f28cV2LFHF9672lcN+qxA==", + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.13.2.tgz", + "integrity": "sha512-wKkBD4rq6PPv9gl1hNJNpl0R0bwJmXCJfDuvotjXmTcU7kV0AIaJ45GVhULkbSCApAAFC6QUJ91oasDUO1ZVxw==", "dependencies": { "@firebase/auth-interop-types": "0.1.6", - "@firebase/component": "0.5.13", - "@firebase/logger": "0.3.2", - "@firebase/util": "1.5.2", + "@firebase/component": "0.5.16", + "@firebase/logger": "0.3.3", + "@firebase/util": "1.6.2", "faye-websocket": "0.11.4", "tslib": "^2.1.0" } }, "node_modules/@firebase/database-compat": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-0.1.8.tgz", - "integrity": "sha512-dhXr5CSieBuKNdU96HgeewMQCT9EgOIkfF1GNy+iRrdl7BWLxmlKuvLfK319rmIytSs/vnCzcD9uqyxTeU/A3A==", - "dependencies": { - "@firebase/component": "0.5.13", - "@firebase/database": "0.12.8", - "@firebase/database-types": "0.9.7", - "@firebase/logger": "0.3.2", - "@firebase/util": "1.5.2", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/@firebase/database-compat/node_modules/@firebase/component": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.13.tgz", - "integrity": "sha512-hxhJtpD8Ppf/VU2Rlos6KFCEV77TGIGD5bJlkPK1+B/WUe0mC6dTjW7KhZtXTc+qRBp9nFHWcsIORnT8liHP9w==", - "dependencies": { - "@firebase/util": "1.5.2", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/database-compat/node_modules/@firebase/database-types": { - "version": "0.9.7", - "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.9.7.tgz", - "integrity": "sha512-EFhgL89Fz6DY3kkB8TzdHvdu8XaqqvzcF2DLVOXEnQ3Ms7L755p5EO42LfxXoJqb9jKFvgLpFmKicyJG25WFWw==", - "dependencies": { - "@firebase/app-types": "0.7.0", - "@firebase/util": "1.5.2" - } - }, - "node_modules/@firebase/database-compat/node_modules/@firebase/util": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.5.2.tgz", - "integrity": "sha512-YvBH2UxFcdWG2HdFnhxZptPl2eVFlpOyTH66iDo13JPEYraWzWToZ5AMTtkyRHVmu7sssUpQlU9igy1KET7TOw==", - "dependencies": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-0.2.2.tgz", + "integrity": "sha512-3wLHJ54WHMhrveCywCMbkspshFezN07PLOIsmqELM1+pmrg3bwMj9u/o3Equ0DwmESMnchp5sMxgzdBUOextJg==", + "dependencies": { + "@firebase/component": "0.5.16", + "@firebase/database": "0.13.2", + "@firebase/database-types": "0.9.10", + "@firebase/logger": "0.3.3", + "@firebase/util": "1.6.2", "tslib": "^2.1.0" } }, "node_modules/@firebase/database-types": { - "version": "0.9.8", - "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.9.8.tgz", - "integrity": "sha512-bI7bwF5xc0nPi6Oa3JVt6JJdfhVAnEpCwgfTNILR4lYDPtxdxlRXhZzQ5lfqlCj7PR+drKh9RvMu6C24N1q04w==", + "version": "0.9.10", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.9.10.tgz", + "integrity": "sha512-2ji6nXRRsY+7hgU6zRhUtK0RmSjVWM71taI7Flgaw+BnopCo/lDF5HSwxp8z7LtiHlvQqeRA3Ozqx5VhlAbiKg==", "dependencies": { "@firebase/app-types": "0.7.0", - "@firebase/util": "1.6.0" - } - }, - "node_modules/@firebase/database/node_modules/@firebase/component": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.13.tgz", - "integrity": "sha512-hxhJtpD8Ppf/VU2Rlos6KFCEV77TGIGD5bJlkPK1+B/WUe0mC6dTjW7KhZtXTc+qRBp9nFHWcsIORnT8liHP9w==", - "dependencies": { - "@firebase/util": "1.5.2", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/database/node_modules/@firebase/util": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.5.2.tgz", - "integrity": "sha512-YvBH2UxFcdWG2HdFnhxZptPl2eVFlpOyTH66iDo13JPEYraWzWToZ5AMTtkyRHVmu7sssUpQlU9igy1KET7TOw==", - "dependencies": { - "tslib": "^2.1.0" + "@firebase/util": "1.6.2" } }, "node_modules/@firebase/logger": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.3.2.tgz", - "integrity": "sha512-lzLrcJp9QBWpo40OcOM9B8QEtBw2Fk1zOZQdvv+rWS6gKmhQBCEMc4SMABQfWdjsylBcDfniD1Q+fUX1dcBTXA==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.3.3.tgz", + "integrity": "sha512-POTJl07jOKTOevLXrTvJD/VZ0M6PnJXflbAh5J9VGkmtXPXNG6MdZ9fmRgqYhXKTaDId6AQenQ262uwgpdtO0Q==", "dependencies": { "tslib": "^2.1.0" } }, "node_modules/@firebase/util": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.6.0.tgz", - "integrity": "sha512-6+hhqb4Zzjoo12xofTDHPkgW3FnN4ydBsjd5X2KuQI268DR3W3Ld64W/gkKPZrKRgUxeNeb+pykfP3qRe7q+vA==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.6.2.tgz", + "integrity": "sha512-VYDqEf/+mS7n0nPj6qJDJYFtKIEfOaTtQeNDsd3x+xp8HWvrbygWOexzeGicLP1dvEzrKr3eQGcJmmmYN3TIsA==", "dependencies": { "tslib": "^2.1.0" } @@ -455,9 +393,9 @@ } }, "node_modules/@google-cloud/storage": { - "version": "5.19.4", - "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-5.19.4.tgz", - "integrity": "sha512-Jz7ugcPHhsEmMVvIxM9uoBsdEbKIYwDkh3u07tifsIymEWs47F4/D6+/Tv/W7kLhznqjyOjVJ/0frtBeIC0lJA==", + "version": "5.20.5", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-5.20.5.tgz", + "integrity": "sha512-lOs/dCyveVF8TkVFnFSF7IGd0CJrTm91qiK6JLu+Z8qiT+7Ag0RyVhxZIWkhiACqwABo7kSHDm8FdH8p2wxSSw==", "optional": true, "dependencies": { "@google-cloud/paginator": "^3.0.7", @@ -468,12 +406,10 @@ "async-retry": "^1.3.3", "compressible": "^2.0.12", "configstore": "^5.0.0", - "date-and-time": "^2.0.0", "duplexify": "^4.0.0", "ent": "^2.2.0", "extend": "^3.0.2", "gaxios": "^4.0.0", - "get-stream": "^6.0.0", "google-auth-library": "^7.14.1", "hash-stream-validation": "^0.2.2", "mime": "^3.0.0", @@ -481,9 +417,9 @@ "p-limit": "^3.0.1", "pumpify": "^2.0.0", "retry-request": "^4.2.2", - "snakeize": "^0.1.0", "stream-events": "^1.0.4", "teeny-request": "^7.1.3", + "uuid": "^8.0.0", "xdg-basedir": "^4.0.0" }, "engines": { @@ -504,15 +440,15 @@ } }, "node_modules/@grpc/proto-loader": { - "version": "0.6.12", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.12.tgz", - "integrity": "sha512-filTVbETFnxb9CyRX98zN18ilChTuf/C5scZ2xyaOTp0EHGq0/ufX8rjqXUcSb1Gpv7eZq4M2jDvbh9BogKnrg==", + "version": "0.6.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.13.tgz", + "integrity": "sha512-FjxPYDRTn6Ec3V0arm1FtSpmP6V50wuph2yILpyvTKzjc76oDdoihXqM1DzOW5ubvCC8GivfCnNtfaRE8myJ7g==", "optional": true, "dependencies": { "@types/long": "^4.0.1", "lodash.camelcase": "^4.3.0", "long": "^4.0.0", - "protobufjs": "^6.10.0", + "protobufjs": "^6.11.3", "yargs": "^16.2.0" }, "bin": { @@ -662,9 +598,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.28", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", - "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", + "version": "4.17.29", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.29.tgz", + "integrity": "sha512-uMd++6dMKS32EOuw1Uli3e3BPgdLIXmezcfHv7N4c1s3gkhikBplORPpMq3fuWkxncZN1reb16d5n8yhQ80x7Q==", "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -683,6 +619,14 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/jsonwebtoken": { + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.8.tgz", + "integrity": "sha512-zm6xBQpFDIDM6o9r6HSgDeIcLy82TKWctCXEPbJJcXb5AKmi5BNNdLXneixK4lplX3PqIVcwLBCGE/kAGnlD4A==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/lodash": { "version": "4.14.182", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz", @@ -701,9 +645,9 @@ "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" }, "node_modules/@types/node": { - "version": "17.0.34", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.34.tgz", - "integrity": "sha512-XImEz7XwTvDBtzlTnm8YvMqGW/ErMWBsKZ+hMTvnDIjGCKxwK5Xpc+c/oQjOauwq8M4OS11hEkpjX8rrI/eEgA==" + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.0.tgz", + "integrity": "sha512-cHlGmko4gWLVI27cGJntjs/Sj8th9aYwplmZFwmmgYQQvL5NUsgVJG7OddLvNfLqYS31KFN0s3qlaD9qCaxACA==" }, "node_modules/@types/qs": { "version": "6.9.7", @@ -936,24 +880,24 @@ } }, "node_modules/algoliasearch": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.13.0.tgz", - "integrity": "sha512-oHv4faI1Vl2s+YC0YquwkK/TsaJs79g2JFg5FDm2rKN12VItPTAeQ7hyJMHarOPPYuCnNC5kixbtcqvb21wchw==", - "dependencies": { - "@algolia/cache-browser-local-storage": "4.13.0", - "@algolia/cache-common": "4.13.0", - "@algolia/cache-in-memory": "4.13.0", - "@algolia/client-account": "4.13.0", - "@algolia/client-analytics": "4.13.0", - "@algolia/client-common": "4.13.0", - "@algolia/client-personalization": "4.13.0", - "@algolia/client-search": "4.13.0", - "@algolia/logger-common": "4.13.0", - "@algolia/logger-console": "4.13.0", - "@algolia/requester-browser-xhr": "4.13.0", - "@algolia/requester-common": "4.13.0", - "@algolia/requester-node-http": "4.13.0", - "@algolia/transporter": "4.13.0" + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.13.1.tgz", + "integrity": "sha512-dtHUSE0caWTCE7liE1xaL+19AFf6kWEcyn76uhcitWpntqvicFHXKFoZe5JJcv9whQOTRM6+B8qJz6sFj+rDJA==", + "dependencies": { + "@algolia/cache-browser-local-storage": "4.13.1", + "@algolia/cache-common": "4.13.1", + "@algolia/cache-in-memory": "4.13.1", + "@algolia/client-account": "4.13.1", + "@algolia/client-analytics": "4.13.1", + "@algolia/client-common": "4.13.1", + "@algolia/client-personalization": "4.13.1", + "@algolia/client-search": "4.13.1", + "@algolia/logger-common": "4.13.1", + "@algolia/logger-console": "4.13.1", + "@algolia/requester-browser-xhr": "4.13.1", + "@algolia/requester-common": "4.13.1", + "@algolia/requester-node-http": "4.13.1", + "@algolia/transporter": "4.13.1" } }, "node_modules/ansi-colors": { @@ -1136,7 +1080,7 @@ "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/brace-expansion": { "version": "1.1.11", @@ -1242,7 +1186,7 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, "node_modules/configstore": { @@ -1292,7 +1236,7 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "node_modules/cors": { "version": "2.8.5", @@ -1329,12 +1273,6 @@ "node": ">=8" } }, - "node_modules/date-and-time": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/date-and-time/-/date-and-time-2.3.1.tgz", - "integrity": "sha512-OaIRmSJXifwEN21rMVVDs0Kz8uhJ3wWPYd86atkRiqN54liaMQYEbbrgjZQea75YXOBWL4ZFb3rG/waenw1TEg==", - "optional": true - }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -1390,17 +1328,6 @@ "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/dicer": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.1.tgz", - "integrity": "sha512-ObioMtXnmjYs3aRtpIJt9rgQSPCIhKVkFPip+E9GUDyWl8N435znUxK/JfNwGZJ2wnn5JKQ7Ly3vOK5Q5dylGA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -1448,7 +1375,7 @@ "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/emoji-regex": { "version": "8.0.0", @@ -1459,7 +1386,7 @@ "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "engines": { "node": ">= 0.8" } @@ -1488,7 +1415,7 @@ "node_modules/ent": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==", "optional": true }, "node_modules/es-abstract": { @@ -1566,7 +1493,7 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "node_modules/escape-string-regexp": { "version": "4.0.0", @@ -1741,7 +1668,7 @@ "node_modules/eslint-plugin-import/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, "node_modules/eslint-scope": { @@ -1880,7 +1807,7 @@ "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "engines": { "node": ">= 0.6" } @@ -1946,7 +1873,7 @@ "node_modules/express/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/extend": { "version": "3.0.2", @@ -1969,13 +1896,13 @@ "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, "node_modules/fast-text-encoding": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz", - "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.4.tgz", + "integrity": "sha512-x6lDDm/tBAzX9kmsPcZsNbvDs3Zey3+scsxaZElS8xWLgUMAg/oFLeewfUz0mu1CblHhhsu15jGkraldkFh8KQ==", "optional": true }, "node_modules/faye-websocket": { @@ -2029,12 +1956,12 @@ "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", "dev": true, "dependencies": { "locate-path": "^2.0.0" @@ -2044,14 +1971,14 @@ } }, "node_modules/firebase-admin": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-10.2.0.tgz", - "integrity": "sha512-6ehn5J9UEFgi4+naqYvozmGpnZae3cJLdwSkSsDc8/Y0eTBjVMFdf9N2ft7N81UNHA0N5DknOyXhlsdAdyBLCA==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-10.3.0.tgz", + "integrity": "sha512-A0wgMLEjyVyUE+heyMJYqHRkPVjpebhOYsa47RHdrTM4ltApcx8Tn86sUmjqxlfh09gNnILAm7a8q5+FmgBYpg==", "dependencies": { - "@firebase/database-compat": "^0.1.8", + "@fastify/busboy": "^1.1.0", + "@firebase/database-compat": "^0.2.0", "@firebase/database-types": "^0.9.7", "@types/node": ">=12.12.47", - "dicer": "^0.3.0", "jsonwebtoken": "^8.5.1", "jwks-rsa": "^2.0.2", "node-forge": "^1.3.1", @@ -2066,9 +1993,9 @@ } }, "node_modules/firebase-functions": { - "version": "3.21.1", - "resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-3.21.1.tgz", - "integrity": "sha512-wUxJaUEceGpCxa+uAYTQUGM13Uc/mekWfJnhuqqPKr8S09WosoVRpoh1yVQO+AnMqNChq3psLkLxHPubW9Tg2A==", + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-3.22.0.tgz", + "integrity": "sha512-d1BxBpT95MhvVqXkpLWDvWbyuX7e2l69cFAiqG3U1XQDaMV88bM9S+Zg7H8i9pitEGFr+76ErjKgrY0n+g3ZDA==", "dependencies": { "@types/cors": "^2.8.5", "@types/express": "4.17.3", @@ -2084,7 +2011,7 @@ "node": "^8.13.0 || >=10.10.0" }, "peerDependencies": { - "firebase-admin": "^8.0.0 || ^9.0.0 || ^10.0.0" + "firebase-admin": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" } }, "node_modules/firebase-functions-test": { @@ -2118,9 +2045,9 @@ } }, "node_modules/flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz", + "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==", "dev": true }, "node_modules/forwarded": { @@ -2134,7 +2061,7 @@ "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "engines": { "node": ">= 0.6" } @@ -2142,7 +2069,7 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, "node_modules/function-bind": { @@ -2171,7 +2098,7 @@ "node_modules/functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", "devOptional": true }, "node_modules/functions-have-names": { @@ -2222,30 +2149,18 @@ } }, "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.1" + "has-symbols": "^1.0.3" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "optional": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/get-symbol-description": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", @@ -2330,9 +2245,9 @@ } }, "node_modules/google-gax": { - "version": "2.30.4", - "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-2.30.4.tgz", - "integrity": "sha512-/W4wWKjYcCXtd3Vz+ux7fN3MElbLVKGmHCCgA6kotigQgoDrLLueSvnXsck7qZaF39ooYnFhA58Rjr7RHe2heA==", + "version": "2.30.5", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-2.30.5.tgz", + "integrity": "sha512-Jey13YrAN2hfpozHzbtrwEfEHdStJh1GwaQ2+Akh1k0Tv/EuNVSuBtHZoKSBm5wBMvNsxTsEIZ/152NrYyZgxQ==", "optional": true, "dependencies": { "@grpc/grpc-js": "~1.6.0", @@ -2346,7 +2261,7 @@ "node-fetch": "^2.6.1", "object-hash": "^3.0.0", "proto3-json-serializer": "^0.1.8", - "protobufjs": "6.11.2", + "protobufjs": "6.11.3", "retry-request": "^4.0.0" }, "bin": { @@ -2480,9 +2395,9 @@ } }, "node_modules/http-parser-js": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz", - "integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==" + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" }, "node_modules/http-proxy-agent": { "version": "5.0.0", @@ -2522,12 +2437,6 @@ "node": ">=0.10.0" } }, - "node_modules/idb": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/idb/-/idb-7.0.1.tgz", - "integrity": "sha512-UUxlE7vGWK5RfB/fDwEGgRf84DY/ieqNha6msMV99UsEMQhJ1RwbCd8AYBj3QMgnE3VZnfQvm4oKVCJTYlqIgg==", - "peer": true - }, "node_modules/ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -2556,7 +2465,7 @@ "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "devOptional": true, "engines": { "node": ">=0.8.19" @@ -2565,7 +2474,7 @@ "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, "dependencies": { "once": "^1.3.0", @@ -2669,7 +2578,7 @@ "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "engines": { "node": ">=0.10.0" @@ -2811,7 +2720,7 @@ "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", "optional": true }, "node_modules/is-weakref": { @@ -2829,7 +2738,7 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, "node_modules/jose": { @@ -2883,7 +2792,7 @@ "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, "node_modules/json5": { @@ -2958,11 +2867,12 @@ } }, "node_modules/jwks-rsa": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-2.1.2.tgz", - "integrity": "sha512-QW2SNEUVvMqULiBJVsIJXSuX73Qj9il/DMCsJZsmCI8AQFZ6BjXgQW6h9wOlPr1LswQBNDdyFT2LPogwMRr1ew==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-2.1.4.tgz", + "integrity": "sha512-mpArfgPkUpX11lNtGxsF/szkasUcbWHGplZl/uFvFO2NuMHmt0dQXIihh0rkPU2yQd5niQtuUHbXnG/WKiXF6Q==", "dependencies": { "@types/express": "^4.17.13", + "@types/jsonwebtoken": "^8.5.8", "debug": "^4.3.4", "jose": "^2.0.5", "limiter": "^1.1.5", @@ -3014,7 +2924,7 @@ "node_modules/locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", "dev": true, "dependencies": { "p-locate": "^2.0.0", @@ -3032,43 +2942,43 @@ "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", "optional": true }, "node_modules/lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" }, "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" }, "node_modules/lodash.isboolean": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" }, "node_modules/lodash.isinteger": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" }, "node_modules/lodash.isnumber": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" }, "node_modules/lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" }, "node_modules/lodash.isstring": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" }, "node_modules/lodash.merge": { "version": "4.6.2", @@ -3079,12 +2989,12 @@ "node_modules/lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" }, "node_modules/lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", "dev": true }, "node_modules/long": { @@ -3117,7 +3027,7 @@ "node_modules/lru-memoizer/node_modules/lru-cache": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.2.tgz", - "integrity": "sha1-HRdnnAac2l0ECZGgnbwsDbN35V4=", + "integrity": "sha512-uQw9OqphAGiZhkuPlpFGmdTU2tEuhxTourM/19qGJrxBPHAr/f8BT1a0i/lOclESnGatdJG/UCkP9kZB/Lh1iw==", "dependencies": { "pseudomap": "^1.0.1", "yallist": "^2.0.0" @@ -3126,7 +3036,7 @@ "node_modules/lru-memoizer/node_modules/yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" }, "node_modules/make-dir": { "version": "3.1.0", @@ -3155,7 +3065,7 @@ "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "engines": { "node": ">= 0.6" } @@ -3163,12 +3073,12 @@ "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "engines": { "node": ">= 0.6" } @@ -3230,7 +3140,7 @@ "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, "node_modules/negotiator": { @@ -3271,7 +3181,7 @@ "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "engines": { "node": ">=0.10.0" } @@ -3286,9 +3196,9 @@ } }, "node_modules/object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3351,7 +3261,7 @@ "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "devOptional": true, "dependencies": { "wrappy": "1" @@ -3392,7 +3302,7 @@ "node_modules/p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", "dev": true, "dependencies": { "p-limit": "^1.1.0" @@ -3416,7 +3326,7 @@ "node_modules/p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", "dev": true, "engines": { "node": ">=4" @@ -3445,7 +3355,7 @@ "node_modules/path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", "dev": true, "engines": { "node": ">=4" @@ -3454,7 +3364,7 @@ "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, "engines": { "node": ">=0.10.0" @@ -3478,7 +3388,7 @@ "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "node_modules/prelude-ls": { "version": "1.2.1", @@ -3508,9 +3418,9 @@ } }, "node_modules/protobufjs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz", - "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==", + "version": "6.11.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz", + "integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==", "hasInstallScript": true, "optional": true, "dependencies": { @@ -3548,7 +3458,7 @@ "node_modules/pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" }, "node_modules/pump": { "version": "3.0.0", @@ -3662,7 +3572,7 @@ "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "optional": true, "engines": { "node": ">=0.10.0" @@ -3678,12 +3588,12 @@ } }, "node_modules/resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", "dev": true, "dependencies": { - "is-core-module": "^2.8.1", + "is-core-module": "^2.9.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -3813,7 +3723,7 @@ "node_modules/send/node_modules/debug/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/send/node_modules/mime": { "version": "1.6.0", @@ -3907,16 +3817,10 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/snakeize": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/snakeize/-/snakeize-0.1.0.tgz", - "integrity": "sha1-EMCI2LWOsHazIpu1oE4jLOEmQi0=", - "optional": true - }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, "node_modules/statuses": { @@ -3942,14 +3846,6 @@ "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", "optional": true }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -4016,7 +3912,7 @@ "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, "engines": { "node": ">=4" @@ -4037,7 +3933,7 @@ "node_modules/stubs": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", - "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=", + "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==", "optional": true }, "node_modules/supports-color": { @@ -4118,10 +4014,15 @@ "node": ">=10" } }, + "node_modules/text-decoding": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-decoding/-/text-decoding-1.0.0.tgz", + "integrity": "sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA==" + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, "node_modules/toidentifier": { @@ -4135,7 +4036,7 @@ "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "node_modules/tsconfig-paths": { "version": "3.14.1", @@ -4263,7 +4164,7 @@ "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "engines": { "node": ">= 0.8" } @@ -4280,13 +4181,13 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "optional": true }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "engines": { "node": ">= 0.4.0" } @@ -4308,7 +4209,7 @@ "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "engines": { "node": ">= 0.8" } @@ -4316,7 +4217,7 @@ "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "node_modules/websocket-driver": { "version": "0.7.4", @@ -4342,7 +4243,7 @@ "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -4408,7 +4309,7 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "devOptional": true }, "node_modules/write-file-atomic": { @@ -4489,118 +4390,118 @@ }, "dependencies": { "@algolia/cache-browser-local-storage": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.13.0.tgz", - "integrity": "sha512-nj1vHRZauTqP/bluwkRIgEADEimqojJgoTRCel5f6q8WCa9Y8QeI4bpDQP28FoeKnDRYa3J5CauDlN466jqRhg==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.13.1.tgz", + "integrity": "sha512-UAUVG2PEfwd/FfudsZtYnidJ9eSCpS+LW9cQiesePQLz41NAcddKxBak6eP2GErqyFagSlnVXe/w2E9h2m2ttg==", "requires": { - "@algolia/cache-common": "4.13.0" + "@algolia/cache-common": "4.13.1" } }, "@algolia/cache-common": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.13.0.tgz", - "integrity": "sha512-f9mdZjskCui/dA/fA/5a+6hZ7xnHaaZI5tM/Rw9X8rRB39SUlF/+o3P47onZ33n/AwkpSbi5QOyhs16wHd55kA==" + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.13.1.tgz", + "integrity": "sha512-7Vaf6IM4L0Jkl3sYXbwK+2beQOgVJ0mKFbz/4qSxKd1iy2Sp77uTAazcX+Dlexekg1fqGUOSO7HS4Sx47ZJmjA==" }, "@algolia/cache-in-memory": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.13.0.tgz", - "integrity": "sha512-hHdc+ahPiMM92CQMljmObE75laYzNFYLrNOu0Q3/eyvubZZRtY2SUsEEgyUEyzXruNdzrkcDxFYa7YpWBJYHAg==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.13.1.tgz", + "integrity": "sha512-pZzybCDGApfA/nutsFK1P0Sbsq6fYJU3DwIvyKg4pURerlJM4qZbB9bfLRef0FkzfQu7W11E4cVLCIOWmyZeuQ==", "requires": { - "@algolia/cache-common": "4.13.0" + "@algolia/cache-common": "4.13.1" } }, "@algolia/client-account": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.13.0.tgz", - "integrity": "sha512-FzFqFt9b0g/LKszBDoEsW+dVBuUe1K3scp2Yf7q6pgHWM1WqyqUlARwVpLxqyc+LoyJkTxQftOKjyFUqddnPKA==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.13.1.tgz", + "integrity": "sha512-TFLiZ1KqMiir3FNHU+h3b0MArmyaHG+eT8Iojio6TdpeFcAQ1Aiy+2gb3SZk3+pgRJa/BxGmDkRUwE5E/lv3QQ==", "requires": { - "@algolia/client-common": "4.13.0", - "@algolia/client-search": "4.13.0", - "@algolia/transporter": "4.13.0" + "@algolia/client-common": "4.13.1", + "@algolia/client-search": "4.13.1", + "@algolia/transporter": "4.13.1" } }, "@algolia/client-analytics": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.13.0.tgz", - "integrity": "sha512-klmnoq2FIiiMHImkzOm+cGxqRLLu9CMHqFhbgSy9wtXZrqb8BBUIUE2VyBe7azzv1wKcxZV2RUyNOMpFqmnRZA==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.13.1.tgz", + "integrity": "sha512-iOS1JBqh7xaL5x00M5zyluZ9+9Uy9GqtYHv/2SMuzNW1qP7/0doz1lbcsP3S7KBbZANJTFHUOfuqyRLPk91iFA==", "requires": { - "@algolia/client-common": "4.13.0", - "@algolia/client-search": "4.13.0", - "@algolia/requester-common": "4.13.0", - "@algolia/transporter": "4.13.0" + "@algolia/client-common": "4.13.1", + "@algolia/client-search": "4.13.1", + "@algolia/requester-common": "4.13.1", + "@algolia/transporter": "4.13.1" } }, "@algolia/client-common": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.13.0.tgz", - "integrity": "sha512-GoXfTp0kVcbgfSXOjfrxx+slSipMqGO9WnNWgeMmru5Ra09MDjrcdunsiiuzF0wua6INbIpBQFTC2Mi5lUNqGA==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.13.1.tgz", + "integrity": "sha512-LcDoUE0Zz3YwfXJL6lJ2OMY2soClbjrrAKB6auYVMNJcoKZZ2cbhQoFR24AYoxnGUYBER/8B+9sTBj5bj/Gqbg==", "requires": { - "@algolia/requester-common": "4.13.0", - "@algolia/transporter": "4.13.0" + "@algolia/requester-common": "4.13.1", + "@algolia/transporter": "4.13.1" } }, "@algolia/client-personalization": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.13.0.tgz", - "integrity": "sha512-KneLz2WaehJmNfdr5yt2HQETpLaCYagRdWwIwkTqRVFCv4DxRQ2ChPVW9jeTj4YfAAhfzE6F8hn7wkQ/Jfj6ZA==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.13.1.tgz", + "integrity": "sha512-1CqrOW1ypVrB4Lssh02hP//YxluoIYXAQCpg03L+/RiXJlCs+uIqlzC0ctpQPmxSlTK6h07kr50JQoYH/TIM9w==", "requires": { - "@algolia/client-common": "4.13.0", - "@algolia/requester-common": "4.13.0", - "@algolia/transporter": "4.13.0" + "@algolia/client-common": "4.13.1", + "@algolia/requester-common": "4.13.1", + "@algolia/transporter": "4.13.1" } }, "@algolia/client-search": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.13.0.tgz", - "integrity": "sha512-blgCKYbZh1NgJWzeGf+caKE32mo3j54NprOf0LZVCubQb3Kx37tk1Hc8SDs9bCAE8hUvf3cazMPIg7wscSxspA==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.13.1.tgz", + "integrity": "sha512-YQKYA83MNRz3FgTNM+4eRYbSmHi0WWpo019s5SeYcL3HUan/i5R09VO9dk3evELDFJYciiydSjbsmhBzbpPP2A==", "requires": { - "@algolia/client-common": "4.13.0", - "@algolia/requester-common": "4.13.0", - "@algolia/transporter": "4.13.0" + "@algolia/client-common": "4.13.1", + "@algolia/requester-common": "4.13.1", + "@algolia/transporter": "4.13.1" } }, "@algolia/logger-common": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.13.0.tgz", - "integrity": "sha512-8yqXk7rMtmQJ9wZiHOt/6d4/JDEg5VCk83gJ39I+X/pwUPzIsbKy9QiK4uJ3aJELKyoIiDT1hpYVt+5ia+94IA==" + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.13.1.tgz", + "integrity": "sha512-L6slbL/OyZaAXNtS/1A8SAbOJeEXD5JcZeDCPYDqSTYScfHu+2ePRTDMgUTY4gQ7HsYZ39N1LujOd8WBTmM2Aw==" }, "@algolia/logger-console": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.13.0.tgz", - "integrity": "sha512-YepRg7w2/87L0vSXRfMND6VJ5d6699sFJBRWzZPOlek2p5fLxxK7O0VncYuc/IbVHEgeApvgXx0WgCEa38GVuQ==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.13.1.tgz", + "integrity": "sha512-7jQOTftfeeLlnb3YqF8bNgA2GZht7rdKkJ31OCeSH2/61haO0tWPoNRjZq9XLlgMQZH276pPo0NdiArcYPHjCA==", "requires": { - "@algolia/logger-common": "4.13.0" + "@algolia/logger-common": "4.13.1" } }, "@algolia/requester-browser-xhr": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.13.0.tgz", - "integrity": "sha512-Dj+bnoWR5MotrnjblzGKZ2kCdQi2cK/VzPURPnE616NU/il7Ypy6U6DLGZ/ZYz+tnwPa0yypNf21uqt84fOgrg==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.13.1.tgz", + "integrity": "sha512-oa0CKr1iH6Nc7CmU6RE7TnXMjHnlyp7S80pP/LvZVABeJHX3p/BcSCKovNYWWltgTxUg0U1o+2uuy8BpMKljwA==", "requires": { - "@algolia/requester-common": "4.13.0" + "@algolia/requester-common": "4.13.1" } }, "@algolia/requester-common": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.13.0.tgz", - "integrity": "sha512-BRTDj53ecK+gn7ugukDWOOcBRul59C4NblCHqj4Zm5msd5UnHFjd/sGX+RLOEoFMhetILAnmg6wMrRrQVac9vw==" + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.13.1.tgz", + "integrity": "sha512-eGVf0ID84apfFEuXsaoSgIxbU3oFsIbz4XiotU3VS8qGCJAaLVUC5BUJEkiFENZIhon7hIB4d0RI13HY4RSA+w==" }, "@algolia/requester-node-http": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.13.0.tgz", - "integrity": "sha512-9b+3O4QFU4azLhGMrZAr/uZPydvzOR4aEZfSL8ZrpLZ7fbbqTO0S/5EVko+QIgglRAtVwxvf8UJ1wzTD2jvKxQ==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.13.1.tgz", + "integrity": "sha512-7C0skwtLdCz5heKTVe/vjvrqgL/eJxmiEjHqXdtypcE5GCQCYI15cb+wC4ytYioZDMiuDGeVYmCYImPoEgUGPw==", "requires": { - "@algolia/requester-common": "4.13.0" + "@algolia/requester-common": "4.13.1" } }, "@algolia/transporter": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.13.0.tgz", - "integrity": "sha512-8tSQYE+ykQENAdeZdofvtkOr5uJ9VcQSWgRhQ9h01AehtBIPAczk/b2CLrMsw5yQZziLs5cZ3pJ3478yI+urhA==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.13.1.tgz", + "integrity": "sha512-pICnNQN7TtrcYJqqPEXByV8rJ8ZRU2hCiIKLTLRyNpghtQG3VAFk6fVtdzlNfdUGZcehSKGarPIZEHlQXnKjgw==", "requires": { - "@algolia/cache-common": "4.13.0", - "@algolia/logger-common": "4.13.0", - "@algolia/requester-common": "4.13.0" + "@algolia/cache-common": "4.13.1", + "@algolia/logger-common": "4.13.1", + "@algolia/requester-common": "4.13.1" } }, "@babel/code-frame": { @@ -4613,18 +4514,18 @@ } }, "@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", "dev": true }, "@babel/highlight": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.12.tgz", - "integrity": "sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.16.7", + "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -4661,19 +4562,19 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true }, "supports-color": { @@ -4704,30 +4605,12 @@ "strip-json-comments": "^3.1.1" } }, - "@firebase/app": { - "version": "0.7.24", - "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.7.24.tgz", - "integrity": "sha512-HIbAhayEykbCez1Rl6pmzAWbIx63Mc9+t3ngWKqZdkMnBNAAJvYaUdx7Krus7O9XHUKNw/gzBUETAEYt93jusA==", - "peer": true, - "requires": { - "@firebase/component": "0.5.14", - "@firebase/logger": "0.3.2", - "@firebase/util": "1.6.0", - "idb": "7.0.1", - "tslib": "^2.1.0" - } - }, - "@firebase/app-compat": { - "version": "0.1.25", - "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.1.25.tgz", - "integrity": "sha512-FdCnYwIM3R+OuRE7nrAdVT5oNlvSAHQHN1ictB/gjCFs58lXMCe0DCIRDrA7zxaOFIKeWPtx35ZNXv3EdPFNpQ==", - "peer": true, + "@fastify/busboy": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-1.1.0.tgz", + "integrity": "sha512-Fv854f94v0CzIDllbY3i/0NJPNBRNLDawf3BTYVGCe9VrIIs3Wi7AFx24F9NzCxdf0wyx/x0Q9kEVnvDOPnlxA==", "requires": { - "@firebase/app": "0.7.24", - "@firebase/component": "0.5.14", - "@firebase/logger": "0.3.2", - "@firebase/util": "1.6.0", - "tslib": "^2.1.0" + "text-decoding": "^1.0.0" } }, "@firebase/app-types": { @@ -4742,109 +4625,61 @@ "requires": {} }, "@firebase/component": { - "version": "0.5.14", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.14.tgz", - "integrity": "sha512-ct2p1MTMV5P/nGIlkC3XjAVwHwjsIZaeo8JVyDAkJCNTROu5mYX3FBK16hjIUIIVJDpgnnzFh9nP74gciL4WrA==", - "peer": true, + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.16.tgz", + "integrity": "sha512-/pkl77mN9PT7dTSzNu1CrvIvd+z1CdePnEl+VITaeSBs9Ko7ZVvSIlzQLbSwqksXX3bAHpxej0Mg6mVKQiRVSw==", "requires": { - "@firebase/util": "1.6.0", + "@firebase/util": "1.6.2", "tslib": "^2.1.0" } }, "@firebase/database": { - "version": "0.12.8", - "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.12.8.tgz", - "integrity": "sha512-JBQVfFLzfhxlQbl4OU6ov9fdsddkytBQdtSSR49cz48homj38ccltAhK6seum+BI7f28cV2LFHF9672lcN+qxA==", + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.13.2.tgz", + "integrity": "sha512-wKkBD4rq6PPv9gl1hNJNpl0R0bwJmXCJfDuvotjXmTcU7kV0AIaJ45GVhULkbSCApAAFC6QUJ91oasDUO1ZVxw==", "requires": { "@firebase/auth-interop-types": "0.1.6", - "@firebase/component": "0.5.13", - "@firebase/logger": "0.3.2", - "@firebase/util": "1.5.2", + "@firebase/component": "0.5.16", + "@firebase/logger": "0.3.3", + "@firebase/util": "1.6.2", "faye-websocket": "0.11.4", "tslib": "^2.1.0" - }, - "dependencies": { - "@firebase/component": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.13.tgz", - "integrity": "sha512-hxhJtpD8Ppf/VU2Rlos6KFCEV77TGIGD5bJlkPK1+B/WUe0mC6dTjW7KhZtXTc+qRBp9nFHWcsIORnT8liHP9w==", - "requires": { - "@firebase/util": "1.5.2", - "tslib": "^2.1.0" - } - }, - "@firebase/util": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.5.2.tgz", - "integrity": "sha512-YvBH2UxFcdWG2HdFnhxZptPl2eVFlpOyTH66iDo13JPEYraWzWToZ5AMTtkyRHVmu7sssUpQlU9igy1KET7TOw==", - "requires": { - "tslib": "^2.1.0" - } - } } }, "@firebase/database-compat": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-0.1.8.tgz", - "integrity": "sha512-dhXr5CSieBuKNdU96HgeewMQCT9EgOIkfF1GNy+iRrdl7BWLxmlKuvLfK319rmIytSs/vnCzcD9uqyxTeU/A3A==", - "requires": { - "@firebase/component": "0.5.13", - "@firebase/database": "0.12.8", - "@firebase/database-types": "0.9.7", - "@firebase/logger": "0.3.2", - "@firebase/util": "1.5.2", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-0.2.2.tgz", + "integrity": "sha512-3wLHJ54WHMhrveCywCMbkspshFezN07PLOIsmqELM1+pmrg3bwMj9u/o3Equ0DwmESMnchp5sMxgzdBUOextJg==", + "requires": { + "@firebase/component": "0.5.16", + "@firebase/database": "0.13.2", + "@firebase/database-types": "0.9.10", + "@firebase/logger": "0.3.3", + "@firebase/util": "1.6.2", "tslib": "^2.1.0" - }, - "dependencies": { - "@firebase/component": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.13.tgz", - "integrity": "sha512-hxhJtpD8Ppf/VU2Rlos6KFCEV77TGIGD5bJlkPK1+B/WUe0mC6dTjW7KhZtXTc+qRBp9nFHWcsIORnT8liHP9w==", - "requires": { - "@firebase/util": "1.5.2", - "tslib": "^2.1.0" - } - }, - "@firebase/database-types": { - "version": "0.9.7", - "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.9.7.tgz", - "integrity": "sha512-EFhgL89Fz6DY3kkB8TzdHvdu8XaqqvzcF2DLVOXEnQ3Ms7L755p5EO42LfxXoJqb9jKFvgLpFmKicyJG25WFWw==", - "requires": { - "@firebase/app-types": "0.7.0", - "@firebase/util": "1.5.2" - } - }, - "@firebase/util": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.5.2.tgz", - "integrity": "sha512-YvBH2UxFcdWG2HdFnhxZptPl2eVFlpOyTH66iDo13JPEYraWzWToZ5AMTtkyRHVmu7sssUpQlU9igy1KET7TOw==", - "requires": { - "tslib": "^2.1.0" - } - } } }, "@firebase/database-types": { - "version": "0.9.8", - "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.9.8.tgz", - "integrity": "sha512-bI7bwF5xc0nPi6Oa3JVt6JJdfhVAnEpCwgfTNILR4lYDPtxdxlRXhZzQ5lfqlCj7PR+drKh9RvMu6C24N1q04w==", + "version": "0.9.10", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.9.10.tgz", + "integrity": "sha512-2ji6nXRRsY+7hgU6zRhUtK0RmSjVWM71taI7Flgaw+BnopCo/lDF5HSwxp8z7LtiHlvQqeRA3Ozqx5VhlAbiKg==", "requires": { "@firebase/app-types": "0.7.0", - "@firebase/util": "1.6.0" + "@firebase/util": "1.6.2" } }, "@firebase/logger": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.3.2.tgz", - "integrity": "sha512-lzLrcJp9QBWpo40OcOM9B8QEtBw2Fk1zOZQdvv+rWS6gKmhQBCEMc4SMABQfWdjsylBcDfniD1Q+fUX1dcBTXA==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.3.3.tgz", + "integrity": "sha512-POTJl07jOKTOevLXrTvJD/VZ0M6PnJXflbAh5J9VGkmtXPXNG6MdZ9fmRgqYhXKTaDId6AQenQ262uwgpdtO0Q==", "requires": { "tslib": "^2.1.0" } }, "@firebase/util": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.6.0.tgz", - "integrity": "sha512-6+hhqb4Zzjoo12xofTDHPkgW3FnN4ydBsjd5X2KuQI268DR3W3Ld64W/gkKPZrKRgUxeNeb+pykfP3qRe7q+vA==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.6.2.tgz", + "integrity": "sha512-VYDqEf/+mS7n0nPj6qJDJYFtKIEfOaTtQeNDsd3x+xp8HWvrbygWOexzeGicLP1dvEzrKr3eQGcJmmmYN3TIsA==", "requires": { "tslib": "^2.1.0" } @@ -4884,9 +4719,9 @@ "optional": true }, "@google-cloud/storage": { - "version": "5.19.4", - "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-5.19.4.tgz", - "integrity": "sha512-Jz7ugcPHhsEmMVvIxM9uoBsdEbKIYwDkh3u07tifsIymEWs47F4/D6+/Tv/W7kLhznqjyOjVJ/0frtBeIC0lJA==", + "version": "5.20.5", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-5.20.5.tgz", + "integrity": "sha512-lOs/dCyveVF8TkVFnFSF7IGd0CJrTm91qiK6JLu+Z8qiT+7Ag0RyVhxZIWkhiACqwABo7kSHDm8FdH8p2wxSSw==", "optional": true, "requires": { "@google-cloud/paginator": "^3.0.7", @@ -4897,12 +4732,10 @@ "async-retry": "^1.3.3", "compressible": "^2.0.12", "configstore": "^5.0.0", - "date-and-time": "^2.0.0", "duplexify": "^4.0.0", "ent": "^2.2.0", "extend": "^3.0.2", "gaxios": "^4.0.0", - "get-stream": "^6.0.0", "google-auth-library": "^7.14.1", "hash-stream-validation": "^0.2.2", "mime": "^3.0.0", @@ -4910,9 +4743,9 @@ "p-limit": "^3.0.1", "pumpify": "^2.0.0", "retry-request": "^4.2.2", - "snakeize": "^0.1.0", "stream-events": "^1.0.4", "teeny-request": "^7.1.3", + "uuid": "^8.0.0", "xdg-basedir": "^4.0.0" } }, @@ -4927,15 +4760,15 @@ } }, "@grpc/proto-loader": { - "version": "0.6.12", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.12.tgz", - "integrity": "sha512-filTVbETFnxb9CyRX98zN18ilChTuf/C5scZ2xyaOTp0EHGq0/ufX8rjqXUcSb1Gpv7eZq4M2jDvbh9BogKnrg==", + "version": "0.6.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.13.tgz", + "integrity": "sha512-FjxPYDRTn6Ec3V0arm1FtSpmP6V50wuph2yILpyvTKzjc76oDdoihXqM1DzOW5ubvCC8GivfCnNtfaRE8myJ7g==", "optional": true, "requires": { "@types/long": "^4.0.1", "lodash.camelcase": "^4.3.0", "long": "^4.0.0", - "protobufjs": "^6.10.0", + "protobufjs": "^6.11.3", "yargs": "^16.2.0" } }, @@ -5070,9 +4903,9 @@ } }, "@types/express-serve-static-core": { - "version": "4.17.28", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", - "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", + "version": "4.17.29", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.29.tgz", + "integrity": "sha512-uMd++6dMKS32EOuw1Uli3e3BPgdLIXmezcfHv7N4c1s3gkhikBplORPpMq3fuWkxncZN1reb16d5n8yhQ80x7Q==", "requires": { "@types/node": "*", "@types/qs": "*", @@ -5091,6 +4924,14 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "@types/jsonwebtoken": { + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.8.tgz", + "integrity": "sha512-zm6xBQpFDIDM6o9r6HSgDeIcLy82TKWctCXEPbJJcXb5AKmi5BNNdLXneixK4lplX3PqIVcwLBCGE/kAGnlD4A==", + "requires": { + "@types/node": "*" + } + }, "@types/lodash": { "version": "4.14.182", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz", @@ -5109,9 +4950,9 @@ "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" }, "@types/node": { - "version": "17.0.34", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.34.tgz", - "integrity": "sha512-XImEz7XwTvDBtzlTnm8YvMqGW/ErMWBsKZ+hMTvnDIjGCKxwK5Xpc+c/oQjOauwq8M4OS11hEkpjX8rrI/eEgA==" + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.0.tgz", + "integrity": "sha512-cHlGmko4gWLVI27cGJntjs/Sj8th9aYwplmZFwmmgYQQvL5NUsgVJG7OddLvNfLqYS31KFN0s3qlaD9qCaxACA==" }, "@types/qs": { "version": "6.9.7", @@ -5256,24 +5097,24 @@ } }, "algoliasearch": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.13.0.tgz", - "integrity": "sha512-oHv4faI1Vl2s+YC0YquwkK/TsaJs79g2JFg5FDm2rKN12VItPTAeQ7hyJMHarOPPYuCnNC5kixbtcqvb21wchw==", - "requires": { - "@algolia/cache-browser-local-storage": "4.13.0", - "@algolia/cache-common": "4.13.0", - "@algolia/cache-in-memory": "4.13.0", - "@algolia/client-account": "4.13.0", - "@algolia/client-analytics": "4.13.0", - "@algolia/client-common": "4.13.0", - "@algolia/client-personalization": "4.13.0", - "@algolia/client-search": "4.13.0", - "@algolia/logger-common": "4.13.0", - "@algolia/logger-console": "4.13.0", - "@algolia/requester-browser-xhr": "4.13.0", - "@algolia/requester-common": "4.13.0", - "@algolia/requester-node-http": "4.13.0", - "@algolia/transporter": "4.13.0" + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.13.1.tgz", + "integrity": "sha512-dtHUSE0caWTCE7liE1xaL+19AFf6kWEcyn76uhcitWpntqvicFHXKFoZe5JJcv9whQOTRM6+B8qJz6sFj+rDJA==", + "requires": { + "@algolia/cache-browser-local-storage": "4.13.1", + "@algolia/cache-common": "4.13.1", + "@algolia/cache-in-memory": "4.13.1", + "@algolia/client-account": "4.13.1", + "@algolia/client-analytics": "4.13.1", + "@algolia/client-common": "4.13.1", + "@algolia/client-personalization": "4.13.1", + "@algolia/client-search": "4.13.1", + "@algolia/logger-common": "4.13.1", + "@algolia/logger-console": "4.13.1", + "@algolia/requester-browser-xhr": "4.13.1", + "@algolia/requester-common": "4.13.1", + "@algolia/requester-node-http": "4.13.1", + "@algolia/transporter": "4.13.1" } }, "ansi-colors": { @@ -5405,7 +5246,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" } } }, @@ -5492,7 +5333,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, "configstore": { @@ -5530,7 +5371,7 @@ "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "cors": { "version": "2.8.5", @@ -5558,12 +5399,6 @@ "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", "optional": true }, - "date-and-time": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/date-and-time/-/date-and-time-2.3.1.tgz", - "integrity": "sha512-OaIRmSJXifwEN21rMVVDs0Kz8uhJ3wWPYd86atkRiqN54liaMQYEbbrgjZQea75YXOBWL4ZFb3rG/waenw1TEg==", - "optional": true - }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -5598,14 +5433,6 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, - "dicer": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.1.tgz", - "integrity": "sha512-ObioMtXnmjYs3aRtpIJt9rgQSPCIhKVkFPip+E9GUDyWl8N435znUxK/JfNwGZJ2wnn5JKQ7Ly3vOK5Q5dylGA==", - "requires": { - "streamsearch": "^1.1.0" - } - }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -5647,7 +5474,7 @@ "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "emoji-regex": { "version": "8.0.0", @@ -5658,7 +5485,7 @@ "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" }, "end-of-stream": { "version": "1.4.4", @@ -5681,7 +5508,7 @@ "ent": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==", "optional": true }, "es-abstract": { @@ -5744,7 +5571,7 @@ "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "escape-string-regexp": { "version": "4.0.0", @@ -5899,7 +5726,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true } } @@ -5995,7 +5822,7 @@ "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" }, "event-target-shim": { "version": "5.0.1", @@ -6052,7 +5879,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" } } }, @@ -6077,13 +5904,13 @@ "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, "fast-text-encoding": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz", - "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.4.tgz", + "integrity": "sha512-x6lDDm/tBAzX9kmsPcZsNbvDs3Zey3+scsxaZElS8xWLgUMAg/oFLeewfUz0mu1CblHhhsu15jGkraldkFh8KQ==", "optional": true }, "faye-websocket": { @@ -6128,30 +5955,30 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" } } }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", "dev": true, "requires": { "locate-path": "^2.0.0" } }, "firebase-admin": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-10.2.0.tgz", - "integrity": "sha512-6ehn5J9UEFgi4+naqYvozmGpnZae3cJLdwSkSsDc8/Y0eTBjVMFdf9N2ft7N81UNHA0N5DknOyXhlsdAdyBLCA==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-10.3.0.tgz", + "integrity": "sha512-A0wgMLEjyVyUE+heyMJYqHRkPVjpebhOYsa47RHdrTM4ltApcx8Tn86sUmjqxlfh09gNnILAm7a8q5+FmgBYpg==", "requires": { - "@firebase/database-compat": "^0.1.8", + "@fastify/busboy": "^1.1.0", + "@firebase/database-compat": "^0.2.0", "@firebase/database-types": "^0.9.7", "@google-cloud/firestore": "^4.15.1", "@google-cloud/storage": "^5.18.3", "@types/node": ">=12.12.47", - "dicer": "^0.3.0", "jsonwebtoken": "^8.5.1", "jwks-rsa": "^2.0.2", "node-forge": "^1.3.1", @@ -6159,9 +5986,9 @@ } }, "firebase-functions": { - "version": "3.21.1", - "resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-3.21.1.tgz", - "integrity": "sha512-wUxJaUEceGpCxa+uAYTQUGM13Uc/mekWfJnhuqqPKr8S09WosoVRpoh1yVQO+AnMqNChq3psLkLxHPubW9Tg2A==", + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-3.22.0.tgz", + "integrity": "sha512-d1BxBpT95MhvVqXkpLWDvWbyuX7e2l69cFAiqG3U1XQDaMV88bM9S+Zg7H8i9pitEGFr+76ErjKgrY0n+g3ZDA==", "requires": { "@types/cors": "^2.8.5", "@types/express": "4.17.3", @@ -6192,9 +6019,9 @@ } }, "flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz", + "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==", "dev": true }, "forwarded": { @@ -6205,12 +6032,12 @@ "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, "function-bind": { @@ -6233,7 +6060,7 @@ "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", "devOptional": true }, "functions-have-names": { @@ -6272,21 +6099,15 @@ "optional": true }, "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.1" + "has-symbols": "^1.0.3" } }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "optional": true - }, "get-symbol-description": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", @@ -6347,9 +6168,9 @@ } }, "google-gax": { - "version": "2.30.4", - "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-2.30.4.tgz", - "integrity": "sha512-/W4wWKjYcCXtd3Vz+ux7fN3MElbLVKGmHCCgA6kotigQgoDrLLueSvnXsck7qZaF39ooYnFhA58Rjr7RHe2heA==", + "version": "2.30.5", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-2.30.5.tgz", + "integrity": "sha512-Jey13YrAN2hfpozHzbtrwEfEHdStJh1GwaQ2+Akh1k0Tv/EuNVSuBtHZoKSBm5wBMvNsxTsEIZ/152NrYyZgxQ==", "optional": true, "requires": { "@grpc/grpc-js": "~1.6.0", @@ -6363,7 +6184,7 @@ "node-fetch": "^2.6.1", "object-hash": "^3.0.0", "proto3-json-serializer": "^0.1.8", - "protobufjs": "6.11.2", + "protobufjs": "6.11.3", "retry-request": "^4.0.0" } }, @@ -6455,9 +6276,9 @@ } }, "http-parser-js": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz", - "integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==" + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" }, "http-proxy-agent": { "version": "5.0.0", @@ -6488,12 +6309,6 @@ "safer-buffer": ">= 2.1.2 < 3" } }, - "idb": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/idb/-/idb-7.0.1.tgz", - "integrity": "sha512-UUxlE7vGWK5RfB/fDwEGgRf84DY/ieqNha6msMV99UsEMQhJ1RwbCd8AYBj3QMgnE3VZnfQvm4oKVCJTYlqIgg==", - "peer": true - }, "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -6513,13 +6328,13 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "devOptional": true }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, "requires": { "once": "^1.3.0", @@ -6593,7 +6408,7 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true }, "is-fullwidth-code-point": { @@ -6684,7 +6499,7 @@ "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", "optional": true }, "is-weakref": { @@ -6699,7 +6514,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, "jose": { @@ -6744,7 +6559,7 @@ "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, "json5": { @@ -6811,11 +6626,12 @@ } }, "jwks-rsa": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-2.1.2.tgz", - "integrity": "sha512-QW2SNEUVvMqULiBJVsIJXSuX73Qj9il/DMCsJZsmCI8AQFZ6BjXgQW6h9wOlPr1LswQBNDdyFT2LPogwMRr1ew==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-2.1.4.tgz", + "integrity": "sha512-mpArfgPkUpX11lNtGxsF/szkasUcbWHGplZl/uFvFO2NuMHmt0dQXIihh0rkPU2yQd5niQtuUHbXnG/WKiXF6Q==", "requires": { "@types/express": "^4.17.13", + "@types/jsonwebtoken": "^8.5.8", "debug": "^4.3.4", "jose": "^2.0.5", "limiter": "^1.1.5", @@ -6863,7 +6679,7 @@ "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", "dev": true, "requires": { "p-locate": "^2.0.0", @@ -6878,43 +6694,43 @@ "lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", "optional": true }, "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" }, "lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" }, "lodash.isboolean": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" }, "lodash.isinteger": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" }, "lodash.isnumber": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" }, "lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" }, "lodash.isstring": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" }, "lodash.merge": { "version": "4.6.2", @@ -6925,12 +6741,12 @@ "lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" }, "lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", "dev": true }, "long": { @@ -6960,7 +6776,7 @@ "lru-cache": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.2.tgz", - "integrity": "sha1-HRdnnAac2l0ECZGgnbwsDbN35V4=", + "integrity": "sha512-uQw9OqphAGiZhkuPlpFGmdTU2tEuhxTourM/19qGJrxBPHAr/f8BT1a0i/lOclESnGatdJG/UCkP9kZB/Lh1iw==", "requires": { "pseudomap": "^1.0.1", "yallist": "^2.0.0" @@ -6969,7 +6785,7 @@ "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" } } }, @@ -6993,17 +6809,17 @@ "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" }, "mime": { "version": "3.0.0", @@ -7047,7 +6863,7 @@ "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, "negotiator": { @@ -7071,7 +6887,7 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" }, "object-hash": { "version": "3.0.0", @@ -7080,9 +6896,9 @@ "optional": true }, "object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==" + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" }, "object-keys": { "version": "1.1.1", @@ -7124,7 +6940,7 @@ "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "devOptional": true, "requires": { "wrappy": "1" @@ -7156,7 +6972,7 @@ "p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", "dev": true, "requires": { "p-limit": "^1.1.0" @@ -7176,7 +6992,7 @@ "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", "dev": true }, "parent-module": { @@ -7196,13 +7012,13 @@ "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", "dev": true }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true }, "path-key": { @@ -7220,7 +7036,7 @@ "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "prelude-ls": { "version": "1.2.1", @@ -7244,9 +7060,9 @@ } }, "protobufjs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz", - "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==", + "version": "6.11.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz", + "integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==", "optional": true, "requires": { "@protobufjs/aspromise": "^1.1.2", @@ -7276,7 +7092,7 @@ "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" }, "pump": { "version": "3.0.0", @@ -7360,7 +7176,7 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "optional": true }, "require-from-string": { @@ -7370,12 +7186,12 @@ "dev": true }, "resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", "dev": true, "requires": { - "is-core-module": "^2.8.1", + "is-core-module": "^2.9.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } @@ -7461,7 +7277,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" } } }, @@ -7535,16 +7351,10 @@ "is-fullwidth-code-point": "^3.0.0" } }, - "snakeize": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/snakeize/-/snakeize-0.1.0.tgz", - "integrity": "sha1-EMCI2LWOsHazIpu1oE4jLOEmQi0=", - "optional": true - }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, "statuses": { @@ -7567,11 +7377,6 @@ "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", "optional": true }, - "streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" - }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -7626,7 +7431,7 @@ "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true }, "strip-json-comments": { @@ -7638,7 +7443,7 @@ "stubs": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", - "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=", + "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==", "optional": true }, "supports-color": { @@ -7702,10 +7507,15 @@ "uuid": "^8.0.0" } }, + "text-decoding": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-decoding/-/text-decoding-1.0.0.tgz", + "integrity": "sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA==" + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, "toidentifier": { @@ -7716,7 +7526,7 @@ "tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "tsconfig-paths": { "version": "3.14.1", @@ -7815,7 +7625,7 @@ "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" }, "uri-js": { "version": "4.4.1", @@ -7829,13 +7639,13 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "optional": true }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" }, "uuid": { "version": "8.3.2", @@ -7851,12 +7661,12 @@ "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" }, "webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "websocket-driver": { "version": "0.7.4", @@ -7876,7 +7686,7 @@ "whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "requires": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -7924,7 +7734,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "devOptional": true }, "write-file-atomic": { diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 90644ea7..ba7337c1 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -52,5 +52,20 @@ + FlutterDeepLinkingEnabled + + CFBundleURLTypes + + + CFBundleTypeRole + Editor + CFBundleURLName + avzag.raxys.app + CFBundleURLSchemes + + customscheme + + + diff --git a/lib/config/themes.dart b/lib/config/themes.dart deleted file mode 100644 index 83677730..00000000 --- a/lib/config/themes.dart +++ /dev/null @@ -1,13 +0,0 @@ -import 'package:flutter/material.dart'; - -import './themes/dark.dart'; -import './themes/light.dart'; - -class Themes { - final ThemeData light; - final ThemeData dark; - - Themes(ColorScheme scheme) - : light = getLightTheme(scheme), - dark = getDarkTheme(scheme); -} diff --git a/lib/config/themes/dark.dart b/lib/config/themes/dark.dart deleted file mode 100644 index 346e9825..00000000 --- a/lib/config/themes/dark.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'package:flutter/material.dart'; - -ThemeData getDarkTheme(ColorScheme colorScheme) => ThemeData.dark().copyWith( - colorScheme: ColorScheme.fromSwatch( - accentColor: Colors.grey, - brightness: Brightness.dark, - ), - cardTheme: const CardTheme( - clipBehavior: Clip.antiAlias, - ), - toggleableActiveColor: colorScheme.primary, - floatingActionButtonTheme: FloatingActionButtonThemeData( - backgroundColor: colorScheme.primary, - foregroundColor: colorScheme.onPrimary, - ), - dividerTheme: const DividerThemeData(space: 0), - ); diff --git a/lib/config/themes/light.dart b/lib/config/themes/light.dart deleted file mode 100644 index 7759f582..00000000 --- a/lib/config/themes/light.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'package:flutter/material.dart'; - -ThemeData getLightTheme(ColorScheme colorScheme) => ThemeData().copyWith( - scaffoldBackgroundColor: Colors.blueGrey.shade50, - colorScheme: ColorScheme.fromSwatch( - accentColor: Colors.grey, - ), - appBarTheme: AppBarTheme( - backgroundColor: colorScheme.surface, - foregroundColor: colorScheme.onSurface, - ), - cardTheme: const CardTheme( - clipBehavior: Clip.antiAlias, - ), - toggleableActiveColor: colorScheme.primary, - floatingActionButtonTheme: FloatingActionButtonThemeData( - backgroundColor: colorScheme.primary, - foregroundColor: colorScheme.onPrimary, - ), - dividerTheme: const DividerThemeData(space: 0), - ); diff --git a/lib/main.dart b/lib/main.dart index b0d9417c..66c39db5 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,51 +1,51 @@ import 'package:algolia/algolia.dart'; import 'package:avzag/store.dart'; +import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'config/themes.dart'; +import 'package:url_strategy/url_strategy.dart'; + import 'firebase_options.dart'; -import 'modules/navigation/nav_drawer.dart'; +import 'modules/navigation/services/root_guard.dart'; +import 'modules/navigation/services/router.gr.dart'; +import 'theme_set.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, ]); - await Firebase.initializeApp( - options: DefaultFirebaseOptions.currentPlatform, - ); prefs = await SharedPreferences.getInstance(); algolia = const Algolia.init( applicationId: 'NYVVAA43NI', apiKey: 'cf52a68ac340fc555978892202ce37df', ); + await Firebase.initializeApp( + options: DefaultFirebaseOptions.currentPlatform, + ); + await FirebaseAuth.instance.authStateChanges().first; await EditorStore.init(); - await GlobalStore.init(); - runApp(const App()); + GlobalStore.init(); + setPathUrlStrategy(); + runApp(App()); } class App extends StatelessWidget { - const App({Key? key}) : super(key: key); + App({Key? key}) : super(key: key); + + final _appRouter = AppRouter(rootGuard: RootGuard()); @override Widget build(context) { - final themes = Themes(Theme.of(context).colorScheme); - return MaterialApp( + final theme = ThemeSet(Theme.of(context).colorScheme); + return MaterialApp.router( title: 'Avzag', - theme: themes.light, - darkTheme: themes.dark, - home: FutureBuilder( - future: Future.value(), - builder: (context, snapshot) { - navigate( - context, - prefs.getString('module') ?? 'home', - ); - return const Material(); - }, - ), + theme: theme.light, + darkTheme: theme.dark, + routerDelegate: _appRouter.delegate(), + routeInformationParser: _appRouter.defaultRouteParser(), ); } } diff --git a/lib/shared/utils/contribution.dart b/lib/models/contribution.dart similarity index 100% rename from lib/shared/utils/contribution.dart rename to lib/models/contribution.dart diff --git a/lib/models/language.dart b/lib/models/language.dart index d3520df9..9a31c421 100644 --- a/lib/models/language.dart +++ b/lib/models/language.dart @@ -1,4 +1,4 @@ -import 'package:avzag/shared/utils/utils.dart'; +import 'package:avzag/shared/utils.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; class LanguageStats { diff --git a/lib/modules/account/screens/account.dart b/lib/modules/account/screens/account.dart new file mode 100644 index 00000000..fed4cc78 --- /dev/null +++ b/lib/modules/account/screens/account.dart @@ -0,0 +1,62 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:avzag/models/language.dart'; +import 'package:avzag/modules/account/widgets/account_tile.dart'; +import 'package:avzag/modules/account/widgets/adminable_languages.dart'; +import 'package:avzag/modules/navigation/services/router.gr.dart'; +import 'package:avzag/store.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter/material.dart'; + +import '../widgets/sign_in_buttons.dart'; + +class AccountScreen extends StatefulWidget { + const AccountScreen({Key? key}) : super(key: key); + + @override + State createState() => _AccountScreenState(); +} + +class _AccountScreenState extends State { + var adminable = []; + User? get user => FirebaseAuth.instance.currentUser; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + leading: IconButton( + icon: const Icon(Icons.arrow_back_rounded), + onPressed: () => context.pushRoute(const RootRoute()), + ), + title: const Text('Account'), + ), + body: ListView( + padding: const EdgeInsets.only(bottom: 76), + children: [ + if (user == null) + SignInButtons( + onSingIn: () => EditorStore.getAdminable().then( + (value) => setState(() { + adminable = value; + }), + ), + ) + else ...[ + AccountTile( + user!, + onSignOut: () => setState(() {}), + ), + AdminableLanguages( + GlobalStore.languages.values.whereType().toList(), + adminable: adminable, + onTap: (l) => setState(() { + EditorStore.language = l == EditorStore.language ? null : l; + }), + selected: EditorStore.language, + ), + ], + ], + ), + ); + } +} diff --git a/lib/modules/account/services/credentials.dart b/lib/modules/account/services/credentials.dart new file mode 100644 index 00000000..e1158293 --- /dev/null +++ b/lib/modules/account/services/credentials.dart @@ -0,0 +1,50 @@ +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter/foundation.dart'; +import 'package:google_sign_in/google_sign_in.dart'; +import 'package:sign_in_with_apple/sign_in_with_apple.dart' as apple; + +import 'crypto.dart'; + +Future getGoogleCredentials() async { + final user = await GoogleSignIn().signIn(); + if (user != null) { + final auth = await user.authentication; + return GoogleAuthProvider.credential( + accessToken: auth.accessToken, + idToken: auth.idToken, + ); + } + return null; +} + +Future getAppleCredentials() async { + if (kIsWeb) { + final provider = OAuthProvider('apple.com') + ..addScope('email') + ..addScope('name'); + await FirebaseAuth.instance.signInWithPopup(provider); + } else { + final rawNonce = generateNonce(); + final nonce = sha256ofString(rawNonce); + var redirectURL = 'https://avzagapp.firebaseapp.com/__/auth/handler'; + var clientID = 'avzagapp'; + final appleIdCredential = await apple.SignInWithApple.getAppleIDCredential( + scopes: [ + apple.AppleIDAuthorizationScopes.email, + apple.AppleIDAuthorizationScopes.fullName, + ], + webAuthenticationOptions: apple.WebAuthenticationOptions( + clientId: clientID, + redirectUri: Uri.parse(redirectURL), + ), + nonce: nonce, + ); + // Create an `OAuthCredential` from the credential returned by Apple. + return OAuthProvider('apple.com').credential( + idToken: appleIdCredential.identityToken, + accessToken: appleIdCredential.authorizationCode, + rawNonce: rawNonce, + ); + } + return null; +} diff --git a/lib/modules/account/services/crypto.dart b/lib/modules/account/services/crypto.dart new file mode 100644 index 00000000..ffa6c75e --- /dev/null +++ b/lib/modules/account/services/crypto.dart @@ -0,0 +1,18 @@ +import 'dart:convert'; +import 'dart:math'; + +import 'package:crypto/crypto.dart'; + +String generateNonce([int length = 32]) { + const charset = + '0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._'; + final random = Random.secure(); + return List.generate(length, (_) => charset[random.nextInt(charset.length)]) + .join(); +} + +String sha256ofString(String input) { + final bytes = utf8.encode(input); + final digest = sha256.convert(bytes); + return digest.toString(); +} diff --git a/lib/modules/account/services/signing.dart b/lib/modules/account/services/signing.dart new file mode 100644 index 00000000..bfc644d5 --- /dev/null +++ b/lib/modules/account/services/signing.dart @@ -0,0 +1,27 @@ +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:google_sign_in/google_sign_in.dart'; + +Future signIn( + Future Function() getCredentials, +) async { + final credentials = await getCredentials(); + if (credentials == null) return false; + await FirebaseAuth.instance.signInWithCredential(credentials); + return true; +} + +Future signOut([User? user]) async { + final provider = (user ?? FirebaseAuth.instance.currentUser) + ?.providerData + .first + .providerId; + if (provider == null) return false; + + await FirebaseAuth.instance.signOut(); + switch (provider) { + case 'google.com': + await GoogleSignIn().signOut(); + break; + } + return true; +} diff --git a/lib/modules/account/widgets/account_tile.dart b/lib/modules/account/widgets/account_tile.dart new file mode 100644 index 00000000..aca26a9b --- /dev/null +++ b/lib/modules/account/widgets/account_tile.dart @@ -0,0 +1,37 @@ +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter/material.dart'; + +import '../services/signing.dart'; + +class AccountTile extends StatelessWidget { + const AccountTile( + this.user, { + this.onSignOut, + Key? key, + }) : super(key: key); + + final User user; + final VoidCallback? onSignOut; + + @override + Widget build(BuildContext context) { + return ListTile( + leading: CircleAvatar( + backgroundImage: + user.photoURL == null ? null : NetworkImage(user.photoURL!), + backgroundColor: Colors.transparent, + ), + title: Text(user.displayName ?? '[no name]'), + subtitle: Text(user.email ?? '[no email]'), + trailing: onSignOut == null + ? null + : IconButton( + onPressed: () async { + if (await signOut(user) == true) onSignOut?.call(); + }, + icon: const Icon(Icons.logout_rounded), + tooltip: 'Sign out', + ), + ); + } +} diff --git a/lib/modules/account/widgets/adminable_languages.dart b/lib/modules/account/widgets/adminable_languages.dart new file mode 100644 index 00000000..59056887 --- /dev/null +++ b/lib/modules/account/widgets/adminable_languages.dart @@ -0,0 +1,70 @@ +import 'package:avzag/models/language.dart'; +import 'package:avzag/shared/extensions.dart'; +import 'package:avzag/shared/utils.dart'; +import 'package:avzag/shared/widgets/column_card.dart'; +import 'package:avzag/shared/widgets/language_avatar.dart'; +import 'package:avzag/shared/widgets/span_icon.dart'; +import 'package:badges/badges.dart'; +import 'package:flutter/material.dart'; + +class AdminableLanguages extends StatelessWidget { + const AdminableLanguages( + this.languages, { + required this.adminable, + required this.onTap, + this.selected, + Key? key, + }) : super(key: key); + + final List languages; + final List adminable; + final String? selected; + final ValueSetter onTap; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context).colorScheme; + return ColumnCard( + children: [ + for (final l in languages) + ListTile( + leading: Badge( + padding: EdgeInsets.zero, + ignorePointer: true, + badgeColor: theme.surface, + position: BadgePosition.topEnd(end: -20), + badgeContent: adminable.contains(l.name) + ? SpanIcon( + Icons.account_circle_rounded, + padding: const EdgeInsets.all(2), + color: theme.onSurface, + ) + : null, + child: LanguageAvatar(l.name), + ), + title: Text( + l.name.titled, + style: const TextStyle( + fontWeight: FontWeight.w500, + fontSize: 18, + ), + ), + onTap: () => onTap(l.name), + selected: l.name == selected, + trailing: Builder( + builder: (context) { + final contact = l.contact; + return contact == null + ? const SizedBox() + : IconButton( + onPressed: () => openLink(contact), + icon: const Icon(Icons.send_rounded), + tooltip: 'Contact admin', + ); + }, + ), + ), + ], + ); + } +} diff --git a/lib/modules/account/widgets/sign_in_buttons.dart b/lib/modules/account/widgets/sign_in_buttons.dart new file mode 100644 index 00000000..098c25ee --- /dev/null +++ b/lib/modules/account/widgets/sign_in_buttons.dart @@ -0,0 +1,76 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:avzag/shared/modals/snackbar_manager.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +import '../services/credentials.dart'; +import '../services/signing.dart' as signing; + +class SignInButtons extends StatefulWidget { + const SignInButtons({ + this.onSingIn, + Key? key, + }) : super(key: key); + + final FutureOr Function()? onSingIn; + + @override + State createState() => _SignInButtonsState(); +} + +class _SignInButtonsState extends State { + var loading = false; + + Future signIn( + Future Function() credentialsGetter, + ) async { + setState(() { + loading = true; + }); + try { + if (await signing.signIn(credentialsGetter) == true) { + await widget.onSingIn?.call(); + } + } catch (e) { + showSnackbar(context); + } + setState(() { + loading = false; + }); + } + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(16), + child: loading + ? const Center( + child: SizedBox.square( + dimension: 24, + child: CircularProgressIndicator(), + ), + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + ElevatedButton.icon( + onPressed: () => signIn(getGoogleCredentials), + icon: const Icon(Icons.login_rounded), + label: const Text('Sign in with Google'), + ), + if (kIsWeb || Platform.isIOS) ...[ + const SizedBox(height: 16), + ElevatedButton.icon( + onPressed: () => signIn(getAppleCredentials), + icon: const Icon(Icons.login_rounded), + label: const Text('Sign in with Apple'), + ), + ], + ], + ), + ); + } +} diff --git a/lib/modules/dictionary/models/entry.dart b/lib/modules/dictionary/models/entry.dart index f0b73614..38672c4d 100644 --- a/lib/modules/dictionary/models/entry.dart +++ b/lib/modules/dictionary/models/entry.dart @@ -1,5 +1,5 @@ import 'package:algolia/algolia.dart'; -import 'package:avzag/shared/utils/utils.dart'; +import 'package:avzag/shared/utils.dart'; class Entry { final String entryID; diff --git a/lib/modules/dictionary/models/use.dart b/lib/modules/dictionary/models/use.dart index c4824bde..3d755b97 100644 --- a/lib/modules/dictionary/models/use.dart +++ b/lib/modules/dictionary/models/use.dart @@ -1,4 +1,4 @@ -import 'package:avzag/shared/utils/utils.dart'; +import 'package:avzag/shared/utils.dart'; import 'sample.dart'; diff --git a/lib/modules/dictionary/models/word.dart b/lib/modules/dictionary/models/word.dart index 239a39a4..2719f92f 100644 --- a/lib/modules/dictionary/models/word.dart +++ b/lib/modules/dictionary/models/word.dart @@ -1,11 +1,11 @@ -import 'package:avzag/shared/utils/contribution.dart'; -import 'package:avzag/shared/utils/utils.dart'; +import 'package:avzag/models/contribution.dart'; +import 'package:avzag/shared/utils.dart'; import 'sample.dart'; import 'use.dart'; class Word { - String? id; + String id; String headword; String? ipa; List forms; @@ -15,8 +15,8 @@ class Word { List uses; Contribution? contribution; - Word({ - this.id, + Word( + this.id, { required this.headword, this.ipa, required this.language, @@ -27,11 +27,9 @@ class Word { this.note, }); - Word.fromJson( - Map json, [ - String? id, - ]) : this( - id: id, + Word.fromJson(Map json, String id) + : this( + id, headword: json['headword'] as String, ipa: json['ipa'] as String?, forms: listFromJson( diff --git a/lib/modules/dictionary/screens/dictionary.dart b/lib/modules/dictionary/screens/dictionary.dart index db004bf4..b061cffe 100644 --- a/lib/modules/dictionary/screens/dictionary.dart +++ b/lib/modules/dictionary/screens/dictionary.dart @@ -1,5 +1,9 @@ +import 'package:auto_route/auto_route.dart'; import 'package:avzag/modules/dictionary/widgets/entry_group.dart'; -import 'package:avzag/modules/navigation/nav_drawer.dart'; +import 'package:avzag/modules/navigation/screens/navigation.dart'; +import 'package:avzag/modules/navigation/services/router.gr.dart'; +import 'package:avzag/shared/modals/loading_dialog.dart'; +import 'package:avzag/shared/modals/snackbar_manager.dart'; import 'package:avzag/shared/widgets/caption.dart'; import 'package:avzag/shared/widgets/rounded_menu_button.dart'; import 'package:avzag/store.dart'; @@ -10,7 +14,7 @@ import 'package:provider/provider.dart'; import '../models/entry.dart'; import '../models/word.dart'; import '../search_controller.dart'; -import '../services/sheets.dart'; +import '../services/word.dart'; import '../widgets/search_toolbar.dart'; class DictionaryScreen extends StatefulWidget { @@ -60,6 +64,7 @@ class DictionaryScreenState extends State { setState(() { if (word == null) { editing ??= Word( + '', headword: '', uses: [], language: EditorStore.language!, @@ -70,29 +75,45 @@ class DictionaryScreenState extends State { editing = Word.fromJson(word.toJson(), word.id); } }); - editWord( - context, - editing!, - () => setState(() { - editing = null; - }), + context.pushRoute( + WordEditorRoute( + word: editing!, + onDone: () => setState(() { + editing = null; + }), + ), ); } - void open(Entry entry) { - if (entry.unverified && EditorStore.admin) { - diffWords(context, entry.entryID); - return; + void open(Entry entry) async { + if (entry.unverified && + EditorStore.admin && + EditorStore.language == entry.language) { + final overwrite = + await showLoadingDialog(context, loadWord(entry.entryID)); + if (overwrite?.contribution == null) return showSnackbar(context); + final base = await showLoadingDialog( + context, + loadWord(overwrite?.contribution?.overwriteId), + ); + context.pushRoute( + WordsDiffRoute( + base: base!, + overwrite: overwrite!, + ), + ); + } else { + context.pushRoute( + WordLoaderRoute( + id: entry.entryID, + onEdit: editing == null && + entry.language == EditorStore.language && + (EditorStore.admin || !entry.unverified) + ? edit + : null, + ), + ); } - openWord( - context, - entry.entryID, - editing == null && - entry.language == EditorStore.language && - (EditorStore.admin || !entry.unverified) - ? edit - : null, - ); } @override @@ -101,7 +122,7 @@ class DictionaryScreenState extends State { value: search, builder: (context, _) { return Scaffold( - drawer: const NavDraver(title: 'dictionary'), + drawer: const NavigationScreen(), floatingActionButton: EditorStore.editor ? FloatingActionButton( onPressed: edit, diff --git a/lib/modules/dictionary/screens/word.dart b/lib/modules/dictionary/screens/word.dart index f8d27d51..835f4497 100644 --- a/lib/modules/dictionary/screens/word.dart +++ b/lib/modules/dictionary/screens/word.dart @@ -1,139 +1,85 @@ -import 'package:avzag/modules/dictionary/widgets/samples_column.dart'; -import 'package:avzag/shared/utils/utils.dart'; -import 'package:avzag/shared/widgets/caption.dart'; -import 'package:avzag/shared/widgets/column_card.dart'; +import 'package:auto_route/auto_route.dart'; +import 'package:avzag/modules/dictionary/services/sharing.dart'; +import 'package:avzag/shared/extensions.dart'; +import 'package:avzag/shared/utils.dart'; import 'package:avzag/shared/widgets/language_flag.dart'; -import 'package:avzag/shared/widgets/markdown_text.dart'; -import 'package:avzag/shared/widgets/modals/snackbar_manager.dart'; +import 'package:avzag/shared/widgets/options_button.dart'; import 'package:avzag/shared/widgets/rounded_back_button.dart'; import 'package:flutter/material.dart'; +import 'package:modal_bottom_sheet/modal_bottom_sheet.dart'; import '../models/word.dart'; +import '../widgets/word_view.dart'; class WordScreen extends StatelessWidget { const WordScreen( this.word, { - this.scroll, + @pathParam String? id, this.onEdit, - this.embedded = false, Key? key, }) : super(key: key); final Word word; - final bool embedded; - final ScrollController? scroll; final ValueSetter? onEdit; @override Widget build(BuildContext context) { - final theme = Theme.of(context).textTheme; return Scaffold( - appBar: embedded - ? null - : AppBar( - leading: const RoundedBackButton(), - title: Stack( - alignment: Alignment.center, - children: [ - Text(capitalize(word.language)), - ], - ), - actions: [ - Opacity( - opacity: .5, - child: LanguageFlag( - word.language, - width: 160, - offset: const Offset(16, -2), - scale: 1.25, - ), - ), - if (onEdit != null) - IconButton( - onPressed: () { - Navigator.pop(context); - onEdit!(word); - }, - tooltip: 'Edit', - icon: const Icon(Icons.edit_rounded), - ), - const SizedBox(width: 4), - ], - ), - floatingActionButton: embedded - ? null - : FloatingActionButton( - onPressed: () => showSnackbar( - context, - text: 'Word sharing is coming soon', - ), - tooltip: 'Share', - child: const Icon(Icons.share_rounded), - ), - body: ListView( - controller: scroll, - padding: const EdgeInsets.only(bottom: 76), - children: [ - ColumnCard( - divider: const SizedBox(height: 4), - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, + appBar: AppBar( + leading: const RoundedBackButton(), + title: Stack( + alignment: Alignment.center, + children: [ + Text(word.language.titled), + ], + ), + actions: [ + Opacity( + opacity: .5, + child: LanguageFlag( + word.language, + width: 160, + offset: const Offset(16, -2), + scale: 1.25, ), - children: [ - Text( - capitalize(word.headword), - style: theme.headline6, - ), - if (word.ipa != null) - Text( - word.ipa!, - style: theme.bodyText1?.copyWith( - color: theme.caption?.color, - ), + ), + OptionsButton( + [ + OptionItem.simple( + Icons.link_rounded, + 'Share link', + onTap: () => copyText( + context, + previewArticle(word), ), - if (word.tags.isNotEmpty) - Text( - prettyTags(word.tags)!, - style: theme.caption, + ), + OptionItem.tile( + const Icon(Icons.article_rounded), + const Text('Share article'), + onTap: () => copyText( + context, + textifyArticle(word), ), - if (word.note != null) MarkdownText(word.note!), + ), ], + icon: const Icon(Icons.share_rounded), ), - if (word.forms.isNotEmpty) - SamplesColumn( - word.forms, - inline: true, - ), - for (final u in word.uses) ...[ - ColumnCard( - divider: const SizedBox(height: 4), - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), - children: [ - Text( - capitalize(u.term), - style: theme.headline6?.copyWith(fontSize: 18), - ), - if (u.tags.isNotEmpty) - Text( - prettyTags(u.tags)!, - style: theme.caption, - ), - if (u.note != null) MarkdownText(u.note!), - ], - ), - if (u.examples.isNotEmpty) SamplesColumn(u.examples), - ], - if (word.contribution != null) - const Caption( - 'Unverified', - icon: Icons.unpublished_rounded, - ), + const SizedBox(width: 4), ], ), + floatingActionButton: onEdit == null + ? null + : FloatingActionButton( + child: const Icon(Icons.edit_rounded), + onPressed: () async { + context.popRoute(); + onEdit!(word); + }, + ), + body: WordView( + word, + scroll: ModalScrollController.of(context), + ), ); } } diff --git a/lib/modules/dictionary/screens/word_editor.dart b/lib/modules/dictionary/screens/word_editor.dart index ced832d5..48fb711d 100644 --- a/lib/modules/dictionary/screens/word_editor.dart +++ b/lib/modules/dictionary/screens/word_editor.dart @@ -1,13 +1,15 @@ +import 'package:auto_route/auto_route.dart'; import 'package:avzag/modules/dictionary/widgets/samples_editor.dart'; -import 'package:avzag/shared/utils/utils.dart'; +import 'package:avzag/shared/extensions.dart'; +import 'package:avzag/shared/modals/danger_dialog.dart'; import 'package:avzag/shared/widgets/column_card.dart'; import 'package:avzag/shared/widgets/compact_input.dart'; import 'package:avzag/shared/widgets/language_flag.dart'; -import 'package:avzag/shared/widgets/modals/danger_dialog.dart'; import 'package:avzag/shared/widgets/options_button.dart'; import 'package:avzag/shared/widgets/rounded_back_button.dart'; import 'package:avzag/store.dart'; import 'package:flutter/material.dart'; +import 'package:modal_bottom_sheet/modal_bottom_sheet.dart'; import '../models/use.dart'; import '../models/word.dart'; @@ -16,13 +18,11 @@ import '../services/word.dart'; class WordEditorScreen extends StatefulWidget { const WordEditorScreen( this.word, { - this.scroll, this.onDone, Key? key, }) : super(key: key); final Word word; - final ScrollController? scroll; final VoidCallback? onDone; @override @@ -31,10 +31,10 @@ class WordEditorScreen extends StatefulWidget { class _WordEditorScreenState extends State { final form = GlobalKey(); - Word get word => widget.word; + late final word = widget.word; void exit() { - Navigator.pop(context); + context.popRoute(); widget.onDone?.call(); } @@ -43,7 +43,7 @@ class _WordEditorScreenState extends State { return Scaffold( appBar: AppBar( leading: const RoundedBackButton(), - title: Text(capitalize(word.language)), + title: Text(word.language.titled), actions: [ Opacity( opacity: .5, @@ -57,17 +57,17 @@ class _WordEditorScreenState extends State { OptionsButton( [ OptionItem.simple( - Icons.cancel_rounded, + Icons.close_rounded, 'Discard', - exit, + onTap: exit, ), - if (word.id != null && EditorStore.admin) + if (word.id.isNotEmpty && EditorStore.admin) OptionItem.simple( - Icons.delete_forever_rounded, + Icons.delete_rounded, 'Delete', - () => deleteWord( + onTap: () => deleteWord( context, - word.id!, + word.id, after: exit, ), ), @@ -92,7 +92,7 @@ class _WordEditorScreenState extends State { key: form, autovalidateMode: AutovalidateMode.onUserInteraction, child: ListView( - controller: widget.scroll, + controller: ModalScrollController.of(context), padding: const EdgeInsets.only(bottom: 76), children: [ ColumnCard( @@ -129,6 +129,7 @@ class _WordEditorScreenState extends State { SamplesEditor('Add a form', word.forms), for (final u in word.uses) ...[ ColumnCard( + key: Key(u.term), divider: null, children: [ CompactInput( diff --git a/lib/modules/dictionary/screens/word_loader.dart b/lib/modules/dictionary/screens/word_loader.dart new file mode 100644 index 00000000..46c3deeb --- /dev/null +++ b/lib/modules/dictionary/screens/word_loader.dart @@ -0,0 +1,42 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:avzag/modules/dictionary/models/word.dart'; +import 'package:avzag/modules/dictionary/services/word.dart'; +import 'package:avzag/modules/navigation/screens/loader.dart'; +import 'package:avzag/modules/navigation/services/router.gr.dart'; +import 'package:flutter/material.dart'; + +class WordLoaderScreen extends StatelessWidget { + const WordLoaderScreen( + @pathParam this.id, { + this.onEdit, + Key? key, + }) : super(key: key); + + final String id; + final void Function(Word)? onEdit; + + @override + Widget build(BuildContext context) { + return LoaderScreen( + loadWord(id), + then: (context, word) async { + final router = context.router; + if (word == null) { + router.navigate(const DictionaryRoute()); + } else { + final router = context.router; + await router.replace( + WordRoute( + word: word, + id: word.id, + onEdit: onEdit, + ), + ); + if (router.stack.length < 2) { + router.navigate(const DictionaryRoute()); + } + } + }, + ); + } +} diff --git a/lib/modules/dictionary/screens/words_diff.dart b/lib/modules/dictionary/screens/words_diff.dart index 4ff13f99..5a79143b 100644 --- a/lib/modules/dictionary/screens/words_diff.dart +++ b/lib/modules/dictionary/screens/words_diff.dart @@ -1,7 +1,9 @@ -import 'package:avzag/modules/dictionary/screens/word.dart'; -import 'package:avzag/shared/utils/utils.dart'; +import 'package:auto_route/auto_route.dart'; +import 'package:avzag/modules/dictionary/widgets/word_view.dart'; +import 'package:avzag/shared/extensions.dart'; import 'package:avzag/shared/widgets/caption.dart'; import 'package:avzag/shared/widgets/language_flag.dart'; +import 'package:avzag/shared/widgets/options_button.dart'; import 'package:avzag/shared/widgets/rounded_back_button.dart'; import 'package:flutter/material.dart'; @@ -12,13 +14,11 @@ class WordsDiffScreen extends StatelessWidget { const WordsDiffScreen( this.base, this.overwrite, { - this.scroll, Key? key, }) : super(key: key); final Word? base; final Word overwrite; - final ScrollController? scroll; @override Widget build(BuildContext context) { @@ -26,20 +26,26 @@ class WordsDiffScreen extends StatelessWidget { length: 2, child: Scaffold( appBar: AppBar( - leading: RoundedBackButton( + leading: const RoundedBackButton( icon: Icons.close_rounded, ), - title: Text(capitalize(overwrite.language)), + title: Text(overwrite.language.titled), bottom: TabBar( labelColor: Theme.of(context).colorScheme.onSurface, tabs: [ Tab( - icon: Icon(Icons.adjust_rounded), - text: 'Base', + child: OptionItem.simple( + Icons.adjust_rounded, + 'Base', + centered: true, + ).widget, ), Tab( - icon: Icon(Icons.edit_rounded), - text: 'Overwrite', + child: OptionItem.simple( + Icons.edit_rounded, + 'Overwrite', + centered: true, + ).widget, ), ], ), @@ -56,11 +62,11 @@ class WordsDiffScreen extends StatelessWidget { IconButton( onPressed: () => deleteWord( context, - overwrite.id!, - after: () => Navigator.pop(context), + overwrite.id, + after: context.popRoute, title: 'Reject the contribution?', ), - icon: Icon(Icons.delete_forever), + icon: const Icon(Icons.delete_forever), tooltip: 'Reject', ), const SizedBox(width: 4), @@ -71,26 +77,20 @@ class WordsDiffScreen extends StatelessWidget { onPressed: () async => acceptContribution( context, overwrite, - after: () => Navigator.pop(context), + after: context.popRoute, ), ), body: TabBarView( children: [ base == null - ? Center( + ? const Center( child: Caption( 'No base word', icon: Icons.highlight_off_rounded, ), ) - : WordScreen( - base!, - embedded: true, - ), - WordScreen( - overwrite, - embedded: true, - ), + : WordView(base!), + WordView(overwrite), ], ), ), diff --git a/lib/modules/dictionary/services/sharing.dart b/lib/modules/dictionary/services/sharing.dart new file mode 100644 index 00000000..1c934173 --- /dev/null +++ b/lib/modules/dictionary/services/sharing.dart @@ -0,0 +1,47 @@ +import 'package:avzag/modules/dictionary/models/sample.dart'; +import 'package:avzag/shared/extensions.dart'; +import 'package:markdown/markdown.dart'; + +import '../models/word.dart'; + +String _getWordLink(Word word) => + 'https://avzag.raxys.app/dictionary/${word.id}'; + +String previewArticle(Word word) => ''' +🌄 Avzag • ${word.language.titled} +🔖 ${word.headword.titled} — ${word.uses.map((u) => u.term.titled).join(', ')} +${_getWordLink(word)} +'''; + +String _cleanMarkdown(String md) => markdownToHtml(md, inlineOnly: true) + .replaceAll(RegExp(r'<[^>]*>|&[^;]+;'), '') + .trim(); + +String textifyArticle(Word word) { + String tags(Iterable ts) => '#️⃣ ${ts.join(", ")}'; + Iterable samples(Iterable ss) => ss.map( + (s) => [ + '🔹 ${s.text}', + if (s.meaning != null) ' • ${s.meaning!}', + ].join(), + ); + String note(String n) => '📝 ${_cleanMarkdown(n)}'; + + final article = [ + '🌄 Avzag • ${word.language.titled}', + _getWordLink(word), + '\n🔖 ${word.headword.titled}', + if (word.ipa != null) '🔉 ${word.ipa}', + if (word.tags.isNotEmpty) tags(word.tags), + if (word.note?.isNotEmpty ?? false) note(word.note!), + if (word.forms.isNotEmpty) ...samples(word.forms), + if (word.uses.isNotEmpty) + for (final use in word.uses) ...[ + '\n💡 ${use.term.titled}', + if (use.tags.isNotEmpty) tags(use.tags), + if (use.note?.isNotEmpty ?? false) note(use.note!), + if (use.examples.isNotEmpty) ...samples(use.examples), + ], + ]; + return article.join('\n'); +} diff --git a/lib/modules/dictionary/services/sheets.dart b/lib/modules/dictionary/services/sheets.dart deleted file mode 100644 index 2fe35768..00000000 --- a/lib/modules/dictionary/services/sheets.dart +++ /dev/null @@ -1,69 +0,0 @@ -import 'package:avzag/modules/dictionary/screens/word_editor.dart'; -import 'package:avzag/modules/dictionary/screens/words_diff.dart'; -import 'package:avzag/shared/widgets/modals/loading_dialog.dart'; -import 'package:avzag/shared/widgets/modals/scrollable_modal_sheet.dart'; -import 'package:avzag/shared/widgets/modals/snackbar_manager.dart'; -import 'package:flutter/cupertino.dart'; - -import '../models/word.dart'; -import '../screens/word.dart'; -import 'word.dart'; - -Future diffWords( - BuildContext context, - String id, [ - ValueSetter? onEdit, -]) async { - final overwrite = await showLoadingDialog(context, loadWord(id)); - if (overwrite?.contribution == null) return showSnackbar(context); - final base = await showLoadingDialog( - context, - loadWord(overwrite?.contribution?.overwriteId), - ); - await showScrollableModalSheet( - context: context, - builder: (context, scroll) { - return WordsDiffScreen( - base, - overwrite!, - scroll: scroll, - ); - }, - ); -} - -Future openWord( - BuildContext context, - String id, [ - ValueSetter? onEdit, -]) async { - final word = await showLoadingDialog(context, loadWord(id)); - if (word == null) return showSnackbar(context); - await showScrollableModalSheet( - context: context, - builder: (context, scroll) { - return WordScreen( - word, - scroll: scroll, - onEdit: onEdit, - ); - }, - ); -} - -Future editWord( - BuildContext context, - Word word, [ - VoidCallback? onDone, -]) async { - await showScrollableModalSheet( - context: context, - builder: (context, scroll) { - return WordEditorScreen( - word, - scroll: scroll, - onDone: onDone, - ); - }, - ); -} diff --git a/lib/modules/dictionary/services/word.dart b/lib/modules/dictionary/services/word.dart index 64622402..5124671e 100644 --- a/lib/modules/dictionary/services/word.dart +++ b/lib/modules/dictionary/services/word.dart @@ -1,7 +1,7 @@ -import 'package:avzag/shared/utils/contribution.dart'; -import 'package:avzag/shared/widgets/modals/danger_dialog.dart'; -import 'package:avzag/shared/widgets/modals/loading_dialog.dart'; -import 'package:avzag/shared/widgets/modals/snackbar_manager.dart'; +import 'package:avzag/models/contribution.dart'; +import 'package:avzag/shared/modals/danger_dialog.dart'; +import 'package:avzag/shared/modals/loading_dialog.dart'; +import 'package:avzag/shared/modals/snackbar_manager.dart'; import 'package:avzag/store.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/material.dart'; @@ -54,7 +54,7 @@ void submitWord( text: 'Must have at least one use', ); } - var id = word.id; + String? id = word.id; var doc = word.toJson(); if (!EditorStore.admin) { doc['contribution'] = Contribution( diff --git a/lib/modules/dictionary/widgets/entry_group.dart b/lib/modules/dictionary/widgets/entry_group.dart index 38379362..ef8ff15b 100644 --- a/lib/modules/dictionary/widgets/entry_group.dart +++ b/lib/modules/dictionary/widgets/entry_group.dart @@ -1,5 +1,5 @@ import 'package:avzag/modules/dictionary/models/entry.dart'; -import 'package:avzag/shared/utils/utils.dart'; +import 'package:avzag/shared/extensions.dart'; import 'package:avzag/shared/widgets/column_card.dart'; import 'package:flutter/material.dart'; @@ -34,7 +34,7 @@ class EntryGroup extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.baseline, children: [ Text( - capitalize(groups.first.first.term), + groups.first.first.term.titled, style: TextStyle( color: theme.caption?.color, fontWeight: FontWeight.w500, @@ -45,11 +45,7 @@ class EntryGroup extends StatelessWidget { child: Padding( padding: const EdgeInsets.only(left: 8), child: Text( - prettyTags( - tags, - separator: ' ', - capitalized: false, - )!, + tags.join(', '), maxLines: 1, overflow: TextOverflow.ellipsis, style: theme.caption, diff --git a/lib/modules/dictionary/widgets/entry_tile.dart b/lib/modules/dictionary/widgets/entry_tile.dart index 6f7e23cf..647260fd 100644 --- a/lib/modules/dictionary/widgets/entry_tile.dart +++ b/lib/modules/dictionary/widgets/entry_tile.dart @@ -1,7 +1,8 @@ -import 'package:avzag/shared/utils/utils.dart'; +import 'package:avzag/shared/extensions.dart'; import 'package:avzag/shared/widgets/span_icon.dart'; import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; import '../models/entry.dart'; @@ -32,8 +33,9 @@ class EntryTile extends StatelessWidget { padding: EdgeInsets.only(right: 4), ), Text( - capitalize(hit.headword), - style: theme.subtitle1?.copyWith( + hit.headword.titled, + style: GoogleFonts.bitter( + textStyle: theme.subtitle1, fontWeight: FontWeight.w500, ), ), @@ -41,8 +43,9 @@ class EntryTile extends StatelessWidget { Padding( padding: const EdgeInsets.only(left: 4), child: Text( - capitalize(hit.form!), - style: theme.subtitle1?.copyWith( + hit.form!.titled, + style: GoogleFonts.bitter( + textStyle: theme.subtitle1, fontWeight: FontWeight.w500, color: theme.caption?.color, ), @@ -51,7 +54,7 @@ class EntryTile extends StatelessWidget { const Spacer(), if (showLanguage) Text( - capitalize(hit.language), + hit.language.titled, style: theme.caption, ), ], diff --git a/lib/modules/dictionary/widgets/samples_column.dart b/lib/modules/dictionary/widgets/samples_column.dart index 1ebdf068..786b1998 100644 --- a/lib/modules/dictionary/widgets/samples_column.dart +++ b/lib/modules/dictionary/widgets/samples_column.dart @@ -1,5 +1,6 @@ -import 'package:avzag/shared/utils/text.dart'; +import 'package:avzag/shared/utils.dart'; import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; import '../models/sample.dart'; class SamplesColumn extends StatelessWidget { @@ -41,7 +42,12 @@ class SamplesColumn extends StatelessWidget { text: TextSpan( style: theme.bodyText2, children: [ - TextSpan(text: s.text), + TextSpan( + text: s.text, + style: GoogleFonts.bitter( + fontWeight: FontWeight.w500, + ), + ), if (s.meaning != null) ...[ TextSpan(text: inline ? ' ' : '\n'), TextSpan( diff --git a/lib/modules/dictionary/widgets/search_toolbar.dart b/lib/modules/dictionary/widgets/search_toolbar.dart index 9922ed14..3d57cce6 100644 --- a/lib/modules/dictionary/widgets/search_toolbar.dart +++ b/lib/modules/dictionary/widgets/search_toolbar.dart @@ -1,6 +1,6 @@ import 'dart:async'; -import 'package:avzag/shared/utils/utils.dart'; +import 'package:avzag/shared/extensions.dart'; import 'package:avzag/shared/widgets/language_avatar.dart'; import 'package:avzag/shared/widgets/options_button.dart'; import 'package:avzag/store.dart'; @@ -71,22 +71,22 @@ class SearchToolbarState extends State { OptionItem.simple( Icons.language_rounded, GlobalStore.languages.length == 1 ? 'English' : 'Multilingual', - () => setLanguage(''), + onTap: () => setLanguage(''), ), OptionItem.simple( Icons.layers_rounded, 'Cross-lingual', - () => setLanguage('_'), + onTap: () => setLanguage('_'), ), OptionItem.divider(), for (final l in GlobalStore.languages.keys) OptionItem.tile( LanguageAvatar(l), Text( - capitalize(l), + l.titled, style: const TextStyle(fontWeight: FontWeight.w500), ), - () => setLanguage(l), + onTap: () => setLanguage(l), ) ], icon: Builder(builder: (context) { @@ -106,7 +106,7 @@ class SearchToolbarState extends State { builder: (context) { var label = 'Search '; label += search.monolingual - ? 'forms in ${capitalize(search.language)}' + ? 'forms in ${search.language.titled}' : '${search.language.isEmpty ? 'over' : 'across'} the languages'; return TextField( controller: inputController, diff --git a/lib/modules/dictionary/widgets/word_view.dart b/lib/modules/dictionary/widgets/word_view.dart new file mode 100644 index 00000000..c3bdc1c9 --- /dev/null +++ b/lib/modules/dictionary/widgets/word_view.dart @@ -0,0 +1,111 @@ +import 'package:avzag/modules/dictionary/models/word.dart'; +import 'package:avzag/shared/extensions.dart'; +import 'package:avzag/shared/widgets/caption.dart'; +import 'package:avzag/shared/widgets/column_card.dart'; +import 'package:avzag/shared/widgets/markdown_text.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; + +import 'samples_column.dart'; + +class WordView extends StatelessWidget { + const WordView( + this.word, { + this.scroll, + Key? key, + }) : super(key: key); + + final Word word; + final ScrollController? scroll; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context).textTheme; + return ListView( + controller: scroll, + padding: const EdgeInsets.only(bottom: 76), + children: [ + ColumnCard( + divider: const SizedBox(height: 4), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 8, + ), + children: [ + Text( + word.headword.titled, + style: GoogleFonts.bitter( + textStyle: theme.headline5, + fontWeight: FontWeight.w500, + ), + ), + if (word.ipa != null) + Text( + '[ ${word.ipa!} ]', + style: GoogleFonts.notoSans( + textStyle: theme.bodyText1, + color: theme.caption?.color, + ), + ), + if (word.tags.isNotEmpty) + Text( + word.tags.join(', '), + style: theme.caption, + ), + if (word.note != null) MarkdownText(word.note!), + ], + ), + if (word.forms.isNotEmpty) + SamplesColumn( + word.forms, + inline: true, + ), + for (final u in word.uses) ...[ + ColumnCard( + divider: const SizedBox(height: 4), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 8, + ), + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Text( + u.term.titled, + style: theme.headline6, + ), + ), + if (u.aliases.isNotEmpty) + Tooltip( + message: u.aliases.join(' • ').titled, + child: Padding( + padding: const EdgeInsets.only(left: 8), + child: Icon( + Icons.label_rounded, + color: Theme.of(context).textTheme.caption?.color, + ), + ), + ) + ], + ), + if (u.tags.isNotEmpty) + Text( + u.tags.join(', '), + style: theme.caption, + ), + if (u.note != null) MarkdownText(u.note!), + ], + ), + if (u.examples.isNotEmpty) SamplesColumn(u.examples), + ], + if (word.contribution != null) + const Caption( + 'Unverified', + icon: Icons.unpublished_rounded, + ), + ], + ); + } +} diff --git a/lib/modules/home/screens/home.dart b/lib/modules/home/screens/home.dart index fef29ae3..00b3d48e 100644 --- a/lib/modules/home/screens/home.dart +++ b/lib/modules/home/screens/home.dart @@ -1,8 +1,8 @@ +import 'package:auto_route/auto_route.dart'; import 'package:avzag/models/language.dart'; -import 'package:avzag/modules/navigation/nav_drawer.dart'; -import 'package:avzag/shared/utils/utils.dart'; +import 'package:avzag/modules/navigation/services/router.gr.dart'; +import 'package:avzag/shared/extensions.dart'; import 'package:avzag/shared/widgets/language_avatar.dart'; -import 'package:avzag/shared/widgets/modals/loading_dialog.dart'; import 'package:avzag/shared/widgets/span_icon.dart'; import 'package:avzag/store.dart'; import 'package:badges/badges.dart'; @@ -48,8 +48,6 @@ class _HomeScreenState extends State { final orderings = [ _LanguageOrdering('name', icon: Icons.label_rounded), - _LanguageOrdering('family', icon: Icons.public_rounded), - null, _LanguageOrdering( 'dictionary', icon: Icons.book_rounded, @@ -57,7 +55,7 @@ class _HomeScreenState extends State { descending: true, ), ]; - late var ordering = orderings.first!; + late var ordering = orderings.first; late final Future loader; final chipsScroll = ScrollController(); @@ -146,14 +144,10 @@ class _HomeScreenState extends State { floatingActionButton: selected.isEmpty ? null : FloatingActionButton( - onPressed: () async { - await showLoadingDialog( - context, - GlobalStore.set(objects: selected), - ); - navigate(context); + onPressed: () { + GlobalStore.set(objects: selected); + context.navigateTo(const RootRoute()); }, - tooltip: 'Continue', child: const Icon(Icons.done_all_rounded), ), appBar: AppBar( @@ -190,7 +184,7 @@ class _HomeScreenState extends State { radius: 12, ), label: Text( - capitalize(language.name), + language.name.titled, style: const TextStyle( fontWeight: FontWeight.w500, ), @@ -252,24 +246,21 @@ class _HomeScreenState extends State { itemBuilder: (context) { return [ for (final ordering in orderings) - if (ordering == null) - const PopupMenuDivider(height: 0) - else - PopupMenuItem( - value: ordering, - child: ListTile( - leading: Icon(ordering.icon), - title: Text( - capitalize(ordering.text), - softWrap: false, - overflow: TextOverflow.fade, - style: const TextStyle( - fontWeight: FontWeight.w500, - ), + PopupMenuItem( + value: ordering, + child: ListTile( + leading: Icon(ordering.icon), + title: Text( + ordering.text.titled, + softWrap: false, + overflow: TextOverflow.fade, + style: const TextStyle( + fontWeight: FontWeight.w500, ), - selected: this.ordering == ordering, ), - ) + selected: this.ordering == ordering, + ), + ) ]; }, ), diff --git a/lib/modules/home/services/mapbox.dart b/lib/modules/home/services/mapbox.dart new file mode 100644 index 00000000..69f4dda2 --- /dev/null +++ b/lib/modules/home/services/mapbox.dart @@ -0,0 +1,18 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_map/flutter_map.dart'; + +TileLayerOptions getTileLayer([bool isDark = false]) { + const token = + 'pk.eyJ1IjoicmF4eXNzdHVkaW9zIiwiYSI6ImNsM2RoamIzaTAxbWYzZG4xNTJ4MWhoOGkifQ.bk09KPfb2EQuwtcxU-INrQ'; + final style = + isDark ? 'cl3hf82ox003315qg72h9wx5y' : 'cl3g6sr4x004o14o2ywap9fhb'; + final background = isDark ? const Color(0xff3b3b3b) : const Color(0xfff7f8f8); + return TileLayerOptions( + urlTemplate: + 'https://api.mapbox.com/styles/v1/raxysstudios/$style/tiles/{z}/{x}/{y}@2x?access_token=$token', + subdomains: ['a', 'b', 'c'], + backgroundColor: background, + tileSize: 512, + zoomOffset: -1, + ); +} diff --git a/lib/modules/home/widgets/language_card.dart b/lib/modules/home/widgets/language_card.dart index 27564b7b..4925fdb2 100644 --- a/lib/modules/home/widgets/language_card.dart +++ b/lib/modules/home/widgets/language_card.dart @@ -1,5 +1,5 @@ import 'package:avzag/models/language.dart'; -import 'package:avzag/shared/utils/utils.dart'; +import 'package:avzag/shared/extensions.dart'; import 'package:avzag/shared/widgets/language_flag.dart'; import 'package:avzag/shared/widgets/span_icon.dart'; import 'package:flutter/material.dart'; @@ -44,7 +44,7 @@ class LanguageCard extends StatelessWidget { selected: selected, minVerticalPadding: 16, title: Text( - capitalize(language.name), + language.name.titled, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.w500, diff --git a/lib/modules/home/widgets/languages_map.dart b/lib/modules/home/widgets/languages_map.dart index 1aec2888..5359a983 100644 --- a/lib/modules/home/widgets/languages_map.dart +++ b/lib/modules/home/widgets/languages_map.dart @@ -1,5 +1,6 @@ import 'package:avzag/models/language.dart'; -import 'package:avzag/shared/utils/utils.dart'; +import 'package:avzag/modules/home/services/mapbox.dart'; +import 'package:avzag/shared/extensions.dart'; import 'package:avzag/shared/widgets/language_avatar.dart'; import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; @@ -20,28 +21,20 @@ class LanguagesMap extends StatelessWidget { @override Widget build(context) { - final theme = Theme.of(context); - final mapStyleUrl = theme.brightness == Brightness.light - ? '4bfb6bd9-e4e9-42b5-abfe-9f90ecb11e6b' - : '5b319ec1-f075-4278-b743-31be8b4a0808'; - return FlutterMap( options: MapOptions( center: LatLng(43, 45), zoom: 5, + maxZoom: 9, + minZoom: 5, interactiveFlags: InteractiveFlag.pinchZoom | InteractiveFlag.drag, - plugins: [ - MarkerClusterPlugin(), - ], + plugins: [MarkerClusterPlugin()], + swPanBoundary: LatLng(41.1, 40), + nePanBoundary: LatLng(45, 48.1), ), layers: [ - TileLayerOptions( - urlTemplate: - 'https://tile.jawg.io/$mapStyleUrl/{z}/{x}/{y}.png?access-token=6F94UuT7990iq8Z5yQpnbyujlm0Zr7bZkJwMshoaTEtYnsabLMp2EttcF6fCoW10', - subdomains: ['a', 'b', 'c'], - backgroundColor: theme.brightness == Brightness.light - ? const Color(0xffcad2d3) - : const Color(0xff191a1a), + getTileLayer( + Theme.of(context).brightness == Brightness.dark, ), MarkerClusterLayerOptions( size: const Size.square(48), @@ -77,7 +70,7 @@ class LanguagesMap extends StatelessWidget { borderRadius: BorderRadius.circular(32), ), child: Tooltip( - message: capitalize(language.name), + message: language.name.titled, preferBelow: false, child: InkWell( onTap: () => onToggle(language), diff --git a/lib/modules/navigation/account.dart b/lib/modules/navigation/account.dart deleted file mode 100644 index 63f01508..00000000 --- a/lib/modules/navigation/account.dart +++ /dev/null @@ -1,98 +0,0 @@ -import 'package:avzag/modules/navigation/sign_in_buttons.dart'; -import 'package:avzag/shared/utils/open_link.dart'; -import 'package:avzag/shared/utils/utils.dart'; -import 'package:avzag/shared/widgets/column_card.dart'; -import 'package:avzag/shared/widgets/language_avatar.dart'; -import 'package:avzag/shared/widgets/span_icon.dart'; -import 'package:avzag/store.dart'; -import 'package:badges/badges.dart'; -import 'package:flutter/material.dart'; - -import 'nav_drawer.dart'; - -class AccountScreen extends StatefulWidget { - const AccountScreen({Key? key}) : super(key: key); - - @override - State createState() => _AccountScreenState(); -} - -class _AccountScreenState extends State { - var adminable = []; - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context).colorScheme; - return Scaffold( - appBar: AppBar( - automaticallyImplyLeading: false, - title: const Text('Account'), - centerTitle: true, - ), - floatingActionButton: FloatingActionButton( - onPressed: () => navigate(context), - tooltip: 'Continue', - child: const Icon(Icons.done_all_rounded), - ), - body: ListView( - padding: const EdgeInsets.only(bottom: 76), - children: [ - SignInButtons( - onSignOut: () => setState(() {}), - onSingIn: () => EditorStore.getAdminable().then( - (value) => setState(() { - adminable = value; - }), - ), - ), - if (EditorStore.user?.uid != null) - ColumnCard( - children: [ - for (final l in GlobalStore.languages.keys) - ListTile( - leading: Badge( - padding: EdgeInsets.zero, - ignorePointer: true, - badgeColor: theme.surface, - position: BadgePosition.topEnd(end: -20), - badgeContent: EditorStore.adminable.contains(l) - ? SpanIcon( - Icons.account_circle_rounded, - padding: const EdgeInsets.all(2), - color: theme.onSurface, - ) - : null, - child: LanguageAvatar(l), - ), - title: Text( - capitalize(l), - style: const TextStyle( - fontWeight: FontWeight.w500, - fontSize: 18, - ), - ), - onTap: () => setState(() { - EditorStore.language = - l == EditorStore.language ? null : l; - }), - selected: l == EditorStore.language, - trailing: Builder( - builder: (context) { - final contact = GlobalStore.languages[l]?.contact; - return contact == null - ? const SizedBox() - : IconButton( - onPressed: () => openLink(contact), - icon: const Icon(Icons.send_rounded), - tooltip: 'Contact admin', - ); - }, - ), - ), - ], - ), - ], - ), - ); - } -} diff --git a/lib/modules/navigation/nav_drawer.dart b/lib/modules/navigation/nav_drawer.dart deleted file mode 100644 index 76e37beb..00000000 --- a/lib/modules/navigation/nav_drawer.dart +++ /dev/null @@ -1,183 +0,0 @@ -import 'package:avzag/modules/dictionary/screens/dictionary.dart'; -import 'package:avzag/modules/home/screens/home.dart'; -import 'package:avzag/shared/utils/open_link.dart'; -import 'package:avzag/shared/utils/utils.dart'; -import 'package:avzag/shared/widgets/column_card.dart'; -import 'package:avzag/shared/widgets/expandable_tile.dart'; -import 'package:avzag/shared/widgets/raxys_logo.dart'; -import 'package:avzag/shared/widgets/span_icon.dart'; -import 'package:avzag/store.dart'; -import 'package:flutter/material.dart'; -import 'package:package_info_plus/package_info_plus.dart'; -import 'package:shared_preferences/shared_preferences.dart'; - -import 'account.dart'; - -Future navigate( - BuildContext context, [ - String? title, -]) async { - final prefs = await SharedPreferences.getInstance(); - if (title == null) { - title = prefs.getString('module'); - if (title == null || title == 'home') title = 'dictionary'; - } - - late Widget Function(BuildContext) builder; - if (title == 'home') { - builder = (_) => const HomeScreen(); - title = null; - } else if (title == 'dictionary') { - builder = (_) => const DictionaryScreen(); - } else { - builder = (_) => const Text('No Route'); - } - - if (title != null) await prefs.setString('module', title); - await Navigator.pushReplacement( - context, - MaterialPageRoute(builder: builder), - ); -} - -class _NavModule { - final IconData icon; - final String text; - _NavModule(this.icon, this.text); - - Widget build(BuildContext context, [String? route]) { - final enabled = route != null; - return ListTile( - leading: Icon(icon), - title: Text( - capitalize(text), - style: const TextStyle(fontSize: 18), - ), - trailing: enabled ? null : const Icon(Icons.construction_rounded), - selected: route == text, - onTap: enabled ? () => navigate(context, text) : null, - enabled: enabled, - ); - } -} - -class NavDraver extends StatelessWidget { - final String? title; - - const NavDraver({ - Key? key, - this.title, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return Drawer( - child: Material( - color: Theme.of(context).scaffoldBackgroundColor, - child: ListView( - children: [ - ExpandableTile( - header: const ListTile( - leading: RaxysLogo( - opacity: .1, - scale: 7, - ), - contentPadding: EdgeInsets.only(left: 16), - title: Text( - 'Ævzag', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), - ), - ), - body: ColumnCard( - divider: null, - margin: const EdgeInsets.only(bottom: 12), - children: [ - ListTile( - leading: const Padding( - padding: EdgeInsets.only(top: 8), - child: Icon(Icons.send_rounded), - ), - title: const Text('Developer Contact'), - subtitle: const Text('Raxys Studios'), - onTap: () => openLink('https://t.me/raxysstudios'), - ), - FutureBuilder( - future: PackageInfo.fromPlatform(), - builder: (context, snapshot) { - var info = 'Loading...'; - final package = snapshot.data; - if (package != null) { - info = [ - 'v${package.version}', - 'b${package.buildNumber}' - ].join(' • '); - } - return ListTile( - leading: const Padding( - padding: EdgeInsets.only(top: 8), - child: Icon(Icons.code_rounded), - ), - title: const Text('GitHub Repository'), - subtitle: Text(info), - onTap: () => openLink( - 'https://github.com/raxysstudios/avzag', - ), - ); - }, - ), - SwitchListTile( - title: const Text('Editor Mode'), - subtitle: Row( - children: [ - if (EditorStore.editor) ...[ - if (EditorStore.admin) - const SpanIcon(Icons.account_circle_rounded), - Text(capitalize(EditorStore.language)), - ] else - const Text('Off') - ], - ), - value: EditorStore.editor, - secondary: const Padding( - padding: EdgeInsets.only(top: 8), - child: Icon(Icons.edit_rounded), - ), - onChanged: (e) => Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const AccountScreen(), - ), - ), - ), - ], - ), - ), - ColumnCard( - divider: null, - margin: EdgeInsets.zero, - children: [ - _NavModule( - Icons.home_rounded, - 'home', - ).build(context, title), - _NavModule( - Icons.book_rounded, - 'dictionary', - ).build(context, title), - ...[ - _NavModule(Icons.music_note_rounded, 'phonology'), - _NavModule(Icons.switch_left_rounded, 'converter'), - _NavModule(Icons.forum_rounded, 'phrasebook'), - _NavModule(Icons.local_library_rounded, 'bootcamp'), - ].map((t) => t.build(context)), - ], - ) - ], - ), - ), - ); - } -} diff --git a/lib/modules/navigation/screens/loader.dart b/lib/modules/navigation/screens/loader.dart new file mode 100644 index 00000000..822c44ce --- /dev/null +++ b/lib/modules/navigation/screens/loader.dart @@ -0,0 +1,41 @@ +import 'dart:async'; + +import 'package:avzag/shared/modals/loading_dialog.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; + +class LoaderScreen extends StatefulWidget { + const LoaderScreen( + this.future, { + required this.then, + Key? key, + }) : super(key: key); + + final Future future; + final void Function(BuildContext, T?) then; + + @override + State> createState() => _LoaderScreenState(); +} + +class _LoaderScreenState extends State> { + T? result; + + @override + void initState() { + super.initState(); + SchedulerBinding.instance.addPostFrameCallback( + (_) async { + widget.then( + context, + await showLoadingDialog(context, widget.future), + ); + }, + ); + } + + @override + Widget build(BuildContext context) { + return const SizedBox(); + } +} diff --git a/lib/modules/navigation/screens/navigation.dart b/lib/modules/navigation/screens/navigation.dart new file mode 100644 index 00000000..b2263a91 --- /dev/null +++ b/lib/modules/navigation/screens/navigation.dart @@ -0,0 +1,84 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:avzag/modules/navigation/widgets/github_tile.dart'; +import 'package:avzag/modules/navigation/widgets/module_tile.dart'; +import 'package:avzag/modules/navigation/widgets/stores_buttons.dart'; +import 'package:avzag/shared/extensions.dart'; +import 'package:avzag/shared/utils.dart'; +import 'package:avzag/shared/widgets/column_card.dart'; +import 'package:avzag/shared/widgets/expandable_tile.dart'; +import 'package:avzag/shared/widgets/raxys.dart'; +import 'package:avzag/shared/widgets/span_icon.dart'; +import 'package:avzag/store.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +import '../services/modules.dart'; +import '../services/router.gr.dart'; + +class NavigationScreen extends StatelessWidget { + const NavigationScreen({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Drawer( + child: Material( + color: Theme.of(context).scaffoldBackgroundColor, + child: ListView( + children: [ + ExpandableTile( + header: ListTile( + leading: const Raxys( + opacity: .1, + scale: 7, + ), + title: Text( + 'Ævzag', + style: Theme.of(context).textTheme.headline6, + ), + ), + body: ColumnCard( + divider: null, + margin: const EdgeInsets.only(bottom: 12), + children: [ + ListTile( + leading: const Icon(Icons.send_rounded), + title: const Text('Developer Contact'), + subtitle: const Text('Raxys Studios'), + onTap: () => openLink('https://t.me/raxysstudios'), + ), + const GitHubTile(), + SwitchListTile( + title: const Text('Editor Mode'), + subtitle: EditorStore.editor + ? Row( + children: [ + if (EditorStore.admin) + const SpanIcon(Icons.account_circle_rounded), + Text(EditorStore.language!.titled), + ], + ) + : null, + value: EditorStore.editor, + secondary: const Icon(Icons.edit_rounded), + onChanged: (e) => context.pushRoute(const AccountRoute()), + ), + if (kIsWeb) ...[ + const Divider(), + const StoresButtons(), + ], + ], + ), + ), + ColumnCard( + divider: null, + margin: EdgeInsets.zero, + children: [ + for (final m in modules) ModuleTile(m), + ], + ) + ], + ), + ), + ); + } +} diff --git a/lib/modules/navigation/services/modules.dart b/lib/modules/navigation/services/modules.dart new file mode 100644 index 00000000..8941f526 --- /dev/null +++ b/lib/modules/navigation/services/modules.dart @@ -0,0 +1,33 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +import 'router.gr.dart'; + +class NavModule { + const NavModule( + this.icon, + this.text, [ + this.route, + ]); + + final IconData icon; + final String text; + final PageRouteInfo? route; +} + +const modules = [ + NavModule( + Icons.home_rounded, + 'home', + HomeRoute(), + ), + NavModule( + Icons.book_rounded, + 'dictionary', + DictionaryRoute(), + ), + NavModule(Icons.music_note_rounded, 'phonology'), + NavModule(Icons.switch_left_rounded, 'converter'), + NavModule(Icons.forum_rounded, 'phrasebook'), + NavModule(Icons.local_library_rounded, 'bootcamp'), +]; diff --git a/lib/modules/navigation/services/root_guard.dart b/lib/modules/navigation/services/root_guard.dart new file mode 100644 index 00000000..e3ee3b45 --- /dev/null +++ b/lib/modules/navigation/services/root_guard.dart @@ -0,0 +1,23 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:avzag/store.dart'; + +import 'modules.dart'; +import 'router.gr.dart'; + +class RootGuard extends AutoRouteGuard { + @override + void onNavigation(NavigationResolver resolver, StackRouter router) { + var route = router.hasEntries ? const DictionaryRoute() : const HomeRoute(); + final saved = prefs.getString('module'); + for (final m in modules) { + if (saved == m.text && m.route != null) { + route = m.route!; + break; + } + } + if (saved == null && router.hasEntries) { + prefs.setString('module', 'dictionary'); + } + router.pushAndPopUntil(route, predicate: (_) => true); + } +} diff --git a/lib/modules/navigation/services/router.dart b/lib/modules/navigation/services/router.dart new file mode 100644 index 00000000..b30900b5 --- /dev/null +++ b/lib/modules/navigation/services/router.dart @@ -0,0 +1,91 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:avzag/modules/account/screens/account.dart'; +import 'package:avzag/modules/dictionary/screens/dictionary.dart'; +import 'package:avzag/modules/dictionary/screens/word.dart'; +import 'package:avzag/modules/dictionary/screens/word_editor.dart'; +import 'package:avzag/modules/dictionary/screens/word_loader.dart'; +import 'package:avzag/modules/dictionary/screens/words_diff.dart'; +import 'package:avzag/modules/home/screens/home.dart'; +import 'package:flutter/material.dart'; +import 'package:modal_bottom_sheet/modal_bottom_sheet.dart'; + +import 'root_guard.dart'; + +@MaterialAutoRouter( + replaceInRouteName: 'Screen,Route', + routes: [ + AutoRoute( + path: '/', + page: EmptyRouterScreen, + name: 'RootRoute', + guards: [RootGuard], + ), + AutoRoute( + path: '/account', + page: AccountScreen, + ), + AutoRoute( + path: '/home', + page: HomeScreen, + ), + AutoRoute( + path: '/dictionary', + page: EmptyRouterScreen, + name: 'DictionaryRoute', + children: [ + AutoRoute( + path: '', + page: DictionaryScreen, + name: '_DictionaryRoute', + ), + CustomRoute( + path: ':id', + page: WordLoaderScreen, + customRouteBuilder: dialogRouteBuilder, + ), + CustomRoute( + path: ':id', + page: WordScreen, + customRouteBuilder: sheetRouteBuilder, + ), + CustomRoute( + path: 'editor', + page: WordEditorScreen, + customRouteBuilder: sheetRouteBuilder, + ), + CustomRoute( + path: 'diff', + page: WordsDiffScreen, + customRouteBuilder: sheetRouteBuilder, + ), + ], + ), + RedirectRoute(path: '*', redirectTo: '/') + ], +) +class $AppRouter {} + +Route dialogRouteBuilder( + BuildContext context, + Widget child, + CustomPage page, +) { + return DialogRoute( + settings: page, + context: context, + builder: (context) => child, + barrierColor: Colors.transparent, + ); +} + +Route sheetRouteBuilder( + BuildContext context, + Widget child, + CustomPage page, +) { + return ModalBottomSheetRoute( + settings: page, + builder: (context) => child, + expanded: true, + ); +} diff --git a/lib/modules/navigation/sign_in_buttons.dart b/lib/modules/navigation/sign_in_buttons.dart deleted file mode 100644 index 84d15967..00000000 --- a/lib/modules/navigation/sign_in_buttons.dart +++ /dev/null @@ -1,181 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; -import 'dart:io' show Platform; -import 'dart:math'; - -import 'package:crypto/crypto.dart'; -import 'package:firebase_auth/firebase_auth.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:google_sign_in/google_sign_in.dart'; -import 'package:sign_in_with_apple/sign_in_with_apple.dart' as apple; - -class SignInButtons extends StatefulWidget { - const SignInButtons({ - this.onSignOut, - this.onSingIn, - Key? key, - }) : super(key: key); - - final FutureOr Function()? onSingIn; - final FutureOr Function()? onSignOut; - - @override - State createState() => _SignInButtonsState(); -} - -class _SignInButtonsState extends State { - var loading = false; - - Future signIn( - Future Function() getCredentials, - ) async { - await signOut(); - setState(() { - loading = true; - }); - final credentials = await getCredentials(); - if (credentials != null) { - await FirebaseAuth.instance.signInWithCredential(credentials); - await widget.onSingIn?.call(); - } - setState(() { - loading = false; - }); - } - - Future signOut() async { - setState(() { - loading = true; - }); - final provider = - FirebaseAuth.instance.currentUser?.providerData.first.providerId; - if (provider == null) return; - - await FirebaseAuth.instance.signOut(); - switch (provider) { - case 'google.com': - await GoogleSignIn().signOut(); - break; - } - await widget.onSignOut?.call(); - setState(() { - loading = false; - }); - } - - Future getGoogleCredentials() async { - final user = await GoogleSignIn().signIn(); - if (user != null) { - final auth = await user.authentication; - return GoogleAuthProvider.credential( - accessToken: auth.accessToken, - idToken: auth.idToken, - ); - } - return null; - } - - Future getAppleCredentials() async { - String generateNonce([int length = 32]) { - const charset = - '0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._'; - final random = Random.secure(); - return List.generate( - length, (_) => charset[random.nextInt(charset.length)]).join(); - } - - String sha256ofString(String input) { - final bytes = utf8.encode(input); - final digest = sha256.convert(bytes); - return digest.toString(); - } - - if (kIsWeb) { - final provider = OAuthProvider('apple.com') - ..addScope('email') - ..addScope('name'); - await FirebaseAuth.instance.signInWithPopup(provider); - } else { - final rawNonce = generateNonce(); - final nonce = sha256ofString(rawNonce); - var redirectURL = 'https://avzagapp.firebaseapp.com/__/auth/handler'; - var clientID = 'avzagapp'; - final appleIdCredential = - await apple.SignInWithApple.getAppleIDCredential( - scopes: [ - apple.AppleIDAuthorizationScopes.email, - apple.AppleIDAuthorizationScopes.fullName, - ], - webAuthenticationOptions: apple.WebAuthenticationOptions( - clientId: clientID, - redirectUri: Uri.parse(redirectURL), - ), - nonce: nonce, - ); - // Create an `OAuthCredential` from the credential returned by Apple. - return OAuthProvider('apple.com').credential( - idToken: appleIdCredential.identityToken, - accessToken: appleIdCredential.authorizationCode, - rawNonce: rawNonce, - ); - } - return null; - } - - @override - Widget build(BuildContext context) { - if (loading) { - return const Center( - child: Padding( - padding: EdgeInsets.all(8), - child: SizedBox.square( - dimension: 24, - child: CircularProgressIndicator(), - ), - ), - ); - } - if (FirebaseAuth.instance.currentUser != null) { - final user = FirebaseAuth.instance.currentUser!; - return ListTile( - leading: CircleAvatar( - backgroundImage: - user.photoURL == null ? null : NetworkImage(user.photoURL!), - backgroundColor: Colors.transparent, - ), - title: Text(user.displayName ?? '[no name]'), - subtitle: Text(user.email ?? '[no email]'), - trailing: IconButton( - onPressed: signOut, - icon: const Icon(Icons.logout_rounded), - tooltip: 'Sign out', - ), - ); - } - return Padding( - padding: const EdgeInsets.all(8), - child: Row( - children: [ - Expanded( - child: OutlinedButton.icon( - onPressed: () => signIn(getGoogleCredentials), - icon: const Icon(Icons.login_rounded), - label: const Text('Sign in with Google'), - ), - ), - if (kIsWeb || Platform.isIOS) ...[ - const SizedBox(width: 8), - Expanded( - child: OutlinedButton.icon( - onPressed: () => signIn(getAppleCredentials), - icon: const Icon(Icons.login_rounded), - label: const Text('Sign in with Apple'), - ), - ), - ], - ], - ), - ); - } -} diff --git a/lib/modules/navigation/widgets/github_tile.dart b/lib/modules/navigation/widgets/github_tile.dart new file mode 100644 index 00000000..e3061b12 --- /dev/null +++ b/lib/modules/navigation/widgets/github_tile.dart @@ -0,0 +1,36 @@ +import 'package:avzag/shared/utils.dart'; +import 'package:flutter/material.dart'; +import 'package:package_info_plus/package_info_plus.dart'; + +class GitHubTile extends StatefulWidget { + const GitHubTile({Key? key}) : super(key: key); + + @override + State createState() => _GitHubTileState(); +} + +class _GitHubTileState extends State { + var info = 'Loading...'; + + @override + void initState() { + super.initState(); + PackageInfo.fromPlatform().then( + (package) => setState(() { + info = 'v${package.version} • b${package.buildNumber}'; + }), + ); + } + + @override + Widget build(BuildContext context) { + return ListTile( + leading: const Icon(Icons.code_rounded), + title: const Text('GitHub Repository'), + subtitle: Text(info), + onTap: () => openLink( + 'https://github.com/raxysstudios/avzag', + ), + ); + } +} diff --git a/lib/modules/navigation/widgets/module_tile.dart b/lib/modules/navigation/widgets/module_tile.dart new file mode 100644 index 00000000..18c21dcf --- /dev/null +++ b/lib/modules/navigation/widgets/module_tile.dart @@ -0,0 +1,37 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:avzag/modules/navigation/services/modules.dart'; +import 'package:avzag/shared/extensions.dart'; +import 'package:avzag/store.dart'; +import 'package:flutter/material.dart'; + +import '../services/router.gr.dart'; + +class ModuleTile extends StatelessWidget { + const ModuleTile( + this.module, { + Key? key, + }) : super(key: key); + + final NavModule module; + + @override + Widget build(BuildContext context) { + return ListTile( + leading: Icon(module.icon), + title: Text( + module.text.titled, + style: const TextStyle(fontSize: 18), + ), + trailing: + module.route == null ? const Icon(Icons.construction_rounded) : null, + selected: context.router.currentPath.startsWith(module.route?.path ?? ''), + onTap: () async { + if (module.route != const HomeRoute()) { + await prefs.setString('module', module.text); + } + context.pushRoute(module.route!); + }, + enabled: module.route != null, + ); + } +} diff --git a/lib/modules/navigation/widgets/stores_buttons.dart b/lib/modules/navigation/widgets/stores_buttons.dart new file mode 100644 index 00000000..f7cde028 --- /dev/null +++ b/lib/modules/navigation/widgets/stores_buttons.dart @@ -0,0 +1,33 @@ +import 'package:avzag/shared/utils.dart'; +import 'package:flutter/material.dart'; + +class StoresButtons extends StatelessWidget { + const StoresButtons({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ListTile( + leading: const Icon(Icons.get_app_rounded), + title: Row( + children: [ + Expanded( + child: TextButton( + onPressed: () => openLink( + 'https://play.google.com/store/apps/details?id=com.alkaitagi.avzag', + ), + child: const Text('Google Play'), + ), + ), + Expanded( + child: TextButton( + onPressed: () => openLink( + 'https://apps.apple.com/app/avzag-languages-of-caucasus/id1603226004', + ), + child: const Text('App Store'), + ), + ), + ], + ), + ); + } +} diff --git a/lib/shared/extensions.dart b/lib/shared/extensions.dart new file mode 100644 index 00000000..377164a8 --- /dev/null +++ b/lib/shared/extensions.dart @@ -0,0 +1,15 @@ +extension Titled on String? { + String get titled { + final text = this; + if (text == null) return ''; + return text + .split(' ') + .where((s) => s.isNotEmpty) + .map((w) => w[0].toUpperCase() + w.substring(1)) + .join(' ') + .split('-') + .where((s) => s.isNotEmpty) + .map((w) => w[0].toUpperCase() + w.substring(1)) + .join('-'); + } +} diff --git a/lib/shared/modals/danger_dialog.dart b/lib/shared/modals/danger_dialog.dart new file mode 100644 index 00000000..2b8b55a8 --- /dev/null +++ b/lib/shared/modals/danger_dialog.dart @@ -0,0 +1,45 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +void showDangerDialog( + BuildContext context, + VoidCallback onConfirm, + String title, { + IconData confirmIcon = Icons.delete_rounded, + String confirmText = 'Delete', + IconData rejectIcon = Icons.edit_rounded, + String rejectText = 'Keep', +}) { + context.router.pushNativeRoute( + DialogRoute( + context: context, + builder: (context) { + final theme = Theme.of(context).colorScheme; + return AlertDialog( + title: Text(title), + actions: [ + TextButton.icon( + onPressed: () { + context.popRoute(); + onConfirm(); + }, + icon: Icon(confirmIcon), + label: Text(confirmText), + style: ButtonStyle( + foregroundColor: MaterialStateProperty.all(theme.error), + overlayColor: MaterialStateProperty.all( + theme.error.withOpacity(0.1), + ), + ), + ), + TextButton.icon( + onPressed: context.popRoute, + icon: Icon(rejectIcon), + label: Text(rejectText), + ), + ], + ); + }, + ), + ); +} diff --git a/lib/shared/modals/loading_dialog.dart b/lib/shared/modals/loading_dialog.dart new file mode 100644 index 00000000..87678e07 --- /dev/null +++ b/lib/shared/modals/loading_dialog.dart @@ -0,0 +1,47 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; + +import 'snackbar_manager.dart'; + +Future showLoadingDialog( + BuildContext context, + Future future, +) { + var done = false; + return context.router.pushNativeRoute( + DialogRoute( + context: context, + builder: (context) { + return Center( + child: Card( + shape: const CircleBorder(), + child: Padding( + padding: const EdgeInsets.all(16), + child: FutureBuilder( + future: future, + builder: (context, snapshot) { + if (!done && + snapshot.connectionState == ConnectionState.done) { + done = true; + SchedulerBinding.instance.addPostFrameCallback( + (_) { + if (snapshot.hasError) { + context.popRoute(); + showSnackbar(context); + } else { + context.popRoute(snapshot.data); + } + }, + ); + } + return const CircularProgressIndicator(); + }, + ), + ), + ), + ); + }, + ), + ); +} diff --git a/lib/shared/modals/scrollable_modal_sheet.dart b/lib/shared/modals/scrollable_modal_sheet.dart new file mode 100644 index 00000000..6c6ec543 --- /dev/null +++ b/lib/shared/modals/scrollable_modal_sheet.dart @@ -0,0 +1,15 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:modal_bottom_sheet/modal_bottom_sheet.dart'; + +Future showScrollableModalSheet( + BuildContext context, + Widget Function(BuildContext) builder, +) { + return context.router.pushNativeRoute( + ModalBottomSheetRoute( + builder: builder, + expanded: true, + ), + ); +} diff --git a/lib/shared/modals/snackbar_manager.dart b/lib/shared/modals/snackbar_manager.dart new file mode 100644 index 00000000..c6e844e4 --- /dev/null +++ b/lib/shared/modals/snackbar_manager.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; + +void showSnackbar( + BuildContext context, { + IconData icon = Icons.error_rounded, + String text = 'Error!', +}) { + ScaffoldMessenger.of(context) + ..hideCurrentSnackBar() + ..showSnackBar( + SnackBar( + duration: const Duration(milliseconds: 2500), + behavior: SnackBarBehavior.floating, + content: Row( + children: [ + Icon( + icon, + color: Theme.of(context).colorScheme.onInverseSurface, + ), + const SizedBox(width: 16), + Text( + text, + overflow: TextOverflow.ellipsis, + maxLines: 1, + ), + ], + ), + ), + ); +} diff --git a/lib/shared/utils.dart b/lib/shared/utils.dart new file mode 100644 index 00000000..e8bd7965 --- /dev/null +++ b/lib/shared/utils.dart @@ -0,0 +1,39 @@ +import 'package:avzag/shared/modals/snackbar_manager.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:url_launcher/url_launcher.dart'; + +void copyText(BuildContext context, String? text) async { + if (text?.isNotEmpty ?? false) { + await Clipboard.setData( + ClipboardData(text: text), + ); + showSnackbar( + context, + icon: Icons.content_copy_rounded, + text: 'Copied to clipboard.', + ); + } +} + +void openLink(String url) { + launchUrl( + Uri.parse(url), + mode: LaunchMode.externalApplication, + ); +} + +List? json2list(Object? array) { + return (array as Iterable?) + ?.map((dynamic i) => i as String) + .toList(); +} + +List? listFromJson( + Object? array, + T Function(dynamic) fromJson, +) { + return (array as Iterable?) + ?.map((dynamic i) => fromJson(i)) + .toList(); +} diff --git a/lib/shared/utils/editor_utils.dart b/lib/shared/utils/editor_utils.dart deleted file mode 100644 index 4c2652a5..00000000 --- a/lib/shared/utils/editor_utils.dart +++ /dev/null @@ -1,6 +0,0 @@ -import 'package:flutter/material.dart'; - -typedef EditorCallback = ValueSetter Function(ValueSetter action); - -EditorCallback getEditor(ValueSetter setState) => - (ValueSetter f) => (V v) => setState(() => f(v)); diff --git a/lib/shared/utils/open_link.dart b/lib/shared/utils/open_link.dart deleted file mode 100644 index f75f71f4..00000000 --- a/lib/shared/utils/open_link.dart +++ /dev/null @@ -1,8 +0,0 @@ -import 'package:url_launcher/url_launcher.dart'; - -void openLink(String url) { - launchUrl( - Uri.parse(url), - mode: LaunchMode.externalApplication, - ); -} diff --git a/lib/shared/utils/text.dart b/lib/shared/utils/text.dart deleted file mode 100644 index 19585b7e..00000000 --- a/lib/shared/utils/text.dart +++ /dev/null @@ -1,16 +0,0 @@ -import 'package:avzag/shared/widgets/modals/snackbar_manager.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; - -void copyText(BuildContext context, String? text) async { - if (text?.isNotEmpty ?? false) { - await Clipboard.setData( - ClipboardData(text: text), - ); - showSnackbar( - context, - icon: Icons.content_copy_outlined, - text: 'Copied to clipboard.', - ); - } -} diff --git a/lib/shared/utils/utils.dart b/lib/shared/utils/utils.dart deleted file mode 100644 index 912cdf10..00000000 --- a/lib/shared/utils/utils.dart +++ /dev/null @@ -1,37 +0,0 @@ -String capitalize(String? text) { - if (text == null) return ''; - return text - .split(' ') - .where((s) => s.isNotEmpty) - .map((w) => w[0].toUpperCase() + w.substring(1)) - .join(' ') - .split('-') - .where((s) => s.isNotEmpty) - .map((w) => w[0].toUpperCase() + w.substring(1)) - .join('-'); -} - -String? prettyTags( - Iterable? tags, { - String separator = ' • ', - bool capitalized = true, -}) { - if (tags == null) return null; - final text = tags.join(separator); - return capitalized ? capitalize(text) : text; -} - -List? json2list(Object? array) { - return (array as Iterable?) - ?.map((dynamic i) => i as String) - .toList(); -} - -List? listFromJson( - Object? array, - T Function(dynamic) fromJson, -) { - return (array as Iterable?) - ?.map((dynamic i) => fromJson(i)) - .toList(); -} diff --git a/lib/shared/widgets/caption.dart b/lib/shared/widgets/caption.dart index c6aba1a1..a657269e 100644 --- a/lib/shared/widgets/caption.dart +++ b/lib/shared/widgets/caption.dart @@ -24,14 +24,13 @@ class Caption extends StatelessWidget { if (icon != null) SpanIcon( icon!, - padding: const EdgeInsets.only(right: 8), + padding: const EdgeInsets.only(right: 4), ), Text( text, style: TextStyle( color: Theme.of(context).textTheme.caption?.color, fontSize: 14, - fontWeight: FontWeight.w500, fontStyle: FontStyle.italic, ), ), diff --git a/lib/shared/widgets/compact_input.dart b/lib/shared/widgets/compact_input.dart index 8b593e89..5e475893 100644 --- a/lib/shared/widgets/compact_input.dart +++ b/lib/shared/widgets/compact_input.dart @@ -43,12 +43,12 @@ class CompactInput extends StatelessWidget { isDense: true, border: InputBorder.none, ), - maxLines: multiline ? 0 : null, + maxLines: multiline ? null : 1, initialValue: initial, validator: noEmpty ? _emptyValidator : null, onChanged: (s) { s = s.trim(); - // if (lowercase) s = s.toLowerCase(); + if (lowercase) s = s.toLowerCase(); onChanged(s); }, ), diff --git a/lib/shared/widgets/language_flag.dart b/lib/shared/widgets/language_flag.dart index df8b3648..c8c17128 100644 --- a/lib/shared/widgets/language_flag.dart +++ b/lib/shared/widgets/language_flag.dart @@ -30,7 +30,7 @@ class _LanguageFlagState extends State { @override Widget build(BuildContext context) { final url = widget.url ?? GlobalStore.languages[widget.language]?.flag; - if (url == null) return SizedBox(); + if (url == null) return const SizedBox(); return Transform.translate( offset: widget.offset, child: Transform.rotate( diff --git a/lib/shared/widgets/markdown_text.dart b/lib/shared/widgets/markdown_text.dart index 6f19edf1..6f2f1a1c 100644 --- a/lib/shared/widgets/markdown_text.dart +++ b/lib/shared/widgets/markdown_text.dart @@ -1,7 +1,8 @@ -import 'package:avzag/shared/utils/open_link.dart'; import 'package:flutter/material.dart'; import 'package:flutter_markdown/flutter_markdown.dart'; +import '../utils.dart'; + class MarkdownText extends StatelessWidget { const MarkdownText( this.text, { diff --git a/lib/shared/widgets/modals/danger_dialog.dart b/lib/shared/widgets/modals/danger_dialog.dart deleted file mode 100644 index e555804b..00000000 --- a/lib/shared/widgets/modals/danger_dialog.dart +++ /dev/null @@ -1,42 +0,0 @@ -import 'package:flutter/material.dart'; - -void showDangerDialog( - BuildContext context, - VoidCallback onConfirm, - String title, { - IconData confirmIcon = Icons.delete_rounded, - String confirmText = 'Delete', - IconData rejectIcon = Icons.edit_rounded, - String rejectText = 'Keep', -}) { - showDialog( - context: context, - builder: (context) { - final theme = Theme.of(context).colorScheme; - return AlertDialog( - title: Text(title), - actions: [ - TextButton.icon( - onPressed: () { - Navigator.pop(context); - onConfirm(); - }, - icon: Icon(confirmIcon), - label: Text(confirmText), - style: ButtonStyle( - foregroundColor: MaterialStateProperty.all(theme.error), - overlayColor: MaterialStateProperty.all( - theme.error.withOpacity(0.1), - ), - ), - ), - TextButton.icon( - onPressed: () => Navigator.pop(context), - icon: Icon(rejectIcon), - label: Text(rejectText), - ), - ], - ); - }, - ); -} diff --git a/lib/shared/widgets/modals/loading_dialog.dart b/lib/shared/widgets/modals/loading_dialog.dart deleted file mode 100644 index d841db0f..00000000 --- a/lib/shared/widgets/modals/loading_dialog.dart +++ /dev/null @@ -1,33 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'snackbar_manager.dart'; - -Future showLoadingDialog( - BuildContext context, - Future future, -) async { - showDialog( - context: context, - barrierDismissible: false, - builder: (context) { - return const Center( - child: Card( - shape: CircleBorder(), - child: Padding( - padding: EdgeInsets.all(16), - child: CircularProgressIndicator(), - ), - ), - ); - }, - ); - try { - final result = await future; - Navigator.pop(context); - return result; - } catch (e) { - Navigator.pop(context); - showSnackbar(context); - rethrow; - } -} diff --git a/lib/shared/widgets/modals/scrollable_modal_sheet.dart b/lib/shared/widgets/modals/scrollable_modal_sheet.dart deleted file mode 100644 index 7ae1df9e..00000000 --- a/lib/shared/widgets/modals/scrollable_modal_sheet.dart +++ /dev/null @@ -1,35 +0,0 @@ -import 'dart:ui'; -import 'package:flutter/material.dart'; - -Future showScrollableModalSheet({ - required BuildContext context, - required ScrollableWidgetBuilder builder, -}) { - final media = MediaQueryData.fromWindow(window); - final size = - 1 - (kToolbarHeight + media.viewPadding.vertical) / media.size.height; - return showModalBottomSheet( - context: context, - isScrollControlled: true, - backgroundColor: Colors.transparent, - builder: (context) { - return DraggableScrollableSheet( - minChildSize: size - .1, - initialChildSize: size, - maxChildSize: size, - builder: (context, controller) { - return Material( - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical( - top: Radius.circular(16), - ), - ), - color: Theme.of(context).scaffoldBackgroundColor, - clipBehavior: Clip.antiAlias, - child: builder(context, controller), - ); - }, - ); - }, - ); -} diff --git a/lib/shared/widgets/modals/snackbar_manager.dart b/lib/shared/widgets/modals/snackbar_manager.dart deleted file mode 100644 index bc2dbbfb..00000000 --- a/lib/shared/widgets/modals/snackbar_manager.dart +++ /dev/null @@ -1,30 +0,0 @@ -import 'package:flutter/material.dart'; - -void showSnackbar( - BuildContext context, { - IconData icon = Icons.error_rounded, - String text = 'Error!', - bool floating = true, -}) { - final theme = Theme.of(context); - final messenger = ScaffoldMessenger.of(context); - messenger.hideCurrentSnackBar(); - messenger.showSnackBar( - SnackBar( - behavior: floating ? SnackBarBehavior.floating : SnackBarBehavior.fixed, - backgroundColor: theme.colorScheme.surface, - content: Row( - children: [ - Icon(icon), - const SizedBox(width: 16), - Text( - text, - style: theme.textTheme.bodyText1, - overflow: TextOverflow.ellipsis, - maxLines: 1, - ), - ], - ), - ), - ); -} diff --git a/lib/shared/widgets/options_button.dart b/lib/shared/widgets/options_button.dart index 0c4cb6fc..896d50fe 100644 --- a/lib/shared/widgets/options_button.dart +++ b/lib/shared/widgets/options_button.dart @@ -5,15 +5,18 @@ class OptionItem { final VoidCallback? onTap; OptionItem( - this.widget, [ + this.widget, { this.onTap, - ]); + }); OptionItem.simple( IconData icon, - String text, [ + String text, { this.onTap, - ]) : widget = Row( + bool centered = false, + }) : widget = Row( + mainAxisAlignment: + centered ? MainAxisAlignment.center : MainAxisAlignment.start, children: [ const SizedBox(width: 16), Icon(icon), @@ -25,9 +28,9 @@ class OptionItem { OptionItem.tile( Widget leading, - Widget title, [ + Widget title, { this.onTap, - ]) : widget = Row( + }) : widget = Row( children: [ const SizedBox(width: 16), leading, diff --git a/lib/shared/widgets/raxys.dart b/lib/shared/widgets/raxys.dart new file mode 100644 index 00000000..4c01a4eb --- /dev/null +++ b/lib/shared/widgets/raxys.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; + +class Raxys extends StatelessWidget { + const Raxys({ + this.size = 24, + this.opacity = 1, + this.scale = 1, + Key? key, + }) : super(key: key); + + final double scale; + final double size; + final double opacity; + + @override + Widget build(BuildContext context) { + return SizedBox.square( + dimension: size, + child: Transform.scale( + scale: scale, + child: Opacity( + opacity: opacity, + child: ColorFiltered( + colorFilter: ColorFilter.mode( + Theme.of(context).brightness == Brightness.light + ? Colors.black + : Colors.white, + BlendMode.modulate, + ), + child: Image.asset( + 'assets/raxys.png', + isAntiAlias: true, + filterQuality: FilterQuality.high, + ), + ), + ), + ), + ); + } +} diff --git a/lib/shared/widgets/raxys_logo.dart b/lib/shared/widgets/raxys_logo.dart deleted file mode 100644 index 5e1a758e..00000000 --- a/lib/shared/widgets/raxys_logo.dart +++ /dev/null @@ -1,34 +0,0 @@ -import 'package:flutter/material.dart'; - -class RaxysLogo extends StatelessWidget { - const RaxysLogo({ - this.size = 24, - this.opacity = 1, - this.scale = 1, - Key? key, - }) : super(key: key); - - final double scale; - final double size; - final double opacity; - - @override - Widget build(BuildContext context) { - return SizedBox.square( - dimension: size, - child: Transform.scale( - scale: scale, - child: Opacity( - opacity: opacity, - child: Image.asset( - Theme.of(context).brightness == Brightness.dark - ? 'assets/raxys_dark.png' - : 'assets/raxys_light.png', - isAntiAlias: true, - filterQuality: FilterQuality.high, - ), - ), - ), - ); - } -} diff --git a/lib/shared/widgets/rounded_back_button.dart b/lib/shared/widgets/rounded_back_button.dart index 970d625d..1b8af3cf 100644 --- a/lib/shared/widgets/rounded_back_button.dart +++ b/lib/shared/widgets/rounded_back_button.dart @@ -1,3 +1,4 @@ +import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; class RoundedBackButton extends StatelessWidget { @@ -11,7 +12,7 @@ class RoundedBackButton extends StatelessWidget { @override Widget build(BuildContext context) { return IconButton( - onPressed: () => Navigator.maybePop(context), + onPressed: context.popRoute, tooltip: 'Back', icon: Icon(icon), ); diff --git a/lib/store.dart b/lib/store.dart index b8ef1e4a..7072df53 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -3,7 +3,7 @@ import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'models/language.dart'; -import 'shared/utils/utils.dart'; +import 'shared/utils.dart'; late final Algolia algolia; late final SharedPreferences prefs; @@ -26,7 +26,12 @@ class EditorStore { static bool get editor => user != null && language != null; static bool get admin => editor && adminable.contains(language); - static Future _check(User? user) async { + static Future> getAdminable() async { + final token = await user?.getIdTokenResult(true); + return json2list(token?.claims?['admin']) ?? []; + } + + static void _check(User? user) async { if (user == null) { adminable.clear(); language = null; @@ -35,12 +40,7 @@ class EditorStore { adminable = await getAdminable(); } - static Future> getAdminable() async { - final token = await user?.getIdTokenResult(true); - return json2list(token?.claims?['admin']) ?? []; - } - - static Future init() async { + static Future init() async { _language = prefs.getString('editorLanguage'); adminable = await getAdminable(); FirebaseAuth.instance.userChanges().listen(_check); @@ -50,10 +50,10 @@ class EditorStore { class GlobalStore { static Map languages = {}; - static Future set({ + static void set({ Iterable? names, Iterable? objects, - }) async { + }) { if (objects != null) { languages = {for (final l in objects) l.name: l}; } else if (names != null) { @@ -65,9 +65,9 @@ class GlobalStore { prefs.setStringList('languages', languages.keys.toList()); } - static Future init([List? names]) async { + static void init([List? names]) { set( - names: names ?? prefs.getStringList('languages') ?? ['iron'], + names: names ?? prefs.getStringList('languages') ?? ['aghul'], ); for (final l in languages.keys) { FirebaseFirestore.instance diff --git a/lib/theme_set.dart b/lib/theme_set.dart new file mode 100644 index 00000000..fe263df2 --- /dev/null +++ b/lib/theme_set.dart @@ -0,0 +1,48 @@ +import 'package:flutter/material.dart'; + +class ThemeSet { + final ThemeData light; + final ThemeData dark; + + ThemeSet(ColorScheme scheme) + : light = _getLightTheme(scheme), + dark = _getDarkTheme(scheme); + + static ThemeData _getDarkTheme(ColorScheme colorScheme) => + ThemeData.dark().copyWith( + colorScheme: ColorScheme.fromSwatch( + accentColor: Colors.grey, + brightness: Brightness.dark, + ), + cardTheme: const CardTheme( + clipBehavior: Clip.antiAlias, + ), + toggleableActiveColor: colorScheme.primary, + floatingActionButtonTheme: FloatingActionButtonThemeData( + backgroundColor: colorScheme.primary, + foregroundColor: colorScheme.onPrimary, + ), + dividerTheme: const DividerThemeData(space: 0), + ); + + static ThemeData _getLightTheme(ColorScheme colorScheme) => + ThemeData().copyWith( + scaffoldBackgroundColor: Colors.blueGrey.shade50, + colorScheme: ColorScheme.fromSwatch( + accentColor: Colors.grey, + ), + appBarTheme: AppBarTheme( + backgroundColor: colorScheme.surface, + foregroundColor: colorScheme.onSurface, + ), + cardTheme: const CardTheme( + clipBehavior: Clip.antiAlias, + ), + toggleableActiveColor: colorScheme.primary, + floatingActionButtonTheme: FloatingActionButtonThemeData( + backgroundColor: colorScheme.primary, + foregroundColor: colorScheme.onPrimary, + ), + dividerTheme: const DividerThemeData(space: 0), + ); +} diff --git a/pubspec.lock b/pubspec.lock index 866b3e7f..ade34ccd 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,7 +7,7 @@ packages: name: _fe_analyzer_shared url: "https://pub.dartlang.org" source: hosted - version: "40.0.0" + version: "38.0.0" algolia: dependency: "direct main" description: @@ -21,7 +21,7 @@ packages: name: analyzer url: "https://pub.dartlang.org" source: hosted - version: "4.1.0" + version: "3.4.1" animated_stack_widget: dependency: transitive description: @@ -42,7 +42,7 @@ packages: name: args url: "https://pub.dartlang.org" source: hosted - version: "2.3.0" + version: "2.3.1" async: dependency: transitive description: @@ -50,13 +50,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.8.2" + auto_route: + dependency: "direct main" + description: + name: auto_route + url: "https://pub.dartlang.org" + source: hosted + version: "4.2.0" + auto_route_generator: + dependency: "direct dev" + description: + name: auto_route_generator + url: "https://pub.dartlang.org" + source: hosted + version: "4.2.0" badges: dependency: "direct main" description: name: badges url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "2.0.3" boolean_selector: dependency: transitive description: @@ -154,21 +168,21 @@ packages: name: cloud_firestore url: "https://pub.dartlang.org" source: hosted - version: "3.1.15" + version: "3.1.18" cloud_firestore_platform_interface: dependency: transitive description: name: cloud_firestore_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "5.5.6" + version: "5.5.8" cloud_firestore_web: dependency: transitive description: name: cloud_firestore_web url: "https://pub.dartlang.org" source: hosted - version: "2.6.15" + version: "2.6.17" code_builder: dependency: transitive description: @@ -197,6 +211,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.0.2" + csslib: + dependency: transitive + description: + name: csslib + url: "https://pub.dartlang.org" + source: hosted + version: "0.17.1" dart_style: dependency: transitive description: @@ -231,42 +252,42 @@ packages: name: firebase_auth url: "https://pub.dartlang.org" source: hosted - version: "3.3.18" + version: "3.3.20" firebase_auth_platform_interface: dependency: transitive description: name: firebase_auth_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "6.2.6" + version: "6.2.8" firebase_auth_web: dependency: transitive description: name: firebase_auth_web url: "https://pub.dartlang.org" source: hosted - version: "3.3.15" + version: "3.3.17" firebase_core: dependency: "direct main" description: name: firebase_core url: "https://pub.dartlang.org" source: hosted - version: "1.17.0" + version: "1.18.0" firebase_core_platform_interface: dependency: transitive description: name: firebase_core_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "4.4.0" + version: "4.4.1" firebase_core_web: dependency: transitive description: name: firebase_core_web url: "https://pub.dartlang.org" source: hosted - version: "1.6.4" + version: "1.6.5" fixnum: dependency: transitive description: @@ -299,28 +320,28 @@ packages: name: flutter_map url: "https://pub.dartlang.org" source: hosted - version: "0.14.0" + version: "1.1.1" flutter_map_marker_cluster: dependency: "direct main" description: name: flutter_map_marker_cluster url: "https://pub.dartlang.org" source: hosted - version: "0.4.4" + version: "0.5.0" flutter_map_marker_popup: dependency: transitive description: name: flutter_map_marker_popup url: "https://pub.dartlang.org" source: hosted - version: "2.1.1+1" + version: "2.2.1" flutter_markdown: dependency: "direct main" description: name: flutter_markdown url: "https://pub.dartlang.org" source: hosted - version: "0.6.10" + version: "0.6.10+2" flutter_test: dependency: "direct dev" description: flutter @@ -345,13 +366,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.2" + google_fonts: + dependency: "direct main" + description: + name: google_fonts + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" google_sign_in: dependency: "direct main" description: name: google_sign_in url: "https://pub.dartlang.org" source: hosted - version: "5.3.1" + version: "5.3.3" google_sign_in_android: dependency: transitive description: @@ -387,6 +415,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + html: + dependency: transitive + description: + name: html + url: "https://pub.dartlang.org" + source: hosted + version: "0.15.0" http: dependency: transitive description: @@ -414,14 +449,14 @@ packages: name: image url: "https://pub.dartlang.org" source: hosted - version: "3.1.3" + version: "3.2.0" infinite_scroll_pagination: dependency: "direct main" description: name: infinite_scroll_pagination url: "https://pub.dartlang.org" source: hosted - version: "3.1.0" + version: "3.2.0" intersperse: dependency: "direct main" description: @@ -493,7 +528,7 @@ packages: source: hosted version: "1.0.2" markdown: - dependency: transitive + dependency: "direct main" description: name: markdown url: "https://pub.dartlang.org" @@ -534,6 +569,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.2" + modal_bottom_sheet: + dependency: "direct main" + description: + name: modal_bottom_sheet + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" nested: dependency: transitive description: @@ -597,6 +639,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.1" + path_provider: + dependency: transitive + description: + name: path_provider + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.10" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.14" + path_provider_ios: + dependency: transitive + description: + name: path_provider_ios + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.9" path_provider_linux: dependency: transitive description: @@ -604,6 +667,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.5" + path_provider_macos: + dependency: transitive + description: + name: path_provider_macos + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.6" path_provider_platform_interface: dependency: transitive description: @@ -624,7 +694,7 @@ packages: name: petitparser url: "https://pub.dartlang.org" source: hosted - version: "4.4.0" + version: "5.0.0" platform: dependency: transitive description: @@ -639,6 +709,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.2" + polylabel: + dependency: transitive + description: + name: polylabel + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" pool: dependency: transitive description: @@ -673,7 +750,7 @@ packages: name: provider url: "https://pub.dartlang.org" source: hosted - version: "6.0.2" + version: "6.0.3" pub_semver: dependency: transitive description: @@ -771,7 +848,7 @@ packages: name: sign_in_with_apple url: "https://pub.dartlang.org" source: hosted - version: "3.3.0" + version: "4.0.0" sign_in_with_apple_platform_interface: dependency: transitive description: @@ -868,13 +945,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.0" - transparent_image: - dependency: transitive - description: - name: transparent_image - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" tuple: dependency: transitive description: @@ -896,6 +966,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.3.1" + universal_html: + dependency: transitive + description: + name: universal_html + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.8" universal_io: dependency: transitive description: @@ -909,7 +986,7 @@ packages: name: url_launcher url: "https://pub.dartlang.org" source: hosted - version: "6.1.2" + version: "6.1.4" url_launcher_android: dependency: transitive description: @@ -944,7 +1021,7 @@ packages: name: url_launcher_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "2.1.0" url_launcher_web: dependency: transitive description: @@ -959,6 +1036,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.0.0" + url_strategy: + dependency: "direct main" + description: + name: url_strategy + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.0" uuid: dependency: transitive description: @@ -1014,7 +1098,7 @@ packages: name: xml url: "https://pub.dartlang.org" source: hosted - version: "5.3.1" + version: "6.1.0" yaml: dependency: transitive description: @@ -1023,5 +1107,5 @@ packages: source: hosted version: "3.1.0" sdks: - dart: ">=2.17.0-206.0.dev <3.0.0" - flutter: ">=2.10.0" + dart: ">=2.17.0 <3.0.0" + flutter: ">=3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index fd130a6e..e2303165 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: avzag -description: Extensible parallel language compendium. +description: Extensible parallel language compendium publish_to: "none" -version: 0.6.3+60 +version: 0.8.2+62 environment: sdk: ">=2.13.0 <3.0.0" @@ -9,24 +9,29 @@ environment: dependencies: flutter: sdk: flutter - firebase_core: ^1.17.0 - cloud_firestore: ^3.1.15 - url_launcher: ^6.1.2 + firebase_core: ^1.18.0 + cloud_firestore: ^3.1.18 + url_launcher: ^6.1.4 shared_preferences: ^2.0.15 - firebase_auth: ^3.3.18 - google_sign_in: ^5.3.1 - sign_in_with_apple: ^3.3.0 + firebase_auth: ^3.3.20 + google_sign_in: ^5.3.3 + sign_in_with_apple: ^4.0.0 crypto: ^3.0.2 algolia: ^1.1.1 - flutter_markdown: ^0.6.10 + markdown: ^5.0.0 + flutter_markdown: ^0.6.10+2 package_info_plus: ^1.4.2 - provider: ^6.0.2 - badges: ^2.0.2 - infinite_scroll_pagination: ^3.1.0 - flutter_map: ^0.14.0 - flutter_map_marker_cluster: ^0.4.4 + provider: ^6.0.3 + badges: ^2.0.3 + infinite_scroll_pagination: ^3.2.0 + flutter_map: ^1.1.1 + flutter_map_marker_cluster: ^0.5.0 latlong2: ^0.8.1 intersperse: ^2.0.0 + google_fonts: ^3.0.1 + auto_route: ^4.2.0 + url_strategy: ^0.2.0 + modal_bottom_sheet: ^2.1.0 dev_dependencies: flutter_test: @@ -35,6 +40,7 @@ dev_dependencies: flutter_lints: ^2.0.1 build_runner: ^2.1.11 json_serializable: ^6.2.0 + auto_route_generator: ^4.2.0 flutter_icons: image_path: "assets/icon.png" @@ -45,3 +51,6 @@ flutter: uses-material-design: true assets: - assets/ + + + \ No newline at end of file diff --git a/web/index.html b/web/index.html index d3346a96..09e2a80c 100644 --- a/web/index.html +++ b/web/index.html @@ -5,11 +5,15 @@ - + + - avzag + Avzag diff --git a/web/manifest.json b/web/manifest.json index 2f73af90..d00d6130 100644 --- a/web/manifest.json +++ b/web/manifest.json @@ -3,8 +3,8 @@ "short_name": "Avzag", "start_url": ".", "display": "standalone", - "background_color": "#212121", - "theme_color": "#212121", + "background_color": "#303030", + "theme_color": "#303030", "orientation": "portrait-primary", "prefer_related_applications": false, "icons": [