diff --git a/.yarn/cache/@adobe-css-tools-npm-4.0.1-414e22a25e-80226e2229.zip b/.yarn/cache/@adobe-css-tools-npm-4.0.1-414e22a25e-80226e2229.zip new file mode 100644 index 000000000..ebe78f9e3 Binary files /dev/null and b/.yarn/cache/@adobe-css-tools-npm-4.0.1-414e22a25e-80226e2229.zip differ diff --git a/.yarn/cache/@algolia-cache-browser-local-storage-npm-4.13.1-c6b6f3cb62-ee7674971a.zip b/.yarn/cache/@algolia-cache-browser-local-storage-npm-4.14.2-1525dcd2d0-e7d5f43ff0.zip similarity index 92% rename from .yarn/cache/@algolia-cache-browser-local-storage-npm-4.13.1-c6b6f3cb62-ee7674971a.zip rename to .yarn/cache/@algolia-cache-browser-local-storage-npm-4.14.2-1525dcd2d0-e7d5f43ff0.zip index 9b808aef8..23feffd5e 100644 Binary files a/.yarn/cache/@algolia-cache-browser-local-storage-npm-4.13.1-c6b6f3cb62-ee7674971a.zip and b/.yarn/cache/@algolia-cache-browser-local-storage-npm-4.14.2-1525dcd2d0-e7d5f43ff0.zip differ diff --git a/.yarn/cache/@algolia-cache-common-npm-4.13.1-e65eb6a114-0ec5f13441.zip b/.yarn/cache/@algolia-cache-common-npm-4.14.2-cd5ab62e07-4fd04c714a.zip similarity index 76% rename from .yarn/cache/@algolia-cache-common-npm-4.13.1-e65eb6a114-0ec5f13441.zip rename to .yarn/cache/@algolia-cache-common-npm-4.14.2-cd5ab62e07-4fd04c714a.zip index e0c2d5734..6c72e5981 100644 Binary files a/.yarn/cache/@algolia-cache-common-npm-4.13.1-e65eb6a114-0ec5f13441.zip and b/.yarn/cache/@algolia-cache-common-npm-4.14.2-cd5ab62e07-4fd04c714a.zip differ diff --git a/.yarn/cache/@algolia-cache-in-memory-npm-4.13.1-3ea72a883f-d1a5935de6.zip b/.yarn/cache/@algolia-cache-in-memory-npm-4.14.2-b2851f6d42-d6981f812a.zip similarity index 91% rename from .yarn/cache/@algolia-cache-in-memory-npm-4.13.1-3ea72a883f-d1a5935de6.zip rename to .yarn/cache/@algolia-cache-in-memory-npm-4.14.2-b2851f6d42-d6981f812a.zip index 8069f04f2..7c296cacd 100644 Binary files a/.yarn/cache/@algolia-cache-in-memory-npm-4.13.1-3ea72a883f-d1a5935de6.zip and b/.yarn/cache/@algolia-cache-in-memory-npm-4.14.2-b2851f6d42-d6981f812a.zip differ diff --git a/.yarn/cache/@algolia-client-account-npm-4.13.1-ba9b82e153-3a3fb580c5.zip b/.yarn/cache/@algolia-client-account-npm-4.14.2-638e7c4fd3-2e9eed5a4b.zip similarity index 93% rename from .yarn/cache/@algolia-client-account-npm-4.13.1-ba9b82e153-3a3fb580c5.zip rename to .yarn/cache/@algolia-client-account-npm-4.14.2-638e7c4fd3-2e9eed5a4b.zip index 55b8296a6..3d6b5fc73 100644 Binary files a/.yarn/cache/@algolia-client-account-npm-4.13.1-ba9b82e153-3a3fb580c5.zip and b/.yarn/cache/@algolia-client-account-npm-4.14.2-638e7c4fd3-2e9eed5a4b.zip differ diff --git a/.yarn/cache/@algolia-client-analytics-npm-4.13.1-c1b43b438c-b593011160.zip b/.yarn/cache/@algolia-client-analytics-npm-4.14.2-6d6467051e-61874e026c.zip similarity index 94% rename from .yarn/cache/@algolia-client-analytics-npm-4.13.1-c1b43b438c-b593011160.zip rename to .yarn/cache/@algolia-client-analytics-npm-4.14.2-6d6467051e-61874e026c.zip index eb64b7cdd..26cb655d5 100644 Binary files a/.yarn/cache/@algolia-client-analytics-npm-4.13.1-c1b43b438c-b593011160.zip and b/.yarn/cache/@algolia-client-analytics-npm-4.14.2-6d6467051e-61874e026c.zip differ diff --git a/.yarn/cache/@algolia-client-common-npm-4.13.1-b93cdb6d0d-4a3d5a14f4.zip b/.yarn/cache/@algolia-client-common-npm-4.13.1-b93cdb6d0d-4a3d5a14f4.zip deleted file mode 100644 index 920b16d3b..000000000 Binary files a/.yarn/cache/@algolia-client-common-npm-4.13.1-b93cdb6d0d-4a3d5a14f4.zip and /dev/null differ diff --git a/.yarn/cache/@algolia-client-common-npm-4.14.2-36b62d83ee-da2be279ac.zip b/.yarn/cache/@algolia-client-common-npm-4.14.2-36b62d83ee-da2be279ac.zip new file mode 100644 index 000000000..16462208e Binary files /dev/null and b/.yarn/cache/@algolia-client-common-npm-4.14.2-36b62d83ee-da2be279ac.zip differ diff --git a/.yarn/cache/@algolia-client-personalization-npm-4.13.1-02aaa55c87-9a318235f5.zip b/.yarn/cache/@algolia-client-personalization-npm-4.14.2-c1d119b502-0dd25c84a4.zip similarity index 92% rename from .yarn/cache/@algolia-client-personalization-npm-4.13.1-02aaa55c87-9a318235f5.zip rename to .yarn/cache/@algolia-client-personalization-npm-4.14.2-c1d119b502-0dd25c84a4.zip index d8061283e..c545ec5a8 100644 Binary files a/.yarn/cache/@algolia-client-personalization-npm-4.13.1-02aaa55c87-9a318235f5.zip and b/.yarn/cache/@algolia-client-personalization-npm-4.14.2-c1d119b502-0dd25c84a4.zip differ diff --git a/.yarn/cache/@algolia-client-search-npm-4.13.1-9a4483967a-44e630b866.zip b/.yarn/cache/@algolia-client-search-npm-4.14.2-f4a9cad087-2695bc9e8c.zip similarity index 83% rename from .yarn/cache/@algolia-client-search-npm-4.13.1-9a4483967a-44e630b866.zip rename to .yarn/cache/@algolia-client-search-npm-4.14.2-f4a9cad087-2695bc9e8c.zip index b7a934932..e94445d85 100644 Binary files a/.yarn/cache/@algolia-client-search-npm-4.13.1-9a4483967a-44e630b866.zip and b/.yarn/cache/@algolia-client-search-npm-4.14.2-f4a9cad087-2695bc9e8c.zip differ diff --git a/.yarn/cache/@algolia-logger-common-npm-4.13.1-83d2aed03f-7330b794af.zip b/.yarn/cache/@algolia-logger-common-npm-4.14.2-55301effc4-a4000a9883.zip similarity index 87% rename from .yarn/cache/@algolia-logger-common-npm-4.13.1-83d2aed03f-7330b794af.zip rename to .yarn/cache/@algolia-logger-common-npm-4.14.2-55301effc4-a4000a9883.zip index 200aa337c..38276bab4 100644 Binary files a/.yarn/cache/@algolia-logger-common-npm-4.13.1-83d2aed03f-7330b794af.zip and b/.yarn/cache/@algolia-logger-common-npm-4.14.2-55301effc4-a4000a9883.zip differ diff --git a/.yarn/cache/@algolia-logger-console-npm-4.13.1-934451a7d6-c78f50a784.zip b/.yarn/cache/@algolia-logger-console-npm-4.14.2-b33418d7de-96c6209c7e.zip similarity index 72% rename from .yarn/cache/@algolia-logger-console-npm-4.13.1-934451a7d6-c78f50a784.zip rename to .yarn/cache/@algolia-logger-console-npm-4.14.2-b33418d7de-96c6209c7e.zip index 7729ab509..0ccde7915 100644 Binary files a/.yarn/cache/@algolia-logger-console-npm-4.13.1-934451a7d6-c78f50a784.zip and b/.yarn/cache/@algolia-logger-console-npm-4.14.2-b33418d7de-96c6209c7e.zip differ diff --git a/.yarn/cache/@algolia-requester-browser-xhr-npm-4.13.1-66d7572617-6ae8e3b03b.zip b/.yarn/cache/@algolia-requester-browser-xhr-npm-4.14.2-7e8355ca8a-7d8666e21c.zip similarity index 93% rename from .yarn/cache/@algolia-requester-browser-xhr-npm-4.13.1-66d7572617-6ae8e3b03b.zip rename to .yarn/cache/@algolia-requester-browser-xhr-npm-4.14.2-7e8355ca8a-7d8666e21c.zip index 24f63d225..25eb3c909 100644 Binary files a/.yarn/cache/@algolia-requester-browser-xhr-npm-4.13.1-66d7572617-6ae8e3b03b.zip and b/.yarn/cache/@algolia-requester-browser-xhr-npm-4.14.2-7e8355ca8a-7d8666e21c.zip differ diff --git a/.yarn/cache/@algolia-requester-common-npm-4.13.1-c0685bf000-4e8039f7fd.zip b/.yarn/cache/@algolia-requester-common-npm-4.14.2-9e4f0ea5c3-7de4148a55.zip similarity index 86% rename from .yarn/cache/@algolia-requester-common-npm-4.13.1-c0685bf000-4e8039f7fd.zip rename to .yarn/cache/@algolia-requester-common-npm-4.14.2-9e4f0ea5c3-7de4148a55.zip index 0fb82fdcd..cff668e72 100644 Binary files a/.yarn/cache/@algolia-requester-common-npm-4.13.1-c0685bf000-4e8039f7fd.zip and b/.yarn/cache/@algolia-requester-common-npm-4.14.2-9e4f0ea5c3-7de4148a55.zip differ diff --git a/.yarn/cache/@algolia-requester-node-http-npm-4.13.1-c7924c91b4-d25fe56c4a.zip b/.yarn/cache/@algolia-requester-node-http-npm-4.14.2-c97bb16407-5f5fe8b040.zip similarity index 93% rename from .yarn/cache/@algolia-requester-node-http-npm-4.13.1-c7924c91b4-d25fe56c4a.zip rename to .yarn/cache/@algolia-requester-node-http-npm-4.14.2-c97bb16407-5f5fe8b040.zip index 3ecc48ebb..c371443e8 100644 Binary files a/.yarn/cache/@algolia-requester-node-http-npm-4.13.1-c7924c91b4-d25fe56c4a.zip and b/.yarn/cache/@algolia-requester-node-http-npm-4.14.2-c97bb16407-5f5fe8b040.zip differ diff --git a/.yarn/cache/@algolia-transporter-npm-4.13.1-4c7713984b-c99451f371.zip b/.yarn/cache/@algolia-transporter-npm-4.14.2-95bfbf32f6-72c72013f3.zip similarity index 95% rename from .yarn/cache/@algolia-transporter-npm-4.13.1-4c7713984b-c99451f371.zip rename to .yarn/cache/@algolia-transporter-npm-4.14.2-95bfbf32f6-72c72013f3.zip index 35b827984..880f4f958 100644 Binary files a/.yarn/cache/@algolia-transporter-npm-4.13.1-4c7713984b-c99451f371.zip and b/.yarn/cache/@algolia-transporter-npm-4.14.2-95bfbf32f6-72c72013f3.zip differ diff --git a/.yarn/cache/@babel-cli-npm-7.18.6-b311dcef26-5559c93127.zip b/.yarn/cache/@babel-cli-npm-7.18.6-b311dcef26-5559c93127.zip deleted file mode 100644 index 750d81078..000000000 Binary files a/.yarn/cache/@babel-cli-npm-7.18.6-b311dcef26-5559c93127.zip and /dev/null differ diff --git a/.yarn/cache/@babel-cli-npm-7.19.3-1e9432d014-baa2317754.zip b/.yarn/cache/@babel-cli-npm-7.19.3-1e9432d014-baa2317754.zip new file mode 100644 index 000000000..7e4117f53 Binary files /dev/null and b/.yarn/cache/@babel-cli-npm-7.19.3-1e9432d014-baa2317754.zip differ diff --git a/.yarn/cache/@babel-compat-data-npm-7.18.6-115e49a0e5-fd73a1bd7b.zip b/.yarn/cache/@babel-compat-data-npm-7.19.4-579e57594f-757fdaeb67.zip similarity index 58% rename from .yarn/cache/@babel-compat-data-npm-7.18.6-115e49a0e5-fd73a1bd7b.zip rename to .yarn/cache/@babel-compat-data-npm-7.19.4-579e57594f-757fdaeb67.zip index 7207d401f..096147e0d 100644 Binary files a/.yarn/cache/@babel-compat-data-npm-7.18.6-115e49a0e5-fd73a1bd7b.zip and b/.yarn/cache/@babel-compat-data-npm-7.19.4-579e57594f-757fdaeb67.zip differ diff --git a/.yarn/cache/@babel-core-npm-7.18.6-52b1065703-711459ebf7.zip b/.yarn/cache/@babel-core-npm-7.18.6-52b1065703-711459ebf7.zip deleted file mode 100644 index 5ba15dcf7..000000000 Binary files a/.yarn/cache/@babel-core-npm-7.18.6-52b1065703-711459ebf7.zip and /dev/null differ diff --git a/.yarn/cache/@babel-core-npm-7.19.3-24bbc57b64-dd88331120.zip b/.yarn/cache/@babel-core-npm-7.19.3-24bbc57b64-dd88331120.zip new file mode 100644 index 000000000..9630595cb Binary files /dev/null and b/.yarn/cache/@babel-core-npm-7.19.3-24bbc57b64-dd88331120.zip differ diff --git a/.yarn/cache/@babel-eslint-parser-npm-7.18.2-8989f47b38-dc9328cf33.zip b/.yarn/cache/@babel-eslint-parser-npm-7.18.2-8989f47b38-dc9328cf33.zip deleted file mode 100644 index 661deda78..000000000 Binary files a/.yarn/cache/@babel-eslint-parser-npm-7.18.2-8989f47b38-dc9328cf33.zip and /dev/null differ diff --git a/.yarn/cache/@babel-eslint-parser-npm-7.19.1-8f22f07e44-6d5360f62f.zip b/.yarn/cache/@babel-eslint-parser-npm-7.19.1-8f22f07e44-6d5360f62f.zip new file mode 100644 index 000000000..19b3c955a Binary files /dev/null and b/.yarn/cache/@babel-eslint-parser-npm-7.19.1-8f22f07e44-6d5360f62f.zip differ diff --git a/.yarn/cache/@babel-generator-npm-7.18.7-14509012bd-aad4b68731.zip b/.yarn/cache/@babel-generator-npm-7.18.7-14509012bd-aad4b68731.zip deleted file mode 100644 index 714dc94e1..000000000 Binary files a/.yarn/cache/@babel-generator-npm-7.18.7-14509012bd-aad4b68731.zip and /dev/null differ diff --git a/.yarn/cache/@babel-generator-npm-7.19.5-a5fa486490-a66eafc540.zip b/.yarn/cache/@babel-generator-npm-7.19.5-a5fa486490-a66eafc540.zip new file mode 100644 index 000000000..7ecca5d69 Binary files /dev/null and b/.yarn/cache/@babel-generator-npm-7.19.5-a5fa486490-a66eafc540.zip differ diff --git a/.yarn/cache/@babel-helper-builder-binary-assignment-operator-visitor-npm-7.18.6-1f67583a44-c4d71356e0.zip b/.yarn/cache/@babel-helper-builder-binary-assignment-operator-visitor-npm-7.18.9-a2c86d7a16-b4bc214cb5.zip similarity index 59% rename from .yarn/cache/@babel-helper-builder-binary-assignment-operator-visitor-npm-7.18.6-1f67583a44-c4d71356e0.zip rename to .yarn/cache/@babel-helper-builder-binary-assignment-operator-visitor-npm-7.18.9-a2c86d7a16-b4bc214cb5.zip index 6856fb58e..cb8be7ada 100644 Binary files a/.yarn/cache/@babel-helper-builder-binary-assignment-operator-visitor-npm-7.18.6-1f67583a44-c4d71356e0.zip and b/.yarn/cache/@babel-helper-builder-binary-assignment-operator-visitor-npm-7.18.9-a2c86d7a16-b4bc214cb5.zip differ diff --git a/.yarn/cache/@babel-helper-compilation-targets-npm-7.18.6-db5c17ef96-f09ddaddc8.zip b/.yarn/cache/@babel-helper-compilation-targets-npm-7.18.6-db5c17ef96-f09ddaddc8.zip deleted file mode 100644 index c19846bdf..000000000 Binary files a/.yarn/cache/@babel-helper-compilation-targets-npm-7.18.6-db5c17ef96-f09ddaddc8.zip and /dev/null differ diff --git a/.yarn/cache/@babel-helper-compilation-targets-npm-7.19.3-ba5dbffed2-aafcb4490c.zip b/.yarn/cache/@babel-helper-compilation-targets-npm-7.19.3-ba5dbffed2-aafcb4490c.zip new file mode 100644 index 000000000..6d4719800 Binary files /dev/null and b/.yarn/cache/@babel-helper-compilation-targets-npm-7.19.3-ba5dbffed2-aafcb4490c.zip differ diff --git a/.yarn/cache/@babel-helper-create-class-features-plugin-npm-7.18.6-a81df9f23b-4d6da441ce.zip b/.yarn/cache/@babel-helper-create-class-features-plugin-npm-7.18.6-a81df9f23b-4d6da441ce.zip deleted file mode 100644 index a66f3b87d..000000000 Binary files a/.yarn/cache/@babel-helper-create-class-features-plugin-npm-7.18.6-a81df9f23b-4d6da441ce.zip and /dev/null differ diff --git a/.yarn/cache/@babel-helper-create-class-features-plugin-npm-7.19.0-684397371f-f0c6fb77b6.zip b/.yarn/cache/@babel-helper-create-class-features-plugin-npm-7.19.0-684397371f-f0c6fb77b6.zip new file mode 100644 index 000000000..13f22e3f5 Binary files /dev/null and b/.yarn/cache/@babel-helper-create-class-features-plugin-npm-7.19.0-684397371f-f0c6fb77b6.zip differ diff --git a/.yarn/cache/@babel-helper-create-regexp-features-plugin-npm-7.18.6-96a83bc902-2d76e660cb.zip b/.yarn/cache/@babel-helper-create-regexp-features-plugin-npm-7.18.6-96a83bc902-2d76e660cb.zip deleted file mode 100644 index 5da8e8f50..000000000 Binary files a/.yarn/cache/@babel-helper-create-regexp-features-plugin-npm-7.18.6-96a83bc902-2d76e660cb.zip and /dev/null differ diff --git a/.yarn/cache/@babel-helper-create-regexp-features-plugin-npm-7.19.0-664f2c7fc6-811cc90afe.zip b/.yarn/cache/@babel-helper-create-regexp-features-plugin-npm-7.19.0-664f2c7fc6-811cc90afe.zip new file mode 100644 index 000000000..6e695efb9 Binary files /dev/null and b/.yarn/cache/@babel-helper-create-regexp-features-plugin-npm-7.19.0-664f2c7fc6-811cc90afe.zip differ diff --git a/.yarn/cache/@babel-helper-define-polyfill-provider-npm-0.3.1-7c6efdf410-e3e93cb22f.zip b/.yarn/cache/@babel-helper-define-polyfill-provider-npm-0.3.1-7c6efdf410-e3e93cb22f.zip deleted file mode 100644 index 5863babaf..000000000 Binary files a/.yarn/cache/@babel-helper-define-polyfill-provider-npm-0.3.1-7c6efdf410-e3e93cb22f.zip and /dev/null differ diff --git a/.yarn/cache/@babel-helper-define-polyfill-provider-npm-0.3.3-8c896ae707-8e3fe75513.zip b/.yarn/cache/@babel-helper-define-polyfill-provider-npm-0.3.3-8c896ae707-8e3fe75513.zip new file mode 100644 index 000000000..328790127 Binary files /dev/null and b/.yarn/cache/@babel-helper-define-polyfill-provider-npm-0.3.3-8c896ae707-8e3fe75513.zip differ diff --git a/.yarn/cache/@babel-helper-environment-visitor-npm-7.18.6-e61d5b6be0-64fce65a26.zip b/.yarn/cache/@babel-helper-environment-visitor-npm-7.18.9-9f5b3635a1-b25101f616.zip similarity index 93% rename from .yarn/cache/@babel-helper-environment-visitor-npm-7.18.6-e61d5b6be0-64fce65a26.zip rename to .yarn/cache/@babel-helper-environment-visitor-npm-7.18.9-9f5b3635a1-b25101f616.zip index 1668e1cef..0d38ae67f 100644 Binary files a/.yarn/cache/@babel-helper-environment-visitor-npm-7.18.6-e61d5b6be0-64fce65a26.zip and b/.yarn/cache/@babel-helper-environment-visitor-npm-7.18.9-9f5b3635a1-b25101f616.zip differ diff --git a/.yarn/cache/@babel-helper-function-name-npm-7.18.6-d041b167ad-bf84c2e069.zip b/.yarn/cache/@babel-helper-function-name-npm-7.18.6-d041b167ad-bf84c2e069.zip deleted file mode 100644 index 8d6a14c5e..000000000 Binary files a/.yarn/cache/@babel-helper-function-name-npm-7.18.6-d041b167ad-bf84c2e069.zip and /dev/null differ diff --git a/.yarn/cache/@babel-helper-function-name-npm-7.19.0-5bcf55236f-eac1f5db42.zip b/.yarn/cache/@babel-helper-function-name-npm-7.19.0-5bcf55236f-eac1f5db42.zip new file mode 100644 index 000000000..d5b5c1ac1 Binary files /dev/null and b/.yarn/cache/@babel-helper-function-name-npm-7.19.0-5bcf55236f-eac1f5db42.zip differ diff --git a/.yarn/cache/@babel-helper-member-expression-to-functions-npm-7.18.6-7d8b465c8e-20c8e82d23.zip b/.yarn/cache/@babel-helper-member-expression-to-functions-npm-7.18.6-7d8b465c8e-20c8e82d23.zip deleted file mode 100644 index 79bb0c8f9..000000000 Binary files a/.yarn/cache/@babel-helper-member-expression-to-functions-npm-7.18.6-7d8b465c8e-20c8e82d23.zip and /dev/null differ diff --git a/.yarn/cache/@babel-helper-member-expression-to-functions-npm-7.18.9-3d2128582a-fcf8184e3b.zip b/.yarn/cache/@babel-helper-member-expression-to-functions-npm-7.18.9-3d2128582a-fcf8184e3b.zip new file mode 100644 index 000000000..2bf84c15e Binary files /dev/null and b/.yarn/cache/@babel-helper-member-expression-to-functions-npm-7.18.9-3d2128582a-fcf8184e3b.zip differ diff --git a/.yarn/cache/@babel-helper-module-transforms-npm-7.18.6-91962d1cd6-75d90be9ec.zip b/.yarn/cache/@babel-helper-module-transforms-npm-7.18.6-91962d1cd6-75d90be9ec.zip deleted file mode 100644 index 8a9d35605..000000000 Binary files a/.yarn/cache/@babel-helper-module-transforms-npm-7.18.6-91962d1cd6-75d90be9ec.zip and /dev/null differ diff --git a/.yarn/cache/@babel-helper-module-transforms-npm-7.19.0-a96e10d627-4483276c66.zip b/.yarn/cache/@babel-helper-module-transforms-npm-7.19.0-a96e10d627-4483276c66.zip new file mode 100644 index 000000000..644bc7e9c Binary files /dev/null and b/.yarn/cache/@babel-helper-module-transforms-npm-7.19.0-a96e10d627-4483276c66.zip differ diff --git a/.yarn/cache/@babel-helper-plugin-utils-npm-7.18.6-12ee942c4e-3dbfceb6c1.zip b/.yarn/cache/@babel-helper-plugin-utils-npm-7.18.6-12ee942c4e-3dbfceb6c1.zip deleted file mode 100644 index 82443ff15..000000000 Binary files a/.yarn/cache/@babel-helper-plugin-utils-npm-7.18.6-12ee942c4e-3dbfceb6c1.zip and /dev/null differ diff --git a/.yarn/cache/@babel-helper-remap-async-to-generator-npm-7.18.6-96e7e1c465-83e890624d.zip b/.yarn/cache/@babel-helper-remap-async-to-generator-npm-7.18.9-c29d128186-4be6076192.zip similarity index 65% rename from .yarn/cache/@babel-helper-remap-async-to-generator-npm-7.18.6-96e7e1c465-83e890624d.zip rename to .yarn/cache/@babel-helper-remap-async-to-generator-npm-7.18.9-c29d128186-4be6076192.zip index 54acd69f5..69fd02514 100644 Binary files a/.yarn/cache/@babel-helper-remap-async-to-generator-npm-7.18.6-96e7e1c465-83e890624d.zip and b/.yarn/cache/@babel-helper-remap-async-to-generator-npm-7.18.9-c29d128186-4be6076192.zip differ diff --git a/.yarn/cache/@babel-helper-replace-supers-npm-7.18.6-4951a4fce3-48e869dc8d.zip b/.yarn/cache/@babel-helper-replace-supers-npm-7.18.6-4951a4fce3-48e869dc8d.zip deleted file mode 100644 index 6171363e5..000000000 Binary files a/.yarn/cache/@babel-helper-replace-supers-npm-7.18.6-4951a4fce3-48e869dc8d.zip and /dev/null differ diff --git a/.yarn/cache/@babel-helper-replace-supers-npm-7.19.1-669aa2ecc7-a0e4bf79eb.zip b/.yarn/cache/@babel-helper-replace-supers-npm-7.19.1-669aa2ecc7-a0e4bf79eb.zip new file mode 100644 index 000000000..76ff61035 Binary files /dev/null and b/.yarn/cache/@babel-helper-replace-supers-npm-7.19.1-669aa2ecc7-a0e4bf79eb.zip differ diff --git a/.yarn/cache/@babel-helper-simple-access-npm-7.18.6-4ef4976ebe-37cd36eef1.zip b/.yarn/cache/@babel-helper-simple-access-npm-7.18.6-4ef4976ebe-37cd36eef1.zip deleted file mode 100644 index ec87a6155..000000000 Binary files a/.yarn/cache/@babel-helper-simple-access-npm-7.18.6-4ef4976ebe-37cd36eef1.zip and /dev/null differ diff --git a/.yarn/cache/@babel-helper-simple-access-npm-7.19.4-c02920b575-964cb1ec36.zip b/.yarn/cache/@babel-helper-simple-access-npm-7.19.4-c02920b575-964cb1ec36.zip new file mode 100644 index 000000000..58c4c8b0c Binary files /dev/null and b/.yarn/cache/@babel-helper-simple-access-npm-7.19.4-c02920b575-964cb1ec36.zip differ diff --git a/.yarn/cache/@babel-helper-skip-transparent-expression-wrappers-npm-7.18.6-ffe811ae8d-069750f969.zip b/.yarn/cache/@babel-helper-skip-transparent-expression-wrappers-npm-7.18.9-25945bbc6b-6e93ccd102.zip similarity index 89% rename from .yarn/cache/@babel-helper-skip-transparent-expression-wrappers-npm-7.18.6-ffe811ae8d-069750f969.zip rename to .yarn/cache/@babel-helper-skip-transparent-expression-wrappers-npm-7.18.9-25945bbc6b-6e93ccd102.zip index 470c5e3f6..4991346bb 100644 Binary files a/.yarn/cache/@babel-helper-skip-transparent-expression-wrappers-npm-7.18.6-ffe811ae8d-069750f969.zip and b/.yarn/cache/@babel-helper-skip-transparent-expression-wrappers-npm-7.18.9-25945bbc6b-6e93ccd102.zip differ diff --git a/.yarn/cache/@babel-helper-string-parser-npm-7.18.10-cf6fe67f9a-d554a43933.zip b/.yarn/cache/@babel-helper-string-parser-npm-7.18.10-cf6fe67f9a-d554a43933.zip deleted file mode 100644 index 11010bcd8..000000000 Binary files a/.yarn/cache/@babel-helper-string-parser-npm-7.18.10-cf6fe67f9a-d554a43933.zip and /dev/null differ diff --git a/.yarn/cache/@babel-helper-string-parser-npm-7.19.4-0db110dc3a-b2f8a3920b.zip b/.yarn/cache/@babel-helper-string-parser-npm-7.19.4-0db110dc3a-b2f8a3920b.zip new file mode 100644 index 000000000..f33c403bf Binary files /dev/null and b/.yarn/cache/@babel-helper-string-parser-npm-7.19.4-0db110dc3a-b2f8a3920b.zip differ diff --git a/.yarn/cache/@babel-helper-validator-identifier-npm-7.18.6-357e4653ab-e295254d61.zip b/.yarn/cache/@babel-helper-validator-identifier-npm-7.18.6-357e4653ab-e295254d61.zip deleted file mode 100644 index 4165848d9..000000000 Binary files a/.yarn/cache/@babel-helper-validator-identifier-npm-7.18.6-357e4653ab-e295254d61.zip and /dev/null differ diff --git a/.yarn/cache/@babel-helper-validator-identifier-npm-7.19.1-d84f19e1dc-0eca5e86a7.zip b/.yarn/cache/@babel-helper-validator-identifier-npm-7.19.1-d84f19e1dc-0eca5e86a7.zip new file mode 100644 index 000000000..a76d411ba Binary files /dev/null and b/.yarn/cache/@babel-helper-validator-identifier-npm-7.19.1-d84f19e1dc-0eca5e86a7.zip differ diff --git a/.yarn/cache/@babel-helper-wrap-function-npm-7.18.6-20b10dd947-b7a4f59b30.zip b/.yarn/cache/@babel-helper-wrap-function-npm-7.18.6-20b10dd947-b7a4f59b30.zip deleted file mode 100644 index fa8985336..000000000 Binary files a/.yarn/cache/@babel-helper-wrap-function-npm-7.18.6-20b10dd947-b7a4f59b30.zip and /dev/null differ diff --git a/.yarn/cache/@babel-helper-wrap-function-npm-7.19.0-0db6124801-2453a6b134.zip b/.yarn/cache/@babel-helper-wrap-function-npm-7.19.0-0db6124801-2453a6b134.zip new file mode 100644 index 000000000..d8109d67d Binary files /dev/null and b/.yarn/cache/@babel-helper-wrap-function-npm-7.19.0-0db6124801-2453a6b134.zip differ diff --git a/.yarn/cache/@babel-helpers-npm-7.18.6-113f2054af-5dea4fa537.zip b/.yarn/cache/@babel-helpers-npm-7.18.6-113f2054af-5dea4fa537.zip deleted file mode 100644 index 1572efd73..000000000 Binary files a/.yarn/cache/@babel-helpers-npm-7.18.6-113f2054af-5dea4fa537.zip and /dev/null differ diff --git a/.yarn/cache/@babel-helpers-npm-7.19.4-f9307ad863-e2684e9a79.zip b/.yarn/cache/@babel-helpers-npm-7.19.4-f9307ad863-e2684e9a79.zip new file mode 100644 index 000000000..139cfd5b7 Binary files /dev/null and b/.yarn/cache/@babel-helpers-npm-7.19.4-f9307ad863-e2684e9a79.zip differ diff --git a/.yarn/cache/@babel-parser-npm-7.18.6-f3f50dbfca-533ffc2666.zip b/.yarn/cache/@babel-parser-npm-7.18.6-f3f50dbfca-533ffc2666.zip deleted file mode 100644 index 67d224b50..000000000 Binary files a/.yarn/cache/@babel-parser-npm-7.18.6-f3f50dbfca-533ffc2666.zip and /dev/null differ diff --git a/.yarn/cache/@babel-parser-npm-7.19.4-0c772881aa-5ef97da979.zip b/.yarn/cache/@babel-parser-npm-7.19.4-0c772881aa-5ef97da979.zip new file mode 100644 index 000000000..c0c658799 Binary files /dev/null and b/.yarn/cache/@babel-parser-npm-7.19.4-0c772881aa-5ef97da979.zip differ diff --git a/.yarn/cache/@babel-plugin-bugfix-v8-spread-parameters-in-optional-chaining-npm-7.18.6-19bd418629-0f0057cd12.zip b/.yarn/cache/@babel-plugin-bugfix-v8-spread-parameters-in-optional-chaining-npm-7.18.6-19bd418629-0f0057cd12.zip deleted file mode 100644 index 438777cb9..000000000 Binary files a/.yarn/cache/@babel-plugin-bugfix-v8-spread-parameters-in-optional-chaining-npm-7.18.6-19bd418629-0f0057cd12.zip and /dev/null differ diff --git a/.yarn/cache/@babel-plugin-bugfix-v8-spread-parameters-in-optional-chaining-npm-7.18.9-4ab877f7f6-93abb5cb17.zip b/.yarn/cache/@babel-plugin-bugfix-v8-spread-parameters-in-optional-chaining-npm-7.18.9-4ab877f7f6-93abb5cb17.zip new file mode 100644 index 000000000..2d2ac7c77 Binary files /dev/null and b/.yarn/cache/@babel-plugin-bugfix-v8-spread-parameters-in-optional-chaining-npm-7.18.9-4ab877f7f6-93abb5cb17.zip differ diff --git a/.yarn/cache/@babel-plugin-proposal-async-generator-functions-npm-7.18.6-8e2ee10a99-3f708808ba.zip b/.yarn/cache/@babel-plugin-proposal-async-generator-functions-npm-7.18.6-8e2ee10a99-3f708808ba.zip deleted file mode 100644 index 6c76a6c2c..000000000 Binary files a/.yarn/cache/@babel-plugin-proposal-async-generator-functions-npm-7.18.6-8e2ee10a99-3f708808ba.zip and /dev/null differ diff --git a/.yarn/cache/@babel-plugin-proposal-async-generator-functions-npm-7.19.1-ec555c8b68-f101555b00.zip b/.yarn/cache/@babel-plugin-proposal-async-generator-functions-npm-7.19.1-ec555c8b68-f101555b00.zip new file mode 100644 index 000000000..3bfe48cda Binary files /dev/null and b/.yarn/cache/@babel-plugin-proposal-async-generator-functions-npm-7.19.1-ec555c8b68-f101555b00.zip differ diff --git a/.yarn/cache/@babel-plugin-proposal-decorators-npm-7.18.6-2ab89a46ef-d15e27e5ad.zip b/.yarn/cache/@babel-plugin-proposal-decorators-npm-7.18.6-2ab89a46ef-d15e27e5ad.zip deleted file mode 100644 index d6514ea53..000000000 Binary files a/.yarn/cache/@babel-plugin-proposal-decorators-npm-7.18.6-2ab89a46ef-d15e27e5ad.zip and /dev/null differ diff --git a/.yarn/cache/@babel-plugin-proposal-decorators-npm-7.19.3-f03cc07f6e-d5ff9b9639.zip b/.yarn/cache/@babel-plugin-proposal-decorators-npm-7.19.3-f03cc07f6e-d5ff9b9639.zip new file mode 100644 index 000000000..c6719f448 Binary files /dev/null and b/.yarn/cache/@babel-plugin-proposal-decorators-npm-7.19.3-f03cc07f6e-d5ff9b9639.zip differ diff --git a/.yarn/cache/@babel-plugin-proposal-export-default-from-npm-7.18.6-5990c0558d-fc5c9d6c05.zip b/.yarn/cache/@babel-plugin-proposal-export-default-from-npm-7.18.10-e44e23b3cf-2a12387e09.zip similarity index 54% rename from .yarn/cache/@babel-plugin-proposal-export-default-from-npm-7.18.6-5990c0558d-fc5c9d6c05.zip rename to .yarn/cache/@babel-plugin-proposal-export-default-from-npm-7.18.10-e44e23b3cf-2a12387e09.zip index d8b6bf17e..eba74b3b9 100644 Binary files a/.yarn/cache/@babel-plugin-proposal-export-default-from-npm-7.18.6-5990c0558d-fc5c9d6c05.zip and b/.yarn/cache/@babel-plugin-proposal-export-default-from-npm-7.18.10-e44e23b3cf-2a12387e09.zip differ diff --git a/.yarn/cache/@babel-plugin-proposal-export-namespace-from-npm-7.18.6-d5ce5e55c4-3227307e11.zip b/.yarn/cache/@babel-plugin-proposal-export-namespace-from-npm-7.18.9-6093116864-84ff22bacc.zip similarity index 78% rename from .yarn/cache/@babel-plugin-proposal-export-namespace-from-npm-7.18.6-d5ce5e55c4-3227307e11.zip rename to .yarn/cache/@babel-plugin-proposal-export-namespace-from-npm-7.18.9-6093116864-84ff22bacc.zip index a02843046..223ea90d1 100644 Binary files a/.yarn/cache/@babel-plugin-proposal-export-namespace-from-npm-7.18.6-d5ce5e55c4-3227307e11.zip and b/.yarn/cache/@babel-plugin-proposal-export-namespace-from-npm-7.18.9-6093116864-84ff22bacc.zip differ diff --git a/.yarn/cache/@babel-plugin-proposal-logical-assignment-operators-npm-7.18.6-c2eb74ab8b-4fe0a0d673.zip b/.yarn/cache/@babel-plugin-proposal-logical-assignment-operators-npm-7.18.9-53329219f5-dd87fa4a48.zip similarity index 59% rename from .yarn/cache/@babel-plugin-proposal-logical-assignment-operators-npm-7.18.6-c2eb74ab8b-4fe0a0d673.zip rename to .yarn/cache/@babel-plugin-proposal-logical-assignment-operators-npm-7.18.9-53329219f5-dd87fa4a48.zip index 666356edc..3d18ee980 100644 Binary files a/.yarn/cache/@babel-plugin-proposal-logical-assignment-operators-npm-7.18.6-c2eb74ab8b-4fe0a0d673.zip and b/.yarn/cache/@babel-plugin-proposal-logical-assignment-operators-npm-7.18.9-53329219f5-dd87fa4a48.zip differ diff --git a/.yarn/cache/@babel-plugin-proposal-object-rest-spread-npm-7.18.6-b7490b3e70-9b7516bad2.zip b/.yarn/cache/@babel-plugin-proposal-object-rest-spread-npm-7.18.6-b7490b3e70-9b7516bad2.zip deleted file mode 100644 index 017516908..000000000 Binary files a/.yarn/cache/@babel-plugin-proposal-object-rest-spread-npm-7.18.6-b7490b3e70-9b7516bad2.zip and /dev/null differ diff --git a/.yarn/cache/@babel-plugin-proposal-object-rest-spread-npm-7.19.4-68e455a9f2-90a2a59da3.zip b/.yarn/cache/@babel-plugin-proposal-object-rest-spread-npm-7.19.4-68e455a9f2-90a2a59da3.zip new file mode 100644 index 000000000..a8fde4611 Binary files /dev/null and b/.yarn/cache/@babel-plugin-proposal-object-rest-spread-npm-7.19.4-68e455a9f2-90a2a59da3.zip differ diff --git a/.yarn/cache/@babel-plugin-proposal-optional-chaining-npm-7.18.6-d67a261856-9c3bf80cfb.zip b/.yarn/cache/@babel-plugin-proposal-optional-chaining-npm-7.18.6-d67a261856-9c3bf80cfb.zip deleted file mode 100644 index 1d281eee0..000000000 Binary files a/.yarn/cache/@babel-plugin-proposal-optional-chaining-npm-7.18.6-d67a261856-9c3bf80cfb.zip and /dev/null differ diff --git a/.yarn/cache/@babel-plugin-proposal-optional-chaining-npm-7.18.9-f7302c42f9-f2db40e261.zip b/.yarn/cache/@babel-plugin-proposal-optional-chaining-npm-7.18.9-f7302c42f9-f2db40e261.zip new file mode 100644 index 000000000..eb91a4958 Binary files /dev/null and b/.yarn/cache/@babel-plugin-proposal-optional-chaining-npm-7.18.9-f7302c42f9-f2db40e261.zip differ diff --git a/.yarn/cache/@babel-plugin-syntax-decorators-npm-7.18.6-df7e72cea2-fb84e064b2.zip b/.yarn/cache/@babel-plugin-syntax-decorators-npm-7.18.6-df7e72cea2-fb84e064b2.zip deleted file mode 100644 index 0d5f678c2..000000000 Binary files a/.yarn/cache/@babel-plugin-syntax-decorators-npm-7.18.6-df7e72cea2-fb84e064b2.zip and /dev/null differ diff --git a/.yarn/cache/@babel-plugin-syntax-decorators-npm-7.19.0-9cb5a3793b-105a13d581.zip b/.yarn/cache/@babel-plugin-syntax-decorators-npm-7.19.0-9cb5a3793b-105a13d581.zip new file mode 100644 index 000000000..c801fbd5a Binary files /dev/null and b/.yarn/cache/@babel-plugin-syntax-decorators-npm-7.19.0-9cb5a3793b-105a13d581.zip differ diff --git a/.yarn/cache/@babel-plugin-transform-block-scoping-npm-7.18.6-3e23ec9e80-b117a005a9.zip b/.yarn/cache/@babel-plugin-transform-block-scoping-npm-7.18.6-3e23ec9e80-b117a005a9.zip deleted file mode 100644 index e6f66e1b0..000000000 Binary files a/.yarn/cache/@babel-plugin-transform-block-scoping-npm-7.18.6-3e23ec9e80-b117a005a9.zip and /dev/null differ diff --git a/.yarn/cache/@babel-plugin-transform-block-scoping-npm-7.19.4-6a21a584c0-86353ccbb5.zip b/.yarn/cache/@babel-plugin-transform-block-scoping-npm-7.19.4-6a21a584c0-86353ccbb5.zip new file mode 100644 index 000000000..0a8680cb7 Binary files /dev/null and b/.yarn/cache/@babel-plugin-transform-block-scoping-npm-7.19.4-6a21a584c0-86353ccbb5.zip differ diff --git a/.yarn/cache/@babel-plugin-transform-classes-npm-7.18.6-1c0921371d-661e370379.zip b/.yarn/cache/@babel-plugin-transform-classes-npm-7.18.6-1c0921371d-661e370379.zip deleted file mode 100644 index 433bc3ed9..000000000 Binary files a/.yarn/cache/@babel-plugin-transform-classes-npm-7.18.6-1c0921371d-661e370379.zip and /dev/null differ diff --git a/.yarn/cache/@babel-plugin-transform-classes-npm-7.19.0-6768e825ce-5500953031.zip b/.yarn/cache/@babel-plugin-transform-classes-npm-7.19.0-6768e825ce-5500953031.zip new file mode 100644 index 000000000..516259009 Binary files /dev/null and b/.yarn/cache/@babel-plugin-transform-classes-npm-7.19.0-6768e825ce-5500953031.zip differ diff --git a/.yarn/cache/@babel-plugin-transform-computed-properties-npm-7.18.6-51714bd34c-686d7b9d03.zip b/.yarn/cache/@babel-plugin-transform-computed-properties-npm-7.18.9-bc774f46b8-a6bfbea207.zip similarity index 69% rename from .yarn/cache/@babel-plugin-transform-computed-properties-npm-7.18.6-51714bd34c-686d7b9d03.zip rename to .yarn/cache/@babel-plugin-transform-computed-properties-npm-7.18.9-bc774f46b8-a6bfbea207.zip index 94b0923ce..e5dce481d 100644 Binary files a/.yarn/cache/@babel-plugin-transform-computed-properties-npm-7.18.6-51714bd34c-686d7b9d03.zip and b/.yarn/cache/@babel-plugin-transform-computed-properties-npm-7.18.9-bc774f46b8-a6bfbea207.zip differ diff --git a/.yarn/cache/@babel-plugin-transform-destructuring-npm-7.18.6-699ad9ddd1-256573bd27.zip b/.yarn/cache/@babel-plugin-transform-destructuring-npm-7.18.6-699ad9ddd1-256573bd27.zip deleted file mode 100644 index 904633405..000000000 Binary files a/.yarn/cache/@babel-plugin-transform-destructuring-npm-7.18.6-699ad9ddd1-256573bd27.zip and /dev/null differ diff --git a/.yarn/cache/@babel-plugin-transform-destructuring-npm-7.19.4-bfbd7d9430-0ca40f6abf.zip b/.yarn/cache/@babel-plugin-transform-destructuring-npm-7.19.4-bfbd7d9430-0ca40f6abf.zip new file mode 100644 index 000000000..8b11a3121 Binary files /dev/null and b/.yarn/cache/@babel-plugin-transform-destructuring-npm-7.19.4-bfbd7d9430-0ca40f6abf.zip differ diff --git a/.yarn/cache/@babel-plugin-transform-duplicate-keys-npm-7.18.6-ce437c298a-c21797ae06.zip b/.yarn/cache/@babel-plugin-transform-duplicate-keys-npm-7.18.9-5c77fd31ac-220bf4a9fe.zip similarity index 60% rename from .yarn/cache/@babel-plugin-transform-duplicate-keys-npm-7.18.6-ce437c298a-c21797ae06.zip rename to .yarn/cache/@babel-plugin-transform-duplicate-keys-npm-7.18.9-5c77fd31ac-220bf4a9fe.zip index a6cb3f751..96437e03b 100644 Binary files a/.yarn/cache/@babel-plugin-transform-duplicate-keys-npm-7.18.6-ce437c298a-c21797ae06.zip and b/.yarn/cache/@babel-plugin-transform-duplicate-keys-npm-7.18.9-5c77fd31ac-220bf4a9fe.zip differ diff --git a/.yarn/cache/@babel-plugin-transform-flow-strip-types-npm-7.18.6-ddf91973f6-aff87510c4.zip b/.yarn/cache/@babel-plugin-transform-flow-strip-types-npm-7.18.6-ddf91973f6-aff87510c4.zip deleted file mode 100644 index 65fd2d4b9..000000000 Binary files a/.yarn/cache/@babel-plugin-transform-flow-strip-types-npm-7.18.6-ddf91973f6-aff87510c4.zip and /dev/null differ diff --git a/.yarn/cache/@babel-plugin-transform-flow-strip-types-npm-7.19.0-9fdcf3079d-c35339bf80.zip b/.yarn/cache/@babel-plugin-transform-flow-strip-types-npm-7.19.0-9fdcf3079d-c35339bf80.zip new file mode 100644 index 000000000..8ef147571 Binary files /dev/null and b/.yarn/cache/@babel-plugin-transform-flow-strip-types-npm-7.19.0-9fdcf3079d-c35339bf80.zip differ diff --git a/.yarn/cache/@babel-plugin-transform-for-of-npm-7.18.6-ae3773ac99-fd92e18d6c.zip b/.yarn/cache/@babel-plugin-transform-for-of-npm-7.18.8-ae76b5daf1-ca64c623cf.zip similarity index 79% rename from .yarn/cache/@babel-plugin-transform-for-of-npm-7.18.6-ae3773ac99-fd92e18d6c.zip rename to .yarn/cache/@babel-plugin-transform-for-of-npm-7.18.8-ae76b5daf1-ca64c623cf.zip index a4cfa3abf..9d0d71af9 100644 Binary files a/.yarn/cache/@babel-plugin-transform-for-of-npm-7.18.6-ae3773ac99-fd92e18d6c.zip and b/.yarn/cache/@babel-plugin-transform-for-of-npm-7.18.8-ae76b5daf1-ca64c623cf.zip differ diff --git a/.yarn/cache/@babel-plugin-transform-function-name-npm-7.18.6-ed01a12a47-d15d36f52d.zip b/.yarn/cache/@babel-plugin-transform-function-name-npm-7.18.9-4e425dceeb-62dd9c6cdc.zip similarity index 60% rename from .yarn/cache/@babel-plugin-transform-function-name-npm-7.18.6-ed01a12a47-d15d36f52d.zip rename to .yarn/cache/@babel-plugin-transform-function-name-npm-7.18.9-4e425dceeb-62dd9c6cdc.zip index 6c3a0f82f..ac04c14ef 100644 Binary files a/.yarn/cache/@babel-plugin-transform-function-name-npm-7.18.6-ed01a12a47-d15d36f52d.zip and b/.yarn/cache/@babel-plugin-transform-function-name-npm-7.18.9-4e425dceeb-62dd9c6cdc.zip differ diff --git a/.yarn/cache/@babel-plugin-transform-literals-npm-7.18.6-fd74177638-859e2405d5.zip b/.yarn/cache/@babel-plugin-transform-literals-npm-7.18.9-d87aa5e6d7-3458dd2f1a.zip similarity index 58% rename from .yarn/cache/@babel-plugin-transform-literals-npm-7.18.6-fd74177638-859e2405d5.zip rename to .yarn/cache/@babel-plugin-transform-literals-npm-7.18.9-d87aa5e6d7-3458dd2f1a.zip index c7d4483b0..19ab6c9d1 100644 Binary files a/.yarn/cache/@babel-plugin-transform-literals-npm-7.18.6-fd74177638-859e2405d5.zip and b/.yarn/cache/@babel-plugin-transform-literals-npm-7.18.9-d87aa5e6d7-3458dd2f1a.zip differ diff --git a/.yarn/cache/@babel-plugin-transform-modules-systemjs-npm-7.18.6-510d17950d-69e476477f.zip b/.yarn/cache/@babel-plugin-transform-modules-systemjs-npm-7.18.6-510d17950d-69e476477f.zip deleted file mode 100644 index f6abd8690..000000000 Binary files a/.yarn/cache/@babel-plugin-transform-modules-systemjs-npm-7.18.6-510d17950d-69e476477f.zip and /dev/null differ diff --git a/.yarn/cache/@babel-plugin-transform-modules-systemjs-npm-7.19.0-60b11d2425-a0742deee4.zip b/.yarn/cache/@babel-plugin-transform-modules-systemjs-npm-7.19.0-60b11d2425-a0742deee4.zip new file mode 100644 index 000000000..5e5e3a670 Binary files /dev/null and b/.yarn/cache/@babel-plugin-transform-modules-systemjs-npm-7.19.0-60b11d2425-a0742deee4.zip differ diff --git a/.yarn/cache/@babel-plugin-transform-named-capturing-groups-regex-npm-7.18.6-dc604756da-6ef64aa3da.zip b/.yarn/cache/@babel-plugin-transform-named-capturing-groups-regex-npm-7.18.6-dc604756da-6ef64aa3da.zip deleted file mode 100644 index 4697b0513..000000000 Binary files a/.yarn/cache/@babel-plugin-transform-named-capturing-groups-regex-npm-7.18.6-dc604756da-6ef64aa3da.zip and /dev/null differ diff --git a/.yarn/cache/@babel-plugin-transform-named-capturing-groups-regex-npm-7.19.1-6822ddb28e-8a40f5d04f.zip b/.yarn/cache/@babel-plugin-transform-named-capturing-groups-regex-npm-7.19.1-6822ddb28e-8a40f5d04f.zip new file mode 100644 index 000000000..3ef0403b8 Binary files /dev/null and b/.yarn/cache/@babel-plugin-transform-named-capturing-groups-regex-npm-7.19.1-6822ddb28e-8a40f5d04f.zip differ diff --git a/.yarn/cache/@babel-plugin-transform-parameters-npm-7.18.6-1f9857e3a1-35bfdf5b2e.zip b/.yarn/cache/@babel-plugin-transform-parameters-npm-7.18.6-1f9857e3a1-35bfdf5b2e.zip deleted file mode 100644 index c4bd614aa..000000000 Binary files a/.yarn/cache/@babel-plugin-transform-parameters-npm-7.18.6-1f9857e3a1-35bfdf5b2e.zip and /dev/null differ diff --git a/.yarn/cache/@babel-plugin-transform-parameters-npm-7.18.8-4c778bfd7e-2b5863300d.zip b/.yarn/cache/@babel-plugin-transform-parameters-npm-7.18.8-4c778bfd7e-2b5863300d.zip new file mode 100644 index 000000000..ad400865c Binary files /dev/null and b/.yarn/cache/@babel-plugin-transform-parameters-npm-7.18.8-4c778bfd7e-2b5863300d.zip differ diff --git a/.yarn/cache/@babel-plugin-transform-react-constant-elements-npm-7.18.12-c89dcdf4ad-d83fbc65e8.zip b/.yarn/cache/@babel-plugin-transform-react-constant-elements-npm-7.18.12-c89dcdf4ad-d83fbc65e8.zip new file mode 100644 index 000000000..80704b0c9 Binary files /dev/null and b/.yarn/cache/@babel-plugin-transform-react-constant-elements-npm-7.18.12-c89dcdf4ad-d83fbc65e8.zip differ diff --git a/.yarn/cache/@babel-plugin-transform-react-constant-elements-npm-7.18.6-ebcc4d541e-8ad4773193.zip b/.yarn/cache/@babel-plugin-transform-react-constant-elements-npm-7.18.6-ebcc4d541e-8ad4773193.zip deleted file mode 100644 index 2bb422ce8..000000000 Binary files a/.yarn/cache/@babel-plugin-transform-react-constant-elements-npm-7.18.6-ebcc4d541e-8ad4773193.zip and /dev/null differ diff --git a/.yarn/cache/@babel-plugin-transform-react-jsx-npm-7.18.6-86ec96ec31-46129eaf1a.zip b/.yarn/cache/@babel-plugin-transform-react-jsx-npm-7.18.6-86ec96ec31-46129eaf1a.zip deleted file mode 100644 index 10a0cdce2..000000000 Binary files a/.yarn/cache/@babel-plugin-transform-react-jsx-npm-7.18.6-86ec96ec31-46129eaf1a.zip and /dev/null differ diff --git a/.yarn/cache/@babel-plugin-transform-runtime-npm-7.18.6-9e7bc666a1-ed1ee31d02.zip b/.yarn/cache/@babel-plugin-transform-runtime-npm-7.18.6-9e7bc666a1-ed1ee31d02.zip deleted file mode 100644 index d3f0cf570..000000000 Binary files a/.yarn/cache/@babel-plugin-transform-runtime-npm-7.18.6-9e7bc666a1-ed1ee31d02.zip and /dev/null differ diff --git a/.yarn/cache/@babel-plugin-transform-runtime-npm-7.19.1-ff83462bc6-d9f693003a.zip b/.yarn/cache/@babel-plugin-transform-runtime-npm-7.19.1-ff83462bc6-d9f693003a.zip new file mode 100644 index 000000000..393a0dddf Binary files /dev/null and b/.yarn/cache/@babel-plugin-transform-runtime-npm-7.19.1-ff83462bc6-d9f693003a.zip differ diff --git a/.yarn/cache/@babel-plugin-transform-spread-npm-7.18.6-cb489a1bba-996b139ed6.zip b/.yarn/cache/@babel-plugin-transform-spread-npm-7.18.6-cb489a1bba-996b139ed6.zip deleted file mode 100644 index 05f6f414f..000000000 Binary files a/.yarn/cache/@babel-plugin-transform-spread-npm-7.18.6-cb489a1bba-996b139ed6.zip and /dev/null differ diff --git a/.yarn/cache/@babel-plugin-transform-spread-npm-7.19.0-ab4a212eb3-e73a4deb09.zip b/.yarn/cache/@babel-plugin-transform-spread-npm-7.19.0-ab4a212eb3-e73a4deb09.zip new file mode 100644 index 000000000..0bd98c2c1 Binary files /dev/null and b/.yarn/cache/@babel-plugin-transform-spread-npm-7.19.0-ab4a212eb3-e73a4deb09.zip differ diff --git a/.yarn/cache/@babel-plugin-transform-template-literals-npm-7.18.6-a579eb9359-6ec354415f.zip b/.yarn/cache/@babel-plugin-transform-template-literals-npm-7.18.9-787bf6a528-3d2fcd79b7.zip similarity index 68% rename from .yarn/cache/@babel-plugin-transform-template-literals-npm-7.18.6-a579eb9359-6ec354415f.zip rename to .yarn/cache/@babel-plugin-transform-template-literals-npm-7.18.9-787bf6a528-3d2fcd79b7.zip index cc617b3da..4e3288eb7 100644 Binary files a/.yarn/cache/@babel-plugin-transform-template-literals-npm-7.18.6-a579eb9359-6ec354415f.zip and b/.yarn/cache/@babel-plugin-transform-template-literals-npm-7.18.9-787bf6a528-3d2fcd79b7.zip differ diff --git a/.yarn/cache/@babel-plugin-transform-typeof-symbol-npm-7.18.6-2394493f2c-b018ac3275.zip b/.yarn/cache/@babel-plugin-transform-typeof-symbol-npm-7.18.9-0775d325d9-e754e0d8b8.zip similarity index 62% rename from .yarn/cache/@babel-plugin-transform-typeof-symbol-npm-7.18.6-2394493f2c-b018ac3275.zip rename to .yarn/cache/@babel-plugin-transform-typeof-symbol-npm-7.18.9-0775d325d9-e754e0d8b8.zip index c7aecd1f8..75517f98e 100644 Binary files a/.yarn/cache/@babel-plugin-transform-typeof-symbol-npm-7.18.6-2394493f2c-b018ac3275.zip and b/.yarn/cache/@babel-plugin-transform-typeof-symbol-npm-7.18.9-0775d325d9-e754e0d8b8.zip differ diff --git a/.yarn/cache/@babel-plugin-transform-typescript-npm-7.18.6-0eb33c6e99-9dc0703046.zip b/.yarn/cache/@babel-plugin-transform-typescript-npm-7.18.6-0eb33c6e99-9dc0703046.zip deleted file mode 100644 index bbda94b92..000000000 Binary files a/.yarn/cache/@babel-plugin-transform-typescript-npm-7.18.6-0eb33c6e99-9dc0703046.zip and /dev/null differ diff --git a/.yarn/cache/@babel-plugin-transform-typescript-npm-7.19.3-f9b18d40fd-094c8c4ad0.zip b/.yarn/cache/@babel-plugin-transform-typescript-npm-7.19.3-f9b18d40fd-094c8c4ad0.zip new file mode 100644 index 000000000..4fc3516ca Binary files /dev/null and b/.yarn/cache/@babel-plugin-transform-typescript-npm-7.19.3-f9b18d40fd-094c8c4ad0.zip differ diff --git a/.yarn/cache/@babel-plugin-transform-unicode-escapes-npm-7.18.6-0101e1c508-297a037067.zip b/.yarn/cache/@babel-plugin-transform-unicode-escapes-npm-7.18.10-83a00fbee1-f5baca55cb.zip similarity index 69% rename from .yarn/cache/@babel-plugin-transform-unicode-escapes-npm-7.18.6-0101e1c508-297a037067.zip rename to .yarn/cache/@babel-plugin-transform-unicode-escapes-npm-7.18.10-83a00fbee1-f5baca55cb.zip index 39265d453..4f95570c1 100644 Binary files a/.yarn/cache/@babel-plugin-transform-unicode-escapes-npm-7.18.6-0101e1c508-297a037067.zip and b/.yarn/cache/@babel-plugin-transform-unicode-escapes-npm-7.18.10-83a00fbee1-f5baca55cb.zip differ diff --git a/.yarn/cache/@babel-preset-env-npm-7.18.6-adec1c5702-0598ff98b6.zip b/.yarn/cache/@babel-preset-env-npm-7.18.6-adec1c5702-0598ff98b6.zip deleted file mode 100644 index 7fb0c1589..000000000 Binary files a/.yarn/cache/@babel-preset-env-npm-7.18.6-adec1c5702-0598ff98b6.zip and /dev/null differ diff --git a/.yarn/cache/@babel-preset-env-npm-7.19.4-b69b33437e-f12af25281.zip b/.yarn/cache/@babel-preset-env-npm-7.19.4-b69b33437e-f12af25281.zip new file mode 100644 index 000000000..1f1573f3b Binary files /dev/null and b/.yarn/cache/@babel-preset-env-npm-7.19.4-b69b33437e-f12af25281.zip differ diff --git a/.yarn/cache/@babel-register-npm-7.18.6-68d797704c-2e55995a7f.zip b/.yarn/cache/@babel-register-npm-7.18.9-bcdce8aed1-4aeaff97e0.zip similarity index 61% rename from .yarn/cache/@babel-register-npm-7.18.6-68d797704c-2e55995a7f.zip rename to .yarn/cache/@babel-register-npm-7.18.9-bcdce8aed1-4aeaff97e0.zip index df18e1cf2..88d1e89b6 100644 Binary files a/.yarn/cache/@babel-register-npm-7.18.6-68d797704c-2e55995a7f.zip and b/.yarn/cache/@babel-register-npm-7.18.9-bcdce8aed1-4aeaff97e0.zip differ diff --git a/.yarn/cache/@babel-runtime-corejs3-npm-7.18.6-88718bb709-55a5315b2e.zip b/.yarn/cache/@babel-runtime-corejs3-npm-7.18.6-88718bb709-55a5315b2e.zip deleted file mode 100644 index 445d63b08..000000000 Binary files a/.yarn/cache/@babel-runtime-corejs3-npm-7.18.6-88718bb709-55a5315b2e.zip and /dev/null differ diff --git a/.yarn/cache/@babel-runtime-corejs3-npm-7.19.4-0547036932-3418534964.zip b/.yarn/cache/@babel-runtime-corejs3-npm-7.19.4-0547036932-3418534964.zip new file mode 100644 index 000000000..1f04e484a Binary files /dev/null and b/.yarn/cache/@babel-runtime-corejs3-npm-7.19.4-0547036932-3418534964.zip differ diff --git a/.yarn/cache/@babel-runtime-npm-7.18.6-6a59ef0d54-8b707b64ae.zip b/.yarn/cache/@babel-runtime-npm-7.18.6-6a59ef0d54-8b707b64ae.zip deleted file mode 100644 index afffbf6db..000000000 Binary files a/.yarn/cache/@babel-runtime-npm-7.18.6-6a59ef0d54-8b707b64ae.zip and /dev/null differ diff --git a/.yarn/cache/@babel-runtime-npm-7.19.4-9f106cb4dd-66b7e3c13e.zip b/.yarn/cache/@babel-runtime-npm-7.19.4-9f106cb4dd-66b7e3c13e.zip new file mode 100644 index 000000000..2f6080e3a Binary files /dev/null and b/.yarn/cache/@babel-runtime-npm-7.19.4-9f106cb4dd-66b7e3c13e.zip differ diff --git a/.yarn/cache/@babel-template-npm-7.18.6-56635d3ce4-cb02ed804b.zip b/.yarn/cache/@babel-template-npm-7.18.10-b6d6fdbaf8-93a6aa094a.zip similarity index 87% rename from .yarn/cache/@babel-template-npm-7.18.6-56635d3ce4-cb02ed804b.zip rename to .yarn/cache/@babel-template-npm-7.18.10-b6d6fdbaf8-93a6aa094a.zip index c367ce39e..08a1c3821 100644 Binary files a/.yarn/cache/@babel-template-npm-7.18.6-56635d3ce4-cb02ed804b.zip and b/.yarn/cache/@babel-template-npm-7.18.10-b6d6fdbaf8-93a6aa094a.zip differ diff --git a/.yarn/cache/@babel-traverse-npm-7.18.6-ab4298b064-5427a9db63.zip b/.yarn/cache/@babel-traverse-npm-7.18.6-ab4298b064-5427a9db63.zip deleted file mode 100644 index 824e6b868..000000000 Binary files a/.yarn/cache/@babel-traverse-npm-7.18.6-ab4298b064-5427a9db63.zip and /dev/null differ diff --git a/.yarn/cache/@babel-traverse-npm-7.19.4-57e0236e96-8ae1ac3dac.zip b/.yarn/cache/@babel-traverse-npm-7.19.4-57e0236e96-8ae1ac3dac.zip new file mode 100644 index 000000000..8601115ac Binary files /dev/null and b/.yarn/cache/@babel-traverse-npm-7.19.4-57e0236e96-8ae1ac3dac.zip differ diff --git a/.yarn/cache/@babel-types-npm-7.18.7-ce70018628-3114ce161c.zip b/.yarn/cache/@babel-types-npm-7.18.7-ce70018628-3114ce161c.zip deleted file mode 100644 index 104c122a2..000000000 Binary files a/.yarn/cache/@babel-types-npm-7.18.7-ce70018628-3114ce161c.zip and /dev/null differ diff --git a/.yarn/cache/@babel-types-npm-7.19.0-8c9f82c2b5-9b346715a6.zip b/.yarn/cache/@babel-types-npm-7.19.4-9a7b64a650-4032f64070.zip similarity index 62% rename from .yarn/cache/@babel-types-npm-7.19.0-8c9f82c2b5-9b346715a6.zip rename to .yarn/cache/@babel-types-npm-7.19.4-9a7b64a650-4032f64070.zip index bc9d6133e..95aacad9c 100644 Binary files a/.yarn/cache/@babel-types-npm-7.19.0-8c9f82c2b5-9b346715a6.zip and b/.yarn/cache/@babel-types-npm-7.19.4-9a7b64a650-4032f64070.zip differ diff --git a/.yarn/cache/@commitlint-cli-npm-17.0.3-802065b1af-d8319889e0.zip b/.yarn/cache/@commitlint-cli-npm-17.0.3-802065b1af-d8319889e0.zip deleted file mode 100644 index d8095bcd7..000000000 Binary files a/.yarn/cache/@commitlint-cli-npm-17.0.3-802065b1af-d8319889e0.zip and /dev/null differ diff --git a/.yarn/cache/@commitlint-cli-npm-17.1.2-8a99e7ce6e-2f87c560ed.zip b/.yarn/cache/@commitlint-cli-npm-17.1.2-8a99e7ce6e-2f87c560ed.zip new file mode 100644 index 000000000..d98596d91 Binary files /dev/null and b/.yarn/cache/@commitlint-cli-npm-17.1.2-8a99e7ce6e-2f87c560ed.zip differ diff --git a/.yarn/cache/@commitlint-config-conventional-npm-17.0.3-58ee159448-1cd30d827c.zip b/.yarn/cache/@commitlint-config-conventional-npm-17.0.3-58ee159448-1cd30d827c.zip deleted file mode 100644 index 144cabe18..000000000 Binary files a/.yarn/cache/@commitlint-config-conventional-npm-17.0.3-58ee159448-1cd30d827c.zip and /dev/null differ diff --git a/.yarn/cache/@commitlint-config-conventional-npm-17.1.0-a81296e2ff-8209f6b105.zip b/.yarn/cache/@commitlint-config-conventional-npm-17.1.0-a81296e2ff-8209f6b105.zip new file mode 100644 index 000000000..985ba6af9 Binary files /dev/null and b/.yarn/cache/@commitlint-config-conventional-npm-17.1.0-a81296e2ff-8209f6b105.zip differ diff --git a/.yarn/cache/@commitlint-config-validator-npm-17.0.3-721ee560ed-bc543193bb.zip b/.yarn/cache/@commitlint-config-validator-npm-17.1.0-fffdc0ccb1-18b4779837.zip similarity index 63% rename from .yarn/cache/@commitlint-config-validator-npm-17.0.3-721ee560ed-bc543193bb.zip rename to .yarn/cache/@commitlint-config-validator-npm-17.1.0-fffdc0ccb1-18b4779837.zip index 0ea5a8ea1..12693ec65 100644 Binary files a/.yarn/cache/@commitlint-config-validator-npm-17.0.3-721ee560ed-bc543193bb.zip and b/.yarn/cache/@commitlint-config-validator-npm-17.1.0-fffdc0ccb1-18b4779837.zip differ diff --git a/.yarn/cache/@commitlint-is-ignored-npm-17.0.3-ada095e18a-5a0b1921ea.zip b/.yarn/cache/@commitlint-is-ignored-npm-17.1.0-1fa49e0e03-d371e7dbf1.zip similarity index 56% rename from .yarn/cache/@commitlint-is-ignored-npm-17.0.3-ada095e18a-5a0b1921ea.zip rename to .yarn/cache/@commitlint-is-ignored-npm-17.1.0-1fa49e0e03-d371e7dbf1.zip index 391f9babc..0e056e311 100644 Binary files a/.yarn/cache/@commitlint-is-ignored-npm-17.0.3-ada095e18a-5a0b1921ea.zip and b/.yarn/cache/@commitlint-is-ignored-npm-17.1.0-1fa49e0e03-d371e7dbf1.zip differ diff --git a/.yarn/cache/@commitlint-lint-npm-17.0.3-396678e8c7-5bbb8bc1f3.zip b/.yarn/cache/@commitlint-lint-npm-17.1.0-48cb2729b4-a457461da4.zip similarity index 59% rename from .yarn/cache/@commitlint-lint-npm-17.0.3-396678e8c7-5bbb8bc1f3.zip rename to .yarn/cache/@commitlint-lint-npm-17.1.0-48cb2729b4-a457461da4.zip index f7b955ef0..b739e2162 100644 Binary files a/.yarn/cache/@commitlint-lint-npm-17.0.3-396678e8c7-5bbb8bc1f3.zip and b/.yarn/cache/@commitlint-lint-npm-17.1.0-48cb2729b4-a457461da4.zip differ diff --git a/.yarn/cache/@commitlint-load-npm-17.0.3-6a5895c82d-786b706447.zip b/.yarn/cache/@commitlint-load-npm-17.1.2-2dba76a786-c01e2d8a5b.zip similarity index 58% rename from .yarn/cache/@commitlint-load-npm-17.0.3-6a5895c82d-786b706447.zip rename to .yarn/cache/@commitlint-load-npm-17.1.2-2dba76a786-c01e2d8a5b.zip index 382245780..33ad122ae 100644 Binary files a/.yarn/cache/@commitlint-load-npm-17.0.3-6a5895c82d-786b706447.zip and b/.yarn/cache/@commitlint-load-npm-17.1.2-2dba76a786-c01e2d8a5b.zip differ diff --git a/.yarn/cache/@commitlint-read-npm-17.0.0-ca6839b4e3-5307d9ba06.zip b/.yarn/cache/@commitlint-read-npm-17.0.0-ca6839b4e3-5307d9ba06.zip deleted file mode 100644 index aa6f36be4..000000000 Binary files a/.yarn/cache/@commitlint-read-npm-17.0.0-ca6839b4e3-5307d9ba06.zip and /dev/null differ diff --git a/.yarn/cache/@commitlint-read-npm-17.1.0-9504842e03-b9f728860a.zip b/.yarn/cache/@commitlint-read-npm-17.1.0-9504842e03-b9f728860a.zip new file mode 100644 index 000000000..e49561596 Binary files /dev/null and b/.yarn/cache/@commitlint-read-npm-17.1.0-9504842e03-b9f728860a.zip differ diff --git a/.yarn/cache/@commitlint-resolve-extends-npm-17.0.3-70f5e27c89-384fc59a5a.zip b/.yarn/cache/@commitlint-resolve-extends-npm-17.0.3-70f5e27c89-384fc59a5a.zip deleted file mode 100644 index 262052b26..000000000 Binary files a/.yarn/cache/@commitlint-resolve-extends-npm-17.0.3-70f5e27c89-384fc59a5a.zip and /dev/null differ diff --git a/.yarn/cache/@commitlint-resolve-extends-npm-17.1.0-a12929b9a2-cc50ed7ca9.zip b/.yarn/cache/@commitlint-resolve-extends-npm-17.1.0-a12929b9a2-cc50ed7ca9.zip new file mode 100644 index 000000000..975cbccbd Binary files /dev/null and b/.yarn/cache/@commitlint-resolve-extends-npm-17.1.0-a12929b9a2-cc50ed7ca9.zip differ diff --git a/.yarn/cache/@csstools-postcss-cascade-layers-npm-1.0.4-5e1bd8dc8e-1edaa13111.zip b/.yarn/cache/@csstools-postcss-cascade-layers-npm-1.0.4-5e1bd8dc8e-1edaa13111.zip deleted file mode 100644 index ed706fe4a..000000000 Binary files a/.yarn/cache/@csstools-postcss-cascade-layers-npm-1.0.4-5e1bd8dc8e-1edaa13111.zip and /dev/null differ diff --git a/.yarn/cache/@csstools-postcss-cascade-layers-npm-1.1.1-4382e19cf0-8ecd6a929e.zip b/.yarn/cache/@csstools-postcss-cascade-layers-npm-1.1.1-4382e19cf0-8ecd6a929e.zip new file mode 100644 index 000000000..e5004abda Binary files /dev/null and b/.yarn/cache/@csstools-postcss-cascade-layers-npm-1.1.1-4382e19cf0-8ecd6a929e.zip differ diff --git a/.yarn/cache/@csstools-postcss-color-function-npm-1.1.0-f2bed658a4-1378858848.zip b/.yarn/cache/@csstools-postcss-color-function-npm-1.1.0-f2bed658a4-1378858848.zip deleted file mode 100644 index 33ad6f3b1..000000000 Binary files a/.yarn/cache/@csstools-postcss-color-function-npm-1.1.0-f2bed658a4-1378858848.zip and /dev/null differ diff --git a/.yarn/cache/@csstools-postcss-color-function-npm-1.1.1-7c5a0199ae-087595985e.zip b/.yarn/cache/@csstools-postcss-color-function-npm-1.1.1-7c5a0199ae-087595985e.zip new file mode 100644 index 000000000..66d1c7173 Binary files /dev/null and b/.yarn/cache/@csstools-postcss-color-function-npm-1.1.1-7c5a0199ae-087595985e.zip differ diff --git a/.yarn/cache/@csstools-postcss-font-format-keywords-npm-1.0.0-428d96321d-4f41dccc46.zip b/.yarn/cache/@csstools-postcss-font-format-keywords-npm-1.0.1-ef1db49912-ed8d9eab97.zip similarity index 54% rename from .yarn/cache/@csstools-postcss-font-format-keywords-npm-1.0.0-428d96321d-4f41dccc46.zip rename to .yarn/cache/@csstools-postcss-font-format-keywords-npm-1.0.1-ef1db49912-ed8d9eab97.zip index 615bda52e..23151048f 100644 Binary files a/.yarn/cache/@csstools-postcss-font-format-keywords-npm-1.0.0-428d96321d-4f41dccc46.zip and b/.yarn/cache/@csstools-postcss-font-format-keywords-npm-1.0.1-ef1db49912-ed8d9eab97.zip differ diff --git a/.yarn/cache/@csstools-postcss-hwb-function-npm-1.0.1-72ef206578-c57a74ac5c.zip b/.yarn/cache/@csstools-postcss-hwb-function-npm-1.0.1-72ef206578-c57a74ac5c.zip deleted file mode 100644 index b0cb0e6e4..000000000 Binary files a/.yarn/cache/@csstools-postcss-hwb-function-npm-1.0.1-72ef206578-c57a74ac5c.zip and /dev/null differ diff --git a/.yarn/cache/@csstools-postcss-hwb-function-npm-1.0.2-f3f621e351-352ead754a.zip b/.yarn/cache/@csstools-postcss-hwb-function-npm-1.0.2-f3f621e351-352ead754a.zip new file mode 100644 index 000000000..8d64eb64b Binary files /dev/null and b/.yarn/cache/@csstools-postcss-hwb-function-npm-1.0.2-f3f621e351-352ead754a.zip differ diff --git a/.yarn/cache/@csstools-postcss-ic-unit-npm-1.0.0-a3a477691b-d194b13a66.zip b/.yarn/cache/@csstools-postcss-ic-unit-npm-1.0.1-111638e451-09c414c9b7.zip similarity index 55% rename from .yarn/cache/@csstools-postcss-ic-unit-npm-1.0.0-a3a477691b-d194b13a66.zip rename to .yarn/cache/@csstools-postcss-ic-unit-npm-1.0.1-111638e451-09c414c9b7.zip index 6c8bab6a4..da992c785 100644 Binary files a/.yarn/cache/@csstools-postcss-ic-unit-npm-1.0.0-a3a477691b-d194b13a66.zip and b/.yarn/cache/@csstools-postcss-ic-unit-npm-1.0.1-111638e451-09c414c9b7.zip differ diff --git a/.yarn/cache/@csstools-postcss-is-pseudo-class-npm-2.0.6-1fb4de6176-66206ca4fa.zip b/.yarn/cache/@csstools-postcss-is-pseudo-class-npm-2.0.6-1fb4de6176-66206ca4fa.zip deleted file mode 100644 index 389544863..000000000 Binary files a/.yarn/cache/@csstools-postcss-is-pseudo-class-npm-2.0.6-1fb4de6176-66206ca4fa.zip and /dev/null differ diff --git a/.yarn/cache/@csstools-postcss-is-pseudo-class-npm-2.0.7-c85939401b-a4494bb8e9.zip b/.yarn/cache/@csstools-postcss-is-pseudo-class-npm-2.0.7-c85939401b-a4494bb8e9.zip new file mode 100644 index 000000000..8032fcf79 Binary files /dev/null and b/.yarn/cache/@csstools-postcss-is-pseudo-class-npm-2.0.7-c85939401b-a4494bb8e9.zip differ diff --git a/.yarn/cache/@csstools-postcss-nested-calc-npm-1.0.0-8028506411-53bb783dd6.zip b/.yarn/cache/@csstools-postcss-nested-calc-npm-1.0.0-8028506411-53bb783dd6.zip new file mode 100644 index 000000000..978822eac Binary files /dev/null and b/.yarn/cache/@csstools-postcss-nested-calc-npm-1.0.0-8028506411-53bb783dd6.zip differ diff --git a/.yarn/cache/@csstools-postcss-normalize-display-values-npm-1.0.0-2c171afd14-5751a171f3.zip b/.yarn/cache/@csstools-postcss-normalize-display-values-npm-1.0.0-2c171afd14-5751a171f3.zip deleted file mode 100644 index d971ab8a6..000000000 Binary files a/.yarn/cache/@csstools-postcss-normalize-display-values-npm-1.0.0-2c171afd14-5751a171f3.zip and /dev/null differ diff --git a/.yarn/cache/@csstools-postcss-normalize-display-values-npm-1.0.1-53721ce3eb-75901daec3.zip b/.yarn/cache/@csstools-postcss-normalize-display-values-npm-1.0.1-53721ce3eb-75901daec3.zip new file mode 100644 index 000000000..35ca3defa Binary files /dev/null and b/.yarn/cache/@csstools-postcss-normalize-display-values-npm-1.0.1-53721ce3eb-75901daec3.zip differ diff --git a/.yarn/cache/@csstools-postcss-oklab-function-npm-1.1.0-4b0abbcbd2-d59616e6ac.zip b/.yarn/cache/@csstools-postcss-oklab-function-npm-1.1.0-4b0abbcbd2-d59616e6ac.zip deleted file mode 100644 index 6d41b99a8..000000000 Binary files a/.yarn/cache/@csstools-postcss-oklab-function-npm-1.1.0-4b0abbcbd2-d59616e6ac.zip and /dev/null differ diff --git a/.yarn/cache/@csstools-postcss-oklab-function-npm-1.1.1-2907029cf1-d66b789060.zip b/.yarn/cache/@csstools-postcss-oklab-function-npm-1.1.1-2907029cf1-d66b789060.zip new file mode 100644 index 000000000..52806763a Binary files /dev/null and b/.yarn/cache/@csstools-postcss-oklab-function-npm-1.1.1-2907029cf1-d66b789060.zip differ diff --git a/.yarn/cache/@csstools-postcss-stepped-value-functions-npm-1.0.0-4b4c8a4008-48e9c20a84.zip b/.yarn/cache/@csstools-postcss-stepped-value-functions-npm-1.0.0-4b4c8a4008-48e9c20a84.zip deleted file mode 100644 index fc80c842d..000000000 Binary files a/.yarn/cache/@csstools-postcss-stepped-value-functions-npm-1.0.0-4b4c8a4008-48e9c20a84.zip and /dev/null differ diff --git a/.yarn/cache/@csstools-postcss-stepped-value-functions-npm-1.0.1-01aa1138bd-2fc88713a0.zip b/.yarn/cache/@csstools-postcss-stepped-value-functions-npm-1.0.1-01aa1138bd-2fc88713a0.zip new file mode 100644 index 000000000..196f2e29f Binary files /dev/null and b/.yarn/cache/@csstools-postcss-stepped-value-functions-npm-1.0.1-01aa1138bd-2fc88713a0.zip differ diff --git a/.yarn/cache/@csstools-postcss-text-decoration-shorthand-npm-1.0.0-96f61ef9fe-d27aaf9787.zip b/.yarn/cache/@csstools-postcss-text-decoration-shorthand-npm-1.0.0-96f61ef9fe-d27aaf9787.zip new file mode 100644 index 000000000..0974bc6e2 Binary files /dev/null and b/.yarn/cache/@csstools-postcss-text-decoration-shorthand-npm-1.0.0-96f61ef9fe-d27aaf9787.zip differ diff --git a/.yarn/cache/@csstools-postcss-trigonometric-functions-npm-1.0.1-2a1acb98c5-28de7e3550.zip b/.yarn/cache/@csstools-postcss-trigonometric-functions-npm-1.0.2-4553514702-f7f5b5f249.zip similarity index 57% rename from .yarn/cache/@csstools-postcss-trigonometric-functions-npm-1.0.1-2a1acb98c5-28de7e3550.zip rename to .yarn/cache/@csstools-postcss-trigonometric-functions-npm-1.0.2-4553514702-f7f5b5f249.zip index 5986568ae..d341796e4 100644 Binary files a/.yarn/cache/@csstools-postcss-trigonometric-functions-npm-1.0.1-2a1acb98c5-28de7e3550.zip and b/.yarn/cache/@csstools-postcss-trigonometric-functions-npm-1.0.2-4553514702-f7f5b5f249.zip differ diff --git a/.yarn/cache/@csstools-postcss-unset-value-npm-1.0.1-95ea0340a2-4d355a88ec.zip b/.yarn/cache/@csstools-postcss-unset-value-npm-1.0.1-95ea0340a2-4d355a88ec.zip deleted file mode 100644 index 6a3b4442a..000000000 Binary files a/.yarn/cache/@csstools-postcss-unset-value-npm-1.0.1-95ea0340a2-4d355a88ec.zip and /dev/null differ diff --git a/.yarn/cache/@csstools-postcss-unset-value-npm-1.0.2-f57c79bfc4-3facdae154.zip b/.yarn/cache/@csstools-postcss-unset-value-npm-1.0.2-f57c79bfc4-3facdae154.zip new file mode 100644 index 000000000..bf2793b21 Binary files /dev/null and b/.yarn/cache/@csstools-postcss-unset-value-npm-1.0.2-f57c79bfc4-3facdae154.zip differ diff --git a/.yarn/cache/@csstools-selector-specificity-npm-2.0.1-3a3919b882-08ec92e674.zip b/.yarn/cache/@csstools-selector-specificity-npm-2.0.2-cbab31242a-a2045a2727.zip similarity index 56% rename from .yarn/cache/@csstools-selector-specificity-npm-2.0.1-3a3919b882-08ec92e674.zip rename to .yarn/cache/@csstools-selector-specificity-npm-2.0.2-cbab31242a-a2045a2727.zip index 5810a39e9..0c7df367a 100644 Binary files a/.yarn/cache/@csstools-selector-specificity-npm-2.0.1-3a3919b882-08ec92e674.zip and b/.yarn/cache/@csstools-selector-specificity-npm-2.0.2-cbab31242a-a2045a2727.zip differ diff --git a/.yarn/cache/@docsearch-css-npm-3.1.1-bc9688ebd1-bbcee5b5cf.zip b/.yarn/cache/@docsearch-css-npm-3.1.1-bc9688ebd1-bbcee5b5cf.zip deleted file mode 100644 index 5e5393bf5..000000000 Binary files a/.yarn/cache/@docsearch-css-npm-3.1.1-bc9688ebd1-bbcee5b5cf.zip and /dev/null differ diff --git a/.yarn/cache/@docsearch-css-npm-3.2.1-74e2292a38-ab7a36a34c.zip b/.yarn/cache/@docsearch-css-npm-3.2.1-74e2292a38-ab7a36a34c.zip new file mode 100644 index 000000000..bc97e3770 Binary files /dev/null and b/.yarn/cache/@docsearch-css-npm-3.2.1-74e2292a38-ab7a36a34c.zip differ diff --git a/.yarn/cache/@docsearch-react-npm-3.1.1-756a016bea-36035fc878.zip b/.yarn/cache/@docsearch-react-npm-3.2.1-dcbe05bdcc-62e4b45bc1.zip similarity index 75% rename from .yarn/cache/@docsearch-react-npm-3.1.1-756a016bea-36035fc878.zip rename to .yarn/cache/@docsearch-react-npm-3.2.1-dcbe05bdcc-62e4b45bc1.zip index 6745af74e..65e65e922 100644 Binary files a/.yarn/cache/@docsearch-react-npm-3.1.1-756a016bea-36035fc878.zip and b/.yarn/cache/@docsearch-react-npm-3.2.1-dcbe05bdcc-62e4b45bc1.zip differ diff --git a/.yarn/cache/@docusaurus-core-npm-2.0.0-beta.21-4363851e6a-5f065225a2.zip b/.yarn/cache/@docusaurus-core-npm-2.1.0-ee70472f68-c8f12d87d0.zip similarity index 57% rename from .yarn/cache/@docusaurus-core-npm-2.0.0-beta.21-4363851e6a-5f065225a2.zip rename to .yarn/cache/@docusaurus-core-npm-2.1.0-ee70472f68-c8f12d87d0.zip index f15c0e3d4..be9e5f6a4 100644 Binary files a/.yarn/cache/@docusaurus-core-npm-2.0.0-beta.21-4363851e6a-5f065225a2.zip and b/.yarn/cache/@docusaurus-core-npm-2.1.0-ee70472f68-c8f12d87d0.zip differ diff --git a/.yarn/cache/@docusaurus-cssnano-preset-npm-2.0.0-beta.21-adf3357170-0822077a6d.zip b/.yarn/cache/@docusaurus-cssnano-preset-npm-2.1.0-a1a0dadc88-3589dcd8dc.zip similarity index 54% rename from .yarn/cache/@docusaurus-cssnano-preset-npm-2.0.0-beta.21-adf3357170-0822077a6d.zip rename to .yarn/cache/@docusaurus-cssnano-preset-npm-2.1.0-a1a0dadc88-3589dcd8dc.zip index 47be25ab5..274201ce2 100644 Binary files a/.yarn/cache/@docusaurus-cssnano-preset-npm-2.0.0-beta.21-adf3357170-0822077a6d.zip and b/.yarn/cache/@docusaurus-cssnano-preset-npm-2.1.0-a1a0dadc88-3589dcd8dc.zip differ diff --git a/.yarn/cache/@docusaurus-logger-npm-2.0.0-beta.21-ecfac1da70-7b2f991b9a.zip b/.yarn/cache/@docusaurus-logger-npm-2.1.0-56726a5a69-af13df70b6.zip similarity index 89% rename from .yarn/cache/@docusaurus-logger-npm-2.0.0-beta.21-ecfac1da70-7b2f991b9a.zip rename to .yarn/cache/@docusaurus-logger-npm-2.1.0-56726a5a69-af13df70b6.zip index 5eba0f293..fe9bf2085 100644 Binary files a/.yarn/cache/@docusaurus-logger-npm-2.0.0-beta.21-ecfac1da70-7b2f991b9a.zip and b/.yarn/cache/@docusaurus-logger-npm-2.1.0-56726a5a69-af13df70b6.zip differ diff --git a/.yarn/cache/@docusaurus-mdx-loader-npm-2.0.0-beta.21-1e02457e1f-d537cbb59f.zip b/.yarn/cache/@docusaurus-mdx-loader-npm-2.0.0-beta.21-1e02457e1f-d537cbb59f.zip deleted file mode 100644 index 094ce7ff3..000000000 Binary files a/.yarn/cache/@docusaurus-mdx-loader-npm-2.0.0-beta.21-1e02457e1f-d537cbb59f.zip and /dev/null differ diff --git a/.yarn/cache/@docusaurus-mdx-loader-npm-2.1.0-8a33968e6f-799982ad50.zip b/.yarn/cache/@docusaurus-mdx-loader-npm-2.1.0-8a33968e6f-799982ad50.zip new file mode 100644 index 000000000..4d2e0b266 Binary files /dev/null and b/.yarn/cache/@docusaurus-mdx-loader-npm-2.1.0-8a33968e6f-799982ad50.zip differ diff --git a/.yarn/cache/@docusaurus-plugin-client-redirects-npm-2.0.0-beta.21-af03c7f17c-9b11e4d71f.zip b/.yarn/cache/@docusaurus-plugin-client-redirects-npm-2.0.0-beta.21-af03c7f17c-9b11e4d71f.zip deleted file mode 100644 index 8baa25401..000000000 Binary files a/.yarn/cache/@docusaurus-plugin-client-redirects-npm-2.0.0-beta.21-af03c7f17c-9b11e4d71f.zip and /dev/null differ diff --git a/.yarn/cache/@docusaurus-plugin-client-redirects-npm-2.1.0-66d8c83da3-22fb5be283.zip b/.yarn/cache/@docusaurus-plugin-client-redirects-npm-2.1.0-66d8c83da3-22fb5be283.zip new file mode 100644 index 000000000..15df84b40 Binary files /dev/null and b/.yarn/cache/@docusaurus-plugin-client-redirects-npm-2.1.0-66d8c83da3-22fb5be283.zip differ diff --git a/.yarn/cache/@docusaurus-utils-common-npm-2.0.0-beta.21-48031f4306-9c7ae87f96.zip b/.yarn/cache/@docusaurus-utils-common-npm-2.1.0-7c83c53819-b4a9282f55.zip similarity index 72% rename from .yarn/cache/@docusaurus-utils-common-npm-2.0.0-beta.21-48031f4306-9c7ae87f96.zip rename to .yarn/cache/@docusaurus-utils-common-npm-2.1.0-7c83c53819-b4a9282f55.zip index aa7f7926f..82c1fa529 100644 Binary files a/.yarn/cache/@docusaurus-utils-common-npm-2.0.0-beta.21-48031f4306-9c7ae87f96.zip and b/.yarn/cache/@docusaurus-utils-common-npm-2.1.0-7c83c53819-b4a9282f55.zip differ diff --git a/.yarn/cache/@docusaurus-utils-npm-2.0.0-beta.21-ccca74e747-ee160b23d5.zip b/.yarn/cache/@docusaurus-utils-npm-2.1.0-aff6efc19a-970c8b2716.zip similarity index 55% rename from .yarn/cache/@docusaurus-utils-npm-2.0.0-beta.21-ccca74e747-ee160b23d5.zip rename to .yarn/cache/@docusaurus-utils-npm-2.1.0-aff6efc19a-970c8b2716.zip index 04621a5be..86784ab27 100644 Binary files a/.yarn/cache/@docusaurus-utils-npm-2.0.0-beta.21-ccca74e747-ee160b23d5.zip and b/.yarn/cache/@docusaurus-utils-npm-2.1.0-aff6efc19a-970c8b2716.zip differ diff --git a/.yarn/cache/@docusaurus-utils-validation-npm-2.0.0-beta.21-f828a15203-aa4d558b84.zip b/.yarn/cache/@docusaurus-utils-validation-npm-2.1.0-4f80534005-63fa924768.zip similarity index 55% rename from .yarn/cache/@docusaurus-utils-validation-npm-2.0.0-beta.21-f828a15203-aa4d558b84.zip rename to .yarn/cache/@docusaurus-utils-validation-npm-2.1.0-4f80534005-63fa924768.zip index cfc1d5dbb..6de7d33ce 100644 Binary files a/.yarn/cache/@docusaurus-utils-validation-npm-2.0.0-beta.21-f828a15203-aa4d558b84.zip and b/.yarn/cache/@docusaurus-utils-validation-npm-2.1.0-4f80534005-63fa924768.zip differ diff --git a/.yarn/cache/@egjs-hammerjs-npm-2.0.17-2e03ba4087-8945137cec.zip b/.yarn/cache/@egjs-hammerjs-npm-2.0.17-2e03ba4087-8945137cec.zip deleted file mode 100644 index 0f2a845b3..000000000 Binary files a/.yarn/cache/@egjs-hammerjs-npm-2.0.17-2e03ba4087-8945137cec.zip and /dev/null differ diff --git a/.yarn/cache/@emotion-babel-plugin-npm-11.10.2-5ade7f379a-7f9e84b3c0.zip b/.yarn/cache/@emotion-babel-plugin-npm-11.10.2-5ade7f379a-7f9e84b3c0.zip new file mode 100644 index 000000000..0a89202c5 Binary files /dev/null and b/.yarn/cache/@emotion-babel-plugin-npm-11.10.2-5ade7f379a-7f9e84b3c0.zip differ diff --git a/.yarn/cache/@emotion-babel-plugin-npm-11.9.2-9822f587b1-2d2c4fadd3.zip b/.yarn/cache/@emotion-babel-plugin-npm-11.9.2-9822f587b1-2d2c4fadd3.zip deleted file mode 100644 index a836322b2..000000000 Binary files a/.yarn/cache/@emotion-babel-plugin-npm-11.9.2-9822f587b1-2d2c4fadd3.zip and /dev/null differ diff --git a/.yarn/cache/@emotion-cache-npm-11.10.3-77f93c9eba-d31291eff1.zip b/.yarn/cache/@emotion-cache-npm-11.10.3-77f93c9eba-d31291eff1.zip new file mode 100644 index 000000000..b61bb5fb5 Binary files /dev/null and b/.yarn/cache/@emotion-cache-npm-11.10.3-77f93c9eba-d31291eff1.zip differ diff --git a/.yarn/cache/@emotion-cache-npm-11.9.3-19440f4c2c-6e0aab2fa5.zip b/.yarn/cache/@emotion-cache-npm-11.9.3-19440f4c2c-6e0aab2fa5.zip deleted file mode 100644 index 2b8c1cf7c..000000000 Binary files a/.yarn/cache/@emotion-cache-npm-11.9.3-19440f4c2c-6e0aab2fa5.zip and /dev/null differ diff --git a/.yarn/cache/@emotion-css-npm-11.10.0-c14df613df-677b90607a.zip b/.yarn/cache/@emotion-css-npm-11.10.0-c14df613df-677b90607a.zip new file mode 100644 index 000000000..9caf39ded Binary files /dev/null and b/.yarn/cache/@emotion-css-npm-11.10.0-c14df613df-677b90607a.zip differ diff --git a/.yarn/cache/@emotion-css-npm-11.9.0-e415e285ad-bd83d9af5c.zip b/.yarn/cache/@emotion-css-npm-11.9.0-e415e285ad-bd83d9af5c.zip deleted file mode 100644 index 9be55cba7..000000000 Binary files a/.yarn/cache/@emotion-css-npm-11.9.0-e415e285ad-bd83d9af5c.zip and /dev/null differ diff --git a/.yarn/cache/@emotion-hash-npm-0.8.0-0104f4bbf3-4b35d88a97.zip b/.yarn/cache/@emotion-hash-npm-0.8.0-0104f4bbf3-4b35d88a97.zip deleted file mode 100644 index a857b7327..000000000 Binary files a/.yarn/cache/@emotion-hash-npm-0.8.0-0104f4bbf3-4b35d88a97.zip and /dev/null differ diff --git a/.yarn/cache/@emotion-hash-npm-0.9.0-efbc0b3f3f-b63428f7c8.zip b/.yarn/cache/@emotion-hash-npm-0.9.0-efbc0b3f3f-b63428f7c8.zip new file mode 100644 index 000000000..1361c9e81 Binary files /dev/null and b/.yarn/cache/@emotion-hash-npm-0.9.0-efbc0b3f3f-b63428f7c8.zip differ diff --git a/.yarn/cache/@emotion-is-prop-valid-npm-1.1.3-d70163c49e-511997c3bb.zip b/.yarn/cache/@emotion-is-prop-valid-npm-1.2.0-332d343e3d-cc7a19850a.zip similarity index 59% rename from .yarn/cache/@emotion-is-prop-valid-npm-1.1.3-d70163c49e-511997c3bb.zip rename to .yarn/cache/@emotion-is-prop-valid-npm-1.2.0-332d343e3d-cc7a19850a.zip index 399887170..db9df9ffa 100644 Binary files a/.yarn/cache/@emotion-is-prop-valid-npm-1.1.3-d70163c49e-511997c3bb.zip and b/.yarn/cache/@emotion-is-prop-valid-npm-1.2.0-332d343e3d-cc7a19850a.zip differ diff --git a/.yarn/cache/@emotion-memoize-npm-0.7.5-e5e7e9eeca-83da8d4a76.zip b/.yarn/cache/@emotion-memoize-npm-0.7.5-e5e7e9eeca-83da8d4a76.zip deleted file mode 100644 index dc37d07e5..000000000 Binary files a/.yarn/cache/@emotion-memoize-npm-0.7.5-e5e7e9eeca-83da8d4a76.zip and /dev/null differ diff --git a/.yarn/cache/@emotion-memoize-npm-0.8.0-c5dd451828-c87bb110b8.zip b/.yarn/cache/@emotion-memoize-npm-0.8.0-c5dd451828-c87bb110b8.zip new file mode 100644 index 000000000..8561995f4 Binary files /dev/null and b/.yarn/cache/@emotion-memoize-npm-0.8.0-c5dd451828-c87bb110b8.zip differ diff --git a/.yarn/cache/@emotion-serialize-npm-1.0.4-5d4f6d63ee-e8cc342056.zip b/.yarn/cache/@emotion-serialize-npm-1.1.0-492b26b387-8f22f83194.zip similarity index 66% rename from .yarn/cache/@emotion-serialize-npm-1.0.4-5d4f6d63ee-e8cc342056.zip rename to .yarn/cache/@emotion-serialize-npm-1.1.0-492b26b387-8f22f83194.zip index a73cb48e6..691274caf 100644 Binary files a/.yarn/cache/@emotion-serialize-npm-1.0.4-5d4f6d63ee-e8cc342056.zip and b/.yarn/cache/@emotion-serialize-npm-1.1.0-492b26b387-8f22f83194.zip differ diff --git a/.yarn/cache/@emotion-sheet-npm-1.1.1-9e89b4e29a-b916ac6657.zip b/.yarn/cache/@emotion-sheet-npm-1.2.0-3bb8dd5fba-b3771e4796.zip similarity index 64% rename from .yarn/cache/@emotion-sheet-npm-1.1.1-9e89b4e29a-b916ac6657.zip rename to .yarn/cache/@emotion-sheet-npm-1.2.0-3bb8dd5fba-b3771e4796.zip index 6c0259c66..1edf2f5ac 100644 Binary files a/.yarn/cache/@emotion-sheet-npm-1.1.1-9e89b4e29a-b916ac6657.zip and b/.yarn/cache/@emotion-sheet-npm-1.2.0-3bb8dd5fba-b3771e4796.zip differ diff --git a/.yarn/cache/@emotion-unitless-npm-0.8.0-aa125284fa-176141117e.zip b/.yarn/cache/@emotion-unitless-npm-0.8.0-aa125284fa-176141117e.zip new file mode 100644 index 000000000..e50a0da68 Binary files /dev/null and b/.yarn/cache/@emotion-unitless-npm-0.8.0-aa125284fa-176141117e.zip differ diff --git a/.yarn/cache/@emotion-utils-npm-1.1.0-cab2893c1f-d3b681ca3a.zip b/.yarn/cache/@emotion-utils-npm-1.1.0-cab2893c1f-d3b681ca3a.zip deleted file mode 100644 index 9fea704c7..000000000 Binary files a/.yarn/cache/@emotion-utils-npm-1.1.0-cab2893c1f-d3b681ca3a.zip and /dev/null differ diff --git a/.yarn/cache/@emotion-utils-npm-1.2.0-337992f692-55457a49dd.zip b/.yarn/cache/@emotion-utils-npm-1.2.0-337992f692-55457a49dd.zip new file mode 100644 index 000000000..5ff7513cf Binary files /dev/null and b/.yarn/cache/@emotion-utils-npm-1.2.0-337992f692-55457a49dd.zip differ diff --git a/.yarn/cache/@emotion-weak-memoize-npm-0.2.5-9f2e49e7c8-27d402b0c6.zip b/.yarn/cache/@emotion-weak-memoize-npm-0.2.5-9f2e49e7c8-27d402b0c6.zip deleted file mode 100644 index 7001bba7b..000000000 Binary files a/.yarn/cache/@emotion-weak-memoize-npm-0.2.5-9f2e49e7c8-27d402b0c6.zip and /dev/null differ diff --git a/.yarn/cache/@emotion-weak-memoize-npm-0.3.0-705bdd075b-f43ef4c8b7.zip b/.yarn/cache/@emotion-weak-memoize-npm-0.3.0-705bdd075b-f43ef4c8b7.zip new file mode 100644 index 000000000..51c0e8991 Binary files /dev/null and b/.yarn/cache/@emotion-weak-memoize-npm-0.3.0-705bdd075b-f43ef4c8b7.zip differ diff --git a/.yarn/cache/@eslint-eslintrc-npm-1.3.0-1f3c51be25-a1e734ad31.zip b/.yarn/cache/@eslint-eslintrc-npm-1.3.0-1f3c51be25-a1e734ad31.zip deleted file mode 100644 index e9b7fa21a..000000000 Binary files a/.yarn/cache/@eslint-eslintrc-npm-1.3.0-1f3c51be25-a1e734ad31.zip and /dev/null differ diff --git a/.yarn/cache/@eslint-eslintrc-npm-1.3.1-f9e7aea43c-9844dcc58a.zip b/.yarn/cache/@eslint-eslintrc-npm-1.3.1-f9e7aea43c-9844dcc58a.zip deleted file mode 100644 index 8bfc979a3..000000000 Binary files a/.yarn/cache/@eslint-eslintrc-npm-1.3.1-f9e7aea43c-9844dcc58a.zip and /dev/null differ diff --git a/.yarn/cache/@eslint-eslintrc-npm-1.3.2-fd8de37609-2074dca47d.zip b/.yarn/cache/@eslint-eslintrc-npm-1.3.3-9e3a462140-f03e9d6727.zip similarity index 77% rename from .yarn/cache/@eslint-eslintrc-npm-1.3.2-fd8de37609-2074dca47d.zip rename to .yarn/cache/@eslint-eslintrc-npm-1.3.3-9e3a462140-f03e9d6727.zip index c2a4a6d81..4d1a8efd5 100644 Binary files a/.yarn/cache/@eslint-eslintrc-npm-1.3.2-fd8de37609-2074dca47d.zip and b/.yarn/cache/@eslint-eslintrc-npm-1.3.3-9e3a462140-f03e9d6727.zip differ diff --git a/.yarn/cache/@expo-react-native-action-sheet-npm-3.13.0-6a87d86cf4-e05e1221bf.zip b/.yarn/cache/@expo-react-native-action-sheet-npm-3.13.0-6a87d86cf4-e05e1221bf.zip deleted file mode 100644 index e282feb74..000000000 Binary files a/.yarn/cache/@expo-react-native-action-sheet-npm-3.13.0-6a87d86cf4-e05e1221bf.zip and /dev/null differ diff --git a/.yarn/cache/@humanwhocodes-config-array-npm-0.10.4-8334b3c6a2-d480e5d57e.zip b/.yarn/cache/@humanwhocodes-config-array-npm-0.10.4-8334b3c6a2-d480e5d57e.zip deleted file mode 100644 index 70b164425..000000000 Binary files a/.yarn/cache/@humanwhocodes-config-array-npm-0.10.4-8334b3c6a2-d480e5d57e.zip and /dev/null differ diff --git a/.yarn/cache/@humanwhocodes-config-array-npm-0.10.7-81c0f4b5e6-009d64be8d.zip b/.yarn/cache/@humanwhocodes-config-array-npm-0.10.7-81c0f4b5e6-009d64be8d.zip new file mode 100644 index 000000000..9bcc70f2c Binary files /dev/null and b/.yarn/cache/@humanwhocodes-config-array-npm-0.10.7-81c0f4b5e6-009d64be8d.zip differ diff --git a/.yarn/cache/@humanwhocodes-config-array-npm-0.9.5-030a025eae-8ba6281bc0.zip b/.yarn/cache/@humanwhocodes-config-array-npm-0.9.5-030a025eae-8ba6281bc0.zip deleted file mode 100644 index 63f5f5e83..000000000 Binary files a/.yarn/cache/@humanwhocodes-config-array-npm-0.9.5-030a025eae-8ba6281bc0.zip and /dev/null differ diff --git a/.yarn/cache/@humanwhocodes-gitignore-to-minimatch-npm-1.0.2-247ae8a408-aba5c40c9e.zip b/.yarn/cache/@humanwhocodes-gitignore-to-minimatch-npm-1.0.2-247ae8a408-aba5c40c9e.zip deleted file mode 100644 index 2636f8c63..000000000 Binary files a/.yarn/cache/@humanwhocodes-gitignore-to-minimatch-npm-1.0.2-247ae8a408-aba5c40c9e.zip and /dev/null differ diff --git a/.yarn/cache/@jest-console-npm-28.1.1-02118260a4-ddf3b9e9b0.zip b/.yarn/cache/@jest-console-npm-28.1.3-8b24613279-fe50d98d26.zip similarity index 90% rename from .yarn/cache/@jest-console-npm-28.1.1-02118260a4-ddf3b9e9b0.zip rename to .yarn/cache/@jest-console-npm-28.1.3-8b24613279-fe50d98d26.zip index 03cb39fdc..5fd0570d2 100644 Binary files a/.yarn/cache/@jest-console-npm-28.1.1-02118260a4-ddf3b9e9b0.zip and b/.yarn/cache/@jest-console-npm-28.1.3-8b24613279-fe50d98d26.zip differ diff --git a/.yarn/cache/@jest-core-npm-28.1.2-d632a1ee2e-dd67cc911c.zip b/.yarn/cache/@jest-core-npm-28.1.3-4b9647f71c-cb79f34baf.zip similarity index 96% rename from .yarn/cache/@jest-core-npm-28.1.2-d632a1ee2e-dd67cc911c.zip rename to .yarn/cache/@jest-core-npm-28.1.3-4b9647f71c-cb79f34baf.zip index d1e0ca8c5..ef357ac7f 100644 Binary files a/.yarn/cache/@jest-core-npm-28.1.2-d632a1ee2e-dd67cc911c.zip and b/.yarn/cache/@jest-core-npm-28.1.3-4b9647f71c-cb79f34baf.zip differ diff --git a/.yarn/cache/@jest-environment-npm-28.1.2-5ba92d7c1b-5bffc464e9.zip b/.yarn/cache/@jest-environment-npm-28.1.3-506a81a227-14c496b84a.zip similarity index 86% rename from .yarn/cache/@jest-environment-npm-28.1.2-5ba92d7c1b-5bffc464e9.zip rename to .yarn/cache/@jest-environment-npm-28.1.3-506a81a227-14c496b84a.zip index 7318e7176..9386cbb77 100644 Binary files a/.yarn/cache/@jest-environment-npm-28.1.2-5ba92d7c1b-5bffc464e9.zip and b/.yarn/cache/@jest-environment-npm-28.1.3-506a81a227-14c496b84a.zip differ diff --git a/.yarn/cache/@jest-expect-npm-28.1.2-c1ba663cb5-ee470cdd3a.zip b/.yarn/cache/@jest-expect-npm-28.1.3-3794e8420c-4197f6fddd.zip similarity index 80% rename from .yarn/cache/@jest-expect-npm-28.1.2-c1ba663cb5-ee470cdd3a.zip rename to .yarn/cache/@jest-expect-npm-28.1.3-3794e8420c-4197f6fddd.zip index 4ace2a492..f491793c2 100644 Binary files a/.yarn/cache/@jest-expect-npm-28.1.2-c1ba663cb5-ee470cdd3a.zip and b/.yarn/cache/@jest-expect-npm-28.1.3-3794e8420c-4197f6fddd.zip differ diff --git a/.yarn/cache/@jest-expect-utils-npm-28.1.1-1823a850d9-46a2ad754b.zip b/.yarn/cache/@jest-expect-utils-npm-28.1.1-1823a850d9-46a2ad754b.zip deleted file mode 100644 index bed0e498a..000000000 Binary files a/.yarn/cache/@jest-expect-utils-npm-28.1.1-1823a850d9-46a2ad754b.zip and /dev/null differ diff --git a/.yarn/cache/@jest-expect-utils-npm-28.1.3-d83dfb8847-808ea3a682.zip b/.yarn/cache/@jest-expect-utils-npm-28.1.3-d83dfb8847-808ea3a682.zip new file mode 100644 index 000000000..53361781d Binary files /dev/null and b/.yarn/cache/@jest-expect-utils-npm-28.1.3-d83dfb8847-808ea3a682.zip differ diff --git a/.yarn/cache/@jest-expect-utils-npm-29.0.3-418f13fbb0-af6fa6e0b9.zip b/.yarn/cache/@jest-expect-utils-npm-29.1.2-4ea76b5f23-31c2a690b5.zip similarity index 92% rename from .yarn/cache/@jest-expect-utils-npm-29.0.3-418f13fbb0-af6fa6e0b9.zip rename to .yarn/cache/@jest-expect-utils-npm-29.1.2-4ea76b5f23-31c2a690b5.zip index d45070219..6c25b0ebc 100644 Binary files a/.yarn/cache/@jest-expect-utils-npm-29.0.3-418f13fbb0-af6fa6e0b9.zip and b/.yarn/cache/@jest-expect-utils-npm-29.1.2-4ea76b5f23-31c2a690b5.zip differ diff --git a/.yarn/cache/@jest-fake-timers-npm-28.1.2-708e436e77-d6e6b1a12f.zip b/.yarn/cache/@jest-fake-timers-npm-28.1.3-593b0acb9a-cec14d5b14.zip similarity index 92% rename from .yarn/cache/@jest-fake-timers-npm-28.1.2-708e436e77-d6e6b1a12f.zip rename to .yarn/cache/@jest-fake-timers-npm-28.1.3-593b0acb9a-cec14d5b14.zip index 4a37426a1..661fe7f9e 100644 Binary files a/.yarn/cache/@jest-fake-timers-npm-28.1.2-708e436e77-d6e6b1a12f.zip and b/.yarn/cache/@jest-fake-timers-npm-28.1.3-593b0acb9a-cec14d5b14.zip differ diff --git a/.yarn/cache/@jest-globals-npm-28.1.2-a3b0bd62de-f07b7d0a2d.zip b/.yarn/cache/@jest-globals-npm-28.1.3-fee1b2ab3f-3504bb23de.zip similarity index 74% rename from .yarn/cache/@jest-globals-npm-28.1.2-a3b0bd62de-f07b7d0a2d.zip rename to .yarn/cache/@jest-globals-npm-28.1.3-fee1b2ab3f-3504bb23de.zip index 7637c890b..6cd127f33 100644 Binary files a/.yarn/cache/@jest-globals-npm-28.1.2-a3b0bd62de-f07b7d0a2d.zip and b/.yarn/cache/@jest-globals-npm-28.1.3-fee1b2ab3f-3504bb23de.zip differ diff --git a/.yarn/cache/@jest-reporters-npm-28.1.2-8a0dea0c1e-26aa66e8ea.zip b/.yarn/cache/@jest-reporters-npm-28.1.3-548703b241-a7440887ce.zip similarity index 97% rename from .yarn/cache/@jest-reporters-npm-28.1.2-8a0dea0c1e-26aa66e8ea.zip rename to .yarn/cache/@jest-reporters-npm-28.1.3-548703b241-a7440887ce.zip index dffb58830..ecb0124a0 100644 Binary files a/.yarn/cache/@jest-reporters-npm-28.1.2-8a0dea0c1e-26aa66e8ea.zip and b/.yarn/cache/@jest-reporters-npm-28.1.3-548703b241-a7440887ce.zip differ diff --git a/.yarn/cache/@jest-schemas-npm-28.0.2-482c1c45c3-6a177e97b1.zip b/.yarn/cache/@jest-schemas-npm-28.0.2-482c1c45c3-6a177e97b1.zip deleted file mode 100644 index 6c022e262..000000000 Binary files a/.yarn/cache/@jest-schemas-npm-28.0.2-482c1c45c3-6a177e97b1.zip and /dev/null differ diff --git a/.yarn/cache/@jest-schemas-npm-28.1.3-231835b296-3cf1d4b66c.zip b/.yarn/cache/@jest-schemas-npm-28.1.3-231835b296-3cf1d4b66c.zip new file mode 100644 index 000000000..543567200 Binary files /dev/null and b/.yarn/cache/@jest-schemas-npm-28.1.3-231835b296-3cf1d4b66c.zip differ diff --git a/.yarn/cache/@jest-test-result-npm-28.1.1-fac1180af0-8812db2649.zip b/.yarn/cache/@jest-test-result-npm-28.1.3-678ecd0b36-957a5dd2fd.zip similarity index 80% rename from .yarn/cache/@jest-test-result-npm-28.1.1-fac1180af0-8812db2649.zip rename to .yarn/cache/@jest-test-result-npm-28.1.3-678ecd0b36-957a5dd2fd.zip index 4f9afe8e3..d54e6bb78 100644 Binary files a/.yarn/cache/@jest-test-result-npm-28.1.1-fac1180af0-8812db2649.zip and b/.yarn/cache/@jest-test-result-npm-28.1.3-678ecd0b36-957a5dd2fd.zip differ diff --git a/.yarn/cache/@jest-test-sequencer-npm-28.1.1-d7bbefa803-acfa3b7ff1.zip b/.yarn/cache/@jest-test-sequencer-npm-28.1.3-456bc6e2ff-13f8905e6d.zip similarity index 88% rename from .yarn/cache/@jest-test-sequencer-npm-28.1.1-d7bbefa803-acfa3b7ff1.zip rename to .yarn/cache/@jest-test-sequencer-npm-28.1.3-456bc6e2ff-13f8905e6d.zip index 34001bc13..ea553591e 100644 Binary files a/.yarn/cache/@jest-test-sequencer-npm-28.1.1-d7bbefa803-acfa3b7ff1.zip and b/.yarn/cache/@jest-test-sequencer-npm-28.1.3-456bc6e2ff-13f8905e6d.zip differ diff --git a/.yarn/cache/@jest-transform-npm-28.1.2-6f3b28178a-cd8d1bdf1a.zip b/.yarn/cache/@jest-transform-npm-28.1.3-c63694eb02-dadf618936.zip similarity index 94% rename from .yarn/cache/@jest-transform-npm-28.1.2-6f3b28178a-cd8d1bdf1a.zip rename to .yarn/cache/@jest-transform-npm-28.1.3-c63694eb02-dadf618936.zip index 4fbb4c261..945e9f595 100644 Binary files a/.yarn/cache/@jest-transform-npm-28.1.2-6f3b28178a-cd8d1bdf1a.zip and b/.yarn/cache/@jest-transform-npm-28.1.3-c63694eb02-dadf618936.zip differ diff --git a/.yarn/cache/@jest-types-npm-28.1.1-ea2654ccbe-3c35d3674e.zip b/.yarn/cache/@jest-types-npm-28.1.3-422ad1bd71-1e258d9c06.zip similarity index 90% rename from .yarn/cache/@jest-types-npm-28.1.1-ea2654ccbe-3c35d3674e.zip rename to .yarn/cache/@jest-types-npm-28.1.3-422ad1bd71-1e258d9c06.zip index 7d314932b..a872d70d4 100644 Binary files a/.yarn/cache/@jest-types-npm-28.1.1-ea2654ccbe-3c35d3674e.zip and b/.yarn/cache/@jest-types-npm-28.1.3-422ad1bd71-1e258d9c06.zip differ diff --git a/.yarn/cache/@jest-types-npm-29.0.3-5cd97a4e8b-3bd33e64d8.zip b/.yarn/cache/@jest-types-npm-29.0.3-5cd97a4e8b-3bd33e64d8.zip deleted file mode 100644 index c54cc5706..000000000 Binary files a/.yarn/cache/@jest-types-npm-29.0.3-5cd97a4e8b-3bd33e64d8.zip and /dev/null differ diff --git a/.yarn/cache/@jest-types-npm-29.1.2-0dbe55dc45-697fc72c37.zip b/.yarn/cache/@jest-types-npm-29.1.2-0dbe55dc45-697fc72c37.zip new file mode 100644 index 000000000..84955d3e8 Binary files /dev/null and b/.yarn/cache/@jest-types-npm-29.1.2-0dbe55dc45-697fc72c37.zip differ diff --git a/.yarn/cache/@jridgewell-resolve-uri-npm-3.0.8-94779c6a1d-28d739f49b.zip b/.yarn/cache/@jridgewell-resolve-uri-npm-3.0.8-94779c6a1d-28d739f49b.zip deleted file mode 100644 index 8fc1c6fec..000000000 Binary files a/.yarn/cache/@jridgewell-resolve-uri-npm-3.0.8-94779c6a1d-28d739f49b.zip and /dev/null differ diff --git a/.yarn/cache/@jridgewell-resolve-uri-npm-3.1.0-6ff2351e61-b5ceaaf9a1.zip b/.yarn/cache/@jridgewell-resolve-uri-npm-3.1.0-6ff2351e61-b5ceaaf9a1.zip new file mode 100644 index 000000000..97e857d7d Binary files /dev/null and b/.yarn/cache/@jridgewell-resolve-uri-npm-3.1.0-6ff2351e61-b5ceaaf9a1.zip differ diff --git a/.yarn/cache/@jridgewell-trace-mapping-npm-0.3.14-c78fcccfdf-b9537b9630.zip b/.yarn/cache/@jridgewell-trace-mapping-npm-0.3.14-c78fcccfdf-b9537b9630.zip deleted file mode 100644 index 95455c62e..000000000 Binary files a/.yarn/cache/@jridgewell-trace-mapping-npm-0.3.14-c78fcccfdf-b9537b9630.zip and /dev/null differ diff --git a/.yarn/cache/@jridgewell-trace-mapping-npm-0.3.15-7357dbf648-38917e9c2b.zip b/.yarn/cache/@jridgewell-trace-mapping-npm-0.3.15-7357dbf648-38917e9c2b.zip deleted file mode 100644 index 2ccfc7560..000000000 Binary files a/.yarn/cache/@jridgewell-trace-mapping-npm-0.3.15-7357dbf648-38917e9c2b.zip and /dev/null differ diff --git a/.yarn/cache/@jridgewell-trace-mapping-npm-0.3.16-f11a7d5a44-881fa21ce0.zip b/.yarn/cache/@jridgewell-trace-mapping-npm-0.3.16-f11a7d5a44-881fa21ce0.zip new file mode 100644 index 000000000..9bd116867 Binary files /dev/null and b/.yarn/cache/@jridgewell-trace-mapping-npm-0.3.16-f11a7d5a44-881fa21ce0.zip differ diff --git a/.yarn/cache/@lerna-lite-cli-npm-1.11.3-6f7f255ce9-3aec995208.zip b/.yarn/cache/@lerna-lite-cli-npm-1.11.3-6f7f255ce9-3aec995208.zip new file mode 100644 index 000000000..d081910b6 Binary files /dev/null and b/.yarn/cache/@lerna-lite-cli-npm-1.11.3-6f7f255ce9-3aec995208.zip differ diff --git a/.yarn/cache/@lerna-lite-cli-npm-1.6.0-fc69462685-92eb1e4fb4.zip b/.yarn/cache/@lerna-lite-cli-npm-1.6.0-fc69462685-92eb1e4fb4.zip deleted file mode 100644 index 57ca396c9..000000000 Binary files a/.yarn/cache/@lerna-lite-cli-npm-1.6.0-fc69462685-92eb1e4fb4.zip and /dev/null differ diff --git a/.yarn/cache/@lerna-lite-core-npm-1.11.3-ba9d892954-33ec8f1f8e.zip b/.yarn/cache/@lerna-lite-core-npm-1.11.3-ba9d892954-33ec8f1f8e.zip new file mode 100644 index 000000000..dd07ba594 Binary files /dev/null and b/.yarn/cache/@lerna-lite-core-npm-1.11.3-ba9d892954-33ec8f1f8e.zip differ diff --git a/.yarn/cache/@lerna-lite-core-npm-1.6.0-13410bd9c1-af3685cdaf.zip b/.yarn/cache/@lerna-lite-core-npm-1.6.0-13410bd9c1-af3685cdaf.zip deleted file mode 100644 index 7ace9319b..000000000 Binary files a/.yarn/cache/@lerna-lite-core-npm-1.6.0-13410bd9c1-af3685cdaf.zip and /dev/null differ diff --git a/.yarn/cache/@lerna-lite-info-npm-1.6.0-53b2bf6dd1-667e55621d.zip b/.yarn/cache/@lerna-lite-info-npm-1.11.3-7cc71aba81-2a96f5ec59.zip similarity index 74% rename from .yarn/cache/@lerna-lite-info-npm-1.6.0-53b2bf6dd1-667e55621d.zip rename to .yarn/cache/@lerna-lite-info-npm-1.11.3-7cc71aba81-2a96f5ec59.zip index 93de5f72a..9471144e0 100644 Binary files a/.yarn/cache/@lerna-lite-info-npm-1.6.0-53b2bf6dd1-667e55621d.zip and b/.yarn/cache/@lerna-lite-info-npm-1.11.3-7cc71aba81-2a96f5ec59.zip differ diff --git a/.yarn/cache/@lerna-lite-init-npm-1.11.3-ce005f57d5-cb263f198e.zip b/.yarn/cache/@lerna-lite-init-npm-1.11.3-ce005f57d5-cb263f198e.zip new file mode 100644 index 000000000..51e361601 Binary files /dev/null and b/.yarn/cache/@lerna-lite-init-npm-1.11.3-ce005f57d5-cb263f198e.zip differ diff --git a/.yarn/cache/@lerna-lite-init-npm-1.6.0-51ea51e753-3b713405d4.zip b/.yarn/cache/@lerna-lite-init-npm-1.6.0-51ea51e753-3b713405d4.zip deleted file mode 100644 index fac6dede2..000000000 Binary files a/.yarn/cache/@lerna-lite-init-npm-1.6.0-51ea51e753-3b713405d4.zip and /dev/null differ diff --git a/.yarn/cache/@lerna-lite-list-npm-1.11.3-5cd11427ac-f9d0b0fba6.zip b/.yarn/cache/@lerna-lite-list-npm-1.11.3-5cd11427ac-f9d0b0fba6.zip new file mode 100644 index 000000000..33f120741 Binary files /dev/null and b/.yarn/cache/@lerna-lite-list-npm-1.11.3-5cd11427ac-f9d0b0fba6.zip differ diff --git a/.yarn/cache/@lerna-lite-list-npm-1.6.0-63fd3896ac-f9ac8c6247.zip b/.yarn/cache/@lerna-lite-list-npm-1.6.0-63fd3896ac-f9ac8c6247.zip deleted file mode 100644 index 6b04418b9..000000000 Binary files a/.yarn/cache/@lerna-lite-list-npm-1.6.0-63fd3896ac-f9ac8c6247.zip and /dev/null differ diff --git a/.yarn/cache/@lerna-lite-listable-npm-1.6.0-9cd0de0c10-b5b3dadcb8.zip b/.yarn/cache/@lerna-lite-listable-npm-1.11.3-7313072e0d-a198d8c987.zip similarity index 84% rename from .yarn/cache/@lerna-lite-listable-npm-1.6.0-9cd0de0c10-b5b3dadcb8.zip rename to .yarn/cache/@lerna-lite-listable-npm-1.11.3-7313072e0d-a198d8c987.zip index d2e35617e..ee0c65077 100644 Binary files a/.yarn/cache/@lerna-lite-listable-npm-1.6.0-9cd0de0c10-b5b3dadcb8.zip and b/.yarn/cache/@lerna-lite-listable-npm-1.11.3-7313072e0d-a198d8c987.zip differ diff --git a/.yarn/cache/@lerna-lite-optional-cmd-common-npm-1.6.0-52bbe066ea-a86937081f.zip b/.yarn/cache/@lerna-lite-optional-cmd-common-npm-1.11.3-0552a5abe0-d283f07786.zip similarity index 72% rename from .yarn/cache/@lerna-lite-optional-cmd-common-npm-1.6.0-52bbe066ea-a86937081f.zip rename to .yarn/cache/@lerna-lite-optional-cmd-common-npm-1.11.3-0552a5abe0-d283f07786.zip index aca563718..b19a4ec25 100644 Binary files a/.yarn/cache/@lerna-lite-optional-cmd-common-npm-1.6.0-52bbe066ea-a86937081f.zip and b/.yarn/cache/@lerna-lite-optional-cmd-common-npm-1.11.3-0552a5abe0-d283f07786.zip differ diff --git a/.yarn/cache/@lerna-lite-publish-npm-1.11.3-ccd56739ca-9b0a6344dc.zip b/.yarn/cache/@lerna-lite-publish-npm-1.11.3-ccd56739ca-9b0a6344dc.zip new file mode 100644 index 000000000..e2b369b4c Binary files /dev/null and b/.yarn/cache/@lerna-lite-publish-npm-1.11.3-ccd56739ca-9b0a6344dc.zip differ diff --git a/.yarn/cache/@lerna-lite-publish-npm-1.6.0-ae8f957c4c-ac11999601.zip b/.yarn/cache/@lerna-lite-publish-npm-1.6.0-ae8f957c4c-ac11999601.zip deleted file mode 100644 index 1e8424a14..000000000 Binary files a/.yarn/cache/@lerna-lite-publish-npm-1.6.0-ae8f957c4c-ac11999601.zip and /dev/null differ diff --git a/.yarn/cache/@lerna-lite-run-npm-1.11.3-f669cf1898-17000c0b41.zip b/.yarn/cache/@lerna-lite-run-npm-1.11.3-f669cf1898-17000c0b41.zip new file mode 100644 index 000000000..c3991a9bc Binary files /dev/null and b/.yarn/cache/@lerna-lite-run-npm-1.11.3-f669cf1898-17000c0b41.zip differ diff --git a/.yarn/cache/@lerna-lite-run-npm-1.6.0-d85881ff48-dd9173801b.zip b/.yarn/cache/@lerna-lite-run-npm-1.6.0-d85881ff48-dd9173801b.zip deleted file mode 100644 index 2cf6d5fe7..000000000 Binary files a/.yarn/cache/@lerna-lite-run-npm-1.6.0-d85881ff48-dd9173801b.zip and /dev/null differ diff --git a/.yarn/cache/@lerna-lite-version-npm-1.11.3-5563d7d3cd-272e72d6e1.zip b/.yarn/cache/@lerna-lite-version-npm-1.11.3-5563d7d3cd-272e72d6e1.zip new file mode 100644 index 000000000..f2b6a9991 Binary files /dev/null and b/.yarn/cache/@lerna-lite-version-npm-1.11.3-5563d7d3cd-272e72d6e1.zip differ diff --git a/.yarn/cache/@lerna-lite-version-npm-1.6.0-c04d55cf79-7212389903.zip b/.yarn/cache/@lerna-lite-version-npm-1.6.0-c04d55cf79-7212389903.zip deleted file mode 100644 index abab2e989..000000000 Binary files a/.yarn/cache/@lerna-lite-version-npm-1.6.0-c04d55cf79-7212389903.zip and /dev/null differ diff --git a/.yarn/cache/@nicolo-ribaudo-eslint-scope-5-internals-npm-5.1.1-v1-87df86be4b-f2e3b2d6a6.zip b/.yarn/cache/@nicolo-ribaudo-eslint-scope-5-internals-npm-5.1.1-v1-87df86be4b-f2e3b2d6a6.zip new file mode 100644 index 000000000..93ca0c341 Binary files /dev/null and b/.yarn/cache/@nicolo-ribaudo-eslint-scope-5-internals-npm-5.1.1-v1-87df86be4b-f2e3b2d6a6.zip differ diff --git a/.yarn/cache/@npmcli-fs-npm-2.1.0-3b106d08bc-6ec6d678af.zip b/.yarn/cache/@npmcli-fs-npm-2.1.2-08d434e77b-405074965e.zip similarity index 56% rename from .yarn/cache/@npmcli-fs-npm-2.1.0-3b106d08bc-6ec6d678af.zip rename to .yarn/cache/@npmcli-fs-npm-2.1.2-08d434e77b-405074965e.zip index 46e2dec69..2d9040ce5 100644 Binary files a/.yarn/cache/@npmcli-fs-npm-2.1.0-3b106d08bc-6ec6d678af.zip and b/.yarn/cache/@npmcli-fs-npm-2.1.2-08d434e77b-405074965e.zip differ diff --git a/.yarn/cache/@npmcli-git-npm-3.0.1-0c54a062d9-0e289d11e2.zip b/.yarn/cache/@npmcli-git-npm-3.0.2-c52c981642-bdfd1229bb.zip similarity index 85% rename from .yarn/cache/@npmcli-git-npm-3.0.1-0c54a062d9-0e289d11e2.zip rename to .yarn/cache/@npmcli-git-npm-3.0.2-c52c981642-bdfd1229bb.zip index 444b1b667..085b7679c 100644 Binary files a/.yarn/cache/@npmcli-git-npm-3.0.1-0c54a062d9-0e289d11e2.zip and b/.yarn/cache/@npmcli-git-npm-3.0.2-c52c981642-bdfd1229bb.zip differ diff --git a/.yarn/cache/@npmcli-move-file-npm-2.0.0-d8bd1d35d2-1388777b50.zip b/.yarn/cache/@npmcli-move-file-npm-2.0.0-d8bd1d35d2-1388777b50.zip deleted file mode 100644 index e896df6c3..000000000 Binary files a/.yarn/cache/@npmcli-move-file-npm-2.0.0-d8bd1d35d2-1388777b50.zip and /dev/null differ diff --git a/.yarn/cache/@npmcli-move-file-npm-2.0.1-b593d8f741-52dc02259d.zip b/.yarn/cache/@npmcli-move-file-npm-2.0.1-b593d8f741-52dc02259d.zip new file mode 100644 index 000000000..f6a649e34 Binary files /dev/null and b/.yarn/cache/@npmcli-move-file-npm-2.0.1-b593d8f741-52dc02259d.zip differ diff --git a/.yarn/cache/@npmcli-run-script-npm-4.1.5-979d3624a1-a71736c628.zip b/.yarn/cache/@npmcli-run-script-npm-4.1.5-979d3624a1-a71736c628.zip deleted file mode 100644 index 05fb9f159..000000000 Binary files a/.yarn/cache/@npmcli-run-script-npm-4.1.5-979d3624a1-a71736c628.zip and /dev/null differ diff --git a/.yarn/cache/@npmcli-run-script-npm-4.2.1-6bd9c817c8-7b8d667635.zip b/.yarn/cache/@npmcli-run-script-npm-4.2.1-6bd9c817c8-7b8d667635.zip new file mode 100644 index 000000000..dc45b474b Binary files /dev/null and b/.yarn/cache/@npmcli-run-script-npm-4.2.1-6bd9c817c8-7b8d667635.zip differ diff --git a/.yarn/cache/@octokit-auth-token-npm-2.5.0-a1c6ffb640-45949296c0.zip b/.yarn/cache/@octokit-auth-token-npm-3.0.2-2c2a6dcca5-c7204770a6.zip similarity index 69% rename from .yarn/cache/@octokit-auth-token-npm-2.5.0-a1c6ffb640-45949296c0.zip rename to .yarn/cache/@octokit-auth-token-npm-3.0.2-2c2a6dcca5-c7204770a6.zip index b737fadf4..73603b1fd 100644 Binary files a/.yarn/cache/@octokit-auth-token-npm-2.5.0-a1c6ffb640-45949296c0.zip and b/.yarn/cache/@octokit-auth-token-npm-3.0.2-2c2a6dcca5-c7204770a6.zip differ diff --git a/.yarn/cache/@octokit-core-npm-3.6.0-1273c50268-f811601290.zip b/.yarn/cache/@octokit-core-npm-3.6.0-1273c50268-f811601290.zip deleted file mode 100644 index 899e2b16a..000000000 Binary files a/.yarn/cache/@octokit-core-npm-3.6.0-1273c50268-f811601290.zip and /dev/null differ diff --git a/.yarn/cache/@octokit-core-npm-4.1.0-53c1d3e6df-4e53e02ff3.zip b/.yarn/cache/@octokit-core-npm-4.1.0-53c1d3e6df-4e53e02ff3.zip new file mode 100644 index 000000000..74a79db3e Binary files /dev/null and b/.yarn/cache/@octokit-core-npm-4.1.0-53c1d3e6df-4e53e02ff3.zip differ diff --git a/.yarn/cache/@octokit-endpoint-npm-6.0.12-d467db27fd-b48b29940a.zip b/.yarn/cache/@octokit-endpoint-npm-6.0.12-d467db27fd-b48b29940a.zip deleted file mode 100644 index b844a8513..000000000 Binary files a/.yarn/cache/@octokit-endpoint-npm-6.0.12-d467db27fd-b48b29940a.zip and /dev/null differ diff --git a/.yarn/cache/@octokit-endpoint-npm-7.0.3-cabcb716ae-c36b157706.zip b/.yarn/cache/@octokit-endpoint-npm-7.0.3-cabcb716ae-c36b157706.zip new file mode 100644 index 000000000..d40900e93 Binary files /dev/null and b/.yarn/cache/@octokit-endpoint-npm-7.0.3-cabcb716ae-c36b157706.zip differ diff --git a/.yarn/cache/@octokit-graphql-npm-4.8.0-83d118b4da-f68afe53f6.zip b/.yarn/cache/@octokit-graphql-npm-4.8.0-83d118b4da-f68afe53f6.zip deleted file mode 100644 index 1b16a6066..000000000 Binary files a/.yarn/cache/@octokit-graphql-npm-4.8.0-83d118b4da-f68afe53f6.zip and /dev/null differ diff --git a/.yarn/cache/@octokit-graphql-npm-5.0.2-1d3e2468fa-cc746573f5.zip b/.yarn/cache/@octokit-graphql-npm-5.0.2-1d3e2468fa-cc746573f5.zip new file mode 100644 index 000000000..9ad3346c4 Binary files /dev/null and b/.yarn/cache/@octokit-graphql-npm-5.0.2-1d3e2468fa-cc746573f5.zip differ diff --git a/.yarn/cache/@octokit-openapi-types-npm-12.8.0-1b7f917c93-66058ebb9a.zip b/.yarn/cache/@octokit-openapi-types-npm-12.8.0-1b7f917c93-66058ebb9a.zip deleted file mode 100644 index 7559160f0..000000000 Binary files a/.yarn/cache/@octokit-openapi-types-npm-12.8.0-1b7f917c93-66058ebb9a.zip and /dev/null differ diff --git a/.yarn/cache/@octokit-openapi-types-npm-13.13.1-6b9bdd4c9f-7f49a46ada.zip b/.yarn/cache/@octokit-openapi-types-npm-13.13.1-6b9bdd4c9f-7f49a46ada.zip new file mode 100644 index 000000000..a62e8d68c Binary files /dev/null and b/.yarn/cache/@octokit-openapi-types-npm-13.13.1-6b9bdd4c9f-7f49a46ada.zip differ diff --git a/.yarn/cache/@octokit-openapi-types-npm-14.0.0-5d05da4dc7-0a1f8f3be9.zip b/.yarn/cache/@octokit-openapi-types-npm-14.0.0-5d05da4dc7-0a1f8f3be9.zip new file mode 100644 index 000000000..a1c206e7d Binary files /dev/null and b/.yarn/cache/@octokit-openapi-types-npm-14.0.0-5d05da4dc7-0a1f8f3be9.zip differ diff --git a/.yarn/cache/@octokit-plugin-paginate-rest-npm-2.21.1-7eac9e6538-2941d0320e.zip b/.yarn/cache/@octokit-plugin-paginate-rest-npm-2.21.1-7eac9e6538-2941d0320e.zip deleted file mode 100644 index 7c7784ac6..000000000 Binary files a/.yarn/cache/@octokit-plugin-paginate-rest-npm-2.21.1-7eac9e6538-2941d0320e.zip and /dev/null differ diff --git a/.yarn/cache/@octokit-plugin-paginate-rest-npm-4.3.1-8b00be66a1-96d420fc99.zip b/.yarn/cache/@octokit-plugin-paginate-rest-npm-4.3.1-8b00be66a1-96d420fc99.zip new file mode 100644 index 000000000..10cc7eb6d Binary files /dev/null and b/.yarn/cache/@octokit-plugin-paginate-rest-npm-4.3.1-8b00be66a1-96d420fc99.zip differ diff --git a/.yarn/cache/@octokit-plugin-rest-endpoint-methods-npm-5.16.2-f54316c392-30fcc50c33.zip b/.yarn/cache/@octokit-plugin-rest-endpoint-methods-npm-5.16.2-f54316c392-30fcc50c33.zip deleted file mode 100644 index 1cfa3e631..000000000 Binary files a/.yarn/cache/@octokit-plugin-rest-endpoint-methods-npm-5.16.2-f54316c392-30fcc50c33.zip and /dev/null differ diff --git a/.yarn/cache/@octokit-plugin-rest-endpoint-methods-npm-6.7.0-8434cbe757-513c6c0717.zip b/.yarn/cache/@octokit-plugin-rest-endpoint-methods-npm-6.7.0-8434cbe757-513c6c0717.zip new file mode 100644 index 000000000..11d081ea4 Binary files /dev/null and b/.yarn/cache/@octokit-plugin-rest-endpoint-methods-npm-6.7.0-8434cbe757-513c6c0717.zip differ diff --git a/.yarn/cache/@octokit-request-error-npm-2.1.0-51ac624306-baec2b5700.zip b/.yarn/cache/@octokit-request-error-npm-3.0.2-ad6a6ba74d-41549554ce.zip similarity index 61% rename from .yarn/cache/@octokit-request-error-npm-2.1.0-51ac624306-baec2b5700.zip rename to .yarn/cache/@octokit-request-error-npm-3.0.2-ad6a6ba74d-41549554ce.zip index fadd972f2..5f2895b30 100644 Binary files a/.yarn/cache/@octokit-request-error-npm-2.1.0-51ac624306-baec2b5700.zip and b/.yarn/cache/@octokit-request-error-npm-3.0.2-ad6a6ba74d-41549554ce.zip differ diff --git a/.yarn/cache/@octokit-request-npm-5.6.3-25a5f5382d-c0b4542eb4.zip b/.yarn/cache/@octokit-request-npm-5.6.3-25a5f5382d-c0b4542eb4.zip deleted file mode 100644 index 19a09612e..000000000 Binary files a/.yarn/cache/@octokit-request-npm-5.6.3-25a5f5382d-c0b4542eb4.zip and /dev/null differ diff --git a/.yarn/cache/@octokit-request-npm-6.2.2-b443394ecf-adbeb38807.zip b/.yarn/cache/@octokit-request-npm-6.2.2-b443394ecf-adbeb38807.zip new file mode 100644 index 000000000..7108a7d64 Binary files /dev/null and b/.yarn/cache/@octokit-request-npm-6.2.2-b443394ecf-adbeb38807.zip differ diff --git a/.yarn/cache/@octokit-rest-npm-18.12.0-f250ac8e5e-c18bd6676a.zip b/.yarn/cache/@octokit-rest-npm-18.12.0-f250ac8e5e-c18bd6676a.zip deleted file mode 100644 index 3819d9611..000000000 Binary files a/.yarn/cache/@octokit-rest-npm-18.12.0-f250ac8e5e-c18bd6676a.zip and /dev/null differ diff --git a/.yarn/cache/@octokit-rest-npm-19.0.4-b6d4756d25-7eba9148b7.zip b/.yarn/cache/@octokit-rest-npm-19.0.4-b6d4756d25-7eba9148b7.zip new file mode 100644 index 000000000..ff0658124 Binary files /dev/null and b/.yarn/cache/@octokit-rest-npm-19.0.4-b6d4756d25-7eba9148b7.zip differ diff --git a/.yarn/cache/@octokit-types-npm-6.39.0-8985f0f61f-0e3d55e4bd.zip b/.yarn/cache/@octokit-types-npm-6.39.0-8985f0f61f-0e3d55e4bd.zip deleted file mode 100644 index fb61d400c..000000000 Binary files a/.yarn/cache/@octokit-types-npm-6.39.0-8985f0f61f-0e3d55e4bd.zip and /dev/null differ diff --git a/.yarn/cache/@octokit-types-npm-7.5.1-1a7540339f-eaa9aac2f4.zip b/.yarn/cache/@octokit-types-npm-7.5.1-1a7540339f-eaa9aac2f4.zip new file mode 100644 index 000000000..d637057c9 Binary files /dev/null and b/.yarn/cache/@octokit-types-npm-7.5.1-1a7540339f-eaa9aac2f4.zip differ diff --git a/.yarn/cache/@octokit-types-npm-8.0.0-8cee8f31e4-1a0197b2c4.zip b/.yarn/cache/@octokit-types-npm-8.0.0-8cee8f31e4-1a0197b2c4.zip new file mode 100644 index 000000000..509f15644 Binary files /dev/null and b/.yarn/cache/@octokit-types-npm-8.0.0-8cee8f31e4-1a0197b2c4.zip differ diff --git a/.yarn/cache/@pmmmwh-react-refresh-webpack-plugin-npm-0.5.7-672cb2972a-3490649181.zip b/.yarn/cache/@pmmmwh-react-refresh-webpack-plugin-npm-0.5.8-8c5cf6807f-48d8b2813d.zip similarity index 57% rename from .yarn/cache/@pmmmwh-react-refresh-webpack-plugin-npm-0.5.7-672cb2972a-3490649181.zip rename to .yarn/cache/@pmmmwh-react-refresh-webpack-plugin-npm-0.5.8-8c5cf6807f-48d8b2813d.zip index 2b871aac6..f4d9ddb70 100644 Binary files a/.yarn/cache/@pmmmwh-react-refresh-webpack-plugin-npm-0.5.7-672cb2972a-3490649181.zip and b/.yarn/cache/@pmmmwh-react-refresh-webpack-plugin-npm-0.5.8-8c5cf6807f-48d8b2813d.zip differ diff --git a/.yarn/cache/@pnpm-npm-conf-npm-1.0.4-cc4c19088e-f94afa48ce.zip b/.yarn/cache/@pnpm-npm-conf-npm-1.0.5-77075df24d-0c5f1a6378.zip similarity index 71% rename from .yarn/cache/@pnpm-npm-conf-npm-1.0.4-cc4c19088e-f94afa48ce.zip rename to .yarn/cache/@pnpm-npm-conf-npm-1.0.5-77075df24d-0c5f1a6378.zip index cb20c1637..fc53a23a7 100644 Binary files a/.yarn/cache/@pnpm-npm-conf-npm-1.0.4-cc4c19088e-f94afa48ce.zip and b/.yarn/cache/@pnpm-npm-conf-npm-1.0.5-77075df24d-0c5f1a6378.zip differ diff --git a/.yarn/cache/@reach-dropdown-npm-0.17.0-7eab50979d-296bc88868.zip b/.yarn/cache/@reach-dropdown-npm-0.17.0-7eab50979d-296bc88868.zip deleted file mode 100644 index 9aa989137..000000000 Binary files a/.yarn/cache/@reach-dropdown-npm-0.17.0-7eab50979d-296bc88868.zip and /dev/null differ diff --git a/.yarn/cache/@reach-menu-button-npm-0.17.0-36c70fdc48-6b539c858d.zip b/.yarn/cache/@reach-menu-button-npm-0.17.0-36c70fdc48-6b539c858d.zip deleted file mode 100644 index 720f4f85e..000000000 Binary files a/.yarn/cache/@reach-menu-button-npm-0.17.0-36c70fdc48-6b539c858d.zip and /dev/null differ diff --git a/.yarn/cache/@react-native-community-cli-hermes-npm-6.3.0-0046ff86a6-47e126be04.zip b/.yarn/cache/@react-native-community-cli-hermes-npm-6.3.1-d4e1415d02-7e82764c85.zip similarity index 95% rename from .yarn/cache/@react-native-community-cli-hermes-npm-6.3.0-0046ff86a6-47e126be04.zip rename to .yarn/cache/@react-native-community-cli-hermes-npm-6.3.1-d4e1415d02-7e82764c85.zip index dd5aae2a9..5bd78c7ae 100644 Binary files a/.yarn/cache/@react-native-community-cli-hermes-npm-6.3.0-0046ff86a6-47e126be04.zip and b/.yarn/cache/@react-native-community-cli-hermes-npm-6.3.1-d4e1415d02-7e82764c85.zip differ diff --git a/.yarn/cache/@react-native-community-cli-platform-android-npm-6.3.0-1b9d17ef3a-997d416db1.zip b/.yarn/cache/@react-native-community-cli-platform-android-npm-6.3.1-ea00774117-cb4d649213.zip similarity index 88% rename from .yarn/cache/@react-native-community-cli-platform-android-npm-6.3.0-1b9d17ef3a-997d416db1.zip rename to .yarn/cache/@react-native-community-cli-platform-android-npm-6.3.1-ea00774117-cb4d649213.zip index 88a9dae50..ea8a26953 100644 Binary files a/.yarn/cache/@react-native-community-cli-platform-android-npm-6.3.0-1b9d17ef3a-997d416db1.zip and b/.yarn/cache/@react-native-community-cli-platform-android-npm-6.3.1-ea00774117-cb4d649213.zip differ diff --git a/.yarn/cache/@react-native-community-cli-platform-ios-npm-6.2.0-a8fc878835-827ce62aa9.zip b/.yarn/cache/@react-native-community-cli-platform-ios-npm-6.2.1-24c88dc83c-40c5a33183.zip similarity index 99% rename from .yarn/cache/@react-native-community-cli-platform-ios-npm-6.2.0-a8fc878835-827ce62aa9.zip rename to .yarn/cache/@react-native-community-cli-platform-ios-npm-6.2.1-24c88dc83c-40c5a33183.zip index 79345b6da..6749ca72f 100644 Binary files a/.yarn/cache/@react-native-community-cli-platform-ios-npm-6.2.0-a8fc878835-827ce62aa9.zip and b/.yarn/cache/@react-native-community-cli-platform-ios-npm-6.2.1-24c88dc83c-40c5a33183.zip differ diff --git a/.yarn/cache/@react-native-community-cli-tools-npm-6.2.0-9f80fc403c-17bb1e2e22.zip b/.yarn/cache/@react-native-community-cli-tools-npm-6.2.1-6e5ab60320-dcc5084c0c.zip similarity index 92% rename from .yarn/cache/@react-native-community-cli-tools-npm-6.2.0-9f80fc403c-17bb1e2e22.zip rename to .yarn/cache/@react-native-community-cli-tools-npm-6.2.1-6e5ab60320-dcc5084c0c.zip index b9ae0e1ce..18f1e767d 100644 Binary files a/.yarn/cache/@react-native-community-cli-tools-npm-6.2.0-9f80fc403c-17bb1e2e22.zip and b/.yarn/cache/@react-native-community-cli-tools-npm-6.2.1-6e5ab60320-dcc5084c0c.zip differ diff --git a/.yarn/cache/@react-native-community-eslint-config-npm-3.0.3-3fee0ccd13-5d2f48a936.zip b/.yarn/cache/@react-native-community-eslint-config-npm-3.0.3-3fee0ccd13-5d2f48a936.zip deleted file mode 100644 index b3b66a441..000000000 Binary files a/.yarn/cache/@react-native-community-eslint-config-npm-3.0.3-3fee0ccd13-5d2f48a936.zip and /dev/null differ diff --git a/.yarn/cache/@react-native-community-eslint-config-npm-3.1.0-742829e4e5-789b4f2009.zip b/.yarn/cache/@react-native-community-eslint-config-npm-3.1.0-742829e4e5-789b4f2009.zip new file mode 100644 index 000000000..49278fef9 Binary files /dev/null and b/.yarn/cache/@react-native-community-eslint-config-npm-3.1.0-742829e4e5-789b4f2009.zip differ diff --git a/.yarn/cache/@react-native-community-masked-view-npm-0.1.11-8993feea47-246bcd94a6.zip b/.yarn/cache/@react-native-community-masked-view-npm-0.1.11-8993feea47-246bcd94a6.zip deleted file mode 100644 index a609fa0d4..000000000 Binary files a/.yarn/cache/@react-native-community-masked-view-npm-0.1.11-8993feea47-246bcd94a6.zip and /dev/null differ diff --git a/.yarn/cache/@react-native-community-segmented-control-npm-2.2.2-46e6e1cef6-2b691a8a1c.zip b/.yarn/cache/@react-native-community-segmented-control-npm-2.2.2-46e6e1cef6-2b691a8a1c.zip deleted file mode 100644 index a4e070143..000000000 Binary files a/.yarn/cache/@react-native-community-segmented-control-npm-2.2.2-46e6e1cef6-2b691a8a1c.zip and /dev/null differ diff --git a/.yarn/cache/@react-navigation-core-npm-6.2.2-730adad334-ecc56be910.zip b/.yarn/cache/@react-navigation-core-npm-6.2.2-730adad334-ecc56be910.zip deleted file mode 100644 index e6796353e..000000000 Binary files a/.yarn/cache/@react-navigation-core-npm-6.2.2-730adad334-ecc56be910.zip and /dev/null differ diff --git a/.yarn/cache/@react-navigation-elements-npm-1.3.4-d81d0d8a9a-5dafd13770.zip b/.yarn/cache/@react-navigation-elements-npm-1.3.4-d81d0d8a9a-5dafd13770.zip deleted file mode 100644 index 03fb9c5b0..000000000 Binary files a/.yarn/cache/@react-navigation-elements-npm-1.3.4-d81d0d8a9a-5dafd13770.zip and /dev/null differ diff --git a/.yarn/cache/@react-navigation-native-npm-6.0.11-f88da23f65-0dab07c814.zip b/.yarn/cache/@react-navigation-native-npm-6.0.11-f88da23f65-0dab07c814.zip deleted file mode 100644 index 1f8d819e7..000000000 Binary files a/.yarn/cache/@react-navigation-native-npm-6.0.11-f88da23f65-0dab07c814.zip and /dev/null differ diff --git a/.yarn/cache/@react-navigation-routers-npm-6.1.1-c0c1461b0a-6889b4eca3.zip b/.yarn/cache/@react-navigation-routers-npm-6.1.1-c0c1461b0a-6889b4eca3.zip deleted file mode 100644 index 19c9278f1..000000000 Binary files a/.yarn/cache/@react-navigation-routers-npm-6.1.1-c0c1461b0a-6889b4eca3.zip and /dev/null differ diff --git a/.yarn/cache/@react-navigation-stack-npm-6.2.2-ec46281444-27cb45e149.zip b/.yarn/cache/@react-navigation-stack-npm-6.2.2-ec46281444-27cb45e149.zip deleted file mode 100644 index e82aaab48..000000000 Binary files a/.yarn/cache/@react-navigation-stack-npm-6.2.2-ec46281444-27cb45e149.zip and /dev/null differ diff --git a/.yarn/cache/@rushstack-eslint-patch-npm-1.1.4-3fdde25f35-597bc84e2f.zip b/.yarn/cache/@rushstack-eslint-patch-npm-1.1.4-3fdde25f35-597bc84e2f.zip deleted file mode 100644 index cde544e1f..000000000 Binary files a/.yarn/cache/@rushstack-eslint-patch-npm-1.1.4-3fdde25f35-597bc84e2f.zip and /dev/null differ diff --git a/.yarn/cache/@rushstack-eslint-patch-npm-1.2.0-917f402e4e-faa749faae.zip b/.yarn/cache/@rushstack-eslint-patch-npm-1.2.0-917f402e4e-faa749faae.zip new file mode 100644 index 000000000..698ee6ae9 Binary files /dev/null and b/.yarn/cache/@rushstack-eslint-patch-npm-1.2.0-917f402e4e-faa749faae.zip differ diff --git a/.yarn/cache/@sinclair-typebox-npm-0.23.5-10c003c068-c96056d35d.zip b/.yarn/cache/@sinclair-typebox-npm-0.23.5-10c003c068-c96056d35d.zip deleted file mode 100644 index d97e81114..000000000 Binary files a/.yarn/cache/@sinclair-typebox-npm-0.23.5-10c003c068-c96056d35d.zip and /dev/null differ diff --git a/.yarn/cache/@sinclair-typebox-npm-0.24.41-207a93bfda-eb9861ad7b.zip b/.yarn/cache/@sinclair-typebox-npm-0.24.46-d630eef884-19d708fe93.zip similarity index 63% rename from .yarn/cache/@sinclair-typebox-npm-0.24.41-207a93bfda-eb9861ad7b.zip rename to .yarn/cache/@sinclair-typebox-npm-0.24.46-d630eef884-19d708fe93.zip index 207553b94..12c305158 100644 Binary files a/.yarn/cache/@sinclair-typebox-npm-0.24.41-207a93bfda-eb9861ad7b.zip and b/.yarn/cache/@sinclair-typebox-npm-0.24.46-d630eef884-19d708fe93.zip differ diff --git a/.yarn/cache/@sindresorhus-is-npm-4.6.0-7cad05c55e-83839f13da.zip b/.yarn/cache/@sindresorhus-is-npm-4.6.0-7cad05c55e-83839f13da.zip deleted file mode 100644 index 93d03d70e..000000000 Binary files a/.yarn/cache/@sindresorhus-is-npm-4.6.0-7cad05c55e-83839f13da.zip and /dev/null differ diff --git a/.yarn/cache/@sindresorhus-is-npm-5.3.0-9deec66459-b31cebabcd.zip b/.yarn/cache/@sindresorhus-is-npm-5.3.0-9deec66459-b31cebabcd.zip new file mode 100644 index 000000000..2feb3ad39 Binary files /dev/null and b/.yarn/cache/@sindresorhus-is-npm-5.3.0-9deec66459-b31cebabcd.zip differ diff --git a/.yarn/cache/@standardnotes-common-npm-1.23.1-ed73dbb679-f498f4c469.zip b/.yarn/cache/@standardnotes-common-npm-1.23.1-ed73dbb679-f498f4c469.zip deleted file mode 100644 index 507ef2442..000000000 Binary files a/.yarn/cache/@standardnotes-common-npm-1.23.1-ed73dbb679-f498f4c469.zip and /dev/null differ diff --git a/.yarn/cache/@standardnotes-common-npm-1.25.0-91e524a124-aec9d4bcda.zip b/.yarn/cache/@standardnotes-common-npm-1.25.0-91e524a124-aec9d4bcda.zip deleted file mode 100644 index 93714b588..000000000 Binary files a/.yarn/cache/@standardnotes-common-npm-1.25.0-91e524a124-aec9d4bcda.zip and /dev/null differ diff --git a/.yarn/cache/@standardnotes-common-npm-1.39.0-1e36e2ef74-92cfad04a6.zip b/.yarn/cache/@standardnotes-common-npm-1.40.0-9e842ca443-d7573e0f58.zip similarity index 80% rename from .yarn/cache/@standardnotes-common-npm-1.39.0-1e36e2ef74-92cfad04a6.zip rename to .yarn/cache/@standardnotes-common-npm-1.40.0-9e842ca443-d7573e0f58.zip index 85ed6ebe6..12e93c0c6 100644 Binary files a/.yarn/cache/@standardnotes-common-npm-1.39.0-1e36e2ef74-92cfad04a6.zip and b/.yarn/cache/@standardnotes-common-npm-1.40.0-9e842ca443-d7573e0f58.zip differ diff --git a/.yarn/cache/@standardnotes-domain-events-npm-2.39.0-ee14411bb8-7a37b281ef.zip b/.yarn/cache/@standardnotes-domain-events-npm-2.68.0-64c9e6944c-fc98c27b71.zip similarity index 50% rename from .yarn/cache/@standardnotes-domain-events-npm-2.39.0-ee14411bb8-7a37b281ef.zip rename to .yarn/cache/@standardnotes-domain-events-npm-2.68.0-64c9e6944c-fc98c27b71.zip index 639485d5a..c5e582654 100644 Binary files a/.yarn/cache/@standardnotes-domain-events-npm-2.39.0-ee14411bb8-7a37b281ef.zip and b/.yarn/cache/@standardnotes-domain-events-npm-2.68.0-64c9e6944c-fc98c27b71.zip differ diff --git a/.yarn/cache/@standardnotes-predicates-npm-1.2.0-8a42210bdb-779a3fcf93.zip b/.yarn/cache/@standardnotes-predicates-npm-1.4.11-2e2008c6ef-5ad80bb49c.zip similarity index 86% rename from .yarn/cache/@standardnotes-predicates-npm-1.2.0-8a42210bdb-779a3fcf93.zip rename to .yarn/cache/@standardnotes-predicates-npm-1.4.11-2e2008c6ef-5ad80bb49c.zip index f0f25728a..b9a7b9e45 100644 Binary files a/.yarn/cache/@standardnotes-predicates-npm-1.2.0-8a42210bdb-779a3fcf93.zip and b/.yarn/cache/@standardnotes-predicates-npm-1.4.11-2e2008c6ef-5ad80bb49c.zip differ diff --git a/.yarn/cache/@standardnotes-react-native-aes-npm-1.4.3-e269100fad-9f53648cd2.zip b/.yarn/cache/@standardnotes-react-native-aes-npm-1.4.3-e269100fad-9f53648cd2.zip deleted file mode 100644 index 07ccb33b2..000000000 Binary files a/.yarn/cache/@standardnotes-react-native-aes-npm-1.4.3-e269100fad-9f53648cd2.zip and /dev/null differ diff --git a/.yarn/cache/@standardnotes-react-native-textview-npm-1.1.0-9c4a76b5bc-150992e82b.zip b/.yarn/cache/@standardnotes-react-native-textview-npm-1.1.0-9c4a76b5bc-150992e82b.zip deleted file mode 100644 index c007afdf8..000000000 Binary files a/.yarn/cache/@standardnotes-react-native-textview-npm-1.1.0-9c4a76b5bc-150992e82b.zip and /dev/null differ diff --git a/.yarn/cache/@standardnotes-security-npm-1.1.0-9d90b8c189-2098584cd3.zip b/.yarn/cache/@standardnotes-security-npm-1.1.0-9d90b8c189-2098584cd3.zip deleted file mode 100644 index 535e70507..000000000 Binary files a/.yarn/cache/@standardnotes-security-npm-1.1.0-9d90b8c189-2098584cd3.zip and /dev/null differ diff --git a/.yarn/cache/@standardnotes-security-npm-1.2.0-850a3f8a6e-3fb92e2be0.zip b/.yarn/cache/@standardnotes-security-npm-1.4.9-bb8235b71d-66e8222644.zip similarity index 77% rename from .yarn/cache/@standardnotes-security-npm-1.2.0-850a3f8a6e-3fb92e2be0.zip rename to .yarn/cache/@standardnotes-security-npm-1.4.9-bb8235b71d-66e8222644.zip index f5cda2ea7..f92850388 100644 Binary files a/.yarn/cache/@standardnotes-security-npm-1.2.0-850a3f8a6e-3fb92e2be0.zip and b/.yarn/cache/@standardnotes-security-npm-1.4.9-bb8235b71d-66e8222644.zip differ diff --git a/.yarn/cache/@standardnotes-settings-npm-1.17.0-fc942a7080-b376015038.zip b/.yarn/cache/@standardnotes-settings-npm-1.17.1-00b721c356-87949b6924.zip similarity index 97% rename from .yarn/cache/@standardnotes-settings-npm-1.17.0-fc942a7080-b376015038.zip rename to .yarn/cache/@standardnotes-settings-npm-1.17.1-00b721c356-87949b6924.zip index b077bb986..ae14acf7e 100644 Binary files a/.yarn/cache/@standardnotes-settings-npm-1.17.0-fc942a7080-b376015038.zip and b/.yarn/cache/@standardnotes-settings-npm-1.17.1-00b721c356-87949b6924.zip differ diff --git a/.yarn/cache/@standardnotes-stylekit-npm-5.29.3-721055c940-64d5e62a72.zip b/.yarn/cache/@standardnotes-stylekit-npm-5.29.3-721055c940-64d5e62a72.zip deleted file mode 100644 index c06e1600d..000000000 Binary files a/.yarn/cache/@standardnotes-stylekit-npm-5.29.3-721055c940-64d5e62a72.zip and /dev/null differ diff --git a/.yarn/cache/@svgr-babel-plugin-add-jsx-attribute-npm-6.0.0-617b96ba2c-8200dfa2ee.zip b/.yarn/cache/@svgr-babel-plugin-add-jsx-attribute-npm-6.0.0-617b96ba2c-8200dfa2ee.zip deleted file mode 100644 index 5bf87b930..000000000 Binary files a/.yarn/cache/@svgr-babel-plugin-add-jsx-attribute-npm-6.0.0-617b96ba2c-8200dfa2ee.zip and /dev/null differ diff --git a/.yarn/cache/@svgr-babel-plugin-add-jsx-attribute-npm-6.3.1-675a944ec5-3a04515743.zip b/.yarn/cache/@svgr-babel-plugin-add-jsx-attribute-npm-6.3.1-675a944ec5-3a04515743.zip new file mode 100644 index 000000000..9f2baa2a6 Binary files /dev/null and b/.yarn/cache/@svgr-babel-plugin-add-jsx-attribute-npm-6.3.1-675a944ec5-3a04515743.zip differ diff --git a/.yarn/cache/@svgr-babel-plugin-remove-jsx-attribute-npm-6.0.0-e1230281fd-82c988ed40.zip b/.yarn/cache/@svgr-babel-plugin-remove-jsx-attribute-npm-6.3.1-acb9ac82e5-ea78848a1d.zip similarity index 58% rename from .yarn/cache/@svgr-babel-plugin-remove-jsx-attribute-npm-6.0.0-e1230281fd-82c988ed40.zip rename to .yarn/cache/@svgr-babel-plugin-remove-jsx-attribute-npm-6.3.1-acb9ac82e5-ea78848a1d.zip index d1b2f44eb..e49b93807 100644 Binary files a/.yarn/cache/@svgr-babel-plugin-remove-jsx-attribute-npm-6.0.0-e1230281fd-82c988ed40.zip and b/.yarn/cache/@svgr-babel-plugin-remove-jsx-attribute-npm-6.3.1-acb9ac82e5-ea78848a1d.zip differ diff --git a/.yarn/cache/@svgr-babel-plugin-remove-jsx-empty-expression-npm-6.0.0-76d9a5c9a4-c80e3ff408.zip b/.yarn/cache/@svgr-babel-plugin-remove-jsx-empty-expression-npm-6.3.1-e176f55a8f-3975ee4ca6.zip similarity index 58% rename from .yarn/cache/@svgr-babel-plugin-remove-jsx-empty-expression-npm-6.0.0-76d9a5c9a4-c80e3ff408.zip rename to .yarn/cache/@svgr-babel-plugin-remove-jsx-empty-expression-npm-6.3.1-e176f55a8f-3975ee4ca6.zip index 69aef0139..6e870138a 100644 Binary files a/.yarn/cache/@svgr-babel-plugin-remove-jsx-empty-expression-npm-6.0.0-76d9a5c9a4-c80e3ff408.zip and b/.yarn/cache/@svgr-babel-plugin-remove-jsx-empty-expression-npm-6.3.1-e176f55a8f-3975ee4ca6.zip differ diff --git a/.yarn/cache/@svgr-babel-plugin-replace-jsx-attribute-value-npm-6.0.0-f9ef2450b6-d6b5e5a983.zip b/.yarn/cache/@svgr-babel-plugin-replace-jsx-attribute-value-npm-6.3.1-4c723d69af-8a65eb8aa9.zip similarity index 54% rename from .yarn/cache/@svgr-babel-plugin-replace-jsx-attribute-value-npm-6.0.0-f9ef2450b6-d6b5e5a983.zip rename to .yarn/cache/@svgr-babel-plugin-replace-jsx-attribute-value-npm-6.3.1-4c723d69af-8a65eb8aa9.zip index 1d7e993f1..45605cf7c 100644 Binary files a/.yarn/cache/@svgr-babel-plugin-replace-jsx-attribute-value-npm-6.0.0-f9ef2450b6-d6b5e5a983.zip and b/.yarn/cache/@svgr-babel-plugin-replace-jsx-attribute-value-npm-6.3.1-4c723d69af-8a65eb8aa9.zip differ diff --git a/.yarn/cache/@svgr-babel-plugin-svg-dynamic-title-npm-6.0.0-614c26c788-b62e0eb16d.zip b/.yarn/cache/@svgr-babel-plugin-svg-dynamic-title-npm-6.0.0-614c26c788-b62e0eb16d.zip deleted file mode 100644 index 9378afbfe..000000000 Binary files a/.yarn/cache/@svgr-babel-plugin-svg-dynamic-title-npm-6.0.0-614c26c788-b62e0eb16d.zip and /dev/null differ diff --git a/.yarn/cache/@svgr-babel-plugin-svg-dynamic-title-npm-6.3.1-b176794950-026f440d2e.zip b/.yarn/cache/@svgr-babel-plugin-svg-dynamic-title-npm-6.3.1-b176794950-026f440d2e.zip new file mode 100644 index 000000000..197d1ca10 Binary files /dev/null and b/.yarn/cache/@svgr-babel-plugin-svg-dynamic-title-npm-6.3.1-b176794950-026f440d2e.zip differ diff --git a/.yarn/cache/@svgr-babel-plugin-svg-em-dimensions-npm-6.0.0-88b66ce05a-873c6ef439.zip b/.yarn/cache/@svgr-babel-plugin-svg-em-dimensions-npm-6.3.1-94d4f03593-02aa7fa0af.zip similarity index 51% rename from .yarn/cache/@svgr-babel-plugin-svg-em-dimensions-npm-6.0.0-88b66ce05a-873c6ef439.zip rename to .yarn/cache/@svgr-babel-plugin-svg-em-dimensions-npm-6.3.1-94d4f03593-02aa7fa0af.zip index 74648f0f5..2ab9793a4 100644 Binary files a/.yarn/cache/@svgr-babel-plugin-svg-em-dimensions-npm-6.0.0-88b66ce05a-873c6ef439.zip and b/.yarn/cache/@svgr-babel-plugin-svg-em-dimensions-npm-6.3.1-94d4f03593-02aa7fa0af.zip differ diff --git a/.yarn/cache/@svgr-babel-plugin-transform-react-native-svg-npm-6.0.0-ffde6946ad-29df306ce0.zip b/.yarn/cache/@svgr-babel-plugin-transform-react-native-svg-npm-6.0.0-ffde6946ad-29df306ce0.zip deleted file mode 100644 index 4cb167a2f..000000000 Binary files a/.yarn/cache/@svgr-babel-plugin-transform-react-native-svg-npm-6.0.0-ffde6946ad-29df306ce0.zip and /dev/null differ diff --git a/.yarn/cache/@svgr-babel-plugin-transform-react-native-svg-npm-6.3.1-026303b9dc-2cbe20f701.zip b/.yarn/cache/@svgr-babel-plugin-transform-react-native-svg-npm-6.3.1-026303b9dc-2cbe20f701.zip new file mode 100644 index 000000000..07b1836fd Binary files /dev/null and b/.yarn/cache/@svgr-babel-plugin-transform-react-native-svg-npm-6.3.1-026303b9dc-2cbe20f701.zip differ diff --git a/.yarn/cache/@svgr-babel-plugin-transform-svg-component-npm-6.2.0-9ab91655c2-2d4c4ff27c.zip b/.yarn/cache/@svgr-babel-plugin-transform-svg-component-npm-6.2.0-9ab91655c2-2d4c4ff27c.zip deleted file mode 100644 index 22e4944c9..000000000 Binary files a/.yarn/cache/@svgr-babel-plugin-transform-svg-component-npm-6.2.0-9ab91655c2-2d4c4ff27c.zip and /dev/null differ diff --git a/.yarn/cache/@svgr-babel-plugin-transform-svg-component-npm-6.3.1-c0c6db0923-76113730f5.zip b/.yarn/cache/@svgr-babel-plugin-transform-svg-component-npm-6.3.1-c0c6db0923-76113730f5.zip new file mode 100644 index 000000000..0639da1af Binary files /dev/null and b/.yarn/cache/@svgr-babel-plugin-transform-svg-component-npm-6.3.1-c0c6db0923-76113730f5.zip differ diff --git a/.yarn/cache/@svgr-babel-preset-npm-6.2.0-98b7d97d8a-9a5ce41481.zip b/.yarn/cache/@svgr-babel-preset-npm-6.2.0-98b7d97d8a-9a5ce41481.zip deleted file mode 100644 index 7fd02f79b..000000000 Binary files a/.yarn/cache/@svgr-babel-preset-npm-6.2.0-98b7d97d8a-9a5ce41481.zip and /dev/null differ diff --git a/.yarn/cache/@svgr-babel-preset-npm-6.4.0-399613b92b-b7fe2d50f8.zip b/.yarn/cache/@svgr-babel-preset-npm-6.4.0-399613b92b-b7fe2d50f8.zip new file mode 100644 index 000000000..eb8348557 Binary files /dev/null and b/.yarn/cache/@svgr-babel-preset-npm-6.4.0-399613b92b-b7fe2d50f8.zip differ diff --git a/.yarn/cache/@svgr-core-npm-6.2.1-4cf4760ae3-b3eff9b081.zip b/.yarn/cache/@svgr-core-npm-6.2.1-4cf4760ae3-b3eff9b081.zip deleted file mode 100644 index 9592d5b32..000000000 Binary files a/.yarn/cache/@svgr-core-npm-6.2.1-4cf4760ae3-b3eff9b081.zip and /dev/null differ diff --git a/.yarn/cache/@svgr-core-npm-6.4.0-06ac222a91-d8c884ee4e.zip b/.yarn/cache/@svgr-core-npm-6.4.0-06ac222a91-d8c884ee4e.zip new file mode 100644 index 000000000..bc8cf7b8a Binary files /dev/null and b/.yarn/cache/@svgr-core-npm-6.4.0-06ac222a91-d8c884ee4e.zip differ diff --git a/.yarn/cache/@svgr-hast-util-to-babel-ast-npm-6.2.1-ea02b9786d-c99b05736e.zip b/.yarn/cache/@svgr-hast-util-to-babel-ast-npm-6.4.0-eaad6c25e9-a94ba920ef.zip similarity index 91% rename from .yarn/cache/@svgr-hast-util-to-babel-ast-npm-6.2.1-ea02b9786d-c99b05736e.zip rename to .yarn/cache/@svgr-hast-util-to-babel-ast-npm-6.4.0-eaad6c25e9-a94ba920ef.zip index 35a7ab122..dd41f5ddf 100644 Binary files a/.yarn/cache/@svgr-hast-util-to-babel-ast-npm-6.2.1-ea02b9786d-c99b05736e.zip and b/.yarn/cache/@svgr-hast-util-to-babel-ast-npm-6.4.0-eaad6c25e9-a94ba920ef.zip differ diff --git a/.yarn/cache/@svgr-plugin-jsx-npm-6.2.1-404dc70a83-998164c3c3.zip b/.yarn/cache/@svgr-plugin-jsx-npm-6.4.0-5dab371ff1-c1a40cc4f1.zip similarity index 57% rename from .yarn/cache/@svgr-plugin-jsx-npm-6.2.1-404dc70a83-998164c3c3.zip rename to .yarn/cache/@svgr-plugin-jsx-npm-6.4.0-5dab371ff1-c1a40cc4f1.zip index 1a76fe71c..9df157319 100644 Binary files a/.yarn/cache/@svgr-plugin-jsx-npm-6.2.1-404dc70a83-998164c3c3.zip and b/.yarn/cache/@svgr-plugin-jsx-npm-6.4.0-5dab371ff1-c1a40cc4f1.zip differ diff --git a/.yarn/cache/@svgr-plugin-svgo-npm-6.2.0-5e0b51a5c6-74d3aedd0f.zip b/.yarn/cache/@svgr-plugin-svgo-npm-6.3.1-868be92f74-037d6f91ba.zip similarity index 51% rename from .yarn/cache/@svgr-plugin-svgo-npm-6.2.0-5e0b51a5c6-74d3aedd0f.zip rename to .yarn/cache/@svgr-plugin-svgo-npm-6.3.1-868be92f74-037d6f91ba.zip index 148ff6aea..581c9f545 100644 Binary files a/.yarn/cache/@svgr-plugin-svgo-npm-6.2.0-5e0b51a5c6-74d3aedd0f.zip and b/.yarn/cache/@svgr-plugin-svgo-npm-6.3.1-868be92f74-037d6f91ba.zip differ diff --git a/.yarn/cache/@svgr-webpack-npm-6.2.1-c497fb9616-3da7e61942.zip b/.yarn/cache/@svgr-webpack-npm-6.4.0-f919307720-c8614f3d70.zip similarity index 60% rename from .yarn/cache/@svgr-webpack-npm-6.2.1-c497fb9616-3da7e61942.zip rename to .yarn/cache/@svgr-webpack-npm-6.4.0-f919307720-c8614f3d70.zip index 8af704396..7afa3f0f4 100644 Binary files a/.yarn/cache/@svgr-webpack-npm-6.2.1-c497fb9616-3da7e61942.zip and b/.yarn/cache/@svgr-webpack-npm-6.4.0-f919307720-c8614f3d70.zip differ diff --git a/.yarn/cache/@testing-library-dom-npm-8.14.0-c0d87cffdc-a916ea5167.zip b/.yarn/cache/@testing-library-dom-npm-8.14.0-c0d87cffdc-a916ea5167.zip deleted file mode 100644 index baa9284e2..000000000 Binary files a/.yarn/cache/@testing-library-dom-npm-8.14.0-c0d87cffdc-a916ea5167.zip and /dev/null differ diff --git a/.yarn/cache/@testing-library-dom-npm-8.19.0-1ae6733a53-6bb93fef96.zip b/.yarn/cache/@testing-library-dom-npm-8.19.0-1ae6733a53-6bb93fef96.zip new file mode 100644 index 000000000..462e6e1e1 Binary files /dev/null and b/.yarn/cache/@testing-library-dom-npm-8.19.0-1ae6733a53-6bb93fef96.zip differ diff --git a/.yarn/cache/@testing-library-jest-dom-npm-5.16.4-0bdb383307-4240501223.zip b/.yarn/cache/@testing-library-jest-dom-npm-5.16.5-b6d1f4e02f-94911f901a.zip similarity index 91% rename from .yarn/cache/@testing-library-jest-dom-npm-5.16.4-0bdb383307-4240501223.zip rename to .yarn/cache/@testing-library-jest-dom-npm-5.16.5-b6d1f4e02f-94911f901a.zip index d66b655a9..0bf4fade9 100644 Binary files a/.yarn/cache/@testing-library-jest-dom-npm-5.16.4-0bdb383307-4240501223.zip and b/.yarn/cache/@testing-library-jest-dom-npm-5.16.5-b6d1f4e02f-94911f901a.zip differ diff --git a/.yarn/cache/@types-babel__traverse-npm-7.17.1-97c6ab6eab-8992d8c1ea.zip b/.yarn/cache/@types-babel__traverse-npm-7.17.1-97c6ab6eab-8992d8c1ea.zip deleted file mode 100644 index 34ab31df3..000000000 Binary files a/.yarn/cache/@types-babel__traverse-npm-7.17.1-97c6ab6eab-8992d8c1ea.zip and /dev/null differ diff --git a/.yarn/cache/@types-babel__traverse-npm-7.18.2-17d99e224e-05972775e2.zip b/.yarn/cache/@types-babel__traverse-npm-7.18.2-17d99e224e-05972775e2.zip new file mode 100644 index 000000000..955f2adcc Binary files /dev/null and b/.yarn/cache/@types-babel__traverse-npm-7.18.2-17d99e224e-05972775e2.zip differ diff --git a/.yarn/cache/@types-cacheable-request-npm-6.0.2-894b6992d5-667d25808d.zip b/.yarn/cache/@types-cacheable-request-npm-6.0.2-894b6992d5-667d25808d.zip deleted file mode 100644 index f03e75385..000000000 Binary files a/.yarn/cache/@types-cacheable-request-npm-6.0.2-894b6992d5-667d25808d.zip and /dev/null differ diff --git a/.yarn/cache/@types-detox-npm-18.1.0-cb1d9c3662-e9f3088110.zip b/.yarn/cache/@types-detox-npm-18.1.0-cb1d9c3662-e9f3088110.zip deleted file mode 100644 index 7264d616f..000000000 Binary files a/.yarn/cache/@types-detox-npm-18.1.0-cb1d9c3662-e9f3088110.zip and /dev/null differ diff --git a/.yarn/cache/@types-dompurify-npm-2.3.3-502805169c-427e2dc60d.zip b/.yarn/cache/@types-dompurify-npm-2.3.3-502805169c-427e2dc60d.zip deleted file mode 100644 index 713a976f1..000000000 Binary files a/.yarn/cache/@types-dompurify-npm-2.3.3-502805169c-427e2dc60d.zip and /dev/null differ diff --git a/.yarn/cache/@types-dompurify-npm-2.3.4-934f5a1643-ea55678bc9.zip b/.yarn/cache/@types-dompurify-npm-2.3.4-934f5a1643-ea55678bc9.zip new file mode 100644 index 000000000..5dd377fb5 Binary files /dev/null and b/.yarn/cache/@types-dompurify-npm-2.3.4-934f5a1643-ea55678bc9.zip differ diff --git a/.yarn/cache/@types-eslint-npm-8.4.5-d510e2a3e3-428b0c971a.zip b/.yarn/cache/@types-eslint-npm-8.4.6-a8726d8319-bfaf27b000.zip similarity index 67% rename from .yarn/cache/@types-eslint-npm-8.4.5-d510e2a3e3-428b0c971a.zip rename to .yarn/cache/@types-eslint-npm-8.4.6-a8726d8319-bfaf27b000.zip index ec7436672..c21b186ed 100644 Binary files a/.yarn/cache/@types-eslint-npm-8.4.5-d510e2a3e3-428b0c971a.zip and b/.yarn/cache/@types-eslint-npm-8.4.6-a8726d8319-bfaf27b000.zip differ diff --git a/.yarn/cache/@types-estree-npm-0.0.52-28dfab9d2b-d1cba22160.zip b/.yarn/cache/@types-estree-npm-0.0.52-28dfab9d2b-d1cba22160.zip deleted file mode 100644 index 4ccc3121e..000000000 Binary files a/.yarn/cache/@types-estree-npm-0.0.52-28dfab9d2b-d1cba22160.zip and /dev/null differ diff --git a/.yarn/cache/@types-estree-npm-1.0.0-eddde5b631-910d97fb70.zip b/.yarn/cache/@types-estree-npm-1.0.0-eddde5b631-910d97fb70.zip new file mode 100644 index 000000000..8b03b040a Binary files /dev/null and b/.yarn/cache/@types-estree-npm-1.0.0-eddde5b631-910d97fb70.zip differ diff --git a/.yarn/cache/@types-express-npm-4.17.13-0e12fe9c24-12a2a0e6c4.zip b/.yarn/cache/@types-express-npm-4.17.13-0e12fe9c24-12a2a0e6c4.zip deleted file mode 100644 index 42b3aabd4..000000000 Binary files a/.yarn/cache/@types-express-npm-4.17.13-0e12fe9c24-12a2a0e6c4.zip and /dev/null differ diff --git a/.yarn/cache/@types-express-npm-4.17.14-076e1b4711-15c1af46d0.zip b/.yarn/cache/@types-express-npm-4.17.14-076e1b4711-15c1af46d0.zip new file mode 100644 index 000000000..3a7ee7f17 Binary files /dev/null and b/.yarn/cache/@types-express-npm-4.17.14-076e1b4711-15c1af46d0.zip differ diff --git a/.yarn/cache/@types-express-serve-static-core-npm-4.17.29-9b96bc0e26-ec4194dc59.zip b/.yarn/cache/@types-express-serve-static-core-npm-4.17.29-9b96bc0e26-ec4194dc59.zip deleted file mode 100644 index 5dd828c55..000000000 Binary files a/.yarn/cache/@types-express-serve-static-core-npm-4.17.29-9b96bc0e26-ec4194dc59.zip and /dev/null differ diff --git a/.yarn/cache/@types-express-serve-static-core-npm-4.17.31-846873f446-009bfbe107.zip b/.yarn/cache/@types-express-serve-static-core-npm-4.17.31-846873f446-009bfbe107.zip new file mode 100644 index 000000000..43817ddc9 Binary files /dev/null and b/.yarn/cache/@types-express-serve-static-core-npm-4.17.31-846873f446-009bfbe107.zip differ diff --git a/.yarn/cache/@types-faker-npm-6.6.9-396b021bf1-8fb069b6f2.zip b/.yarn/cache/@types-faker-npm-6.6.9-396b021bf1-8fb069b6f2.zip deleted file mode 100644 index 5fc85d28b..000000000 Binary files a/.yarn/cache/@types-faker-npm-6.6.9-396b021bf1-8fb069b6f2.zip and /dev/null differ diff --git a/.yarn/cache/@types-hammerjs-npm-2.0.41-0bbbcc986d-d16fbd688f.zip b/.yarn/cache/@types-hammerjs-npm-2.0.41-0bbbcc986d-d16fbd688f.zip deleted file mode 100644 index 88020dc9c..000000000 Binary files a/.yarn/cache/@types-hammerjs-npm-2.0.41-0bbbcc986d-d16fbd688f.zip and /dev/null differ diff --git a/.yarn/cache/@types-invariant-npm-2.2.35-4dde8d7c77-af1b624057.zip b/.yarn/cache/@types-invariant-npm-2.2.35-4dde8d7c77-af1b624057.zip deleted file mode 100644 index e976fa695..000000000 Binary files a/.yarn/cache/@types-invariant-npm-2.2.35-4dde8d7c77-af1b624057.zip and /dev/null differ diff --git a/.yarn/cache/@types-jest-npm-28.1.4-0d5921a434-97e22c6003.zip b/.yarn/cache/@types-jest-npm-28.1.4-0d5921a434-97e22c6003.zip deleted file mode 100644 index aa32fb70f..000000000 Binary files a/.yarn/cache/@types-jest-npm-28.1.4-0d5921a434-97e22c6003.zip and /dev/null differ diff --git a/.yarn/cache/@types-jest-npm-28.1.5-baa8088d99-994bfc25a5.zip b/.yarn/cache/@types-jest-npm-28.1.5-baa8088d99-994bfc25a5.zip deleted file mode 100644 index 9094b616f..000000000 Binary files a/.yarn/cache/@types-jest-npm-28.1.5-baa8088d99-994bfc25a5.zip and /dev/null differ diff --git a/.yarn/cache/@types-jest-npm-28.1.8-c361b866d1-d4cd36158a.zip b/.yarn/cache/@types-jest-npm-28.1.8-c361b866d1-d4cd36158a.zip new file mode 100644 index 000000000..a409a3539 Binary files /dev/null and b/.yarn/cache/@types-jest-npm-28.1.8-c361b866d1-d4cd36158a.zip differ diff --git a/.yarn/cache/@types-jest-npm-29.0.2-633da80e03-27c46b58fa.zip b/.yarn/cache/@types-jest-npm-29.0.2-633da80e03-27c46b58fa.zip deleted file mode 100644 index b6490f3bd..000000000 Binary files a/.yarn/cache/@types-jest-npm-29.0.2-633da80e03-27c46b58fa.zip and /dev/null differ diff --git a/.yarn/cache/@types-jest-npm-29.1.2-e051639cbf-a6761b5ac1.zip b/.yarn/cache/@types-jest-npm-29.1.2-e051639cbf-a6761b5ac1.zip new file mode 100644 index 000000000..da575398c Binary files /dev/null and b/.yarn/cache/@types-jest-npm-29.1.2-e051639cbf-a6761b5ac1.zip differ diff --git a/.yarn/cache/@types-js-base64-npm-3.3.1-0a2c52ee43-fbaaa1e6d2.zip b/.yarn/cache/@types-js-base64-npm-3.3.1-0a2c52ee43-fbaaa1e6d2.zip deleted file mode 100644 index a1ce74d2e..000000000 Binary files a/.yarn/cache/@types-js-base64-npm-3.3.1-0a2c52ee43-fbaaa1e6d2.zip and /dev/null differ diff --git a/.yarn/cache/@types-jsdom-npm-16.2.14-bfbb37071c-12bb926fa7.zip b/.yarn/cache/@types-jsdom-npm-16.2.15-1241c41fda-e038335321.zip similarity index 78% rename from .yarn/cache/@types-jsdom-npm-16.2.14-bfbb37071c-12bb926fa7.zip rename to .yarn/cache/@types-jsdom-npm-16.2.15-1241c41fda-e038335321.zip index 62ae3528b..a2dfad0dc 100644 Binary files a/.yarn/cache/@types-jsdom-npm-16.2.14-bfbb37071c-12bb926fa7.zip and b/.yarn/cache/@types-jsdom-npm-16.2.15-1241c41fda-e038335321.zip differ diff --git a/.yarn/cache/@types-json-buffer-npm-3.0.0-9f2fe89eaa-6b0a371dd6.zip b/.yarn/cache/@types-json-buffer-npm-3.0.0-9f2fe89eaa-6b0a371dd6.zip deleted file mode 100644 index ba0659e87..000000000 Binary files a/.yarn/cache/@types-json-buffer-npm-3.0.0-9f2fe89eaa-6b0a371dd6.zip and /dev/null differ diff --git a/.yarn/cache/@types-libsodium-wrappers-npm-0.7.9-4b14af299f-5ddf61b804.zip b/.yarn/cache/@types-libsodium-wrappers-npm-0.7.10-1977488a6a-717054ebcb.zip similarity index 56% rename from .yarn/cache/@types-libsodium-wrappers-npm-0.7.9-4b14af299f-5ddf61b804.zip rename to .yarn/cache/@types-libsodium-wrappers-npm-0.7.10-1977488a6a-717054ebcb.zip index 300ec5993..a4af6ae0b 100644 Binary files a/.yarn/cache/@types-libsodium-wrappers-npm-0.7.9-4b14af299f-5ddf61b804.zip and b/.yarn/cache/@types-libsodium-wrappers-npm-0.7.10-1977488a6a-717054ebcb.zip differ diff --git a/.yarn/cache/@types-lodash-npm-4.14.182-1073aac722-7dd137aa9d.zip b/.yarn/cache/@types-lodash-npm-4.14.182-1073aac722-7dd137aa9d.zip deleted file mode 100644 index 56f0da6f2..000000000 Binary files a/.yarn/cache/@types-lodash-npm-4.14.182-1073aac722-7dd137aa9d.zip and /dev/null differ diff --git a/.yarn/cache/@types-lodash-npm-4.14.185-974674435a-f81d13da5e.zip b/.yarn/cache/@types-lodash-npm-4.14.186-63caeea1e5-ee0c1368a8.zip similarity index 74% rename from .yarn/cache/@types-lodash-npm-4.14.185-974674435a-f81d13da5e.zip rename to .yarn/cache/@types-lodash-npm-4.14.186-63caeea1e5-ee0c1368a8.zip index 89ff4e5b0..e3b6d9d66 100644 Binary files a/.yarn/cache/@types-lodash-npm-4.14.185-974674435a-f81d13da5e.zip and b/.yarn/cache/@types-lodash-npm-4.14.186-63caeea1e5-ee0c1368a8.zip differ diff --git a/.yarn/cache/@types-marked-npm-4.0.3-595af935f1-2fc409a629.zip b/.yarn/cache/@types-marked-npm-4.0.3-595af935f1-2fc409a629.zip deleted file mode 100644 index 761f284e6..000000000 Binary files a/.yarn/cache/@types-marked-npm-4.0.3-595af935f1-2fc409a629.zip and /dev/null differ diff --git a/.yarn/cache/@types-marked-npm-4.0.7-9766a6e6d5-4907b6a606.zip b/.yarn/cache/@types-marked-npm-4.0.7-9766a6e6d5-4907b6a606.zip new file mode 100644 index 000000000..042baa0e5 Binary files /dev/null and b/.yarn/cache/@types-marked-npm-4.0.7-9766a6e6d5-4907b6a606.zip differ diff --git a/.yarn/cache/@types-mime-npm-1.3.2-ea71878ab3-0493368244.zip b/.yarn/cache/@types-mime-npm-1.3.2-ea71878ab3-0493368244.zip deleted file mode 100644 index e363cbe58..000000000 Binary files a/.yarn/cache/@types-mime-npm-1.3.2-ea71878ab3-0493368244.zip and /dev/null differ diff --git a/.yarn/cache/@types-mime-npm-3.0.1-dec03536dc-4040fac73f.zip b/.yarn/cache/@types-mime-npm-3.0.1-dec03536dc-4040fac73f.zip new file mode 100644 index 000000000..7c90f6383 Binary files /dev/null and b/.yarn/cache/@types-mime-npm-3.0.1-dec03536dc-4040fac73f.zip differ diff --git a/.yarn/cache/@types-minimatch-npm-5.1.2-aab9c394d3-0391a28286.zip b/.yarn/cache/@types-minimatch-npm-5.1.2-aab9c394d3-0391a28286.zip new file mode 100644 index 000000000..2d74ccef4 Binary files /dev/null and b/.yarn/cache/@types-minimatch-npm-5.1.2-aab9c394d3-0391a28286.zip differ diff --git a/.yarn/cache/@types-node-npm-14.18.21-2487d6eca5-4ed35b7660.zip b/.yarn/cache/@types-node-npm-14.18.21-2487d6eca5-4ed35b7660.zip deleted file mode 100644 index c049b6bec..000000000 Binary files a/.yarn/cache/@types-node-npm-14.18.21-2487d6eca5-4ed35b7660.zip and /dev/null differ diff --git a/.yarn/cache/@types-node-npm-14.18.32-e109f2acf7-45463114bf.zip b/.yarn/cache/@types-node-npm-14.18.32-e109f2acf7-45463114bf.zip new file mode 100644 index 000000000..a0f427b80 Binary files /dev/null and b/.yarn/cache/@types-node-npm-14.18.32-e109f2acf7-45463114bf.zip differ diff --git a/.yarn/cache/@types-node-npm-16.11.58-90178e4c18-efdf14c62e.zip b/.yarn/cache/@types-node-npm-16.11.58-90178e4c18-efdf14c62e.zip deleted file mode 100644 index 5b1c5b9c0..000000000 Binary files a/.yarn/cache/@types-node-npm-16.11.58-90178e4c18-efdf14c62e.zip and /dev/null differ diff --git a/.yarn/cache/@types-node-npm-16.11.65-1ab60ac4e7-81d84cb1e7.zip b/.yarn/cache/@types-node-npm-16.11.65-1ab60ac4e7-81d84cb1e7.zip new file mode 100644 index 000000000..71dd79b75 Binary files /dev/null and b/.yarn/cache/@types-node-npm-16.11.65-1ab60ac4e7-81d84cb1e7.zip differ diff --git a/.yarn/cache/@types-node-npm-18.0.1-35e22b3e26-be14b251c5.zip b/.yarn/cache/@types-node-npm-18.0.1-35e22b3e26-be14b251c5.zip deleted file mode 100644 index dd0248a07..000000000 Binary files a/.yarn/cache/@types-node-npm-18.0.1-35e22b3e26-be14b251c5.zip and /dev/null differ diff --git a/.yarn/cache/@types-node-npm-18.8.5-726f8e422b-f7d896f547.zip b/.yarn/cache/@types-node-npm-18.8.5-726f8e422b-f7d896f547.zip new file mode 100644 index 000000000..0fe0c42f9 Binary files /dev/null and b/.yarn/cache/@types-node-npm-18.8.5-726f8e422b-f7d896f547.zip differ diff --git a/.yarn/cache/@types-prettier-npm-2.6.3-8d27063d48-e1836699ca.zip b/.yarn/cache/@types-prettier-npm-2.6.3-8d27063d48-e1836699ca.zip deleted file mode 100644 index 1a91d8c32..000000000 Binary files a/.yarn/cache/@types-prettier-npm-2.6.3-8d27063d48-e1836699ca.zip and /dev/null differ diff --git a/.yarn/cache/@types-prettier-npm-2.7.1-d46ada27e6-5e3f58e229.zip b/.yarn/cache/@types-prettier-npm-2.7.1-d46ada27e6-5e3f58e229.zip new file mode 100644 index 000000000..15de2b6ee Binary files /dev/null and b/.yarn/cache/@types-prettier-npm-2.7.1-d46ada27e6-5e3f58e229.zip differ diff --git a/.yarn/cache/@types-react-native-npm-0.65.23-5966ac809b-ed8f53afec.zip b/.yarn/cache/@types-react-native-npm-0.65.23-5966ac809b-ed8f53afec.zip deleted file mode 100644 index c268d7b1c..000000000 Binary files a/.yarn/cache/@types-react-native-npm-0.65.23-5966ac809b-ed8f53afec.zip and /dev/null differ diff --git a/.yarn/cache/@types-react-native-npm-0.67.11-375d14d2d2-5c38a29c62.zip b/.yarn/cache/@types-react-native-npm-0.67.11-375d14d2d2-5c38a29c62.zip deleted file mode 100644 index 35ae961d9..000000000 Binary files a/.yarn/cache/@types-react-native-npm-0.67.11-375d14d2d2-5c38a29c62.zip and /dev/null differ diff --git a/.yarn/cache/@types-react-native-npm-0.67.15-d5fa496bd5-303648aff9.zip b/.yarn/cache/@types-react-native-npm-0.67.15-d5fa496bd5-303648aff9.zip new file mode 100644 index 000000000..247d5a1d5 Binary files /dev/null and b/.yarn/cache/@types-react-native-npm-0.67.15-d5fa496bd5-303648aff9.zip differ diff --git a/.yarn/cache/@types-react-native-npm-0.69.2-331fd7c411-210a658415.zip b/.yarn/cache/@types-react-native-npm-0.69.2-331fd7c411-210a658415.zip deleted file mode 100644 index f89e08726..000000000 Binary files a/.yarn/cache/@types-react-native-npm-0.69.2-331fd7c411-210a658415.zip and /dev/null differ diff --git a/.yarn/cache/@types-react-native-vector-icons-npm-6.4.11-bf7260d11d-f2ed7fbf25.zip b/.yarn/cache/@types-react-native-vector-icons-npm-6.4.11-bf7260d11d-f2ed7fbf25.zip deleted file mode 100644 index ff943b521..000000000 Binary files a/.yarn/cache/@types-react-native-vector-icons-npm-6.4.11-bf7260d11d-f2ed7fbf25.zip and /dev/null differ diff --git a/.yarn/cache/@types-react-npm-17.0.47-fa0afc8272-2e7fe0eb63.zip b/.yarn/cache/@types-react-npm-17.0.47-fa0afc8272-2e7fe0eb63.zip deleted file mode 100644 index c23eb8d5b..000000000 Binary files a/.yarn/cache/@types-react-npm-17.0.47-fa0afc8272-2e7fe0eb63.zip and /dev/null differ diff --git a/.yarn/cache/@types-react-npm-17.0.50-14eafba020-b5629dff7c.zip b/.yarn/cache/@types-react-npm-17.0.50-14eafba020-b5629dff7c.zip new file mode 100644 index 000000000..1014a2766 Binary files /dev/null and b/.yarn/cache/@types-react-npm-17.0.50-14eafba020-b5629dff7c.zip differ diff --git a/.yarn/cache/@types-react-npm-18.0.14-8bf0a6b01e-608eb57a38.zip b/.yarn/cache/@types-react-npm-18.0.14-8bf0a6b01e-608eb57a38.zip deleted file mode 100644 index 61cf78884..000000000 Binary files a/.yarn/cache/@types-react-npm-18.0.14-8bf0a6b01e-608eb57a38.zip and /dev/null differ diff --git a/.yarn/cache/@types-react-npm-18.0.20-064ea90ef1-f67f5b16ef.zip b/.yarn/cache/@types-react-npm-18.0.21-e933f9864e-36c1a7c9d5.zip similarity index 84% rename from .yarn/cache/@types-react-npm-18.0.20-064ea90ef1-f67f5b16ef.zip rename to .yarn/cache/@types-react-npm-18.0.21-e933f9864e-36c1a7c9d5.zip index ad546d5a9..c4f191fcb 100644 Binary files a/.yarn/cache/@types-react-npm-18.0.20-064ea90ef1-f67f5b16ef.zip and b/.yarn/cache/@types-react-npm-18.0.21-e933f9864e-36c1a7c9d5.zip differ diff --git a/.yarn/cache/@types-react-test-renderer-npm-17.0.2-71899ad95b-0be325798b.zip b/.yarn/cache/@types-react-test-renderer-npm-17.0.2-71899ad95b-0be325798b.zip deleted file mode 100644 index adc1a5f03..000000000 Binary files a/.yarn/cache/@types-react-test-renderer-npm-17.0.2-71899ad95b-0be325798b.zip and /dev/null differ diff --git a/.yarn/cache/@types-semver-npm-7.3.10-bcda8eb925-7047c2822b.zip b/.yarn/cache/@types-semver-npm-7.3.10-bcda8eb925-7047c2822b.zip deleted file mode 100644 index 1128c29ee..000000000 Binary files a/.yarn/cache/@types-semver-npm-7.3.10-bcda8eb925-7047c2822b.zip and /dev/null differ diff --git a/.yarn/cache/@types-semver-npm-7.3.12-c91001a94c-35536b2fc5.zip b/.yarn/cache/@types-semver-npm-7.3.12-c91001a94c-35536b2fc5.zip new file mode 100644 index 000000000..7db9a40de Binary files /dev/null and b/.yarn/cache/@types-semver-npm-7.3.12-c91001a94c-35536b2fc5.zip differ diff --git a/.yarn/cache/@types-serve-static-npm-1.13.10-5434e2c519-eaca858739.zip b/.yarn/cache/@types-serve-static-npm-1.13.10-5434e2c519-eaca858739.zip deleted file mode 100644 index 3c2a9460c..000000000 Binary files a/.yarn/cache/@types-serve-static-npm-1.13.10-5434e2c519-eaca858739.zip and /dev/null differ diff --git a/.yarn/cache/@types-serve-static-npm-1.15.0-ec80a4ac87-b6ac93d471.zip b/.yarn/cache/@types-serve-static-npm-1.15.0-ec80a4ac87-b6ac93d471.zip new file mode 100644 index 000000000..40ebf94a5 Binary files /dev/null and b/.yarn/cache/@types-serve-static-npm-1.15.0-ec80a4ac87-b6ac93d471.zip differ diff --git a/.yarn/cache/@types-styled-components-npm-5.1.25-c6ef913a87-60ce64f132.zip b/.yarn/cache/@types-styled-components-npm-5.1.25-c6ef913a87-60ce64f132.zip deleted file mode 100644 index 7cfe4f41f..000000000 Binary files a/.yarn/cache/@types-styled-components-npm-5.1.25-c6ef913a87-60ce64f132.zip and /dev/null differ diff --git a/.yarn/cache/@types-styled-components-react-native-npm-5.1.3-8a544d27f2-503e693c06.zip b/.yarn/cache/@types-styled-components-react-native-npm-5.1.3-8a544d27f2-503e693c06.zip deleted file mode 100644 index 269243840..000000000 Binary files a/.yarn/cache/@types-styled-components-react-native-npm-5.1.3-8a544d27f2-503e693c06.zip and /dev/null differ diff --git a/.yarn/cache/@types-uglify-js-npm-3.16.0-58c2ee2004-10b0c4a5f3.zip b/.yarn/cache/@types-uglify-js-npm-3.16.0-58c2ee2004-10b0c4a5f3.zip deleted file mode 100644 index 143f17fa8..000000000 Binary files a/.yarn/cache/@types-uglify-js-npm-3.16.0-58c2ee2004-10b0c4a5f3.zip and /dev/null differ diff --git a/.yarn/cache/@types-uglify-js-npm-3.17.0-8a9a6e6de3-931bc58008.zip b/.yarn/cache/@types-uglify-js-npm-3.17.0-8a9a6e6de3-931bc58008.zip new file mode 100644 index 000000000..684c970b7 Binary files /dev/null and b/.yarn/cache/@types-uglify-js-npm-3.17.0-8a9a6e6de3-931bc58008.zip differ diff --git a/.yarn/cache/@types-verror-npm-1.10.5-992a3c4e93-f9f7073d86.zip b/.yarn/cache/@types-verror-npm-1.10.5-992a3c4e93-f9f7073d86.zip deleted file mode 100644 index aef675180..000000000 Binary files a/.yarn/cache/@types-verror-npm-1.10.5-992a3c4e93-f9f7073d86.zip and /dev/null differ diff --git a/.yarn/cache/@types-verror-npm-1.10.6-159ceda3ad-650620b851.zip b/.yarn/cache/@types-verror-npm-1.10.6-159ceda3ad-650620b851.zip new file mode 100644 index 000000000..42d195d7a Binary files /dev/null and b/.yarn/cache/@types-verror-npm-1.10.6-159ceda3ad-650620b851.zip differ diff --git a/.yarn/cache/@types-yargs-npm-17.0.10-04ed5382c7-f0673cbfc0.zip b/.yarn/cache/@types-yargs-npm-17.0.10-04ed5382c7-f0673cbfc0.zip deleted file mode 100644 index b007567ba..000000000 Binary files a/.yarn/cache/@types-yargs-npm-17.0.10-04ed5382c7-f0673cbfc0.zip and /dev/null differ diff --git a/.yarn/cache/@types-yargs-npm-17.0.13-67226ed55b-0ab269abc2.zip b/.yarn/cache/@types-yargs-npm-17.0.13-67226ed55b-0ab269abc2.zip new file mode 100644 index 000000000..e3c97fa2f Binary files /dev/null and b/.yarn/cache/@types-yargs-npm-17.0.13-67226ed55b-0ab269abc2.zip differ diff --git a/.yarn/cache/@typescript-eslint-eslint-plugin-npm-5.30.5-56e8842647-cf763fb091.zip b/.yarn/cache/@typescript-eslint-eslint-plugin-npm-5.30.5-56e8842647-cf763fb091.zip deleted file mode 100644 index 9ed7baa45..000000000 Binary files a/.yarn/cache/@typescript-eslint-eslint-plugin-npm-5.30.5-56e8842647-cf763fb091.zip and /dev/null differ diff --git a/.yarn/cache/@typescript-eslint-eslint-plugin-npm-5.40.0-167e1ee74d-ac9e8fcea3.zip b/.yarn/cache/@typescript-eslint-eslint-plugin-npm-5.40.0-167e1ee74d-ac9e8fcea3.zip new file mode 100644 index 000000000..2e8abb11c Binary files /dev/null and b/.yarn/cache/@typescript-eslint-eslint-plugin-npm-5.40.0-167e1ee74d-ac9e8fcea3.zip differ diff --git a/.yarn/cache/@typescript-eslint-experimental-utils-npm-5.30.5-2415824bd6-7aeaa9b427.zip b/.yarn/cache/@typescript-eslint-experimental-utils-npm-5.40.0-7147adb5e7-3556f78dc8.zip similarity index 73% rename from .yarn/cache/@typescript-eslint-experimental-utils-npm-5.30.5-2415824bd6-7aeaa9b427.zip rename to .yarn/cache/@typescript-eslint-experimental-utils-npm-5.40.0-7147adb5e7-3556f78dc8.zip index b467faa03..dbf045a91 100644 Binary files a/.yarn/cache/@typescript-eslint-experimental-utils-npm-5.30.5-2415824bd6-7aeaa9b427.zip and b/.yarn/cache/@typescript-eslint-experimental-utils-npm-5.40.0-7147adb5e7-3556f78dc8.zip differ diff --git a/.yarn/cache/@typescript-eslint-parser-npm-5.30.5-27a499c345-6c16821e12.zip b/.yarn/cache/@typescript-eslint-parser-npm-5.30.5-27a499c345-6c16821e12.zip deleted file mode 100644 index 48eb12769..000000000 Binary files a/.yarn/cache/@typescript-eslint-parser-npm-5.30.5-27a499c345-6c16821e12.zip and /dev/null differ diff --git a/.yarn/cache/@typescript-eslint-parser-npm-5.40.0-36cbbd9048-a8d02950dd.zip b/.yarn/cache/@typescript-eslint-parser-npm-5.40.0-36cbbd9048-a8d02950dd.zip new file mode 100644 index 000000000..ea9266092 Binary files /dev/null and b/.yarn/cache/@typescript-eslint-parser-npm-5.40.0-36cbbd9048-a8d02950dd.zip differ diff --git a/.yarn/cache/@typescript-eslint-scope-manager-npm-5.30.5-3e1fbf788a-509bee6d62.zip b/.yarn/cache/@typescript-eslint-scope-manager-npm-5.30.5-3e1fbf788a-509bee6d62.zip deleted file mode 100644 index a3c62d9be..000000000 Binary files a/.yarn/cache/@typescript-eslint-scope-manager-npm-5.30.5-3e1fbf788a-509bee6d62.zip and /dev/null differ diff --git a/.yarn/cache/@typescript-eslint-scope-manager-npm-5.40.0-86f5f7a2d0-48dfb2f1a7.zip b/.yarn/cache/@typescript-eslint-scope-manager-npm-5.40.0-86f5f7a2d0-48dfb2f1a7.zip new file mode 100644 index 000000000..6056e2ae3 Binary files /dev/null and b/.yarn/cache/@typescript-eslint-scope-manager-npm-5.40.0-86f5f7a2d0-48dfb2f1a7.zip differ diff --git a/.yarn/cache/@typescript-eslint-type-utils-npm-5.30.5-765594d88b-080cc12317.zip b/.yarn/cache/@typescript-eslint-type-utils-npm-5.40.0-e60c776425-eabe86de93.zip similarity index 62% rename from .yarn/cache/@typescript-eslint-type-utils-npm-5.30.5-765594d88b-080cc12317.zip rename to .yarn/cache/@typescript-eslint-type-utils-npm-5.40.0-e60c776425-eabe86de93.zip index 7a816b538..07f68c82d 100644 Binary files a/.yarn/cache/@typescript-eslint-type-utils-npm-5.30.5-765594d88b-080cc12317.zip and b/.yarn/cache/@typescript-eslint-type-utils-npm-5.40.0-e60c776425-eabe86de93.zip differ diff --git a/.yarn/cache/@typescript-eslint-types-npm-5.30.5-77f495433c-c70420618c.zip b/.yarn/cache/@typescript-eslint-types-npm-5.30.5-77f495433c-c70420618c.zip deleted file mode 100644 index c71017ab5..000000000 Binary files a/.yarn/cache/@typescript-eslint-types-npm-5.30.5-77f495433c-c70420618c.zip and /dev/null differ diff --git a/.yarn/cache/@typescript-eslint-types-npm-5.40.0-032e3ccf3b-892ff16217.zip b/.yarn/cache/@typescript-eslint-types-npm-5.40.0-032e3ccf3b-892ff16217.zip new file mode 100644 index 000000000..f70a445e7 Binary files /dev/null and b/.yarn/cache/@typescript-eslint-types-npm-5.40.0-032e3ccf3b-892ff16217.zip differ diff --git a/.yarn/cache/@typescript-eslint-typescript-estree-npm-5.30.5-da9a64fff6-19dce426c8.zip b/.yarn/cache/@typescript-eslint-typescript-estree-npm-5.30.5-da9a64fff6-19dce426c8.zip deleted file mode 100644 index 5ea0d78cb..000000000 Binary files a/.yarn/cache/@typescript-eslint-typescript-estree-npm-5.30.5-da9a64fff6-19dce426c8.zip and /dev/null differ diff --git a/.yarn/cache/@typescript-eslint-typescript-estree-npm-5.40.0-6f9c0e3909-8b67b8c427.zip b/.yarn/cache/@typescript-eslint-typescript-estree-npm-5.40.0-6f9c0e3909-8b67b8c427.zip new file mode 100644 index 000000000..62a7b7daa Binary files /dev/null and b/.yarn/cache/@typescript-eslint-typescript-estree-npm-5.40.0-6f9c0e3909-8b67b8c427.zip differ diff --git a/.yarn/cache/@typescript-eslint-utils-npm-5.30.5-4cd4c166a4-12f68cb34a.zip b/.yarn/cache/@typescript-eslint-utils-npm-5.30.5-4cd4c166a4-12f68cb34a.zip deleted file mode 100644 index 0a0f10c4b..000000000 Binary files a/.yarn/cache/@typescript-eslint-utils-npm-5.30.5-4cd4c166a4-12f68cb34a.zip and /dev/null differ diff --git a/.yarn/cache/@typescript-eslint-utils-npm-5.40.0-887fe13b58-608e16ad51.zip b/.yarn/cache/@typescript-eslint-utils-npm-5.40.0-887fe13b58-608e16ad51.zip new file mode 100644 index 000000000..be0e47ef2 Binary files /dev/null and b/.yarn/cache/@typescript-eslint-utils-npm-5.40.0-887fe13b58-608e16ad51.zip differ diff --git a/.yarn/cache/@typescript-eslint-visitor-keys-npm-5.30.5-027fead89e-c0de9ae483.zip b/.yarn/cache/@typescript-eslint-visitor-keys-npm-5.40.0-0b6573a5a2-a11787f7e6.zip similarity index 62% rename from .yarn/cache/@typescript-eslint-visitor-keys-npm-5.30.5-027fead89e-c0de9ae483.zip rename to .yarn/cache/@typescript-eslint-visitor-keys-npm-5.40.0-0b6573a5a2-a11787f7e6.zip index 42a93a37c..9cc26f86c 100644 Binary files a/.yarn/cache/@typescript-eslint-visitor-keys-npm-5.30.5-027fead89e-c0de9ae483.zip and b/.yarn/cache/@typescript-eslint-visitor-keys-npm-5.40.0-0b6573a5a2-a11787f7e6.zip differ diff --git a/.yarn/cache/@zip.js-zip.js-npm-2.6.26-405aca16d1-617f28a864.zip b/.yarn/cache/@zip.js-zip.js-npm-2.6.26-405aca16d1-617f28a864.zip deleted file mode 100644 index 2bf9e2475..000000000 Binary files a/.yarn/cache/@zip.js-zip.js-npm-2.6.26-405aca16d1-617f28a864.zip and /dev/null differ diff --git a/.yarn/cache/@zip.js-zip.js-npm-2.6.43-c13b646e3f-d75f09e8d9.zip b/.yarn/cache/@zip.js-zip.js-npm-2.6.43-c13b646e3f-d75f09e8d9.zip new file mode 100644 index 000000000..966732280 Binary files /dev/null and b/.yarn/cache/@zip.js-zip.js-npm-2.6.43-c13b646e3f-d75f09e8d9.zip differ diff --git a/.yarn/cache/acorn-globals-npm-7.0.1-97c48c0140-2a2998a547.zip b/.yarn/cache/acorn-globals-npm-7.0.1-97c48c0140-2a2998a547.zip new file mode 100644 index 000000000..f18c3d9ca Binary files /dev/null and b/.yarn/cache/acorn-globals-npm-7.0.1-97c48c0140-2a2998a547.zip differ diff --git a/.yarn/cache/acorn-npm-8.7.1-7c7a019990-aca0aabf98.zip b/.yarn/cache/acorn-npm-8.7.1-7c7a019990-aca0aabf98.zip deleted file mode 100644 index 7cb7203ce..000000000 Binary files a/.yarn/cache/acorn-npm-8.7.1-7c7a019990-aca0aabf98.zip and /dev/null differ diff --git a/.yarn/cache/address-npm-1.2.0-ed441d6b8a-2ef3aa9d23.zip b/.yarn/cache/address-npm-1.2.0-ed441d6b8a-2ef3aa9d23.zip deleted file mode 100644 index 11d70078f..000000000 Binary files a/.yarn/cache/address-npm-1.2.0-ed441d6b8a-2ef3aa9d23.zip and /dev/null differ diff --git a/.yarn/cache/address-npm-1.2.1-e8f7122c11-e4c0f96146.zip b/.yarn/cache/address-npm-1.2.1-e8f7122c11-e4c0f96146.zip new file mode 100644 index 000000000..66994720c Binary files /dev/null and b/.yarn/cache/address-npm-1.2.1-e8f7122c11-e4c0f96146.zip differ diff --git a/.yarn/cache/algoliasearch-helper-npm-3.10.0-8122227956-5b74cbc1d1.zip b/.yarn/cache/algoliasearch-helper-npm-3.10.0-8122227956-5b74cbc1d1.zip deleted file mode 100644 index ee6f2f8de..000000000 Binary files a/.yarn/cache/algoliasearch-helper-npm-3.10.0-8122227956-5b74cbc1d1.zip and /dev/null differ diff --git a/.yarn/cache/algoliasearch-helper-npm-3.11.1-1cc35e5b35-207616ca45.zip b/.yarn/cache/algoliasearch-helper-npm-3.11.1-1cc35e5b35-207616ca45.zip new file mode 100644 index 000000000..6a90281f1 Binary files /dev/null and b/.yarn/cache/algoliasearch-helper-npm-3.11.1-1cc35e5b35-207616ca45.zip differ diff --git a/.yarn/cache/algoliasearch-npm-4.13.1-c21b78d633-c2083e7827.zip b/.yarn/cache/algoliasearch-npm-4.13.1-c21b78d633-c2083e7827.zip deleted file mode 100644 index 28334a150..000000000 Binary files a/.yarn/cache/algoliasearch-npm-4.13.1-c21b78d633-c2083e7827.zip and /dev/null differ diff --git a/.yarn/cache/algoliasearch-npm-4.14.2-df3332ab38-4365a0d0f0.zip b/.yarn/cache/algoliasearch-npm-4.14.2-df3332ab38-4365a0d0f0.zip new file mode 100644 index 000000000..2f492d1d7 Binary files /dev/null and b/.yarn/cache/algoliasearch-npm-4.14.2-df3332ab38-4365a0d0f0.zip differ diff --git a/.yarn/cache/ansi-styles-npm-6.1.0-4f6a594d04-7a7f8528c0.zip b/.yarn/cache/ansi-styles-npm-6.1.0-4f6a594d04-7a7f8528c0.zip deleted file mode 100644 index 27d0a18c8..000000000 Binary files a/.yarn/cache/ansi-styles-npm-6.1.0-4f6a594d04-7a7f8528c0.zip and /dev/null differ diff --git a/.yarn/cache/ansi-styles-npm-6.2.1-d43647018c-ef940f2f0c.zip b/.yarn/cache/ansi-styles-npm-6.2.1-d43647018c-ef940f2f0c.zip new file mode 100644 index 000000000..aa1bdfde1 Binary files /dev/null and b/.yarn/cache/ansi-styles-npm-6.2.1-d43647018c-ef940f2f0c.zip differ diff --git a/.yarn/cache/appdirsjs-npm-1.2.6-ee85413504-b680cffe91.zip b/.yarn/cache/appdirsjs-npm-1.2.6-ee85413504-b680cffe91.zip deleted file mode 100644 index 9863f220c..000000000 Binary files a/.yarn/cache/appdirsjs-npm-1.2.6-ee85413504-b680cffe91.zip and /dev/null differ diff --git a/.yarn/cache/appdirsjs-npm-1.2.7-fcd05e6058-3411b4e31e.zip b/.yarn/cache/appdirsjs-npm-1.2.7-fcd05e6058-3411b4e31e.zip new file mode 100644 index 000000000..0ab326694 Binary files /dev/null and b/.yarn/cache/appdirsjs-npm-1.2.7-fcd05e6058-3411b4e31e.zip differ diff --git a/.yarn/cache/are-we-there-yet-npm-3.0.0-1391430190-348edfdd93.zip b/.yarn/cache/are-we-there-yet-npm-3.0.1-3395b1512f-52590c2486.zip similarity index 66% rename from .yarn/cache/are-we-there-yet-npm-3.0.0-1391430190-348edfdd93.zip rename to .yarn/cache/are-we-there-yet-npm-3.0.1-3395b1512f-52590c2486.zip index b4d0a71b8..1f0af5013 100644 Binary files a/.yarn/cache/are-we-there-yet-npm-3.0.0-1391430190-348edfdd93.zip and b/.yarn/cache/are-we-there-yet-npm-3.0.1-3395b1512f-52590c2486.zip differ diff --git a/.yarn/cache/aria-query-npm-5.0.0-986fb11e0e-c41f98866c.zip b/.yarn/cache/aria-query-npm-5.0.0-986fb11e0e-c41f98866c.zip deleted file mode 100644 index 50e4bcbd5..000000000 Binary files a/.yarn/cache/aria-query-npm-5.0.0-986fb11e0e-c41f98866c.zip and /dev/null differ diff --git a/.yarn/cache/aria-query-npm-5.0.2-9d7c225334-2ecb77a64b.zip b/.yarn/cache/aria-query-npm-5.0.2-9d7c225334-2ecb77a64b.zip new file mode 100644 index 000000000..434a72fa6 Binary files /dev/null and b/.yarn/cache/aria-query-npm-5.0.2-9d7c225334-2ecb77a64b.zip differ diff --git a/.yarn/cache/array-filter-npm-0.0.1-37dfbb574c-0e9afdf5e2.zip b/.yarn/cache/array-filter-npm-0.0.1-37dfbb574c-0e9afdf5e2.zip deleted file mode 100644 index d5b3b3080..000000000 Binary files a/.yarn/cache/array-filter-npm-0.0.1-37dfbb574c-0e9afdf5e2.zip and /dev/null differ diff --git a/.yarn/cache/array-map-npm-0.0.0-45992ed41e-30d73fdc99.zip b/.yarn/cache/array-map-npm-0.0.0-45992ed41e-30d73fdc99.zip deleted file mode 100644 index 60f878729..000000000 Binary files a/.yarn/cache/array-map-npm-0.0.0-45992ed41e-30d73fdc99.zip and /dev/null differ diff --git a/.yarn/cache/array-reduce-npm-0.0.0-d774206485-d622632527.zip b/.yarn/cache/array-reduce-npm-0.0.0-d774206485-d622632527.zip deleted file mode 100644 index 13c432495..000000000 Binary files a/.yarn/cache/array-reduce-npm-0.0.0-d774206485-d622632527.zip and /dev/null differ diff --git a/.yarn/cache/asar-npm-3.1.0-95ed7986e6-facc808456.zip b/.yarn/cache/asar-npm-3.2.0-ce87ce2b73-f7d30b4597.zip similarity index 51% rename from .yarn/cache/asar-npm-3.1.0-95ed7986e6-facc808456.zip rename to .yarn/cache/asar-npm-3.2.0-ce87ce2b73-f7d30b4597.zip index 58dc72542..b5891d939 100644 Binary files a/.yarn/cache/asar-npm-3.1.0-95ed7986e6-facc808456.zip and b/.yarn/cache/asar-npm-3.2.0-ce87ce2b73-f7d30b4597.zip differ diff --git a/.yarn/cache/autoprefixer-npm-10.4.10-9a4998334e-e48d99b285.zip b/.yarn/cache/autoprefixer-npm-10.4.12-e87232197d-6ae79cbacd.zip similarity index 82% rename from .yarn/cache/autoprefixer-npm-10.4.10-9a4998334e-e48d99b285.zip rename to .yarn/cache/autoprefixer-npm-10.4.12-e87232197d-6ae79cbacd.zip index f70916f84..44566f9f7 100644 Binary files a/.yarn/cache/autoprefixer-npm-10.4.10-9a4998334e-e48d99b285.zip and b/.yarn/cache/autoprefixer-npm-10.4.12-e87232197d-6ae79cbacd.zip differ diff --git a/.yarn/cache/autoprefixer-npm-10.4.7-463a114196-0e55d0d198.zip b/.yarn/cache/autoprefixer-npm-10.4.7-463a114196-0e55d0d198.zip deleted file mode 100644 index ad2777709..000000000 Binary files a/.yarn/cache/autoprefixer-npm-10.4.7-463a114196-0e55d0d198.zip and /dev/null differ diff --git a/.yarn/cache/axe-core-npm-4.4.2-4872658842-93fbb36c5a.zip b/.yarn/cache/axe-core-npm-4.4.2-4872658842-93fbb36c5a.zip deleted file mode 100644 index f5d799e0d..000000000 Binary files a/.yarn/cache/axe-core-npm-4.4.2-4872658842-93fbb36c5a.zip and /dev/null differ diff --git a/.yarn/cache/axe-core-npm-4.4.3-6a07ed8cf6-c3ea000d9a.zip b/.yarn/cache/axe-core-npm-4.4.3-6a07ed8cf6-c3ea000d9a.zip new file mode 100644 index 000000000..e3325f939 Binary files /dev/null and b/.yarn/cache/axe-core-npm-4.4.3-6a07ed8cf6-c3ea000d9a.zip differ diff --git a/.yarn/cache/babel-jest-npm-28.1.2-9fe49235c4-1aa605ef4d.zip b/.yarn/cache/babel-jest-npm-28.1.3-3bb56d0efd-57ccd2296e.zip similarity index 82% rename from .yarn/cache/babel-jest-npm-28.1.2-9fe49235c4-1aa605ef4d.zip rename to .yarn/cache/babel-jest-npm-28.1.3-3bb56d0efd-57ccd2296e.zip index 8d16285b1..38c057dcb 100644 Binary files a/.yarn/cache/babel-jest-npm-28.1.2-9fe49235c4-1aa605ef4d.zip and b/.yarn/cache/babel-jest-npm-28.1.3-3bb56d0efd-57ccd2296e.zip differ diff --git a/.yarn/cache/babel-plugin-jest-hoist-npm-28.1.1-aaeb3ac36a-5fb9ad012e.zip b/.yarn/cache/babel-plugin-jest-hoist-npm-28.1.3-ffadc60ff3-648d89f9d8.zip similarity index 84% rename from .yarn/cache/babel-plugin-jest-hoist-npm-28.1.1-aaeb3ac36a-5fb9ad012e.zip rename to .yarn/cache/babel-plugin-jest-hoist-npm-28.1.3-ffadc60ff3-648d89f9d8.zip index 0ead1dcbd..e7f9c123a 100644 Binary files a/.yarn/cache/babel-plugin-jest-hoist-npm-28.1.1-aaeb3ac36a-5fb9ad012e.zip and b/.yarn/cache/babel-plugin-jest-hoist-npm-28.1.3-ffadc60ff3-648d89f9d8.zip differ diff --git a/.yarn/cache/babel-plugin-macros-npm-2.8.0-451367d7e7-59b09a21cf.zip b/.yarn/cache/babel-plugin-macros-npm-2.8.0-451367d7e7-59b09a21cf.zip deleted file mode 100644 index cdb42c1ba..000000000 Binary files a/.yarn/cache/babel-plugin-macros-npm-2.8.0-451367d7e7-59b09a21cf.zip and /dev/null differ diff --git a/.yarn/cache/babel-plugin-polyfill-corejs2-npm-0.3.1-43e6df66ff-ca873f14cc.zip b/.yarn/cache/babel-plugin-polyfill-corejs2-npm-0.3.1-43e6df66ff-ca873f14cc.zip deleted file mode 100644 index b7c9915cb..000000000 Binary files a/.yarn/cache/babel-plugin-polyfill-corejs2-npm-0.3.1-43e6df66ff-ca873f14cc.zip and /dev/null differ diff --git a/.yarn/cache/babel-plugin-polyfill-corejs2-npm-0.3.3-374b04c5be-7db3044993.zip b/.yarn/cache/babel-plugin-polyfill-corejs2-npm-0.3.3-374b04c5be-7db3044993.zip new file mode 100644 index 000000000..258349719 Binary files /dev/null and b/.yarn/cache/babel-plugin-polyfill-corejs2-npm-0.3.3-374b04c5be-7db3044993.zip differ diff --git a/.yarn/cache/babel-plugin-polyfill-corejs3-npm-0.5.2-b8b8ecbf76-2f3184c73f.zip b/.yarn/cache/babel-plugin-polyfill-corejs3-npm-0.5.2-b8b8ecbf76-2f3184c73f.zip deleted file mode 100644 index 25158c3c8..000000000 Binary files a/.yarn/cache/babel-plugin-polyfill-corejs3-npm-0.5.2-b8b8ecbf76-2f3184c73f.zip and /dev/null differ diff --git a/.yarn/cache/babel-plugin-polyfill-corejs3-npm-0.6.0-2d0edf85b8-470bb8c59f.zip b/.yarn/cache/babel-plugin-polyfill-corejs3-npm-0.6.0-2d0edf85b8-470bb8c59f.zip new file mode 100644 index 000000000..0b9ece33b Binary files /dev/null and b/.yarn/cache/babel-plugin-polyfill-corejs3-npm-0.6.0-2d0edf85b8-470bb8c59f.zip differ diff --git a/.yarn/cache/babel-plugin-polyfill-regenerator-npm-0.3.1-5ab9515a96-f1473df7b7.zip b/.yarn/cache/babel-plugin-polyfill-regenerator-npm-0.3.1-5ab9515a96-f1473df7b7.zip deleted file mode 100644 index 4d4a4e7e6..000000000 Binary files a/.yarn/cache/babel-plugin-polyfill-regenerator-npm-0.3.1-5ab9515a96-f1473df7b7.zip and /dev/null differ diff --git a/.yarn/cache/babel-plugin-polyfill-regenerator-npm-0.4.1-f2ab3efe27-ab0355efba.zip b/.yarn/cache/babel-plugin-polyfill-regenerator-npm-0.4.1-f2ab3efe27-ab0355efba.zip new file mode 100644 index 000000000..8d79321a2 Binary files /dev/null and b/.yarn/cache/babel-plugin-polyfill-regenerator-npm-0.4.1-f2ab3efe27-ab0355efba.zip differ diff --git a/.yarn/cache/babel-preset-jest-npm-28.1.1-05a1e38dd1-c581a81967.zip b/.yarn/cache/babel-preset-jest-npm-28.1.3-8e610faead-8248a4a5ca.zip similarity index 70% rename from .yarn/cache/babel-preset-jest-npm-28.1.1-05a1e38dd1-c581a81967.zip rename to .yarn/cache/babel-preset-jest-npm-28.1.3-8e610faead-8248a4a5ca.zip index 84bf3bfe6..72ed52192 100644 Binary files a/.yarn/cache/babel-preset-jest-npm-28.1.1-05a1e38dd1-c581a81967.zip and b/.yarn/cache/babel-preset-jest-npm-28.1.3-8e610faead-8248a4a5ca.zip differ diff --git a/.yarn/cache/before-after-hook-npm-2.2.2-b463f0552f-dc2e1ffe38.zip b/.yarn/cache/before-after-hook-npm-2.2.2-b463f0552f-dc2e1ffe38.zip deleted file mode 100644 index ca7bd8a72..000000000 Binary files a/.yarn/cache/before-after-hook-npm-2.2.2-b463f0552f-dc2e1ffe38.zip and /dev/null differ diff --git a/.yarn/cache/before-after-hook-npm-2.2.3-d79e3d6608-a1a2430976.zip b/.yarn/cache/before-after-hook-npm-2.2.3-d79e3d6608-a1a2430976.zip new file mode 100644 index 000000000..b03fd8f3e Binary files /dev/null and b/.yarn/cache/before-after-hook-npm-2.2.3-d79e3d6608-a1a2430976.zip differ diff --git a/.yarn/cache/body-parser-npm-1.20.0-1820eff49a-12fffdeac8.zip b/.yarn/cache/body-parser-npm-1.20.1-759fd14db9-f1050dbac3.zip similarity index 53% rename from .yarn/cache/body-parser-npm-1.20.0-1820eff49a-12fffdeac8.zip rename to .yarn/cache/body-parser-npm-1.20.1-759fd14db9-f1050dbac3.zip index 74cdc3074..00619628e 100644 Binary files a/.yarn/cache/body-parser-npm-1.20.0-1820eff49a-12fffdeac8.zip and b/.yarn/cache/body-parser-npm-1.20.1-759fd14db9-f1050dbac3.zip differ diff --git a/.yarn/cache/bonjour-service-npm-1.0.13-ed9b3adbfe-aee186f542.zip b/.yarn/cache/bonjour-service-npm-1.0.14-42da5d049d-4a825bbf18.zip similarity index 77% rename from .yarn/cache/bonjour-service-npm-1.0.13-ed9b3adbfe-aee186f542.zip rename to .yarn/cache/bonjour-service-npm-1.0.14-42da5d049d-4a825bbf18.zip index 8c4c2c514..b0db29aba 100644 Binary files a/.yarn/cache/bonjour-service-npm-1.0.13-ed9b3adbfe-aee186f542.zip and b/.yarn/cache/bonjour-service-npm-1.0.14-42da5d049d-4a825bbf18.zip differ diff --git a/.yarn/cache/bplist-creator-npm-0.1.0-f194332b98-d4ccd88ea1.zip b/.yarn/cache/bplist-creator-npm-0.1.1-46ec2e397c-b0d40d1d16.zip similarity index 91% rename from .yarn/cache/bplist-creator-npm-0.1.0-f194332b98-d4ccd88ea1.zip rename to .yarn/cache/bplist-creator-npm-0.1.1-46ec2e397c-b0d40d1d16.zip index 442890ddf..629c00cc5 100644 Binary files a/.yarn/cache/bplist-creator-npm-0.1.0-f194332b98-d4ccd88ea1.zip and b/.yarn/cache/bplist-creator-npm-0.1.1-46ec2e397c-b0d40d1d16.zip differ diff --git a/.yarn/cache/bplist-parser-npm-0.3.1-2ca33ea639-7cabc5bead.zip b/.yarn/cache/bplist-parser-npm-0.3.1-2ca33ea639-7cabc5bead.zip deleted file mode 100644 index 495113f59..000000000 Binary files a/.yarn/cache/bplist-parser-npm-0.3.1-2ca33ea639-7cabc5bead.zip and /dev/null differ diff --git a/.yarn/cache/bplist-parser-npm-0.3.2-94c89d7427-fad0f6eb15.zip b/.yarn/cache/bplist-parser-npm-0.3.2-94c89d7427-fad0f6eb15.zip new file mode 100644 index 000000000..d7747c8dc Binary files /dev/null and b/.yarn/cache/bplist-parser-npm-0.3.2-94c89d7427-fad0f6eb15.zip differ diff --git a/.yarn/cache/browserslist-npm-4.21.1-930e90b93a-4904a9ded0.zip b/.yarn/cache/browserslist-npm-4.21.1-930e90b93a-4904a9ded0.zip deleted file mode 100644 index 12cc79e60..000000000 Binary files a/.yarn/cache/browserslist-npm-4.21.1-930e90b93a-4904a9ded0.zip and /dev/null differ diff --git a/.yarn/cache/browserslist-npm-4.21.3-7dabe86a57-ff512a7bcc.zip b/.yarn/cache/browserslist-npm-4.21.4-7d64a96afc-4af3793704.zip similarity index 80% rename from .yarn/cache/browserslist-npm-4.21.3-7dabe86a57-ff512a7bcc.zip rename to .yarn/cache/browserslist-npm-4.21.4-7d64a96afc-4af3793704.zip index 7fd8bd259..581b52a18 100644 Binary files a/.yarn/cache/browserslist-npm-4.21.3-7dabe86a57-ff512a7bcc.zip and b/.yarn/cache/browserslist-npm-4.21.4-7d64a96afc-4af3793704.zip differ diff --git a/.yarn/cache/cacache-npm-16.1.1-84a00badf3-4885246170.zip b/.yarn/cache/cacache-npm-16.1.3-4e2088ed0d-d91409e6e5.zip similarity index 59% rename from .yarn/cache/cacache-npm-16.1.1-84a00badf3-4885246170.zip rename to .yarn/cache/cacache-npm-16.1.3-4e2088ed0d-d91409e6e5.zip index f677e5200..2bba5de79 100644 Binary files a/.yarn/cache/cacache-npm-16.1.1-84a00badf3-4885246170.zip and b/.yarn/cache/cacache-npm-16.1.3-4e2088ed0d-d91409e6e5.zip differ diff --git a/.yarn/cache/cacheable-lookup-npm-6.0.4-fe6f8fb6da-7aea70f5ea.zip b/.yarn/cache/cacheable-lookup-npm-6.0.4-fe6f8fb6da-7aea70f5ea.zip deleted file mode 100644 index 0f25ad378..000000000 Binary files a/.yarn/cache/cacheable-lookup-npm-6.0.4-fe6f8fb6da-7aea70f5ea.zip and /dev/null differ diff --git a/.yarn/cache/cacheable-lookup-npm-7.0.0-b6cd95c14a-9e2856763f.zip b/.yarn/cache/cacheable-lookup-npm-7.0.0-b6cd95c14a-9e2856763f.zip new file mode 100644 index 000000000..346938bab Binary files /dev/null and b/.yarn/cache/cacheable-lookup-npm-7.0.0-b6cd95c14a-9e2856763f.zip differ diff --git a/.yarn/cache/cacheable-request-npm-10.2.1-905f8188a4-11bcee52d6.zip b/.yarn/cache/cacheable-request-npm-10.2.1-905f8188a4-11bcee52d6.zip new file mode 100644 index 000000000..1a2827593 Binary files /dev/null and b/.yarn/cache/cacheable-request-npm-10.2.1-905f8188a4-11bcee52d6.zip differ diff --git a/.yarn/cache/cacheable-request-npm-7.0.2-e64cc641fc-6152813982.zip b/.yarn/cache/cacheable-request-npm-7.0.2-e64cc641fc-6152813982.zip deleted file mode 100644 index 440f866df..000000000 Binary files a/.yarn/cache/cacheable-request-npm-7.0.2-e64cc641fc-6152813982.zip and /dev/null differ diff --git a/.yarn/cache/camelize-npm-1.0.0-5eda108776-769f8d1007.zip b/.yarn/cache/camelize-npm-1.0.0-5eda108776-769f8d1007.zip deleted file mode 100644 index d58e6e1b7..000000000 Binary files a/.yarn/cache/camelize-npm-1.0.0-5eda108776-769f8d1007.zip and /dev/null differ diff --git a/.yarn/cache/camelize-npm-1.0.1-d86ebe085a-91d8611d09.zip b/.yarn/cache/camelize-npm-1.0.1-d86ebe085a-91d8611d09.zip new file mode 100644 index 000000000..81cef64d2 Binary files /dev/null and b/.yarn/cache/camelize-npm-1.0.1-d86ebe085a-91d8611d09.zip differ diff --git a/.yarn/cache/caniuse-lite-npm-1.0.30001363-33f2768163-8dfcb2fa97.zip b/.yarn/cache/caniuse-lite-npm-1.0.30001363-33f2768163-8dfcb2fa97.zip deleted file mode 100644 index 60d61780f..000000000 Binary files a/.yarn/cache/caniuse-lite-npm-1.0.30001363-33f2768163-8dfcb2fa97.zip and /dev/null differ diff --git a/.yarn/cache/caniuse-lite-npm-1.0.30001399-96a5592f00-dd105b06fb.zip b/.yarn/cache/caniuse-lite-npm-1.0.30001399-96a5592f00-dd105b06fb.zip deleted file mode 100644 index e76dc2df7..000000000 Binary files a/.yarn/cache/caniuse-lite-npm-1.0.30001399-96a5592f00-dd105b06fb.zip and /dev/null differ diff --git a/.yarn/cache/caniuse-lite-npm-1.0.30001419-f5202d11f6-7a4dc2794a.zip b/.yarn/cache/caniuse-lite-npm-1.0.30001419-f5202d11f6-7a4dc2794a.zip new file mode 100644 index 000000000..876174bc3 Binary files /dev/null and b/.yarn/cache/caniuse-lite-npm-1.0.30001419-f5202d11f6-7a4dc2794a.zip differ diff --git a/.yarn/cache/capture-stack-trace-npm-1.0.1-0ffa4b6380-493668211d.zip b/.yarn/cache/capture-stack-trace-npm-1.0.1-0ffa4b6380-493668211d.zip deleted file mode 100644 index dced92f79..000000000 Binary files a/.yarn/cache/capture-stack-trace-npm-1.0.1-0ffa4b6380-493668211d.zip and /dev/null differ diff --git a/.yarn/cache/capture-stack-trace-npm-1.0.2-58ba7644bb-13295e8176.zip b/.yarn/cache/capture-stack-trace-npm-1.0.2-58ba7644bb-13295e8176.zip new file mode 100644 index 000000000..99a515248 Binary files /dev/null and b/.yarn/cache/capture-stack-trace-npm-1.0.2-58ba7644bb-13295e8176.zip differ diff --git a/.yarn/cache/chalk-npm-5.0.1-6afcb94227-7b45300372.zip b/.yarn/cache/chalk-npm-5.0.1-6afcb94227-7b45300372.zip deleted file mode 100644 index 6e33620bb..000000000 Binary files a/.yarn/cache/chalk-npm-5.0.1-6afcb94227-7b45300372.zip and /dev/null differ diff --git a/.yarn/cache/chalk-npm-5.1.2-221d111371-804d7485e3.zip b/.yarn/cache/chalk-npm-5.1.2-221d111371-804d7485e3.zip new file mode 100644 index 000000000..8d4ecc8b2 Binary files /dev/null and b/.yarn/cache/chalk-npm-5.1.2-221d111371-804d7485e3.zip differ diff --git a/.yarn/cache/ci-info-npm-3.3.2-fb5617e149-fd81f1edd2.zip b/.yarn/cache/ci-info-npm-3.3.2-fb5617e149-fd81f1edd2.zip deleted file mode 100644 index d02ab0334..000000000 Binary files a/.yarn/cache/ci-info-npm-3.3.2-fb5617e149-fd81f1edd2.zip and /dev/null differ diff --git a/.yarn/cache/ci-info-npm-3.5.0-9f42814be7-7def378970.zip b/.yarn/cache/ci-info-npm-3.5.0-9f42814be7-7def378970.zip new file mode 100644 index 000000000..72692cac0 Binary files /dev/null and b/.yarn/cache/ci-info-npm-3.5.0-9f42814be7-7def378970.zip differ diff --git a/.yarn/cache/clean-css-npm-5.3.0-8dc6397d0c-29e15ef467.zip b/.yarn/cache/clean-css-npm-5.3.1-e052e24a9f-860696c605.zip similarity index 82% rename from .yarn/cache/clean-css-npm-5.3.0-8dc6397d0c-29e15ef467.zip rename to .yarn/cache/clean-css-npm-5.3.1-e052e24a9f-860696c605.zip index 3a2435143..fc3fc4802 100644 Binary files a/.yarn/cache/clean-css-npm-5.3.0-8dc6397d0c-29e15ef467.zip and b/.yarn/cache/clean-css-npm-5.3.1-e052e24a9f-860696c605.zip differ diff --git a/.yarn/cache/cli-spinners-npm-2.6.1-33ce2bad0f-423409baaa.zip b/.yarn/cache/cli-spinners-npm-2.6.1-33ce2bad0f-423409baaa.zip deleted file mode 100644 index 485c09ed3..000000000 Binary files a/.yarn/cache/cli-spinners-npm-2.6.1-33ce2bad0f-423409baaa.zip and /dev/null differ diff --git a/.yarn/cache/cli-spinners-npm-2.7.0-ace95632f5-a9afaf73f5.zip b/.yarn/cache/cli-spinners-npm-2.7.0-ace95632f5-a9afaf73f5.zip new file mode 100644 index 000000000..b85b7fcce Binary files /dev/null and b/.yarn/cache/cli-spinners-npm-2.7.0-ace95632f5-a9afaf73f5.zip differ diff --git a/.yarn/cache/cli-table3-npm-0.6.2-dff919b99d-2f82391698.zip b/.yarn/cache/cli-table3-npm-0.6.2-dff919b99d-2f82391698.zip deleted file mode 100644 index d6059a7bf..000000000 Binary files a/.yarn/cache/cli-table3-npm-0.6.2-dff919b99d-2f82391698.zip and /dev/null differ diff --git a/.yarn/cache/cli-table3-npm-0.6.3-1dca7f9152-09897f6846.zip b/.yarn/cache/cli-table3-npm-0.6.3-1dca7f9152-09897f6846.zip new file mode 100644 index 000000000..d57566947 Binary files /dev/null and b/.yarn/cache/cli-table3-npm-0.6.3-1dca7f9152-09897f6846.zip differ diff --git a/.yarn/cache/cliui-npm-8.0.1-3b029092cf-79648b3b00.zip b/.yarn/cache/cliui-npm-8.0.1-3b029092cf-79648b3b00.zip new file mode 100644 index 000000000..a90643c5e Binary files /dev/null and b/.yarn/cache/cliui-npm-8.0.1-3b029092cf-79648b3b00.zip differ diff --git a/.yarn/cache/clone-response-npm-1.0.2-135ae8239d-2d0e61547f.zip b/.yarn/cache/clone-response-npm-1.0.2-135ae8239d-2d0e61547f.zip deleted file mode 100644 index 5b5af5351..000000000 Binary files a/.yarn/cache/clone-response-npm-1.0.2-135ae8239d-2d0e61547f.zip and /dev/null differ diff --git a/.yarn/cache/clone-response-npm-1.0.3-f71cb6aff5-4e671cac39.zip b/.yarn/cache/clone-response-npm-1.0.3-f71cb6aff5-4e671cac39.zip new file mode 100644 index 000000000..020cff2ac Binary files /dev/null and b/.yarn/cache/clone-response-npm-1.0.3-f71cb6aff5-4e671cac39.zip differ diff --git a/.yarn/cache/clsx-npm-1.2.0-4e65d720ee-551a0b4f18.zip b/.yarn/cache/clsx-npm-1.2.1-77792dc182-30befca801.zip similarity index 53% rename from .yarn/cache/clsx-npm-1.2.0-4e65d720ee-551a0b4f18.zip rename to .yarn/cache/clsx-npm-1.2.1-77792dc182-30befca801.zip index 25ffe761f..4f1dff8ef 100644 Binary files a/.yarn/cache/clsx-npm-1.2.0-4e65d720ee-551a0b4f18.zip and b/.yarn/cache/clsx-npm-1.2.1-77792dc182-30befca801.zip differ diff --git a/.yarn/cache/codemirror-npm-5.65.6-2d74e8af09-d65aa28af0.zip b/.yarn/cache/codemirror-npm-5.65.9-95f0ac2341-bbdb3991d4.zip similarity index 62% rename from .yarn/cache/codemirror-npm-5.65.6-2d74e8af09-d65aa28af0.zip rename to .yarn/cache/codemirror-npm-5.65.9-95f0ac2341-bbdb3991d4.zip index 86085d646..023f50035 100644 Binary files a/.yarn/cache/codemirror-npm-5.65.6-2d74e8af09-d65aa28af0.zip and b/.yarn/cache/codemirror-npm-5.65.9-95f0ac2341-bbdb3991d4.zip differ diff --git a/.yarn/cache/color-npm-4.2.3-4a23227581-0579629c02.zip b/.yarn/cache/color-npm-4.2.3-4a23227581-0579629c02.zip deleted file mode 100644 index cca7ea310..000000000 Binary files a/.yarn/cache/color-npm-4.2.3-4a23227581-0579629c02.zip and /dev/null differ diff --git a/.yarn/cache/colord-npm-2.9.2-5b43cbb043-2aa6a9b3ab.zip b/.yarn/cache/colord-npm-2.9.3-5c35c27898-95d909bfbc.zip similarity index 87% rename from .yarn/cache/colord-npm-2.9.2-5b43cbb043-2aa6a9b3ab.zip rename to .yarn/cache/colord-npm-2.9.3-5c35c27898-95d909bfbc.zip index fd7a89f5b..9a082cebf 100644 Binary files a/.yarn/cache/colord-npm-2.9.2-5b43cbb043-2aa6a9b3ab.zip and b/.yarn/cache/colord-npm-2.9.3-5c35c27898-95d909bfbc.zip differ diff --git a/.yarn/cache/commander-npm-9.3.0-1393a6e1f6-d421ce66fe.zip b/.yarn/cache/commander-npm-9.3.0-1393a6e1f6-d421ce66fe.zip deleted file mode 100644 index 7bfdb5365..000000000 Binary files a/.yarn/cache/commander-npm-9.3.0-1393a6e1f6-d421ce66fe.zip and /dev/null differ diff --git a/.yarn/cache/commander-npm-9.4.1-9deffb2749-bfb18e325a.zip b/.yarn/cache/commander-npm-9.4.1-9deffb2749-bfb18e325a.zip new file mode 100644 index 000000000..81a9ce607 Binary files /dev/null and b/.yarn/cache/commander-npm-9.4.1-9deffb2749-bfb18e325a.zip differ diff --git a/.yarn/cache/compare-versions-npm-4.1.3-d4c4a7f412-54460756ab.zip b/.yarn/cache/compare-versions-npm-4.1.4-7ea14e31a1-c1617544b7.zip similarity index 78% rename from .yarn/cache/compare-versions-npm-4.1.3-d4c4a7f412-54460756ab.zip rename to .yarn/cache/compare-versions-npm-4.1.4-7ea14e31a1-c1617544b7.zip index db4910381..047ee29cd 100644 Binary files a/.yarn/cache/compare-versions-npm-4.1.3-d4c4a7f412-54460756ab.zip and b/.yarn/cache/compare-versions-npm-4.1.4-7ea14e31a1-c1617544b7.zip differ diff --git a/.yarn/cache/compress-brotli-npm-1.3.8-9b6ceac281-de7589d692.zip b/.yarn/cache/compress-brotli-npm-1.3.8-9b6ceac281-de7589d692.zip deleted file mode 100644 index 411a49e4e..000000000 Binary files a/.yarn/cache/compress-brotli-npm-1.3.8-9b6ceac281-de7589d692.zip and /dev/null differ diff --git a/.yarn/cache/convert-source-map-npm-1.8.0-037f671dde-985d974a2d.zip b/.yarn/cache/convert-source-map-npm-1.8.0-037f671dde-985d974a2d.zip deleted file mode 100644 index 00cffe534..000000000 Binary files a/.yarn/cache/convert-source-map-npm-1.8.0-037f671dde-985d974a2d.zip and /dev/null differ diff --git a/.yarn/cache/convert-source-map-npm-1.9.0-e294555f4b-dc55a1f28d.zip b/.yarn/cache/convert-source-map-npm-1.9.0-e294555f4b-dc55a1f28d.zip new file mode 100644 index 000000000..409c3442c Binary files /dev/null and b/.yarn/cache/convert-source-map-npm-1.9.0-e294555f4b-dc55a1f28d.zip differ diff --git a/.yarn/cache/core-js-compat-npm-3.23.3-1a3ce4fd9f-a5fd680a31.zip b/.yarn/cache/core-js-compat-npm-3.23.3-1a3ce4fd9f-a5fd680a31.zip deleted file mode 100644 index f4b2c05dd..000000000 Binary files a/.yarn/cache/core-js-compat-npm-3.23.3-1a3ce4fd9f-a5fd680a31.zip and /dev/null differ diff --git a/.yarn/cache/core-js-compat-npm-3.25.5-085d444501-30686b750d.zip b/.yarn/cache/core-js-compat-npm-3.25.5-085d444501-30686b750d.zip new file mode 100644 index 000000000..7e2b9b376 Binary files /dev/null and b/.yarn/cache/core-js-compat-npm-3.25.5-085d444501-30686b750d.zip differ diff --git a/.yarn/cache/core-js-npm-3.23.3-83cb265bcd-f517546388.zip b/.yarn/cache/core-js-npm-3.25.5-a4ed2eca5b-208b308c49.zip similarity index 61% rename from .yarn/cache/core-js-npm-3.23.3-83cb265bcd-f517546388.zip rename to .yarn/cache/core-js-npm-3.25.5-a4ed2eca5b-208b308c49.zip index 561b1ea91..a0c5454d9 100644 Binary files a/.yarn/cache/core-js-npm-3.23.3-83cb265bcd-f517546388.zip and b/.yarn/cache/core-js-npm-3.25.5-a4ed2eca5b-208b308c49.zip differ diff --git a/.yarn/cache/core-js-pure-npm-3.23.3-e00f2fa9ac-09a477a569.zip b/.yarn/cache/core-js-pure-npm-3.25.5-aaaed61bed-e48799a8ab.zip similarity index 62% rename from .yarn/cache/core-js-pure-npm-3.23.3-e00f2fa9ac-09a477a569.zip rename to .yarn/cache/core-js-pure-npm-3.25.5-aaaed61bed-e48799a8ab.zip index b00b785b7..42380d926 100644 Binary files a/.yarn/cache/core-js-pure-npm-3.23.3-e00f2fa9ac-09a477a569.zip and b/.yarn/cache/core-js-pure-npm-3.25.5-aaaed61bed-e48799a8ab.zip differ diff --git a/.yarn/cache/cosmiconfig-typescript-loader-npm-2.0.2-6811bc8e72-0c9a777e2e.zip b/.yarn/cache/cosmiconfig-typescript-loader-npm-2.0.2-6811bc8e72-0c9a777e2e.zip deleted file mode 100644 index b21c6cbda..000000000 Binary files a/.yarn/cache/cosmiconfig-typescript-loader-npm-2.0.2-6811bc8e72-0c9a777e2e.zip and /dev/null differ diff --git a/.yarn/cache/cosmiconfig-typescript-loader-npm-4.1.1-77b25222d1-a774961868.zip b/.yarn/cache/cosmiconfig-typescript-loader-npm-4.1.1-77b25222d1-a774961868.zip new file mode 100644 index 000000000..72b59babd Binary files /dev/null and b/.yarn/cache/cosmiconfig-typescript-loader-npm-4.1.1-77b25222d1-a774961868.zip differ diff --git a/.yarn/cache/css-declaration-sorter-npm-6.3.0-4e1c2237c9-69ce1c2e0e.zip b/.yarn/cache/css-declaration-sorter-npm-6.3.0-4e1c2237c9-69ce1c2e0e.zip deleted file mode 100644 index 9da5d9716..000000000 Binary files a/.yarn/cache/css-declaration-sorter-npm-6.3.0-4e1c2237c9-69ce1c2e0e.zip and /dev/null differ diff --git a/.yarn/cache/css-declaration-sorter-npm-6.3.1-06bf8d7c1c-ff0d9989ee.zip b/.yarn/cache/css-declaration-sorter-npm-6.3.1-06bf8d7c1c-ff0d9989ee.zip new file mode 100644 index 000000000..f299203b3 Binary files /dev/null and b/.yarn/cache/css-declaration-sorter-npm-6.3.1-06bf8d7c1c-ff0d9989ee.zip differ diff --git a/.yarn/cache/css-minimizer-webpack-plugin-npm-4.0.0-3fa970ae07-18487ee9aa.zip b/.yarn/cache/css-minimizer-webpack-plugin-npm-4.0.0-3fa970ae07-18487ee9aa.zip deleted file mode 100644 index f2ff7cc69..000000000 Binary files a/.yarn/cache/css-minimizer-webpack-plugin-npm-4.0.0-3fa970ae07-18487ee9aa.zip and /dev/null differ diff --git a/.yarn/cache/css-minimizer-webpack-plugin-npm-4.2.1-ff8893d0eb-d7de086b6e.zip b/.yarn/cache/css-minimizer-webpack-plugin-npm-4.2.1-ff8893d0eb-d7de086b6e.zip new file mode 100644 index 000000000..ba30ab72c Binary files /dev/null and b/.yarn/cache/css-minimizer-webpack-plugin-npm-4.2.1-ff8893d0eb-d7de086b6e.zip differ diff --git a/.yarn/cache/css-npm-3.0.0-ef426b63b3-4273ac816d.zip b/.yarn/cache/css-npm-3.0.0-ef426b63b3-4273ac816d.zip deleted file mode 100644 index 60a324543..000000000 Binary files a/.yarn/cache/css-npm-3.0.0-ef426b63b3-4273ac816d.zip and /dev/null differ diff --git a/.yarn/cache/cssdb-npm-6.6.3-a33ff6af5c-0d5bd77bbf.zip b/.yarn/cache/cssdb-npm-6.6.3-a33ff6af5c-0d5bd77bbf.zip deleted file mode 100644 index 5bab72a8c..000000000 Binary files a/.yarn/cache/cssdb-npm-6.6.3-a33ff6af5c-0d5bd77bbf.zip and /dev/null differ diff --git a/.yarn/cache/cssdb-npm-7.0.1-215a5ab052-4b4de59864.zip b/.yarn/cache/cssdb-npm-7.0.1-215a5ab052-4b4de59864.zip new file mode 100644 index 000000000..235b73052 Binary files /dev/null and b/.yarn/cache/cssdb-npm-7.0.1-215a5ab052-4b4de59864.zip differ diff --git a/.yarn/cache/cssnano-npm-5.1.12-053744178f-5bc6a6195e.zip b/.yarn/cache/cssnano-npm-5.1.13-15b03b6fab-3af0810c98.zip similarity index 88% rename from .yarn/cache/cssnano-npm-5.1.12-053744178f-5bc6a6195e.zip rename to .yarn/cache/cssnano-npm-5.1.13-15b03b6fab-3af0810c98.zip index f001a7614..c18d46687 100644 Binary files a/.yarn/cache/cssnano-npm-5.1.12-053744178f-5bc6a6195e.zip and b/.yarn/cache/cssnano-npm-5.1.13-15b03b6fab-3af0810c98.zip differ diff --git a/.yarn/cache/csstype-npm-3.1.0-0e405212e2-644e986cef.zip b/.yarn/cache/csstype-npm-3.1.0-0e405212e2-644e986cef.zip deleted file mode 100644 index 4f5cda617..000000000 Binary files a/.yarn/cache/csstype-npm-3.1.0-0e405212e2-644e986cef.zip and /dev/null differ diff --git a/.yarn/cache/csstype-npm-3.1.1-3857baf48b-1f7b4f5fdd.zip b/.yarn/cache/csstype-npm-3.1.1-3857baf48b-1f7b4f5fdd.zip new file mode 100644 index 000000000..8cf431c8f Binary files /dev/null and b/.yarn/cache/csstype-npm-3.1.1-3857baf48b-1f7b4f5fdd.zip differ diff --git a/.yarn/cache/dayjs-npm-1.11.3-88985d494e-c87e06b562.zip b/.yarn/cache/dayjs-npm-1.11.3-88985d494e-c87e06b562.zip deleted file mode 100644 index 09587dda9..000000000 Binary files a/.yarn/cache/dayjs-npm-1.11.3-88985d494e-c87e06b562.zip and /dev/null differ diff --git a/.yarn/cache/decimal.js-npm-10.3.1-797c736b6c-0351ac9f05.zip b/.yarn/cache/decimal.js-npm-10.3.1-797c736b6c-0351ac9f05.zip deleted file mode 100644 index 585ed75c0..000000000 Binary files a/.yarn/cache/decimal.js-npm-10.3.1-797c736b6c-0351ac9f05.zip and /dev/null differ diff --git a/.yarn/cache/decimal.js-npm-10.4.2-0119c97ba5-536cd6816a.zip b/.yarn/cache/decimal.js-npm-10.4.2-0119c97ba5-536cd6816a.zip new file mode 100644 index 000000000..43de39555 Binary files /dev/null and b/.yarn/cache/decimal.js-npm-10.4.2-0119c97ba5-536cd6816a.zip differ diff --git a/.yarn/cache/defaults-npm-1.0.3-e829107b9e-96e2112da6.zip b/.yarn/cache/defaults-npm-1.0.3-e829107b9e-96e2112da6.zip deleted file mode 100644 index 0b0bc1beb..000000000 Binary files a/.yarn/cache/defaults-npm-1.0.3-e829107b9e-96e2112da6.zip and /dev/null differ diff --git a/.yarn/cache/defaults-npm-1.0.4-f3fbaf2528-3a88b7a587.zip b/.yarn/cache/defaults-npm-1.0.4-f3fbaf2528-3a88b7a587.zip new file mode 100644 index 000000000..cbd9cc402 Binary files /dev/null and b/.yarn/cache/defaults-npm-1.0.4-f3fbaf2528-3a88b7a587.zip differ diff --git a/.yarn/cache/defined-npm-1.0.0-891782ba77-77672997c5.zip b/.yarn/cache/defined-npm-1.0.0-891782ba77-77672997c5.zip deleted file mode 100644 index c2fc980e6..000000000 Binary files a/.yarn/cache/defined-npm-1.0.0-891782ba77-77672997c5.zip and /dev/null differ diff --git a/.yarn/cache/defined-npm-1.0.1-7471d27847-b1a852300b.zip b/.yarn/cache/defined-npm-1.0.1-7471d27847-b1a852300b.zip new file mode 100644 index 000000000..04752f7f2 Binary files /dev/null and b/.yarn/cache/defined-npm-1.0.1-7471d27847-b1a852300b.zip differ diff --git a/.yarn/cache/dequal-npm-2.0.2-370927eb6c-86c7a2c59f.zip b/.yarn/cache/dequal-npm-2.0.3-53a630c60e-8679b850e1.zip similarity index 75% rename from .yarn/cache/dequal-npm-2.0.2-370927eb6c-86c7a2c59f.zip rename to .yarn/cache/dequal-npm-2.0.3-53a630c60e-8679b850e1.zip index 3cc355b6f..77213918f 100644 Binary files a/.yarn/cache/dequal-npm-2.0.2-370927eb6c-86c7a2c59f.zip and b/.yarn/cache/dequal-npm-2.0.3-53a630c60e-8679b850e1.zip differ diff --git a/.yarn/cache/detect-port-npm-1.3.0-9bd72802b4-93c40febe7.zip b/.yarn/cache/detect-port-npm-1.3.0-9bd72802b4-93c40febe7.zip deleted file mode 100644 index 7675377db..000000000 Binary files a/.yarn/cache/detect-port-npm-1.3.0-9bd72802b4-93c40febe7.zip and /dev/null differ diff --git a/.yarn/cache/detect-port-npm-1.5.1-fbb9694f69-b48da93404.zip b/.yarn/cache/detect-port-npm-1.5.1-fbb9694f69-b48da93404.zip new file mode 100644 index 000000000..c6253164f Binary files /dev/null and b/.yarn/cache/detect-port-npm-1.5.1-fbb9694f69-b48da93404.zip differ diff --git a/.yarn/cache/detox-npm-19.7.1-0e55e462fb-6f82c2642f.zip b/.yarn/cache/detox-npm-19.12.5-72644b4e85-b4ce730928.zip similarity index 52% rename from .yarn/cache/detox-npm-19.7.1-0e55e462fb-6f82c2642f.zip rename to .yarn/cache/detox-npm-19.12.5-72644b4e85-b4ce730928.zip index d627ba85d..7f0896979 100644 Binary files a/.yarn/cache/detox-npm-19.7.1-0e55e462fb-6f82c2642f.zip and b/.yarn/cache/detox-npm-19.12.5-72644b4e85-b4ce730928.zip differ diff --git a/.yarn/cache/dompurify-npm-2.3.8-c4b696b00d-dc7b32ee57.zip b/.yarn/cache/dompurify-npm-2.3.8-c4b696b00d-dc7b32ee57.zip deleted file mode 100644 index cb2cd423a..000000000 Binary files a/.yarn/cache/dompurify-npm-2.3.8-c4b696b00d-dc7b32ee57.zip and /dev/null differ diff --git a/.yarn/cache/dompurify-npm-2.4.0-0ffecf22ef-c93ea73cf8.zip b/.yarn/cache/dompurify-npm-2.4.0-0ffecf22ef-c93ea73cf8.zip new file mode 100644 index 000000000..a92551334 Binary files /dev/null and b/.yarn/cache/dompurify-npm-2.4.0-0ffecf22ef-c93ea73cf8.zip differ diff --git a/.yarn/cache/dotenv-npm-16.0.1-d99e72bb95-f459ffce07.zip b/.yarn/cache/dotenv-npm-16.0.1-d99e72bb95-f459ffce07.zip deleted file mode 100644 index f69b23680..000000000 Binary files a/.yarn/cache/dotenv-npm-16.0.1-d99e72bb95-f459ffce07.zip and /dev/null differ diff --git a/.yarn/cache/dotenv-npm-16.0.2-80af4821b1-ca8f9ca2d6.zip b/.yarn/cache/dotenv-npm-16.0.2-80af4821b1-ca8f9ca2d6.zip deleted file mode 100644 index 3d7b94014..000000000 Binary files a/.yarn/cache/dotenv-npm-16.0.2-80af4821b1-ca8f9ca2d6.zip and /dev/null differ diff --git a/.yarn/cache/dotenv-npm-16.0.3-4cc29121dc-afcf03f373.zip b/.yarn/cache/dotenv-npm-16.0.3-4cc29121dc-afcf03f373.zip new file mode 100644 index 000000000..90a95535b Binary files /dev/null and b/.yarn/cache/dotenv-npm-16.0.3-4cc29121dc-afcf03f373.zip differ diff --git a/.yarn/cache/duplexer3-npm-0.1.4-361a33d994-c2fd696931.zip b/.yarn/cache/duplexer3-npm-0.1.4-361a33d994-c2fd696931.zip deleted file mode 100644 index 858d0a852..000000000 Binary files a/.yarn/cache/duplexer3-npm-0.1.4-361a33d994-c2fd696931.zip and /dev/null differ diff --git a/.yarn/cache/duplexer3-npm-0.1.5-343d4ab7e3-e677cb4c48.zip b/.yarn/cache/duplexer3-npm-0.1.5-343d4ab7e3-e677cb4c48.zip new file mode 100644 index 000000000..041c03e93 Binary files /dev/null and b/.yarn/cache/duplexer3-npm-0.1.5-343d4ab7e3-e677cb4c48.zip differ diff --git a/.yarn/cache/electron-to-chromium-npm-1.4.179-f4759f42ff-e31691dd0f.zip b/.yarn/cache/electron-to-chromium-npm-1.4.179-f4759f42ff-e31691dd0f.zip deleted file mode 100644 index 85c3ed6e1..000000000 Binary files a/.yarn/cache/electron-to-chromium-npm-1.4.179-f4759f42ff-e31691dd0f.zip and /dev/null differ diff --git a/.yarn/cache/electron-to-chromium-npm-1.4.248-7d88493fa1-b90e572aef.zip b/.yarn/cache/electron-to-chromium-npm-1.4.248-7d88493fa1-b90e572aef.zip deleted file mode 100644 index a860cd335..000000000 Binary files a/.yarn/cache/electron-to-chromium-npm-1.4.248-7d88493fa1-b90e572aef.zip and /dev/null differ diff --git a/.yarn/cache/electron-to-chromium-npm-1.4.281-2181cd779e-8c64a7b8a6.zip b/.yarn/cache/electron-to-chromium-npm-1.4.281-2181cd779e-8c64a7b8a6.zip new file mode 100644 index 000000000..61f311cc7 Binary files /dev/null and b/.yarn/cache/electron-to-chromium-npm-1.4.281-2181cd779e-8c64a7b8a6.zip differ diff --git a/.yarn/cache/electron-updater-npm-5.2.4-7761696fec-7fdda386f2.zip b/.yarn/cache/electron-updater-npm-5.3.0-451ef3ebab-975381ffb0.zip similarity index 79% rename from .yarn/cache/electron-updater-npm-5.2.4-7761696fec-7fdda386f2.zip rename to .yarn/cache/electron-updater-npm-5.3.0-451ef3ebab-975381ffb0.zip index f9105749d..900b736a8 100644 Binary files a/.yarn/cache/electron-updater-npm-5.2.4-7761696fec-7fdda386f2.zip and b/.yarn/cache/electron-updater-npm-5.3.0-451ef3ebab-975381ffb0.zip differ diff --git a/.yarn/cache/entities-npm-3.0.1-21eeb201ba-aaf7f12033.zip b/.yarn/cache/entities-npm-3.0.1-21eeb201ba-aaf7f12033.zip deleted file mode 100644 index 78991fcd2..000000000 Binary files a/.yarn/cache/entities-npm-3.0.1-21eeb201ba-aaf7f12033.zip and /dev/null differ diff --git a/.yarn/cache/entities-npm-4.3.1-3a76d89ee3-e8f6d2bac2.zip b/.yarn/cache/entities-npm-4.3.1-3a76d89ee3-e8f6d2bac2.zip deleted file mode 100644 index e916792a5..000000000 Binary files a/.yarn/cache/entities-npm-4.3.1-3a76d89ee3-e8f6d2bac2.zip and /dev/null differ diff --git a/.yarn/cache/entities-npm-4.4.0-97635dc5cc-84d250329f.zip b/.yarn/cache/entities-npm-4.4.0-97635dc5cc-84d250329f.zip new file mode 100644 index 000000000..4509c223f Binary files /dev/null and b/.yarn/cache/entities-npm-4.4.0-97635dc5cc-84d250329f.zip differ diff --git a/.yarn/cache/es-abstract-npm-1.20.1-83d41a4d88-28da27ae0e.zip b/.yarn/cache/es-abstract-npm-1.20.4-543318afab-89297cc785.zip similarity index 85% rename from .yarn/cache/es-abstract-npm-1.20.1-83d41a4d88-28da27ae0e.zip rename to .yarn/cache/es-abstract-npm-1.20.4-543318afab-89297cc785.zip index 2e35daef6..25c78c9c3 100644 Binary files a/.yarn/cache/es-abstract-npm-1.20.1-83d41a4d88-28da27ae0e.zip and b/.yarn/cache/es-abstract-npm-1.20.4-543318afab-89297cc785.zip differ diff --git a/.yarn/cache/eslint-module-utils-npm-2.7.3-ccd32fe6fd-77048263f3.zip b/.yarn/cache/eslint-module-utils-npm-2.7.3-ccd32fe6fd-77048263f3.zip deleted file mode 100644 index 647dc4960..000000000 Binary files a/.yarn/cache/eslint-module-utils-npm-2.7.3-ccd32fe6fd-77048263f3.zip and /dev/null differ diff --git a/.yarn/cache/eslint-module-utils-npm-2.7.4-a1640084cb-5da13645da.zip b/.yarn/cache/eslint-module-utils-npm-2.7.4-a1640084cb-5da13645da.zip new file mode 100644 index 000000000..005d442b0 Binary files /dev/null and b/.yarn/cache/eslint-module-utils-npm-2.7.4-a1640084cb-5da13645da.zip differ diff --git a/.yarn/cache/eslint-npm-8.19.0-147f1e0c86-0bc9df1a3a.zip b/.yarn/cache/eslint-npm-8.19.0-147f1e0c86-0bc9df1a3a.zip deleted file mode 100644 index 26e088b30..000000000 Binary files a/.yarn/cache/eslint-npm-8.19.0-147f1e0c86-0bc9df1a3a.zip and /dev/null differ diff --git a/.yarn/cache/eslint-npm-8.23.0-4ce1a8504a-ff6075daa2.zip b/.yarn/cache/eslint-npm-8.23.0-4ce1a8504a-ff6075daa2.zip deleted file mode 100644 index bbe836d3d..000000000 Binary files a/.yarn/cache/eslint-npm-8.23.0-4ce1a8504a-ff6075daa2.zip and /dev/null differ diff --git a/.yarn/cache/eslint-npm-8.23.1-bc9a4812f6-a727e15492.zip b/.yarn/cache/eslint-npm-8.25.0-2af5e4f121-7acf2693b5.zip similarity index 86% rename from .yarn/cache/eslint-npm-8.23.1-bc9a4812f6-a727e15492.zip rename to .yarn/cache/eslint-npm-8.25.0-2af5e4f121-7acf2693b5.zip index fdfdbfd03..0c04e028f 100644 Binary files a/.yarn/cache/eslint-npm-8.23.1-bc9a4812f6-a727e15492.zip and b/.yarn/cache/eslint-npm-8.25.0-2af5e4f121-7acf2693b5.zip differ diff --git a/.yarn/cache/eslint-plugin-ft-flow-npm-2.0.1-96fad0382c-f9519a9d93.zip b/.yarn/cache/eslint-plugin-ft-flow-npm-2.0.1-96fad0382c-f9519a9d93.zip new file mode 100644 index 000000000..cb4b517c0 Binary files /dev/null and b/.yarn/cache/eslint-plugin-ft-flow-npm-2.0.1-96fad0382c-f9519a9d93.zip differ diff --git a/.yarn/cache/eslint-plugin-jest-npm-26.9.0-865b788669-6d5fd5c953.zip b/.yarn/cache/eslint-plugin-jest-npm-26.9.0-865b788669-6d5fd5c953.zip new file mode 100644 index 000000000..ec02046a4 Binary files /dev/null and b/.yarn/cache/eslint-plugin-jest-npm-26.9.0-865b788669-6d5fd5c953.zip differ diff --git a/.yarn/cache/eslint-plugin-jsx-a11y-npm-6.6.0-c2d75b6ce4-d9da9a3ec7.zip b/.yarn/cache/eslint-plugin-jsx-a11y-npm-6.6.1-02552a3ea2-baae7377f0.zip similarity index 81% rename from .yarn/cache/eslint-plugin-jsx-a11y-npm-6.6.0-c2d75b6ce4-d9da9a3ec7.zip rename to .yarn/cache/eslint-plugin-jsx-a11y-npm-6.6.1-02552a3ea2-baae7377f0.zip index 58503d0b7..8f8019f24 100644 Binary files a/.yarn/cache/eslint-plugin-jsx-a11y-npm-6.6.0-c2d75b6ce4-d9da9a3ec7.zip and b/.yarn/cache/eslint-plugin-jsx-a11y-npm-6.6.1-02552a3ea2-baae7377f0.zip differ diff --git a/.yarn/cache/eslint-plugin-promise-npm-6.0.1-44f44fa21c-c1bb3c2e59.zip b/.yarn/cache/eslint-plugin-promise-npm-6.0.1-44f44fa21c-c1bb3c2e59.zip deleted file mode 100644 index 554218df0..000000000 Binary files a/.yarn/cache/eslint-plugin-promise-npm-6.0.1-44f44fa21c-c1bb3c2e59.zip and /dev/null differ diff --git a/.yarn/cache/eslint-plugin-promise-npm-6.1.0-fbc1a09f9f-01c55f6c4d.zip b/.yarn/cache/eslint-plugin-promise-npm-6.1.0-fbc1a09f9f-01c55f6c4d.zip new file mode 100644 index 000000000..f6570cb55 Binary files /dev/null and b/.yarn/cache/eslint-plugin-promise-npm-6.1.0-fbc1a09f9f-01c55f6c4d.zip differ diff --git a/.yarn/cache/eslint-plugin-react-native-npm-3.11.0-61e76345c0-100006a29c.zip b/.yarn/cache/eslint-plugin-react-native-npm-3.11.0-61e76345c0-100006a29c.zip deleted file mode 100644 index 8ee014956..000000000 Binary files a/.yarn/cache/eslint-plugin-react-native-npm-3.11.0-61e76345c0-100006a29c.zip and /dev/null differ diff --git a/.yarn/cache/eslint-plugin-react-native-npm-4.0.0-9c6914c0dd-69fee2de6b.zip b/.yarn/cache/eslint-plugin-react-native-npm-4.0.0-9c6914c0dd-69fee2de6b.zip new file mode 100644 index 000000000..6db649758 Binary files /dev/null and b/.yarn/cache/eslint-plugin-react-native-npm-4.0.0-9c6914c0dd-69fee2de6b.zip differ diff --git a/.yarn/cache/eslint-plugin-react-npm-7.30.1-5d85704bd1-553fb9ece6.zip b/.yarn/cache/eslint-plugin-react-npm-7.30.1-5d85704bd1-553fb9ece6.zip deleted file mode 100644 index d79ad4f9f..000000000 Binary files a/.yarn/cache/eslint-plugin-react-npm-7.30.1-5d85704bd1-553fb9ece6.zip and /dev/null differ diff --git a/.yarn/cache/eslint-plugin-react-npm-7.31.8-54babab916-0683e2a624.zip b/.yarn/cache/eslint-plugin-react-npm-7.31.10-d43fb4c6e9-f013669c29.zip similarity index 84% rename from .yarn/cache/eslint-plugin-react-npm-7.31.8-54babab916-0683e2a624.zip rename to .yarn/cache/eslint-plugin-react-npm-7.31.10-d43fb4c6e9-f013669c29.zip index 18eb33638..4b66a2306 100644 Binary files a/.yarn/cache/eslint-plugin-react-npm-7.31.8-54babab916-0683e2a624.zip and b/.yarn/cache/eslint-plugin-react-npm-7.31.10-d43fb4c6e9-f013669c29.zip differ diff --git a/.yarn/cache/eslint-plugin-testing-library-npm-5.5.1-ea8e7be2aa-558994da12.zip b/.yarn/cache/eslint-plugin-testing-library-npm-5.7.2-0db0cfac3d-33ab09b0bc.zip similarity index 51% rename from .yarn/cache/eslint-plugin-testing-library-npm-5.5.1-ea8e7be2aa-558994da12.zip rename to .yarn/cache/eslint-plugin-testing-library-npm-5.7.2-0db0cfac3d-33ab09b0bc.zip index abb6abb59..d9fd56a7c 100644 Binary files a/.yarn/cache/eslint-plugin-testing-library-npm-5.5.1-ea8e7be2aa-558994da12.zip and b/.yarn/cache/eslint-plugin-testing-library-npm-5.7.2-0db0cfac3d-33ab09b0bc.zip differ diff --git a/.yarn/cache/espree-npm-9.3.2-c70fa2a91d-9a790d6779.zip b/.yarn/cache/espree-npm-9.3.2-c70fa2a91d-9a790d6779.zip deleted file mode 100644 index 4b4bfe1f4..000000000 Binary files a/.yarn/cache/espree-npm-9.3.2-c70fa2a91d-9a790d6779.zip and /dev/null differ diff --git a/.yarn/cache/expect-npm-28.1.1-0260491458-6e557b681f.zip b/.yarn/cache/expect-npm-28.1.3-e3316724f1-101e0090de.zip similarity index 95% rename from .yarn/cache/expect-npm-28.1.1-0260491458-6e557b681f.zip rename to .yarn/cache/expect-npm-28.1.3-e3316724f1-101e0090de.zip index f28560f17..18e188285 100644 Binary files a/.yarn/cache/expect-npm-28.1.1-0260491458-6e557b681f.zip and b/.yarn/cache/expect-npm-28.1.3-e3316724f1-101e0090de.zip differ diff --git a/.yarn/cache/expect-npm-29.0.3-63dbd1de55-21b7fd346c.zip b/.yarn/cache/expect-npm-29.1.2-34e14175c0-578c61459e.zip similarity index 80% rename from .yarn/cache/expect-npm-29.0.3-63dbd1de55-21b7fd346c.zip rename to .yarn/cache/expect-npm-29.1.2-34e14175c0-578c61459e.zip index 277e901d4..22e04712b 100644 Binary files a/.yarn/cache/expect-npm-29.0.3-63dbd1de55-21b7fd346c.zip and b/.yarn/cache/expect-npm-29.1.2-34e14175c0-578c61459e.zip differ diff --git a/.yarn/cache/express-npm-4.18.1-842e583ae1-c3d44c92e4.zip b/.yarn/cache/express-npm-4.18.1-842e583ae1-c3d44c92e4.zip deleted file mode 100644 index a9b46e3e1..000000000 Binary files a/.yarn/cache/express-npm-4.18.1-842e583ae1-c3d44c92e4.zip and /dev/null differ diff --git a/.yarn/cache/express-npm-4.18.2-bb15ff679a-3c4b9b0768.zip b/.yarn/cache/express-npm-4.18.2-bb15ff679a-3c4b9b0768.zip new file mode 100644 index 000000000..4d2711460 Binary files /dev/null and b/.yarn/cache/express-npm-4.18.2-bb15ff679a-3c4b9b0768.zip differ diff --git a/.yarn/cache/faker-npm-6.6.6-555f97fca7-bfb0d581ab.zip b/.yarn/cache/faker-npm-6.6.6-555f97fca7-bfb0d581ab.zip deleted file mode 100644 index d7ecf77cb..000000000 Binary files a/.yarn/cache/faker-npm-6.6.6-555f97fca7-bfb0d581ab.zip and /dev/null differ diff --git a/.yarn/cache/fast-glob-npm-3.2.11-bc01135fef-f473105324.zip b/.yarn/cache/fast-glob-npm-3.2.11-bc01135fef-f473105324.zip deleted file mode 100644 index 2bd4bfc03..000000000 Binary files a/.yarn/cache/fast-glob-npm-3.2.11-bc01135fef-f473105324.zip and /dev/null differ diff --git a/.yarn/cache/fast-glob-npm-3.2.12-162763bbae-0b1990f6ce.zip b/.yarn/cache/fast-glob-npm-3.2.12-162763bbae-0b1990f6ce.zip new file mode 100644 index 000000000..dd13e7598 Binary files /dev/null and b/.yarn/cache/fast-glob-npm-3.2.12-162763bbae-0b1990f6ce.zip differ diff --git a/.yarn/cache/fastest-levenshtein-npm-1.0.12-a32b4ef51e-e1a013698d.zip b/.yarn/cache/fastest-levenshtein-npm-1.0.12-a32b4ef51e-e1a013698d.zip deleted file mode 100644 index 2e122db17..000000000 Binary files a/.yarn/cache/fastest-levenshtein-npm-1.0.12-a32b4ef51e-e1a013698d.zip and /dev/null differ diff --git a/.yarn/cache/fastest-levenshtein-npm-1.0.16-192d328856-a78d44285c.zip b/.yarn/cache/fastest-levenshtein-npm-1.0.16-192d328856-a78d44285c.zip new file mode 100644 index 000000000..26d734f36 Binary files /dev/null and b/.yarn/cache/fastest-levenshtein-npm-1.0.16-192d328856-a78d44285c.zip differ diff --git a/.yarn/cache/fb-watchman-npm-2.0.1-30005d50fe-8510230778.zip b/.yarn/cache/fb-watchman-npm-2.0.1-30005d50fe-8510230778.zip deleted file mode 100644 index 5ab8d2a94..000000000 Binary files a/.yarn/cache/fb-watchman-npm-2.0.1-30005d50fe-8510230778.zip and /dev/null differ diff --git a/.yarn/cache/fb-watchman-npm-2.0.2-bcb6f8f831-b15a124cef.zip b/.yarn/cache/fb-watchman-npm-2.0.2-bcb6f8f831-b15a124cef.zip new file mode 100644 index 000000000..63d51b050 Binary files /dev/null and b/.yarn/cache/fb-watchman-npm-2.0.2-bcb6f8f831-b15a124cef.zip differ diff --git a/.yarn/cache/filter-obj-npm-1.1.0-84128fc26d-cf2104a7c4.zip b/.yarn/cache/filter-obj-npm-1.1.0-84128fc26d-cf2104a7c4.zip deleted file mode 100644 index 41aa4b22b..000000000 Binary files a/.yarn/cache/filter-obj-npm-1.1.0-84128fc26d-cf2104a7c4.zip and /dev/null differ diff --git a/.yarn/cache/flatted-npm-3.2.6-a309e17eb3-33b87aa88d.zip b/.yarn/cache/flatted-npm-3.2.6-a309e17eb3-33b87aa88d.zip deleted file mode 100644 index 9e29c139c..000000000 Binary files a/.yarn/cache/flatted-npm-3.2.6-a309e17eb3-33b87aa88d.zip and /dev/null differ diff --git a/.yarn/cache/flatted-npm-3.2.7-0da10b7c56-427633049d.zip b/.yarn/cache/flatted-npm-3.2.7-0da10b7c56-427633049d.zip new file mode 100644 index 000000000..b5d1ef6f7 Binary files /dev/null and b/.yarn/cache/flatted-npm-3.2.7-0da10b7c56-427633049d.zip differ diff --git a/.yarn/cache/flow-parser-npm-0.181.2-5d30e5494a-c0e5c1ec97.zip b/.yarn/cache/flow-parser-npm-0.181.2-5d30e5494a-c0e5c1ec97.zip deleted file mode 100644 index c409473ad..000000000 Binary files a/.yarn/cache/flow-parser-npm-0.181.2-5d30e5494a-c0e5c1ec97.zip and /dev/null differ diff --git a/.yarn/cache/flow-parser-npm-0.189.0-0408aa2903-c59ab3e81c.zip b/.yarn/cache/flow-parser-npm-0.189.0-0408aa2903-c59ab3e81c.zip new file mode 100644 index 000000000..1e4d104fd Binary files /dev/null and b/.yarn/cache/flow-parser-npm-0.189.0-0408aa2903-c59ab3e81c.zip differ diff --git a/.yarn/cache/focus-lock-npm-0.11.2-bebce9a7c0-f1a62ea7bb.zip b/.yarn/cache/focus-lock-npm-0.11.3-b228657fe5-d0ed6daadd.zip similarity index 65% rename from .yarn/cache/focus-lock-npm-0.11.2-bebce9a7c0-f1a62ea7bb.zip rename to .yarn/cache/focus-lock-npm-0.11.3-b228657fe5-d0ed6daadd.zip index f1ae51449..30a0c808e 100644 Binary files a/.yarn/cache/focus-lock-npm-0.11.2-bebce9a7c0-f1a62ea7bb.zip and b/.yarn/cache/focus-lock-npm-0.11.3-b228657fe5-d0ed6daadd.zip differ diff --git a/.yarn/cache/follow-redirects-npm-1.15.1-6b191885cd-6aa4e3e3cd.zip b/.yarn/cache/follow-redirects-npm-1.15.1-6b191885cd-6aa4e3e3cd.zip deleted file mode 100644 index f48c3fb38..000000000 Binary files a/.yarn/cache/follow-redirects-npm-1.15.1-6b191885cd-6aa4e3e3cd.zip and /dev/null differ diff --git a/.yarn/cache/follow-redirects-npm-1.15.2-1ec1dd82be-faa66059b6.zip b/.yarn/cache/follow-redirects-npm-1.15.2-1ec1dd82be-faa66059b6.zip new file mode 100644 index 000000000..b50d7751a Binary files /dev/null and b/.yarn/cache/follow-redirects-npm-1.15.2-1ec1dd82be-faa66059b6.zip differ diff --git a/.yarn/cache/form-data-encoder-npm-1.7.1-7c80545199-a2a360d558.zip b/.yarn/cache/form-data-encoder-npm-1.7.1-7c80545199-a2a360d558.zip deleted file mode 100644 index d36bf3882..000000000 Binary files a/.yarn/cache/form-data-encoder-npm-1.7.1-7c80545199-a2a360d558.zip and /dev/null differ diff --git a/.yarn/cache/form-data-encoder-npm-2.1.3-c53b7de344-f2db77767f.zip b/.yarn/cache/form-data-encoder-npm-2.1.3-c53b7de344-f2db77767f.zip new file mode 100644 index 000000000..9003206b2 Binary files /dev/null and b/.yarn/cache/form-data-encoder-npm-2.1.3-c53b7de344-f2db77767f.zip differ diff --git a/.yarn/cache/get-intrinsic-npm-1.1.2-89f421122b-252f45491f.zip b/.yarn/cache/get-intrinsic-npm-1.1.3-b6c7bd1010-152d79e872.zip similarity index 61% rename from .yarn/cache/get-intrinsic-npm-1.1.2-89f421122b-252f45491f.zip rename to .yarn/cache/get-intrinsic-npm-1.1.3-b6c7bd1010-152d79e872.zip index eef682cbd..94f375902 100644 Binary files a/.yarn/cache/get-intrinsic-npm-1.1.2-89f421122b-252f45491f.zip and b/.yarn/cache/get-intrinsic-npm-1.1.3-b6c7bd1010-152d79e872.zip differ diff --git a/.yarn/cache/git-up-npm-4.0.5-ee94e6e390-dd8f39a115.zip b/.yarn/cache/git-up-npm-4.0.5-ee94e6e390-dd8f39a115.zip deleted file mode 100644 index 72be888fa..000000000 Binary files a/.yarn/cache/git-up-npm-4.0.5-ee94e6e390-dd8f39a115.zip and /dev/null differ diff --git a/.yarn/cache/git-up-npm-7.0.0-5e37fa590f-2faadbab51.zip b/.yarn/cache/git-up-npm-7.0.0-5e37fa590f-2faadbab51.zip new file mode 100644 index 000000000..9085a8d16 Binary files /dev/null and b/.yarn/cache/git-up-npm-7.0.0-5e37fa590f-2faadbab51.zip differ diff --git a/.yarn/cache/git-url-parse-npm-11.6.0-864c0a6898-18a7d0bbac.zip b/.yarn/cache/git-url-parse-npm-11.6.0-864c0a6898-18a7d0bbac.zip deleted file mode 100644 index 5d926403e..000000000 Binary files a/.yarn/cache/git-url-parse-npm-11.6.0-864c0a6898-18a7d0bbac.zip and /dev/null differ diff --git a/.yarn/cache/git-url-parse-npm-13.1.0-724765d793-212a9b0343.zip b/.yarn/cache/git-url-parse-npm-13.1.0-724765d793-212a9b0343.zip new file mode 100644 index 000000000..316c23b15 Binary files /dev/null and b/.yarn/cache/git-url-parse-npm-13.1.0-724765d793-212a9b0343.zip differ diff --git a/.yarn/cache/globals-npm-13.16.0-ddfe03ff07-e571b28462.zip b/.yarn/cache/globals-npm-13.16.0-ddfe03ff07-e571b28462.zip deleted file mode 100644 index 79a433b9c..000000000 Binary files a/.yarn/cache/globals-npm-13.16.0-ddfe03ff07-e571b28462.zip and /dev/null differ diff --git a/.yarn/cache/globals-npm-13.17.0-a6039e7d26-fbaf4112e5.zip b/.yarn/cache/globals-npm-13.17.0-a6039e7d26-fbaf4112e5.zip new file mode 100644 index 000000000..5af5a6542 Binary files /dev/null and b/.yarn/cache/globals-npm-13.17.0-a6039e7d26-fbaf4112e5.zip differ diff --git a/.yarn/cache/got-npm-12.1.0-5d0f237e8e-1cc9af6ca5.zip b/.yarn/cache/got-npm-12.1.0-5d0f237e8e-1cc9af6ca5.zip deleted file mode 100644 index ba426044a..000000000 Binary files a/.yarn/cache/got-npm-12.1.0-5d0f237e8e-1cc9af6ca5.zip and /dev/null differ diff --git a/.yarn/cache/got-npm-12.5.2-6e4c27c353-f84b704ca8.zip b/.yarn/cache/got-npm-12.5.2-6e4c27c353-f84b704ca8.zip new file mode 100644 index 000000000..d8281db18 Binary files /dev/null and b/.yarn/cache/got-npm-12.5.2-6e4c27c353-f84b704ca8.zip differ diff --git a/.yarn/cache/hastscript-npm-7.0.2-1e552f9bb3-ee33aff714.zip b/.yarn/cache/hastscript-npm-7.0.2-1e552f9bb3-ee33aff714.zip deleted file mode 100644 index a475ce80c..000000000 Binary files a/.yarn/cache/hastscript-npm-7.0.2-1e552f9bb3-ee33aff714.zip and /dev/null differ diff --git a/.yarn/cache/hastscript-npm-7.1.0-8fa5b1698b-5c88419b72.zip b/.yarn/cache/hastscript-npm-7.1.0-8fa5b1698b-5c88419b72.zip new file mode 100644 index 000000000..f29c19591 Binary files /dev/null and b/.yarn/cache/hastscript-npm-7.1.0-8fa5b1698b-5c88419b72.zip differ diff --git a/.yarn/cache/highlight.js-npm-11.5.1-0fb1167640-bff556101d.zip b/.yarn/cache/highlight.js-npm-11.6.0-ea3d017805-3908eb34a4.zip similarity index 82% rename from .yarn/cache/highlight.js-npm-11.5.1-0fb1167640-bff556101d.zip rename to .yarn/cache/highlight.js-npm-11.6.0-ea3d017805-3908eb34a4.zip index efbd98ed5..a2feac891 100644 Binary files a/.yarn/cache/highlight.js-npm-11.5.1-0fb1167640-bff556101d.zip and b/.yarn/cache/highlight.js-npm-11.6.0-ea3d017805-3908eb34a4.zip differ diff --git a/.yarn/cache/hosted-git-info-npm-5.0.0-22560cf9c6-515e69463d.zip b/.yarn/cache/hosted-git-info-npm-5.0.0-22560cf9c6-515e69463d.zip deleted file mode 100644 index cf7898ca9..000000000 Binary files a/.yarn/cache/hosted-git-info-npm-5.0.0-22560cf9c6-515e69463d.zip and /dev/null differ diff --git a/.yarn/cache/hosted-git-info-npm-5.1.0-4185a64b6f-22abbc6a74.zip b/.yarn/cache/hosted-git-info-npm-5.1.0-4185a64b6f-22abbc6a74.zip new file mode 100644 index 000000000..b6d9b8663 Binary files /dev/null and b/.yarn/cache/hosted-git-info-npm-5.1.0-4185a64b6f-22abbc6a74.zip differ diff --git a/.yarn/cache/idb-npm-6.1.5-0ae02eb47a-45d81be3bf.zip b/.yarn/cache/idb-npm-6.1.5-0ae02eb47a-45d81be3bf.zip deleted file mode 100644 index 162243863..000000000 Binary files a/.yarn/cache/idb-npm-6.1.5-0ae02eb47a-45d81be3bf.zip and /dev/null differ diff --git a/.yarn/cache/idb-npm-7.1.0-fcd329313f-1ae62bcf9f.zip b/.yarn/cache/idb-npm-7.1.0-fcd329313f-1ae62bcf9f.zip new file mode 100644 index 000000000..636065e6d Binary files /dev/null and b/.yarn/cache/idb-npm-7.1.0-fcd329313f-1ae62bcf9f.zip differ diff --git a/.yarn/cache/image-size-npm-1.0.1-6c278f22d8-ffa74672dc.zip b/.yarn/cache/image-size-npm-1.0.2-ed5424d843-01745fdb47.zip similarity index 50% rename from .yarn/cache/image-size-npm-1.0.1-6c278f22d8-ffa74672dc.zip rename to .yarn/cache/image-size-npm-1.0.2-ed5424d843-01745fdb47.zip index 4acda0d1c..a50468605 100644 Binary files a/.yarn/cache/image-size-npm-1.0.1-6c278f22d8-ffa74672dc.zip and b/.yarn/cache/image-size-npm-1.0.2-ed5424d843-01745fdb47.zip differ diff --git a/.yarn/cache/ip-npm-2.0.0-204facb3cc-cfcfac6b87.zip b/.yarn/cache/ip-npm-2.0.0-204facb3cc-cfcfac6b87.zip new file mode 100644 index 000000000..0aad8938b Binary files /dev/null and b/.yarn/cache/ip-npm-2.0.0-204facb3cc-cfcfac6b87.zip differ diff --git a/.yarn/cache/is-callable-npm-1.2.4-03fc17459c-1a28d57dc4.zip b/.yarn/cache/is-callable-npm-1.2.4-03fc17459c-1a28d57dc4.zip deleted file mode 100644 index a5b406969..000000000 Binary files a/.yarn/cache/is-callable-npm-1.2.4-03fc17459c-1a28d57dc4.zip and /dev/null differ diff --git a/.yarn/cache/is-callable-npm-1.2.7-808a303e61-61fd57d03b.zip b/.yarn/cache/is-callable-npm-1.2.7-808a303e61-61fd57d03b.zip new file mode 100644 index 000000000..0e383ae51 Binary files /dev/null and b/.yarn/cache/is-callable-npm-1.2.7-808a303e61-61fd57d03b.zip differ diff --git a/.yarn/cache/is-core-module-npm-2.10.0-6dff9310aa-0f3f77811f.zip b/.yarn/cache/is-core-module-npm-2.10.0-6dff9310aa-0f3f77811f.zip new file mode 100644 index 000000000..42dc0c31e Binary files /dev/null and b/.yarn/cache/is-core-module-npm-2.10.0-6dff9310aa-0f3f77811f.zip differ diff --git a/.yarn/cache/is-core-module-npm-2.9.0-5ba77c35ae-b27034318b.zip b/.yarn/cache/is-core-module-npm-2.9.0-5ba77c35ae-b27034318b.zip deleted file mode 100644 index b7f03ef99..000000000 Binary files a/.yarn/cache/is-core-module-npm-2.9.0-5ba77c35ae-b27034318b.zip and /dev/null differ diff --git a/.yarn/cache/is-unicode-supported-npm-1.2.0-ed541ab508-2d90b4b3ce.zip b/.yarn/cache/is-unicode-supported-npm-1.2.0-ed541ab508-2d90b4b3ce.zip deleted file mode 100644 index 41113bcf5..000000000 Binary files a/.yarn/cache/is-unicode-supported-npm-1.2.0-ed541ab508-2d90b4b3ce.zip and /dev/null differ diff --git a/.yarn/cache/is-unicode-supported-npm-1.3.0-9371ea1eda-20a1fc161a.zip b/.yarn/cache/is-unicode-supported-npm-1.3.0-9371ea1eda-20a1fc161a.zip new file mode 100644 index 000000000..f8d4a8ca6 Binary files /dev/null and b/.yarn/cache/is-unicode-supported-npm-1.3.0-9371ea1eda-20a1fc161a.zip differ diff --git a/.yarn/cache/istanbul-lib-instrument-npm-5.2.0-6aa783f498-7c242ed782.zip b/.yarn/cache/istanbul-lib-instrument-npm-5.2.0-6aa783f498-7c242ed782.zip deleted file mode 100644 index f3e2637d5..000000000 Binary files a/.yarn/cache/istanbul-lib-instrument-npm-5.2.0-6aa783f498-7c242ed782.zip and /dev/null differ diff --git a/.yarn/cache/istanbul-lib-instrument-npm-5.2.1-1b3ad719a9-bf16f1803b.zip b/.yarn/cache/istanbul-lib-instrument-npm-5.2.1-1b3ad719a9-bf16f1803b.zip new file mode 100644 index 000000000..b630935eb Binary files /dev/null and b/.yarn/cache/istanbul-lib-instrument-npm-5.2.1-1b3ad719a9-bf16f1803b.zip differ diff --git a/.yarn/cache/istanbul-reports-npm-3.1.4-5faaa9636c-2132983355.zip b/.yarn/cache/istanbul-reports-npm-3.1.4-5faaa9636c-2132983355.zip deleted file mode 100644 index c9a9a9c94..000000000 Binary files a/.yarn/cache/istanbul-reports-npm-3.1.4-5faaa9636c-2132983355.zip and /dev/null differ diff --git a/.yarn/cache/istanbul-reports-npm-3.1.5-fb11324e3e-7867228f83.zip b/.yarn/cache/istanbul-reports-npm-3.1.5-fb11324e3e-7867228f83.zip new file mode 100644 index 000000000..c6e973cf8 Binary files /dev/null and b/.yarn/cache/istanbul-reports-npm-3.1.5-fb11324e3e-7867228f83.zip differ diff --git a/.yarn/cache/jest-changed-files-npm-28.0.2-86f0227b65-389d4de4b2.zip b/.yarn/cache/jest-changed-files-npm-28.1.3-bb00ac0321-c78af14a68.zip similarity index 65% rename from .yarn/cache/jest-changed-files-npm-28.0.2-86f0227b65-389d4de4b2.zip rename to .yarn/cache/jest-changed-files-npm-28.1.3-bb00ac0321-c78af14a68.zip index 514ac8e96..91d5e066d 100644 Binary files a/.yarn/cache/jest-changed-files-npm-28.0.2-86f0227b65-389d4de4b2.zip and b/.yarn/cache/jest-changed-files-npm-28.1.3-bb00ac0321-c78af14a68.zip differ diff --git a/.yarn/cache/jest-circus-npm-28.1.2-7f50bea781-c8f2e024e4.zip b/.yarn/cache/jest-circus-npm-28.1.3-cd59c17100-b635e60a9c.zip similarity index 83% rename from .yarn/cache/jest-circus-npm-28.1.2-7f50bea781-c8f2e024e4.zip rename to .yarn/cache/jest-circus-npm-28.1.3-cd59c17100-b635e60a9c.zip index e5b377503..f29b3b911 100644 Binary files a/.yarn/cache/jest-circus-npm-28.1.2-7f50bea781-c8f2e024e4.zip and b/.yarn/cache/jest-circus-npm-28.1.3-cd59c17100-b635e60a9c.zip differ diff --git a/.yarn/cache/jest-cli-npm-28.1.2-cbf6c8906a-527873c257.zip b/.yarn/cache/jest-cli-npm-28.1.3-aab5c7389d-fb424576bf.zip similarity index 64% rename from .yarn/cache/jest-cli-npm-28.1.2-cbf6c8906a-527873c257.zip rename to .yarn/cache/jest-cli-npm-28.1.3-aab5c7389d-fb424576bf.zip index 202c92147..c00764d0c 100644 Binary files a/.yarn/cache/jest-cli-npm-28.1.2-cbf6c8906a-527873c257.zip and b/.yarn/cache/jest-cli-npm-28.1.3-aab5c7389d-fb424576bf.zip differ diff --git a/.yarn/cache/jest-config-npm-28.1.2-56df4d8edb-ddc4de7a28.zip b/.yarn/cache/jest-config-npm-28.1.3-47d1c91477-ddabffd3a3.zip similarity index 97% rename from .yarn/cache/jest-config-npm-28.1.2-56df4d8edb-ddc4de7a28.zip rename to .yarn/cache/jest-config-npm-28.1.3-47d1c91477-ddabffd3a3.zip index 1dee08e41..2f3be5c84 100644 Binary files a/.yarn/cache/jest-config-npm-28.1.2-56df4d8edb-ddc4de7a28.zip and b/.yarn/cache/jest-config-npm-28.1.3-47d1c91477-ddabffd3a3.zip differ diff --git a/.yarn/cache/jest-diff-npm-28.1.1-42aa8732d8-d9e0355880.zip b/.yarn/cache/jest-diff-npm-28.1.3-cdbbfc3cc7-fa8583e0cc.zip similarity index 95% rename from .yarn/cache/jest-diff-npm-28.1.1-42aa8732d8-d9e0355880.zip rename to .yarn/cache/jest-diff-npm-28.1.3-cdbbfc3cc7-fa8583e0cc.zip index da4ee85bf..76454cd7e 100644 Binary files a/.yarn/cache/jest-diff-npm-28.1.1-42aa8732d8-d9e0355880.zip and b/.yarn/cache/jest-diff-npm-28.1.3-cdbbfc3cc7-fa8583e0cc.zip differ diff --git a/.yarn/cache/jest-diff-npm-29.0.3-46ff0e9ddd-1e12b63ea6.zip b/.yarn/cache/jest-diff-npm-29.1.2-e2d025d72e-0c97741559.zip similarity index 95% rename from .yarn/cache/jest-diff-npm-29.0.3-46ff0e9ddd-1e12b63ea6.zip rename to .yarn/cache/jest-diff-npm-29.1.2-e2d025d72e-0c97741559.zip index 72db91f3f..c7a47854c 100644 Binary files a/.yarn/cache/jest-diff-npm-29.0.3-46ff0e9ddd-1e12b63ea6.zip and b/.yarn/cache/jest-diff-npm-29.1.2-e2d025d72e-0c97741559.zip differ diff --git a/.yarn/cache/jest-each-npm-28.1.1-299702462d-91965603f8.zip b/.yarn/cache/jest-each-npm-28.1.3-ca0bd1494b-5c5b8ccb14.zip similarity index 92% rename from .yarn/cache/jest-each-npm-28.1.1-299702462d-91965603f8.zip rename to .yarn/cache/jest-each-npm-28.1.3-ca0bd1494b-5c5b8ccb14.zip index 5d393e140..7df622fc8 100644 Binary files a/.yarn/cache/jest-each-npm-28.1.1-299702462d-91965603f8.zip and b/.yarn/cache/jest-each-npm-28.1.3-ca0bd1494b-5c5b8ccb14.zip differ diff --git a/.yarn/cache/jest-environment-jsdom-npm-28.1.2-225ffc028f-73388b5cde.zip b/.yarn/cache/jest-environment-jsdom-npm-28.1.3-c3ce0aea09-32758f9b9a.zip similarity index 85% rename from .yarn/cache/jest-environment-jsdom-npm-28.1.2-225ffc028f-73388b5cde.zip rename to .yarn/cache/jest-environment-jsdom-npm-28.1.3-c3ce0aea09-32758f9b9a.zip index 9e69fc770..8220a0938 100644 Binary files a/.yarn/cache/jest-environment-jsdom-npm-28.1.2-225ffc028f-73388b5cde.zip and b/.yarn/cache/jest-environment-jsdom-npm-28.1.3-c3ce0aea09-32758f9b9a.zip differ diff --git a/.yarn/cache/jest-environment-node-npm-28.1.2-a3cfa6adac-cee61a3e25.zip b/.yarn/cache/jest-environment-node-npm-28.1.3-46a696a38b-1048fe306a.zip similarity index 80% rename from .yarn/cache/jest-environment-node-npm-28.1.2-a3cfa6adac-cee61a3e25.zip rename to .yarn/cache/jest-environment-node-npm-28.1.3-46a696a38b-1048fe306a.zip index 89436f3fb..d70e649ae 100644 Binary files a/.yarn/cache/jest-environment-node-npm-28.1.2-a3cfa6adac-cee61a3e25.zip and b/.yarn/cache/jest-environment-node-npm-28.1.3-46a696a38b-1048fe306a.zip differ diff --git a/.yarn/cache/jest-haste-map-npm-28.1.1-184dfbeed0-db31a2a839.zip b/.yarn/cache/jest-haste-map-npm-28.1.3-9ce0dea452-d05fdc1086.zip similarity index 96% rename from .yarn/cache/jest-haste-map-npm-28.1.1-184dfbeed0-db31a2a839.zip rename to .yarn/cache/jest-haste-map-npm-28.1.3-9ce0dea452-d05fdc1086.zip index 506c06428..87d07cd88 100644 Binary files a/.yarn/cache/jest-haste-map-npm-28.1.1-184dfbeed0-db31a2a839.zip and b/.yarn/cache/jest-haste-map-npm-28.1.3-9ce0dea452-d05fdc1086.zip differ diff --git a/.yarn/cache/jest-leak-detector-npm-28.1.1-99f9cda79d-379a15ad7b.zip b/.yarn/cache/jest-leak-detector-npm-28.1.1-99f9cda79d-379a15ad7b.zip deleted file mode 100644 index a5bb5038a..000000000 Binary files a/.yarn/cache/jest-leak-detector-npm-28.1.1-99f9cda79d-379a15ad7b.zip and /dev/null differ diff --git a/.yarn/cache/jest-leak-detector-npm-28.1.3-36abac94be-2e976a4880.zip b/.yarn/cache/jest-leak-detector-npm-28.1.3-36abac94be-2e976a4880.zip new file mode 100644 index 000000000..3e3ed7f2d Binary files /dev/null and b/.yarn/cache/jest-leak-detector-npm-28.1.3-36abac94be-2e976a4880.zip differ diff --git a/.yarn/cache/jest-matcher-utils-npm-28.1.1-43475d399c-cb73ccd347.zip b/.yarn/cache/jest-matcher-utils-npm-28.1.3-6a206019d4-6b34f0cf66.zip similarity index 92% rename from .yarn/cache/jest-matcher-utils-npm-28.1.1-43475d399c-cb73ccd347.zip rename to .yarn/cache/jest-matcher-utils-npm-28.1.3-6a206019d4-6b34f0cf66.zip index aaac5542a..5e9bb3657 100644 Binary files a/.yarn/cache/jest-matcher-utils-npm-28.1.1-43475d399c-cb73ccd347.zip and b/.yarn/cache/jest-matcher-utils-npm-28.1.3-6a206019d4-6b34f0cf66.zip differ diff --git a/.yarn/cache/jest-matcher-utils-npm-29.0.3-9317a74a1e-e39ab74a04.zip b/.yarn/cache/jest-matcher-utils-npm-29.1.2-2e9d1c97cd-648afe4349.zip similarity index 90% rename from .yarn/cache/jest-matcher-utils-npm-29.0.3-9317a74a1e-e39ab74a04.zip rename to .yarn/cache/jest-matcher-utils-npm-29.1.2-2e9d1c97cd-648afe4349.zip index 495cd4bda..1e75d8f53 100644 Binary files a/.yarn/cache/jest-matcher-utils-npm-29.0.3-9317a74a1e-e39ab74a04.zip and b/.yarn/cache/jest-matcher-utils-npm-29.1.2-2e9d1c97cd-648afe4349.zip differ diff --git a/.yarn/cache/jest-message-util-npm-28.1.1-c09153ceb7-cca23b9a01.zip b/.yarn/cache/jest-message-util-npm-28.1.3-bee4da4d10-1f26685416.zip similarity index 88% rename from .yarn/cache/jest-message-util-npm-28.1.1-c09153ceb7-cca23b9a01.zip rename to .yarn/cache/jest-message-util-npm-28.1.3-bee4da4d10-1f26685416.zip index 5713ff49c..7d220e858 100644 Binary files a/.yarn/cache/jest-message-util-npm-28.1.1-c09153ceb7-cca23b9a01.zip and b/.yarn/cache/jest-message-util-npm-28.1.3-bee4da4d10-1f26685416.zip differ diff --git a/.yarn/cache/jest-message-util-npm-29.0.3-6be00c7820-04bee1fee1.zip b/.yarn/cache/jest-message-util-npm-29.1.2-fde61ad1c5-d1541bd726.zip similarity index 88% rename from .yarn/cache/jest-message-util-npm-29.0.3-6be00c7820-04bee1fee1.zip rename to .yarn/cache/jest-message-util-npm-29.1.2-fde61ad1c5-d1541bd726.zip index 402494d23..30319139f 100644 Binary files a/.yarn/cache/jest-message-util-npm-29.0.3-6be00c7820-04bee1fee1.zip and b/.yarn/cache/jest-message-util-npm-29.1.2-fde61ad1c5-d1541bd726.zip differ diff --git a/.yarn/cache/jest-mock-npm-28.1.1-66f9031b26-285716d062.zip b/.yarn/cache/jest-mock-npm-28.1.3-75849d2dd2-a573bf8e5f.zip similarity index 66% rename from .yarn/cache/jest-mock-npm-28.1.1-66f9031b26-285716d062.zip rename to .yarn/cache/jest-mock-npm-28.1.3-75849d2dd2-a573bf8e5f.zip index 090d62946..eb6f6b79c 100644 Binary files a/.yarn/cache/jest-mock-npm-28.1.1-66f9031b26-285716d062.zip and b/.yarn/cache/jest-mock-npm-28.1.3-75849d2dd2-a573bf8e5f.zip differ diff --git a/.yarn/cache/jest-npm-28.1.2-0cb80d72d4-8ad37088c4.zip b/.yarn/cache/jest-npm-28.1.3-207c50e059-b9dcb542eb.zip similarity index 68% rename from .yarn/cache/jest-npm-28.1.2-0cb80d72d4-8ad37088c4.zip rename to .yarn/cache/jest-npm-28.1.3-207c50e059-b9dcb542eb.zip index 8041992e4..61f799118 100644 Binary files a/.yarn/cache/jest-npm-28.1.2-0cb80d72d4-8ad37088c4.zip and b/.yarn/cache/jest-npm-28.1.3-207c50e059-b9dcb542eb.zip differ diff --git a/.yarn/cache/jest-resolve-dependencies-npm-28.1.2-3bd416d27e-2f822678b5.zip b/.yarn/cache/jest-resolve-dependencies-npm-28.1.3-143d112ae5-4eea9ec33a.zip similarity index 74% rename from .yarn/cache/jest-resolve-dependencies-npm-28.1.2-3bd416d27e-2f822678b5.zip rename to .yarn/cache/jest-resolve-dependencies-npm-28.1.3-143d112ae5-4eea9ec33a.zip index f43105d03..40b39640f 100644 Binary files a/.yarn/cache/jest-resolve-dependencies-npm-28.1.2-3bd416d27e-2f822678b5.zip and b/.yarn/cache/jest-resolve-dependencies-npm-28.1.3-143d112ae5-4eea9ec33a.zip differ diff --git a/.yarn/cache/jest-resolve-npm-28.1.1-5f1937a1f8-cda5c472fe.zip b/.yarn/cache/jest-resolve-npm-28.1.3-acd3a0d26b-df61a490c9.zip similarity index 96% rename from .yarn/cache/jest-resolve-npm-28.1.1-5f1937a1f8-cda5c472fe.zip rename to .yarn/cache/jest-resolve-npm-28.1.3-acd3a0d26b-df61a490c9.zip index 8fa0209c2..f19d2f39c 100644 Binary files a/.yarn/cache/jest-resolve-npm-28.1.1-5f1937a1f8-cda5c472fe.zip and b/.yarn/cache/jest-resolve-npm-28.1.3-acd3a0d26b-df61a490c9.zip differ diff --git a/.yarn/cache/jest-runner-npm-28.1.2-f1340306c4-51e46779e6.zip b/.yarn/cache/jest-runner-npm-28.1.3-b6c86f7ed5-32405cd970.zip similarity index 66% rename from .yarn/cache/jest-runner-npm-28.1.2-f1340306c4-51e46779e6.zip rename to .yarn/cache/jest-runner-npm-28.1.3-b6c86f7ed5-32405cd970.zip index 7b6143ab1..f6739632e 100644 Binary files a/.yarn/cache/jest-runner-npm-28.1.2-f1340306c4-51e46779e6.zip and b/.yarn/cache/jest-runner-npm-28.1.3-b6c86f7ed5-32405cd970.zip differ diff --git a/.yarn/cache/jest-runtime-npm-28.1.2-ae8fb2675f-d9a2f45a7b.zip b/.yarn/cache/jest-runtime-npm-28.1.3-15fdfa887e-b17c40af85.zip similarity index 95% rename from .yarn/cache/jest-runtime-npm-28.1.2-ae8fb2675f-d9a2f45a7b.zip rename to .yarn/cache/jest-runtime-npm-28.1.3-15fdfa887e-b17c40af85.zip index 54506df8e..8b00bbda6 100644 Binary files a/.yarn/cache/jest-runtime-npm-28.1.2-ae8fb2675f-d9a2f45a7b.zip and b/.yarn/cache/jest-runtime-npm-28.1.3-15fdfa887e-b17c40af85.zip differ diff --git a/.yarn/cache/jest-snapshot-npm-28.1.2-c457ca7d89-5c33c8b05d.zip b/.yarn/cache/jest-snapshot-npm-28.1.3-b36ae70475-2a46a5493f.zip similarity index 76% rename from .yarn/cache/jest-snapshot-npm-28.1.2-c457ca7d89-5c33c8b05d.zip rename to .yarn/cache/jest-snapshot-npm-28.1.3-b36ae70475-2a46a5493f.zip index 1529adc2f..d4170a577 100644 Binary files a/.yarn/cache/jest-snapshot-npm-28.1.2-c457ca7d89-5c33c8b05d.zip and b/.yarn/cache/jest-snapshot-npm-28.1.3-b36ae70475-2a46a5493f.zip differ diff --git a/.yarn/cache/jest-util-npm-28.1.1-a4a13e7130-bca1601099.zip b/.yarn/cache/jest-util-npm-28.1.3-9ae2283a08-fd6459742c.zip similarity index 95% rename from .yarn/cache/jest-util-npm-28.1.1-a4a13e7130-bca1601099.zip rename to .yarn/cache/jest-util-npm-28.1.3-9ae2283a08-fd6459742c.zip index ef9c4e47c..de7d725d2 100644 Binary files a/.yarn/cache/jest-util-npm-28.1.1-a4a13e7130-bca1601099.zip and b/.yarn/cache/jest-util-npm-28.1.3-9ae2283a08-fd6459742c.zip differ diff --git a/.yarn/cache/jest-util-npm-29.0.3-52059003ed-39c31e75ba.zip b/.yarn/cache/jest-util-npm-29.1.2-6cc211f8dd-6c55464e20.zip similarity index 74% rename from .yarn/cache/jest-util-npm-29.0.3-52059003ed-39c31e75ba.zip rename to .yarn/cache/jest-util-npm-29.1.2-6cc211f8dd-6c55464e20.zip index 875c4c985..4e4bdf57d 100644 Binary files a/.yarn/cache/jest-util-npm-29.0.3-52059003ed-39c31e75ba.zip and b/.yarn/cache/jest-util-npm-29.1.2-6cc211f8dd-6c55464e20.zip differ diff --git a/.yarn/cache/jest-validate-npm-28.1.1-3a8ac7efbd-7bb5427d9b.zip b/.yarn/cache/jest-validate-npm-28.1.3-f1a729aeb4-95e0513b38.zip similarity index 84% rename from .yarn/cache/jest-validate-npm-28.1.1-3a8ac7efbd-7bb5427d9b.zip rename to .yarn/cache/jest-validate-npm-28.1.3-f1a729aeb4-95e0513b38.zip index 015aeaf81..2fe965288 100644 Binary files a/.yarn/cache/jest-validate-npm-28.1.1-3a8ac7efbd-7bb5427d9b.zip and b/.yarn/cache/jest-validate-npm-28.1.3-f1a729aeb4-95e0513b38.zip differ diff --git a/.yarn/cache/jest-watcher-npm-28.1.1-3bd0da3611-60ee90a3b7.zip b/.yarn/cache/jest-watcher-npm-28.1.3-8da81cc37d-8f6d674a48.zip similarity index 89% rename from .yarn/cache/jest-watcher-npm-28.1.1-3bd0da3611-60ee90a3b7.zip rename to .yarn/cache/jest-watcher-npm-28.1.3-8da81cc37d-8f6d674a48.zip index 6bc51217b..432a693f2 100644 Binary files a/.yarn/cache/jest-watcher-npm-28.1.1-3bd0da3611-60ee90a3b7.zip and b/.yarn/cache/jest-watcher-npm-28.1.3-8da81cc37d-8f6d674a48.zip differ diff --git a/.yarn/cache/jest-worker-npm-28.1.1-3ed8b085d3-28519c43b4.zip b/.yarn/cache/jest-worker-npm-28.1.3-5d0ff9006c-e921c9a1b8.zip similarity index 96% rename from .yarn/cache/jest-worker-npm-28.1.1-3ed8b085d3-28519c43b4.zip rename to .yarn/cache/jest-worker-npm-28.1.3-5d0ff9006c-e921c9a1b8.zip index d8c2f0c1d..949ec251a 100644 Binary files a/.yarn/cache/jest-worker-npm-28.1.1-3ed8b085d3-28519c43b4.zip and b/.yarn/cache/jest-worker-npm-28.1.3-5d0ff9006c-e921c9a1b8.zip differ diff --git a/.yarn/cache/jest-worker-npm-29.1.2-570b728071-788d14b2a0.zip b/.yarn/cache/jest-worker-npm-29.1.2-570b728071-788d14b2a0.zip new file mode 100644 index 000000000..4333b2577 Binary files /dev/null and b/.yarn/cache/jest-worker-npm-29.1.2-570b728071-788d14b2a0.zip differ diff --git a/.yarn/cache/joi-npm-17.6.0-987ef6515f-eaf62f6c02.zip b/.yarn/cache/joi-npm-17.6.3-2a8ba9150f-a4cd53a83e.zip similarity index 51% rename from .yarn/cache/joi-npm-17.6.0-987ef6515f-eaf62f6c02.zip rename to .yarn/cache/joi-npm-17.6.3-2a8ba9150f-a4cd53a83e.zip index 524ff4ad2..fe49667af 100644 Binary files a/.yarn/cache/joi-npm-17.6.0-987ef6515f-eaf62f6c02.zip and b/.yarn/cache/joi-npm-17.6.3-2a8ba9150f-a4cd53a83e.zip differ diff --git a/.yarn/cache/jquery-npm-3.6.0-ca7872bdbb-8fd5fef4aa.zip b/.yarn/cache/jquery-npm-3.6.0-ca7872bdbb-8fd5fef4aa.zip deleted file mode 100644 index 2c23cc857..000000000 Binary files a/.yarn/cache/jquery-npm-3.6.0-ca7872bdbb-8fd5fef4aa.zip and /dev/null differ diff --git a/.yarn/cache/jquery-npm-3.6.1-6f29087f48-6177d866a7.zip b/.yarn/cache/jquery-npm-3.6.1-6f29087f48-6177d866a7.zip new file mode 100644 index 000000000..3ace5cee5 Binary files /dev/null and b/.yarn/cache/jquery-npm-3.6.1-6f29087f48-6177d866a7.zip differ diff --git a/.yarn/cache/js-base64-npm-3.7.2-706fb77a0b-573f28e9a2.zip b/.yarn/cache/js-base64-npm-3.7.2-706fb77a0b-573f28e9a2.zip deleted file mode 100644 index e2151db69..000000000 Binary files a/.yarn/cache/js-base64-npm-3.7.2-706fb77a0b-573f28e9a2.zip and /dev/null differ diff --git a/.yarn/cache/js-sdsl-npm-4.1.4-334fa1c399-1977cea4ab.zip b/.yarn/cache/js-sdsl-npm-4.1.4-334fa1c399-1977cea4ab.zip deleted file mode 100644 index 95759c5db..000000000 Binary files a/.yarn/cache/js-sdsl-npm-4.1.4-334fa1c399-1977cea4ab.zip and /dev/null differ diff --git a/.yarn/cache/js-sdsl-npm-4.1.5-66fcf4f580-695f657ddc.zip b/.yarn/cache/js-sdsl-npm-4.1.5-66fcf4f580-695f657ddc.zip new file mode 100644 index 000000000..c581e91e6 Binary files /dev/null and b/.yarn/cache/js-sdsl-npm-4.1.5-66fcf4f580-695f657ddc.zip differ diff --git a/.yarn/cache/jsdom-npm-20.0.0-9c1ad43ab8-f69b40679d.zip b/.yarn/cache/jsdom-npm-20.0.1-b1381838f2-9fc0b66a86.zip similarity index 91% rename from .yarn/cache/jsdom-npm-20.0.0-9c1ad43ab8-f69b40679d.zip rename to .yarn/cache/jsdom-npm-20.0.1-b1381838f2-9fc0b66a86.zip index f209ba812..53582ad14 100644 Binary files a/.yarn/cache/jsdom-npm-20.0.0-9c1ad43ab8-f69b40679d.zip and b/.yarn/cache/jsdom-npm-20.0.1-b1381838f2-9fc0b66a86.zip differ diff --git a/.yarn/cache/jsonify-npm-0.0.0-80da2da40c-d8d4ed476c.zip b/.yarn/cache/jsonify-npm-0.0.0-80da2da40c-d8d4ed476c.zip deleted file mode 100644 index 78b9d9a18..000000000 Binary files a/.yarn/cache/jsonify-npm-0.0.0-80da2da40c-d8d4ed476c.zip and /dev/null differ diff --git a/.yarn/cache/jsonify-npm-0.0.1-22c28aed92-027287e1c0.zip b/.yarn/cache/jsonify-npm-0.0.1-22c28aed92-027287e1c0.zip new file mode 100644 index 000000000..ec2910fe8 Binary files /dev/null and b/.yarn/cache/jsonify-npm-0.0.1-22c28aed92-027287e1c0.zip differ diff --git a/.yarn/cache/jsonpointer-npm-5.0.0-b84d1f8c02-c7ec0b6bb5.zip b/.yarn/cache/jsonpointer-npm-5.0.0-b84d1f8c02-c7ec0b6bb5.zip deleted file mode 100644 index 95b1601c8..000000000 Binary files a/.yarn/cache/jsonpointer-npm-5.0.0-b84d1f8c02-c7ec0b6bb5.zip and /dev/null differ diff --git a/.yarn/cache/jsonpointer-npm-5.0.1-8e4c22e512-0b40f71290.zip b/.yarn/cache/jsonpointer-npm-5.0.1-8e4c22e512-0b40f71290.zip new file mode 100644 index 000000000..3216800d4 Binary files /dev/null and b/.yarn/cache/jsonpointer-npm-5.0.1-8e4c22e512-0b40f71290.zip differ diff --git a/.yarn/cache/jsx-ast-utils-npm-3.3.1-3881043695-1d4b32fd24.zip b/.yarn/cache/jsx-ast-utils-npm-3.3.3-3d3171e1e4-a2ed78cac4.zip similarity index 74% rename from .yarn/cache/jsx-ast-utils-npm-3.3.1-3881043695-1d4b32fd24.zip rename to .yarn/cache/jsx-ast-utils-npm-3.3.3-3d3171e1e4-a2ed78cac4.zip index d76696d95..1a14df014 100644 Binary files a/.yarn/cache/jsx-ast-utils-npm-3.3.1-3881043695-1d4b32fd24.zip and b/.yarn/cache/jsx-ast-utils-npm-3.3.3-3d3171e1e4-a2ed78cac4.zip differ diff --git a/.yarn/cache/keyv-npm-4.3.2-036dc9c0ad-237952f5fa.zip b/.yarn/cache/keyv-npm-4.3.2-036dc9c0ad-237952f5fa.zip deleted file mode 100644 index 766cb4500..000000000 Binary files a/.yarn/cache/keyv-npm-4.3.2-036dc9c0ad-237952f5fa.zip and /dev/null differ diff --git a/.yarn/cache/keyv-npm-4.5.0-57560bec53-d294873cf8.zip b/.yarn/cache/keyv-npm-4.5.0-57560bec53-d294873cf8.zip new file mode 100644 index 000000000..9d2dd39e3 Binary files /dev/null and b/.yarn/cache/keyv-npm-4.5.0-57560bec53-d294873cf8.zip differ diff --git a/.yarn/cache/libnpmaccess-npm-6.0.3-16e0ea9723-4a437390d5.zip b/.yarn/cache/libnpmaccess-npm-6.0.4-1b28cf19e9-86130b435c.zip similarity index 79% rename from .yarn/cache/libnpmaccess-npm-6.0.3-16e0ea9723-4a437390d5.zip rename to .yarn/cache/libnpmaccess-npm-6.0.4-1b28cf19e9-86130b435c.zip index 2c03e6896..ba23b1758 100644 Binary files a/.yarn/cache/libnpmaccess-npm-6.0.3-16e0ea9723-4a437390d5.zip and b/.yarn/cache/libnpmaccess-npm-6.0.4-1b28cf19e9-86130b435c.zip differ diff --git a/.yarn/cache/libnpmpublish-npm-6.0.4-6b4574d30e-d653e0d9be.zip b/.yarn/cache/libnpmpublish-npm-6.0.5-41d6654b18-d2f2434517.zip similarity index 85% rename from .yarn/cache/libnpmpublish-npm-6.0.4-6b4574d30e-d653e0d9be.zip rename to .yarn/cache/libnpmpublish-npm-6.0.5-41d6654b18-d2f2434517.zip index 596891441..17e31d7a0 100644 Binary files a/.yarn/cache/libnpmpublish-npm-6.0.4-6b4574d30e-d653e0d9be.zip and b/.yarn/cache/libnpmpublish-npm-6.0.5-41d6654b18-d2f2434517.zip differ diff --git a/.yarn/cache/lru-cache-npm-7.12.0-eae8176c54-fdb6226297.zip b/.yarn/cache/lru-cache-npm-7.12.0-eae8176c54-fdb6226297.zip deleted file mode 100644 index ce807f2d4..000000000 Binary files a/.yarn/cache/lru-cache-npm-7.12.0-eae8176c54-fdb6226297.zip and /dev/null differ diff --git a/.yarn/cache/lru-cache-npm-7.14.0-354cf654ec-efdd329f2c.zip b/.yarn/cache/lru-cache-npm-7.14.0-354cf654ec-efdd329f2c.zip new file mode 100644 index 000000000..26e634c84 Binary files /dev/null and b/.yarn/cache/lru-cache-npm-7.14.0-354cf654ec-efdd329f2c.zip differ diff --git a/.yarn/cache/make-fetch-happen-npm-10.1.8-1571a0a77a-5fe9fd9da5.zip b/.yarn/cache/make-fetch-happen-npm-10.2.1-f1cc7cd2df-2332eb9a8e.zip similarity index 68% rename from .yarn/cache/make-fetch-happen-npm-10.1.8-1571a0a77a-5fe9fd9da5.zip rename to .yarn/cache/make-fetch-happen-npm-10.2.1-f1cc7cd2df-2332eb9a8e.zip index cc312953d..f257e35c7 100644 Binary files a/.yarn/cache/make-fetch-happen-npm-10.1.8-1571a0a77a-5fe9fd9da5.zip and b/.yarn/cache/make-fetch-happen-npm-10.2.1-f1cc7cd2df-2332eb9a8e.zip differ diff --git a/.yarn/cache/marked-npm-4.0.17-d85fa63152-33a3c43a20.zip b/.yarn/cache/marked-npm-4.0.17-d85fa63152-33a3c43a20.zip deleted file mode 100644 index 97d23bcbb..000000000 Binary files a/.yarn/cache/marked-npm-4.0.17-d85fa63152-33a3c43a20.zip and /dev/null differ diff --git a/.yarn/cache/marked-npm-4.1.1-b1d6abaf9f-717e335795.zip b/.yarn/cache/marked-npm-4.1.1-b1d6abaf9f-717e335795.zip new file mode 100644 index 000000000..7e28d159e Binary files /dev/null and b/.yarn/cache/marked-npm-4.1.1-b1d6abaf9f-717e335795.zip differ diff --git a/.yarn/cache/material-icons-npm-1.11.4-7ec51530cb-1a187adb3e.zip b/.yarn/cache/material-icons-npm-1.11.4-7ec51530cb-1a187adb3e.zip deleted file mode 100644 index 3dc32e43d..000000000 Binary files a/.yarn/cache/material-icons-npm-1.11.4-7ec51530cb-1a187adb3e.zip and /dev/null differ diff --git a/.yarn/cache/material-icons-npm-1.12.0-c1e834e12c-a48c3c0cfb.zip b/.yarn/cache/material-icons-npm-1.12.0-c1e834e12c-a48c3c0cfb.zip new file mode 100644 index 000000000..8f520a58c Binary files /dev/null and b/.yarn/cache/material-icons-npm-1.12.0-c1e834e12c-a48c3c0cfb.zip differ diff --git a/.yarn/cache/mdast-util-find-and-replace-npm-2.2.0-032991171e-1ca772fcec.zip b/.yarn/cache/mdast-util-find-and-replace-npm-2.2.1-35ada596c4-9b23a6858b.zip similarity index 62% rename from .yarn/cache/mdast-util-find-and-replace-npm-2.2.0-032991171e-1ca772fcec.zip rename to .yarn/cache/mdast-util-find-and-replace-npm-2.2.1-35ada596c4-9b23a6858b.zip index bfa20f104..b17b70d5c 100644 Binary files a/.yarn/cache/mdast-util-find-and-replace-npm-2.2.0-032991171e-1ca772fcec.zip and b/.yarn/cache/mdast-util-find-and-replace-npm-2.2.1-35ada596c4-9b23a6858b.zip differ diff --git a/.yarn/cache/mdast-util-gfm-table-npm-1.0.4-f9d294e29a-56d9f0376b.zip b/.yarn/cache/mdast-util-gfm-table-npm-1.0.4-f9d294e29a-56d9f0376b.zip deleted file mode 100644 index 771113793..000000000 Binary files a/.yarn/cache/mdast-util-gfm-table-npm-1.0.4-f9d294e29a-56d9f0376b.zip and /dev/null differ diff --git a/.yarn/cache/mdast-util-gfm-table-npm-1.0.6-48a37cbb10-1b0469d9a9.zip b/.yarn/cache/mdast-util-gfm-table-npm-1.0.6-48a37cbb10-1b0469d9a9.zip new file mode 100644 index 000000000..4ccf9622d Binary files /dev/null and b/.yarn/cache/mdast-util-gfm-table-npm-1.0.6-48a37cbb10-1b0469d9a9.zip differ diff --git a/.yarn/cache/micromark-npm-3.0.10-8d661b8a4a-04663fe030.zip b/.yarn/cache/micromark-npm-3.0.10-8d661b8a4a-04663fe030.zip deleted file mode 100644 index 8e8c90ee7..000000000 Binary files a/.yarn/cache/micromark-npm-3.0.10-8d661b8a4a-04663fe030.zip and /dev/null differ diff --git a/.yarn/cache/micromark-npm-3.1.0-2432407996-5fe5bc3bf9.zip b/.yarn/cache/micromark-npm-3.1.0-2432407996-5fe5bc3bf9.zip new file mode 100644 index 000000000..5b0c604b8 Binary files /dev/null and b/.yarn/cache/micromark-npm-3.1.0-2432407996-5fe5bc3bf9.zip differ diff --git a/.yarn/cache/micromark-util-sanitize-uri-npm-1.0.0-ca1fc53943-77448ec3a5.zip b/.yarn/cache/micromark-util-sanitize-uri-npm-1.0.0-ca1fc53943-77448ec3a5.zip deleted file mode 100644 index efa0b7b4d..000000000 Binary files a/.yarn/cache/micromark-util-sanitize-uri-npm-1.0.0-ca1fc53943-77448ec3a5.zip and /dev/null differ diff --git a/.yarn/cache/micromark-util-sanitize-uri-npm-1.1.0-4389b68137-fe6093faa0.zip b/.yarn/cache/micromark-util-sanitize-uri-npm-1.1.0-4389b68137-fe6093faa0.zip new file mode 100644 index 000000000..6c078e4c1 Binary files /dev/null and b/.yarn/cache/micromark-util-sanitize-uri-npm-1.1.0-4389b68137-fe6093faa0.zip differ diff --git a/.yarn/cache/mimic-response-npm-4.0.0-c080547e26-33b804cc96.zip b/.yarn/cache/mimic-response-npm-4.0.0-c080547e26-33b804cc96.zip new file mode 100644 index 000000000..78c961b11 Binary files /dev/null and b/.yarn/cache/mimic-response-npm-4.0.0-c080547e26-33b804cc96.zip differ diff --git a/.yarn/cache/mini-create-react-context-npm-0.4.1-06f382591b-f8cb2c7738.zip b/.yarn/cache/mini-create-react-context-npm-0.4.1-06f382591b-f8cb2c7738.zip deleted file mode 100644 index d4a3699a4..000000000 Binary files a/.yarn/cache/mini-create-react-context-npm-0.4.1-06f382591b-f8cb2c7738.zip and /dev/null differ diff --git a/.yarn/cache/minimist-npm-1.2.6-f4cee4b4af-d15428cd1e.zip b/.yarn/cache/minimist-npm-1.2.6-f4cee4b4af-d15428cd1e.zip deleted file mode 100644 index e7466c584..000000000 Binary files a/.yarn/cache/minimist-npm-1.2.6-f4cee4b4af-d15428cd1e.zip and /dev/null differ diff --git a/.yarn/cache/minimist-npm-1.2.7-51d33b1371-7346574a10.zip b/.yarn/cache/minimist-npm-1.2.7-51d33b1371-7346574a10.zip new file mode 100644 index 000000000..d60d31296 Binary files /dev/null and b/.yarn/cache/minimist-npm-1.2.7-51d33b1371-7346574a10.zip differ diff --git a/.yarn/cache/minipass-fetch-npm-2.1.0-300ce55188-1334732859.zip b/.yarn/cache/minipass-fetch-npm-2.1.2-9b21a5c930-3f216be791.zip similarity index 64% rename from .yarn/cache/minipass-fetch-npm-2.1.0-300ce55188-1334732859.zip rename to .yarn/cache/minipass-fetch-npm-2.1.2-9b21a5c930-3f216be791.zip index 389d884dc..59a89f1b1 100644 Binary files a/.yarn/cache/minipass-fetch-npm-2.1.0-300ce55188-1334732859.zip and b/.yarn/cache/minipass-fetch-npm-2.1.2-9b21a5c930-3f216be791.zip differ diff --git a/.yarn/cache/minipass-npm-3.3.4-6cf48a6c5e-5d95a7738c.zip b/.yarn/cache/minipass-npm-3.3.5-a555b091e7-f89f02bcaa.zip similarity index 82% rename from .yarn/cache/minipass-npm-3.3.4-6cf48a6c5e-5d95a7738c.zip rename to .yarn/cache/minipass-npm-3.3.5-a555b091e7-f89f02bcaa.zip index fee39d2fc..fa7d12c7e 100644 Binary files a/.yarn/cache/minipass-npm-3.3.4-6cf48a6c5e-5d95a7738c.zip and b/.yarn/cache/minipass-npm-3.3.5-a555b091e7-f89f02bcaa.zip differ diff --git a/.yarn/cache/moment-mini-npm-2.24.0-2fedc8306a-c1162322fd.zip b/.yarn/cache/moment-mini-npm-2.24.0-2fedc8306a-c1162322fd.zip deleted file mode 100644 index 41b024056..000000000 Binary files a/.yarn/cache/moment-mini-npm-2.24.0-2fedc8306a-c1162322fd.zip and /dev/null differ diff --git a/.yarn/cache/moment-mini-npm-2.29.4-c2d2de80a5-5d386872d0.zip b/.yarn/cache/moment-mini-npm-2.29.4-c2d2de80a5-5d386872d0.zip new file mode 100644 index 000000000..8885e6078 Binary files /dev/null and b/.yarn/cache/moment-mini-npm-2.29.4-c2d2de80a5-5d386872d0.zip differ diff --git a/.yarn/cache/moment-npm-2.29.3-fe4ba99bae-2e780e36d9.zip b/.yarn/cache/moment-npm-2.29.4-902943305d-0ec3f9c2bc.zip similarity index 71% rename from .yarn/cache/moment-npm-2.29.3-fe4ba99bae-2e780e36d9.zip rename to .yarn/cache/moment-npm-2.29.4-902943305d-0ec3f9c2bc.zip index 8db6d8b80..78acd14be 100644 Binary files a/.yarn/cache/moment-npm-2.29.3-fe4ba99bae-2e780e36d9.zip and b/.yarn/cache/moment-npm-2.29.4-902943305d-0ec3f9c2bc.zip differ diff --git a/.yarn/cache/nan-npm-2.16.0-cac314a230-cb16937273.zip b/.yarn/cache/nan-npm-2.17.0-bf36a21d6f-ec609aeaf7.zip similarity index 72% rename from .yarn/cache/nan-npm-2.16.0-cac314a230-cb16937273.zip rename to .yarn/cache/nan-npm-2.17.0-bf36a21d6f-ec609aeaf7.zip index d2907fbe7..55727fc94 100644 Binary files a/.yarn/cache/nan-npm-2.16.0-cac314a230-cb16937273.zip and b/.yarn/cache/nan-npm-2.17.0-bf36a21d6f-ec609aeaf7.zip differ diff --git a/.yarn/cache/nanostores-npm-0.5.12-11dd704b55-87a975b00d.zip b/.yarn/cache/nanostores-npm-0.5.13-f2c3c3e3f4-f3831519a3.zip similarity index 64% rename from .yarn/cache/nanostores-npm-0.5.12-11dd704b55-87a975b00d.zip rename to .yarn/cache/nanostores-npm-0.5.13-f2c3c3e3f4-f3831519a3.zip index f3ebeecdc..013dca446 100644 Binary files a/.yarn/cache/nanostores-npm-0.5.12-11dd704b55-87a975b00d.zip and b/.yarn/cache/nanostores-npm-0.5.13-f2c3c3e3f4-f3831519a3.zip differ diff --git a/.yarn/cache/nock-npm-13.2.8-6b3bcf0f50-656f696d3c.zip b/.yarn/cache/nock-npm-13.2.9-de18b54858-04a2dc60b4.zip similarity index 68% rename from .yarn/cache/nock-npm-13.2.8-6b3bcf0f50-656f696d3c.zip rename to .yarn/cache/nock-npm-13.2.9-de18b54858-04a2dc60b4.zip index 274e4ceed..b5ccdd767 100644 Binary files a/.yarn/cache/nock-npm-13.2.8-6b3bcf0f50-656f696d3c.zip and b/.yarn/cache/nock-npm-13.2.9-de18b54858-04a2dc60b4.zip differ diff --git a/.yarn/cache/node-abi-npm-3.22.0-2db16ee8b1-ad76823920.zip b/.yarn/cache/node-abi-npm-3.26.0-1131f8cef7-01271cf7b7.zip similarity index 85% rename from .yarn/cache/node-abi-npm-3.22.0-2db16ee8b1-ad76823920.zip rename to .yarn/cache/node-abi-npm-3.26.0-1131f8cef7-01271cf7b7.zip index 0488174bf..dde7d9dce 100644 Binary files a/.yarn/cache/node-abi-npm-3.22.0-2db16ee8b1-ad76823920.zip and b/.yarn/cache/node-abi-npm-3.26.0-1131f8cef7-01271cf7b7.zip differ diff --git a/.yarn/cache/node-gyp-npm-9.0.0-0eccfca4d1-4d8ef8860f.zip b/.yarn/cache/node-gyp-npm-9.3.0-21c41a4dfd-589ddd3ed9.zip similarity index 59% rename from .yarn/cache/node-gyp-npm-9.0.0-0eccfca4d1-4d8ef8860f.zip rename to .yarn/cache/node-gyp-npm-9.3.0-21c41a4dfd-589ddd3ed9.zip index 417b1c24f..f1e4e6d34 100644 Binary files a/.yarn/cache/node-gyp-npm-9.0.0-0eccfca4d1-4d8ef8860f.zip and b/.yarn/cache/node-gyp-npm-9.3.0-21c41a4dfd-589ddd3ed9.zip differ diff --git a/.yarn/cache/node-releases-npm-2.0.5-ddba717991-e85d949add.zip b/.yarn/cache/node-releases-npm-2.0.5-ddba717991-e85d949add.zip deleted file mode 100644 index 82aaf5227..000000000 Binary files a/.yarn/cache/node-releases-npm-2.0.5-ddba717991-e85d949add.zip and /dev/null differ diff --git a/.yarn/cache/node-sass-npm-7.0.3-5d8f0c9b2f-7d577d0fb6.zip b/.yarn/cache/node-sass-npm-7.0.3-5d8f0c9b2f-7d577d0fb6.zip new file mode 100644 index 000000000..1eb432fe3 Binary files /dev/null and b/.yarn/cache/node-sass-npm-7.0.3-5d8f0c9b2f-7d577d0fb6.zip differ diff --git a/.yarn/cache/nopt-npm-6.0.0-5ea8050815-82149371f8.zip b/.yarn/cache/nopt-npm-6.0.0-5ea8050815-82149371f8.zip new file mode 100644 index 000000000..ce92f8631 Binary files /dev/null and b/.yarn/cache/nopt-npm-6.0.0-5ea8050815-82149371f8.zip differ diff --git a/.yarn/cache/normalize-package-data-npm-4.0.0-150eace0e2-b0f47de429.zip b/.yarn/cache/normalize-package-data-npm-4.0.1-2f74d18009-292e0aa740.zip similarity index 50% rename from .yarn/cache/normalize-package-data-npm-4.0.0-150eace0e2-b0f47de429.zip rename to .yarn/cache/normalize-package-data-npm-4.0.1-2f74d18009-292e0aa740.zip index ac91e3f49..f3140f4cf 100644 Binary files a/.yarn/cache/normalize-package-data-npm-4.0.0-150eace0e2-b0f47de429.zip and b/.yarn/cache/normalize-package-data-npm-4.0.1-2f74d18009-292e0aa740.zip differ diff --git a/.yarn/cache/normalize-url-npm-7.2.0-2b0a459e68-7753f081ee.zip b/.yarn/cache/normalize-url-npm-7.2.0-2b0a459e68-7753f081ee.zip new file mode 100644 index 000000000..042961f2a Binary files /dev/null and b/.yarn/cache/normalize-url-npm-7.2.0-2b0a459e68-7753f081ee.zip differ diff --git a/.yarn/cache/npm-bundled-npm-2.0.1-b14512ad18-7747293985.zip b/.yarn/cache/npm-bundled-npm-2.0.1-b14512ad18-7747293985.zip new file mode 100644 index 000000000..23d548ba7 Binary files /dev/null and b/.yarn/cache/npm-bundled-npm-2.0.1-b14512ad18-7747293985.zip differ diff --git a/.yarn/cache/npm-check-updates-npm-15.0.3-1bcb874e03-675eb3f490.zip b/.yarn/cache/npm-check-updates-npm-15.0.3-1bcb874e03-675eb3f490.zip deleted file mode 100644 index 93e5de423..000000000 Binary files a/.yarn/cache/npm-check-updates-npm-15.0.3-1bcb874e03-675eb3f490.zip and /dev/null differ diff --git a/.yarn/cache/npm-check-updates-npm-16.3.11-af8c9c16d0-fffd287ac1.zip b/.yarn/cache/npm-check-updates-npm-16.3.11-af8c9c16d0-fffd287ac1.zip new file mode 100644 index 000000000..db08c091e Binary files /dev/null and b/.yarn/cache/npm-check-updates-npm-16.3.11-af8c9c16d0-fffd287ac1.zip differ diff --git a/.yarn/cache/npm-normalize-package-bin-npm-2.0.0-1b0f4f2468-7c5379f9b1.zip b/.yarn/cache/npm-normalize-package-bin-npm-2.0.0-1b0f4f2468-7c5379f9b1.zip new file mode 100644 index 000000000..ed3445e26 Binary files /dev/null and b/.yarn/cache/npm-normalize-package-bin-npm-2.0.0-1b0f4f2468-7c5379f9b1.zip differ diff --git a/.yarn/cache/npm-package-arg-npm-9.1.0-b08550e522-277c214777.zip b/.yarn/cache/npm-package-arg-npm-9.1.0-b08550e522-277c214777.zip deleted file mode 100644 index c85e88031..000000000 Binary files a/.yarn/cache/npm-package-arg-npm-9.1.0-b08550e522-277c214777.zip and /dev/null differ diff --git a/.yarn/cache/npm-package-arg-npm-9.1.2-102a03ad31-3793488843.zip b/.yarn/cache/npm-package-arg-npm-9.1.2-102a03ad31-3793488843.zip new file mode 100644 index 000000000..fa77432f8 Binary files /dev/null and b/.yarn/cache/npm-package-arg-npm-9.1.2-102a03ad31-3793488843.zip differ diff --git a/.yarn/cache/npm-packlist-npm-5.1.1-38389ac20f-28dab15374.zip b/.yarn/cache/npm-packlist-npm-5.1.3-16be2a45cc-94cc9c6674.zip similarity index 90% rename from .yarn/cache/npm-packlist-npm-5.1.1-38389ac20f-28dab15374.zip rename to .yarn/cache/npm-packlist-npm-5.1.3-16be2a45cc-94cc9c6674.zip index 55a089b53..8927da014 100644 Binary files a/.yarn/cache/npm-packlist-npm-5.1.1-38389ac20f-28dab15374.zip and b/.yarn/cache/npm-packlist-npm-5.1.3-16be2a45cc-94cc9c6674.zip differ diff --git a/.yarn/cache/npm-pick-manifest-npm-7.0.1-cd3bcc8dff-9a4a8e64d2.zip b/.yarn/cache/npm-pick-manifest-npm-7.0.2-6da502b6d3-a93ec449c1.zip similarity index 82% rename from .yarn/cache/npm-pick-manifest-npm-7.0.1-cd3bcc8dff-9a4a8e64d2.zip rename to .yarn/cache/npm-pick-manifest-npm-7.0.2-6da502b6d3-a93ec449c1.zip index 11cb96e04..5648c1851 100644 Binary files a/.yarn/cache/npm-pick-manifest-npm-7.0.1-cd3bcc8dff-9a4a8e64d2.zip and b/.yarn/cache/npm-pick-manifest-npm-7.0.2-6da502b6d3-a93ec449c1.zip differ diff --git a/.yarn/cache/npm-registry-fetch-npm-13.1.1-d484645123-e085faf5cd.zip b/.yarn/cache/npm-registry-fetch-npm-13.1.1-d484645123-e085faf5cd.zip deleted file mode 100644 index 49f6b14a1..000000000 Binary files a/.yarn/cache/npm-registry-fetch-npm-13.1.1-d484645123-e085faf5cd.zip and /dev/null differ diff --git a/.yarn/cache/npm-registry-fetch-npm-13.3.1-1a3862f20e-5a941c2c79.zip b/.yarn/cache/npm-registry-fetch-npm-13.3.1-1a3862f20e-5a941c2c79.zip new file mode 100644 index 000000000..8c93d2b91 Binary files /dev/null and b/.yarn/cache/npm-registry-fetch-npm-13.3.1-1a3862f20e-5a941c2c79.zip differ diff --git a/.yarn/cache/nwsapi-npm-2.2.1-a1537f87af-6c21fcb695.zip b/.yarn/cache/nwsapi-npm-2.2.1-a1537f87af-6c21fcb695.zip deleted file mode 100644 index c39f4f90e..000000000 Binary files a/.yarn/cache/nwsapi-npm-2.2.1-a1537f87af-6c21fcb695.zip and /dev/null differ diff --git a/.yarn/cache/nwsapi-npm-2.2.2-b77040326c-4376910629.zip b/.yarn/cache/nwsapi-npm-2.2.2-b77040326c-4376910629.zip new file mode 100644 index 000000000..c44e18d97 Binary files /dev/null and b/.yarn/cache/nwsapi-npm-2.2.2-b77040326c-4376910629.zip differ diff --git a/.yarn/cache/object.assign-npm-4.1.2-d52edada1c-d621d832ed.zip b/.yarn/cache/object.assign-npm-4.1.2-d52edada1c-d621d832ed.zip deleted file mode 100644 index 0031b9781..000000000 Binary files a/.yarn/cache/object.assign-npm-4.1.2-d52edada1c-d621d832ed.zip and /dev/null differ diff --git a/.yarn/cache/object.assign-npm-4.1.4-fb3deb1c3a-76cab513a5.zip b/.yarn/cache/object.assign-npm-4.1.4-fb3deb1c3a-76cab513a5.zip new file mode 100644 index 000000000..8a1fef055 Binary files /dev/null and b/.yarn/cache/object.assign-npm-4.1.4-fb3deb1c3a-76cab513a5.zip differ diff --git a/.yarn/cache/orderedmap-npm-2.0.0-4739cf1a6a-ccb835deb4.zip b/.yarn/cache/orderedmap-npm-2.0.0-4739cf1a6a-ccb835deb4.zip deleted file mode 100644 index 07cf64ae0..000000000 Binary files a/.yarn/cache/orderedmap-npm-2.0.0-4739cf1a6a-ccb835deb4.zip and /dev/null differ diff --git a/.yarn/cache/orderedmap-npm-2.1.0-0135fadc5b-af3f2bd3b7.zip b/.yarn/cache/orderedmap-npm-2.1.0-0135fadc5b-af3f2bd3b7.zip new file mode 100644 index 000000000..ef308d47c Binary files /dev/null and b/.yarn/cache/orderedmap-npm-2.1.0-0135fadc5b-af3f2bd3b7.zip differ diff --git a/.yarn/cache/pacote-npm-13.6.1-5bb9ef467e-26cebb59ae.zip b/.yarn/cache/pacote-npm-13.6.1-5bb9ef467e-26cebb59ae.zip deleted file mode 100644 index dd6efc997..000000000 Binary files a/.yarn/cache/pacote-npm-13.6.1-5bb9ef467e-26cebb59ae.zip and /dev/null differ diff --git a/.yarn/cache/pacote-npm-13.6.2-1018a3151b-a7b7f97094.zip b/.yarn/cache/pacote-npm-13.6.2-1018a3151b-a7b7f97094.zip new file mode 100644 index 000000000..e49681ec7 Binary files /dev/null and b/.yarn/cache/pacote-npm-13.6.2-1018a3151b-a7b7f97094.zip differ diff --git a/.yarn/cache/parse-path-npm-4.0.4-6a095a43a2-909e628c35.zip b/.yarn/cache/parse-path-npm-4.0.4-6a095a43a2-909e628c35.zip deleted file mode 100644 index bb93e59f7..000000000 Binary files a/.yarn/cache/parse-path-npm-4.0.4-6a095a43a2-909e628c35.zip and /dev/null differ diff --git a/.yarn/cache/parse-path-npm-7.0.0-ceda41e594-244b46523a.zip b/.yarn/cache/parse-path-npm-7.0.0-ceda41e594-244b46523a.zip new file mode 100644 index 000000000..f11412e15 Binary files /dev/null and b/.yarn/cache/parse-path-npm-7.0.0-ceda41e594-244b46523a.zip differ diff --git a/.yarn/cache/parse-url-npm-6.0.2-f349157ca2-cbd11ad5e5.zip b/.yarn/cache/parse-url-npm-6.0.2-f349157ca2-cbd11ad5e5.zip deleted file mode 100644 index d96c9b3f4..000000000 Binary files a/.yarn/cache/parse-url-npm-6.0.2-f349157ca2-cbd11ad5e5.zip and /dev/null differ diff --git a/.yarn/cache/parse-url-npm-8.1.0-0995f15c34-b93e21ab4c.zip b/.yarn/cache/parse-url-npm-8.1.0-0995f15c34-b93e21ab4c.zip new file mode 100644 index 000000000..1b5684a56 Binary files /dev/null and b/.yarn/cache/parse-url-npm-8.1.0-0995f15c34-b93e21ab4c.zip differ diff --git a/.yarn/cache/parse5-npm-7.0.0-3158a72394-7da5d61cc1.zip b/.yarn/cache/parse5-npm-7.0.0-3158a72394-7da5d61cc1.zip deleted file mode 100644 index 3159f21f0..000000000 Binary files a/.yarn/cache/parse5-npm-7.0.0-3158a72394-7da5d61cc1.zip and /dev/null differ diff --git a/.yarn/cache/parse5-npm-7.1.1-27fa6524c4-8f72fbfa6d.zip b/.yarn/cache/parse5-npm-7.1.1-27fa6524c4-8f72fbfa6d.zip new file mode 100644 index 000000000..480cbdc8e Binary files /dev/null and b/.yarn/cache/parse5-npm-7.1.1-27fa6524c4-8f72fbfa6d.zip differ diff --git a/.yarn/cache/plist-npm-3.0.5-7ac7035402-f8b82816f6.zip b/.yarn/cache/plist-npm-3.0.5-7ac7035402-f8b82816f6.zip deleted file mode 100644 index bc7dca23f..000000000 Binary files a/.yarn/cache/plist-npm-3.0.5-7ac7035402-f8b82816f6.zip and /dev/null differ diff --git a/.yarn/cache/plist-npm-3.0.6-19666ae92c-e21390fab8.zip b/.yarn/cache/plist-npm-3.0.6-19666ae92c-e21390fab8.zip new file mode 100644 index 000000000..0885498e0 Binary files /dev/null and b/.yarn/cache/plist-npm-3.0.6-19666ae92c-e21390fab8.zip differ diff --git a/.yarn/cache/pod-install-npm-0.1.37-b05d104d7f-1044628631.zip b/.yarn/cache/pod-install-npm-0.1.37-b05d104d7f-1044628631.zip deleted file mode 100644 index 956a25641..000000000 Binary files a/.yarn/cache/pod-install-npm-0.1.37-b05d104d7f-1044628631.zip and /dev/null differ diff --git a/.yarn/cache/pod-install-npm-0.1.38-b722289aa1-9ff3e8f50d.zip b/.yarn/cache/pod-install-npm-0.1.38-b722289aa1-9ff3e8f50d.zip new file mode 100644 index 000000000..488db2f17 Binary files /dev/null and b/.yarn/cache/pod-install-npm-0.1.38-b722289aa1-9ff3e8f50d.zip differ diff --git a/.yarn/cache/portfinder-npm-1.0.28-12c37407ab-91fef602f1.zip b/.yarn/cache/portfinder-npm-1.0.28-12c37407ab-91fef602f1.zip deleted file mode 100644 index df1bbba2e..000000000 Binary files a/.yarn/cache/portfinder-npm-1.0.28-12c37407ab-91fef602f1.zip and /dev/null differ diff --git a/.yarn/cache/portfinder-npm-1.0.32-20cc84ebcf-116b4aed1b.zip b/.yarn/cache/portfinder-npm-1.0.32-20cc84ebcf-116b4aed1b.zip new file mode 100644 index 000000000..ceccb9a87 Binary files /dev/null and b/.yarn/cache/portfinder-npm-1.0.32-20cc84ebcf-116b4aed1b.zip differ diff --git a/.yarn/cache/postcss-attribute-case-insensitive-npm-5.0.1-68c09ceed4-9abfe72b7c.zip b/.yarn/cache/postcss-attribute-case-insensitive-npm-5.0.1-68c09ceed4-9abfe72b7c.zip deleted file mode 100644 index 87b16cbd6..000000000 Binary files a/.yarn/cache/postcss-attribute-case-insensitive-npm-5.0.1-68c09ceed4-9abfe72b7c.zip and /dev/null differ diff --git a/.yarn/cache/postcss-attribute-case-insensitive-npm-5.0.2-6aa24bfafa-c0b8139f37.zip b/.yarn/cache/postcss-attribute-case-insensitive-npm-5.0.2-6aa24bfafa-c0b8139f37.zip new file mode 100644 index 000000000..8195f331f Binary files /dev/null and b/.yarn/cache/postcss-attribute-case-insensitive-npm-5.0.2-6aa24bfafa-c0b8139f37.zip differ diff --git a/.yarn/cache/postcss-color-functional-notation-npm-4.2.3-6cd789e54c-1be72dd64b.zip b/.yarn/cache/postcss-color-functional-notation-npm-4.2.3-6cd789e54c-1be72dd64b.zip deleted file mode 100644 index dd72c9fa0..000000000 Binary files a/.yarn/cache/postcss-color-functional-notation-npm-4.2.3-6cd789e54c-1be72dd64b.zip and /dev/null differ diff --git a/.yarn/cache/postcss-color-functional-notation-npm-4.2.4-8f3a9400c3-b763e164fe.zip b/.yarn/cache/postcss-color-functional-notation-npm-4.2.4-8f3a9400c3-b763e164fe.zip new file mode 100644 index 000000000..3c02982e9 Binary files /dev/null and b/.yarn/cache/postcss-color-functional-notation-npm-4.2.4-8f3a9400c3-b763e164fe.zip differ diff --git a/.yarn/cache/postcss-color-rebeccapurple-npm-7.1.0-93768cd172-48a3bb51d4.zip b/.yarn/cache/postcss-color-rebeccapurple-npm-7.1.1-b7828c0a0c-03482f9b81.zip similarity index 56% rename from .yarn/cache/postcss-color-rebeccapurple-npm-7.1.0-93768cd172-48a3bb51d4.zip rename to .yarn/cache/postcss-color-rebeccapurple-npm-7.1.1-b7828c0a0c-03482f9b81.zip index cd7802b0d..0dd5a1c02 100644 Binary files a/.yarn/cache/postcss-color-rebeccapurple-npm-7.1.0-93768cd172-48a3bb51d4.zip and b/.yarn/cache/postcss-color-rebeccapurple-npm-7.1.1-b7828c0a0c-03482f9b81.zip differ diff --git a/.yarn/cache/postcss-custom-properties-npm-12.1.8-c64b220d4f-4615b8181f.zip b/.yarn/cache/postcss-custom-properties-npm-12.1.8-c64b220d4f-4615b8181f.zip deleted file mode 100644 index cc2b0ad0c..000000000 Binary files a/.yarn/cache/postcss-custom-properties-npm-12.1.8-c64b220d4f-4615b8181f.zip and /dev/null differ diff --git a/.yarn/cache/postcss-custom-properties-npm-12.1.9-1b598d28a1-db4194665b.zip b/.yarn/cache/postcss-custom-properties-npm-12.1.9-1b598d28a1-db4194665b.zip new file mode 100644 index 000000000..577a881e6 Binary files /dev/null and b/.yarn/cache/postcss-custom-properties-npm-12.1.9-1b598d28a1-db4194665b.zip differ diff --git a/.yarn/cache/postcss-dir-pseudo-class-npm-6.0.4-660236d1ec-e493e6ed54.zip b/.yarn/cache/postcss-dir-pseudo-class-npm-6.0.4-660236d1ec-e493e6ed54.zip deleted file mode 100644 index 5f98e325c..000000000 Binary files a/.yarn/cache/postcss-dir-pseudo-class-npm-6.0.4-660236d1ec-e493e6ed54.zip and /dev/null differ diff --git a/.yarn/cache/postcss-dir-pseudo-class-npm-6.0.5-2555aeb05f-7810c439d8.zip b/.yarn/cache/postcss-dir-pseudo-class-npm-6.0.5-2555aeb05f-7810c439d8.zip new file mode 100644 index 000000000..cf9902e6a Binary files /dev/null and b/.yarn/cache/postcss-dir-pseudo-class-npm-6.0.5-2555aeb05f-7810c439d8.zip differ diff --git a/.yarn/cache/postcss-double-position-gradients-npm-3.1.1-ae1171586e-c59131b2d0.zip b/.yarn/cache/postcss-double-position-gradients-npm-3.1.2-278f758391-ca09bf2aef.zip similarity index 53% rename from .yarn/cache/postcss-double-position-gradients-npm-3.1.1-ae1171586e-c59131b2d0.zip rename to .yarn/cache/postcss-double-position-gradients-npm-3.1.2-278f758391-ca09bf2aef.zip index b6dfa1d00..fd0bd31ff 100644 Binary files a/.yarn/cache/postcss-double-position-gradients-npm-3.1.1-ae1171586e-c59131b2d0.zip and b/.yarn/cache/postcss-double-position-gradients-npm-3.1.2-278f758391-ca09bf2aef.zip differ diff --git a/.yarn/cache/postcss-gap-properties-npm-3.0.3-b9358e381e-8b7bb42920.zip b/.yarn/cache/postcss-gap-properties-npm-3.0.5-78f268ad64-aed559d6d3.zip similarity index 56% rename from .yarn/cache/postcss-gap-properties-npm-3.0.3-b9358e381e-8b7bb42920.zip rename to .yarn/cache/postcss-gap-properties-npm-3.0.5-78f268ad64-aed559d6d3.zip index c05498a4e..49d99fb39 100644 Binary files a/.yarn/cache/postcss-gap-properties-npm-3.0.3-b9358e381e-8b7bb42920.zip and b/.yarn/cache/postcss-gap-properties-npm-3.0.5-78f268ad64-aed559d6d3.zip differ diff --git a/.yarn/cache/postcss-image-set-function-npm-4.0.6-79c36fa099-bdcd11d5ef.zip b/.yarn/cache/postcss-image-set-function-npm-4.0.7-46769dca3e-7e50933098.zip similarity index 53% rename from .yarn/cache/postcss-image-set-function-npm-4.0.6-79c36fa099-bdcd11d5ef.zip rename to .yarn/cache/postcss-image-set-function-npm-4.0.7-46769dca3e-7e50933098.zip index eca0cdff5..35af1e1c0 100644 Binary files a/.yarn/cache/postcss-image-set-function-npm-4.0.6-79c36fa099-bdcd11d5ef.zip and b/.yarn/cache/postcss-image-set-function-npm-4.0.7-46769dca3e-7e50933098.zip differ diff --git a/.yarn/cache/postcss-lab-function-npm-4.2.0-6f2e01b320-89ca828b8e.zip b/.yarn/cache/postcss-lab-function-npm-4.2.0-6f2e01b320-89ca828b8e.zip deleted file mode 100644 index 1ea1e7382..000000000 Binary files a/.yarn/cache/postcss-lab-function-npm-4.2.0-6f2e01b320-89ca828b8e.zip and /dev/null differ diff --git a/.yarn/cache/postcss-lab-function-npm-4.2.1-1ebd916151-26ac74b430.zip b/.yarn/cache/postcss-lab-function-npm-4.2.1-1ebd916151-26ac74b430.zip new file mode 100644 index 000000000..962a6e6c7 Binary files /dev/null and b/.yarn/cache/postcss-lab-function-npm-4.2.1-1ebd916151-26ac74b430.zip differ diff --git a/.yarn/cache/postcss-loader-npm-7.0.0-e0a0c61fcd-b8e51e9989.zip b/.yarn/cache/postcss-loader-npm-7.0.0-e0a0c61fcd-b8e51e9989.zip deleted file mode 100644 index 944aeea2d..000000000 Binary files a/.yarn/cache/postcss-loader-npm-7.0.0-e0a0c61fcd-b8e51e9989.zip and /dev/null differ diff --git a/.yarn/cache/postcss-nesting-npm-10.1.10-9d5cf3d2c4-fffaf42aaa.zip b/.yarn/cache/postcss-nesting-npm-10.1.10-9d5cf3d2c4-fffaf42aaa.zip deleted file mode 100644 index e79003555..000000000 Binary files a/.yarn/cache/postcss-nesting-npm-10.1.10-9d5cf3d2c4-fffaf42aaa.zip and /dev/null differ diff --git a/.yarn/cache/postcss-nesting-npm-10.2.0-eec5f664e8-25e6e66186.zip b/.yarn/cache/postcss-nesting-npm-10.2.0-eec5f664e8-25e6e66186.zip new file mode 100644 index 000000000..28d03002b Binary files /dev/null and b/.yarn/cache/postcss-nesting-npm-10.2.0-eec5f664e8-25e6e66186.zip differ diff --git a/.yarn/cache/postcss-npm-8.4.14-c0d448b728-fe58766ff3.zip b/.yarn/cache/postcss-npm-8.4.14-c0d448b728-fe58766ff3.zip deleted file mode 100644 index 63ace659e..000000000 Binary files a/.yarn/cache/postcss-npm-8.4.14-c0d448b728-fe58766ff3.zip and /dev/null differ diff --git a/.yarn/cache/postcss-npm-8.4.16-7367383579-10eee25efd.zip b/.yarn/cache/postcss-npm-8.4.18-f1d73c0a84-9349fd9984.zip similarity index 83% rename from .yarn/cache/postcss-npm-8.4.16-7367383579-10eee25efd.zip rename to .yarn/cache/postcss-npm-8.4.18-f1d73c0a84-9349fd9984.zip index d1850d656..2955faf8c 100644 Binary files a/.yarn/cache/postcss-npm-8.4.16-7367383579-10eee25efd.zip and b/.yarn/cache/postcss-npm-8.4.18-f1d73c0a84-9349fd9984.zip differ diff --git a/.yarn/cache/postcss-overflow-shorthand-npm-3.0.3-0c0f2150ef-52080efd1c.zip b/.yarn/cache/postcss-overflow-shorthand-npm-3.0.4-b5a0785c77-7400902249.zip similarity index 54% rename from .yarn/cache/postcss-overflow-shorthand-npm-3.0.3-0c0f2150ef-52080efd1c.zip rename to .yarn/cache/postcss-overflow-shorthand-npm-3.0.4-b5a0785c77-7400902249.zip index dae781dd5..accfb9b27 100644 Binary files a/.yarn/cache/postcss-overflow-shorthand-npm-3.0.3-0c0f2150ef-52080efd1c.zip and b/.yarn/cache/postcss-overflow-shorthand-npm-3.0.4-b5a0785c77-7400902249.zip differ diff --git a/.yarn/cache/postcss-place-npm-7.0.4-3aadacab0a-dd1738ec9b.zip b/.yarn/cache/postcss-place-npm-7.0.5-895593f8b4-903fec0c31.zip similarity index 51% rename from .yarn/cache/postcss-place-npm-7.0.4-3aadacab0a-dd1738ec9b.zip rename to .yarn/cache/postcss-place-npm-7.0.5-895593f8b4-903fec0c31.zip index d0215b5a3..b8e3db21e 100644 Binary files a/.yarn/cache/postcss-place-npm-7.0.4-3aadacab0a-dd1738ec9b.zip and b/.yarn/cache/postcss-place-npm-7.0.5-895593f8b4-903fec0c31.zip differ diff --git a/.yarn/cache/postcss-preset-env-npm-7.7.2-7b47fdf8c3-15648b4f4e.zip b/.yarn/cache/postcss-preset-env-npm-7.7.2-7b47fdf8c3-15648b4f4e.zip deleted file mode 100644 index dd253d92b..000000000 Binary files a/.yarn/cache/postcss-preset-env-npm-7.7.2-7b47fdf8c3-15648b4f4e.zip and /dev/null differ diff --git a/.yarn/cache/postcss-preset-env-npm-7.8.2-768a1a1e4d-ffe86bef47.zip b/.yarn/cache/postcss-preset-env-npm-7.8.2-768a1a1e4d-ffe86bef47.zip new file mode 100644 index 000000000..36d0a77cb Binary files /dev/null and b/.yarn/cache/postcss-preset-env-npm-7.8.2-768a1a1e4d-ffe86bef47.zip differ diff --git a/.yarn/cache/postcss-pseudo-class-any-link-npm-7.1.5-e78bc16fcb-b2aaa1e75d.zip b/.yarn/cache/postcss-pseudo-class-any-link-npm-7.1.5-e78bc16fcb-b2aaa1e75d.zip deleted file mode 100644 index 1a2687e26..000000000 Binary files a/.yarn/cache/postcss-pseudo-class-any-link-npm-7.1.5-e78bc16fcb-b2aaa1e75d.zip and /dev/null differ diff --git a/.yarn/cache/postcss-pseudo-class-any-link-npm-7.1.6-1a34600b0e-43aa18ea1e.zip b/.yarn/cache/postcss-pseudo-class-any-link-npm-7.1.6-1a34600b0e-43aa18ea1e.zip new file mode 100644 index 000000000..b661f5c4f Binary files /dev/null and b/.yarn/cache/postcss-pseudo-class-any-link-npm-7.1.6-1a34600b0e-43aa18ea1e.zip differ diff --git a/.yarn/cache/postcss-selector-not-npm-6.0.0-065b34b722-d7aac5810a.zip b/.yarn/cache/postcss-selector-not-npm-6.0.0-065b34b722-d7aac5810a.zip deleted file mode 100644 index 4ccd90123..000000000 Binary files a/.yarn/cache/postcss-selector-not-npm-6.0.0-065b34b722-d7aac5810a.zip and /dev/null differ diff --git a/.yarn/cache/postcss-selector-not-npm-6.0.1-135f19a20c-fe523a0219.zip b/.yarn/cache/postcss-selector-not-npm-6.0.1-135f19a20c-fe523a0219.zip new file mode 100644 index 000000000..40b3d819d Binary files /dev/null and b/.yarn/cache/postcss-selector-not-npm-6.0.1-135f19a20c-fe523a0219.zip differ diff --git a/.yarn/cache/postcss-sort-media-queries-npm-4.2.1-813d0a974a-56a4363ce9.zip b/.yarn/cache/postcss-sort-media-queries-npm-4.3.0-ca46fe7408-7bf9fcde74.zip similarity index 54% rename from .yarn/cache/postcss-sort-media-queries-npm-4.2.1-813d0a974a-56a4363ce9.zip rename to .yarn/cache/postcss-sort-media-queries-npm-4.3.0-ca46fe7408-7bf9fcde74.zip index d9f10563e..c0e97ce74 100644 Binary files a/.yarn/cache/postcss-sort-media-queries-npm-4.2.1-813d0a974a-56a4363ce9.zip and b/.yarn/cache/postcss-sort-media-queries-npm-4.3.0-ca46fe7408-7bf9fcde74.zip differ diff --git a/.yarn/cache/pretty-format-npm-28.1.1-0ea4ce5004-7fde4e2d6f.zip b/.yarn/cache/pretty-format-npm-28.1.3-fdf56e33bc-e69f857358.zip similarity index 92% rename from .yarn/cache/pretty-format-npm-28.1.1-0ea4ce5004-7fde4e2d6f.zip rename to .yarn/cache/pretty-format-npm-28.1.3-fdf56e33bc-e69f857358.zip index 27c2aed29..f5ecc5aed 100644 Binary files a/.yarn/cache/pretty-format-npm-28.1.1-0ea4ce5004-7fde4e2d6f.zip and b/.yarn/cache/pretty-format-npm-28.1.3-fdf56e33bc-e69f857358.zip differ diff --git a/.yarn/cache/pretty-format-npm-29.0.3-c339768dec-239aa73b09.zip b/.yarn/cache/pretty-format-npm-29.1.2-37c8a710ba-b2c6e77666.zip similarity index 95% rename from .yarn/cache/pretty-format-npm-29.0.3-c339768dec-239aa73b09.zip rename to .yarn/cache/pretty-format-npm-29.1.2-37c8a710ba-b2c6e77666.zip index 2d5a5c66b..4ae64970c 100644 Binary files a/.yarn/cache/pretty-format-npm-29.0.3-c339768dec-239aa73b09.zip and b/.yarn/cache/pretty-format-npm-29.1.2-37c8a710ba-b2c6e77666.zip differ diff --git a/.yarn/cache/prismjs-npm-1.28.0-28f20a79ff-bde93fb2be.zip b/.yarn/cache/prismjs-npm-1.29.0-6faa5b04b8-007a8869d4.zip similarity index 78% rename from .yarn/cache/prismjs-npm-1.28.0-28f20a79ff-bde93fb2be.zip rename to .yarn/cache/prismjs-npm-1.29.0-6faa5b04b8-007a8869d4.zip index 8f2e4f2ea..25137aad3 100644 Binary files a/.yarn/cache/prismjs-npm-1.28.0-28f20a79ff-bde93fb2be.zip and b/.yarn/cache/prismjs-npm-1.29.0-6faa5b04b8-007a8869d4.zip differ diff --git a/.yarn/cache/promise-npm-8.1.0-09977f1805-89b71a5615.zip b/.yarn/cache/promise-npm-8.1.0-09977f1805-89b71a5615.zip deleted file mode 100644 index 7c4438e62..000000000 Binary files a/.yarn/cache/promise-npm-8.1.0-09977f1805-89b71a5615.zip and /dev/null differ diff --git a/.yarn/cache/promise-npm-8.2.0-3845bccde5-45d65ffe4f.zip b/.yarn/cache/promise-npm-8.2.0-3845bccde5-45d65ffe4f.zip new file mode 100644 index 000000000..01a9361ab Binary files /dev/null and b/.yarn/cache/promise-npm-8.2.0-3845bccde5-45d65ffe4f.zip differ diff --git a/.yarn/cache/prompts-ncu-npm-2.5.0-5d11c7d5b9-e050961c30.zip b/.yarn/cache/prompts-ncu-npm-2.5.1-586a5abf0b-e8b6479305.zip similarity index 88% rename from .yarn/cache/prompts-ncu-npm-2.5.0-5d11c7d5b9-e050961c30.zip rename to .yarn/cache/prompts-ncu-npm-2.5.1-586a5abf0b-e8b6479305.zip index df0c4a037..a63b6bd96 100644 Binary files a/.yarn/cache/prompts-ncu-npm-2.5.0-5d11c7d5b9-e050961c30.zip and b/.yarn/cache/prompts-ncu-npm-2.5.1-586a5abf0b-e8b6479305.zip differ diff --git a/.yarn/cache/prosemirror-commands-npm-1.3.0-2c4d72afe3-1e896b1ddc.zip b/.yarn/cache/prosemirror-commands-npm-1.3.0-2c4d72afe3-1e896b1ddc.zip deleted file mode 100644 index 5992927d4..000000000 Binary files a/.yarn/cache/prosemirror-commands-npm-1.3.0-2c4d72afe3-1e896b1ddc.zip and /dev/null differ diff --git a/.yarn/cache/prosemirror-commands-npm-1.3.1-fe1c45de67-6d5d740a05.zip b/.yarn/cache/prosemirror-commands-npm-1.3.1-fe1c45de67-6d5d740a05.zip new file mode 100644 index 000000000..616aaf9ed Binary files /dev/null and b/.yarn/cache/prosemirror-commands-npm-1.3.1-fe1c45de67-6d5d740a05.zip differ diff --git a/.yarn/cache/prosemirror-dropcursor-npm-1.5.0-11f95b3f71-3cf8c4cc76.zip b/.yarn/cache/prosemirror-dropcursor-npm-1.6.0-11722a44c0-ccfbb857bc.zip similarity index 72% rename from .yarn/cache/prosemirror-dropcursor-npm-1.5.0-11f95b3f71-3cf8c4cc76.zip rename to .yarn/cache/prosemirror-dropcursor-npm-1.6.0-11722a44c0-ccfbb857bc.zip index bb51e2df1..f2a6768f5 100644 Binary files a/.yarn/cache/prosemirror-dropcursor-npm-1.5.0-11f95b3f71-3cf8c4cc76.zip and b/.yarn/cache/prosemirror-dropcursor-npm-1.6.0-11722a44c0-ccfbb857bc.zip differ diff --git a/.yarn/cache/prosemirror-schema-list-npm-1.2.0-76bfbe2481-31d47e6a53.zip b/.yarn/cache/prosemirror-schema-list-npm-1.2.0-76bfbe2481-31d47e6a53.zip deleted file mode 100644 index 707520773..000000000 Binary files a/.yarn/cache/prosemirror-schema-list-npm-1.2.0-76bfbe2481-31d47e6a53.zip and /dev/null differ diff --git a/.yarn/cache/prosemirror-schema-list-npm-1.2.2-dd9fc18483-ddfa2f05bb.zip b/.yarn/cache/prosemirror-schema-list-npm-1.2.2-dd9fc18483-ddfa2f05bb.zip new file mode 100644 index 000000000..2da7d6b00 Binary files /dev/null and b/.yarn/cache/prosemirror-schema-list-npm-1.2.2-dd9fc18483-ddfa2f05bb.zip differ diff --git a/.yarn/cache/prosemirror-tables-npm-1.1.1-4bb1b6fcf3-26033de877.zip b/.yarn/cache/prosemirror-tables-npm-1.1.1-4bb1b6fcf3-26033de877.zip deleted file mode 100644 index f74b82704..000000000 Binary files a/.yarn/cache/prosemirror-tables-npm-1.1.1-4bb1b6fcf3-26033de877.zip and /dev/null differ diff --git a/.yarn/cache/prosemirror-tables-npm-1.2.5-1bc05dc868-4208368a28.zip b/.yarn/cache/prosemirror-tables-npm-1.2.5-1bc05dc868-4208368a28.zip new file mode 100644 index 000000000..91ea5c502 Binary files /dev/null and b/.yarn/cache/prosemirror-tables-npm-1.2.5-1bc05dc868-4208368a28.zip differ diff --git a/.yarn/cache/prosemirror-transform-npm-1.6.0-b5f6ad8b4a-b199b17052.zip b/.yarn/cache/prosemirror-transform-npm-1.6.0-b5f6ad8b4a-b199b17052.zip deleted file mode 100644 index 672c58bd3..000000000 Binary files a/.yarn/cache/prosemirror-transform-npm-1.6.0-b5f6ad8b4a-b199b17052.zip and /dev/null differ diff --git a/.yarn/cache/prosemirror-transform-npm-1.7.0-8c6cc0ac14-8d099ae0dc.zip b/.yarn/cache/prosemirror-transform-npm-1.7.0-8c6cc0ac14-8d099ae0dc.zip new file mode 100644 index 000000000..b77a825e5 Binary files /dev/null and b/.yarn/cache/prosemirror-transform-npm-1.7.0-8c6cc0ac14-8d099ae0dc.zip differ diff --git a/.yarn/cache/prosemirror-view-npm-1.26.4-7884a21bd7-28abbfc61b.zip b/.yarn/cache/prosemirror-view-npm-1.26.4-7884a21bd7-28abbfc61b.zip deleted file mode 100644 index 88d5275eb..000000000 Binary files a/.yarn/cache/prosemirror-view-npm-1.26.4-7884a21bd7-28abbfc61b.zip and /dev/null differ diff --git a/.yarn/cache/prosemirror-view-npm-1.29.0-ce819d77b0-6d4807a113.zip b/.yarn/cache/prosemirror-view-npm-1.29.0-ce819d77b0-6d4807a113.zip new file mode 100644 index 000000000..0fd8d3d0f Binary files /dev/null and b/.yarn/cache/prosemirror-view-npm-1.29.0-ce819d77b0-6d4807a113.zip differ diff --git a/.yarn/cache/protocols-npm-1.4.8-f05b04a69f-2d555c013d.zip b/.yarn/cache/protocols-npm-1.4.8-f05b04a69f-2d555c013d.zip deleted file mode 100644 index 9b437879b..000000000 Binary files a/.yarn/cache/protocols-npm-1.4.8-f05b04a69f-2d555c013d.zip and /dev/null differ diff --git a/.yarn/cache/qs-npm-6.10.3-172e1a3fb7-0fac5e6c71.zip b/.yarn/cache/qs-npm-6.10.3-172e1a3fb7-0fac5e6c71.zip deleted file mode 100644 index c8c26218e..000000000 Binary files a/.yarn/cache/qs-npm-6.10.3-172e1a3fb7-0fac5e6c71.zip and /dev/null differ diff --git a/.yarn/cache/query-string-npm-6.14.1-dad16e37e6-f2c7347578.zip b/.yarn/cache/query-string-npm-6.14.1-dad16e37e6-f2c7347578.zip deleted file mode 100644 index 8631913a9..000000000 Binary files a/.yarn/cache/query-string-npm-6.14.1-dad16e37e6-f2c7347578.zip and /dev/null differ diff --git a/.yarn/cache/query-string-npm-7.1.1-55c6f31f52-b227d1f588.zip b/.yarn/cache/query-string-npm-7.1.1-55c6f31f52-b227d1f588.zip deleted file mode 100644 index 42542d565..000000000 Binary files a/.yarn/cache/query-string-npm-7.1.1-55c6f31f52-b227d1f588.zip and /dev/null differ diff --git a/.yarn/cache/react-beautiful-dnd-npm-13.1.0-fcf5568b1c-12b7e9fbe8.zip b/.yarn/cache/react-beautiful-dnd-npm-13.1.1-ddc8adf565-5f90f7c0ab.zip similarity index 65% rename from .yarn/cache/react-beautiful-dnd-npm-13.1.0-fcf5568b1c-12b7e9fbe8.zip rename to .yarn/cache/react-beautiful-dnd-npm-13.1.1-ddc8adf565-5f90f7c0ab.zip index c56f82b2d..acd4ef28d 100644 Binary files a/.yarn/cache/react-beautiful-dnd-npm-13.1.0-fcf5568b1c-12b7e9fbe8.zip and b/.yarn/cache/react-beautiful-dnd-npm-13.1.1-ddc8adf565-5f90f7c0ab.zip differ diff --git a/.yarn/cache/react-devtools-core-npm-4.24.7-bca4dbd78c-1939e73730.zip b/.yarn/cache/react-devtools-core-npm-4.24.7-bca4dbd78c-1939e73730.zip deleted file mode 100644 index 4448ec78e..000000000 Binary files a/.yarn/cache/react-devtools-core-npm-4.24.7-bca4dbd78c-1939e73730.zip and /dev/null differ diff --git a/.yarn/cache/react-devtools-core-npm-4.26.0-3a6d40332d-82de66b531.zip b/.yarn/cache/react-devtools-core-npm-4.26.0-3a6d40332d-82de66b531.zip new file mode 100644 index 000000000..68661f3bb Binary files /dev/null and b/.yarn/cache/react-devtools-core-npm-4.26.0-3a6d40332d-82de66b531.zip differ diff --git a/.yarn/cache/react-devtools-npm-4.24.7-03a21e386b-297f6a2ba3.zip b/.yarn/cache/react-devtools-npm-4.26.0-5fc402b0df-e2aabcc9ad.zip similarity index 71% rename from .yarn/cache/react-devtools-npm-4.24.7-03a21e386b-297f6a2ba3.zip rename to .yarn/cache/react-devtools-npm-4.26.0-5fc402b0df-e2aabcc9ad.zip index f9a103d63..50dc14195 100644 Binary files a/.yarn/cache/react-devtools-npm-4.24.7-03a21e386b-297f6a2ba3.zip and b/.yarn/cache/react-devtools-npm-4.26.0-5fc402b0df-e2aabcc9ad.zip differ diff --git a/.yarn/cache/react-freeze-npm-1.0.0-63e3e3a53a-c746b9d369.zip b/.yarn/cache/react-freeze-npm-1.0.0-63e3e3a53a-c746b9d369.zip deleted file mode 100644 index 4cee139ea..000000000 Binary files a/.yarn/cache/react-freeze-npm-1.0.0-63e3e3a53a-c746b9d369.zip and /dev/null differ diff --git a/.yarn/cache/react-native-alternate-icons-https-ba967edfce-cecec14d93.zip b/.yarn/cache/react-native-alternate-icons-https-ba967edfce-cecec14d93.zip deleted file mode 100644 index 368917ba6..000000000 Binary files a/.yarn/cache/react-native-alternate-icons-https-ba967edfce-cecec14d93.zip and /dev/null differ diff --git a/.yarn/cache/react-native-default-preference-npm-1.4.4-cb57c3dd2d-6a1239741d.zip b/.yarn/cache/react-native-default-preference-npm-1.4.4-cb57c3dd2d-6a1239741d.zip deleted file mode 100644 index f45a6b493..000000000 Binary files a/.yarn/cache/react-native-default-preference-npm-1.4.4-cb57c3dd2d-6a1239741d.zip and /dev/null differ diff --git a/.yarn/cache/react-native-document-picker-npm-8.1.1-10a39bfbb1-d47cc8d742.zip b/.yarn/cache/react-native-document-picker-npm-8.1.1-10a39bfbb1-d47cc8d742.zip deleted file mode 100644 index 6c4ca5245..000000000 Binary files a/.yarn/cache/react-native-document-picker-npm-8.1.1-10a39bfbb1-d47cc8d742.zip and /dev/null differ diff --git a/.yarn/cache/react-native-fab-https-9ec64160a4-8463739091.zip b/.yarn/cache/react-native-fab-https-9ec64160a4-8463739091.zip deleted file mode 100644 index e90410b62..000000000 Binary files a/.yarn/cache/react-native-fab-https-9ec64160a4-8463739091.zip and /dev/null differ diff --git a/.yarn/cache/react-native-gesture-handler-npm-2.3.2-c45f0b71c7-d0d3cc4047.zip b/.yarn/cache/react-native-gesture-handler-npm-2.3.2-c45f0b71c7-d0d3cc4047.zip deleted file mode 100644 index dea252535..000000000 Binary files a/.yarn/cache/react-native-gesture-handler-npm-2.3.2-c45f0b71c7-d0d3cc4047.zip and /dev/null differ diff --git a/.yarn/cache/react-native-image-picker-npm-4.8.4-f0a5fc3e89-594de84172.zip b/.yarn/cache/react-native-image-picker-npm-4.8.4-f0a5fc3e89-594de84172.zip deleted file mode 100644 index 12e68b184..000000000 Binary files a/.yarn/cache/react-native-image-picker-npm-4.8.4-f0a5fc3e89-594de84172.zip and /dev/null differ diff --git a/.yarn/cache/react-native-mail-https-507e0acc37-66a52b8dca.zip b/.yarn/cache/react-native-mail-https-507e0acc37-66a52b8dca.zip deleted file mode 100644 index cec8baea0..000000000 Binary files a/.yarn/cache/react-native-mail-https-507e0acc37-66a52b8dca.zip and /dev/null differ diff --git a/.yarn/cache/react-native-reanimated-npm-2.9.1-cd6f7733a6-4ec8e62c86.zip b/.yarn/cache/react-native-reanimated-npm-2.9.1-cd6f7733a6-4ec8e62c86.zip deleted file mode 100644 index 4978e1ad9..000000000 Binary files a/.yarn/cache/react-native-reanimated-npm-2.9.1-cd6f7733a6-4ec8e62c86.zip and /dev/null differ diff --git a/.yarn/cache/react-native-safe-area-context-npm-4.3.1-d42fdb8470-34a4bc6044.zip b/.yarn/cache/react-native-safe-area-context-npm-4.3.1-d42fdb8470-34a4bc6044.zip deleted file mode 100644 index 0df52f1e6..000000000 Binary files a/.yarn/cache/react-native-safe-area-context-npm-4.3.1-d42fdb8470-34a4bc6044.zip and /dev/null differ diff --git a/.yarn/cache/react-native-screens-npm-3.13.1-20e6fc5832-aaab7071f6.zip b/.yarn/cache/react-native-screens-npm-3.13.1-20e6fc5832-aaab7071f6.zip deleted file mode 100644 index dc62c48ce..000000000 Binary files a/.yarn/cache/react-native-screens-npm-3.13.1-20e6fc5832-aaab7071f6.zip and /dev/null differ diff --git a/.yarn/cache/react-native-search-bar-https-5eeb4350f4-b8a25a5cb0.zip b/.yarn/cache/react-native-search-bar-https-5eeb4350f4-b8a25a5cb0.zip deleted file mode 100644 index b19d9c8d5..000000000 Binary files a/.yarn/cache/react-native-search-bar-https-5eeb4350f4-b8a25a5cb0.zip and /dev/null differ diff --git a/.yarn/cache/react-native-search-box-https-fb39c532db-58e057b998.zip b/.yarn/cache/react-native-search-box-https-fb39c532db-58e057b998.zip deleted file mode 100644 index 2c3fafaad..000000000 Binary files a/.yarn/cache/react-native-search-box-https-fb39c532db-58e057b998.zip and /dev/null differ diff --git a/.yarn/cache/react-native-share-npm-7.9.0-b553614939-8eb2f5b4be.zip b/.yarn/cache/react-native-share-npm-7.9.1-fb27b98242-276f872de7.zip similarity index 92% rename from .yarn/cache/react-native-share-npm-7.9.0-b553614939-8eb2f5b4be.zip rename to .yarn/cache/react-native-share-npm-7.9.1-fb27b98242-276f872de7.zip index 41ee9e47c..d0ee90f71 100644 Binary files a/.yarn/cache/react-native-share-npm-7.9.0-b553614939-8eb2f5b4be.zip and b/.yarn/cache/react-native-share-npm-7.9.1-fb27b98242-276f872de7.zip differ diff --git a/.yarn/cache/react-native-sodium-jsi-npm-1.2.0-120f42b455-9292e7a53c.zip b/.yarn/cache/react-native-sodium-jsi-npm-1.2.0-120f42b455-9292e7a53c.zip deleted file mode 100644 index fe18510b9..000000000 Binary files a/.yarn/cache/react-native-sodium-jsi-npm-1.2.0-120f42b455-9292e7a53c.zip and /dev/null differ diff --git a/.yarn/cache/react-native-static-server-https-33cfd18310-df37288bff.zip b/.yarn/cache/react-native-static-server-https-33cfd18310-df37288bff.zip deleted file mode 100644 index cdbc53d4c..000000000 Binary files a/.yarn/cache/react-native-static-server-https-33cfd18310-df37288bff.zip and /dev/null differ diff --git a/.yarn/cache/react-native-store-review-npm-0.2.1-c38beb6bf0-36e19879df.zip b/.yarn/cache/react-native-store-review-npm-0.2.1-c38beb6bf0-36e19879df.zip deleted file mode 100644 index 4301edf7b..000000000 Binary files a/.yarn/cache/react-native-store-review-npm-0.2.1-c38beb6bf0-36e19879df.zip and /dev/null differ diff --git a/.yarn/cache/react-native-svg-npm-12.3.0-9a1a7ae20d-9bed890d03.zip b/.yarn/cache/react-native-svg-npm-12.3.0-9a1a7ae20d-9bed890d03.zip deleted file mode 100644 index 44424b75e..000000000 Binary files a/.yarn/cache/react-native-svg-npm-12.3.0-9a1a7ae20d-9bed890d03.zip and /dev/null differ diff --git a/.yarn/cache/react-native-svg-transformer-npm-1.0.0-31f6d700cf-649ab64a64.zip b/.yarn/cache/react-native-svg-transformer-npm-1.0.0-31f6d700cf-649ab64a64.zip deleted file mode 100644 index fef1dbb40..000000000 Binary files a/.yarn/cache/react-native-svg-transformer-npm-1.0.0-31f6d700cf-649ab64a64.zip and /dev/null differ diff --git a/.yarn/cache/react-native-tab-view-npm-3.1.1-d9ad4f1aaa-8866e746f9.zip b/.yarn/cache/react-native-tab-view-npm-3.1.1-d9ad4f1aaa-8866e746f9.zip deleted file mode 100644 index e07d26cf2..000000000 Binary files a/.yarn/cache/react-native-tab-view-npm-3.1.1-d9ad4f1aaa-8866e746f9.zip and /dev/null differ diff --git a/.yarn/cache/react-native-toast-message-npm-2.1.5-5254ba79be-01005d7735.zip b/.yarn/cache/react-native-toast-message-npm-2.1.5-5254ba79be-01005d7735.zip deleted file mode 100644 index 79665111b..000000000 Binary files a/.yarn/cache/react-native-toast-message-npm-2.1.5-5254ba79be-01005d7735.zip and /dev/null differ diff --git a/.yarn/cache/react-native-url-polyfill-npm-1.3.0-069da56445-24ef81493a.zip b/.yarn/cache/react-native-url-polyfill-npm-1.3.0-069da56445-24ef81493a.zip deleted file mode 100644 index 45dbf6063..000000000 Binary files a/.yarn/cache/react-native-url-polyfill-npm-1.3.0-069da56445-24ef81493a.zip and /dev/null differ diff --git a/.yarn/cache/react-native-vector-icons-npm-9.2.0-7e7f70fd28-222baf88c3.zip b/.yarn/cache/react-native-vector-icons-npm-9.2.0-7e7f70fd28-222baf88c3.zip deleted file mode 100644 index 7237c79df..000000000 Binary files a/.yarn/cache/react-native-vector-icons-npm-9.2.0-7e7f70fd28-222baf88c3.zip and /dev/null differ diff --git a/.yarn/cache/react-native-zip-archive-npm-6.0.8-7c17daf1ec-c725e8f154.zip b/.yarn/cache/react-native-zip-archive-npm-6.0.8-7c17daf1ec-c725e8f154.zip deleted file mode 100644 index cc7ca0934..000000000 Binary files a/.yarn/cache/react-native-zip-archive-npm-6.0.8-7c17daf1ec-c725e8f154.zip and /dev/null differ diff --git a/.yarn/cache/react-navigation-header-buttons-npm-9.0.1-76fb9736b8-b2254a2603.zip b/.yarn/cache/react-navigation-header-buttons-npm-9.0.1-76fb9736b8-b2254a2603.zip deleted file mode 100644 index 10ebc1979..000000000 Binary files a/.yarn/cache/react-navigation-header-buttons-npm-9.0.1-76fb9736b8-b2254a2603.zip and /dev/null differ diff --git a/.yarn/cache/react-redux-npm-7.2.8-096f36457b-ecf1933e91.zip b/.yarn/cache/react-redux-npm-7.2.9-612aa35519-369a2bdcf8.zip similarity index 87% rename from .yarn/cache/react-redux-npm-7.2.8-096f36457b-ecf1933e91.zip rename to .yarn/cache/react-redux-npm-7.2.9-612aa35519-369a2bdcf8.zip index 044ddfdf8..9f9a8fd78 100644 Binary files a/.yarn/cache/react-redux-npm-7.2.8-096f36457b-ecf1933e91.zip and b/.yarn/cache/react-redux-npm-7.2.9-612aa35519-369a2bdcf8.zip differ diff --git a/.yarn/cache/react-remove-scroll-bar-npm-2.3.3-fac8e35ded-fc8c70014a.zip b/.yarn/cache/react-remove-scroll-bar-npm-2.3.3-fac8e35ded-fc8c70014a.zip deleted file mode 100644 index cb22949de..000000000 Binary files a/.yarn/cache/react-remove-scroll-bar-npm-2.3.3-fac8e35ded-fc8c70014a.zip and /dev/null differ diff --git a/.yarn/cache/react-remove-scroll-bar-npm-2.3.4-7d25bbed45-b5ce5f2f98.zip b/.yarn/cache/react-remove-scroll-bar-npm-2.3.4-7d25bbed45-b5ce5f2f98.zip new file mode 100644 index 000000000..ed04b2cb0 Binary files /dev/null and b/.yarn/cache/react-remove-scroll-bar-npm-2.3.4-7d25bbed45-b5ce5f2f98.zip differ diff --git a/.yarn/cache/react-router-dom-npm-5.3.3-dbff5ef5e3-e1998918e3.zip b/.yarn/cache/react-router-dom-npm-5.3.3-dbff5ef5e3-e1998918e3.zip deleted file mode 100644 index af75b1e87..000000000 Binary files a/.yarn/cache/react-router-dom-npm-5.3.3-dbff5ef5e3-e1998918e3.zip and /dev/null differ diff --git a/.yarn/cache/react-router-dom-npm-5.3.4-678cc1057f-b86a6f2f52.zip b/.yarn/cache/react-router-dom-npm-5.3.4-678cc1057f-b86a6f2f52.zip new file mode 100644 index 000000000..66e5c87e2 Binary files /dev/null and b/.yarn/cache/react-router-dom-npm-5.3.4-678cc1057f-b86a6f2f52.zip differ diff --git a/.yarn/cache/react-router-npm-5.3.3-594fcd8832-52a9f28fa9.zip b/.yarn/cache/react-router-npm-5.3.3-594fcd8832-52a9f28fa9.zip deleted file mode 100644 index b2f571b39..000000000 Binary files a/.yarn/cache/react-router-npm-5.3.3-594fcd8832-52a9f28fa9.zip and /dev/null differ diff --git a/.yarn/cache/react-router-npm-5.3.4-cc0757f6df-892d4e274a.zip b/.yarn/cache/react-router-npm-5.3.4-cc0757f6df-892d4e274a.zip new file mode 100644 index 000000000..134467786 Binary files /dev/null and b/.yarn/cache/react-router-npm-5.3.4-cc0757f6df-892d4e274a.zip differ diff --git a/.yarn/cache/read-package-json-npm-5.0.1-a5a303cfe6-e8c2ad72df.zip b/.yarn/cache/read-package-json-npm-5.0.2-a9701ba368-0882ac9cec.zip similarity index 86% rename from .yarn/cache/read-package-json-npm-5.0.1-a5a303cfe6-e8c2ad72df.zip rename to .yarn/cache/read-package-json-npm-5.0.2-a9701ba368-0882ac9cec.zip index 6916066a5..5e3499f0f 100644 Binary files a/.yarn/cache/read-package-json-npm-5.0.1-a5a303cfe6-e8c2ad72df.zip and b/.yarn/cache/read-package-json-npm-5.0.2-a9701ba368-0882ac9cec.zip differ diff --git a/.yarn/cache/refractor-npm-4.7.0-8bb075c835-85618d594b.zip b/.yarn/cache/refractor-npm-4.8.0-3a6fad5c89-57cda9deb6.zip similarity index 59% rename from .yarn/cache/refractor-npm-4.7.0-8bb075c835-85618d594b.zip rename to .yarn/cache/refractor-npm-4.8.0-3a6fad5c89-57cda9deb6.zip index 4448e24c8..953462a4c 100644 Binary files a/.yarn/cache/refractor-npm-4.7.0-8bb075c835-85618d594b.zip and b/.yarn/cache/refractor-npm-4.8.0-3a6fad5c89-57cda9deb6.zip differ diff --git a/.yarn/cache/regenerate-unicode-properties-npm-10.0.1-a750d23172-1b638b7087.zip b/.yarn/cache/regenerate-unicode-properties-npm-10.0.1-a750d23172-1b638b7087.zip deleted file mode 100644 index 1383a7aa3..000000000 Binary files a/.yarn/cache/regenerate-unicode-properties-npm-10.0.1-a750d23172-1b638b7087.zip and /dev/null differ diff --git a/.yarn/cache/regenerate-unicode-properties-npm-10.1.0-f0d5adf0df-b1a8929588.zip b/.yarn/cache/regenerate-unicode-properties-npm-10.1.0-f0d5adf0df-b1a8929588.zip new file mode 100644 index 000000000..cc0107c83 Binary files /dev/null and b/.yarn/cache/regenerate-unicode-properties-npm-10.1.0-f0d5adf0df-b1a8929588.zip differ diff --git a/.yarn/cache/regexpu-core-npm-5.1.0-ac0a69b941-7b4eb8d182.zip b/.yarn/cache/regexpu-core-npm-5.1.0-ac0a69b941-7b4eb8d182.zip deleted file mode 100644 index d852d02cc..000000000 Binary files a/.yarn/cache/regexpu-core-npm-5.1.0-ac0a69b941-7b4eb8d182.zip and /dev/null differ diff --git a/.yarn/cache/regexpu-core-npm-5.2.1-a3ca320a7f-c1244db79f.zip b/.yarn/cache/regexpu-core-npm-5.2.1-a3ca320a7f-c1244db79f.zip new file mode 100644 index 000000000..f064f9e7c Binary files /dev/null and b/.yarn/cache/regexpu-core-npm-5.2.1-a3ca320a7f-c1244db79f.zip differ diff --git a/.yarn/cache/regjsgen-npm-0.6.0-bae949467e-c5158ebd73.zip b/.yarn/cache/regjsgen-npm-0.6.0-bae949467e-c5158ebd73.zip deleted file mode 100644 index 77ed97173..000000000 Binary files a/.yarn/cache/regjsgen-npm-0.6.0-bae949467e-c5158ebd73.zip and /dev/null differ diff --git a/.yarn/cache/regjsgen-npm-0.7.1-953834bf22-7cac399921.zip b/.yarn/cache/regjsgen-npm-0.7.1-953834bf22-7cac399921.zip new file mode 100644 index 000000000..f31e5ea0f Binary files /dev/null and b/.yarn/cache/regjsgen-npm-0.7.1-953834bf22-7cac399921.zip differ diff --git a/.yarn/cache/regjsparser-npm-0.8.4-df84fdb4b8-d069b93249.zip b/.yarn/cache/regjsparser-npm-0.8.4-df84fdb4b8-d069b93249.zip deleted file mode 100644 index 118574db2..000000000 Binary files a/.yarn/cache/regjsparser-npm-0.8.4-df84fdb4b8-d069b93249.zip and /dev/null differ diff --git a/.yarn/cache/regjsparser-npm-0.9.1-47cd7c2ee2-5e1b76afe8.zip b/.yarn/cache/regjsparser-npm-0.9.1-47cd7c2ee2-5e1b76afe8.zip new file mode 100644 index 000000000..6c8bd3166 Binary files /dev/null and b/.yarn/cache/regjsparser-npm-0.9.1-47cd7c2ee2-5e1b76afe8.zip differ diff --git a/.yarn/cache/responselike-npm-2.0.0-7813864e97-6a4d32c37d.zip b/.yarn/cache/responselike-npm-2.0.0-7813864e97-6a4d32c37d.zip deleted file mode 100644 index 8a908923f..000000000 Binary files a/.yarn/cache/responselike-npm-2.0.0-7813864e97-6a4d32c37d.zip and /dev/null differ diff --git a/.yarn/cache/responselike-npm-3.0.0-9ab07af81f-e0cc9be30d.zip b/.yarn/cache/responselike-npm-3.0.0-9ab07af81f-e0cc9be30d.zip new file mode 100644 index 000000000..6e1abaf72 Binary files /dev/null and b/.yarn/cache/responselike-npm-3.0.0-9ab07af81f-e0cc9be30d.zip differ diff --git a/.yarn/cache/rollup-npm-2.75.7-3918160ee7-a6331d46b0.zip b/.yarn/cache/rollup-npm-2.75.7-3918160ee7-a6331d46b0.zip deleted file mode 100644 index 35ac2865b..000000000 Binary files a/.yarn/cache/rollup-npm-2.75.7-3918160ee7-a6331d46b0.zip and /dev/null differ diff --git a/.yarn/cache/rollup-npm-2.79.1-94e707a9a3-6a2bf167b3.zip b/.yarn/cache/rollup-npm-2.79.1-94e707a9a3-6a2bf167b3.zip new file mode 100644 index 000000000..84b099303 Binary files /dev/null and b/.yarn/cache/rollup-npm-2.79.1-94e707a9a3-6a2bf167b3.zip differ diff --git a/.yarn/cache/rxjs-npm-7.5.5-d0546b1ccb-e034f60805.zip b/.yarn/cache/rxjs-npm-7.5.7-602d5c56e4-edabcdb73b.zip similarity index 67% rename from .yarn/cache/rxjs-npm-7.5.5-d0546b1ccb-e034f60805.zip rename to .yarn/cache/rxjs-npm-7.5.7-602d5c56e4-edabcdb73b.zip index c7a67f471..63c9c28d9 100644 Binary files a/.yarn/cache/rxjs-npm-7.5.5-d0546b1ccb-e034f60805.zip and b/.yarn/cache/rxjs-npm-7.5.7-602d5c56e4-edabcdb73b.zip differ diff --git a/.yarn/cache/safe-regex-test-npm-1.0.0-e94a09b84e-bc566d8beb.zip b/.yarn/cache/safe-regex-test-npm-1.0.0-e94a09b84e-bc566d8beb.zip new file mode 100644 index 000000000..9e9dbfc63 Binary files /dev/null and b/.yarn/cache/safe-regex-test-npm-1.0.0-e94a09b84e-bc566d8beb.zip differ diff --git a/.yarn/cache/sass-graph-npm-4.0.1-62c3ce0d99-896f99253b.zip b/.yarn/cache/sass-graph-npm-4.0.1-62c3ce0d99-896f99253b.zip new file mode 100644 index 000000000..e10a3a75e Binary files /dev/null and b/.yarn/cache/sass-graph-npm-4.0.1-62c3ce0d99-896f99253b.zip differ diff --git a/.yarn/cache/sass-loader-npm-10.3.0-1721e8e2de-554144457c.zip b/.yarn/cache/sass-loader-npm-10.3.1-bf2637a8cb-ab73a41a8a.zip similarity index 52% rename from .yarn/cache/sass-loader-npm-10.3.0-1721e8e2de-554144457c.zip rename to .yarn/cache/sass-loader-npm-10.3.1-bf2637a8cb-ab73a41a8a.zip index 35bec8847..6af89a70d 100644 Binary files a/.yarn/cache/sass-loader-npm-10.3.0-1721e8e2de-554144457c.zip and b/.yarn/cache/sass-loader-npm-10.3.1-bf2637a8cb-ab73a41a8a.zip differ diff --git a/.yarn/cache/sass-loader-npm-13.0.2-ca68afd73d-6306712cc7.zip b/.yarn/cache/sass-loader-npm-13.0.2-ca68afd73d-6306712cc7.zip deleted file mode 100644 index 4e19c96da..000000000 Binary files a/.yarn/cache/sass-loader-npm-13.0.2-ca68afd73d-6306712cc7.zip and /dev/null differ diff --git a/.yarn/cache/sass-loader-npm-13.1.0-a57874dd1b-6b3b6c0e07.zip b/.yarn/cache/sass-loader-npm-13.1.0-a57874dd1b-6b3b6c0e07.zip new file mode 100644 index 000000000..cfcbc2705 Binary files /dev/null and b/.yarn/cache/sass-loader-npm-13.1.0-a57874dd1b-6b3b6c0e07.zip differ diff --git a/.yarn/cache/sass-npm-1.53.0-84886439f0-4bcb0617d6.zip b/.yarn/cache/sass-npm-1.53.0-84886439f0-4bcb0617d6.zip deleted file mode 100644 index 8a8d2a94b..000000000 Binary files a/.yarn/cache/sass-npm-1.53.0-84886439f0-4bcb0617d6.zip and /dev/null differ diff --git a/.yarn/cache/sass-npm-1.55.0-594c748a96-7d769ed08e.zip b/.yarn/cache/sass-npm-1.55.0-594c748a96-7d769ed08e.zip new file mode 100644 index 000000000..385f41b41 Binary files /dev/null and b/.yarn/cache/sass-npm-1.55.0-594c748a96-7d769ed08e.zip differ diff --git a/.yarn/cache/scss-tokenizer-npm-0.4.3-f6735ed4f7-f3697bb155.zip b/.yarn/cache/scss-tokenizer-npm-0.4.3-f6735ed4f7-f3697bb155.zip new file mode 100644 index 000000000..7100d426f Binary files /dev/null and b/.yarn/cache/scss-tokenizer-npm-0.4.3-f6735ed4f7-f3697bb155.zip differ diff --git a/.yarn/cache/selfsigned-npm-2.0.1-491b5e712c-864e65c2f3.zip b/.yarn/cache/selfsigned-npm-2.1.1-311d9b0b6d-aa9ce2150a.zip similarity index 81% rename from .yarn/cache/selfsigned-npm-2.0.1-491b5e712c-864e65c2f3.zip rename to .yarn/cache/selfsigned-npm-2.1.1-311d9b0b6d-aa9ce2150a.zip index 865ea738f..42d8556cb 100644 Binary files a/.yarn/cache/selfsigned-npm-2.0.1-491b5e712c-864e65c2f3.zip and b/.yarn/cache/selfsigned-npm-2.1.1-311d9b0b6d-aa9ce2150a.zip differ diff --git a/.yarn/cache/semver-npm-7.0.0-218e8c00ca-272c11bf8d.zip b/.yarn/cache/semver-npm-7.0.0-218e8c00ca-272c11bf8d.zip deleted file mode 100644 index 74b3f93cf..000000000 Binary files a/.yarn/cache/semver-npm-7.0.0-218e8c00ca-272c11bf8d.zip and /dev/null differ diff --git a/.yarn/cache/semver-npm-7.3.8-25a996cb4f-ba9c7cbbf2.zip b/.yarn/cache/semver-npm-7.3.8-25a996cb4f-ba9c7cbbf2.zip new file mode 100644 index 000000000..c6d8940e6 Binary files /dev/null and b/.yarn/cache/semver-npm-7.3.8-25a996cb4f-ba9c7cbbf2.zip differ diff --git a/.yarn/cache/shell-quote-npm-1.6.1-193629270d-982a4fdf2d.zip b/.yarn/cache/shell-quote-npm-1.6.1-193629270d-982a4fdf2d.zip deleted file mode 100644 index 4acb19041..000000000 Binary files a/.yarn/cache/shell-quote-npm-1.6.1-193629270d-982a4fdf2d.zip and /dev/null differ diff --git a/.yarn/cache/simple-plist-npm-1.3.1-867629e5dc-3890b49db5.zip b/.yarn/cache/simple-plist-npm-1.3.1-867629e5dc-3890b49db5.zip deleted file mode 100644 index 6261f1ead..000000000 Binary files a/.yarn/cache/simple-plist-npm-1.3.1-867629e5dc-3890b49db5.zip and /dev/null differ diff --git a/.yarn/cache/simple-plist-npm-1.4.0-e7f7c6ecb2-fa8086f6b7.zip b/.yarn/cache/simple-plist-npm-1.4.0-e7f7c6ecb2-fa8086f6b7.zip new file mode 100644 index 000000000..e8f5f1425 Binary files /dev/null and b/.yarn/cache/simple-plist-npm-1.4.0-e7f7c6ecb2-fa8086f6b7.zip differ diff --git a/.yarn/cache/socks-npm-2.6.2-94c1dcb8b8-dd91942930.zip b/.yarn/cache/socks-npm-2.6.2-94c1dcb8b8-dd91942930.zip deleted file mode 100644 index bec5d0ca3..000000000 Binary files a/.yarn/cache/socks-npm-2.6.2-94c1dcb8b8-dd91942930.zip and /dev/null differ diff --git a/.yarn/cache/socks-npm-2.7.1-17f2b53052-259d9e3e8e.zip b/.yarn/cache/socks-npm-2.7.1-17f2b53052-259d9e3e8e.zip new file mode 100644 index 000000000..f225cdefd Binary files /dev/null and b/.yarn/cache/socks-npm-2.7.1-17f2b53052-259d9e3e8e.zip differ diff --git a/.yarn/cache/sort-css-media-queries-npm-2.0.4-8f5038d864-610661adf5.zip b/.yarn/cache/sort-css-media-queries-npm-2.0.4-8f5038d864-610661adf5.zip deleted file mode 100644 index 80f2f56c3..000000000 Binary files a/.yarn/cache/sort-css-media-queries-npm-2.0.4-8f5038d864-610661adf5.zip and /dev/null differ diff --git a/.yarn/cache/sort-css-media-queries-npm-2.1.0-781449e923-25cb8f08b1.zip b/.yarn/cache/sort-css-media-queries-npm-2.1.0-781449e923-25cb8f08b1.zip new file mode 100644 index 000000000..f694f5662 Binary files /dev/null and b/.yarn/cache/sort-css-media-queries-npm-2.1.0-781449e923-25cb8f08b1.zip differ diff --git a/.yarn/cache/source-map-explorer-npm-2.5.2-2f924086cf-ff6748a5e1.zip b/.yarn/cache/source-map-explorer-npm-2.5.3-1f901669e9-1d4e619d7e.zip similarity index 75% rename from .yarn/cache/source-map-explorer-npm-2.5.2-2f924086cf-ff6748a5e1.zip rename to .yarn/cache/source-map-explorer-npm-2.5.3-1f901669e9-1d4e619d7e.zip index 98fbd89ad..0c0becd94 100644 Binary files a/.yarn/cache/source-map-explorer-npm-2.5.2-2f924086cf-ff6748a5e1.zip and b/.yarn/cache/source-map-explorer-npm-2.5.3-1f901669e9-1d4e619d7e.zip differ diff --git a/.yarn/cache/source-map-resolve-npm-0.6.0-6e67c9e55f-fe503b9e5d.zip b/.yarn/cache/source-map-resolve-npm-0.6.0-6e67c9e55f-fe503b9e5d.zip deleted file mode 100644 index b18eb56af..000000000 Binary files a/.yarn/cache/source-map-resolve-npm-0.6.0-6e67c9e55f-fe503b9e5d.zip and /dev/null differ diff --git a/.yarn/cache/spdx-license-ids-npm-3.0.11-a8d9a5ff74-1da1acb090.zip b/.yarn/cache/spdx-license-ids-npm-3.0.11-a8d9a5ff74-1da1acb090.zip deleted file mode 100644 index c8712c25e..000000000 Binary files a/.yarn/cache/spdx-license-ids-npm-3.0.11-a8d9a5ff74-1da1acb090.zip and /dev/null differ diff --git a/.yarn/cache/spdx-license-ids-npm-3.0.12-750216a0df-92a4dddce6.zip b/.yarn/cache/spdx-license-ids-npm-3.0.12-750216a0df-92a4dddce6.zip new file mode 100644 index 000000000..1bdd53ea5 Binary files /dev/null and b/.yarn/cache/spdx-license-ids-npm-3.0.12-750216a0df-92a4dddce6.zip differ diff --git a/.yarn/cache/split-on-first-npm-1.1.0-e2f3ab5e4e-16ff85b54d.zip b/.yarn/cache/split-on-first-npm-1.1.0-e2f3ab5e4e-16ff85b54d.zip deleted file mode 100644 index 8045223c5..000000000 Binary files a/.yarn/cache/split-on-first-npm-1.1.0-e2f3ab5e4e-16ff85b54d.zip and /dev/null differ diff --git a/.yarn/cache/std-env-npm-3.1.1-561b29a54e-7c8b34e9b8.zip b/.yarn/cache/std-env-npm-3.1.1-561b29a54e-7c8b34e9b8.zip deleted file mode 100644 index b198afe2c..000000000 Binary files a/.yarn/cache/std-env-npm-3.1.1-561b29a54e-7c8b34e9b8.zip and /dev/null differ diff --git a/.yarn/cache/std-env-npm-3.2.1-b30626bd3d-c046af2573.zip b/.yarn/cache/std-env-npm-3.2.1-b30626bd3d-c046af2573.zip new file mode 100644 index 000000000..f9cad18c5 Binary files /dev/null and b/.yarn/cache/std-env-npm-3.2.1-b30626bd3d-c046af2573.zip differ diff --git a/.yarn/cache/strict-uri-encode-npm-2.0.0-1ec3189376-eaac4cf978.zip b/.yarn/cache/strict-uri-encode-npm-2.0.0-1ec3189376-eaac4cf978.zip deleted file mode 100644 index 360da3af2..000000000 Binary files a/.yarn/cache/strict-uri-encode-npm-2.0.0-1ec3189376-eaac4cf978.zip and /dev/null differ diff --git a/.yarn/cache/string-hash-64-npm-1.0.3-c61b0cdf83-79de8431b4.zip b/.yarn/cache/string-hash-64-npm-1.0.3-c61b0cdf83-79de8431b4.zip deleted file mode 100644 index fd048a273..000000000 Binary files a/.yarn/cache/string-hash-64-npm-1.0.3-c61b0cdf83-79de8431b4.zip and /dev/null differ diff --git a/.yarn/cache/styled-components-npm-5.3.5-88e3937b59-05a664dfe4.zip b/.yarn/cache/styled-components-npm-5.3.5-88e3937b59-05a664dfe4.zip deleted file mode 100644 index 595230b30..000000000 Binary files a/.yarn/cache/styled-components-npm-5.3.5-88e3937b59-05a664dfe4.zip and /dev/null differ diff --git a/.yarn/cache/styled-components-npm-5.3.6-934fe4f344-68eac1e451.zip b/.yarn/cache/styled-components-npm-5.3.6-934fe4f344-68eac1e451.zip new file mode 100644 index 000000000..c2d113f4a Binary files /dev/null and b/.yarn/cache/styled-components-npm-5.3.6-934fe4f344-68eac1e451.zip differ diff --git a/.yarn/cache/stylis-npm-4.1.1-d5d28cbe16-e9b0a08699.zip b/.yarn/cache/stylis-npm-4.1.1-d5d28cbe16-e9b0a08699.zip deleted file mode 100644 index 6d5a66a5a..000000000 Binary files a/.yarn/cache/stylis-npm-4.1.1-d5d28cbe16-e9b0a08699.zip and /dev/null differ diff --git a/.yarn/cache/stylis-npm-4.1.2-c95b2a8ed4-de57715262.zip b/.yarn/cache/stylis-npm-4.1.2-c95b2a8ed4-de57715262.zip new file mode 100644 index 000000000..1ce50c886 Binary files /dev/null and b/.yarn/cache/stylis-npm-4.1.2-c95b2a8ed4-de57715262.zip differ diff --git a/.yarn/cache/supports-hyperlinks-npm-2.2.0-9b22a6271b-aef04fb41f.zip b/.yarn/cache/supports-hyperlinks-npm-2.3.0-d19176eba2-9ee0de3c8c.zip similarity index 56% rename from .yarn/cache/supports-hyperlinks-npm-2.2.0-9b22a6271b-aef04fb41f.zip rename to .yarn/cache/supports-hyperlinks-npm-2.3.0-d19176eba2-9ee0de3c8c.zip index bbb1bbd48..ebc23cc1b 100644 Binary files a/.yarn/cache/supports-hyperlinks-npm-2.2.0-9b22a6271b-aef04fb41f.zip and b/.yarn/cache/supports-hyperlinks-npm-2.3.0-d19176eba2-9ee0de3c8c.zip differ diff --git a/.yarn/cache/tailwindcss-npm-3.1.4-e6f25bb2a1-716b7d80e5.zip b/.yarn/cache/tailwindcss-npm-3.1.4-e6f25bb2a1-716b7d80e5.zip deleted file mode 100644 index 24dead5b9..000000000 Binary files a/.yarn/cache/tailwindcss-npm-3.1.4-e6f25bb2a1-716b7d80e5.zip and /dev/null differ diff --git a/.yarn/cache/terser-npm-4.8.0-272e3d2592-f980789097.zip b/.yarn/cache/terser-npm-4.8.0-272e3d2592-f980789097.zip deleted file mode 100644 index 7bb84c688..000000000 Binary files a/.yarn/cache/terser-npm-4.8.0-272e3d2592-f980789097.zip and /dev/null differ diff --git a/.yarn/cache/terser-npm-4.8.1-16347908cf-b342819bf7.zip b/.yarn/cache/terser-npm-4.8.1-16347908cf-b342819bf7.zip new file mode 100644 index 000000000..f1a2b061e Binary files /dev/null and b/.yarn/cache/terser-npm-4.8.1-16347908cf-b342819bf7.zip differ diff --git a/.yarn/cache/terser-npm-5.14.1-2c67379fd0-7b0e51f3d1.zip b/.yarn/cache/terser-npm-5.14.1-2c67379fd0-7b0e51f3d1.zip deleted file mode 100644 index ec079c958..000000000 Binary files a/.yarn/cache/terser-npm-5.14.1-2c67379fd0-7b0e51f3d1.zip and /dev/null differ diff --git a/.yarn/cache/terser-npm-5.15.0-a7f79b7859-b2358c989f.zip b/.yarn/cache/terser-npm-5.15.1-63dec1247d-9880a1e095.zip similarity index 50% rename from .yarn/cache/terser-npm-5.15.0-a7f79b7859-b2358c989f.zip rename to .yarn/cache/terser-npm-5.15.1-63dec1247d-9880a1e095.zip index 77c23300d..79fc04282 100644 Binary files a/.yarn/cache/terser-npm-5.15.0-a7f79b7859-b2358c989f.zip and b/.yarn/cache/terser-npm-5.15.1-63dec1247d-9880a1e095.zip differ diff --git a/.yarn/cache/terser-webpack-plugin-npm-5.3.3-659a8e4514-4b8d508d8a.zip b/.yarn/cache/terser-webpack-plugin-npm-5.3.3-659a8e4514-4b8d508d8a.zip deleted file mode 100644 index b02417795..000000000 Binary files a/.yarn/cache/terser-webpack-plugin-npm-5.3.3-659a8e4514-4b8d508d8a.zip and /dev/null differ diff --git a/.yarn/cache/tiny-invariant-npm-1.2.0-024338c59c-e09a718a7c.zip b/.yarn/cache/tiny-invariant-npm-1.2.0-024338c59c-e09a718a7c.zip deleted file mode 100644 index 70266ec24..000000000 Binary files a/.yarn/cache/tiny-invariant-npm-1.2.0-024338c59c-e09a718a7c.zip and /dev/null differ diff --git a/.yarn/cache/tiny-invariant-npm-1.3.1-a8ca214e49-872dbd1ff2.zip b/.yarn/cache/tiny-invariant-npm-1.3.1-a8ca214e49-872dbd1ff2.zip new file mode 100644 index 000000000..d15e4391a Binary files /dev/null and b/.yarn/cache/tiny-invariant-npm-1.3.1-a8ca214e49-872dbd1ff2.zip differ diff --git a/.yarn/cache/tough-cookie-npm-4.0.0-7c5f3086af-0891b37eb7.zip b/.yarn/cache/tough-cookie-npm-4.0.0-7c5f3086af-0891b37eb7.zip deleted file mode 100644 index dd3687b57..000000000 Binary files a/.yarn/cache/tough-cookie-npm-4.0.0-7c5f3086af-0891b37eb7.zip and /dev/null differ diff --git a/.yarn/cache/tough-cookie-npm-4.1.2-09068826e1-a7359e9a3e.zip b/.yarn/cache/tough-cookie-npm-4.1.2-09068826e1-a7359e9a3e.zip new file mode 100644 index 000000000..474ee1853 Binary files /dev/null and b/.yarn/cache/tough-cookie-npm-4.1.2-09068826e1-a7359e9a3e.zip differ diff --git a/.yarn/cache/ts-jest-npm-28.0.5-8c44d8b86f-53e05db5b7.zip b/.yarn/cache/ts-jest-npm-28.0.8-eeca582fd6-c72e929270.zip similarity index 57% rename from .yarn/cache/ts-jest-npm-28.0.5-8c44d8b86f-53e05db5b7.zip rename to .yarn/cache/ts-jest-npm-28.0.8-eeca582fd6-c72e929270.zip index 5f695e1b4..208b507a7 100644 Binary files a/.yarn/cache/ts-jest-npm-28.0.5-8c44d8b86f-53e05db5b7.zip and b/.yarn/cache/ts-jest-npm-28.0.8-eeca582fd6-c72e929270.zip differ diff --git a/.yarn/cache/ts-loader-npm-9.3.1-634433ef6a-462a8ac315.zip b/.yarn/cache/ts-loader-npm-9.3.1-634433ef6a-462a8ac315.zip deleted file mode 100644 index 7c16e5062..000000000 Binary files a/.yarn/cache/ts-loader-npm-9.3.1-634433ef6a-462a8ac315.zip and /dev/null differ diff --git a/.yarn/cache/ts-loader-npm-9.4.1-379dc021ff-b8947f6d39.zip b/.yarn/cache/ts-loader-npm-9.4.1-379dc021ff-b8947f6d39.zip new file mode 100644 index 000000000..3bf330293 Binary files /dev/null and b/.yarn/cache/ts-loader-npm-9.4.1-379dc021ff-b8947f6d39.zip differ diff --git a/.yarn/cache/ts-node-npm-10.8.2-f3c0c9eaee-1eede939be.zip b/.yarn/cache/ts-node-npm-10.8.2-f3c0c9eaee-1eede939be.zip deleted file mode 100644 index 61b690272..000000000 Binary files a/.yarn/cache/ts-node-npm-10.8.2-f3c0c9eaee-1eede939be.zip and /dev/null differ diff --git a/.yarn/cache/type-fest-npm-2.16.0-8d42df3332-897fc5f683.zip b/.yarn/cache/type-fest-npm-2.19.0-918b953248-a4ef07ece2.zip similarity index 50% rename from .yarn/cache/type-fest-npm-2.16.0-8d42df3332-897fc5f683.zip rename to .yarn/cache/type-fest-npm-2.19.0-918b953248-a4ef07ece2.zip index 00ffa3c98..e499820ab 100644 Binary files a/.yarn/cache/type-fest-npm-2.16.0-8d42df3332-897fc5f683.zip and b/.yarn/cache/type-fest-npm-2.19.0-918b953248-a4ef07ece2.zip differ diff --git a/.yarn/cache/typescript-npm-4.7.4-65aa6ffb42-5750181b1c.zip b/.yarn/cache/typescript-npm-4.7.3-edc6629fdf-fd13a1ce53.zip similarity index 63% rename from .yarn/cache/typescript-npm-4.7.4-65aa6ffb42-5750181b1c.zip rename to .yarn/cache/typescript-npm-4.7.3-edc6629fdf-fd13a1ce53.zip index 9dd083303..e050ea1c6 100644 Binary files a/.yarn/cache/typescript-npm-4.7.4-65aa6ffb42-5750181b1c.zip and b/.yarn/cache/typescript-npm-4.7.3-edc6629fdf-fd13a1ce53.zip differ diff --git a/.yarn/cache/typescript-npm-4.8.4-9c0a335511-3e4f061658.zip b/.yarn/cache/typescript-npm-4.8.4-9c0a335511-3e4f061658.zip new file mode 100644 index 000000000..ffe3d5cfb Binary files /dev/null and b/.yarn/cache/typescript-npm-4.8.4-9c0a335511-3e4f061658.zip differ diff --git a/.yarn/cache/typescript-patch-e8b9857d0c-9096d8f6c1.zip b/.yarn/cache/typescript-patch-e8f1acd78e-137d18a77f.zip similarity index 57% rename from .yarn/cache/typescript-patch-e8b9857d0c-9096d8f6c1.zip rename to .yarn/cache/typescript-patch-e8f1acd78e-137d18a77f.zip index 3b8bfa9b9..7bbf88f2a 100644 Binary files a/.yarn/cache/typescript-patch-e8b9857d0c-9096d8f6c1.zip and b/.yarn/cache/typescript-patch-e8f1acd78e-137d18a77f.zip differ diff --git a/.yarn/cache/typescript-patch-fd8e6362bb-563a0ef47a.zip b/.yarn/cache/typescript-patch-fd8e6362bb-563a0ef47a.zip new file mode 100644 index 000000000..902a50c7f Binary files /dev/null and b/.yarn/cache/typescript-patch-fd8e6362bb-563a0ef47a.zip differ diff --git a/.yarn/cache/typo-js-npm-1.2.1-e6e4c64baa-35726fd7c5.zip b/.yarn/cache/typo-js-npm-1.2.2-a71b33b3c4-425e5fbd52.zip similarity index 96% rename from .yarn/cache/typo-js-npm-1.2.1-e6e4c64baa-35726fd7c5.zip rename to .yarn/cache/typo-js-npm-1.2.2-a71b33b3c4-425e5fbd52.zip index 78df2c6fb..d2afb2a0f 100644 Binary files a/.yarn/cache/typo-js-npm-1.2.1-e6e4c64baa-35726fd7c5.zip and b/.yarn/cache/typo-js-npm-1.2.2-a71b33b3c4-425e5fbd52.zip differ diff --git a/.yarn/cache/uglify-js-npm-3.16.2-859e08ad93-5b62e748b7.zip b/.yarn/cache/uglify-js-npm-3.16.2-859e08ad93-5b62e748b7.zip deleted file mode 100644 index a1e9e2b5d..000000000 Binary files a/.yarn/cache/uglify-js-npm-3.16.2-859e08ad93-5b62e748b7.zip and /dev/null differ diff --git a/.yarn/cache/uglify-js-npm-3.17.3-e5b5a65475-2650b2e038.zip b/.yarn/cache/uglify-js-npm-3.17.3-e5b5a65475-2650b2e038.zip new file mode 100644 index 000000000..523d7c4f0 Binary files /dev/null and b/.yarn/cache/uglify-js-npm-3.17.3-e5b5a65475-2650b2e038.zip differ diff --git a/.yarn/cache/unicode-property-aliases-ecmascript-npm-2.0.0-1636cb7768-dda4d39128.zip b/.yarn/cache/unicode-property-aliases-ecmascript-npm-2.1.0-46779595f4-2435244318.zip similarity index 71% rename from .yarn/cache/unicode-property-aliases-ecmascript-npm-2.0.0-1636cb7768-dda4d39128.zip rename to .yarn/cache/unicode-property-aliases-ecmascript-npm-2.1.0-46779595f4-2435244318.zip index cdaff7663..be89e75a7 100644 Binary files a/.yarn/cache/unicode-property-aliases-ecmascript-npm-2.0.0-1636cb7768-dda4d39128.zip and b/.yarn/cache/unicode-property-aliases-ecmascript-npm-2.1.0-46779595f4-2435244318.zip differ diff --git a/.yarn/cache/unique-filename-npm-2.0.1-183c6c7c2b-807acf3381.zip b/.yarn/cache/unique-filename-npm-2.0.1-183c6c7c2b-807acf3381.zip new file mode 100644 index 000000000..1d4f41956 Binary files /dev/null and b/.yarn/cache/unique-filename-npm-2.0.1-183c6c7c2b-807acf3381.zip differ diff --git a/.yarn/cache/unique-slug-npm-3.0.0-0b82e51577-49f8d915ba.zip b/.yarn/cache/unique-slug-npm-3.0.0-0b82e51577-49f8d915ba.zip new file mode 100644 index 000000000..9e3f7f2f6 Binary files /dev/null and b/.yarn/cache/unique-slug-npm-3.0.0-0b82e51577-49f8d915ba.zip differ diff --git a/.yarn/cache/unist-util-visit-npm-4.1.0-71b0165ce5-3521abee2e.zip b/.yarn/cache/unist-util-visit-npm-4.1.0-71b0165ce5-3521abee2e.zip deleted file mode 100644 index 7f7519cb8..000000000 Binary files a/.yarn/cache/unist-util-visit-npm-4.1.0-71b0165ce5-3521abee2e.zip and /dev/null differ diff --git a/.yarn/cache/unist-util-visit-npm-4.1.1-d4ebc5dd61-c4a63734b0.zip b/.yarn/cache/unist-util-visit-npm-4.1.1-d4ebc5dd61-c4a63734b0.zip new file mode 100644 index 000000000..e0e9a7699 Binary files /dev/null and b/.yarn/cache/unist-util-visit-npm-4.1.1-d4ebc5dd61-c4a63734b0.zip differ diff --git a/.yarn/cache/unist-util-visit-parents-npm-5.1.0-5b9348080b-7c413dbb3d.zip b/.yarn/cache/unist-util-visit-parents-npm-5.1.0-5b9348080b-7c413dbb3d.zip deleted file mode 100644 index f66f351bc..000000000 Binary files a/.yarn/cache/unist-util-visit-parents-npm-5.1.0-5b9348080b-7c413dbb3d.zip and /dev/null differ diff --git a/.yarn/cache/unist-util-visit-parents-npm-5.1.1-fe9eee5f6b-c699d18f5b.zip b/.yarn/cache/unist-util-visit-parents-npm-5.1.1-fe9eee5f6b-c699d18f5b.zip new file mode 100644 index 000000000..d4f1c1ea1 Binary files /dev/null and b/.yarn/cache/unist-util-visit-parents-npm-5.1.1-fe9eee5f6b-c699d18f5b.zip differ diff --git a/.yarn/cache/universalify-npm-0.2.0-9984e61c10-e86134cb12.zip b/.yarn/cache/universalify-npm-0.2.0-9984e61c10-e86134cb12.zip new file mode 100644 index 000000000..7f1d80c19 Binary files /dev/null and b/.yarn/cache/universalify-npm-0.2.0-9984e61c10-e86134cb12.zip differ diff --git a/.yarn/cache/untildify-npm-4.0.0-4a8b569825-39ced9c418.zip b/.yarn/cache/untildify-npm-4.0.0-4a8b569825-39ced9c418.zip new file mode 100644 index 000000000..a88f9ac1d Binary files /dev/null and b/.yarn/cache/untildify-npm-4.0.0-4a8b569825-39ced9c418.zip differ diff --git a/.yarn/cache/update-browserslist-db-npm-1.0.10-676baf0b9f-12db73b4f6.zip b/.yarn/cache/update-browserslist-db-npm-1.0.10-676baf0b9f-12db73b4f6.zip new file mode 100644 index 000000000..b964a1a69 Binary files /dev/null and b/.yarn/cache/update-browserslist-db-npm-1.0.10-676baf0b9f-12db73b4f6.zip differ diff --git a/.yarn/cache/update-browserslist-db-npm-1.0.4-bf636db585-7c7da28d0f.zip b/.yarn/cache/update-browserslist-db-npm-1.0.4-bf636db585-7c7da28d0f.zip deleted file mode 100644 index 9ebaa9f1e..000000000 Binary files a/.yarn/cache/update-browserslist-db-npm-1.0.4-bf636db585-7c7da28d0f.zip and /dev/null differ diff --git a/.yarn/cache/update-browserslist-db-npm-1.0.9-b9b06a6669-f625899b23.zip b/.yarn/cache/update-browserslist-db-npm-1.0.9-b9b06a6669-f625899b23.zip deleted file mode 100644 index db19a9c0d..000000000 Binary files a/.yarn/cache/update-browserslist-db-npm-1.0.9-b9b06a6669-f625899b23.zip and /dev/null differ diff --git a/.yarn/cache/use-memo-one-npm-1.1.2-f58177cfe3-71f4598ce4.zip b/.yarn/cache/use-memo-one-npm-1.1.2-f58177cfe3-71f4598ce4.zip deleted file mode 100644 index d5bf3af01..000000000 Binary files a/.yarn/cache/use-memo-one-npm-1.1.2-f58177cfe3-71f4598ce4.zip and /dev/null differ diff --git a/.yarn/cache/use-memo-one-npm-1.1.3-b9dc77468a-8f08eba26d.zip b/.yarn/cache/use-memo-one-npm-1.1.3-b9dc77468a-8f08eba26d.zip new file mode 100644 index 000000000..5104b0fc5 Binary files /dev/null and b/.yarn/cache/use-memo-one-npm-1.1.3-b9dc77468a-8f08eba26d.zip differ diff --git a/.yarn/cache/uuid-npm-9.0.0-46c41e3e43-8dd2c83c43.zip b/.yarn/cache/uuid-npm-9.0.0-46c41e3e43-8dd2c83c43.zip new file mode 100644 index 000000000..90b6b788a Binary files /dev/null and b/.yarn/cache/uuid-npm-9.0.0-46c41e3e43-8dd2c83c43.zip differ diff --git a/.yarn/cache/vfile-npm-5.3.4-0d04e09115-2382edc7c6.zip b/.yarn/cache/vfile-npm-5.3.5-aa9b688b1f-14a9ea19d1.zip similarity index 60% rename from .yarn/cache/vfile-npm-5.3.4-0d04e09115-2382edc7c6.zip rename to .yarn/cache/vfile-npm-5.3.5-aa9b688b1f-14a9ea19d1.zip index df5a97bf1..b85a7b6dc 100644 Binary files a/.yarn/cache/vfile-npm-5.3.4-0d04e09115-2382edc7c6.zip and b/.yarn/cache/vfile-npm-5.3.5-aa9b688b1f-14a9ea19d1.zip differ diff --git a/.yarn/cache/w3c-keyname-npm-2.2.4-8c6e5969c5-890180452b.zip b/.yarn/cache/w3c-keyname-npm-2.2.4-8c6e5969c5-890180452b.zip deleted file mode 100644 index 11988565d..000000000 Binary files a/.yarn/cache/w3c-keyname-npm-2.2.4-8c6e5969c5-890180452b.zip and /dev/null differ diff --git a/.yarn/cache/w3c-keyname-npm-2.2.6-55cd4f6245-59a31d23ca.zip b/.yarn/cache/w3c-keyname-npm-2.2.6-55cd4f6245-59a31d23ca.zip new file mode 100644 index 000000000..e44984210 Binary files /dev/null and b/.yarn/cache/w3c-keyname-npm-2.2.6-55cd4f6245-59a31d23ca.zip differ diff --git a/.yarn/cache/warn-once-npm-0.1.0-b6ae45a83b-5fde2b526d.zip b/.yarn/cache/warn-once-npm-0.1.0-b6ae45a83b-5fde2b526d.zip deleted file mode 100644 index 331a9009d..000000000 Binary files a/.yarn/cache/warn-once-npm-0.1.0-b6ae45a83b-5fde2b526d.zip and /dev/null differ diff --git a/.yarn/cache/webpack-bundle-analyzer-npm-4.5.0-82010cf435-158e96810e.zip b/.yarn/cache/webpack-bundle-analyzer-npm-4.5.0-82010cf435-158e96810e.zip deleted file mode 100644 index 0c6f92443..000000000 Binary files a/.yarn/cache/webpack-bundle-analyzer-npm-4.5.0-82010cf435-158e96810e.zip and /dev/null differ diff --git a/.yarn/cache/webpack-bundle-analyzer-npm-4.6.1-04a8f1486c-4bc97ac6a1.zip b/.yarn/cache/webpack-bundle-analyzer-npm-4.6.1-04a8f1486c-4bc97ac6a1.zip new file mode 100644 index 000000000..18c17e93d Binary files /dev/null and b/.yarn/cache/webpack-bundle-analyzer-npm-4.6.1-04a8f1486c-4bc97ac6a1.zip differ diff --git a/.yarn/cache/webpack-dev-server-npm-4.9.3-8ff96f1b16-845f2cc8e7.zip b/.yarn/cache/webpack-dev-server-npm-4.11.1-12e4e9dfc1-b7601a39ee.zip similarity index 66% rename from .yarn/cache/webpack-dev-server-npm-4.9.3-8ff96f1b16-845f2cc8e7.zip rename to .yarn/cache/webpack-dev-server-npm-4.11.1-12e4e9dfc1-b7601a39ee.zip index 2e4515dd2..68c9c0cd0 100644 Binary files a/.yarn/cache/webpack-dev-server-npm-4.9.3-8ff96f1b16-845f2cc8e7.zip and b/.yarn/cache/webpack-dev-server-npm-4.11.1-12e4e9dfc1-b7601a39ee.zip differ diff --git a/.yarn/cache/webpack-npm-5.73.0-fc8c985a74-aa434a241b.zip b/.yarn/cache/webpack-npm-5.74.0-f5b838a00d-320c41369a.zip similarity index 82% rename from .yarn/cache/webpack-npm-5.73.0-fc8c985a74-aa434a241b.zip rename to .yarn/cache/webpack-npm-5.74.0-f5b838a00d-320c41369a.zip index 9f77205ce..6f3a50ac5 100644 Binary files a/.yarn/cache/webpack-npm-5.73.0-fc8c985a74-aa434a241b.zip and b/.yarn/cache/webpack-npm-5.74.0-f5b838a00d-320c41369a.zip differ diff --git a/.yarn/cache/webpack-remove-empty-scripts-npm-0.8.1-ff4bfa8fea-79d070c415.zip b/.yarn/cache/webpack-remove-empty-scripts-npm-0.8.1-ff4bfa8fea-79d070c415.zip deleted file mode 100644 index abcdb9e88..000000000 Binary files a/.yarn/cache/webpack-remove-empty-scripts-npm-0.8.1-ff4bfa8fea-79d070c415.zip and /dev/null differ diff --git a/.yarn/cache/webpack-remove-empty-scripts-npm-0.8.4-42b8a9ebd8-8831524d75.zip b/.yarn/cache/webpack-remove-empty-scripts-npm-0.8.4-42b8a9ebd8-8831524d75.zip new file mode 100644 index 000000000..18d162aba Binary files /dev/null and b/.yarn/cache/webpack-remove-empty-scripts-npm-0.8.4-42b8a9ebd8-8831524d75.zip differ diff --git a/.yarn/cache/whatwg-url-without-unicode-npm-8.0.0-3-d98937d586-1fe266f716.zip b/.yarn/cache/whatwg-url-without-unicode-npm-8.0.0-3-d98937d586-1fe266f716.zip deleted file mode 100644 index 0a0eb4203..000000000 Binary files a/.yarn/cache/whatwg-url-without-unicode-npm-8.0.0-3-d98937d586-1fe266f716.zip and /dev/null differ diff --git a/.yarn/cache/workbox-background-sync-npm-6.5.3-326d34005b-dabd839298.zip b/.yarn/cache/workbox-background-sync-npm-6.5.3-326d34005b-dabd839298.zip deleted file mode 100644 index dec10d772..000000000 Binary files a/.yarn/cache/workbox-background-sync-npm-6.5.3-326d34005b-dabd839298.zip and /dev/null differ diff --git a/.yarn/cache/workbox-background-sync-npm-6.5.4-13a7f8219a-60ac80275c.zip b/.yarn/cache/workbox-background-sync-npm-6.5.4-13a7f8219a-60ac80275c.zip new file mode 100644 index 000000000..d19bff3ff Binary files /dev/null and b/.yarn/cache/workbox-background-sync-npm-6.5.4-13a7f8219a-60ac80275c.zip differ diff --git a/.yarn/cache/workbox-broadcast-update-npm-6.5.3-866d051239-00e5473739.zip b/.yarn/cache/workbox-broadcast-update-npm-6.5.4-37b0700ca4-63cbab2012.zip similarity index 71% rename from .yarn/cache/workbox-broadcast-update-npm-6.5.3-866d051239-00e5473739.zip rename to .yarn/cache/workbox-broadcast-update-npm-6.5.4-37b0700ca4-63cbab2012.zip index 0fca407e5..c07f19e02 100644 Binary files a/.yarn/cache/workbox-broadcast-update-npm-6.5.3-866d051239-00e5473739.zip and b/.yarn/cache/workbox-broadcast-update-npm-6.5.4-37b0700ca4-63cbab2012.zip differ diff --git a/.yarn/cache/workbox-build-npm-6.5.3-e56c93d480-bb59bd9266.zip b/.yarn/cache/workbox-build-npm-6.5.3-e56c93d480-bb59bd9266.zip deleted file mode 100644 index 07f0ea725..000000000 Binary files a/.yarn/cache/workbox-build-npm-6.5.3-e56c93d480-bb59bd9266.zip and /dev/null differ diff --git a/.yarn/cache/workbox-build-npm-6.5.4-71d02fae43-7336bbab4c.zip b/.yarn/cache/workbox-build-npm-6.5.4-71d02fae43-7336bbab4c.zip new file mode 100644 index 000000000..8b88f68d0 Binary files /dev/null and b/.yarn/cache/workbox-build-npm-6.5.4-71d02fae43-7336bbab4c.zip differ diff --git a/.yarn/cache/workbox-cacheable-response-npm-6.5.3-6300fc7e40-d3b32d9a3f.zip b/.yarn/cache/workbox-cacheable-response-npm-6.5.4-5661dd1793-f7545b71c1.zip similarity index 50% rename from .yarn/cache/workbox-cacheable-response-npm-6.5.3-6300fc7e40-d3b32d9a3f.zip rename to .yarn/cache/workbox-cacheable-response-npm-6.5.4-5661dd1793-f7545b71c1.zip index 61e2b68ae..c72ebf8b2 100644 Binary files a/.yarn/cache/workbox-cacheable-response-npm-6.5.3-6300fc7e40-d3b32d9a3f.zip and b/.yarn/cache/workbox-cacheable-response-npm-6.5.4-5661dd1793-f7545b71c1.zip differ diff --git a/.yarn/cache/workbox-core-npm-6.5.3-a3490d4bd1-b898da6d99.zip b/.yarn/cache/workbox-core-npm-6.5.4-a956387c31-d973cc6c1c.zip similarity index 56% rename from .yarn/cache/workbox-core-npm-6.5.3-a3490d4bd1-b898da6d99.zip rename to .yarn/cache/workbox-core-npm-6.5.4-a956387c31-d973cc6c1c.zip index 3c298d4cf..34b0a68a4 100644 Binary files a/.yarn/cache/workbox-core-npm-6.5.3-a3490d4bd1-b898da6d99.zip and b/.yarn/cache/workbox-core-npm-6.5.4-a956387c31-d973cc6c1c.zip differ diff --git a/.yarn/cache/workbox-expiration-npm-6.5.3-2ee92a192d-8c98890a83.zip b/.yarn/cache/workbox-expiration-npm-6.5.3-2ee92a192d-8c98890a83.zip deleted file mode 100644 index 29285e303..000000000 Binary files a/.yarn/cache/workbox-expiration-npm-6.5.3-2ee92a192d-8c98890a83.zip and /dev/null differ diff --git a/.yarn/cache/workbox-expiration-npm-6.5.4-081a8d4613-4b012b69ce.zip b/.yarn/cache/workbox-expiration-npm-6.5.4-081a8d4613-4b012b69ce.zip new file mode 100644 index 000000000..63de55071 Binary files /dev/null and b/.yarn/cache/workbox-expiration-npm-6.5.4-081a8d4613-4b012b69ce.zip differ diff --git a/.yarn/cache/workbox-google-analytics-npm-6.5.3-cb4cd9772a-16dd867ada.zip b/.yarn/cache/workbox-google-analytics-npm-6.5.3-cb4cd9772a-16dd867ada.zip deleted file mode 100644 index b34bd11f6..000000000 Binary files a/.yarn/cache/workbox-google-analytics-npm-6.5.3-cb4cd9772a-16dd867ada.zip and /dev/null differ diff --git a/.yarn/cache/workbox-google-analytics-npm-6.5.4-bf443f64b1-fcce5e3137.zip b/.yarn/cache/workbox-google-analytics-npm-6.5.4-bf443f64b1-fcce5e3137.zip new file mode 100644 index 000000000..4899a646a Binary files /dev/null and b/.yarn/cache/workbox-google-analytics-npm-6.5.4-bf443f64b1-fcce5e3137.zip differ diff --git a/.yarn/cache/workbox-navigation-preload-npm-6.5.3-5d503d425a-51f8c1b8b0.zip b/.yarn/cache/workbox-navigation-preload-npm-6.5.3-5d503d425a-51f8c1b8b0.zip deleted file mode 100644 index 0a19b2604..000000000 Binary files a/.yarn/cache/workbox-navigation-preload-npm-6.5.3-5d503d425a-51f8c1b8b0.zip and /dev/null differ diff --git a/.yarn/cache/workbox-navigation-preload-npm-6.5.4-f9b6686723-c8c341b799.zip b/.yarn/cache/workbox-navigation-preload-npm-6.5.4-f9b6686723-c8c341b799.zip new file mode 100644 index 000000000..d16c6e3f2 Binary files /dev/null and b/.yarn/cache/workbox-navigation-preload-npm-6.5.4-f9b6686723-c8c341b799.zip differ diff --git a/.yarn/cache/workbox-precaching-npm-6.5.3-1e3cb5c579-231aab3fc5.zip b/.yarn/cache/workbox-precaching-npm-6.5.3-1e3cb5c579-231aab3fc5.zip deleted file mode 100644 index 8767a0386..000000000 Binary files a/.yarn/cache/workbox-precaching-npm-6.5.3-1e3cb5c579-231aab3fc5.zip and /dev/null differ diff --git a/.yarn/cache/workbox-precaching-npm-6.5.4-69d8a56e94-15ef24ffb0.zip b/.yarn/cache/workbox-precaching-npm-6.5.4-69d8a56e94-15ef24ffb0.zip new file mode 100644 index 000000000..9ea4f69be Binary files /dev/null and b/.yarn/cache/workbox-precaching-npm-6.5.4-69d8a56e94-15ef24ffb0.zip differ diff --git a/.yarn/cache/workbox-range-requests-npm-6.5.3-5b23802865-78cc980136.zip b/.yarn/cache/workbox-range-requests-npm-6.5.3-5b23802865-78cc980136.zip deleted file mode 100644 index 763e46c58..000000000 Binary files a/.yarn/cache/workbox-range-requests-npm-6.5.3-5b23802865-78cc980136.zip and /dev/null differ diff --git a/.yarn/cache/workbox-range-requests-npm-6.5.4-81869b9d72-50f144ced7.zip b/.yarn/cache/workbox-range-requests-npm-6.5.4-81869b9d72-50f144ced7.zip new file mode 100644 index 000000000..12e73da2e Binary files /dev/null and b/.yarn/cache/workbox-range-requests-npm-6.5.4-81869b9d72-50f144ced7.zip differ diff --git a/.yarn/cache/workbox-recipes-npm-6.5.3-2fe6d6fa4c-c0a427da18.zip b/.yarn/cache/workbox-recipes-npm-6.5.4-03aa78ea0b-397befeb7c.zip similarity index 55% rename from .yarn/cache/workbox-recipes-npm-6.5.3-2fe6d6fa4c-c0a427da18.zip rename to .yarn/cache/workbox-recipes-npm-6.5.4-03aa78ea0b-397befeb7c.zip index ca2021927..e523c7987 100644 Binary files a/.yarn/cache/workbox-recipes-npm-6.5.3-2fe6d6fa4c-c0a427da18.zip and b/.yarn/cache/workbox-recipes-npm-6.5.4-03aa78ea0b-397befeb7c.zip differ diff --git a/.yarn/cache/workbox-routing-npm-6.5.3-02837f1ab3-9274c40f5b.zip b/.yarn/cache/workbox-routing-npm-6.5.3-02837f1ab3-9274c40f5b.zip deleted file mode 100644 index e6616dd10..000000000 Binary files a/.yarn/cache/workbox-routing-npm-6.5.3-02837f1ab3-9274c40f5b.zip and /dev/null differ diff --git a/.yarn/cache/workbox-routing-npm-6.5.4-7e767a784d-7198c50b90.zip b/.yarn/cache/workbox-routing-npm-6.5.4-7e767a784d-7198c50b90.zip new file mode 100644 index 000000000..ec68cce11 Binary files /dev/null and b/.yarn/cache/workbox-routing-npm-6.5.4-7e767a784d-7198c50b90.zip differ diff --git a/.yarn/cache/workbox-strategies-npm-6.5.3-66f4995798-74e1ac4d23.zip b/.yarn/cache/workbox-strategies-npm-6.5.3-66f4995798-74e1ac4d23.zip deleted file mode 100644 index 88874f9bb..000000000 Binary files a/.yarn/cache/workbox-strategies-npm-6.5.3-66f4995798-74e1ac4d23.zip and /dev/null differ diff --git a/.yarn/cache/workbox-strategies-npm-6.5.4-8bc6258bfc-52134ecd6c.zip b/.yarn/cache/workbox-strategies-npm-6.5.4-8bc6258bfc-52134ecd6c.zip new file mode 100644 index 000000000..de317a6e0 Binary files /dev/null and b/.yarn/cache/workbox-strategies-npm-6.5.4-8bc6258bfc-52134ecd6c.zip differ diff --git a/.yarn/cache/workbox-streams-npm-6.5.3-aaf65dfd40-3cecca9fe7.zip b/.yarn/cache/workbox-streams-npm-6.5.3-aaf65dfd40-3cecca9fe7.zip deleted file mode 100644 index 116758e4f..000000000 Binary files a/.yarn/cache/workbox-streams-npm-6.5.3-aaf65dfd40-3cecca9fe7.zip and /dev/null differ diff --git a/.yarn/cache/workbox-streams-npm-6.5.4-17a6050105-efd6917ead.zip b/.yarn/cache/workbox-streams-npm-6.5.4-17a6050105-efd6917ead.zip new file mode 100644 index 000000000..5eb94ccc5 Binary files /dev/null and b/.yarn/cache/workbox-streams-npm-6.5.4-17a6050105-efd6917ead.zip differ diff --git a/.yarn/cache/workbox-sw-npm-6.5.3-c109b73e7a-d143e7fd84.zip b/.yarn/cache/workbox-sw-npm-6.5.3-c109b73e7a-d143e7fd84.zip deleted file mode 100644 index ae6ac82a8..000000000 Binary files a/.yarn/cache/workbox-sw-npm-6.5.3-c109b73e7a-d143e7fd84.zip and /dev/null differ diff --git a/.yarn/cache/workbox-sw-npm-6.5.4-307d7c4499-b95c76a74b.zip b/.yarn/cache/workbox-sw-npm-6.5.4-307d7c4499-b95c76a74b.zip new file mode 100644 index 000000000..09b885eef Binary files /dev/null and b/.yarn/cache/workbox-sw-npm-6.5.4-307d7c4499-b95c76a74b.zip differ diff --git a/.yarn/cache/workbox-webpack-plugin-npm-6.5.3-8db5586094-c5a14666ab.zip b/.yarn/cache/workbox-webpack-plugin-npm-6.5.4-3842d0960f-d42ab21399.zip similarity index 51% rename from .yarn/cache/workbox-webpack-plugin-npm-6.5.3-8db5586094-c5a14666ab.zip rename to .yarn/cache/workbox-webpack-plugin-npm-6.5.4-3842d0960f-d42ab21399.zip index 58ad1cc01..da9b6f7c1 100644 Binary files a/.yarn/cache/workbox-webpack-plugin-npm-6.5.3-8db5586094-c5a14666ab.zip and b/.yarn/cache/workbox-webpack-plugin-npm-6.5.4-3842d0960f-d42ab21399.zip differ diff --git a/.yarn/cache/workbox-window-npm-6.5.3-51189ee36e-c9410f6383.zip b/.yarn/cache/workbox-window-npm-6.5.3-51189ee36e-c9410f6383.zip deleted file mode 100644 index ee05641ee..000000000 Binary files a/.yarn/cache/workbox-window-npm-6.5.3-51189ee36e-c9410f6383.zip and /dev/null differ diff --git a/.yarn/cache/workbox-window-npm-6.5.4-20240f4b44-bc43c8d319.zip b/.yarn/cache/workbox-window-npm-6.5.4-20240f4b44-bc43c8d319.zip new file mode 100644 index 000000000..a1161468c Binary files /dev/null and b/.yarn/cache/workbox-window-npm-6.5.4-20240f4b44-bc43c8d319.zip differ diff --git a/.yarn/cache/write-file-atomic-npm-4.0.1-96ec744721-8f78023253.zip b/.yarn/cache/write-file-atomic-npm-4.0.1-96ec744721-8f78023253.zip deleted file mode 100644 index b23a2f047..000000000 Binary files a/.yarn/cache/write-file-atomic-npm-4.0.1-96ec744721-8f78023253.zip and /dev/null differ diff --git a/.yarn/cache/write-file-atomic-npm-4.0.2-661baae4aa-5da60bd4ee.zip b/.yarn/cache/write-file-atomic-npm-4.0.2-661baae4aa-5da60bd4ee.zip new file mode 100644 index 000000000..127e30c69 Binary files /dev/null and b/.yarn/cache/write-file-atomic-npm-4.0.2-661baae4aa-5da60bd4ee.zip differ diff --git a/.yarn/cache/ws-npm-7.5.8-62217fef00-49479ccf3d.zip b/.yarn/cache/ws-npm-7.5.9-26f12a5ed6-c3c100a181.zip similarity index 76% rename from .yarn/cache/ws-npm-7.5.8-62217fef00-49479ccf3d.zip rename to .yarn/cache/ws-npm-7.5.9-26f12a5ed6-c3c100a181.zip index f43c1232d..5e9490b85 100644 Binary files a/.yarn/cache/ws-npm-7.5.8-62217fef00-49479ccf3d.zip and b/.yarn/cache/ws-npm-7.5.9-26f12a5ed6-c3c100a181.zip differ diff --git a/.yarn/cache/ws-npm-8.8.0-89e1c83090-6ceed1ca1c.zip b/.yarn/cache/ws-npm-8.9.0-d620434feb-23aa0f021b.zip similarity index 75% rename from .yarn/cache/ws-npm-8.8.0-89e1c83090-6ceed1ca1c.zip rename to .yarn/cache/ws-npm-8.9.0-d620434feb-23aa0f021b.zip index 6c682a047..fede246f8 100644 Binary files a/.yarn/cache/ws-npm-8.8.0-89e1c83090-6ceed1ca1c.zip and b/.yarn/cache/ws-npm-8.9.0-d620434feb-23aa0f021b.zip differ diff --git a/.yarn/cache/xmlbuilder-npm-9.0.7-44519dbccb-8193bb3238.zip b/.yarn/cache/xmlbuilder-npm-9.0.7-44519dbccb-8193bb3238.zip deleted file mode 100644 index 2399092b6..000000000 Binary files a/.yarn/cache/xmlbuilder-npm-9.0.7-44519dbccb-8193bb3238.zip and /dev/null differ diff --git a/.yarn/cache/xmldoc-npm-1.1.4-27d000c5b1-794c4afabd.zip b/.yarn/cache/xmldoc-npm-1.1.4-27d000c5b1-794c4afabd.zip deleted file mode 100644 index a2e73b139..000000000 Binary files a/.yarn/cache/xmldoc-npm-1.1.4-27d000c5b1-794c4afabd.zip and /dev/null differ diff --git a/.yarn/cache/xmldoc-npm-1.2.0-69488d19bf-df42d06cf4.zip b/.yarn/cache/xmldoc-npm-1.2.0-69488d19bf-df42d06cf4.zip new file mode 100644 index 000000000..baad297c1 Binary files /dev/null and b/.yarn/cache/xmldoc-npm-1.2.0-69488d19bf-df42d06cf4.zip differ diff --git a/.yarn/cache/yaml-npm-2.1.1-e717f9b915-f48bb20991.zip b/.yarn/cache/yaml-npm-2.1.3-654a90032d-9131606232.zip similarity index 85% rename from .yarn/cache/yaml-npm-2.1.1-e717f9b915-f48bb20991.zip rename to .yarn/cache/yaml-npm-2.1.3-654a90032d-9131606232.zip index b2d8391c8..4ad503d16 100644 Binary files a/.yarn/cache/yaml-npm-2.1.1-e717f9b915-f48bb20991.zip and b/.yarn/cache/yaml-npm-2.1.3-654a90032d-9131606232.zip differ diff --git a/.yarn/cache/yargs-npm-17.5.1-0902fa46de-00d58a2c05.zip b/.yarn/cache/yargs-npm-17.6.0-6343ad1a2d-604bdb4a63.zip similarity index 51% rename from .yarn/cache/yargs-npm-17.5.1-0902fa46de-00d58a2c05.zip rename to .yarn/cache/yargs-npm-17.6.0-6343ad1a2d-604bdb4a63.zip index acafce0cd..508f784ce 100644 Binary files a/.yarn/cache/yargs-npm-17.5.1-0902fa46de-00d58a2c05.zip and b/.yarn/cache/yargs-npm-17.6.0-6343ad1a2d-604bdb4a63.zip differ diff --git a/.yarn/cache/yargs-parser-npm-21.0.1-b778fd3462-c3ea2ed12c.zip b/.yarn/cache/yargs-parser-npm-21.0.1-b778fd3462-c3ea2ed12c.zip deleted file mode 100644 index e08e0d71f..000000000 Binary files a/.yarn/cache/yargs-parser-npm-21.0.1-b778fd3462-c3ea2ed12c.zip and /dev/null differ diff --git a/.yarn/cache/yargs-parser-npm-21.1.1-8fdc003314-ed2d96a616.zip b/.yarn/cache/yargs-parser-npm-21.1.1-8fdc003314-ed2d96a616.zip new file mode 100644 index 000000000..d68ba748e Binary files /dev/null and b/.yarn/cache/yargs-parser-npm-21.1.1-8fdc003314-ed2d96a616.zip differ diff --git a/package.json b/package.json index 0ed6a7963..d8ac0b1e4 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "npm-check-updates": "^14.1.1", "prettier": "^2.6.2", "sass-loader": "^13.0.0", - "typescript": "^4.7.3", + "typescript": "4.7.3", "webpack": "^5.72.0", "webpack-cli": "^4.9.2", "webpack-dev-server": "^4.9.2", diff --git a/packages/features/package.json b/packages/features/package.json index 8ad92f415..0768a6d76 100644 --- a/packages/features/package.json +++ b/packages/features/package.json @@ -36,6 +36,6 @@ "eslint-plugin-prettier": "*", "jest": "^28.1.2", "ts-jest": "^28.0.5", - "typescript": "^4.7.4" + "typescript": "4.7.3" } } diff --git a/packages/filepicker/package.json b/packages/filepicker/package.json index a2c9cd115..14fe265d2 100644 --- a/packages/filepicker/package.json +++ b/packages/filepicker/package.json @@ -28,7 +28,8 @@ "eslint-plugin-prettier": "*", "jest": "^28.1.2", "ts-jest": "^28.0.5", - "ts-node": "^10.5.0" + "ts-node": "^10.5.0", + "typescript": "*" }, "dependencies": { "@standardnotes/common": "^1.39.0", diff --git a/packages/filepicker/src/Streaming/StreamingApi.ts b/packages/filepicker/src/Streaming/StreamingApi.ts index 50b9fa041..0c5d6baf1 100644 --- a/packages/filepicker/src/Streaming/StreamingApi.ts +++ b/packages/filepicker/src/Streaming/StreamingApi.ts @@ -90,7 +90,7 @@ export class StreamingFileApi implements FileSystemApi { let previousChunk: Uint8Array - const processChunk = async (result: ReadableStreamDefaultReadResult): Promise => { + const processChunk = async (result: ReadableStreamReadResult): Promise => { if (result.done) { await onBytes(previousChunk, true) return diff --git a/packages/filepicker/src/Streaming/StreamingReader.ts b/packages/filepicker/src/Streaming/StreamingReader.ts index 4df1d1a14..f90e0455f 100644 --- a/packages/filepicker/src/Streaming/StreamingReader.ts +++ b/packages/filepicker/src/Streaming/StreamingReader.ts @@ -1,5 +1,4 @@ import { ByteChunker, OnChunkCallback } from '@standardnotes/files' - import { FileReaderInterface } from './../Interface/FileReader' import { FileSelectionResponse } from '../types' @@ -48,7 +47,7 @@ async function readFile( let previousChunk: Uint8Array - const processChunk = async (result: ReadableStreamDefaultReadResult): Promise => { + const processChunk = async (result: ReadableStreamReadResult): Promise => { if (result.done) { await byteChunker.addBytes(previousChunk, true) return diff --git a/packages/mobile/babel.config.js b/packages/mobile/babel.config.js index 983e075de..cf1f9fbbc 100644 --- a/packages/mobile/babel.config.js +++ b/packages/mobile/babel.config.js @@ -1,4 +1,3 @@ module.exports = { presets: ['module:metro-react-native-babel-preset'], - plugins: ['react-native-reanimated/plugin'], -}; +} diff --git a/packages/mobile/e2e/Helpers.ts b/packages/mobile/e2e/Helpers.ts deleted file mode 100644 index 05f571a73..000000000 --- a/packages/mobile/e2e/Helpers.ts +++ /dev/null @@ -1,53 +0,0 @@ -const faker = require('faker') -import { by, device, element, expect, waitFor } from 'detox' - -export const expectToBeVisible = async (testedElement: Detox.IndexableNativeElement) => { - try { - await expect(testedElement).toBeVisible() - return true - } catch (e) { - return false - } -} - -const checkAfterReinstall = async () => { - if (device.getPlatform() === 'ios') { - const alertElement = element(by.label('Delete Local Data').and(by.type('_UIAlertControllerActionView'))) - const alertVisible = await expectToBeVisible(alertElement) - if (alertVisible) { - await element(by.label('Delete Local Data').and(by.type('_UIAlertControllerActionView'))).tap() - } - } -} - -export const openSettingsScreen = async () => { - await checkAfterReinstall() - await device.reloadReactNative() - - // Opens the settings screen - await waitFor(element(by.id('rootView'))) - .toBeVisible() - .withTimeout(2000) - await element(by.id('headerButton')).tap() - await element(by.id('settingsButton')).tap() -} - -export const openComposeNewNoteScreen = async () => { - await device.reloadReactNative() - - // Opens the screen to compose a new note - await waitFor(element(by.id('rootView'))) - .toBeVisible() - .withTimeout(2000) - await waitFor(element(by.id('newNoteButton'))) - .toBeVisible() - .withTimeout(2000) - - await element(by.id('newNoteButton')).tap() -} - -export const randomCredentials = { - email: faker.internet.exampleEmail(), - password: faker.internet.password(), - syncServerUrl: 'https://app-dev.standardnotes.com', -} diff --git a/packages/mobile/e2e/Screens/Settings/Account.spec.ts b/packages/mobile/e2e/Screens/Settings/Account.spec.ts deleted file mode 100644 index d9eac0fd3..000000000 --- a/packages/mobile/e2e/Screens/Settings/Account.spec.ts +++ /dev/null @@ -1,98 +0,0 @@ -const helpers = require('../../Helpers') -import { by, device, element, expect, waitFor } from 'detox' -import { openSettingsScreen } from '../../Helpers' -console.log('aaaa is', helpers) -// console.log('bbbb is', helpers2) -console.log('cccc is', helpers.openSettingsScreen === openSettingsScreen) - -fdescribe('Account section', () => { - describe('Form', () => { - beforeAll(async () => { - await helpers.openSettingsScreen() - }) - - it('should have the "Email" and "Password" fields visible', async () => { - await expect(element(by.id('emailField'))).toBeVisible() - await expect(element(by.id('passwordField'))).toBeVisible() - }) - - it('should have the "Sign In" button visible', async () => { - await expect(element(by.id('signInButton'))).toBeVisible() - }) - - it('should have the "Register" button visible', async () => { - await expect(element(by.id('registerButton'))).toBeVisible() - }) - - it('should have the "Other Options" button visible', async () => { - await expect(element(by.id('otherOptionsButton'))).toBeVisible() - }) - - it('should have the "Sync Server" field visible when "Other Options" button is pressed', async () => { - await element(by.id('otherOptionsButton')).tap() - await expect(element(by.id('syncServerField'))).toBeVisible() - }) - }) - - describe('Register', () => { - beforeAll(async () => { - await helpers.openSettingsScreen() - }) - - it('should work when valid data is provided', async () => { - await element(by.id('emailField')).typeText(helpers.randomCredentials.email) - await element(by.id('passwordField')).typeText(helpers.randomCredentials.password) - await element(by.id('otherOptionsButton')).tap() - await element(by.id('syncServerField')).clearText() - await element(by.id('syncServerField')).typeText(helpers.randomCredentials.syncServerUrl + '\n') - // wait for buttons to be visible after closing keyboard on smaller devices - await waitFor(element(by.id('registerButton'))) - .toBeVisible() - .withTimeout(1000) - await element(by.id('registerButton')).tap() - - // A confirmation screen is shown after we click the register button... - await expect(element(by.id('passwordConfirmationField'))).toBeVisible() - await expect(element(by.id('registerConfirmButton'))).toBeVisible() - - // Password confirmation is required... - await element(by.id('passwordConfirmationField')).typeText(helpers.randomCredentials.password) - await element(by.id('registerConfirmButton')).tap() - }) - - afterAll(async () => { - await helpers.openSettingsScreen() - - // Account is created and we now proceed to sign out... - await expect(element(by.id('signOutButton'))).toBeVisible() - await element(by.id('signOutButton')).tap() - - // Confirmation button in the dialog... - if (device.getPlatform() === 'ios') { - await element(by.label('Sign Out').and(by.type('_UIAlertControllerActionView'))).tap() - } else { - await expect(element(by.text('SIGN OUT'))).toBeVisible() - await element(by.text('SIGN OUT')).tap() - } - }) - }) - - describe('Sign In', () => { - beforeAll(async () => { - await helpers.openSettingsScreen() - }) - - it('should work when valid data is provided', async () => { - await element(by.id('emailField')).typeText(helpers.randomCredentials.email) - await element(by.id('passwordField')).typeText(helpers.randomCredentials.password) - await element(by.id('otherOptionsButton')).tap() - await element(by.id('syncServerField')).clearText() - await element(by.id('syncServerField')).typeText(helpers.randomCredentials.syncServerUrl + '\n') - // wait for button to be visible after keyboard close - await waitFor(element(by.id('signInButton'))) - .toBeVisible() - .withTimeout(1000) - await element(by.id('signInButton')).tap() - }) - }) -}) diff --git a/packages/mobile/e2e/Screens/Settings/Options.spec.ts b/packages/mobile/e2e/Screens/Settings/Options.spec.ts deleted file mode 100644 index 5bd47bbc4..000000000 --- a/packages/mobile/e2e/Screens/Settings/Options.spec.ts +++ /dev/null @@ -1,35 +0,0 @@ -const helpers = require('../../Helpers') -import { by, device, element, expect } from 'detox' - -describe('Options section', () => { - beforeAll(async () => { - await helpers.openSettingsScreen() - }) - - describe('Export Data', () => { - it('should have the option visible', async () => { - await expect(element(by.id('exportData'))).toBeVisible() - await expect(element(by.id('exportData-title'))).toHaveText('Export Data') - }) - - it('should restore to "Export Data" if dialog is dismissed', async () => { - await expect(element(by.id('exportData-option-decrypted'))).toBeVisible() - if (device.getPlatform() === 'android') { - await element(by.id('exportData-option-decrypted')).tap() - await device.pressBack() - await expect(element(by.id('exportData-title'))).toHaveText('Export Data') - } - }) - - it('should export decrypted notes', async () => { - await expect(element(by.id('exportData-option-decrypted'))).toBeVisible() - if (device.getPlatform() === 'android') { - await element(by.id('exportData-option-decrypted')).tap() - await element(by.text('SAVE TO DISK')).tap() - - await element(by.text('DONE')).tap() - await expect(element(by.id('exportData-title'))).toHaveText('Export Data') - } - }) - }) -}) diff --git a/packages/mobile/e2e/config.json b/packages/mobile/e2e/config.json deleted file mode 100644 index af6a97d64..000000000 --- a/packages/mobile/e2e/config.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "setupFilesAfterEnv": ["./init.js"], - "testEnvironment": "detox/runners/jest/JestCircusEnvironment", - "testRunner": "jest-circus/runner", - "reporters": ["detox/runners/jest/streamlineReporter"], - "verbose": true -} diff --git a/packages/mobile/e2e/init.js b/packages/mobile/e2e/init.js deleted file mode 100644 index 22886abde..000000000 --- a/packages/mobile/e2e/init.js +++ /dev/null @@ -1,37 +0,0 @@ -/* eslint-disable no-undef */ -const detox = require('detox'); -const config = require('../package.json').detox; -const adapter = require('detox/runners/jest/adapter'); -const specReporter = require('detox/runners/jest/specReporter'); -const assignReporter = require('detox/runners/jest/assignReporter'); - -// Set the default timeout -jest.setTimeout(120000); - -detoxCircus.getEnv().addEventsListener(adapter); -detoxCircus.getEnv().addEventsListener(specReporter); -detoxCircus.getEnv().addEventsListener(assignReporter); - -beforeAll(async () => { - await detox.init(config); -}, 600000); - -// beforeEach(async () => { -// try { -// await adapter.beforeEach(); -// } catch (err) { -// // Workaround for the 'jest-jasmine' runner (default one): if 'beforeAll' hook above fails with a timeout, -// // unfortunately, 'jest' might continue running other hooks and test suites. To prevent that behavior, -// // adapter.beforeEach() will throw if detox.init() is still running; that allows us to run detox.cleanup() -// // in that emergency case and disable calling 'device', 'element', 'expect', 'by' and other Detox globals. -// // If you switch to 'jest-circus' runner, you can omit this try-catch workaround at all. - -// await detox.cleanup(); -// throw err; -// } -// }); - -afterAll(async () => { - await adapter.afterAll(); - await detox.cleanup(); -}); diff --git a/packages/mobile/index.js b/packages/mobile/index.js index 284de9ff7..10b2b7781 100644 --- a/packages/mobile/index.js +++ b/packages/mobile/index.js @@ -1,15 +1,8 @@ -import { IsMobileWeb } from '@Lib/Utils' -import { MobileWebApp } from '@Root/MobileWebApp' import { SNLog } from '@standardnotes/snjs' import { AppRegistry } from 'react-native' -import 'react-native-gesture-handler' -import { enableScreens } from 'react-native-screens' -import 'react-native-url-polyfill/auto' import { name as appName } from './app.json' -import { NativeApp } from './src/NativeApp' -import { enableAndroidFontFix } from './src/Style/android_text_fix' +import { MobileWebApp } from './src/MobileWebApp' -enableScreens() /* eslint-disable no-console, @typescript-eslint/no-empty-function */ if (__DEV__ === false) { console.log = () => {} @@ -35,6 +28,4 @@ console.warn = function filterWarnings(msg) { } } -enableAndroidFontFix() - -AppRegistry.registerComponent(appName, () => (IsMobileWeb ? MobileWebApp : NativeApp)) +AppRegistry.registerComponent(appName, () => MobileWebApp) diff --git a/packages/mobile/ios/Podfile.lock b/packages/mobile/ios/Podfile.lock index c52107c25..03e55f2c2 100644 --- a/packages/mobile/ios/Podfile.lock +++ b/packages/mobile/ios/Podfile.lock @@ -71,9 +71,6 @@ PODS: - FlipperKit/Core - FlipperKit/FlipperKitNetworkPlugin - fmt (6.2.1) - - GCDWebServer (3.5.4): - - GCDWebServer/Core (= 3.5.4) - - GCDWebServer/Core (3.5.4) - glog (0.3.5) - libevent (2.1.12) - OpenSSL-Universal (1.1.180) @@ -275,31 +272,10 @@ PODS: - React-jsinspector (0.67.4) - React-logger (0.67.4): - glog - - react-native-aes (1.4.3): - - React-Core - - react-native-document-picker (8.1.1): - - React-Core - react-native-fingerprint-scanner (5.0.0): - React-Core - - react-native-image-picker (4.8.4): - - React-Core - - react-native-mail (4.1.0): - - React-Core - react-native-pager-view (5.4.25): - React-Core - - react-native-safe-area-context (4.3.1): - - RCT-Folly - - RCTRequired - - RCTTypeSafety - - React - - ReactCommon/turbomodule/core - - react-native-segmented-control (2.2.2): - - React-Core - - react-native-sodium-jsi (1.2.0): - - React-Core - - react-native-static-server (0.5.2): - - GCDWebServer (~> 3.0) - - React - react-native-version-info (1.1.1): - React-Core - react-native-webview (11.23.1): @@ -369,76 +345,20 @@ PODS: - React-jsi (= 0.67.4) - React-logger (= 0.67.4) - React-perflogger (= 0.67.4) - - ReactNativeAlternateIcons (0.3.0): - - React - RNCAsyncStorage (1.12.1): - React-Core - - RNCMaskedView (0.1.11): - - React - - RNDefaultPreference (1.4.4): - - React-Core - RNFileViewer (2.1.5): - React-Core - RNFS (2.20.0): - React-Core - - RNGestureHandler (2.3.2): - - React-Core - RNKeychain (8.0.0): - React-Core - RNPrivacySnapshot (1.0.0): - React-Core - - RNReanimated (2.9.1): - - DoubleConversion - - FBLazyVector - - FBReactNativeSpec - - glog - - RCT-Folly - - RCTRequired - - RCTTypeSafety - - React-callinvoker - - React-Core - - React-Core/DevSupport - - React-Core/RCTWebSocket - - React-CoreModules - - React-cxxreact - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-RCTActionSheet - - React-RCTAnimation - - React-RCTBlob - - React-RCTImage - - React-RCTLinking - - React-RCTNetwork - - React-RCTSettings - - React-RCTText - - ReactCommon/turbomodule/core - - Yoga - - RNScreens (3.13.1): - - React-Core - - React-RCTImage - - RNSearchBar (3.5.1): - - React-Core - - RNShare (7.9.0): - - React-Core - - RNStoreReview (0.2.1): - - React-Core - - RNSVG (12.3.0): - - React-Core - - RNVectorIcons (9.2.0): - - React-Core - - RNZipArchive (6.0.8): - - React-Core - - RNZipArchive/Core (= 6.0.8) - - SSZipArchive (= 2.2.3) - - RNZipArchive/Core (6.0.8): - - React-Core - - SSZipArchive (= 2.2.3) - - sn-textview (1.1.0): + - RNShare (7.9.1): - React-Core - SNReactNative (1.0.1): - React-Core - - SSZipArchive (2.2.3) - TrustKit (1.6.5) - Yoga (1.14.0) - YogaKit (1.18.1): @@ -486,16 +406,8 @@ DEPENDENCIES: - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`) - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`) - React-logger (from `../node_modules/react-native/ReactCommon/logger`) - - "react-native-aes (from `../node_modules/@standardnotes/react-native-aes`)" - - react-native-document-picker (from `../node_modules/react-native-document-picker`) - react-native-fingerprint-scanner (from `../node_modules/react-native-fingerprint-scanner`) - - react-native-image-picker (from `../node_modules/react-native-image-picker`) - - react-native-mail (from `../node_modules/react-native-mail`) - react-native-pager-view (from `../node_modules/react-native-pager-view`) - - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) - - "react-native-segmented-control (from `../node_modules/@react-native-community/segmented-control`)" - - react-native-sodium-jsi (from `../node_modules/react-native-sodium-jsi`) - - react-native-static-server (from `../node_modules/react-native-static-server`) - react-native-version-info (from `../node_modules/react-native-version-info`) - react-native-webview (from `../node_modules/react-native-webview`) - React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`) @@ -510,24 +422,12 @@ DEPENDENCIES: - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`) - React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`) - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) - - ReactNativeAlternateIcons (from `../node_modules/react-native-alternate-icons`) - "RNCAsyncStorage (from `../node_modules/@react-native-community/async-storage`)" - - "RNCMaskedView (from `../node_modules/@react-native-community/masked-view`)" - - RNDefaultPreference (from `../node_modules/react-native-default-preference`) - RNFileViewer (from `../node_modules/react-native-file-viewer`) - RNFS (from `../node_modules/react-native-fs`) - - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) - RNKeychain (from `../node_modules/react-native-keychain`) - RNPrivacySnapshot (from `../node_modules/react-native-privacy-snapshot`) - - RNReanimated (from `../node_modules/react-native-reanimated`) - - RNScreens (from `../node_modules/react-native-screens`) - - RNSearchBar (from `../node_modules/react-native-search-bar`) - RNShare (from `../node_modules/react-native-share`) - - RNStoreReview (from `../node_modules/react-native-store-review`) - - RNSVG (from `../node_modules/react-native-svg`) - - RNVectorIcons (from `../node_modules/react-native-vector-icons`) - - RNZipArchive (from `../node_modules/react-native-zip-archive`) - - "sn-textview (from `../node_modules/@standardnotes/react-native-textview`)" - "SNReactNative (from `../node_modules/@standardnotes/react-native-utils`)" - TrustKit (= 1.6.5) - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) @@ -545,10 +445,8 @@ SPEC REPOS: - Flipper-RSocket - FlipperKit - fmt - - GCDWebServer - libevent - OpenSSL-Universal - - SSZipArchive - TrustKit - YogaKit @@ -587,26 +485,10 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/jsinspector" React-logger: :path: "../node_modules/react-native/ReactCommon/logger" - react-native-aes: - :path: "../node_modules/@standardnotes/react-native-aes" - react-native-document-picker: - :path: "../node_modules/react-native-document-picker" react-native-fingerprint-scanner: :path: "../node_modules/react-native-fingerprint-scanner" - react-native-image-picker: - :path: "../node_modules/react-native-image-picker" - react-native-mail: - :path: "../node_modules/react-native-mail" react-native-pager-view: :path: "../node_modules/react-native-pager-view" - react-native-safe-area-context: - :path: "../node_modules/react-native-safe-area-context" - react-native-segmented-control: - :path: "../node_modules/@react-native-community/segmented-control" - react-native-sodium-jsi: - :path: "../node_modules/react-native-sodium-jsi" - react-native-static-server: - :path: "../node_modules/react-native-static-server" react-native-version-info: :path: "../node_modules/react-native-version-info" react-native-webview: @@ -635,42 +517,18 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/runtimeexecutor" ReactCommon: :path: "../node_modules/react-native/ReactCommon" - ReactNativeAlternateIcons: - :path: "../node_modules/react-native-alternate-icons" RNCAsyncStorage: :path: "../node_modules/@react-native-community/async-storage" - RNCMaskedView: - :path: "../node_modules/@react-native-community/masked-view" - RNDefaultPreference: - :path: "../node_modules/react-native-default-preference" RNFileViewer: :path: "../node_modules/react-native-file-viewer" RNFS: :path: "../node_modules/react-native-fs" - RNGestureHandler: - :path: "../node_modules/react-native-gesture-handler" RNKeychain: :path: "../node_modules/react-native-keychain" RNPrivacySnapshot: :path: "../node_modules/react-native-privacy-snapshot" - RNReanimated: - :path: "../node_modules/react-native-reanimated" - RNScreens: - :path: "../node_modules/react-native-screens" - RNSearchBar: - :path: "../node_modules/react-native-search-bar" RNShare: :path: "../node_modules/react-native-share" - RNStoreReview: - :path: "../node_modules/react-native-store-review" - RNSVG: - :path: "../node_modules/react-native-svg" - RNVectorIcons: - :path: "../node_modules/react-native-vector-icons" - RNZipArchive: - :path: "../node_modules/react-native-zip-archive" - sn-textview: - :path: "../node_modules/@standardnotes/react-native-textview" SNReactNative: :path: "../node_modules/@standardnotes/react-native-utils" Yoga: @@ -692,7 +550,6 @@ SPEC CHECKSUMS: Flipper-RSocket: d9d9ade67cbecf6ac10730304bf5607266dd2541 FlipperKit: d8d346844eca5d9120c17d441a2f38596e8ed2b9 fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 - GCDWebServer: 2c156a56c8226e2d5c0c3f208a3621ccffbe3ce4 glog: 85ecdd10ee8d8ec362ef519a6a45ff9aa27b2e85 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 OpenSSL-Universal: 1aa4f6a6ee7256b83db99ec1ccdaa80d10f9af9b @@ -708,16 +565,8 @@ SPEC CHECKSUMS: React-jsiexecutor: cbdf37cebdc4f5d8b3d0bf5ccaa6147fd9de9f3d React-jsinspector: f4775ea9118cbe1f72b834f0f842baa7a99508d8 React-logger: a1f028f6d8639a3f364ef80419e5e862e1115250 - react-native-aes: 420f829e2c4ff32e3deb2aa056094a6a29fcf992 - react-native-document-picker: f68191637788994baed5f57d12994aa32cf8bf88 react-native-fingerprint-scanner: be63e626b31fb951780a5fac5328b065a61a3d6e - react-native-image-picker: cffb727cf2f59bd5c0408e30b3dbe0b935f88835 - react-native-mail: 5fe7239a5b5c1e858d425501c03d1ab977434122 react-native-pager-view: da490aa1f902c9a5aeecf0909cc975ad0e92e53e - react-native-safe-area-context: 6c12e3859b6f27b25de4fee8201cfb858432d8de - react-native-segmented-control: 65df6cd0619b780b3843d574a72d4c7cec396097 - react-native-sodium-jsi: c8901320767d00385f9111bc95ba25aaa9a29890 - react-native-static-server: 880d9b697ef68722e6fa06ae06e6b843e906ed0b react-native-version-info: a106f23009ac0db4ee00de39574eb546682579b9 react-native-webview: d33e2db8925d090871ffeb232dfa50cb3a727581 React-perflogger: 0afaf2f01a47fd0fc368a93bfbb5bd3b26db6e7f @@ -732,26 +581,13 @@ SPEC CHECKSUMS: React-RCTVibration: 3b52a7dced19cdb025b4f88ab26ceb2d85f30ba2 React-runtimeexecutor: a9d3c82ddf7ffdad9fbe6a81c6d6f8c06385464d ReactCommon: 07d0c460b9ba9af3eaf1b8f5abe7daaad28c9c4e - ReactNativeAlternateIcons: b2a8a729d9d9756ed0652c352694f190407f297f RNCAsyncStorage: b03032fdbdb725bea0bd9e5ec5a7272865ae7398 - RNCMaskedView: 0e1bc4bfa8365eba5fbbb71e07fbdc0555249489 - RNDefaultPreference: 08bdb06cfa9188d5da97d4642dac745218d7fb31 RNFileViewer: ce7ca3ac370e18554d35d6355cffd7c30437c592 RNFS: 4ac0f0ea233904cb798630b3c077808c06931688 - RNGestureHandler: 6e757e487a4834e7280e98e9bac66d2d9c575e9c RNKeychain: 4f63aada75ebafd26f4bc2c670199461eab85d94 RNPrivacySnapshot: 8eaf571478a353f2e5184f5c803164f22428b023 - RNReanimated: b5b17149593e7c05e4ec5c0efea1f21e05829510 - RNScreens: 40a2cb40a02a609938137a1e0acfbf8fc9eebf19 - RNSearchBar: 5ed8e13ba8a6c701fbd2afdfe4164493d24b2aee - RNShare: be91a5c149585affb02c25b351bd07ba927c7006 - RNStoreReview: e05edbbf426563070524cec384ac0b8df69be801 - RNSVG: 302bfc9905bd8122f08966dc2ce2d07b7b52b9f8 - RNVectorIcons: fcc2f6cb32f5735b586e66d14103a74ce6ad61f8 - RNZipArchive: 3f89b114cfeb89dac027fc5c7afd7e58d3dc4ebf - sn-textview: 494186ad03660daa52b1d3fd7b50b116b550f925 + RNShare: a5dc3b9c53ddc73e155b8cd9a94c70c91913c43c SNReactNative: b5e9e529c175c13f3a618e27c76cf3071213d5e1 - SSZipArchive: 62d4947b08730e4cda640473b0066d209ff033c9 TrustKit: 073855e3adecd317417bda4ac9e9ac54a2e3b9f2 Yoga: d6b6a80659aa3e91aaba01d0012e7edcbedcbecd YogaKit: f782866e155069a2cca2517aafea43200b01fd5a diff --git a/packages/mobile/metro.config.js b/packages/mobile/metro.config.js index 972acf698..d5809211e 100644 --- a/packages/mobile/metro.config.js +++ b/packages/mobile/metro.config.js @@ -19,22 +19,7 @@ module.exports = (async () => { } = await getDefaultConfig() return { - watchFolders: [ - __dirname, - '../icons', - '../styles', - '../components', - '../features', - '../encryption', - '../filepicker', - '../services', - '../files', - '../utils', - '../sncrypto-common', - '../snjs', - '../responses', - '../models', - ], + watchFolders: [__dirname, '../snjs'], transformer: { getTransformOptions: async () => ({ transform: { @@ -42,7 +27,6 @@ module.exports = (async () => { inlineRequires: true, }, }), - babelTransformerPath: require.resolve('react-native-svg-transformer'), }, resolver: { assetExts: assetExts.filter((ext) => ext !== 'svg'), diff --git a/packages/mobile/package.json b/packages/mobile/package.json index e99b5dabe..4c853b1f7 100644 --- a/packages/mobile/package.json +++ b/packages/mobile/package.json @@ -28,62 +28,21 @@ "hoistingLimits": "workspaces" }, "dependencies": { - "@expo/react-native-action-sheet": "^3.13.0", "@react-native-community/async-storage": "1.12.1", - "@react-native-community/masked-view": "^0.1.11", - "@react-native-community/segmented-control": "^2.2.2", - "@react-navigation/elements": "^1.3.3", - "@react-navigation/native": "^6.0.10", - "@react-navigation/stack": "^6.2.1", - "@standardnotes/components-meta": "workspace:*", - "@standardnotes/filepicker": "workspace:*", - "@standardnotes/icons": "workspace:*", - "@standardnotes/react-native-aes": "^1.4.3", - "@standardnotes/react-native-textview": "1.1.0", "@standardnotes/react-native-utils": "1.0.1", - "@standardnotes/sncrypto-common": "workspace:*", "@standardnotes/snjs": "workspace:*", - "@standardnotes/stylekit": "5.29.3", "@standardnotes/web": "workspace:*", - "@types/styled-components-react-native": "5.1.3", - "dompurify": "^2.3.8", - "js-base64": "^3.7.2", - "moment": "^2.29.2", "react": "17.0.2", "react-native": "0.67.4", - "react-native-alternate-icons": "standardnotes/react-native-alternate-icons#1d335d13bb518ed4d26cb00bcd1f6b1c4d60a052", - "react-native-default-preference": "^1.4.3", - "react-native-document-picker": "^8.1.0", - "react-native-fab": "standardnotes/react-native-fab#cb60e0067bbd938df5e85838760d8ff87f0cddda", "react-native-file-viewer": "^2.1.5", "react-native-fingerprint-scanner": "standardnotes/react-native-fingerprint-scanner#0f9c1f6712ee0c1a2908fe7e589c72151d143c48", "react-native-flag-secure-android": "standardnotes/react-native-flag-secure-android#cb08e74583c22a5d912842459b35ebbbb4bcd852", "react-native-fs": "^2.19.0", - "react-native-gesture-handler": "2.3.2", - "react-native-image-picker": "^4.7.3", "react-native-keychain": "standardnotes/react-native-keychain#d277d360494cbd02be4accb4a360772a8e0e97b6", - "react-native-mail": "standardnotes/react-native-mail#fd26119e67a2ffc5eaa95a9c17049743e39ce2d3", "react-native-privacy-snapshot": "standardnotes/react-native-privacy-snapshot#653e904c90fc6f2b578da59138f2bfe5d7f942fe", - "react-native-reanimated": "^2.8.0", - "react-native-safe-area-context": "^4.2.2", - "react-native-screens": "3.13.1", - "react-native-search-bar": "standardnotes/react-native-search-bar#7d2139daf9b7663b570403f21f520deceba9bb09", - "react-native-search-box": "standardnotes/react-native-search-box#8c46369912cba78dca718588aca9c16926953ff7", "react-native-share": "^7.9.0", - "react-native-sodium-jsi": "1.2.0", - "react-native-static-server": "standardnotes/react-native-static-server#28ef0175dbee3db9aadfab57498497067556a836", - "react-native-store-review": "^0.2.0", - "react-native-svg": "^12.3.0", - "react-native-svg-transformer": "^1.0.0", - "react-native-tab-view": "^3.1.1", - "react-native-toast-message": "^2.1.5", - "react-native-url-polyfill": "^1.3.0", - "react-native-vector-icons": "^9.1.0", "react-native-version-info": "^1.1.1", - "react-native-webview": "11.23.1", - "react-native-zip-archive": "^6.0.6", - "react-navigation-header-buttons": "^9.0.1", - "styled-components": "5.3.5" + "react-native-webview": "11.23.1" }, "devDependencies": { "@babel/core": "*", @@ -91,25 +50,15 @@ "@babel/runtime": "^7.18.3", "@react-native-community/eslint-config": "^3.0.1", "@standardnotes/config": "^2.4.3", - "@types/detox": "^18.1.0", - "@types/faker": "^6.6.9", - "@types/jest": "^28.1.5", - "@types/js-base64": "^3.3.1", - "@types/react": "17.0.2", + "@types/react": "^18.0.21", "@types/react-native": "^0.67.3", - "@types/react-native-vector-icons": "^6.4.10", - "@types/react-test-renderer": "^17.0.1", "@typescript-eslint/eslint-plugin": "^5.20.0", "@typescript-eslint/parser": "^5.20.0", "babel-jest": "^27.5.1", "detox": "^19.5.7", "eslint": "^8.13.0", - "eslint-plugin-flowtype": "^8.0.3", "eslint-plugin-prettier": "^4.0.0", - "faker": "^6.6.6", "get-yarn-workspaces": "^1.0.2", - "jest": "^28.1.2", - "jest-circus": "^27.5.1", "metro-react-native-babel-preset": "^0.70.1", "npm-check-updates": "*", "pod-install": "^0.1.33", @@ -129,42 +78,5 @@ "componentsCdn": { "dev": "https://cdn.jsdelivr.net/gh/standardnotes/app@", "prod": "https://cdn.jsdelivr.net/gh/standardnotes/app@" - }, - "detox": { - "configurations": { - "ios.sim.debug": { - "binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/StandardNotes.app", - "build": "xcodebuild -workspace ios/StandardNotes.xcworkspace -scheme StandardNotes -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build", - "type": "ios.simulator", - "device": { - "type": "iPhone SE (2nd generation)" - } - }, - "ios.sim.release": { - "binaryPath": "ios/build/Build/Products/Release-iphonesimulator/StandardNotes.app", - "build": "xcodebuild -workspace ios/StandardNotes.xcworkspace -scheme StandardNotes -configuration Release -sdk iphonesimulator -derivedDataPath ios/build", - "type": "ios.simulator", - "device": { - "type": "iPhone 11 Pro" - } - }, - "android.emu.debug": { - "binaryPath": "android/app/build/outputs/apk/debug/app-debug.apk", - "build": "cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug && cd ..", - "type": "android.emulator", - "device": { - "avdName": "pixel" - } - }, - "android.emu.release": { - "binaryPath": "android/app/build/outputs/apk/release/app-release.apk", - "build": "cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release && cd ..", - "type": "android.emulator", - "device": { - "avdName": "pixel" - } - } - }, - "test-runner": "jest" } } diff --git a/packages/mobile/src/AppStack.tsx b/packages/mobile/src/AppStack.tsx deleted file mode 100644 index 244f53c55..000000000 --- a/packages/mobile/src/AppStack.tsx +++ /dev/null @@ -1,261 +0,0 @@ -import { AppStateEventType, AppStateType, TabletModeChangeData } from '@Lib/ApplicationState' -import { AlwaysOpenWebAppOnLaunchKey } from '@Lib/constants' -import { useHasEditor, useIsLocked } from '@Lib/SnjsHelperHooks' -import { ScreenStatus } from '@Lib/StatusManager' -import { IsMobileWeb } from '@Lib/Utils' -import { CompositeNavigationProp, RouteProp } from '@react-navigation/native' -import { createStackNavigator, StackNavigationProp } from '@react-navigation/stack' -import { HeaderTitleView } from '@Root/Components/HeaderTitleView' -import { IoniconsHeaderButton } from '@Root/Components/IoniconsHeaderButton' -import { Compose } from '@Root/Screens/Compose/Compose' -import { SCREEN_COMPOSE, SCREEN_NOTES, SCREEN_VIEW_PROTECTED_NOTE } from '@Root/Screens/screens' -import { MainSideMenu } from '@Root/Screens/SideMenu/MainSideMenu' -import { NoteSideMenu } from '@Root/Screens/SideMenu/NoteSideMenu' -import { ViewProtectedNote } from '@Root/Screens/ViewProtectedNote/ViewProtectedNote' -import { Root } from '@Screens/Root' -import { StorageValueModes, UuidString } from '@standardnotes/snjs' -import { ICON_MENU } from '@Style/Icons' -import { ThemeService } from '@Style/ThemeService' -import { getDefaultDrawerWidth } from '@Style/Utils' -import React, { useCallback, useContext, useEffect, useRef, useState } from 'react' -import { Dimensions, Keyboard, ScaledSize } from 'react-native' -import DrawerLayout, { DrawerState } from 'react-native-gesture-handler/DrawerLayout' -import { HeaderButtons, Item } from 'react-navigation-header-buttons' -import { ThemeContext } from 'styled-components' -import { ApplicationContext } from './ApplicationContext' -import { MobileWebAppContainer } from './MobileWebAppContainer' -import { ModalStackNavigationProp } from './ModalStack' -import { HeaderTitleParams } from './NativeApp' - -export type AppStackNavigatorParamList = { - [SCREEN_NOTES]: HeaderTitleParams - [SCREEN_COMPOSE]: HeaderTitleParams & { - noteUuid: UuidString - } - [SCREEN_VIEW_PROTECTED_NOTE]: { - onPressView: () => void - } -} - -export type AppStackNavigationProp = { - navigation: CompositeNavigationProp< - ModalStackNavigationProp<'AppStack'>['navigation'], - StackNavigationProp - > - route: RouteProp -} - -export const AppStack = createStackNavigator() - -export const AppStackComponent = (props: ModalStackNavigationProp<'AppStack'>) => { - // Context - const application = useContext(ApplicationContext) - const theme = useContext(ThemeContext) - const [isLocked] = useIsLocked() - const [hasEditor] = useHasEditor() - - // State - const [dimensions, setDimensions] = useState(() => Dimensions.get('window')) - const [isInTabletMode, setIsInTabletMode] = useState(() => application?.getAppState().isInTabletMode) - const [notesStatus, setNotesStatus] = useState() - const [composeStatus, setComposeStatus] = useState() - const [noteDrawerOpen, setNoteDrawerOpen] = useState(false) - - // Ref - const drawerRef = useRef(null) - const noteDrawerRef = useRef(null) - - useEffect(() => { - const removeObserver = application?.getAppState().addStateChangeObserver((event) => { - if (event === AppStateType.EditorClosed) { - noteDrawerRef.current?.closeDrawer() - if (!isInTabletMode && props.navigation.canGoBack()) { - props.navigation.popToTop() - } - } - }) - - return removeObserver - }, [application, props.navigation, isInTabletMode]) - - useEffect(() => { - const removeObserver = application?.getStatusManager().addHeaderStatusObserver((messages) => { - setNotesStatus(messages[SCREEN_NOTES]) - setComposeStatus(messages[SCREEN_COMPOSE]) - }) - - return removeObserver - }, [application, isInTabletMode]) - - useEffect(() => { - const updateDimensions = ({ window }: { window: ScaledSize }) => { - setDimensions(window) - } - - const removeDimensionsChangeListener = Dimensions.addEventListener('change', updateDimensions) - - return () => removeDimensionsChangeListener.remove() - }, []) - - useEffect(() => { - const remoteTabletModeSubscription = application?.getAppState().addStateEventObserver((event, data) => { - if (event === AppStateEventType.TabletModeChange) { - const eventData = data as TabletModeChangeData - if (eventData.new_isInTabletMode && !eventData.old_isInTabletMode) { - setIsInTabletMode(true) - } else if (!eventData.new_isInTabletMode && eventData.old_isInTabletMode) { - setIsInTabletMode(false) - } - } - }) - - return remoteTabletModeSubscription - }, [application]) - - const handleDrawerStateChange = useCallback( - (newState: DrawerState, drawerWillShow: boolean) => { - if (newState !== 'Idle' && drawerWillShow) { - application?.getAppState().onDrawerOpen() - } - }, - [application], - ) - - const shouldOpenWebApp = application?.getValue(AlwaysOpenWebAppOnLaunchKey, StorageValueModes.Nonwrapped) as boolean - - if (IsMobileWeb || shouldOpenWebApp) { - return ( - ({ - headerShown: false, - })} - initialRouteName={SCREEN_NOTES} - > - - - ) - } - - return ( - !isLocked && } - > - setNoteDrawerOpen(true)} - onDrawerClose={() => setNoteDrawerOpen(false)} - drawerPosition={'right'} - drawerType="slide" - drawerLockMode={hasEditor ? 'unlocked' : 'locked-closed'} - renderNavigationView={() => - hasEditor && - } - > - ({ - headerStyle: { - backgroundColor: theme.stylekitContrastBackgroundColor, - }, - headerTintColor: theme.stylekitInfoColor, - headerTitle: ({ children }) => { - return - }, - })} - initialRouteName={SCREEN_NOTES} - > - ({ - title: 'All notes', - headerShown: !shouldOpenWebApp, - headerTitle: ({ children }) => { - const screenStatus = isInTabletMode ? composeStatus || notesStatus : notesStatus - - const title = route.params?.title ?? (children || '') - const subtitle = [screenStatus?.status, route.params?.subTitle].filter((x) => !!x).join(' • ') - - return - }, - headerLeft: () => ( - - { - Keyboard.dismiss() - drawerRef.current?.openDrawer() - }} - /> - - ), - headerRight: () => - isInTabletMode && - hasEditor && ( - - { - Keyboard.dismiss() - noteDrawerRef.current?.openDrawer() - }} - /> - - ), - })} - component={shouldOpenWebApp ? MobileWebAppContainer : Root} - /> - ({ - headerTitle: ({ children }) => { - return ( - - ) - }, - headerRight: () => - !isInTabletMode && ( - - { - Keyboard.dismiss() - noteDrawerRef.current?.openDrawer() - }} - /> - - ), - })} - component={Compose} - /> - ({ - title: 'View Protected Note', - })} - component={ViewProtectedNote} - /> - - - - ) -} diff --git a/packages/mobile/src/ApplicationContext.tsx b/packages/mobile/src/ApplicationContext.tsx deleted file mode 100644 index c0f666863..000000000 --- a/packages/mobile/src/ApplicationContext.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import { MobileApplication } from '@Lib/Application' -import React from 'react' - -export const ApplicationContext = React.createContext(undefined) - -export const SafeApplicationContext = ApplicationContext as React.Context diff --git a/packages/mobile/src/ApplicationGroupContext.tsx b/packages/mobile/src/ApplicationGroupContext.tsx deleted file mode 100644 index cc15f8dbf..000000000 --- a/packages/mobile/src/ApplicationGroupContext.tsx +++ /dev/null @@ -1,4 +0,0 @@ -import { ApplicationGroup } from '@Lib/ApplicationGroup' -import React from 'react' - -export const ApplicationGroupContext = React.createContext(undefined) diff --git a/packages/mobile/src/Components/BlockingModal.styled.ts b/packages/mobile/src/Components/BlockingModal.styled.ts deleted file mode 100644 index d7fb22f7f..000000000 --- a/packages/mobile/src/Components/BlockingModal.styled.ts +++ /dev/null @@ -1,29 +0,0 @@ -import styled from 'styled-components/native' - -export const Container = styled.View` - flex: 1; - background-color: transparent; - align-items: center; - justify-content: center; -` - -export const Content = styled.View` - background-color: ${({ theme }) => theme.stylekitBackgroundColor}; - padding: 20px; - border-radius: 10px; - width: 80%; -` - -export const Title = styled.Text` - color: ${({ theme }) => theme.stylekitForegroundColor}; - font-size: 16px; - font-weight: bold; - text-align: center; - margin-bottom: 5px; -` - -export const Subtitle = styled.Text` - color: ${({ theme }) => theme.stylekitForegroundColor}; - font-size: 14px; - text-align: center; -` diff --git a/packages/mobile/src/Components/BlockingModal.tsx b/packages/mobile/src/Components/BlockingModal.tsx deleted file mode 100644 index e355bc6cb..000000000 --- a/packages/mobile/src/Components/BlockingModal.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { ModalStackNavigationProp } from '@Root/ModalStack' -import { MODAL_BLOCKING_ALERT } from '@Root/Screens/screens' -import React from 'react' -import { Container, Content, Subtitle, Title } from './BlockingModal.styled' - -type Props = ModalStackNavigationProp - -export const BlockingModal = ({ route: { params } }: Props) => { - return ( - - - {params.title && {params.title}} - {params.text} - - - ) -} diff --git a/packages/mobile/src/Components/Button.tsx b/packages/mobile/src/Components/Button.tsx deleted file mode 100644 index 8bab36514..000000000 --- a/packages/mobile/src/Components/Button.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import React from 'react' -import styled, { css } from 'styled-components/native' - -type Props = { - onPress: () => void - label: string - primary?: boolean - fullWidth?: boolean - last?: boolean -} - -const PrimaryButtonContainer = styled.TouchableOpacity.attrs({ - activeOpacity: 0.84, -})<{ - fullWidth?: boolean - last?: boolean -}>` - background-color: ${({ theme }) => theme.stylekitInfoColor}; - padding: 12px 24px; - border-radius: 4px; - border-width: 1px; - border-color: ${({ theme }) => theme.stylekitInfoColor}; - margin-bottom: ${({ fullWidth, last }) => (fullWidth && !last ? '16px' : 0)}; - ${({ fullWidth }) => - !fullWidth && - css` - align-self: center; - `}; -` - -const SecondaryButtonContainer = styled.TouchableHighlight.attrs(({ theme }) => ({ - activeOpacity: 0.84, - underlayColor: theme.stylekitBorderColor, -}))<{ - fullWidth?: boolean - last?: boolean -}>` - background-color: ${({ theme }) => theme.stylekitBackgroundColor}; - padding: 12px 24px; - border-radius: 4px; - border-width: 1px; - border-color: ${({ theme }) => theme.stylekitBorderColor}; - margin-bottom: ${({ fullWidth, last }) => (fullWidth && !last ? '16px' : 0)}; - ${({ fullWidth }) => - !fullWidth && - css` - align-self: center; - `}; -` - -const ButtonLabel = styled.Text<{ primary?: boolean }>` - text-align: center; - text-align-vertical: center; - font-weight: bold; - color: ${({ theme, primary }) => { - return primary ? theme.stylekitInfoContrastColor : theme.stylekitForegroundColor - }}; - font-size: ${(props) => props.theme.mainTextFontSize}px; -` - -export const Button: React.FC = ({ onPress, label, primary, fullWidth, last }: Props) => { - if (primary) { - return ( - - {label} - - ) - } else { - return ( - - {label} - - ) - } -} diff --git a/packages/mobile/src/Components/ButtonCell.tsx b/packages/mobile/src/Components/ButtonCell.tsx deleted file mode 100644 index ebe064ac7..000000000 --- a/packages/mobile/src/Components/ButtonCell.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import React from 'react' -import { Platform } from 'react-native' -import styled, { css } from 'styled-components/native' -import { Props as TableCellProps, SectionedTableCellTouchableHighlight } from './SectionedTableCell' - -type Props = { - testID?: string - maxHeight?: number - leftAligned?: boolean - bold?: boolean - disabled?: boolean - important?: boolean - onPress: () => void - first?: boolean - last?: boolean - title?: string -} - -type ContainerProps = Pick & TableCellProps -const Container = styled(SectionedTableCellTouchableHighlight).attrs((props) => ({ - underlayColor: props.theme.stylekitBorderColor, -}))` - padding-top: ${12}px; - justify-content: center; - ${({ maxHeight }) => - maxHeight && - css` - max-height: 50px; - `}; -` -const ButtonContainer = styled.View`` - -type ButtonLabelProps = Pick -const ButtonLabel = styled.Text` - text-align: ${(props) => (props.leftAligned ? 'left' : 'center')}; - text-align-vertical: center; - color: ${(props) => { - let color = Platform.OS === 'android' ? props.theme.stylekitForegroundColor : props.theme.stylekitInfoColor - if (props.disabled) { - color = 'gray' - } else if (props.important) { - color = props.theme.stylekitDangerColor - } - return color - }}; - font-size: ${(props) => props.theme.mainTextFontSize}px; - ${({ bold }) => - bold && - css` - font-weight: bold; - `} - ${({ disabled }) => - disabled && - css` - opacity: 0.6; - `} -` - -export const ButtonCell: React.FC = (props) => ( - - - - {props.title} - - {props.children && props.children} - - -) diff --git a/packages/mobile/src/Components/Chip.tsx b/packages/mobile/src/Components/Chip.tsx deleted file mode 100644 index a11ae2c4e..000000000 --- a/packages/mobile/src/Components/Chip.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import React, { useCallback, useEffect, useRef } from 'react' -import { Animated } from 'react-native' -import { TouchableWithoutFeedback } from 'react-native-gesture-handler' -import styled, { css } from 'styled-components/native' - -type Props = { - selected: boolean - onPress: () => void - label: string - last?: boolean -} - -const Container = styled.View<{ - last?: boolean -}>` - border-radius: 100px; - padding: 5px 10px; - border-width: 1px; - ${({ last }) => - !last && - css` - margin-right: 8px; - `}; -` - -const Label = styled.Text<{ selected: boolean }>` - font-size: 14px; -` - -const ActiveContainer = styled(Container)` - background-color: ${({ theme }) => theme.stylekitInfoColor}; - border-color: ${({ theme }) => theme.stylekitInfoColor}; -` - -const InactiveContainer = styled(Container)` - position: absolute; - background-color: ${({ theme }) => theme.stylekitInfoContrastColor}; - border-color: ${({ theme }) => theme.stylekitBorderColor}; -` - -const ActiveLabel = styled(Label)` - color: ${({ theme }) => theme.stylekitNeutralContrastColor}; -` - -const InactiveLabel = styled(Label)` - color: ${({ theme }) => theme.stylekitNeutralColor}; -` - -export const Chip: React.FC = ({ selected, onPress, label, last }) => { - const animationValue = useRef(new Animated.Value(selected ? 1 : 0)).current - const selectedRef = useRef(selected) - - const toggleChip = useCallback(() => { - Animated.timing(animationValue, { - toValue: selected ? 1 : 0, - duration: 100, - useNativeDriver: true, - }).start() - }, [animationValue, selected]) - - useEffect(() => { - if (selected !== selectedRef.current) { - toggleChip() - selectedRef.current = selected - } - }, [selected, toggleChip]) - - return ( - - - - {label} - - - - - {label} - - - - ) -} diff --git a/packages/mobile/src/Components/Circle.ts b/packages/mobile/src/Components/Circle.ts deleted file mode 100644 index 566312bde..000000000 --- a/packages/mobile/src/Components/Circle.ts +++ /dev/null @@ -1,16 +0,0 @@ -import styled from 'styled-components/native' - -type Props = { - size?: number - backgroundColor?: string - borderColor?: string -} - -export const Circle = styled.View` - width: ${(props) => props.size ?? 12}px; - height: ${(props) => props.size ?? 12}px; - border-radius: ${(props) => (props.size ?? 12) / 2}px; - background-color: ${(props) => props.backgroundColor}; - border-color: ${(props) => props.borderColor}; - border-width: 1px; -` diff --git a/packages/mobile/src/Components/HeaderTitleView.tsx b/packages/mobile/src/Components/HeaderTitleView.tsx deleted file mode 100644 index 289294592..000000000 --- a/packages/mobile/src/Components/HeaderTitleView.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import React from 'react' -import { Platform } from 'react-native' -import styled from 'styled-components/native' - -type Props = { - subtitleColor?: string - title: string - subtitle?: string -} - -const Container = styled.View` - /* background-color: ${(props) => props.theme.stylekitContrastBackgroundColor}; */ - flex: 1; - justify-content: center; - - ${Platform.OS === 'android' && 'align-items: flex-start; min-width: 100px;'} -` -const Title = styled.Text` - color: ${(props) => props.theme.stylekitForegroundColor}; - font-weight: bold; - font-size: 18px; - text-align: center; -` -const SubTitle = styled.Text.attrs(() => ({ - adjustsFontSizeToFit: true, - numberOfLines: 1, -}))<{ color?: string }>` - color: ${(props) => props.color ?? props.theme.stylekitForegroundColor}; - opacity: ${(props) => (props.color ? 1 : 0.6)}; - font-size: ${Platform.OS === 'android' ? 13 : 12}px; - ${Platform.OS === 'ios' && 'text-align: center'} -` - -export const HeaderTitleView: React.FC = (props) => ( - - {props.title} - {props.subtitle && props.subtitle.length > 0 ? ( - {props.subtitle} - ) : undefined} - -) diff --git a/packages/mobile/src/Components/Icon.styled.ts b/packages/mobile/src/Components/Icon.styled.ts deleted file mode 100644 index 9005213a4..000000000 --- a/packages/mobile/src/Components/Icon.styled.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { StyleSheet } from 'react-native' - -export const iconStyles = StyleSheet.create({ - icon: { - width: 14, - height: 14, - }, -}) diff --git a/packages/mobile/src/Components/IoniconsHeaderButton.tsx b/packages/mobile/src/Components/IoniconsHeaderButton.tsx deleted file mode 100644 index 8d2abaf4d..000000000 --- a/packages/mobile/src/Components/IoniconsHeaderButton.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import React, { useContext } from 'react' -import Icon from 'react-native-vector-icons/Ionicons' -import { HeaderButton, HeaderButtonProps } from 'react-navigation-header-buttons' -import { ThemeContext } from 'styled-components' - -export const IoniconsHeaderButton = (passMeFurther: HeaderButtonProps) => { - // the `passMeFurther` variable here contains props from as well as - // and it is important to pass those props to `HeaderButton` - // then you may add some information like icon size or color (if you use icons) - const theme = useContext(ThemeContext) - return ( - - ) -} diff --git a/packages/mobile/src/Components/SearchBar.styled.ts b/packages/mobile/src/Components/SearchBar.styled.ts deleted file mode 100644 index 9e1673222..000000000 --- a/packages/mobile/src/Components/SearchBar.styled.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { StyleSheet } from 'react-native' - -export const searchBarStyles = StyleSheet.create({ - androidSearch: { - height: 30, - }, -}) diff --git a/packages/mobile/src/Components/SearchBar.tsx b/packages/mobile/src/Components/SearchBar.tsx deleted file mode 100644 index 814e67aa7..000000000 --- a/packages/mobile/src/Components/SearchBar.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { ThemeServiceContext } from '@Style/ThemeService' -import React, { FC, RefObject, useCallback, useContext } from 'react' -import { Platform } from 'react-native' -import IosSearchBar from 'react-native-search-bar' -import AndroidSearchBar from 'react-native-search-box' -import { ThemeContext } from 'styled-components/native' -import { searchBarStyles } from './/SearchBar.styled' - -type Props = { - onChangeText: (text: string) => void - onSearchCancel: () => void - iosSearchBarInputRef: RefObject - androidSearchBarInputRef: RefObject - onSearchFocusCallback?: () => void - onSearchBlurCallback?: () => void - collapseSearchBarOnBlur?: boolean -} - -export const SearchBar: FC = ({ - onChangeText, - onSearchCancel, - iosSearchBarInputRef, - androidSearchBarInputRef, - onSearchFocusCallback, - onSearchBlurCallback, - collapseSearchBarOnBlur = true, -}) => { - const theme = useContext(ThemeContext) - const themeService = useContext(ThemeServiceContext) - - const onSearchFocus = useCallback(() => { - onSearchFocusCallback?.() - }, [onSearchFocusCallback]) - - const onSearchBlur = useCallback(() => { - onSearchBlurCallback?.() - }, [onSearchBlurCallback]) - - return ( - <> - {Platform.OS === 'ios' && ( - { - iosSearchBarInputRef.current?.blur() - }} - onCancelButtonPress={() => { - iosSearchBarInputRef.current?.blur() - onSearchCancel() - }} - onFocus={onSearchFocus} - onBlur={onSearchBlur} - /> - )} - {Platform.OS === 'android' && ( - { - onSearchBlur() - onSearchCancel() - }} - onDelete={onSearchCancel} - onFocus={onSearchFocus} - onBlur={onSearchBlur} - collapseOnBlur={collapseSearchBarOnBlur} - blurOnSubmit={true} - backgroundColor={theme.stylekitBackgroundColor} - titleCancelColor={theme.stylekitInfoColor} - keyboardDismissMode={'interactive'} - keyboardAppearance={themeService?.keyboardColorForActiveTheme()} - inputBorderRadius={4} - tintColorSearch={theme.stylekitForegroundColor} - inputStyle={[ - searchBarStyles.androidSearch, - { - color: theme.stylekitForegroundColor, - backgroundColor: theme.stylekitContrastBackgroundColor, - }, - ]} - placeholderExpandedMargin={25} - searchIconCollapsedMargin={30} - /> - )} - - ) -} diff --git a/packages/mobile/src/Components/SectionHeader.tsx b/packages/mobile/src/Components/SectionHeader.tsx deleted file mode 100644 index 32a0aa028..000000000 --- a/packages/mobile/src/Components/SectionHeader.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import React from 'react' -import { Platform } from 'react-native' -import styled from 'styled-components/native' - -type Props = { - title?: string - subtitle?: string - buttonText?: string - buttonAction?: () => void - buttonStyles?: any - tinted?: boolean - backgroundColor?: string -} - -const Container = styled.View>` - /* flex: 1; */ - /* flex-grow: 0; */ - justify-content: space-between; - flex-direction: row; - padding-right: ${(props) => props.theme.paddingLeft}px; - padding-bottom: 10px; - padding-top: 10px; - background-color: ${(props) => props.backgroundColor ?? props.theme.stylekitBackgroundColor}; -` -const TitleContainer = styled.View`` -const Title = styled.Text>` - background-color: ${(props) => props.theme.stylekitBackgroundColor}; - font-size: ${(props) => { - return Platform.OS === 'android' ? props.theme.mainTextFontSize - 2 : props.theme.mainTextFontSize - 4 - }}px; - padding-left: ${(props) => props.theme.paddingLeft}px; - color: ${(props) => { - if (props.tinted) { - return props.theme.stylekitInfoColor - } - - return Platform.OS === 'android' ? props.theme.stylekitInfoColor : props.theme.stylekitNeutralColor - }}; - font-weight: ${Platform.OS === 'android' ? 'bold' : 'normal'}; -` -const SubTitle = styled.Text` - background-color: ${(props) => props.theme.stylekitBackgroundColor}; - font-size: ${(props) => props.theme.mainTextFontSize - 5}px; - margin-top: 4px; - padding-left: ${(props) => props.theme.paddingLeft}px; - color: ${(props) => props.theme.stylekitNeutralColor}; -` -const ButtonContainer = styled.TouchableOpacity` - flex: 1; - align-items: flex-end; - justify-content: center; -` -const Button = styled.Text` - color: ${(props) => props.theme.stylekitInfoColor}; -` - -export const SectionHeader: React.FC = (props) => ( - - - {!!props.title && ( - - {Platform.select({ - ios: props.title.toUpperCase(), - android: props.title, - })} - - )} - {!!props.subtitle && {props.subtitle}} - - {!!props.buttonText && ( - - - - )} - -) diff --git a/packages/mobile/src/Components/SectionedAccessoryTableCell.tsx b/packages/mobile/src/Components/SectionedAccessoryTableCell.tsx deleted file mode 100644 index 0806de525..000000000 --- a/packages/mobile/src/Components/SectionedAccessoryTableCell.tsx +++ /dev/null @@ -1,132 +0,0 @@ -import React, { useContext } from 'react' -import { Platform } from 'react-native' -import Icon from 'react-native-vector-icons/Ionicons' -import { ThemeContext } from 'styled-components' -import styled, { css } from 'styled-components/native' -import { SectionedTableCellTouchableHighlight } from './/SectionedTableCell' - -type Props = { - testID?: string - disabled?: boolean - onPress: () => void - onLongPress?: () => void - iconName?: string - selected?: () => boolean - leftAlignIcon?: boolean - color?: string - bold?: boolean - tinted?: boolean - dimmed?: boolean - text: string - first?: boolean - last?: boolean -} - -const TouchableContainer = styled(SectionedTableCellTouchableHighlight).attrs((props) => ({ - underlayColor: props.theme.stylekitBorderColor, -}))` - flex-direction: column; - padding-top: 0px; - padding-bottom: 0px; - min-height: 47px; - background-color: transparent; -` -const ContentContainer = styled.View>` - flex: 1; - justify-content: ${(props) => { - return props.leftAlignIcon ? 'flex-start' : 'space-between' - }}; - flex-direction: row; - align-items: center; -` -const IconContainer = styled.View` - width: 30px; - max-width: 30px; -` -type LabelProps = Pick -const Label = styled.Text` - min-width: 80%; - color: ${(props) => { - let color = props.theme.stylekitForegroundColor - if (props.tinted) { - color = props.theme.stylekitInfoColor - } - if (props.dimmed) { - color = props.theme.stylekitNeutralColor - } - if (props.color) { - color = props.color - } - return color - }}; - font-size: ${(props) => props.theme.mainTextFontSize}px; - ${({ bold, selected }) => - ((selected && selected() === true) || bold) && - css` - font-weight: bold; - `}; -` - -export const SectionedAccessoryTableCell: React.FC = (props) => { - const themeContext = useContext(ThemeContext) - const onPress = () => { - if (props.disabled) { - return - } - - props.onPress() - } - - const onLongPress = () => { - if (props.disabled) { - return - } - - if (props.onLongPress) { - props.onLongPress() - } - } - - const checkmarkName = Platform.OS === 'android' ? 'md-checkbox' : 'ios-checkmark-circle' - const iconName = props.iconName ? props.iconName : props.selected && props.selected() ? checkmarkName : null - - const left = props.leftAlignIcon - let iconSize = left ? 25 : 30 - let color = left ? themeContext.stylekitForegroundColor : themeContext.stylekitInfoColor - - if (Platform.OS === 'android') { - iconSize -= 5 - } - - if (props.color) { - color = props.color - } - let icon: any = null - - if (iconName) { - icon = ( - - - - ) - } - - const textWrapper = ( - - ) - - return ( - - {props.leftAlignIcon ? [icon, textWrapper] : [textWrapper, icon]} - - ) -} diff --git a/packages/mobile/src/Components/SectionedOptionsTableCell.tsx b/packages/mobile/src/Components/SectionedOptionsTableCell.tsx deleted file mode 100644 index e05636ee8..000000000 --- a/packages/mobile/src/Components/SectionedOptionsTableCell.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import React from 'react' -import styled, { css } from 'styled-components/native' - -export type Option = { selected: boolean; key: string; title: string } - -type Props = { - testID?: string - title: string - first?: boolean - height?: number - onPress: (option: Option) => void - options: Option[] - leftAligned?: boolean -} -type ContainerProps = Omit - -export const Container = styled.View` - border-bottom-color: ${(props) => props.theme.stylekitBorderColor}; - border-bottom-width: 1px; - padding-left: ${(props) => props.theme.paddingLeft}px; - padding-right: ${(props) => props.theme.paddingLeft}px; - background-color: ${(props) => props.theme.stylekitBackgroundColor}; - ${({ first, theme }) => - first && - css` - border-top-color: ${theme.stylekitBorderColor}; - border-top-width: ${1}px; - `}; - ${({ height }) => - height && - css` - height: ${height}px; - `}; - flex-direction: row; - justify-content: center; - align-items: center; - max-height: 45px; -` - -const Title = styled.Text<{ leftAligned?: boolean }>` - font-size: ${(props) => props.theme.mainTextFontSize}px; - color: ${(props) => props.theme.stylekitForegroundColor}; - text-align: ${(props) => (props.leftAligned ? 'left' : 'center')}; - width: 42%; - min-width: 0px; -` - -const OptionsContainer = styled.View` - width: 58%; - flex-direction: row; - align-items: center; - justify-content: center; - background-color: ${(props) => props.theme.stylekitBackgroundColor}; -` - -const ButtonTouchable = styled.TouchableHighlight.attrs((props) => ({ - underlayColor: props.theme.stylekitBorderColor, -}))` - border-left-color: ${(props) => props.theme.stylekitBorderColor}; - border-left-width: 1px; - flex-grow: 1; - padding: 10px; - padding-top: 12px; -` - -const ButtonTitle = styled.Text<{ selected: boolean }>` - color: ${(props) => { - return props.selected ? props.theme.stylekitInfoColor : props.theme.stylekitNeutralColor - }}; - font-size: 16px; - text-align: center; - width: 100%; -` - -export const SectionedOptionsTableCell: React.FC = (props) => ( - - {props.title} - - {props.options.map((option) => { - return ( - props.onPress(option)}> - {option.title} - - ) - })} - - -) diff --git a/packages/mobile/src/Components/SectionedTableCell.ts b/packages/mobile/src/Components/SectionedTableCell.ts deleted file mode 100644 index 360395195..000000000 --- a/packages/mobile/src/Components/SectionedTableCell.ts +++ /dev/null @@ -1,59 +0,0 @@ -import styled, { css } from 'styled-components/native' - -export type Props = { - first?: boolean - last?: boolean - textInputCell?: any - height?: number - extraStyles?: any -} - -export const SectionedTableCell = styled.View` - border-bottom-color: ${(props) => props.theme.stylekitBorderColor}; - border-bottom-width: 1px; - padding-left: ${(props) => props.theme.paddingLeft}px; - padding-right: ${(props) => props.theme.paddingLeft}px; - padding-bottom: ${(props) => (props.textInputCell ? 0 : 12)}px; - background-color: ${(props) => props.theme.stylekitBackgroundColor}; - ${({ first, theme }) => - first && - css` - border-top-color: ${theme.stylekitBorderColor}; - border-top-width: ${1}px; - `}; - ${({ textInputCell }) => - textInputCell && - css` - max-height: 50px; - `}; - ${({ height }) => - height && - css` - height: ${height}px; - `}; -` - -export const SectionedTableCellTouchableHighlight = styled.TouchableHighlight` - border-bottom-color: ${(props) => props.theme.stylekitBorderColor}; - border-bottom-width: 1px; - padding-left: ${(props) => props.theme.paddingLeft}px; - padding-right: ${(props) => props.theme.paddingLeft}px; - padding-bottom: ${(props) => (props.textInputCell ? 0 : 12)}px; - background-color: ${(props) => props.theme.stylekitBackgroundColor}; - ${({ first, theme }) => - first && - css` - border-top-color: ${theme.stylekitBorderColor}; - border-top-width: ${1}px; - `}; - ${({ textInputCell }) => - textInputCell && - css` - max-height: 50px; - `}; - ${({ height }) => - height && - css` - height: ${height}px; - `}; -` diff --git a/packages/mobile/src/Components/SnIcon.tsx b/packages/mobile/src/Components/SnIcon.tsx deleted file mode 100644 index 17f94b6d1..000000000 --- a/packages/mobile/src/Components/SnIcon.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import ArchiveIcon from '@standardnotes/icons/src/Icons/ic-archive.svg' -import AttachmentFileIcon from '@standardnotes/icons/src/Icons/ic-attachment-file.svg' -import AuthenticatorIcon from '@standardnotes/icons/src/Icons/ic-authenticator.svg' -import ClearCircleFilledIcon from '@standardnotes/icons/src/Icons/ic-clear-circle-filled.svg' -import CodeIcon from '@standardnotes/icons/src/Icons/ic-code.svg' -import FileDocIcon from '@standardnotes/icons/src/Icons/ic-file-doc.svg' -import FileImageIcon from '@standardnotes/icons/src/Icons/ic-file-image.svg' -import FileMovIcon from '@standardnotes/icons/src/Icons/ic-file-mov.svg' -import FileMusicIcon from '@standardnotes/icons/src/Icons/ic-file-music.svg' -import FileOtherIcon from '@standardnotes/icons/src/Icons/ic-file-other.svg' -import FilePdfIcon from '@standardnotes/icons/src/Icons/ic-file-pdf.svg' -import FilePptIcon from '@standardnotes/icons/src/Icons/ic-file-ppt.svg' -import FileXlsIcon from '@standardnotes/icons/src/Icons/ic-file-xls.svg' -import FileZipIcon from '@standardnotes/icons/src/Icons/ic-file-zip.svg' -import LockFilledIcon from '@standardnotes/icons/src/Icons/ic-lock-filled.svg' -import MarkdownIcon from '@standardnotes/icons/src/Icons/ic-markdown.svg' -import NotesIcon from '@standardnotes/icons/src/Icons/ic-notes.svg' -import OpenInIcon from '@standardnotes/icons/src/Icons/ic-open-in.svg' -import PencilOffIcon from '@standardnotes/icons/src/Icons/ic-pencil-off.svg' -import PinFilledIcon from '@standardnotes/icons/src/Icons/ic-pin-filled.svg' -import SpreadsheetsIcon from '@standardnotes/icons/src/Icons/ic-spreadsheets.svg' -import TasksIcon from '@standardnotes/icons/src/Icons/ic-tasks.svg' -import PlainTextIcon from '@standardnotes/icons/src/Icons/ic-text-paragraph.svg' -import RichTextIcon from '@standardnotes/icons/src/Icons/ic-text-rich.svg' -import TrashFilledIcon from '@standardnotes/icons/src/Icons/ic-trash-filled.svg' -import UserAddIcon from '@standardnotes/icons/src/Icons/ic-user-add.svg' -import FilesIllustration from '@standardnotes/icons/src/Icons/il-files.svg' - -import { IconType } from '@standardnotes/snjs' -import React, { FC, useContext } from 'react' -import { SvgProps } from 'react-native-svg' -import { ThemeContext } from 'styled-components' -import { iconStyles } from './/Icon.styled' - -type TIcons = { - [key in IconType]: FC -} - -const ICONS: Partial = { - 'pencil-off': PencilOffIcon, - 'plain-text': PlainTextIcon, - 'rich-text': RichTextIcon, - code: CodeIcon, - markdown: MarkdownIcon, - spreadsheets: SpreadsheetsIcon, - tasks: TasksIcon, - authenticator: AuthenticatorIcon, - 'trash-filled': TrashFilledIcon, - 'pin-filled': PinFilledIcon, - archive: ArchiveIcon, - 'user-add': UserAddIcon, - 'open-in': OpenInIcon, - notes: NotesIcon, - 'attachment-file': AttachmentFileIcon, - 'files-illustration': FilesIllustration, - 'file-doc': FileDocIcon, - 'file-image': FileImageIcon, - 'file-mov': FileMovIcon, - 'file-music': FileMusicIcon, - 'file-other': FileOtherIcon, - 'file-pdf': FilePdfIcon, - 'file-ppt': FilePptIcon, - 'file-xls': FileXlsIcon, - 'file-zip': FileZipIcon, - 'clear-circle-filled': ClearCircleFilledIcon, - 'lock-filled': LockFilledIcon, -} - -type Props = { - type: IconType - fill?: string - style?: Record - width?: number - height?: number -} - -export const SnIcon = ({ type, fill, width, height, style = {} }: Props) => { - const theme = useContext(ThemeContext) - const fillColor = fill || theme.stylekitPalSky - - const IconComponent = ICONS[type] - - if (!IconComponent) { - return null - } - - let customSizes = {} - if (width !== undefined) { - customSizes = { - ...customSizes, - width, - } - } - if (height !== undefined) { - customSizes = { - ...customSizes, - height, - } - } - - return -} diff --git a/packages/mobile/src/Components/TableSection.ts b/packages/mobile/src/Components/TableSection.ts deleted file mode 100644 index 112d12115..000000000 --- a/packages/mobile/src/Components/TableSection.ts +++ /dev/null @@ -1,7 +0,0 @@ -import styled from 'styled-components/native' - -export const TableSection = styled.View` - margin-top: 10px; - margin-bottom: 10px; - background-color: ${(props) => props.theme.stylekitBackgroundColor}; -` diff --git a/packages/mobile/src/Components/ToastWrapper.styled.ts b/packages/mobile/src/Components/ToastWrapper.styled.ts deleted file mode 100644 index 04121ce59..000000000 --- a/packages/mobile/src/Components/ToastWrapper.styled.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { StyleSheet } from 'react-native' -import { DefaultTheme } from 'styled-components/native' - -export const useToastStyles = (theme: DefaultTheme) => { - return (props: { [key: string]: unknown }) => { - return StyleSheet.create({ - info: { - borderLeftColor: theme.stylekitInfoColor, - height: props.percentComplete !== undefined ? 70 : 60, - }, - animatedViewContainer: { - height: 8, - borderWidth: 1, - borderRadius: 8, - borderColor: theme.stylekitInfoColor, - marginRight: 8, - marginLeft: 12, - marginTop: -16, - }, - animatedView: { - backgroundColor: theme.stylekitInfoColor, - }, - success: { - borderLeftColor: theme.stylekitSuccessColor, - }, - error: { - borderLeftColor: theme.stylekitWarningColor, - }, - }) - } -} diff --git a/packages/mobile/src/Components/ToastWrapper.tsx b/packages/mobile/src/Components/ToastWrapper.tsx deleted file mode 100644 index 5b7b87af0..000000000 --- a/packages/mobile/src/Components/ToastWrapper.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { useToastStyles } from '@Components/ToastWrapper.styled' -import { useProgressBar } from '@Root/Hooks/useProgessBar' -import React, { FC, useContext } from 'react' -import { Animated, StyleSheet, View } from 'react-native' -import Toast, { ErrorToast, InfoToast, SuccessToast, ToastConfig } from 'react-native-toast-message' -import { ThemeContext } from 'styled-components' - -export const ToastWrapper: FC = () => { - const theme = useContext(ThemeContext) - const styles = useToastStyles(theme) - - const { updateProgressBar, progressBarWidth } = useProgressBar() - - const toastStyles: ToastConfig = { - info: (props) => { - const percentComplete = props.props?.percentComplete || 0 - updateProgressBar(percentComplete) - - return ( - - - {props.props?.percentComplete !== undefined ? ( - - - - ) : null} - - ) - }, - success: (props) => { - const percentComplete = props.props?.percentComplete || 0 - updateProgressBar(percentComplete) - - return - }, - error: (props) => { - const percentComplete = props.props?.percentComplete || 0 - updateProgressBar(percentComplete) - - return - }, - } - - return -} diff --git a/packages/mobile/src/Components/package.json b/packages/mobile/src/Components/package.json deleted file mode 100644 index 370c4e4eb..000000000 --- a/packages/mobile/src/Components/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": "@Components" -} diff --git a/packages/mobile/src/HistoryStack.tsx b/packages/mobile/src/HistoryStack.tsx deleted file mode 100644 index b6f8e1d4b..000000000 --- a/packages/mobile/src/HistoryStack.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import { RouteProp } from '@react-navigation/native' -import { createStackNavigator, StackNavigationProp } from '@react-navigation/stack' -import { HeaderTitleView } from '@Root/Components/HeaderTitleView' -import { IoniconsHeaderButton } from '@Root/Components/IoniconsHeaderButton' -import { NoteHistory } from '@Root/Screens/NoteHistory/NoteHistory' -import { NoteHistoryPreview } from '@Root/Screens/NoteHistory/NoteHistoryPreview' -import { SCREEN_NOTE_HISTORY, SCREEN_NOTE_HISTORY_PREVIEW } from '@Root/Screens/screens' -import { NoteHistoryEntry } from '@standardnotes/snjs' -import { ICON_CHECKMARK } from '@Style/Icons' -import { ThemeService } from '@Style/ThemeService' -import React, { useContext } from 'react' -import { Platform } from 'react-native' -import { HeaderButtons, Item } from 'react-navigation-header-buttons' -import { ThemeContext } from 'styled-components' -import { HeaderTitleParams } from './NativeApp' - -type HistoryStackNavigatorParamList = { - [SCREEN_NOTE_HISTORY]: (HeaderTitleParams & { noteUuid: string }) | (undefined & { noteUuid: string }) - [SCREEN_NOTE_HISTORY_PREVIEW]: HeaderTitleParams & { - revision: NoteHistoryEntry - originalNoteUuid: string - } -} - -export type HistoryStackNavigationProp = { - navigation: StackNavigationProp - route: RouteProp -} - -const MainStack = createStackNavigator() - -export const HistoryStack = () => { - const theme = useContext(ThemeContext) - - return ( - - ({ - title: 'Note history', - headerBackTitleVisible: false, - headerLeft: ({ disabled, onPress }) => ( - - - - ), - headerTitle: ({ children }) => { - return ( - - ) - }, - })} - component={NoteHistory} - /> - ({ - title: 'Preview', - headerBackTitleVisible: false, - headerTitle: ({ children }) => { - return ( - - ) - }, - })} - component={NoteHistoryPreview} - /> - - ) -} diff --git a/packages/mobile/src/Hooks/useFiles.ts b/packages/mobile/src/Hooks/useFiles.ts deleted file mode 100644 index 004ca2b07..000000000 --- a/packages/mobile/src/Hooks/useFiles.ts +++ /dev/null @@ -1,816 +0,0 @@ -import { ErrorMessage } from '@Lib/constants' -import { ToastType } from '@Lib/Types' -import { useNavigation } from '@react-navigation/native' -import { useSafeApplicationContext } from '@Root/Hooks/useSafeApplicationContext' -import { SCREEN_INPUT_MODAL_FILE_NAME } from '@Root/Screens/screens' -import { TAppStackNavigationProp } from '@Root/Screens/UploadedFilesList/UploadedFileItem' -import { - UploadedFileItemAction, - UploadedFileItemActionType, -} from '@Root/Screens/UploadedFilesList/UploadedFileItemAction' -import { Tabs } from '@Screens/UploadedFilesList/UploadedFilesList' -import { - ButtonType, - ChallengeReason, - ClientDisplayableError, - ContentType, - FileDownloadProgress, - FileItem, - SNNote, -} from '@standardnotes/snjs' -import { CustomActionSheetOption, useCustomActionSheet } from '@Style/CustomActionSheet' -import { useCallback, useEffect, useState } from 'react' -import { Platform } from 'react-native' -import DocumentPicker, { DocumentPickerResponse, isInProgress, pickMultiple } from 'react-native-document-picker' -import FileViewer from 'react-native-file-viewer' -import RNFS, { exists } from 'react-native-fs' -import { Asset, launchCamera, launchImageLibrary, MediaType } from 'react-native-image-picker' -import RNShare from 'react-native-share' -import Toast from 'react-native-toast-message' - -type Props = { - note: SNNote -} -type TDownloadFileAndReturnLocalPathParams = { - file: FileItem - saveInTempLocation?: boolean - showSuccessToast?: boolean -} - -type TUploadFileFromCameraOrImageGalleryParams = { - uploadFromGallery?: boolean - mediaType?: MediaType -} - -export const isFileTypePreviewable = (fileType: string) => { - const isImage = fileType.startsWith('image/') - const isVideo = fileType.startsWith('video/') - const isAudio = fileType.startsWith('audio/') - const isPdf = fileType === 'application/pdf' - const isText = fileType === 'text/plain' - - return isImage || isVideo || isAudio || isPdf || isText -} - -export const useFiles = ({ note }: Props) => { - const application = useSafeApplicationContext() - - const { showActionSheet } = useCustomActionSheet() - const navigation = useNavigation() - - const [attachedFiles, setAttachedFiles] = useState([]) - const [allFiles, setAllFiles] = useState([]) - const [isDownloading, setIsDownloading] = useState(false) - - const { GeneralText } = ErrorMessage - const { Success, Info, Error } = ToastType - - const filesService = application.getFilesService() - - const reloadAttachedFiles = useCallback(() => { - setAttachedFiles(application.items.getSortedFilesLinkingToItem(note).sort(filesService.sortByName)) - }, [application.items, filesService.sortByName, note]) - - const reloadAllFiles = useCallback(() => { - setAllFiles(application.items.getItems(ContentType.File).sort(filesService.sortByName) as FileItem[]) - }, [application.items, filesService.sortByName]) - - const deleteFileAtPath = useCallback(async (path: string) => { - try { - if (await exists(path)) { - await RNFS.unlink(path) - } - } catch (err) { - console.error(err) - } - }, []) - - const showDownloadToastWithProgressBar = useCallback( - (percentComplete: number | undefined) => { - const percentCompleteFormatted = filesService.formatCompletedPercent(percentComplete) - - Toast.show({ - type: Info, - text1: `Downloading and decrypting file... (${percentCompleteFormatted}%)`, - props: { - percentComplete: percentCompleteFormatted, - }, - autoHide: false, - }) - }, - [Info, filesService], - ) - - const showUploadToastWithProgressBar = useCallback( - (fileName: string, percentComplete: number | undefined) => { - const percentCompleteFormatted = filesService.formatCompletedPercent(percentComplete) - - Toast.show({ - type: Info, - text1: `Uploading "${fileName}"... (${percentCompleteFormatted}%)`, - autoHide: false, - props: { - percentComplete: percentCompleteFormatted, - }, - }) - }, - [Info, filesService], - ) - - const resetProgressState = useCallback(() => { - Toast.show({ - type: Info, - props: { - percentComplete: 0, - }, - onShow: Toast.hide, - }) - }, [Info]) - - const updateProgressPercentOnDownload = useCallback( - (progress: FileDownloadProgress | undefined) => { - showDownloadToastWithProgressBar(progress?.percentComplete) - }, - [showDownloadToastWithProgressBar], - ) - - const downloadFileAndReturnLocalPath = useCallback( - async ({ - file, - saveInTempLocation = false, - showSuccessToast = true, - }: TDownloadFileAndReturnLocalPathParams): Promise => { - if (isDownloading) { - return - } - const isGrantedStoragePermissionOnAndroid = await filesService.hasStoragePermissionOnAndroid() - - if (!isGrantedStoragePermissionOnAndroid) { - return - } - setIsDownloading(true) - - try { - showDownloadToastWithProgressBar(0) - - const path = filesService.getDestinationPath({ - fileName: file.name, - saveInTempLocation, - }) - - await deleteFileAtPath(path) - const response = await filesService.downloadFileInChunks(file, path, updateProgressPercentOnDownload) - - resetProgressState() - - if (response instanceof ClientDisplayableError) { - Toast.show({ - type: Error, - text1: 'Error', - text2: response.text || GeneralText, - }) - return - } - - if (showSuccessToast) { - Toast.show({ - type: Success, - text1: 'Success', - text2: 'Successfully downloaded. Press here to open the file.', - position: 'bottom', - onPress: async () => { - await FileViewer.open(path, { showOpenWithDialog: true }) - }, - }) - } else { - Toast.hide() - } - - return path - } catch (error) { - Toast.show({ - type: Error, - text1: 'Error', - text2: 'An error occurred while downloading the file', - onPress: Toast.hide, - }) - return - } finally { - setIsDownloading(false) - } - }, - [ - Error, - GeneralText, - Success, - deleteFileAtPath, - filesService, - isDownloading, - resetProgressState, - showDownloadToastWithProgressBar, - updateProgressPercentOnDownload, - ], - ) - - const cleanupTempFileOnAndroid = useCallback( - async (downloadedFilePath: string) => { - if (Platform.OS === 'android') { - await deleteFileAtPath(downloadedFilePath) - } - }, - [deleteFileAtPath], - ) - - const shareFile = useCallback( - async (file: FileItem) => { - const downloadedFilePath = await downloadFileAndReturnLocalPath({ - file, - saveInTempLocation: true, - showSuccessToast: false, - }) - if (!downloadedFilePath) { - return - } - await application.getAppState().performActionWithoutStateChangeImpact(async () => { - try { - // On Android this response always returns {success: false}, there is an open issue for that: - // https://github.com/react-native-share/react-native-share/issues/1059 - const shareDialogResponse = await RNShare.open({ - url: `file://${downloadedFilePath}`, - failOnCancel: false, - }) - - // On iOS the user can store files locally from "Share" screen, so we don't show "Download" option there. - // For Android the user has a separate "Download" action for the file, therefore after the file is shared, - // it's not needed anymore and we remove it from the storage. - await cleanupTempFileOnAndroid(downloadedFilePath) - - if (shareDialogResponse.success) { - Toast.show({ - type: Success, - text1: 'Successfully exported. Press here to open the file.', - position: 'bottom', - onPress: async () => { - await FileViewer.open(downloadedFilePath) - }, - }) - } - } catch (error) { - Toast.show({ - type: Error, - text1: 'An error occurred while trying to share this file', - onPress: Toast.hide, - }) - } - }) - }, - [Error, Success, application, cleanupTempFileOnAndroid, downloadFileAndReturnLocalPath], - ) - - const attachFileToNote = useCallback( - async (file: FileItem, showToastAfterAction = true) => { - await application.items.associateFileWithNote(file, note) - void application.sync.sync() - - if (showToastAfterAction) { - Toast.show({ - type: Success, - text1: 'Successfully attached file to note', - onPress: Toast.hide, - }) - } - }, - [Success, application, note], - ) - - const detachFileFromNote = useCallback( - async (file: FileItem) => { - await application.items.disassociateFileWithNote(file, note) - void application.sync.sync() - Toast.show({ - type: Success, - text1: 'Successfully detached file from note', - onPress: Toast.hide, - }) - }, - [Success, application, note], - ) - - const toggleFileProtection = useCallback( - async (file: FileItem) => { - try { - let result: FileItem | undefined - if (file.protected) { - result = await application.mutator.unprotectFile(file) - } else { - result = await application.mutator.protectFile(file) - } - const isProtected = result ? result.protected : file.protected - return isProtected - } catch (error) { - console.error('An error occurred: ', error) - return file.protected - } - }, - [application], - ) - - const authorizeProtectedActionForFile = useCallback( - async (file: FileItem, challengeReason: ChallengeReason) => { - const authorizedFiles = await application.protections.authorizeProtectedActionForItems([file], challengeReason) - return authorizedFiles.length > 0 && authorizedFiles.includes(file) - }, - [application], - ) - - const renameFile = useCallback( - async (file: FileItem, fileName: string) => { - await application.items.renameFile(file, fileName) - }, - [application], - ) - - const previewFile = useCallback( - async (file: FileItem) => { - let downloadedFilePath: string | undefined = '' - try { - const isPreviewable = isFileTypePreviewable(file.mimeType) - - if (!isPreviewable) { - const tryToPreview = await application.alertService.confirm( - 'This file may not be previewable. Do you wish to try anyway?', - '', - 'Try to preview', - ButtonType.Info, - 'Cancel', - ) - if (!tryToPreview) { - return - } - } - - downloadedFilePath = await downloadFileAndReturnLocalPath({ - file, - saveInTempLocation: true, - showSuccessToast: false, - }) - - if (!downloadedFilePath) { - return - } - await FileViewer.open(downloadedFilePath, { - onDismiss: async () => { - await cleanupTempFileOnAndroid(downloadedFilePath as string) - }, - }) - - return true - } catch (error) { - await cleanupTempFileOnAndroid(downloadedFilePath as string) - await application.alertService.alert('An error occurred while previewing the file.') - - return false - } - }, - [application, cleanupTempFileOnAndroid, downloadFileAndReturnLocalPath], - ) - - const deleteFile = useCallback( - async (file: FileItem) => { - const shouldDelete = await application.alertService.confirm( - `Are you sure you want to permanently delete "${file.name}"?`, - undefined, - 'Confirm', - ButtonType.Danger, - 'Cancel', - ) - if (shouldDelete) { - Toast.show({ - type: Info, - text1: `Deleting "${file.name}"...`, - }) - const response = await application.files.deleteFile(file) - - if (response instanceof ClientDisplayableError) { - Toast.show({ - type: Error, - text1: 'Error', - text2: response.text || GeneralText, - }) - return - } - - Toast.show({ - type: Success, - text1: `Successfully deleted "${file.name}"`, - }) - } - }, - [Error, GeneralText, Info, Success, application.alertService, application.files], - ) - - const handlePickFilesError = async (error: unknown) => { - if (DocumentPicker.isCancel(error)) { - // User canceled the picker, exit any dialogs or menus and move on - } else if (isInProgress(error)) { - Toast.show({ - type: Info, - text2: 'Multiple pickers were opened; only the last one will be considered.', - }) - } else { - Toast.show({ - type: Error, - text1: 'An error occurred while attempting to select files.', - }) - } - } - - const handleUploadError = async () => { - Toast.show({ - type: Error, - text1: 'Error', - text2: 'An error occurred while uploading file(s).', - }) - } - - const pickFiles = async (): Promise => { - try { - const selectedFiles = await pickMultiple() - - return selectedFiles - } catch (error) { - await handlePickFilesError(error) - } - } - - const uploadSingleFile = async (file: DocumentPickerResponse | Asset, size: number): Promise => { - try { - const fileName = filesService.getFileName(file) - const operation = await application.files.beginNewFileUpload(size) - - if (operation instanceof ClientDisplayableError) { - Toast.show({ - type: Error, - text1: operation.text, - }) - return - } - - const initialPercentComplete = operation.getProgress().percentComplete - - showUploadToastWithProgressBar(fileName, initialPercentComplete) - - const onChunk = async (chunk: Uint8Array, index: number, isLast: boolean) => { - await application.files.pushBytesForUpload(operation, chunk, index, isLast) - showUploadToastWithProgressBar(fileName, operation.getProgress().percentComplete) - } - - const fileResult = await filesService.readFile(file, onChunk) - const fileObj = await application.files.finishUpload(operation, fileResult) - - resetProgressState() - - if (fileObj instanceof ClientDisplayableError) { - Toast.show({ - type: Error, - text1: fileObj.text, - }) - return - } - return fileObj - } catch (error) { - await handleUploadError() - } - } - - const uploadFiles = async (): Promise => { - try { - const selectedFiles = await pickFiles() - if (!selectedFiles || selectedFiles.length === 0) { - return - } - const uploadedFiles: FileItem[] = [] - for (const file of selectedFiles) { - if (!file.uri || !file.size) { - continue - } - const fileObject = await uploadSingleFile(file, file.size) - if (!fileObject) { - Toast.show({ - type: Error, - text1: 'Error', - text2: `An error occurred while uploading ${file.name}.`, - }) - continue - } - uploadedFiles.push(fileObject) - - Toast.show({ text1: `Successfully uploaded ${fileObject.name}` }) - } - if (selectedFiles.length > 1) { - Toast.show({ text1: 'Successfully uploaded' }) - } - - return uploadedFiles - } catch (error) { - await handleUploadError() - } - } - - const handleAttachFromCamera = (currentTab: Tabs | undefined) => { - const options = [ - { - text: 'Photo', - callback: async () => { - const uploadedFile = await uploadFileFromCameraOrImageGallery({ - mediaType: 'photo', - }) - if (!uploadedFile) { - return - } - if (shouldAttachToNote(currentTab)) { - await attachFileToNote(uploadedFile, false) - } - }, - }, - { - text: 'Video', - callback: async () => { - const uploadedFile = await uploadFileFromCameraOrImageGallery({ - mediaType: 'video', - }) - if (!uploadedFile) { - return - } - await attachFileToNote(uploadedFile, false) - }, - }, - ] - showActionSheet({ - title: 'Choose file type', - options, - }) - } - - const shouldAttachToNote = (currentTab: Tabs | undefined) => { - return currentTab === undefined || currentTab === Tabs.AttachedFiles - } - - const handlePressAttachFile = (currentTab?: Tabs) => { - const options: CustomActionSheetOption[] = [ - { - text: 'Attach from files', - key: 'files', - callback: async () => { - const uploadedFiles = await uploadFiles() - if (!uploadedFiles) { - return - } - if (shouldAttachToNote(currentTab)) { - uploadedFiles.forEach((file) => attachFileToNote(file, false)) - } - }, - }, - { - text: 'Attach from Photo Library', - key: 'library', - callback: async () => { - const uploadedFile = await uploadFileFromCameraOrImageGallery({ - uploadFromGallery: true, - }) - if (!uploadedFile) { - return - } - if (shouldAttachToNote(currentTab)) { - await attachFileToNote(uploadedFile, false) - } - }, - }, - { - text: 'Attach from Camera', - key: 'camera', - callback: async () => { - handleAttachFromCamera(currentTab) - }, - }, - ] - const osSpecificOptions = Platform.OS === 'android' ? options.filter((option) => option.key !== 'library') : options - showActionSheet({ - title: 'Choose action', - options: osSpecificOptions, - }) - } - - const uploadFileFromCameraOrImageGallery = async ({ - uploadFromGallery = false, - mediaType = 'photo', - }: TUploadFileFromCameraOrImageGalleryParams): Promise => { - try { - const result = uploadFromGallery - ? await launchImageLibrary({ mediaType: 'mixed' }) - : await launchCamera({ mediaType }) - - if (result.didCancel || !result.assets) { - return - } - const file = result.assets[0] - const fileObject = await uploadSingleFile(file, file.fileSize || 0) - if (!file.uri || !file.fileSize) { - return - } - if (!fileObject) { - Toast.show({ - type: Error, - text1: 'Error', - text2: `An error occurred while uploading ${file.fileName}.`, - }) - return - } - Toast.show({ text1: `Successfully uploaded ${fileObject.name}` }) - - return fileObject - } catch (error) { - await handleUploadError() - } - } - - const handleFileAction = useCallback( - async (action: UploadedFileItemAction) => { - const file = action.payload - let isAuthorizedForAction = true - - if (file.protected && action.type !== UploadedFileItemActionType.ToggleFileProtection) { - isAuthorizedForAction = await authorizeProtectedActionForFile(file, ChallengeReason.AccessProtectedFile) - } - - if (!isAuthorizedForAction) { - return false - } - - switch (action.type) { - case UploadedFileItemActionType.AttachFileToNote: - await attachFileToNote(file) - break - case UploadedFileItemActionType.DetachFileToNote: - await detachFileFromNote(file) - break - case UploadedFileItemActionType.ShareFile: - await shareFile(file) - break - case UploadedFileItemActionType.DownloadFile: - await downloadFileAndReturnLocalPath({ file }) - break - case UploadedFileItemActionType.ToggleFileProtection: { - await toggleFileProtection(file) - break - } - case UploadedFileItemActionType.RenameFile: - navigation.navigate(SCREEN_INPUT_MODAL_FILE_NAME, { - file, - renameFile, - }) - break - case UploadedFileItemActionType.PreviewFile: - await previewFile(file) - break - case UploadedFileItemActionType.DeleteFile: - await deleteFile(file) - break - default: - break - } - - await application.sync.sync() - return true - }, - [ - application.sync, - attachFileToNote, - authorizeProtectedActionForFile, - deleteFile, - detachFileFromNote, - downloadFileAndReturnLocalPath, - navigation, - previewFile, - renameFile, - shareFile, - toggleFileProtection, - ], - ) - - useEffect(() => { - const unregisterFileStream = application.streamItems(ContentType.File, () => { - reloadAttachedFiles() - reloadAllFiles() - }) - - return () => { - unregisterFileStream() - } - }, [application, reloadAllFiles, reloadAttachedFiles]) - - const showActionsMenu = useCallback( - (file: FileItem | undefined) => { - if (!file) { - return - } - const isAttachedToNote = attachedFiles.includes(file) - - const actions: CustomActionSheetOption[] = [ - { - text: 'Preview', - callback: async () => { - await handleFileAction({ - type: UploadedFileItemActionType.PreviewFile, - payload: file, - }) - }, - }, - { - text: isAttachedToNote ? 'Detach from note' : 'Attach to note', - callback: isAttachedToNote - ? async () => { - await handleFileAction({ - type: UploadedFileItemActionType.DetachFileToNote, - payload: file, - }) - } - : async () => { - await handleFileAction({ - type: UploadedFileItemActionType.AttachFileToNote, - payload: file, - }) - }, - }, - { - text: `${file.protected ? 'Disable' : 'Enable'} password protection`, - callback: async () => { - await handleFileAction({ - type: UploadedFileItemActionType.ToggleFileProtection, - payload: file, - }) - }, - }, - { - text: Platform.OS === 'ios' ? 'Export' : 'Share', - callback: async () => { - await handleFileAction({ - type: UploadedFileItemActionType.ShareFile, - payload: file, - }) - }, - }, - { - text: 'Download', - callback: async () => { - await handleFileAction({ - type: UploadedFileItemActionType.DownloadFile, - payload: file, - }) - }, - }, - { - text: 'Rename', - callback: async () => { - await handleFileAction({ - type: UploadedFileItemActionType.RenameFile, - payload: file, - }) - }, - }, - { - text: 'Delete permanently', - callback: async () => { - await handleFileAction({ - type: UploadedFileItemActionType.DeleteFile, - payload: file, - }) - }, - destructive: true, - }, - ] - const osDependentActions = - Platform.OS === 'ios' ? actions.filter((action) => action.text !== 'Download') : [...actions] - showActionSheet({ - title: file.name, - options: osDependentActions, - styles: { - titleTextStyle: { - fontWeight: 'bold', - }, - }, - }) - }, - [attachedFiles, handleFileAction, showActionSheet], - ) - - return { - showActionsMenu, - attachedFiles, - allFiles, - handleFileAction, - handlePressAttachFile, - uploadFileFromCameraOrImageGallery, - attachFileToNote, - } -} diff --git a/packages/mobile/src/Hooks/useProgessBar.ts b/packages/mobile/src/Hooks/useProgessBar.ts deleted file mode 100644 index 8a0456ec0..000000000 --- a/packages/mobile/src/Hooks/useProgessBar.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { useCallback, useRef } from 'react' -import { Animated } from 'react-native' - -export const useProgressBar = () => { - const counterRef = useRef(new Animated.Value(0)).current - - const updateProgressBar = useCallback( - (percentComplete: number) => { - Animated.timing(counterRef, { - toValue: percentComplete, - duration: 500, - useNativeDriver: false, - }).start() - }, - [counterRef], - ) - - const progressBarWidth = counterRef.interpolate({ - inputRange: [0, 100], - outputRange: ['0%', '100%'], - extrapolate: 'identity', - }) - - return { - updateProgressBar, - progressBarWidth, - } -} diff --git a/packages/mobile/src/Hooks/useSafeApplicationContext.ts b/packages/mobile/src/Hooks/useSafeApplicationContext.ts deleted file mode 100644 index b594647f1..000000000 --- a/packages/mobile/src/Hooks/useSafeApplicationContext.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { MobileApplication } from '@Lib/Application' -import { ApplicationContext } from '@Root/ApplicationContext' -import { useContext } from 'react' - -export const useSafeApplicationContext = () => { - const application = useContext(ApplicationContext) as MobileApplication - return application -} diff --git a/packages/mobile/src/Hooks/useSafeApplicationGroupContext.ts b/packages/mobile/src/Hooks/useSafeApplicationGroupContext.ts deleted file mode 100644 index 7919c55a5..000000000 --- a/packages/mobile/src/Hooks/useSafeApplicationGroupContext.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { ApplicationGroup } from '@Lib/ApplicationGroup' -import { ApplicationGroupContext } from '@Root/ApplicationGroupContext' -import { useContext } from 'react' - -export const useSafeApplicationGroupContext = () => { - const applicationGroupContext = useContext(ApplicationGroupContext) as ApplicationGroup - return applicationGroupContext -} diff --git a/packages/mobile/src/Lib/AlertService.ts b/packages/mobile/src/Lib/AlertService.ts deleted file mode 100644 index 589a792dc..000000000 --- a/packages/mobile/src/Lib/AlertService.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { MODAL_BLOCKING_ALERT } from '@Root/Screens/screens' -import { AlertService, ButtonType, DismissBlockingDialog } from '@standardnotes/snjs' -import { Alert, AlertButton } from 'react-native' -import { goBack, navigate } from './NavigationService' - -export class MobileAlertService extends AlertService { - blockingDialog(text: string, title?: string): DismissBlockingDialog | Promise { - navigate(MODAL_BLOCKING_ALERT, { text, title }) - - return goBack - } - alert(text: string, title: string, closeButtonText?: string) { - return new Promise((resolve) => { - // On iOS, confirm should go first. On Android, cancel should go first. - const buttons = [ - { - text: closeButtonText, - onPress: async () => { - resolve() - }, - }, - ] - Alert.alert(title, text, buttons, { - cancelable: true, - }) - }) - } - - confirm( - text: string, - title: string, - confirmButtonText = 'Confirm', - confirmButtonType?: ButtonType, - cancelButtonText = 'Cancel', - ) { - return new Promise((resolve, reject) => { - // On iOS, confirm should go first. On Android, cancel should go first. - const buttons: AlertButton[] = [ - { - text: cancelButtonText, - style: 'cancel', - onPress: async () => { - resolve(false) - }, - }, - { - text: confirmButtonText, - style: confirmButtonType === ButtonType.Danger ? 'destructive' : 'default', - onPress: async () => { - resolve(true) - }, - }, - ] - Alert.alert(title, text, buttons, { - cancelable: true, - onDismiss: async () => { - reject() - }, - }) - }) - } -} diff --git a/packages/mobile/src/Lib/Application.ts b/packages/mobile/src/Lib/Application.ts deleted file mode 100644 index 107094d48..000000000 --- a/packages/mobile/src/Lib/Application.ts +++ /dev/null @@ -1,171 +0,0 @@ -import { SCREEN_AUTHENTICATE } from '@Root/Screens/screens' -import { - Challenge, - ChallengePrompt, - ChallengeReason, - ChallengeValidation, - DeinitMode, - DeinitSource, - Environment, - IconsController, - ItemGroupController, - MobileUnlockTiming, - platformFromString, - SNApplication, - SNComponentManager, - StorageValueModes, -} from '@standardnotes/snjs' -import { Platform } from 'react-native' - -import { version } from '../../package.json' -import { MobileAlertService } from './AlertService' -import { ApplicationState } from './ApplicationState' -import { BackupsService } from './BackupsService' -import { ComponentManager } from './ComponentManager' -import { AlwaysOpenWebAppOnLaunchKey } from './constants' -import { FilesService } from './FilesService' -import { InstallationService } from './InstallationService' -import { MobileDevice } from './Interface' -import { push } from './NavigationService' -import { PreferencesManager } from './PreferencesManager' -import { SNReactNativeCrypto } from './ReactNativeCrypto' -import { ReviewService } from './ReviewService' -import { StatusManager } from './StatusManager' -import { IsDev, IsMobileWeb } from './Utils' - -type MobileServices = { - applicationState: ApplicationState - reviewService: ReviewService - backupsService: BackupsService - installationService: InstallationService - prefsService: PreferencesManager - statusManager: StatusManager - filesService: FilesService -} - -export class MobileApplication extends SNApplication { - private MobileServices!: MobileServices - public editorGroup: ItemGroupController - public iconsController: IconsController - private startedDeinit = false - - // UI remounts when Uuid changes - public Uuid: string - - static previouslyLaunched = false - - constructor(deviceInterface: MobileDevice, identifier: string) { - super({ - environment: Environment.Mobile, - platform: platformFromString(Platform.OS), - deviceInterface: deviceInterface, - crypto: new SNReactNativeCrypto(), - alertService: new MobileAlertService(), - identifier, - swapClasses: [ - { - swap: SNComponentManager, - with: ComponentManager, - }, - ], - defaultHost: IsDev ? 'https://api-dev.standardnotes.com' : 'https://api.standardnotes.com', - appVersion: version, - webSocketUrl: IsDev ? 'wss://sockets-dev.standardnotes.com' : 'wss://sockets.standardnotes.com', - }) - - this.Uuid = Math.random().toString() - this.editorGroup = new ItemGroupController(this) - this.iconsController = new IconsController() - - void this.mobileComponentManager.initialize(this.protocolService) - } - - get mobileComponentManager(): ComponentManager { - return this.componentManager as ComponentManager - } - - static getPreviouslyLaunched() { - return this.previouslyLaunched - } - - static setPreviouslyLaunched() { - this.previouslyLaunched = true - } - - public hasStartedDeinit() { - return this.startedDeinit - } - - override deinit(mode: DeinitMode, source: DeinitSource): void { - this.startedDeinit = true - - for (const service of Object.values(this.MobileServices)) { - if (service.deinit) { - service.deinit() - } - - if ('application' in service) { - const typedService = service as { application?: MobileApplication } - typedService.application = undefined - } - } - - this.MobileServices = {} as MobileServices - this.editorGroup.deinit() - super.deinit(mode, source) - } - - override getLaunchChallenge() { - const challenge = super.getLaunchChallenge() - - if (!challenge) { - return undefined - } - - const previouslyLaunched = MobileApplication.getPreviouslyLaunched() - const biometricsTiming = this.getAppState().biometricsTiming - - if (previouslyLaunched && biometricsTiming === MobileUnlockTiming.OnQuit) { - const filteredPrompts = challenge.prompts.filter( - (prompt: ChallengePrompt) => prompt.validation !== ChallengeValidation.Biometric, - ) - - return new Challenge(filteredPrompts, ChallengeReason.ApplicationUnlock, false) - } - - return challenge - } - - promptForChallenge(challenge: Challenge) { - const optedIntoWebPreview = this.getValue(AlwaysOpenWebAppOnLaunchKey, StorageValueModes.Nonwrapped) as boolean - if (IsMobileWeb || optedIntoWebPreview) { - return - } - - push(SCREEN_AUTHENTICATE, { challenge, title: challenge.modalTitle }) - } - - setMobileServices(services: MobileServices) { - this.MobileServices = services - } - - public getAppState() { - return this.MobileServices.applicationState - } - - public getBackupsService() { - return this.MobileServices.backupsService - } - - public getLocalPreferences() { - return this.MobileServices.prefsService - } - - public getStatusManager() { - return this.MobileServices.statusManager - } - - public getFilesService() { - return this.MobileServices.filesService - } -} diff --git a/packages/mobile/src/Lib/ApplicationGroup.ts b/packages/mobile/src/Lib/ApplicationGroup.ts deleted file mode 100644 index fb7e24f00..000000000 --- a/packages/mobile/src/Lib/ApplicationGroup.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { ApplicationDescriptor, DeviceInterface, InternalEventBus, SNApplicationGroup } from '@standardnotes/snjs' -import { MobileApplication } from './Application' -import { ApplicationState } from './ApplicationState' -import { BackupsService } from './BackupsService' -import { FilesService } from './FilesService' -import { InstallationService } from './InstallationService' -import { MobileDevice } from './Interface' -import { PreferencesManager } from './PreferencesManager' -import { ReviewService } from './ReviewService' -import { StatusManager } from './StatusManager' - -export class ApplicationGroup extends SNApplicationGroup { - constructor() { - super(new MobileDevice()) - } - - override async initialize(_callback?: any): Promise { - await super.initialize({ - applicationCreator: this.createApplication, - }) - } - - private createApplication = async (descriptor: ApplicationDescriptor, deviceInterface: DeviceInterface) => { - const application = new MobileApplication(deviceInterface as MobileDevice, descriptor.identifier) - const internalEventBus = new InternalEventBus() - const applicationState = new ApplicationState(application) - const reviewService = new ReviewService(application, internalEventBus) - const backupsService = new BackupsService(application, internalEventBus) - const prefsService = new PreferencesManager(application, internalEventBus) - const installationService = new InstallationService(application, internalEventBus) - const statusManager = new StatusManager(application, internalEventBus) - const filesService = new FilesService(application, internalEventBus) - application.setMobileServices({ - applicationState, - reviewService, - backupsService, - prefsService, - installationService, - statusManager, - filesService, - }) - return application - } -} diff --git a/packages/mobile/src/Lib/ApplicationState.ts b/packages/mobile/src/Lib/ApplicationState.ts deleted file mode 100644 index f28b14493..000000000 --- a/packages/mobile/src/Lib/ApplicationState.ts +++ /dev/null @@ -1,644 +0,0 @@ -import { MobileDevice } from '@Lib/Interface' -import { - ApplicationEvent, - ApplicationService, - Challenge, - ChallengePrompt, - ChallengeReason, - ChallengeValidation, - ContentType, - InternalEventBus, - isNullOrUndefined, - MobileUnlockTiming, - NoteViewController, - PayloadEmitSource, - PrefKey, - removeFromArray, - SmartView, - SNNote, - SNTag, - SNUserPrefs, - StorageKey, - StorageValueModes, - SystemViewId, - Uuid, -} from '@standardnotes/snjs' -import { - AppState, - AppStateStatus, - EmitterSubscription, - InteractionManager, - Keyboard, - KeyboardEventListener, - NativeEventSubscription, - NativeModules, -} from 'react-native' -import { hide, show } from 'react-native-privacy-snapshot' -import VersionInfo from 'react-native-version-info' -import pjson from '../../package.json' -import { MobileApplication } from './Application' -import { associateComponentWithNote } from './ComponentManager' - -const { PlatformConstants } = NativeModules - -export enum AppStateType { - LosingFocus = 1, - EnteringBackground = 2, - GainingFocus = 3, - ResumingFromBackground = 4, - TagChanged = 5, - EditorClosed = 6, - PreferencesChanged = 7, -} - -export enum LockStateType { - Locked = 1, - Unlocked = 2, -} - -export enum AppStateEventType { - KeyboardChangeEvent = 1, - TabletModeChange = 2, - DrawerOpen = 3, -} - -export type TabletModeChangeData = { - new_isInTabletMode: boolean - old_isInTabletMode: boolean -} - -export enum PasscodeKeyboardType { - Default = 'default', - Numeric = 'numeric', -} - -export enum MobileStorageKey { - PasscodeKeyboardTypeKey = 'passcodeKeyboardType', -} - -type EventObserverCallback = (event: AppStateEventType, data?: TabletModeChangeData) => void | Promise -type ObserverCallback = (event: AppStateType, data?: unknown) => void | Promise -type LockStateObserverCallback = (event: LockStateType) => void | Promise - -export class ApplicationState extends ApplicationService { - override application: MobileApplication - observers: ObserverCallback[] = [] - private stateObservers: EventObserverCallback[] = [] - private lockStateObservers: LockStateObserverCallback[] = [] - locked = true - keyboardDidShowListener?: EmitterSubscription - keyboardDidHideListener?: EmitterSubscription - keyboardHeight?: number - removeAppEventObserver!: () => void - selectedTagRestored = false - selectedTag: SNTag | SmartView = this.application.items.getSmartViews()[0] - userPreferences?: SNUserPrefs - tabletMode = false - ignoreStateChanges = false - mostRecentState?: AppStateType - authenticationInProgress = false - multiEditorEnabled = false - screenshotPrivacyEnabled?: boolean - passcodeTiming?: MobileUnlockTiming - biometricsTiming?: MobileUnlockTiming - removeHandleReactNativeAppStateChangeListener: NativeEventSubscription - removeItemChangesListener?: () => void - removePreferencesLoadedListener?: () => void - - constructor(application: MobileApplication) { - super(application, new InternalEventBus()) - this.application = application - this.setTabletModeEnabled(this.isTabletDevice) - this.handleApplicationEvents() - this.handleItemsChanges() - - this.removeHandleReactNativeAppStateChangeListener = AppState.addEventListener( - 'change', - this.handleReactNativeAppStateChange, - ) - - this.keyboardDidShowListener = Keyboard.addListener('keyboardWillShow', this.keyboardDidShow) - this.keyboardDidHideListener = Keyboard.addListener('keyboardWillHide', this.keyboardDidHide) - } - - override deinit() { - this.removeAppEventObserver() - ;(this.removeAppEventObserver as unknown) = undefined - - this.removeHandleReactNativeAppStateChangeListener.remove() - if (this.removeItemChangesListener) { - this.removeItemChangesListener() - } - if (this.removePreferencesLoadedListener) { - this.removePreferencesLoadedListener() - } - - this.observers.length = 0 - this.keyboardDidShowListener = undefined - this.keyboardDidHideListener = undefined - } - - restoreSelectedTag() { - if (this.selectedTagRestored) { - return - } - const savedTagUuid: string | undefined = this.prefService.getValue(PrefKey.MobileSelectedTagUuid, undefined) - - if (isNullOrUndefined(savedTagUuid)) { - this.selectedTagRestored = true - return - } - - const savedTag = - (this.application.items.findItem(savedTagUuid) as SNTag) || - this.application.items.getSmartViews().find((tag) => tag.uuid === savedTagUuid) - if (savedTag) { - this.setSelectedTag(savedTag, false) - this.selectedTagRestored = true - } - } - - override async onAppStart() { - this.removePreferencesLoadedListener = this.prefService.addPreferencesLoadedObserver(() => { - this.notifyOfStateChange(AppStateType.PreferencesChanged) - }) - - await this.loadUnlockTiming() - } - - override async onAppLaunch() { - MobileApplication.setPreviouslyLaunched() - this.screenshotPrivacyEnabled = (await this.getScreenshotPrivacyEnabled()) ?? true - await (this.application.deviceInterface as MobileDevice).setAndroidScreenshotPrivacy(this.screenshotPrivacyEnabled) - } - - /** - * Registers an observer for App State change - * @returns function that unregisters this observer - */ - public addStateChangeObserver(callback: ObserverCallback) { - this.observers.push(callback) - return () => { - removeFromArray(this.observers, callback) - } - } - - /** - * Registers an observer for lock state change - * @returns function that unregisters this observer - */ - public addLockStateChangeObserver(callback: LockStateObserverCallback) { - this.lockStateObservers.push(callback) - return () => { - removeFromArray(this.lockStateObservers, callback) - } - } - - /** - * Registers an observer for App State Event change - * @returns function that unregisters this observer - */ - public addStateEventObserver(callback: EventObserverCallback) { - this.stateObservers.push(callback) - return () => { - removeFromArray(this.stateObservers, callback) - } - } - - /** - * Notify observers of ApplicationState change - */ - private notifyOfStateChange(state: AppStateType, data?: unknown) { - if (this.ignoreStateChanges) { - return - } - - // Set most recent state before notifying observers, in case they need to query this value. - this.mostRecentState = state - - for (const observer of this.observers) { - void observer(state, data) - } - } - - /** - * Notify observers of ApplicationState Events - */ - private notifyEventObservers(event: AppStateEventType, data?: TabletModeChangeData) { - for (const observer of this.stateObservers) { - void observer(event, data) - } - } - - /** - * Notify observers of ApplicationState Events - */ - private notifyLockStateObservers(event: LockStateType) { - for (const observer of this.lockStateObservers) { - void observer(event) - } - } - - private async loadUnlockTiming() { - this.passcodeTiming = await this.getPasscodeTiming() - this.biometricsTiming = await this.getBiometricsTiming() - } - - /** - * Creates a new editor if one doesn't exist. If one does, we'll replace the - * editor's note with an empty one. - */ - async createEditor(title?: string) { - const selectedTagUuid = this.selectedTag - ? this.selectedTag instanceof SmartView - ? undefined - : this.selectedTag.uuid - : undefined - - this.application.editorGroup.closeActiveItemController() - - const noteView = await this.application.editorGroup.createItemController({ title, tag: selectedTagUuid }) - - const defaultEditor = this.application.componentManager.getDefaultEditor() - if (defaultEditor) { - await associateComponentWithNote(this.application, defaultEditor, this.getActiveNoteController().item) - } - - return noteView - } - - async openEditor(noteUuid: string): Promise { - const note = this.application.items.findItem(noteUuid) as SNNote - const activeEditor = this.getActiveNoteController() - if (activeEditor) { - this.application.editorGroup.closeActiveItemController() - } - - const noteView = (await this.application.editorGroup.createItemController(note)) as NoteViewController - - if (note && note.conflictOf) { - void InteractionManager.runAfterInteractions(() => { - void this.application?.mutator.changeAndSaveItem(note, (mutator) => { - mutator.conflictOf = undefined - }) - }) - } - - return noteView - } - - getActiveNoteController(): NoteViewController { - return this.application.editorGroup.itemControllers[0] as NoteViewController - } - - getEditors(): NoteViewController[] { - return this.application.editorGroup.itemControllers as NoteViewController[] - } - - closeEditor(editor: NoteViewController) { - this.notifyOfStateChange(AppStateType.EditorClosed) - this.application.editorGroup.closeItemController(editor) - } - - closeActiveEditor() { - this.notifyOfStateChange(AppStateType.EditorClosed) - this.application.editorGroup.closeActiveItemController() - } - - closeAllEditors() { - this.notifyOfStateChange(AppStateType.EditorClosed) - this.application.editorGroup.closeAllItemControllers() - } - - editorForNote(uuid: Uuid): NoteViewController | void { - for (const editor of this.getEditors()) { - if (editor.item?.uuid === uuid) { - return editor - } - } - } - - private keyboardDidShow: KeyboardEventListener = (e) => { - this.keyboardHeight = e.endCoordinates.height - this.notifyEventObservers(AppStateEventType.KeyboardChangeEvent) - } - - private keyboardDidHide: KeyboardEventListener = () => { - this.keyboardHeight = 0 - this.notifyEventObservers(AppStateEventType.KeyboardChangeEvent) - } - - /** - * @returns Returns keybord height - */ - getKeyboardHeight() { - return this.keyboardHeight - } - - /** - * Reacts to @SNNote and @SNTag Changes - */ - private handleItemsChanges() { - this.removeItemChangesListener = this.application.streamItems( - [ContentType.Note, ContentType.Tag], - async ({ changed, inserted, removed, source }) => { - if (source === PayloadEmitSource.PreSyncSave || source === PayloadEmitSource.RemoteRetrieved) { - const removedNotes = removed.filter((i) => i.content_type === ContentType.Note) - for (const removedNote of removedNotes) { - const editor = this.editorForNote(removedNote.uuid) - if (editor) { - this.closeEditor(editor) - } - } - - const notes = [...changed, ...inserted].filter((candidate) => candidate.content_type === ContentType.Note) - - const isBrowswingTrashedNotes = - this.selectedTag instanceof SmartView && this.selectedTag.uuid === SystemViewId.TrashedNotes - - const isBrowsingArchivedNotes = - this.selectedTag instanceof SmartView && this.selectedTag.uuid === SystemViewId.ArchivedNotes - - for (const note of notes) { - const editor = this.editorForNote(note.uuid) - if (!editor) { - continue - } - - if (note.trashed && !isBrowswingTrashedNotes) { - this.closeEditor(editor) - } else if (note.archived && !isBrowsingArchivedNotes) { - this.closeEditor(editor) - } - } - } - - if (this.selectedTag) { - const matchingTag = [...changed, ...inserted].find((candidate) => candidate.uuid === this.selectedTag.uuid) - if (matchingTag) { - this.selectedTag = matchingTag as SNTag - } - } - }, - ) - } - - /** - * Registers for MobileApplication events - */ - private handleApplicationEvents() { - this.removeAppEventObserver = this.application.addEventObserver(async (eventName) => { - switch (eventName) { - case ApplicationEvent.LocalDataIncrementalLoad: - case ApplicationEvent.LocalDataLoaded: { - this.restoreSelectedTag() - break - } - case ApplicationEvent.Started: { - this.locked = true - break - } - case ApplicationEvent.Launched: { - this.locked = false - this.notifyLockStateObservers(LockStateType.Unlocked) - break - } - } - }) - } - - /** - * Set selected @SNTag - */ - public setSelectedTag(tag: SNTag | SmartView, saveSelection = true) { - if (this.selectedTag.uuid === tag.uuid) { - return - } - const previousTag = this.selectedTag - this.selectedTag = tag - - if (saveSelection) { - void this.application.getLocalPreferences().setUserPrefValue(PrefKey.MobileSelectedTagUuid, tag.uuid) - } - - this.notifyOfStateChange(AppStateType.TagChanged, { - tag, - previousTag, - }) - } - - /** - * @returns tags that are referencing note - */ - public getNoteTags(note: SNNote) { - return this.application.items.itemsReferencingItem(note).filter((ref) => { - return ref.content_type === ContentType.Tag - }) as SNTag[] - } - - /** - * @returns notes this tag references - */ - public getTagNotes(tag: SNTag | SmartView) { - if (tag instanceof SmartView) { - return this.application.items.notesMatchingSmartView(tag) - } else { - return this.application.items.referencesForItem(tag).filter((ref) => { - return ref.content_type === ContentType.Note - }) as SNNote[] - } - } - - public getSelectedTag() { - return this.selectedTag - } - - static get version() { - return `${pjson.version} (${VersionInfo.buildVersion})` - } - - get isTabletDevice() { - const deviceType = PlatformConstants.interfaceIdiom - return deviceType === 'pad' - } - - get isInTabletMode() { - return this.tabletMode - } - - setTabletModeEnabled(enabledTabletMode: boolean) { - if (enabledTabletMode !== this.tabletMode) { - this.tabletMode = enabledTabletMode - this.notifyEventObservers(AppStateEventType.TabletModeChange, { - new_isInTabletMode: enabledTabletMode, - old_isInTabletMode: !enabledTabletMode, - }) - } - } - - private async checkAndLockApplication() { - const isLocked = await this.application.isLocked() - - if (isLocked) { - return - } - - const hasBiometrics = this.application.protections.hasBiometricsEnabled() - const hasPasscode = this.application.hasPasscode() - const passcodeLockImmediately = hasPasscode && this.passcodeTiming === MobileUnlockTiming.Immediately - const biometricsLockImmediately = - hasBiometrics && this.biometricsTiming === MobileUnlockTiming.Immediately && !this.locked - - if (passcodeLockImmediately) { - await this.application.lock() - } else if (biometricsLockImmediately) { - const challenge = new Challenge( - [new ChallengePrompt(ChallengeValidation.Biometric)], - ChallengeReason.ApplicationUnlock, - false, - ) - void this.application.promptForCustomChallenge(challenge) - - this.locked = true - this.notifyLockStateObservers(LockStateType.Locked) - this.application.addChallengeObserver(challenge, { - onComplete: () => { - this.locked = false - this.notifyLockStateObservers(LockStateType.Unlocked) - }, - }) - } - } - - /** - * handles App State change from React Native - */ - private handleReactNativeAppStateChange = async (nextAppState: AppStateStatus) => { - if (this.ignoreStateChanges) { - return - } - - // if the most recent state is not 'background' ('inactive'), then we're going - // from inactive to active, which doesn't really happen unless you, say, swipe - // notification center in iOS down then back up. We don't want to lock on this state change. - const isResuming = nextAppState === 'active' - const isResumingFromBackground = isResuming && this.mostRecentState === AppStateType.EnteringBackground - const isEnteringBackground = nextAppState === 'background' - const isLosingFocus = nextAppState === 'inactive' - - if (isEnteringBackground) { - this.notifyOfStateChange(AppStateType.EnteringBackground) - return this.checkAndLockApplication() - } - - if (isResumingFromBackground || isResuming) { - if (this.screenshotPrivacyEnabled) { - hide() - } - - if (isResumingFromBackground) { - this.notifyOfStateChange(AppStateType.ResumingFromBackground) - } - - // Notify of GainingFocus even if resuming from background - this.notifyOfStateChange(AppStateType.GainingFocus) - return - } - - if (isLosingFocus) { - if (this.screenshotPrivacyEnabled) { - show() - } - - this.notifyOfStateChange(AppStateType.LosingFocus) - return this.checkAndLockApplication() - } - } - - /** - * Visibility change events are like active, inactive, background, - * while non-app cycle events are custom events like locking and unlocking - */ - isAppVisibilityChange(state: AppStateType) { - return ( - [ - AppStateType.LosingFocus, - AppStateType.EnteringBackground, - AppStateType.GainingFocus, - AppStateType.ResumingFromBackground, - ] as Array - ).includes(state) - } - - private async getScreenshotPrivacyEnabled(): Promise { - return this.application.protections.getMobileScreenshotPrivacyEnabled() - } - - private async getPasscodeTiming(): Promise { - return this.application.protections.getMobilePasscodeTiming() - } - - private async getBiometricsTiming(): Promise { - return this.application.protections.getMobileBiometricsTiming() - } - - public async setScreenshotPrivacyEnabled(enabled: boolean) { - await this.application.protections.setMobileScreenshotPrivacyEnabled(enabled) - this.screenshotPrivacyEnabled = enabled - await (this.application.deviceInterface as MobileDevice).setAndroidScreenshotPrivacy(enabled) - } - - public async setPasscodeTiming(timing: MobileUnlockTiming) { - this.application.setValue(StorageKey.MobilePasscodeTiming, timing, StorageValueModes.Nonwrapped) - this.passcodeTiming = timing - } - - public async setBiometricsTiming(timing: MobileUnlockTiming) { - this.application.setValue(StorageKey.MobileBiometricsTiming, timing, StorageValueModes.Nonwrapped) - this.biometricsTiming = timing - } - - public async getPasscodeKeyboardType(): Promise { - return this.application.getValue( - MobileStorageKey.PasscodeKeyboardTypeKey, - StorageValueModes.Nonwrapped, - ) as Promise - } - - public async setPasscodeKeyboardType(type: PasscodeKeyboardType) { - this.application.setValue(MobileStorageKey.PasscodeKeyboardTypeKey, type, StorageValueModes.Nonwrapped) - } - - public onDrawerOpen() { - this.notifyEventObservers(AppStateEventType.DrawerOpen) - } - - /* - Allows other parts of the code to perform external actions without triggering state change notifications. - This is useful on Android when you present a share sheet and dont want immediate authentication to appear. - */ - async performActionWithoutStateChangeImpact(block: () => void | Promise, notAwaited?: boolean) { - this.ignoreStateChanges = true - if (notAwaited) { - void block() - } else { - await block() - } - setTimeout(() => { - this.ignoreStateChanges = false - }, 350) - } - - getMostRecentState() { - return this.mostRecentState - } - - private get prefService() { - return this.application.getLocalPreferences() - } - - public getEnvironment() { - const bundleId = VersionInfo.bundleIdentifier - return bundleId && bundleId.includes('dev') ? 'dev' : 'prod' - } -} diff --git a/packages/mobile/src/Lib/BackupsService.ts b/packages/mobile/src/Lib/BackupsService.ts deleted file mode 100644 index 1d7602473..000000000 --- a/packages/mobile/src/Lib/BackupsService.ts +++ /dev/null @@ -1,162 +0,0 @@ -import { ApplicationService, ButtonType, Platform } from '@standardnotes/snjs' -import { Base64 } from 'js-base64' -import { Alert, PermissionsAndroid, Share } from 'react-native' -import FileViewer from 'react-native-file-viewer' -import RNFS from 'react-native-fs' -import Mailer from 'react-native-mail' -import { MobileApplication } from './Application' - -export class BackupsService extends ApplicationService { - /* - On iOS, we can use Share to share a file of arbitrary length. - This doesn't work on Android however. Seems to have a very low limit. - For Android, we'll use RNFS to save the file to disk, then FileViewer to - ask the user what application they would like to open the file with. - For .txt files, not many applications handle it. So, we'll want to notify the user - the path the file was saved to. - */ - - async export(encrypted: boolean): Promise { - const data = encrypted - ? await this.application.createEncryptedBackupFile() - : await this.application.createDecryptedBackupFile() - const prettyPrint = 2 - const stringifiedData = JSON.stringify(data, null, prettyPrint) - - const modifier = encrypted ? 'Encrypted' : 'Decrypted' - const filename = `Standard Notes ${modifier} Backup - ${this.formattedDate()}.txt` - if (data) { - if (this.application?.platform === Platform.Ios) { - return this.exportIOS(filename, stringifiedData) - } else { - const result = await this.showAndroidEmailOrSaveOption() - if (result === 'email') { - return this.exportViaEmailAndroid(Base64.encode(stringifiedData), filename) - } else if (result === 'save') { - await this.exportAndroid(filename, stringifiedData) - } else { - return - } - } - } - } - - private async showAndroidEmailOrSaveOption() { - try { - const confirmed = await this.application!.alertService?.confirm( - 'Choose Export Method', - '', - 'Email', - ButtonType.Info, - 'Save to Disk', - ) - if (confirmed) { - return 'email' - } else { - return 'save' - } - } catch (e) { - return undefined - } - } - - private async exportIOS(filename: string, data: string) { - return new Promise((resolve) => { - void (this.application! as MobileApplication).getAppState().performActionWithoutStateChangeImpact(async () => { - Share.share({ - title: filename, - message: data, - }) - .then((result) => { - resolve(result.action !== Share.dismissedAction) - }) - .catch(() => { - resolve(false) - }) - }) - }) - } - - private async exportAndroid(filename: string, data: string) { - try { - let filepath = `${RNFS.ExternalDirectoryPath}/${filename}` - const granted = await this.requestStoragePermissionsAndroid() - if (granted) { - filepath = `${RNFS.DownloadDirectoryPath}/${filename}` - } - await RNFS.writeFile(filepath, data) - void this.showFileSavePromptAndroid(filepath) - } catch (err) { - console.error('Error exporting backup', err) - void this.application.alertService.alert('There was an issue exporting your backup.') - } - } - - private async openFileAndroid(filepath: string) { - return FileViewer.open(filepath) - .then(() => { - // success - return true - }) - .catch((error) => { - console.error('Error opening file', error) - return false - }) - } - - private async showFileSavePromptAndroid(filepath: string) { - const confirmed = await this.application!.alertService?.confirm( - `Your backup file has been saved to your local disk at this location:\n\n${filepath}`, - 'Backup Saved', - 'Open File', - ButtonType.Info, - 'Done', - ) - if (confirmed) { - void this.openFileAndroid(filepath) - } - return true - } - - private async exportViaEmailAndroid(data: string, filename: string) { - return new Promise((resolve) => { - const fileType = '.json' // Android creates a tmp file and expects dot with extension - - let resolved = false - Mailer.mail( - { - subject: 'Standard Notes Backup', - recipients: [''], - body: '', - isHTML: true, - attachment: { data, type: fileType, name: filename }, - }, - (error: any) => { - if (error) { - Alert.alert('Error', 'Unable to send email.') - } - resolved = true - resolve(false) - }, - ) - - // On Android the Mailer callback event isn't always triggered. - setTimeout(function () { - if (!resolved) { - resolve(true) - } - }, 2500) - }) - } - - private async requestStoragePermissionsAndroid() { - const writeStorageGranted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE) - return writeStorageGranted === PermissionsAndroid.RESULTS.GRANTED - } - - /* Utils */ - - private formattedDate() { - return new Date().getTime() - } -} diff --git a/packages/mobile/src/Lib/ComponentManager.ts b/packages/mobile/src/Lib/ComponentManager.ts deleted file mode 100644 index b4752d327..000000000 --- a/packages/mobile/src/Lib/ComponentManager.ts +++ /dev/null @@ -1,367 +0,0 @@ -import { MobileTheme } from '@Root/Style/MobileTheme' -import { ComponentChecksumsType } from '@standardnotes/components-meta' -import RawComponentChecksumsFile from '@standardnotes/components-meta/dist/zips/checksums.json' -import { - ComponentMutator, - EncryptionService, - FeatureDescription, - FeatureIdentifier, - GetFeatures, - isRightVersionGreaterThanLeft, - PermissionDialog, - SNApplication, - SNComponent, - SNComponentManager, - SNLog, - SNNote, -} from '@standardnotes/snjs' -import { objectToCss } from '@Style/CssParser' -import { Base64 } from 'js-base64' -import RNFS, { DocumentDirectoryPath } from 'react-native-fs' -import StaticServer from 'react-native-static-server' -import { unzip } from 'react-native-zip-archive' -import { componentsCdn, name, version } from '../../package.json' -import { MobileThemeContent } from '../Style/MobileTheme' -import { IsDev } from './Utils' - -const FeatureChecksums = RawComponentChecksumsFile as ComponentChecksumsType - -export enum ComponentLoadingError { - FailedDownload = 'FailedDownload', - ChecksumMismatch = 'ChecksumMismatch', - LocalServerFailure = 'LocalServerFailure', - DoesntExist = 'DoesntExist', - Unknown = 'Unknown', -} - -const STATIC_SERVER_PORT = 8080 -const BASE_DOCUMENTS_PATH = DocumentDirectoryPath -const COMPONENTS_PATH = '/components' - -export class ComponentManager extends SNComponentManager { - private mobileActiveTheme?: MobileTheme - - private staticServer!: StaticServer - private staticServerUrl!: string - private protocolService!: EncryptionService - private thirdPartyIndexPaths: Record = {} - - public async initialize(protocolService: EncryptionService) { - this.loggingEnabled = true - this.protocolService = protocolService - await this.createServer() - } - - private async createServer() { - const path = `${BASE_DOCUMENTS_PATH}${COMPONENTS_PATH}` - const server = new StaticServer(STATIC_SERVER_PORT, path, { - localOnly: true, - }) - try { - const serverUrl = await server.start() - this.staticServer = server - this.staticServerUrl = serverUrl - } catch (e) { - void this.alertService.alert( - 'Unable to start component server. ' + - 'Editors other than the Plain Editor will fail to load. ' + - 'Please restart the app and try again.', - ) - SNLog.error(e as any) - } - } - - override deinit() { - super.deinit() - void this.staticServer!.stop() - } - - private cdnUrlForFeature(identifier: FeatureIdentifier): string { - const cdn = IsDev ? componentsCdn.dev : componentsCdn.prod - const appVersion = version - const mobilePackageName = name - const tagPath = `${mobilePackageName}@${appVersion}`.replaceAll('@', '%40') - const url = `${cdn}${tagPath}/packages/components/dist/zips/${identifier}.zip` - this.log('Getting zip from cdn url', url) - return url - } - - private downloadUrlForComponent(component: SNComponent): string | undefined { - const identifier = component.identifier - const nativeFeature = this.nativeFeatureForIdentifier(identifier) - if (nativeFeature) { - return this.cdnUrlForFeature(identifier) - } else { - return component.package_info?.download_url - } - } - - public isComponentDownloadable(component: SNComponent): boolean { - const downloadUrl = this.downloadUrlForComponent(component) - return !!downloadUrl - } - - public async uninstallComponent(component: SNComponent) { - const path = this.pathForComponent(component.identifier) - if (await RNFS.exists(path)) { - this.log('Deleting dir at', path) - await RNFS.unlink(path) - } - } - - public async doesComponentNeedDownload(component: SNComponent): Promise { - const identifier = component.identifier - const nativeFeature = this.nativeFeatureForIdentifier(identifier) - const downloadUrl = this.downloadUrlForComponent(component) - - if (!downloadUrl) { - throw Error('Attempting to download component with no download url') - } - - const currentPackageJson = await this.getDownloadedComponentPackageJsonFile(identifier) - const currentVersion = currentPackageJson?.version - const newVersion = nativeFeature ? FeatureChecksums[identifier].version : component.package_info?.version - - if (!newVersion) { - this.log('Cannot retrieve new version string for component', identifier) - return false - } - - this.log('Existing package version', currentVersion) - this.log('Latest package version', newVersion) - - const shouldDownload = !currentPackageJson || isRightVersionGreaterThanLeft(currentVersion, newVersion) - this.log('Needs upgrade', shouldDownload) - - return shouldDownload - } - - public async downloadComponentOffline(component: SNComponent): Promise { - const identifier = component.identifier - const downloadUrl = this.downloadUrlForComponent(component) - - if (!downloadUrl) { - throw Error('Attempting to download component with no download url') - } - - let error - try { - error = await this.performDownloadComponent(identifier, downloadUrl) - } catch (e) { - console.error(e) - return ComponentLoadingError.Unknown - } - - if (error) { - return error - } - - const componentPath = this.pathForComponent(identifier) - if (!(await RNFS.exists(componentPath))) { - this.log(`No component exists at path ${componentPath}, not using offline component`) - return ComponentLoadingError.DoesntExist - } - - return error - } - - public nativeFeatureForIdentifier(identifier: FeatureIdentifier) { - return GetFeatures().find((feature: FeatureDescription) => feature.identifier === identifier) - } - - public isComponentThirdParty(identifier: FeatureIdentifier): boolean { - return !this.nativeFeatureForIdentifier(identifier) - } - - public async preloadThirdPartyIndexPathFromDisk(identifier: FeatureIdentifier) { - const packageJson = await this.getDownloadedComponentPackageJsonFile(identifier) - this.thirdPartyIndexPaths[identifier] = packageJson?.sn?.main || 'index.html' - } - - private async passesChecksumValidation(filePath: string, featureIdentifier: FeatureIdentifier) { - this.log('Performing checksum verification on', filePath) - const zipContents = await RNFS.readFile(filePath, 'base64') - const checksum = await this.protocolService.crypto.sha256(zipContents) - - const desiredChecksum = FeatureChecksums[featureIdentifier]?.base64 - if (!desiredChecksum) { - this.log(`Checksum is missing for ${featureIdentifier}; aborting installation`) - return false - } - - if (checksum !== desiredChecksum) { - this.log(`Checksums don't match for ${featureIdentifier}; ${checksum} != ${desiredChecksum}; aborting install`) - return false - } - - this.log(`Checksum ${checksum} matches ${desiredChecksum} for ${featureIdentifier}`) - - return true - } - - private async performDownloadComponent( - identifier: FeatureIdentifier, - downloadUrl: string, - ): Promise { - const tmpLocation = `${BASE_DOCUMENTS_PATH}/${identifier}.zip` - - if (await RNFS.exists(tmpLocation)) { - this.log('Deleting file at', tmpLocation) - await RNFS.unlink(tmpLocation) - } - - this.log('Downloading component', identifier, 'from url', downloadUrl, 'to location', tmpLocation) - - const result = await RNFS.downloadFile({ - fromUrl: downloadUrl, - toFile: tmpLocation, - }).promise - - if (!String(result.statusCode).startsWith('2')) { - console.error(`Error downloading file ${downloadUrl}`) - return ComponentLoadingError.FailedDownload - } - - this.log('Finished download to tmp location', tmpLocation) - - const requireChecksumVerification = !!this.nativeFeatureForIdentifier(identifier) - if (requireChecksumVerification) { - const passes = await this.passesChecksumValidation(tmpLocation, identifier) - if (!passes) { - return ComponentLoadingError.ChecksumMismatch - } - } - - const componentPath = this.pathForComponent(identifier) - - this.log(`Attempting to unzip ${tmpLocation} to ${componentPath}`) - await unzip(tmpLocation, componentPath) - this.log('Unzipped component to', componentPath) - - const directoryContents = await RNFS.readDir(componentPath) - const isNestedArchive = directoryContents.length === 1 && directoryContents[0].isDirectory() - if (isNestedArchive) { - this.log('Component download includes base level dir that is not its identifier, fixing...') - const nestedDir = directoryContents[0] - const tmpMovePath = `${BASE_DOCUMENTS_PATH}/${identifier}` - await RNFS.moveFile(nestedDir.path, tmpMovePath) - await RNFS.unlink(componentPath) - await RNFS.moveFile(tmpMovePath, componentPath) - this.log(`Moved directory from ${directoryContents[0].path} to ${componentPath}`) - } - await RNFS.unlink(tmpLocation) - return - } - - private pathForComponent(identifier: FeatureIdentifier) { - return `${BASE_DOCUMENTS_PATH}${COMPONENTS_PATH}/${identifier}` - } - - public async getFile(identifier: FeatureIdentifier, relativePath: string) { - const componentPath = this.pathForComponent(identifier) - if (!(await RNFS.exists(componentPath))) { - return undefined - } - - const filePath = `${componentPath}/${relativePath}` - if (!(await RNFS.exists(filePath))) { - return undefined - } - - const fileContents = await RNFS.readFile(filePath) - return fileContents - } - - public async getIndexFile(identifier: FeatureIdentifier) { - if (this.isComponentThirdParty(identifier)) { - await this.preloadThirdPartyIndexPathFromDisk(identifier) - } - const relativePath = this.getIndexFileRelativePath(identifier) - return this.getFile(identifier, relativePath!) - } - - private async getDownloadedComponentPackageJsonFile( - identifier: FeatureIdentifier, - ): Promise | undefined> { - const file = await this.getFile(identifier, 'package.json') - if (!file) { - return undefined - } - const packageJson = JSON.parse(file) - return packageJson - } - - override async presentPermissionsDialog(dialog: PermissionDialog) { - const text = `${dialog.component.name} would like to interact with your ${dialog.permissionsString}` - const approved = await this.alertService.confirm(text, 'Grant Permissions', 'Continue', undefined, 'Cancel') - dialog.callback(approved) - } - - private getIndexFileRelativePath(identifier: FeatureIdentifier) { - const nativeFeature = this.nativeFeatureForIdentifier(identifier) - if (nativeFeature) { - return nativeFeature.index_path - } else { - return this.thirdPartyIndexPaths[identifier] - } - } - - override urlForComponent(component: SNComponent) { - if (component.isTheme() && (component.content as MobileThemeContent).isSystemTheme) { - const theme = component as MobileTheme - const cssData = objectToCss(theme.mobileContent.variables) - const encoded = Base64.encodeURI(cssData) - return `data:text/css;base64,${encoded}` - } - - if (!this.isComponentDownloadable(component)) { - return super.urlForComponent(component) - } - - const identifier = component.identifier - const componentPath = this.pathForComponent(identifier) - const indexFilePath = this.getIndexFileRelativePath(identifier) - - if (!indexFilePath) { - throw Error('Third party index path was not preloaded') - } - - const splitPackagePath = componentPath.split(COMPONENTS_PATH) - const relativePackagePath = splitPackagePath[splitPackagePath.length - 1] - const relativeMainFilePath = `${relativePackagePath}/${indexFilePath}` - const url = `${this.staticServerUrl}${relativeMainFilePath}` - return url - } - - public setMobileActiveTheme(theme: MobileTheme) { - this.mobileActiveTheme = theme - this.postActiveThemesToAllViewers() - } - - override getActiveThemes() { - if (this.mobileActiveTheme) { - return [this.mobileActiveTheme] - } else { - return [] - } - } - - public async preloadThirdPartyThemeIndexPath() { - const theme = this.mobileActiveTheme - if (!theme) { - return - } - - const { identifier } = theme - if (this.isComponentThirdParty(identifier)) { - await this.preloadThirdPartyIndexPathFromDisk(identifier) - } - } -} - -export async function associateComponentWithNote(application: SNApplication, component: SNComponent, note: SNNote) { - return application.mutator.changeItem(component, (mutator) => { - mutator.removeDisassociatedItemId(note.uuid) - mutator.associateWithItem(note.uuid) - }) -} diff --git a/packages/mobile/src/Lib/FilesService.ts b/packages/mobile/src/Lib/FilesService.ts deleted file mode 100644 index 86b694f96..000000000 --- a/packages/mobile/src/Lib/FilesService.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { FileSelectionResponse } from '@standardnotes/filepicker' -import { - ApplicationService, - ByteChunker, - ClientDisplayableError, - FileDownloadProgress, - FileItem, - OnChunkCallback, -} from '@standardnotes/snjs' -import { Buffer } from 'buffer' -import { Base64 } from 'js-base64' -import { PermissionsAndroid, Platform } from 'react-native' -import { DocumentPickerResponse } from 'react-native-document-picker' -import RNFS, { CachesDirectoryPath, DocumentDirectoryPath, DownloadDirectoryPath, read } from 'react-native-fs' -import { Asset } from 'react-native-image-picker' - -type TGetFileDestinationPath = { - fileName: string - saveInTempLocation?: boolean -} - -export class FilesService extends ApplicationService { - private fileChunkSizeForReading = 2000000 - - getDestinationPath({ fileName, saveInTempLocation = false }: TGetFileDestinationPath): string { - let directory = DocumentDirectoryPath - - if (Platform.OS === 'android') { - directory = saveInTempLocation ? CachesDirectoryPath : DownloadDirectoryPath - } - return `${directory}/${fileName}` - } - - async hasStoragePermissionOnAndroid(): Promise { - if (Platform.OS !== 'android') { - return true - } - const grantedStatus = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE) - if (grantedStatus === PermissionsAndroid.RESULTS.GRANTED) { - return true - } - await this.application.alertService.alert( - 'Storage permissions are required in order to download files. Please accept the permissions prompt and try again.', - ) - return false - } - - async downloadFileInChunks( - file: FileItem, - path: string, - handleOnChunk: (progress: FileDownloadProgress | undefined) => unknown, - ): Promise { - const response = await this.application.files.downloadFile(file, async (decryptedBytes: Uint8Array, progress) => { - const base64String = new Buffer(decryptedBytes).toString('base64') - handleOnChunk(progress) - - await RNFS.appendFile(path, base64String, 'base64') - }) - return response - } - - getFileName(file: DocumentPickerResponse | Asset) { - if ('name' in file) { - return file.name - } - return file.fileName as string - } - - async readFile(file: DocumentPickerResponse | Asset, onChunk: OnChunkCallback): Promise { - const fileUri = (Platform.OS === 'ios' ? decodeURI(file.uri!) : file.uri) as string - - let positionShift = 0 - let filePortion = '' - - const chunker = new ByteChunker(this.application.files.minimumChunkSize(), onChunk) - let isFinalChunk = false - - do { - filePortion = await read(fileUri, this.fileChunkSizeForReading, positionShift, 'base64') - const bytes = Base64.toUint8Array(filePortion) - isFinalChunk = bytes.length < this.fileChunkSizeForReading - - await chunker.addBytes(bytes, isFinalChunk) - - positionShift += this.fileChunkSizeForReading - } while (!isFinalChunk) - - const fileName = this.getFileName(file) - - return { - name: fileName, - mimeType: file.type || '', - } - } - - sortByName(file1: FileItem, file2: FileItem): number { - return file1.name.toLocaleLowerCase() > file2.name.toLocaleLowerCase() ? 1 : -1 - } - - formatCompletedPercent(percent: number | undefined) { - return Math.round(percent || 0) - } -} diff --git a/packages/mobile/src/Lib/InstallationService.ts b/packages/mobile/src/Lib/InstallationService.ts deleted file mode 100644 index a3ed50824..000000000 --- a/packages/mobile/src/Lib/InstallationService.ts +++ /dev/null @@ -1,64 +0,0 @@ -import SNReactNative from '@standardnotes/react-native-utils' -import { ApplicationService, ButtonType, StorageValueModes } from '@standardnotes/snjs' -import { MobileDevice } from './Interface' - -const FIRST_RUN_KEY = 'first_run' - -export class InstallationService extends ApplicationService { - override async onAppStart() { - if (await this.needsWipe()) { - await this.wipeData() - } else { - void this.markApplicationAsRan() - } - } - - async markApplicationAsRan() { - return this.application.deviceInterface.setRawStorageValue(FIRST_RUN_KEY, 'false') - } - - /** - * Needs wipe if has keys but no data. However, since "no data" can be incorrectly reported by underlying - * AsyncStorage failures, we want to confirm with the user before deleting anything. - */ - async needsWipe() { - const hasAccountOrPasscode = this.application.hasAccount() || this.application?.hasPasscode() - const deviceInterface = this.application.deviceInterface as MobileDevice - const keychainKey = await deviceInterface.getNamespacedKeychainValue(this.application.identifier) - - const hasKeychainValue = keychainKey != undefined - - const firstRunKey = await this.application.deviceInterface.getRawStorageValue(FIRST_RUN_KEY) - let firstRunKeyMissing = firstRunKey == undefined - if (firstRunKeyMissing) { - const fallbackFirstRunValue = await this.application.getValue(FIRST_RUN_KEY, StorageValueModes.Nonwrapped) - firstRunKeyMissing = fallbackFirstRunValue == undefined - } - - return !hasAccountOrPasscode && hasKeychainValue && firstRunKeyMissing - } - - /** - * On iOS, keychain data is persisted between installs/uninstalls. (https://stackoverflow.com/questions/4747404/delete-keychain-items-when-an-app-is-uninstalled) - * This prevents the user from deleting the app and reinstalling if they forgot their local passocde - * or if fingerprint scanning isn't working. By deleting all data on first run, we allow the user to reset app - * state after uninstall. - */ - async wipeData() { - const confirmed = await this.application?.alertService?.confirm( - "We've detected a previous installation of Standard Notes based on your keychain data. You must wipe all data from previous installation to continue.\n\nIf you're seeing this message in error, it might mean we're having issues loading your local database. Please restart the app and try again.", - 'Previous Installation', - 'Delete Local Data', - ButtonType.Danger, - 'Quit App', - ) - - if (confirmed) { - await this.application?.deviceInterface?.removeAllRawStorageValues() - await this.application?.deviceInterface?.removeAllRawDatabasePayloads(this.application?.identifier) - await this.application?.deviceInterface?.clearRawKeychainValue() - } else { - SNReactNative.exitApp() - } - } -} diff --git a/packages/mobile/src/Lib/Interface.ts b/packages/mobile/src/Lib/Interface.ts index 68814a2f4..7911983bc 100644 --- a/packages/mobile/src/Lib/Interface.ts +++ b/packages/mobile/src/Lib/Interface.ts @@ -1,5 +1,4 @@ import AsyncStorage from '@react-native-community/async-storage' -import { AndroidBackHandlerService } from '@Root/AndroidBackHandlerService' import SNReactNative from '@standardnotes/react-native-utils' import { ApplicationIdentifier, @@ -27,9 +26,9 @@ import { } from 'react-native-fs' import { hide, show } from 'react-native-privacy-snapshot' import Share from 'react-native-share' +import { AndroidBackHandlerService } from '../AndroidBackHandlerService' import { AppStateObserverService } from './../AppStateObserverService' import Keychain from './Keychain' -import { IsMobileWeb } from './Utils' export type BiometricsType = 'Fingerprint' | 'Face ID' | 'Biometrics' | 'Touch ID' @@ -435,11 +434,7 @@ export class MobileDevice implements MobileDeviceInterface { } performSoftReset() { - if (IsMobileWeb) { - this.notifyEvent(MobileDeviceEvent.RequestsWebViewReload) - } else { - SNReactNative.exitApp() - } + this.notifyEvent(MobileDeviceEvent.RequestsWebViewReload) } addMobileWebEventReceiver(handler: MobileDeviceEventHandler): () => void { diff --git a/packages/mobile/src/Lib/NavigationService.ts b/packages/mobile/src/Lib/NavigationService.ts deleted file mode 100644 index 703c46c56..000000000 --- a/packages/mobile/src/Lib/NavigationService.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { NavigationContainerRef, StackActions } from '@react-navigation/native' -import { AppStackNavigatorParamList } from '@Root/AppStack' -import { ModalStackNavigatorParamList } from '@Root/ModalStack' -import * as React from 'react' - -export const navigationRef = - React.createRef>() - -export function navigate(name: keyof AppStackNavigatorParamList | keyof ModalStackNavigatorParamList, params?: any) { - navigationRef.current?.navigate(name, params) -} - -export function push(name: string, params?: any) { - const pushAction = StackActions.push(name, params) - - navigationRef.current?.dispatch(pushAction) -} - -export function goBack() { - navigationRef.current?.goBack() -} diff --git a/packages/mobile/src/Lib/PreferencesManager.ts b/packages/mobile/src/Lib/PreferencesManager.ts deleted file mode 100644 index b6603e5a1..000000000 --- a/packages/mobile/src/Lib/PreferencesManager.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { ApplicationService, isNullOrUndefined, PrefKey, removeFromArray } from '@standardnotes/snjs' -import { MobileApplication } from './Application' - -type Preferences = Record -type PreferencesObserver = () => Promise | void -export const LAST_EXPORT_DATE_KEY = 'LastExportDateKey' -const PREFS_KEY = 'preferences' - -export class PreferencesManager extends ApplicationService { - private userPreferences!: Preferences - observers: PreferencesObserver[] = [] - - /** @override */ - override async onAppLaunch() { - void super.onAppLaunch() - void this.loadPreferences() - } - - override deinit() { - this.observers = [] - } - - /** - * Registers an observer for preferences loaded event - * @returns function that unregisters this observer - */ - public addPreferencesLoadedObserver(callback: PreferencesObserver) { - this.observers.push(callback) - return () => { - removeFromArray(this.observers, callback) - } - } - - notifyObserversOfPreferencesLoaded() { - for (const observer of this.observers) { - void observer() - } - } - - get mobileApplication() { - return this.application as MobileApplication - } - - private async loadPreferences() { - const preferences = await this.application.getValue(PREFS_KEY) - this.userPreferences = (preferences as Preferences) ?? {} - this.notifyObserversOfPreferencesLoaded() - } - - private async saveSingleton() { - return this.application.setValue(PREFS_KEY, this.userPreferences) - } - - private async savePreference(key: PrefKey, value: any) { - return this.application.setPreference(key, value) - } - - getValue(key: PrefKey, defaultValue?: any) { - if (!this.userPreferences) { - return defaultValue - } - const value = this.application.getPreference(key) - return !isNullOrUndefined(value) ? value : defaultValue - } - - async setUserPrefValue(key: PrefKey, value: any) { - this.userPreferences[key] = value - await this.saveSingleton() - await this.savePreference(key, value) - } -} diff --git a/packages/mobile/src/Lib/ReactNativeCrypto.ts b/packages/mobile/src/Lib/ReactNativeCrypto.ts deleted file mode 100644 index 8cae981a4..000000000 --- a/packages/mobile/src/Lib/ReactNativeCrypto.ts +++ /dev/null @@ -1,202 +0,0 @@ -import { - Base64String, - HexString, - PkcKeyPair, - PureCryptoInterface, - SodiumConstant, - StreamDecryptorResult, - timingSafeEqual, - Utf8String, -} from '@standardnotes/sncrypto-common' -import { NativeModules } from 'react-native' -import * as Sodium from 'react-native-sodium-jsi' - -const { Aes } = NativeModules - -export class SNReactNativeCrypto implements PureCryptoInterface { - // eslint-disable-next-line @typescript-eslint/no-empty-function - deinit(): void {} - public timingSafeEqual(a: string, b: string) { - return timingSafeEqual(a, b) - } - - async initialize(): Promise { - return - } - - pbkdf2(password: Utf8String, salt: Utf8String, iterations: number, length: number): Promise { - return Aes.pbkdf2(password, salt, iterations, length) - } - - public generateRandomKey(bits: number): string { - const bytes = bits / 8 - const result = Sodium.randombytes_buf(bytes) - return result - } - - aes256CbcEncrypt(plaintext: Utf8String, iv: HexString, key: HexString): Promise { - return Aes.encrypt(plaintext, key, iv) - } - - async aes256CbcDecrypt(ciphertext: Base64String, iv: HexString, key: HexString): Promise { - try { - return Aes.decrypt(ciphertext, key, iv) - } catch (e) { - return null - } - } - - async hmac256(message: Utf8String, key: HexString): Promise { - try { - return Aes.hmac256(message, key) - } catch (e) { - return null - } - } - - public async sha256(text: string): Promise { - return Aes.sha256(text) - } - - public unsafeSha1(text: string): Promise { - return Aes.sha1(text) - } - - public argon2(password: Utf8String, salt: HexString, iterations: number, bytes: number, length: number): HexString { - return Sodium.crypto_pwhash(length, password, salt, iterations, bytes, Sodium.constants.crypto_pwhash_ALG_DEFAULT) - } - - xchacha20Encrypt(plaintext: Utf8String, nonce: HexString, key: HexString, assocData: Utf8String): Base64String { - return Sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(plaintext, nonce, key, assocData) - } - - public xchacha20Decrypt( - ciphertext: Base64String, - nonce: HexString, - key: HexString, - assocData: Utf8String, - ): string | null { - try { - const result = Sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(ciphertext, nonce, key, assocData) - return result - } catch (e) { - return null - } - } - - public xchacha20StreamInitEncryptor(key: HexString): Sodium.MobileStreamEncryptor { - const encryptor = Sodium.crypto_secretstream_xchacha20poly1305_init_push(key) - return encryptor - } - - public xchacha20StreamEncryptorPush( - encryptor: Sodium.MobileStreamEncryptor, - plainBuffer: Uint8Array, - assocData: Utf8String, - tag: SodiumConstant = SodiumConstant.CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH, - ): Uint8Array { - const encryptedBuffer = Sodium.crypto_secretstream_xchacha20poly1305_push( - encryptor, - plainBuffer.buffer, - assocData, - tag, - ) - return new Uint8Array(encryptedBuffer) - } - - public xchacha20StreamInitDecryptor(header: Base64String, key: HexString): Sodium.MobileStreamDecryptor { - const decryptor = Sodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key) - return decryptor - } - - public xchacha20StreamDecryptorPush( - decryptor: Sodium.MobileStreamDecryptor, - encryptedBuffer: Uint8Array, - assocData: Utf8String, - ): StreamDecryptorResult | false { - if (encryptedBuffer.length < SodiumConstant.CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES) { - throw new Error('Invalid ciphertext size') - } - - const result = Sodium.crypto_secretstream_xchacha20poly1305_pull(decryptor, encryptedBuffer.buffer, assocData) - - if (!result) { - return false - } - - return { - message: new Uint8Array(result.message), - tag: result.tag, - } - } - - public sodiumCryptoBoxEasyEncrypt( - _message: Utf8String, - _nonce: HexString, - _senderSecretKey: HexString, - _recipientPublicKey: HexString, - ): Base64String { - throw new Error('Not implemented') - } - - public sodiumCryptoBoxEasyDecrypt( - _ciphertext: Base64String, - _nonce: HexString, - _senderPublicKey: HexString, - _recipientSecretKey: HexString, - ): Utf8String { - throw new Error('Not implemented') - } - - public sodiumCryptoBoxGenerateKeypair(): PkcKeyPair { - throw new Error('Not implemented') - } - - public generateUUID() { - const randomBuf = Sodium.randombytes_buf(16) - const tempBuf = new Uint8Array(randomBuf.length / 2) - - for (let i = 0; i < randomBuf.length; i += 2) { - tempBuf[i / 2] = parseInt(randomBuf.substring(i, i + 2), 16) - } - - const buf = new Uint32Array(tempBuf.buffer) - let idx = -1 - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { - idx++ - // eslint-disable-next-line no-bitwise - const r = (buf[idx >> 3] >> ((idx % 8) * 4)) & 15 - // eslint-disable-next-line no-bitwise - const v = c === 'x' ? r : (r & 0x3) | 0x8 - return v.toString(16) - }) - } - - public base64Encode(text: Utf8String): string { - return Sodium.to_base64(text) - } - - public base64Decode(base64String: Base64String): string { - return Sodium.from_base64(base64String) - } - - public base64URLEncode(text: string): string { - return Sodium.to_base64(text, Sodium.constants.base64_variant_VARIANT_URLSAFE_NO_PADDING) - } - - public hmac1(): Promise { - throw new Error('hmac1 is not implemented on mobile') - } - - public generateOtpSecret(): Promise { - throw new Error('generateOtpSecret is not implemented on mobile') - } - - public hotpToken(): Promise { - throw new Error('hotpToken is not implemented on mobile') - } - - public totpToken(): Promise { - throw new Error('totpToken is not implemented on mobile') - } -} diff --git a/packages/mobile/src/Lib/ReviewService.ts b/packages/mobile/src/Lib/ReviewService.ts deleted file mode 100644 index 30561c728..000000000 --- a/packages/mobile/src/Lib/ReviewService.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ApplicationService, Platform } from '@standardnotes/snjs' -import * as StoreReview from 'react-native-store-review' - -const RUN_COUNTS_BEFORE_REVIEW = [18, 45, 105] - -export class ReviewService extends ApplicationService { - override async onAppLaunch() { - if (this.application?.platform === Platform.Android || !StoreReview.isAvailable) { - return - } - const runCount = await this.getRunCount() - void this.setRunCount(runCount + 1) - if (RUN_COUNTS_BEFORE_REVIEW.includes(runCount)) { - setTimeout(function () { - StoreReview.requestReview() - }, 1000) - } - } - async getRunCount() { - return Number(this.application?.getValue('runCount')) - } - async setRunCount(runCount: number) { - return this.application?.setValue('runCount', runCount) - } -} diff --git a/packages/mobile/src/Lib/SnjsHelperHooks.ts b/packages/mobile/src/Lib/SnjsHelperHooks.ts deleted file mode 100644 index 56ab85184..000000000 --- a/packages/mobile/src/Lib/SnjsHelperHooks.ts +++ /dev/null @@ -1,426 +0,0 @@ -import { ApplicationContext } from '@Root/ApplicationContext' -import { useSafeApplicationContext } from '@Root/Hooks/useSafeApplicationContext' -import { SCREEN_NOTES } from '@Root/Screens/screens' -import { - ApplicationEvent, - ButtonType, - isSameDay, - NoteMutator, - NoteViewController, - SNNote, - StorageEncryptionPolicy, -} from '@standardnotes/snjs' -import React, { useCallback, useEffect } from 'react' -import { LockStateType } from './ApplicationState' - -export const useSignedIn = (signedInCallback?: () => void, signedOutCallback?: () => void) => { - // Context - const application = useSafeApplicationContext() - - const [isLocked] = useIsLocked() - - // State - const [signedIn, setSignedIn] = React.useState(false) - - React.useEffect(() => { - let mounted = true - const getSignedIn = async () => { - if (mounted && !isLocked) { - setSignedIn(!application.noAccount()) - } - } - void getSignedIn() - const removeSignedInObserver = application.addEventObserver(async (event) => { - if (event === ApplicationEvent.Launched) { - void getSignedIn() - } - if (event === ApplicationEvent.SignedIn) { - setSignedIn(true) - signedInCallback && signedInCallback() - } else if (event === ApplicationEvent.SignedOut) { - setSignedIn(false) - signedOutCallback && signedOutCallback() - } - }) - - return () => { - mounted = false - removeSignedInObserver && removeSignedInObserver() - } - }, [application, signedInCallback, signedOutCallback, isLocked]) - - return [signedIn] -} - -export const useOutOfSync = () => { - // Context - const application = useSafeApplicationContext() - - // State - const [outOfSync, setOutOfSync] = React.useState(false) - - React.useEffect(() => { - let isMounted = true - const getOutOfSync = async () => { - const outOfSyncInitial = await application.sync.isOutOfSync() - if (isMounted) { - setOutOfSync(Boolean(outOfSyncInitial)) - } - } - void getOutOfSync() - return () => { - isMounted = false - } - }, [application]) - - React.useEffect(() => { - const removeSignedInObserver = application.addEventObserver(async (event) => { - if (event === ApplicationEvent.EnteredOutOfSync) { - setOutOfSync(true) - } else if (event === ApplicationEvent.ExitedOutOfSync) { - setOutOfSync(false) - } - }) - - return removeSignedInObserver - }, [application]) - - return [outOfSync] -} - -export const useIsLocked = () => { - // Context - const application = React.useContext(ApplicationContext) - - // State - const [isLocked, setIsLocked] = React.useState(() => { - if (!application || !application.getAppState()) { - return true - } - - return Boolean(application?.getAppState().locked) - }) - - useEffect(() => { - let isMounted = true - const removeSignedInObserver = application?.getAppState().addLockStateChangeObserver((event) => { - if (isMounted) { - if (event === LockStateType.Locked) { - setIsLocked(true) - } - if (event === LockStateType.Unlocked) { - setIsLocked(false) - } - } - }) - - return () => { - isMounted = false - removeSignedInObserver && removeSignedInObserver() - } - }, [application]) - - return [isLocked] -} - -export const useHasEditor = () => { - // Context - const application = React.useContext(ApplicationContext) - - // State - const [hasEditor, setHasEditor] = React.useState(false) - - useEffect(() => { - const removeEditorObserver = application?.editorGroup.addActiveControllerChangeObserver((newEditor) => { - setHasEditor(Boolean(newEditor)) - }) - return removeEditorObserver - }, [application]) - - return [hasEditor] -} - -export const useSyncStatus = () => { - // Context - const application = React.useContext(ApplicationContext) - - // State - const [completedInitialSync, setCompletedInitialSync] = React.useState(false) - const [loading, setLoading] = React.useState(false) - const [decrypting, setDecrypting] = React.useState(false) - const [refreshing, setRefreshing] = React.useState(false) - - const setStatus = useCallback( - (status = '') => { - application?.getStatusManager().setMessage(SCREEN_NOTES, status) - }, - [application], - ) - - const updateLocalDataStatus = useCallback(() => { - const syncStatus = application!.sync.getSyncStatus() - const stats = syncStatus.getStats() - const encryption = - application!.isEncryptionAvailable() && - application!.getStorageEncryptionPolicy() === StorageEncryptionPolicy.Default - - if (stats.localDataCurrent === 0 || stats.localDataTotal === 0 || stats.localDataDone) { - setStatus() - return - } - const notesString = `${stats.localDataCurrent}/${stats.localDataTotal} items…` - const loadingStatus = encryption ? `Decrypting ${notesString}` : `Loading ${notesString}` - setStatus(loadingStatus) - }, [application, setStatus]) - - useEffect(() => { - let mounted = true - const isEncryptionAvailable = - application!.isEncryptionAvailable() && - application!.getStorageEncryptionPolicy() === StorageEncryptionPolicy.Default - if (mounted) { - setDecrypting(!completedInitialSync && isEncryptionAvailable) - updateLocalDataStatus() - setLoading(!completedInitialSync && !isEncryptionAvailable) - } - return () => { - mounted = false - } - }, [application, completedInitialSync, updateLocalDataStatus]) - - const updateSyncStatus = useCallback(() => { - const syncStatus = application!.sync.getSyncStatus() - const stats = syncStatus.getStats() - if (syncStatus.hasError()) { - setRefreshing(false) - setStatus('Unable to Sync') - } else if (stats.downloadCount > 20) { - const text = `Downloading ${stats.downloadCount} items. Keep app open.` - setStatus(text) - } else if (stats.uploadTotalCount > 20) { - setStatus(`Syncing ${stats.uploadCompletionCount}/${stats.uploadTotalCount} items...`) - } else if (syncStatus.syncInProgress && !completedInitialSync) { - setStatus('Syncing…') - } else { - setStatus() - } - }, [application, completedInitialSync, setStatus]) - - useEffect(() => { - const unsubscribeAppEvents = application?.addEventObserver(async (eventName) => { - if (eventName === ApplicationEvent.LocalDataIncrementalLoad) { - updateLocalDataStatus() - } else if (eventName === ApplicationEvent.SyncStatusChanged || eventName === ApplicationEvent.FailedSync) { - updateSyncStatus() - } else if (eventName === ApplicationEvent.LocalDataLoaded) { - setDecrypting(false) - setLoading(false) - updateLocalDataStatus() - } else if (eventName === ApplicationEvent.CompletedFullSync) { - if (completedInitialSync) { - setRefreshing(false) - } else { - setCompletedInitialSync(true) - } - setLoading(false) - updateSyncStatus() - } else if (eventName === ApplicationEvent.LocalDatabaseReadError) { - void application!.alertService!.alert('Unable to load local storage. Please restart the app and try again.') - } else if (eventName === ApplicationEvent.LocalDatabaseWriteError) { - void application!.alertService!.alert('Unable to write to local storage. Please restart the app and try again.') - } else if (eventName === ApplicationEvent.SignedIn) { - setLoading(true) - } - }) - - return unsubscribeAppEvents - }, [application, completedInitialSync, setStatus, updateLocalDataStatus, updateSyncStatus]) - - const startRefreshing = () => { - setRefreshing(true) - } - - return [loading, decrypting, refreshing, startRefreshing] as [boolean, boolean, boolean, () => void] -} - -export const useDeleteNoteWithPrivileges = ( - note: SNNote, - onDeleteCallback: () => void, - onTrashCallback: () => void, - editor?: NoteViewController, -) => { - // Context - const application = React.useContext(ApplicationContext) - - const trashNote = useCallback(async () => { - const title = 'Move to Trash' - const message = 'Are you sure you want to move this note to the trash?' - - const confirmed = await application?.alertService?.confirm(message, title, 'Confirm', ButtonType.Danger) - if (confirmed) { - onTrashCallback() - } - }, [application?.alertService, onTrashCallback]) - - const deleteNotePermanently = useCallback(async () => { - const title = `Delete ${note!.title}` - const message = 'Are you sure you want to permanently delete this note?' - if (editor?.isTemplateNote) { - void application?.alertService!.alert( - 'This note is a placeholder and cannot be deleted. To remove from your list, simply navigate to a different note.', - ) - return - } - const confirmed = await application?.alertService?.confirm(message, title, 'Delete', ButtonType.Danger, 'Cancel') - if (confirmed) { - onDeleteCallback() - } - }, [application?.alertService, editor?.isTemplateNote, note, onDeleteCallback]) - - const deleteNote = useCallback( - async (permanently: boolean) => { - if (note?.locked) { - void application?.alertService.alert( - "This note has editing disabled. If you'd like to delete it, enable editing on it, and try again.", - ) - return - } - if (permanently) { - void deleteNotePermanently() - } else { - void trashNote() - } - }, - [application, deleteNotePermanently, note?.locked, trashNote], - ) - - return [deleteNote] -} - -export const useProtectionSessionExpiry = () => { - // Context - const application = useSafeApplicationContext() - - const getProtectionsDisabledUntil = React.useCallback(() => { - const protectionExpiry = application?.getProtectionSessionExpiryDate() - const now = new Date() - - if (protectionExpiry && protectionExpiry > now) { - if (typeof Intl !== 'undefined' && Intl.DateTimeFormat) { - let f: Intl.DateTimeFormat - - if (isSameDay(protectionExpiry, now)) { - f = new Intl.DateTimeFormat(undefined, { - hour: 'numeric', - minute: 'numeric', - }) - } else { - f = new Intl.DateTimeFormat(undefined, { - weekday: 'long', - day: 'numeric', - month: 'short', - hour: 'numeric', - minute: 'numeric', - }) - } - - return f.format(protectionExpiry) - } else { - if (isSameDay(protectionExpiry, now)) { - return protectionExpiry.toLocaleTimeString() - } else { - return `${protectionExpiry.toDateString()} ${protectionExpiry.toLocaleTimeString()}` - } - } - } - return null - }, [application]) - - // State - const [protectionsDisabledUntil, setProtectionsDisabledUntil] = React.useState(getProtectionsDisabledUntil()) - - useEffect(() => { - const removeProtectionLengthSubscriber = application?.addEventObserver(async (event) => { - if ([ApplicationEvent.UnprotectedSessionBegan, ApplicationEvent.UnprotectedSessionExpired].includes(event)) { - setProtectionsDisabledUntil(getProtectionsDisabledUntil()) - } - }) - return () => { - removeProtectionLengthSubscriber && removeProtectionLengthSubscriber() - } - }, [application, getProtectionsDisabledUntil]) - - return [protectionsDisabledUntil] -} - -export const useChangeNoteChecks = (note: SNNote | undefined, editor: NoteViewController | undefined = undefined) => { - // Context - const application = useSafeApplicationContext() - - const canChangeNote = useCallback(async () => { - if (!note) { - return false - } - - if (editor && editor.isTemplateNote) { - await editor.insertTemplatedNote() - } - - if (!application.items.findItem(note.uuid)) { - void application.alertService!.alert( - "The note you are attempting to save can not be found or has been deleted. Changes you make will not be synced. Please copy this note's text and start a new note.", - ) - return false - } - - return true - }, [application, editor, note]) - - return [canChangeNote] -} - -export const useChangeNote = (note: SNNote | undefined, editor: NoteViewController | undefined = undefined) => { - const application = React.useContext(ApplicationContext) - - const [canChangeNote] = useChangeNoteChecks(note, editor) - - const changeNote = useCallback( - async (mutate: (mutator: NoteMutator) => void, updateTimestamps: boolean) => { - if (await canChangeNote()) { - await application?.mutator.changeAndSaveItem( - note!, - (mutator) => { - const noteMutator = mutator as NoteMutator - mutate(noteMutator) - }, - updateTimestamps, - ) - } - }, - [application, note, canChangeNote], - ) - - return [changeNote] -} - -export const useProtectOrUnprotectNote = ( - note: SNNote | undefined, - editor: NoteViewController | undefined = undefined, -) => { - // Context - const application = React.useContext(ApplicationContext) - - const [canChangeNote] = useChangeNoteChecks(note, editor) - - const protectOrUnprotectNote = useCallback(async () => { - if (await canChangeNote()) { - if (note!.protected) { - await application?.mutator.unprotectNote(note!) - } else { - await application?.mutator.protectNote(note!) - } - } - }, [application, note, canChangeNote]) - - return [protectOrUnprotectNote] -} diff --git a/packages/mobile/src/Lib/StatusManager.ts b/packages/mobile/src/Lib/StatusManager.ts deleted file mode 100644 index 087c4280b..000000000 --- a/packages/mobile/src/Lib/StatusManager.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { SCREEN_COMPOSE, SCREEN_NOTES } from '@Root/Screens/screens' -import { ApplicationService, removeFromArray } from '@standardnotes/snjs' - -export type ScreenStatus = { - status: string - color?: string -} -type StatusState = { - [SCREEN_NOTES]: ScreenStatus - [SCREEN_COMPOSE]: ScreenStatus -} -type HeaderStatusObserverCallback = (status: StatusState) => void - -export class StatusManager extends ApplicationService { - private messages: StatusState = { - [SCREEN_NOTES]: { - status: '', - }, - [SCREEN_COMPOSE]: { - status: '', - }, - } - private observers: HeaderStatusObserverCallback[] = [] - - override deinit() { - this.observers = [] - this.messages = { - [SCREEN_NOTES]: { - status: '', - }, - [SCREEN_COMPOSE]: { - status: '', - }, - } - } - - /** - * Registers an observer for UI header status change - * @returns function that unregisters this observer - */ - public addHeaderStatusObserver(callback: HeaderStatusObserverCallback) { - this.observers.push(callback) - return () => { - removeFromArray(this.observers, callback) - } - } - - setMessage(screen: typeof SCREEN_COMPOSE | typeof SCREEN_NOTES, message: string, color?: string) { - this.messages[screen] = { - status: message, - color, - } - this.notifyObservers() - } - - hasMessage(screen: typeof SCREEN_COMPOSE | typeof SCREEN_NOTES) { - const message = this.getMessage(screen) - if (!message || message.status.length === 0) { - return false - } - return true - } - - getMessage(screen: typeof SCREEN_COMPOSE | typeof SCREEN_NOTES) { - return this.messages[screen] - } - - private notifyObservers() { - for (const observer of this.observers) { - observer(this.messages) - } - } -} diff --git a/packages/mobile/src/Lib/Types.ts b/packages/mobile/src/Lib/Types.ts deleted file mode 100644 index 34246dcf2..000000000 --- a/packages/mobile/src/Lib/Types.ts +++ /dev/null @@ -1,5 +0,0 @@ -export enum ToastType { - Success = 'success', - Info = 'info', - Error = 'error', -} diff --git a/packages/mobile/src/Lib/Utils.ts b/packages/mobile/src/Lib/Utils.ts index b44b32e6e..193913d97 100644 --- a/packages/mobile/src/Lib/Utils.ts +++ b/packages/mobile/src/Lib/Utils.ts @@ -1,8 +1,6 @@ -import { TEnvironment } from '@Root/NativeApp' import VersionInfo from 'react-native-version-info' export const IsDev = VersionInfo.bundleIdentifier?.includes('dev') -export const IsMobileWeb = IsDev export function isNullOrUndefined(value: unknown) { return value === null || value === undefined @@ -40,7 +38,3 @@ export function isSameDay(dateA: Date, dateB: Date) { dateA.getDate() === dateB.getDate() ) } - -export function isUnfinishedFeaturesEnabled(env: TEnvironment): boolean { - return env === 'dev' || __DEV__ -} diff --git a/packages/mobile/src/Lib/constants.ts b/packages/mobile/src/Lib/constants.ts deleted file mode 100644 index 559e82ccd..000000000 --- a/packages/mobile/src/Lib/constants.ts +++ /dev/null @@ -1,5 +0,0 @@ -export enum ErrorMessage { - GeneralText = 'An error occurred. Please try again later.', -} - -export const AlwaysOpenWebAppOnLaunchKey = 'AlwaysOpenWebAppOnLaunch' diff --git a/packages/mobile/src/Lib/moment.ts b/packages/mobile/src/Lib/moment.ts deleted file mode 100644 index b35d65b8e..000000000 --- a/packages/mobile/src/Lib/moment.ts +++ /dev/null @@ -1,12 +0,0 @@ -// moment.js -import moment from 'moment' -import { NativeModules, Platform } from 'react-native' - -// moment.js -const locale = - Platform.OS === 'android' - ? NativeModules.I18nManager.localeIdentifier - : NativeModules.SettingsManager.settings.AppleLocale -moment.locale(locale) - -export default moment diff --git a/packages/mobile/src/Lib/package.json b/packages/mobile/src/Lib/package.json deleted file mode 100644 index c107ca8f7..000000000 --- a/packages/mobile/src/Lib/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": "@Lib" -} diff --git a/packages/mobile/src/MobileWebApp.tsx b/packages/mobile/src/MobileWebApp.tsx index 862f55b15..9ae19532f 100644 --- a/packages/mobile/src/MobileWebApp.tsx +++ b/packages/mobile/src/MobileWebApp.tsx @@ -1,14 +1,8 @@ -import { navigationRef } from '@Lib/NavigationService' -import { NavigationContainer } from '@react-navigation/native' import React from 'react' -import { MobileWebMainStackComponent } from './ModalStack' +import { MobileWebAppContainer } from './MobileWebAppContainer' const AppComponent: React.FC = () => { - return ( - - - - ) + return } export const MobileWebApp = () => { diff --git a/packages/mobile/src/MobileWebAppContainer.tsx b/packages/mobile/src/MobileWebAppContainer.tsx index 7c1b14a84..d7c5a9e25 100644 --- a/packages/mobile/src/MobileWebAppContainer.tsx +++ b/packages/mobile/src/MobileWebAppContainer.tsx @@ -1,5 +1,3 @@ -import { MobileDevice, MobileDeviceEvent } from '@Lib/Interface' -import { IsDev } from '@Lib/Utils' import { ReactNativeToWebEvent } from '@standardnotes/snjs' import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { Keyboard, Platform } from 'react-native' @@ -8,6 +6,8 @@ import { WebView, WebViewMessageEvent } from 'react-native-webview' import pjson from '../package.json' import { AndroidBackHandlerService } from './AndroidBackHandlerService' import { AppStateObserverService } from './AppStateObserverService' +import { MobileDevice, MobileDeviceEvent } from './Lib/Interface' +import { IsDev } from './Lib/Utils' const LoggingEnabled = IsDev diff --git a/packages/mobile/src/ModalStack.tsx b/packages/mobile/src/ModalStack.tsx deleted file mode 100644 index fb4875ab9..000000000 --- a/packages/mobile/src/ModalStack.tsx +++ /dev/null @@ -1,336 +0,0 @@ -import { RouteProp } from '@react-navigation/native' -import { createStackNavigator, StackNavigationProp } from '@react-navigation/stack' -import { BlockingModal } from '@Root/Components/BlockingModal' -import { HeaderTitleView } from '@Root/Components/HeaderTitleView' -import { IoniconsHeaderButton } from '@Root/Components/IoniconsHeaderButton' -import { Authenticate } from '@Root/Screens/Authenticate/Authenticate' -import { FileInputModal } from '@Root/Screens/InputModal/FileInputModal' -import { PasscodeInputModal } from '@Root/Screens/InputModal/PasscodeInputModal' -import { TagInputModal } from '@Root/Screens/InputModal/TagInputModal' -import { ManageSessions } from '@Root/Screens/ManageSessions/ManageSessions' -import { - MODAL_BLOCKING_ALERT, - SCREEN_AUTHENTICATE, - SCREEN_INPUT_MODAL_FILE_NAME, - SCREEN_INPUT_MODAL_PASSCODE, - SCREEN_INPUT_MODAL_TAG, - SCREEN_INPUT_MODAL_WORKSPACE_NAME, - SCREEN_MANAGE_SESSIONS, - SCREEN_SETTINGS, - SCREEN_UPLOADED_FILES_LIST, - SCREEN_WEB_APP, -} from '@Root/Screens/screens' -import { Settings } from '@Root/Screens/Settings/Settings' -import { UploadedFilesList } from '@Root/Screens/UploadedFilesList/UploadedFilesList' -import { WorkspaceInputModal } from '@Screens/InputModal/WorkspaceInputModal' -import { ApplicationDescriptor, Challenge, DeinitMode, DeinitSource, FileItem, SNNote } from '@standardnotes/snjs' -import { ICON_CHECKMARK, ICON_CLOSE } from '@Style/Icons' -import { ThemeService } from '@Style/ThemeService' -import React, { memo, useContext } from 'react' -import { Platform } from 'react-native' -import { HeaderButtons, Item } from 'react-navigation-header-buttons' -import { ThemeContext } from 'styled-components' -import { ApplicationContext } from './ApplicationContext' -import { AppStackComponent } from './AppStack' -import { HistoryStack } from './HistoryStack' -import { MobileWebAppContainer } from './MobileWebAppContainer' -import { HeaderTitleParams, TEnvironment } from './NativeApp' - -export type ModalStackNavigatorParamList = { - AppStack: undefined - HistoryStack: undefined - [SCREEN_SETTINGS]: undefined - [SCREEN_MANAGE_SESSIONS]: undefined - [SCREEN_INPUT_MODAL_TAG]: HeaderTitleParams & { - tagUuid?: string - noteUuid?: string - } - [SCREEN_INPUT_MODAL_FILE_NAME]: HeaderTitleParams & { - file: FileItem - renameFile: (file: FileItem, fileName: string) => Promise - } - [SCREEN_UPLOADED_FILES_LIST]: HeaderTitleParams & { - note: SNNote - } - [SCREEN_INPUT_MODAL_WORKSPACE_NAME]: HeaderTitleParams & { - descriptor: ApplicationDescriptor - renameWorkspace: (descriptor: ApplicationDescriptor, workspaceName: string) => Promise - } - [SCREEN_INPUT_MODAL_PASSCODE]: undefined - [SCREEN_AUTHENTICATE]: { - challenge: Challenge - title?: string - } - [MODAL_BLOCKING_ALERT]: { - title?: string - text: string - } - [SCREEN_WEB_APP]: undefined -} - -export type ModalStackNavigationProp = { - navigation: StackNavigationProp - route: RouteProp -} - -const MainStack = createStackNavigator() - -export const MobileWebMainStackComponent = () => { - const MemoizedAppStackComponent = memo((props: ModalStackNavigationProp<'AppStack'>) => ( - - )) - - return ( - - - - ) -} - -export const NativeMainStackComponent = ({ env }: { env: TEnvironment }) => { - const application = useContext(ApplicationContext) - const theme = useContext(ThemeContext) - - const MemoizedAppStackComponent = memo((props: ModalStackNavigationProp<'AppStack'>) => ( - - )) - - return ( - - - - ({ - title: 'Settings', - headerTitle: ({ children }) => { - return - }, - headerLeft: ({ disabled, onPress }) => ( - - - - ), - headerRight: () => - (env === 'dev' || __DEV__) && ( - - { - await application?.deviceInterface?.removeAllRawStorageValues() - await application?.deviceInterface?.removeAllRawDatabasePayloads(application?.identifier) - application?.deinit(DeinitMode.Soft, DeinitSource.SignOut) - }} - /> - - ), - })} - component={Settings} - /> - ({ - title: 'Active Sessions', - headerTitle: ({ children }) => { - return - }, - headerLeft: ({ disabled, onPress }) => ( - - - - ), - })} - component={ManageSessions} - /> - { - return - }, - headerLeft: ({ disabled, onPress }) => ( - - - - ), - }} - component={PasscodeInputModal} - /> - ({ - title: 'Tag', - gestureEnabled: false, - headerTitle: ({ children }) => { - return - }, - headerLeft: ({ disabled, onPress }) => ( - - - - ), - })} - component={TagInputModal} - /> - ({ - title: 'File', - gestureEnabled: false, - headerTitle: ({ children }) => { - return - }, - headerLeft: ({ disabled, onPress }) => ( - - - - ), - })} - component={FileInputModal} - /> - - ({ - title: 'Authenticate', - headerLeft: () => undefined, - headerTitle: ({ children }) => , - })} - component={Authenticate} - /> - ({ - title: 'Files', - headerLeft: ({ disabled, onPress }) => ( - - - - ), - headerTitle: ({ children }) => { - return - }, - })} - component={UploadedFilesList} - /> - ({ - headerShown: false, - cardStyle: { backgroundColor: 'rgba(0, 0, 0, 0.15)' }, - cardOverlayEnabled: true, - cardStyleInterpolator: ({ current: { progress } }) => ({ - cardStyle: { - opacity: progress.interpolate({ - inputRange: [0, 0.5, 0.9, 1], - outputRange: [0, 0.25, 0.7, 1], - }), - }, - overlayStyle: { - opacity: progress.interpolate({ - inputRange: [0, 1], - outputRange: [0, 0.5], - extrapolate: 'clamp', - }), - }, - }), - })} - component={BlockingModal} - /> - ({ - title: 'Workspace', - gestureEnabled: false, - headerTitle: ({ children }) => { - return - }, - headerLeft: ({ disabled, onPress }) => ( - - - - ), - })} - component={WorkspaceInputModal} - /> - ({ title: 'App' })} component={MobileWebAppContainer} /> - - ) -} diff --git a/packages/mobile/src/NativeApp.tsx b/packages/mobile/src/NativeApp.tsx deleted file mode 100644 index 2950f810d..000000000 --- a/packages/mobile/src/NativeApp.tsx +++ /dev/null @@ -1,160 +0,0 @@ -import { ToastWrapper } from '@Components/ToastWrapper' -import { ActionSheetProvider } from '@expo/react-native-action-sheet' -import { MobileApplication } from '@Lib/Application' -import { ApplicationGroup } from '@Lib/ApplicationGroup' -import { navigationRef } from '@Lib/NavigationService' -import { DefaultTheme, NavigationContainer } from '@react-navigation/native' -import { ApplicationGroupContext } from '@Root/ApplicationGroupContext' -import { MobileThemeVariables } from '@Root/Style/Themes/styled-components' -import { ApplicationGroupEvent, DeinitMode, DeinitSource } from '@standardnotes/snjs' -import { ThemeService, ThemeServiceContext } from '@Style/ThemeService' -import React, { useCallback, useEffect, useRef, useState } from 'react' -import { ThemeProvider } from 'styled-components/native' -import { ApplicationContext } from './ApplicationContext' -import { NativeMainStackComponent } from './ModalStack' - -export type HeaderTitleParams = { - title?: string - subTitle?: string - subTitleColor?: string -} - -export type TEnvironment = 'prod' | 'dev' - -const AppComponent: React.FC<{ - application: MobileApplication - env: TEnvironment -}> = ({ application, env }) => { - const themeService = useRef() - const appReady = useRef(false) - const navigationReady = useRef(false) - const [activeTheme, setActiveTheme] = useState() - - const setThemeServiceRef = useCallback((node: ThemeService | undefined) => { - if (node) { - node.addThemeChangeObserver(() => { - setActiveTheme(node.variables) - }) - } - - /** - * We check if both application and navigation are ready and launch application afterwads - */ - themeService.current = node - }, []) - - /** - * We check if both application and navigation are ready and launch application afterwads - */ - const launchApp = useCallback( - (setAppReady: boolean, setNavigationReady: boolean) => { - if (setAppReady) { - appReady.current = true - } - if (setNavigationReady) { - navigationReady.current = true - } - if (navigationReady.current && appReady.current) { - void application.launch() - } - }, - [application], - ) - - useEffect(() => { - let themeServiceInstance: ThemeService - const loadApplication = async () => { - themeServiceInstance = new ThemeService(application) - setThemeServiceRef(themeServiceInstance) - - await application.prepareForLaunch({ - receiveChallenge: async (challenge) => { - application.promptForChallenge(challenge) - }, - }) - - await themeServiceInstance.init() - launchApp(true, false) - } - - void loadApplication() - - return () => { - themeServiceInstance?.deinit() - setThemeServiceRef(undefined) - - if (!application.hasStartedDeinit()) { - application.deinit(DeinitMode.Soft, DeinitSource.Lock) - } - } - }, [application, application.Uuid, env, launchApp, setThemeServiceRef]) - - if (!themeService.current || !activeTheme) { - return null - } - - return ( - launchApp(false, true)} - theme={{ - ...DefaultTheme, - colors: { - ...DefaultTheme.colors, - background: activeTheme.stylekitBackgroundColor, - border: activeTheme.stylekitBorderColor, - }, - }} - ref={navigationRef} - > - {themeService.current && ( - <> - - - - - - - - - - )} - - ) -} - -export const NativeApp = (props: { env: TEnvironment }) => { - const [application, setApplication] = useState() - - const createNewAppGroup = useCallback(() => { - const group = new ApplicationGroup() - void group.initialize() - return group - }, []) - - const [appGroup, setAppGroup] = useState(() => createNewAppGroup()) - - useEffect(() => { - const removeAppChangeObserver = appGroup.addEventObserver((event) => { - if (event === ApplicationGroupEvent.PrimaryApplicationSet) { - const mobileApplication = appGroup.primaryApplication as MobileApplication - setApplication(mobileApplication) - } else if (event === ApplicationGroupEvent.DeviceWillRestart) { - setApplication(undefined) - setAppGroup(createNewAppGroup()) - } - }) - return removeAppChangeObserver - }, [appGroup, appGroup.primaryApplication, createNewAppGroup]) - - if (!application) { - return null - } - - return ( - - - - - - ) -} diff --git a/packages/mobile/src/Screens/Authenticate/Authenticate.styled.ts b/packages/mobile/src/Screens/Authenticate/Authenticate.styled.ts deleted file mode 100644 index 46fd6c920..000000000 --- a/packages/mobile/src/Screens/Authenticate/Authenticate.styled.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { SectionedTableCell } from '@Root/Components/SectionedTableCell' -import { TableSection } from '@Root/Components/TableSection' -import styled, { css } from 'styled-components/native' - -export const StyledKeyboardAvoidingView = styled.KeyboardAvoidingView` - flex: 1; - background-color: ${({ theme }) => theme.stylekitBackgroundColor}; -` - -export const BaseView = styled.View`` - -export const StyledSectionedTableCell = styled(SectionedTableCell)` - padding-top: 4px; -` - -export const Title = styled.Text` - color: ${({ theme }) => theme.stylekitForegroundColor}; - font-size: 14px; - font-weight: bold; -` - -export const Subtitle = styled.Text` - color: ${({ theme }) => theme.stylekitNeutralColor}; - font-size: 14px; - margin-top: 4px; -` - -export const Input = styled.TextInput.attrs(({ theme }) => ({ - placeholderTextColor: theme.stylekitNeutralColor, -}))` - font-size: ${({ theme }) => theme.mainTextFontSize}px; - padding: 0px; - color: ${({ theme }) => theme.stylekitForegroundColor}; - height: 100%; -` - -export const SectionContainer = styled.View`` - -export const SourceContainer = styled.View`` - -export const SessionLengthContainer = styled.View`` - -export const StyledTableSection = styled(TableSection)<{ last?: boolean }>` - ${({ last }) => - last && - css` - margin-bottom: 0px; - `}; -` diff --git a/packages/mobile/src/Screens/Authenticate/Authenticate.tsx b/packages/mobile/src/Screens/Authenticate/Authenticate.tsx deleted file mode 100644 index 03fed2d4b..000000000 --- a/packages/mobile/src/Screens/Authenticate/Authenticate.tsx +++ /dev/null @@ -1,678 +0,0 @@ -import { AppStateType, PasscodeKeyboardType } from '@Lib/ApplicationState' -import { MobileDevice } from '@Lib/Interface' -import { HeaderHeightContext } from '@react-navigation/elements' -import { useFocusEffect } from '@react-navigation/native' -import { ApplicationContext } from '@Root/ApplicationContext' -import { ButtonCell } from '@Root/Components/ButtonCell' -import { IoniconsHeaderButton } from '@Root/Components/IoniconsHeaderButton' -import { SectionedAccessoryTableCell } from '@Root/Components/SectionedAccessoryTableCell' -import { SectionedTableCell } from '@Root/Components/SectionedTableCell' -import { SectionHeader } from '@Root/Components/SectionHeader' -import { ModalStackNavigationProp } from '@Root/ModalStack' -import { SCREEN_AUTHENTICATE } from '@Root/Screens/screens' -import { ChallengeReason, ChallengeValidation, ChallengeValue, ProtectionSessionDurations } from '@standardnotes/snjs' -import { ICON_CLOSE } from '@Style/Icons' -import { ThemeService, ThemeServiceContext } from '@Style/ThemeService' -import React, { useCallback, useContext, useEffect, useMemo, useReducer, useRef, useState } from 'react' -import { Alert, BackHandler, Keyboard, Platform, ScrollView, TextInput } from 'react-native' -import FingerprintScanner from 'react-native-fingerprint-scanner' -import { hide } from 'react-native-privacy-snapshot' -import { HeaderButtons, Item } from 'react-navigation-header-buttons' -import styled, { ThemeContext } from 'styled-components' -import { - BaseView, - Input, - SectionContainer, - SessionLengthContainer, - SourceContainer, - StyledKeyboardAvoidingView, - StyledSectionedTableCell, - StyledTableSection, - Subtitle, - Title, -} from './Authenticate.styled' -import { - authenticationReducer, - AuthenticationValueStateType, - findIndexInObject, - getChallengePromptTitle, - getLabelForStateAndType, - isInActiveState, -} from './helpers' - -type Props = ModalStackNavigationProp - -function isValidChallengeValue(challengeValue: ChallengeValue): boolean { - switch (challengeValue.prompt.validation) { - case ChallengeValidation.ProtectionSessionDuration: - return typeof challengeValue.value === 'number' - default: - return !!challengeValue.value - } -} - -const ItemStyled = styled(Item)` - width: 100px; -` - -export const Authenticate = ({ - route: { - params: { challenge }, - }, - navigation, -}: Props) => { - // Context - const application = useContext(ApplicationContext) - const themeService = useContext(ThemeServiceContext) - const theme = useContext(ThemeContext) - - // State - const [supportsBiometrics, setSupportsBiometrics] = useState(undefined) - const [passcodeKeyboardType, setPasscodeKeyboardType] = useState( - PasscodeKeyboardType.Default, - ) - const [singleValidation] = useState(() => !(challenge.prompts.filter((prompt) => prompt.validates).length > 0)) - const [showSwitchKeyboard, setShowSwitchKeyboard] = useState(false) - - const [{ challengeValues, challengeValueStates }, dispatch] = useReducer( - authenticationReducer, - { - challengeValues: challenge.prompts.reduce((map, current) => { - map[current.id] = { - prompt: current, - value: current.initialValue ?? null, - } as ChallengeValue - return map - }, {} as Record), - challengeValueStates: challenge.prompts.reduce((map, current, index) => { - if (index === 0) { - map[current.id] = AuthenticationValueStateType.WaitingInput - } else { - map[current.id] = AuthenticationValueStateType.WaitingTurn - } - return map - }, {} as Record), - }, - undefined, - ) - const [pending, setPending] = useState(false) - - // Refs - const isAuthenticating = useRef(false) - const firstInputRef = useRef(null) - const secondInputRef = useRef(null) - const thirdInputRef = useRef(null) - const fourthInputRef = useRef(null) - - React.useLayoutEffect(() => { - if (challenge.cancelable) { - navigation.setOptions({ - headerLeft: ({ disabled }) => ( - - { - if (!pending) { - application?.cancelChallenge(challenge) - } - }} - /> - - ), - }) - } - }, [navigation, challenge, application, pending]) - - const validateChallengeValue = useCallback( - async (challengeValue: ChallengeValue) => { - if (singleValidation) { - setPending(true) - return application?.submitValuesForChallenge(challenge, Object.values(challengeValues)) - } else { - const state = challengeValueStates[challengeValue.prompt.id] - - if ( - state === AuthenticationValueStateType.Locked || - state === AuthenticationValueStateType.Success || - !isValidChallengeValue(challengeValue) - ) { - return - } - return application?.submitValuesForChallenge(challenge, [challengeValue]) - } - }, - [challengeValueStates, singleValidation, challengeValues, application, challenge], - ) - - const onValueLocked = useCallback((challengeValue: ChallengeValue) => { - dispatch({ - type: 'setState', - id: challengeValue.prompt.id.toString(), - state: AuthenticationValueStateType.Locked, - }) - - setTimeout(() => { - dispatch({ - type: 'setState', - id: challengeValue.prompt.id.toString(), - state: AuthenticationValueStateType.WaitingTurn, - }) - }, 30 * 1000) - }, []) - - const checkForBiometrics = useCallback( - async () => (application?.deviceInterface as MobileDevice).getDeviceBiometricsAvailability(), - [application], - ) - - const checkPasscodeKeyboardType = useCallback( - async () => application?.getAppState().getPasscodeKeyboardType(), - [application], - ) - - const authenticateBiometrics = useCallback( - async (challengeValue: ChallengeValue) => { - let hasBiometrics = supportsBiometrics - if (supportsBiometrics === undefined) { - hasBiometrics = await checkForBiometrics() - setSupportsBiometrics(hasBiometrics) - } - if (!hasBiometrics) { - FingerprintScanner.release() - dispatch({ - type: 'setState', - id: challengeValue.prompt.id.toString(), - state: AuthenticationValueStateType.Fail, - }) - Alert.alert('Unsuccessful', 'This device either does not have a biometric sensor or it may not configured.') - return - } - - dispatch({ - type: 'setState', - id: challengeValue.prompt.id.toString(), - state: AuthenticationValueStateType.Pending, - }) - - if (application?.protections.getMobileScreenshotPrivacyEnabled()) { - hide() - } - - if (Platform.OS === 'android') { - await application?.getAppState().performActionWithoutStateChangeImpact(async () => { - isAuthenticating.current = true - FingerprintScanner.authenticate({ - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore ts type does not exist for deviceCredentialAllowed - deviceCredentialAllowed: true, - description: 'Biometrics are required to access your notes.', - }) - .then(() => { - FingerprintScanner.release() - const newChallengeValue = { ...challengeValue, value: true } - - onValueChange(newChallengeValue) - return validateChallengeValue(newChallengeValue) - }) - .catch((error) => { - FingerprintScanner.release() - if (error.name === 'DeviceLocked') { - onValueLocked(challengeValue) - Alert.alert('Unsuccessful', 'Authentication failed. Wait 30 seconds to try again.') - } else { - dispatch({ - type: 'setState', - id: challengeValue.prompt.id.toString(), - state: AuthenticationValueStateType.Fail, - }) - Alert.alert('Unsuccessful', 'Authentication failed. Tap to try again.') - } - }) - .finally(() => { - isAuthenticating.current = false - }) - }, true) - } else { - // iOS - await application?.getAppState().performActionWithoutStateChangeImpact(async () => { - isAuthenticating.current = true - FingerprintScanner.authenticate({ - fallbackEnabled: true, - description: 'This is required to access your notes.', - }) - .then(() => { - FingerprintScanner.release() - - const newChallengeValue = { ...challengeValue, value: true } - onValueChange(newChallengeValue) - return validateChallengeValue(newChallengeValue) - }) - .catch((error_1) => { - onValueChange({ ...challengeValue, value: false }) - FingerprintScanner.release() - if (error_1.name !== 'SystemCancel') { - if (error_1.name !== 'UserCancel') { - Alert.alert('Unsuccessful') - } else { - Alert.alert('Unsuccessful', 'Authentication failed. Tap to try again.') - } - } - dispatch({ - type: 'setState', - id: challengeValue.prompt.id.toString(), - state: AuthenticationValueStateType.Fail, - }) - }) - .finally(() => { - isAuthenticating.current = false - }) - }, true) - } - }, - [application, checkForBiometrics, onValueLocked, supportsBiometrics, validateChallengeValue], - ) - - const firstNotSuccessful = useMemo(() => { - for (const id in challengeValueStates) { - if (challengeValueStates[id] !== AuthenticationValueStateType.Success) { - return id - } - } - return - }, [challengeValueStates]) - - const beginAuthenticatingForNextChallengeReason = useCallback( - (completedChallengeValue?: ChallengeValue) => { - let challengeValue - if (completedChallengeValue === undefined) { - challengeValue = challengeValues[firstNotSuccessful!] - } else { - const index = findIndexInObject(challengeValues, completedChallengeValue.prompt.id.toString()) - - const hasNextItem = Object.prototype.hasOwnProperty.call(Object.keys(challengeValues), index + 1) - if (!hasNextItem) { - return - } - const nextItemId = Object.keys(challengeValues)[index + 1] - challengeValue = challengeValues[nextItemId] - } - - /** - * Authentication modal may be displayed on lose focus just before the app - * is closing. In this state however, we don't want to begin auth. We'll - * wait until the app gains focus. - */ - const isLosingFocusOrInBackground = - application?.getAppState().getMostRecentState() === AppStateType.LosingFocus || - application?.getAppState().getMostRecentState() === AppStateType.EnteringBackground - - if (challengeValue.prompt.validation === ChallengeValidation.Biometric && !isLosingFocusOrInBackground) { - /** Begin authentication right away, we're not waiting for any input */ - void authenticateBiometrics(challengeValue) - } else { - const index = findIndexInObject(challengeValues, challengeValue.prompt.id.toString()) - switch (index) { - case 0: - firstInputRef.current?.focus() - break - case 1: - secondInputRef.current?.focus() - break - case 2: - thirdInputRef.current?.focus() - break - case 3: - fourthInputRef.current?.focus() - break - } - } - - dispatch({ - type: 'setState', - id: challengeValue.prompt.id.toString(), - state: AuthenticationValueStateType.WaitingInput, - }) - }, - [application, authenticateBiometrics, challengeValues, firstNotSuccessful], - ) - - useEffect(() => { - const remove = application?.getAppState().addStateChangeObserver((state) => { - if (state === AppStateType.ResumingFromBackground) { - if (!isAuthenticating.current) { - beginAuthenticatingForNextChallengeReason() - } - } else if (state === AppStateType.EnteringBackground) { - FingerprintScanner.release() - dispatch({ - type: 'setState', - id: firstNotSuccessful!, - state: AuthenticationValueStateType.WaitingInput, - }) - } - }) - return remove - }, [application, beginAuthenticatingForNextChallengeReason, challengeValueStates, firstNotSuccessful]) - - const onValidValue = useCallback( - (value: ChallengeValue) => { - setPending(false) - dispatch({ - type: 'setState', - id: value.prompt.id.toString(), - state: AuthenticationValueStateType.Success, - }) - beginAuthenticatingForNextChallengeReason(value) - }, - [beginAuthenticatingForNextChallengeReason], - ) - - const onInvalidValue = (value: ChallengeValue) => { - setPending(false) - dispatch({ - type: 'setState', - id: value.prompt.id.toString(), - state: AuthenticationValueStateType.Fail, - }) - } - - useEffect(() => { - // eslint-disable-next-line @typescript-eslint/no-empty-function - let removeObserver: () => void = () => {} - if (application?.addChallengeObserver) { - removeObserver = application?.addChallengeObserver(challenge, { - onValidValue, - onInvalidValue, - onComplete: () => { - navigation.goBack() - }, - onCancel: () => { - navigation.goBack() - }, - }) - } - return removeObserver - }, [application, challenge, navigation, onValidValue]) - - useEffect(() => { - let mounted = true - const setBiometricsAsync = async () => { - if (challenge.reason === ChallengeReason.ApplicationUnlock) { - const hasBiometrics = await checkForBiometrics() - if (mounted) { - setSupportsBiometrics(hasBiometrics) - } - } - } - void setBiometricsAsync() - const setInitialPasscodeKeyboardType = async () => { - const initialPasscodeKeyboardType = await checkPasscodeKeyboardType() - if (mounted) { - setPasscodeKeyboardType(initialPasscodeKeyboardType) - } - } - void setInitialPasscodeKeyboardType() - return () => { - mounted = false - } - }, [challenge.reason, checkForBiometrics, checkPasscodeKeyboardType]) - - /** - * Authenticate for challenge reasons like biometrics as soon as possible, - * unless a prompt has a prefilled control value, in which case give the - * option to adjust them first. - */ - useEffect(() => { - if ( - challenge.prompts && - challenge.prompts.length > 0 && - challenge.prompts[0].validation !== ChallengeValidation.ProtectionSessionDuration - ) { - beginAuthenticatingForNextChallengeReason() - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []) - - const onBiometricDirectPress = () => { - Keyboard.dismiss() - - const biometricChallengeValue = Object.values(challengeValues).find( - (value) => value.prompt.validation === ChallengeValidation.Biometric, - ) - const state = challengeValueStates[biometricChallengeValue?.prompt.id as number] - if (state === AuthenticationValueStateType.Locked || state === AuthenticationValueStateType.Success) { - return - } - - beginAuthenticatingForNextChallengeReason() - } - - const onValueChange = (newValue: ChallengeValue, dismissKeyboard = false) => { - if (dismissKeyboard) { - Keyboard.dismiss() - } - - dispatch({ - type: 'setValue', - id: newValue.prompt.id.toString(), - value: newValue.value, - }) - } - - useFocusEffect( - React.useCallback(() => { - const onBackPress = () => { - // Always block back button on Android - return true - } - - BackHandler.addEventListener('hardwareBackPress', onBackPress) - - return () => BackHandler.removeEventListener('hardwareBackPress', onBackPress) - }, []), - ) - - const onSubmitPress = () => { - const challengeValue = challengeValues[firstNotSuccessful!] - if (!isValidChallengeValue(challengeValue)) { - return - } - if (singleValidation) { - void validateChallengeValue(challengeValue) - } else { - const state = challengeValueStates[firstNotSuccessful!] - if ( - challengeValue.prompt.validation === ChallengeValidation.Biometric && - (state === AuthenticationValueStateType.Locked || state === AuthenticationValueStateType.Fail) - ) { - beginAuthenticatingForNextChallengeReason() - return - } - void validateChallengeValue(challengeValue) - } - } - - const switchKeyboard = () => { - if (passcodeKeyboardType === PasscodeKeyboardType.Numeric) { - setPasscodeKeyboardType(PasscodeKeyboardType.Default) - } else { - setPasscodeKeyboardType(PasscodeKeyboardType.Numeric) - } - } - - const readyToSubmit = useMemo( - () => - Object.values(challengeValues) - .map((challengeValue) => challengeValue.value) - .filter((value) => !value).length === 0, - [challengeValues], - ) - - const renderAuthenticationSource = (challengeValue: ChallengeValue, index: number) => { - const last = index === Object.keys(challengeValues).length - 1 - const state = challengeValueStates[challengeValue.prompt.id] - const active = isInActiveState(state) - const isBiometric = challengeValue.prompt.validation === ChallengeValidation.Biometric - const isProtectionSessionDuration = - challengeValue.prompt.validation === ChallengeValidation.ProtectionSessionDuration - const isInput = !isBiometric && !isProtectionSessionDuration - const stateLabel = getLabelForStateAndType(challengeValue.prompt.validation, state) - - const stateTitle = getChallengePromptTitle(challengeValue.prompt, state) - - const keyboardType = - challengeValue.prompt.keyboardType ?? - (challengeValue.prompt.validation === ChallengeValidation.LocalPasscode ? passcodeKeyboardType : 'default') - - return ( - - - - {isInput && ( - - - { - onValueChange({ ...challengeValue, value: text }) - }} - value={(challengeValue.value || '') as string} - autoCorrect={false} - autoFocus={false} - autoCapitalize={'none'} - secureTextEntry={challengeValue.prompt.secureTextEntry} - keyboardType={keyboardType} - keyboardAppearance={themeService?.keyboardColorForActiveTheme()} - underlineColorAndroid={'transparent'} - onSubmitEditing={ - !singleValidation - ? () => { - void validateChallengeValue(challengeValue) - } - : undefined - } - onFocus={() => setShowSwitchKeyboard(true)} - onBlur={() => setShowSwitchKeyboard(false)} - /> - - - )} - {isBiometric && ( - - - - )} - {isProtectionSessionDuration && ( - - {ProtectionSessionDurations.map((duration, i) => ( - { - return duration.valueInSeconds === challengeValue.value - }} - onPress={() => { - onValueChange( - { - ...challengeValue, - value: duration.valueInSeconds, - }, - true, - ) - }} - /> - ))} - - )} - - - ) - } - - const isPending = useMemo( - () => Object.values(challengeValueStates).findIndex((state) => state === AuthenticationValueStateType.Pending) >= 0, - [challengeValueStates], - ) - - let submitButtonTitle: 'Submit' | 'Next' - if (singleValidation) { - submitButtonTitle = 'Submit' - } else if (!firstNotSuccessful) { - submitButtonTitle = 'Next' - } else { - const stateKeys = Object.keys(challengeValueStates) - submitButtonTitle = 'Submit' - /** Check the next values; if one of them is not successful, show 'Next' */ - for (let i = stateKeys.indexOf(firstNotSuccessful) + 1; i < stateKeys.length; i++) { - const nextValueState = challengeValueStates[stateKeys[i]] - if (nextValueState !== AuthenticationValueStateType.Success) { - submitButtonTitle = 'Next' - } - } - } - - return ( - - {(headerHeight) => ( - - - {(challenge.heading || challenge.subheading) && ( - - - - {challenge.heading && {challenge.heading}} - {challenge.subheading && {challenge.subheading}} - - - - )} - {Object.values(challengeValues).map((challengeValue, index) => - renderAuthenticationSource(challengeValue, index), - )} - - - - )} - - ) -} diff --git a/packages/mobile/src/Screens/Authenticate/helpers.ts b/packages/mobile/src/Screens/Authenticate/helpers.ts deleted file mode 100644 index b02794c43..000000000 --- a/packages/mobile/src/Screens/Authenticate/helpers.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { ChallengePrompt, ChallengeValidation, ChallengeValue } from '@standardnotes/snjs' - -export const isInActiveState = (state: AuthenticationValueStateType) => - state !== AuthenticationValueStateType.WaitingInput && state !== AuthenticationValueStateType.Success - -export enum AuthenticationValueStateType { - WaitingTurn = 0, - WaitingInput = 1, - Success = 2, - Fail = 3, - Pending = 4, - Locked = 5, -} - -type ChallengeValueState = { - challengeValues: Record - challengeValueStates: Record -} -type SetChallengeValueState = { - type: 'setState' - id: string - state: AuthenticationValueStateType -} -type SetChallengeValue = { - type: 'setValue' - id: string - value: ChallengeValue['value'] -} - -type Action = SetChallengeValueState | SetChallengeValue -export const authenticationReducer = (state: ChallengeValueState, action: Action): ChallengeValueState => { - switch (action.type) { - case 'setState': { - return { - ...state, - challengeValueStates: { - ...state.challengeValueStates, - [action.id]: action.state, - }, - } - } - case 'setValue': { - const updatedChallengeValue = state.challengeValues[action.id] - return { - ...state, - challengeValues: { - ...state.challengeValues, - [action.id]: { - ...updatedChallengeValue, - value: action.value, - }, - }, - } - } - default: - return state - } -} - -export const findIndexInObject = ( - map: ChallengeValueState['challengeValues'] | ChallengeValueState['challengeValueStates'], - id: string, -) => { - return Object.keys(map).indexOf(id) -} - -export const getChallengePromptTitle = (prompt: ChallengePrompt, state: AuthenticationValueStateType) => { - const title = prompt.title - switch (state) { - case AuthenticationValueStateType.WaitingTurn: - return title ?? 'Waiting' - case AuthenticationValueStateType.Locked: - return title ?? 'Locked' - default: - return title - } -} - -export const getLabelForStateAndType = (validation: ChallengeValidation, state: AuthenticationValueStateType) => { - switch (validation) { - case ChallengeValidation.Biometric: { - switch (state) { - case AuthenticationValueStateType.WaitingTurn: - return 'Waiting for passcode' - case AuthenticationValueStateType.WaitingInput: - return 'Press here to begin biometrics scan' - case AuthenticationValueStateType.Pending: - return 'Waiting for unlock' - case AuthenticationValueStateType.Success: - return 'Success | Biometrics' - case AuthenticationValueStateType.Fail: - return 'Biometrics failed. Tap to try again.' - case AuthenticationValueStateType.Locked: - return 'Biometrics locked. Try again in 30 seconds.' - default: - return '' - } - } - default: - switch (state) { - case AuthenticationValueStateType.WaitingTurn: - case AuthenticationValueStateType.WaitingInput: - return 'Waiting' - case AuthenticationValueStateType.Pending: - return 'Verifying keys...' - case AuthenticationValueStateType.Success: - return 'Success' - case AuthenticationValueStateType.Fail: - return 'Invalid value. Please try again.' - default: - return '' - } - } -} diff --git a/packages/mobile/src/Screens/Compose/ComponentView.styled.ts b/packages/mobile/src/Screens/Compose/ComponentView.styled.ts deleted file mode 100644 index 7fa799659..000000000 --- a/packages/mobile/src/Screens/Compose/ComponentView.styled.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { ICON_ALERT, ICON_LOCK } from '@Style/Icons' -import { ThemeService } from '@Style/ThemeService' -import { SafeAreaView } from 'react-native-safe-area-context' -import Icon from 'react-native-vector-icons/Ionicons' -import WebView from 'react-native-webview' -import styled, { css } from 'styled-components/native' - -export const FlexContainer = styled(SafeAreaView).attrs(() => ({ - edges: ['bottom'], -}))` - flex: 1; - background-color: ${({ theme }) => theme.stylekitBackgroundColor}; -` - -export const LockedContainer = styled.View` - justify-content: flex-start; - flex-direction: row; - align-items: center; - padding: 10px; - background-color: ${({ theme }) => theme.stylekitWarningColor}; - border-bottom-color: ${({ theme }) => theme.stylekitBorderColor}; - border-bottom-width: 1px; -` -export const LockedText = styled.Text` - font-weight: bold; - font-size: 12px; - color: ${({ theme }) => theme.stylekitBackgroundColor}; - padding-left: 10px; -` - -export const StyledWebview = styled(WebView)<{ showWebView: boolean }>` - flex: 1; - background-color: transparent; - opacity: 0.99; - min-height: 1px; - ${({ showWebView }) => - !showWebView && - css` - display: none; - `}; -` - -export const StyledIcon = styled(Icon).attrs(({ theme }) => ({ - color: theme.stylekitBackgroundColor, - size: 16, - name: ThemeService.nameForIcon(ICON_LOCK), -}))`` - -export const DeprecatedContainer = styled.View` - justify-content: flex-start; - flex-direction: row; - align-items: center; - padding: 10px; - background-color: ${({ theme }) => theme.stylekitWarningColor}; - border-bottom-color: ${({ theme }) => theme.stylekitBorderColor}; - border-bottom-width: 1px; -` - -export const DeprecatedText = styled.Text` - font-weight: bold; - font-size: 12px; - color: ${({ theme }) => theme.stylekitBackgroundColor}; - padding-left: 10px; -` - -export const DeprecatedIcon = styled(Icon).attrs(({ theme }) => ({ - color: theme.stylekitBackgroundColor, - size: 16, - name: ThemeService.nameForIcon(ICON_ALERT), -}))`` diff --git a/packages/mobile/src/Screens/Compose/ComponentView.tsx b/packages/mobile/src/Screens/Compose/ComponentView.tsx deleted file mode 100644 index a40766bf8..000000000 --- a/packages/mobile/src/Screens/Compose/ComponentView.tsx +++ /dev/null @@ -1,315 +0,0 @@ -import { ComponentLoadingError } from '@Lib/ComponentManager' -import { useFocusEffect, useNavigation } from '@react-navigation/native' -import { ApplicationContext } from '@Root/ApplicationContext' -import { AppStackNavigationProp } from '@Root/AppStack' -import { SCREEN_NOTES } from '@Root/Screens/screens' -import { ButtonType, ComponentViewerInterface, PrefKey } from '@standardnotes/snjs' -import { ThemeServiceContext } from '@Style/ThemeService' -import React, { useCallback, useContext, useEffect, useRef, useState } from 'react' -import { Platform } from 'react-native' -import { WebView } from 'react-native-webview' -import { - OnShouldStartLoadWithRequest, - WebViewErrorEvent, - WebViewMessageEvent, -} from 'react-native-webview/lib/WebViewTypes' -import { - DeprecatedContainer, - DeprecatedIcon, - DeprecatedText, - FlexContainer, - LockedContainer, - LockedText, - StyledIcon, - StyledWebview, -} from './ComponentView.styled' - -type Props = { - componentViewer: ComponentViewerInterface - onLoadEnd: () => void - onLoadStart: () => void - onLoadError: (error: ComponentLoadingError, desc?: string) => void - onDownloadEditorStart: () => void - onDownloadEditorEnd: () => void -} - -const log = (message?: any, ...optionalParams: any[]) => { - const LOGGING_ENABLED = false - if (LOGGING_ENABLED) { - console.log(message, optionalParams, '\n\n') - console.log('\n\n') - } -} - -/** On Android, webview.onShouldStartLoadWithRequest is not called by react-native-webview*/ -const SupportsShouldLoadRequestHandler = Platform.OS === 'ios' - -export const ComponentView = ({ - onLoadEnd, - onLoadError, - onLoadStart, - onDownloadEditorStart, - onDownloadEditorEnd, - componentViewer, -}: Props) => { - // Context - const application = useContext(ApplicationContext) - const themeService = useContext(ThemeServiceContext) - - // State - const [showWebView, setShowWebView] = useState(true) - const [requiresLocalEditor, setRequiresLocalEditor] = useState(false) - const [localEditorReady, setLocalEditorReady] = useState(false) - - // Ref - const didLoadRootUrl = useRef(false) - const webViewRef = useRef(null) - const timeoutRef = useRef | undefined>(undefined) - - const navigation = useNavigation['navigation']>() - - useEffect(() => { - const removeBlurScreenListener = navigation.addListener('blur', () => { - setShowWebView(false) - }) - - return removeBlurScreenListener - }, [navigation]) - - useFocusEffect(() => { - setShowWebView(true) - }) - - useEffect(() => { - const warnIfUnsupportedEditors = async () => { - let platformVersionRequirements - - switch (Platform.OS) { - case 'ios': - if (parseInt(Platform.Version.toString(), 10) < 11) { - // WKWebView has issues on iOS < 11 - platformVersionRequirements = 'iOS 11 or greater' - } - break - case 'android': - if (Platform.Version <= 23) { - /** - * postMessage doesn't work on Android <= 6 (API version 23) - * https://github.com/facebook/react-native/issues/11594 - */ - platformVersionRequirements = 'Android 7.0 or greater' - } - break - } - - if (!platformVersionRequirements) { - return - } - - const doNotShowAgainUnsupportedEditors = application - ?.getLocalPreferences() - .getValue(PrefKey.MobileDoNotShowAgainUnsupportedEditors, false) - - if (!doNotShowAgainUnsupportedEditors) { - const alertText = - `Web editors require ${platformVersionRequirements}. ` + - 'Your version does not support web editors. ' + - 'Changes you make may not be properly saved. Please switch to the Plain Editor for the best experience.' - - const confirmed = await application?.alertService?.confirm( - alertText, - 'Editors Not Supported', - "Don't show again", - ButtonType.Info, - 'OK', - ) - - if (confirmed) { - void application?.getLocalPreferences().setUserPrefValue(PrefKey.MobileDoNotShowAgainUnsupportedEditors, true) - } - } - } - - void warnIfUnsupportedEditors() - }, [application]) - - const onLoadErrorHandler = useCallback( - (error?: WebViewErrorEvent) => { - log('On load error', error) - if (timeoutRef.current) { - clearTimeout(timeoutRef.current) - } - - onLoadError(ComponentLoadingError.Unknown, error?.nativeEvent?.description) - }, - [onLoadError, timeoutRef], - ) - - useEffect(() => { - const componentManager = application!.mobileComponentManager - const component = componentViewer.component - const isDownloadable = componentManager.isComponentDownloadable(component) - setRequiresLocalEditor(isDownloadable) - - if (isDownloadable) { - const asyncFunc = async () => { - if (await componentManager.doesComponentNeedDownload(component)) { - onDownloadEditorStart() - const error = await componentManager.downloadComponentOffline(component) - log('Download component error', error) - onDownloadEditorEnd() - if (error) { - onLoadError(error) - } - } - setLocalEditorReady(true) - } - void asyncFunc() - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []) - - const onMessage = (event: WebViewMessageEvent) => { - let data - try { - data = JSON.parse(event.nativeEvent.data) - } catch (e) { - log('Message is not valid JSON, returning') - return - } - componentViewer?.handleMessage(data) - } - - const onFrameLoad = useCallback(() => { - log('Iframe did load', webViewRef.current?.props.source) - - /** - * We have no way of knowing if the webview load is successful or not. We - * have to wait to see if the error event is fired. Looking at the code, - * the error event is fired right after this, so we can wait just a few ms - * to see if the error event is fired before registering the component - * window. Otherwise, on error, this component will be dealloced, and a - * pending postMessage will cause a memory leak crash on Android in the - * form of "react native attempt to invoke virtual method - * double java.lang.double.doublevalue() on a null object reference" - */ - if (timeoutRef.current) { - clearTimeout(timeoutRef.current) - } - - if (didLoadRootUrl.current === true || !SupportsShouldLoadRequestHandler) { - log('Setting component viewer webview') - timeoutRef.current = setTimeout(() => { - componentViewer?.setWindow(webViewRef.current as unknown as Window) - }, 1) - /** - * The parent will remove their loading screen on load end. We want to - * delay this to avoid flicker that may result if using a dark theme. - * This delay will allow editor to load its theme. - */ - const isDarkTheme = themeService?.isLikelyUsingDarkColorTheme() - const delayToAvoidFlicker = isDarkTheme ? 50 : 0 - setTimeout(() => { - onLoadEnd() - }, delayToAvoidFlicker) - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []) - - const onLoadStartHandler = () => { - onLoadStart() - } - - const onShouldStartLoadWithRequest: OnShouldStartLoadWithRequest = (request) => { - log('Setting last iframe URL to', request.url) - /** The first request can typically be 'about:blank', which we want to ignore */ - if (!didLoadRootUrl.current) { - didLoadRootUrl.current = request.url === componentViewer.url! - } - /** - * We want to handle link clicks within an editor by opening the browser - * instead of loading inline. On iOS, onShouldStartLoadWithRequest is - * called for all requests including the initial request to load the editor. - * On iOS, clicks in the editors have a navigationType of 'click', but on - * Android, this is not the case (no navigationType). - * However, on Android, this function is not called for the initial request. - * So that might be one way to determine if this request is a click or the - * actual editor load request. But I don't think it's safe to rely on this - * being the case in the future. So on Android, we'll handle url loads only - * if the url isn't equal to the editor url. - */ - - if ( - (Platform.OS === 'ios' && request.navigationType === 'click') || - (Platform.OS === 'android' && request.url !== componentViewer.url!) - ) { - application!.deviceInterface!.openUrl(request.url) - return false - } - return true - } - - const defaultInjectedJavaScript = () => { - return `(function() { - window.parent.postMessage = function(data) { - window.parent.ReactNativeWebView.postMessage(data); - }; - const meta = document.createElement('meta'); - meta.setAttribute('content', 'width=device-width, initial-scale=1, user-scalable=no'); - meta.setAttribute('name', 'viewport'); - document.getElementsByTagName('head')[0].appendChild(meta); - return true; - })()` - } - - const deprecationMessage = componentViewer.component.deprecationMessage - - const renderWebview = !requiresLocalEditor || localEditorReady - - return ( - - {componentViewer.component.isExpired && ( - - - - Subscription expired. Editors are in a read-only state. To edit immediately, please switch to the Plain - Editor. - - - )} - - {componentViewer.component.isDeprecated && ( - - - {deprecationMessage || 'This extension is deprecated.'} - - )} - - {renderWebview && ( - onLoadErrorHandler()} - onMessage={onMessage} - hideKeyboardAccessoryView={true} - setSupportMultipleWindows={false} - onShouldStartLoadWithRequest={onShouldStartLoadWithRequest} - cacheEnabled={true} - autoManageStatusBarEnabled={false /* To prevent StatusBar from changing colors when focusing */} - injectedJavaScript={defaultInjectedJavaScript()} - onContentProcessDidTerminate={() => onLoadErrorHandler()} - /> - )} - - ) -} diff --git a/packages/mobile/src/Screens/Compose/Compose.styled.ts b/packages/mobile/src/Screens/Compose/Compose.styled.ts deleted file mode 100644 index 7d20abcb8..000000000 --- a/packages/mobile/src/Screens/Compose/Compose.styled.ts +++ /dev/null @@ -1,121 +0,0 @@ -import SNTextView from '@standardnotes/react-native-textview' -import React, { ComponentProps } from 'react' -import { Platform } from 'react-native' -import styled, { css } from 'styled-components/native' - -const PADDING = 14 -const NOTE_TITLE_HEIGHT = 50 - -export const Container = styled.View` - flex: 1; - background-color: ${({ theme }) => theme.stylekitBackgroundColor}; -` -export const LockedContainer = styled.View` - justify-content: flex-start; - flex-direction: row; - align-items: center; - padding-left: ${PADDING}px; - padding: 8px; - background-color: ${({ theme }) => theme.stylekitNeutralColor}; - border-bottom-color: ${({ theme }) => theme.stylekitBorderColor}; - border-bottom-width: 1px; -` -export const LockedText = styled.Text` - font-weight: bold; - font-size: 12px; - color: ${({ theme }) => theme.stylekitBackgroundColor}; - padding-left: 10px; - padding-right: 100px; -` -export const WebViewReloadButton = styled.TouchableOpacity` - position: absolute; - right: ${PADDING}px; - height: 100%; - flex: 1; - flex-direction: column; - align-items: center; - justify-content: center; -` -export const WebViewReloadButtonText = styled.Text` - color: ${({ theme }) => theme.stylekitBackgroundColor}; - font-size: 12px; - font-weight: bold; -` -export const NoteTitleInput = styled.TextInput` - font-weight: ${Platform.OS === 'ios' ? 600 : 'bold'}; - font-size: ${Platform.OS === 'ios' ? 17 : 18}px; - color: ${({ theme }) => theme.stylekitForegroundColor}; - background-color: ${({ theme }) => theme.stylekitBackgroundColor}; - height: ${NOTE_TITLE_HEIGHT}px; - border-bottom-color: ${({ theme }) => theme.stylekitBorderColor}; - border-bottom-width: 1px; - padding-top: ${Platform.OS === 'ios' ? 5 : 12}px; - padding-left: ${PADDING}px; - padding-right: ${PADDING}px; -` -export const LoadingWebViewContainer = styled.View<{ locked?: boolean }>` - position: absolute; - height: 100%; - width: 100%; - top: ${({ locked }) => (locked ? NOTE_TITLE_HEIGHT + 26 : NOTE_TITLE_HEIGHT)}px; - bottom: 0px; - z-index: 300; - display: flex; - align-items: center; - justify-content: center; - background-color: ${({ theme }) => theme.stylekitBackgroundColor}; -` -export const LoadingText = styled.Text` - padding-left: 0px; - color: ${({ theme }) => theme.stylekitForegroundColor}; - opacity: 0.7; - margin-top: 5px; -` -export const ContentContainer = styled.View` - flex-grow: 1; -` -export const TextContainer = styled.View` - flex: 1; -` -export const StyledKeyboardAvoidngView = styled.KeyboardAvoidingView` - flex: 1; - ${({ theme }) => theme.stylekitBackgroundColor}; -` - -const StyledTextViewComponent = styled(SNTextView)<{ errorState: boolean }>` - padding-top: 10px; - color: ${({ theme }) => theme.stylekitForegroundColor}; - padding-left: ${({ theme }) => theme.paddingLeft - (Platform.OS === 'ios' ? 5 : 0)}px; - padding-right: ${({ theme }) => theme.paddingLeft - (Platform.OS === 'ios' ? 5 : 0)}px; - padding-bottom: ${({ errorState }) => (errorState ? 36 : 10)}px; - ${Platform.OS === 'ios' && - css` - height: 96%; - `} - ${Platform.OS === 'android' && - css` - flex: 1; - `} - background-color: ${({ theme }) => theme.stylekitBackgroundColor}; - /* ${Platform.OS === 'ios' && 'padding-bottom: 10px'}; */ -` - -export const StyledTextView = React.memo( - StyledTextViewComponent, - (newProps: ComponentProps, prevProps: ComponentProps) => { - if ( - newProps.value !== prevProps.value || - newProps.selectionColor !== prevProps.selectionColor || - newProps.handlesColor !== prevProps.handlesColor || - newProps.autoFocus !== prevProps.autoFocus || - newProps.editable !== prevProps.editable || - newProps.keyboardDismissMode !== prevProps.keyboardDismissMode || - newProps.keyboardAppearance !== prevProps.keyboardAppearance || - newProps.testID !== prevProps.testID || - newProps.multiline !== prevProps.multiline - ) { - return false - } - return true - }, -) diff --git a/packages/mobile/src/Screens/Compose/Compose.tsx b/packages/mobile/src/Screens/Compose/Compose.tsx deleted file mode 100644 index 4f5b37824..000000000 --- a/packages/mobile/src/Screens/Compose/Compose.tsx +++ /dev/null @@ -1,593 +0,0 @@ -import { AppStateEventType } from '@Lib/ApplicationState' -import { ComponentLoadingError, ComponentManager } from '@Lib/ComponentManager' -import { ApplicationContext, SafeApplicationContext } from '@Root/ApplicationContext' -import { AppStackNavigationProp } from '@Root/AppStack' -import { SCREEN_COMPOSE } from '@Root/Screens/screens' -import SNTextView from '@standardnotes/react-native-textview' -import { - ApplicationEvent, - ComponentMutator, - ComponentViewerInterface, - ContentType, - isPayloadSourceInternalChange, - isPayloadSourceRetrieved, - ItemMutator, - NoteMutator, - NoteViewController, - PayloadEmitSource, - SNComponent, - UuidString, -} from '@standardnotes/snjs' -import { ICON_ALERT, ICON_LOCK } from '@Style/Icons' -import { ThemeService, ThemeServiceContext } from '@Style/ThemeService' -import { lighten } from '@Style/Utils' -import React, { createRef } from 'react' -import { Keyboard, Platform, View } from 'react-native' -import Icon from 'react-native-vector-icons/Ionicons' -import { ThemeContext } from 'styled-components' -import { ComponentView } from './ComponentView' -import { - Container, - LoadingText, - LoadingWebViewContainer, - LockedContainer, - LockedText, - NoteTitleInput, - StyledTextView, - TextContainer, - WebViewReloadButton, - WebViewReloadButtonText, -} from './Compose.styled' - -const NOTE_PREVIEW_CHAR_LIMIT = 80 -const MINIMUM_STATUS_DURATION = 400 -const SAVE_TIMEOUT_DEBOUNCE = 250 -const SAVE_TIMEOUT_NO_DEBOUNCE = 100 - -type State = { - title: string - saveError: boolean - webViewError?: ComponentLoadingError - webViewErrorDesc?: string - loadingWebview: boolean - downloadingEditor: boolean - componentViewer?: ComponentViewerInterface -} - -type PropsWhenNavigating = AppStackNavigationProp - -type PropsWhenRenderingDirectly = { - noteUuid: UuidString -} - -const EditingIsDisabledText = 'This note has editing disabled. Please enable editing on this note to make changes.' - -export class Compose extends React.Component { - static override contextType = ApplicationContext - override context: React.ContextType - controller: NoteViewController - editorViewRef: React.RefObject = createRef() - saveTimeout: ReturnType | undefined - alreadySaved = false - statusTimeout: ReturnType | undefined - downloadingMessageTimeout: ReturnType | undefined - removeNoteInnerValueObserver?: () => void - removeComponentsObserver?: () => void - removeStreamComponents?: () => void - removeStateEventObserver?: () => void - removeAppEventObserver?: () => void - removeComponentHandler?: () => void - - constructor( - props: PropsWhenNavigating | PropsWhenRenderingDirectly, - context: React.ContextType, - ) { - super(props) - this.context = context - - const noteUuid = 'noteUuid' in props ? props.noteUuid : props.route.params.noteUuid - const editor = this.context.editorGroup.itemControllers.find((c) => c.item.uuid === noteUuid) as NoteViewController - if (!editor) { - throw 'Unable to to find note controller' - } - - this.controller = editor - - this.state = { - title: this.controller.item.title, - componentViewer: undefined, - saveError: false, - webViewError: undefined, - loadingWebview: false, - downloadingEditor: false, - } - } - - override componentDidMount() { - this.removeNoteInnerValueObserver = this.controller.addNoteInnerValueChangeObserver((note, source) => { - if (isPayloadSourceRetrieved(source)) { - this.setState({ - title: note.title, - }) - - this.editorViewRef.current?.setText(note.text) - } - - const isTemplateNoteInsertedToBeInteractableWithEditor = source === PayloadEmitSource.LocalInserted && note.dirty - if (isTemplateNoteInsertedToBeInteractableWithEditor) { - return - } - - if (note.lastSyncBegan || note.dirty) { - if (note.lastSyncEnd) { - if (note.dirty || (note.lastSyncBegan && note.lastSyncBegan.getTime() > note.lastSyncEnd.getTime())) { - this.showSavingStatus() - } else if ( - this.context?.getStatusManager().hasMessage(SCREEN_COMPOSE) && - note.lastSyncBegan && - note.lastSyncEnd.getTime() > note.lastSyncBegan.getTime() - ) { - this.showAllChangesSavedStatus() - } - } else { - this.showSavingStatus() - } - } - }) - - this.removeStreamComponents = this.context?.streamItems(ContentType.Component, async ({ source }) => { - if (isPayloadSourceInternalChange(source)) { - return - } - - if (!this.controllerNote) { - return - } - - void this.reloadComponentEditorState() - }) - - this.removeAppEventObserver = this.context?.addEventObserver(async (eventName) => { - if (!this.controller || this.controller.dealloced) { - return - } - - if (eventName === ApplicationEvent.CompletedFullSync) { - /** if we're still dirty, don't change status, a sync is likely upcoming. */ - if (!this.controllerNote.dirty && this.state.saveError) { - this.showAllChangesSavedStatus() - } - } else if (eventName === ApplicationEvent.FailedSync) { - /** - * Only show error status in editor if the note is dirty. - * Otherwise, it means the originating sync came from somewhere else - * and we don't want to display an error here. - */ - if (this.controllerNote.dirty) { - this.showErrorStatus('Sync Unavailable (changes saved offline)') - } - } else if (eventName === ApplicationEvent.LocalDatabaseWriteError) { - this.showErrorStatus('Offline Saving Issue (changes not saved)') - } - }) - - this.removeStateEventObserver = this.context?.getAppState().addStateEventObserver((state) => { - if (state === AppStateEventType.DrawerOpen) { - this.dismissKeyboard() - /** - * Saves latest note state before any change might happen in the drawer - */ - } - }) - - if (this.controller.isTemplateNote && Platform.OS === 'ios') { - setTimeout(() => { - this.editorViewRef?.current?.focus() - }, 0) - } - } - - override componentWillUnmount() { - this.dismissKeyboard() - this.removeNoteInnerValueObserver && this.removeNoteInnerValueObserver() - this.removeAppEventObserver && this.removeAppEventObserver() - this.removeStreamComponents && this.removeStreamComponents() - this.removeStateEventObserver && this.removeStateEventObserver() - this.removeComponentHandler && this.removeComponentHandler() - this.removeStateEventObserver = undefined - this.removeNoteInnerValueObserver = undefined - this.removeComponentHandler = undefined - this.removeStreamComponents = undefined - this.removeAppEventObserver = undefined - this.context?.getStatusManager()?.setMessage(SCREEN_COMPOSE, '') - if (this.state.componentViewer && this.componentManager) { - this.componentManager.destroyComponentViewer(this.state.componentViewer) - } - if (this.saveTimeout) { - clearTimeout(this.saveTimeout) - } - if (this.statusTimeout) { - clearTimeout(this.statusTimeout) - } - if (this.downloadingMessageTimeout) { - clearTimeout(this.downloadingMessageTimeout) - } - } - - /** - * Because note.locked accesses note.content.appData, - * we do not want to expose the template to direct access to note.locked, - * otherwise an exception will occur when trying to access note.locked if the note - * is deleted. There is potential for race conditions to occur with setState, where a - * previous setState call may have queued a digest cycle, and the digest cycle triggers - * on a deleted note. - */ - get noteLocked() { - if (!this.controllerNote) { - return false - } - return this.controllerNote.locked - } - - setStatus = (status: string, color?: string, wait = true) => { - if (this.statusTimeout) { - clearTimeout(this.statusTimeout) - } - if (wait) { - this.statusTimeout = setTimeout(() => { - this.context?.getStatusManager()?.setMessage(SCREEN_COMPOSE, status, color) - }, MINIMUM_STATUS_DURATION) - } else { - this.context?.getStatusManager()?.setMessage(SCREEN_COMPOSE, status, color) - } - } - - showSavingStatus = () => { - this.setStatus('Saving...', undefined, false) - } - - showAllChangesSavedStatus = () => { - this.setState({ - saveError: false, - }) - const offlineStatus = this.context?.hasAccount() ? '' : ' (offline)' - this.setStatus('All changes saved' + offlineStatus) - } - - showErrorStatus = (message: string) => { - this.setState({ - saveError: true, - }) - this.setStatus(message) - } - - get controllerNote() { - return this.controller.item - } - - dismissKeyboard = () => { - Keyboard.dismiss() - this.editorViewRef.current?.blur() - } - - get componentManager() { - return this.context?.mobileComponentManager as ComponentManager - } - - async associateComponentWithCurrentNote(component: SNComponent) { - const note = this.controllerNote - if (!note) { - return - } - - return this.context?.mutator.changeItem(component, (m: ItemMutator) => { - const mutator = m as ComponentMutator - mutator.removeDisassociatedItemId(note.uuid) - mutator.associateWithItem(note.uuid) - }) - } - - reloadComponentEditorState = async () => { - this.setState({ - downloadingEditor: false, - loadingWebview: false, - webViewError: undefined, - }) - - const associatedEditor = this.componentManager.editorForNote(this.controllerNote) - - /** Editors cannot interact with template notes so the note must be inserted */ - if (associatedEditor && this.controller.isTemplateNote) { - await this.controller.insertTemplatedNote() - void this.associateComponentWithCurrentNote(associatedEditor) - } - - if (!associatedEditor) { - if (this.state.componentViewer) { - this.componentManager.destroyComponentViewer(this.state.componentViewer) - this.setState({ componentViewer: undefined }) - } - } else if (associatedEditor.uuid !== this.state.componentViewer?.component.uuid) { - if (this.state.componentViewer) { - this.componentManager.destroyComponentViewer(this.state.componentViewer) - } - if (this.componentManager.isComponentThirdParty(associatedEditor.identifier)) { - await this.componentManager.preloadThirdPartyIndexPathFromDisk(associatedEditor.identifier) - } - this.loadComponentViewer(associatedEditor) - } - } - - loadComponentViewer(component: SNComponent) { - this.setState({ - componentViewer: this.componentManager.createComponentViewer(component, this.controllerNote.uuid), - }) - } - - async forceReloadExistingEditor() { - if (this.state.componentViewer) { - this.componentManager.destroyComponentViewer(this.state.componentViewer) - } - - this.setState({ - componentViewer: undefined, - loadingWebview: false, - webViewError: undefined, - }) - - const associatedEditor = this.componentManager.editorForNote(this.controllerNote) - if (associatedEditor) { - this.loadComponentViewer(associatedEditor) - } - } - - saveNote = async (params: { newTitle?: string; newText?: string }) => { - if (this.controller.isTemplateNote) { - await this.controller.insertTemplatedNote() - } - - if (!this.context?.items.findItem(this.controllerNote.uuid)) { - void this.context?.alertService.alert('Attempting to save this note has failed. The note cannot be found.') - return - } - - const { newTitle, newText } = params - - await this.context.mutator.changeItem( - this.controllerNote, - (mutator) => { - const noteMutator = mutator as NoteMutator - - if (newTitle != null) { - noteMutator.title = newTitle - } - - if (newText != null) { - noteMutator.text = newText - - const substring = newText.substring(0, NOTE_PREVIEW_CHAR_LIMIT) - const shouldTruncate = newText.length > NOTE_PREVIEW_CHAR_LIMIT - const previewPlain = substring + (shouldTruncate ? '...' : '') - noteMutator.preview_plain = previewPlain - noteMutator.preview_html = undefined - } - }, - true, - ) - - if (this.saveTimeout) { - clearTimeout(this.saveTimeout) - } - const noDebounce = this.context?.noAccount() - const syncDebouceMs = noDebounce ? SAVE_TIMEOUT_NO_DEBOUNCE : SAVE_TIMEOUT_DEBOUNCE - - this.saveTimeout = setTimeout(() => { - void this.context?.sync.sync() - }, syncDebouceMs) - } - - onTitleChange = (newTitle: string) => { - if (this.controllerNote.locked) { - void this.context?.alertService?.alert(EditingIsDisabledText) - return - } - - this.setState( - { - title: newTitle, - }, - () => this.saveNote({ newTitle: newTitle }), - ) - } - - onContentChange = (text: string) => { - if (this.controllerNote.locked) { - void this.context?.alertService?.alert(EditingIsDisabledText) - return - } - - void this.saveNote({ newText: text }) - } - - onLoadWebViewStart = () => { - this.setState({ - loadingWebview: true, - webViewError: undefined, - }) - } - - onLoadWebViewEnd = () => { - this.setState({ - loadingWebview: false, - }) - } - - onLoadWebViewError = (error: ComponentLoadingError, desc?: string) => { - this.setState({ - loadingWebview: false, - webViewError: error, - webViewErrorDesc: desc, - }) - } - - onDownloadEditorStart = () => { - this.setState({ - downloadingEditor: true, - }) - } - - onDownloadEditorEnd = () => { - if (this.downloadingMessageTimeout) { - clearTimeout(this.downloadingMessageTimeout) - } - - this.downloadingMessageTimeout = setTimeout( - () => - this.setState({ - downloadingEditor: false, - }), - this.state.webViewError ? 0 : 200, - ) - } - - getErrorText(): string { - let text = '' - switch (this.state.webViewError) { - case ComponentLoadingError.ChecksumMismatch: - text = 'The remote editor signature differs from the expected value.' - break - case ComponentLoadingError.DoesntExist: - text = 'The local editor files do not exist.' - break - case ComponentLoadingError.FailedDownload: - text = 'The editor failed to download.' - break - case ComponentLoadingError.LocalServerFailure: - text = 'The local component server has an error.' - break - case ComponentLoadingError.Unknown: - text = 'An unknown error occurred.' - break - default: - break - } - - if (this.state.webViewErrorDesc) { - text += `Webview Error: ${this.state.webViewErrorDesc}` - } - - return text - } - - override render() { - const shouldDisplayEditor = - this.state.componentViewer && - Boolean(this.controllerNote) && - !this.controllerNote.prefersPlainEditor && - !this.state.webViewError - - return ( - - - {(theme) => ( - <> - {this.noteLocked && ( - - - Note Editing Disabled - - )} - {this.state.webViewError && ( - - - - Unable to load {this.state.componentViewer?.component.name} — {this.getErrorText()} - - { - void this.forceReloadExistingEditor() - }} - > - Reload - - - )} - - {(themeService) => ( - <> - - {(this.state.downloadingEditor || - (this.state.loadingWebview && themeService?.isLikelyUsingDarkColorTheme())) && ( - - - {'Loading '} - {this.state.componentViewer?.component.name}... - - - )} - {/* setting webViewError to false on onLoadEnd will cause an infinite loop on Android upon webview error, so, don't do that. */} - {shouldDisplayEditor && this.state.componentViewer && ( - - )} - - {!shouldDisplayEditor && this.controllerNote != undefined && Platform.OS === 'android' && ( - - - - )} - {/* Empty wrapping view fixes native textview crashing */} - {!shouldDisplayEditor && Platform.OS === 'ios' && ( - - - - )} - - )} - - - )} - - - ) - } -} diff --git a/packages/mobile/src/Screens/InputModal/FileInputModal.tsx b/packages/mobile/src/Screens/InputModal/FileInputModal.tsx deleted file mode 100644 index 1ad1fb0e8..000000000 --- a/packages/mobile/src/Screens/InputModal/FileInputModal.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { ButtonCell } from '@Root/Components/ButtonCell' -import { SectionedTableCell } from '@Root/Components/SectionedTableCell' -import { TableSection } from '@Root/Components/TableSection' -import { useSafeApplicationContext } from '@Root/Hooks/useSafeApplicationContext' -import { ModalStackNavigationProp } from '@Root/ModalStack' -import { SCREEN_INPUT_MODAL_FILE_NAME } from '@Root/Screens/screens' -import { ThemeServiceContext } from '@Style/ThemeService' -import React, { FC, useContext, useEffect, useRef, useState } from 'react' -import { TextInput } from 'react-native' -import { Container, Input } from './InputModal.styled' - -type Props = ModalStackNavigationProp - -export const FileInputModal: FC = (props) => { - const { file, renameFile } = props.route.params - const themeService = useContext(ThemeServiceContext) - const application = useSafeApplicationContext() - - const fileNameInputRef = useRef(null) - - const [fileName, setFileName] = useState(file.name) - - const onSubmit = async () => { - const trimmedFileName = fileName.trim() - if (trimmedFileName === '') { - setFileName(file.name) - await application?.alertService.alert('File name cannot be empty') - fileNameInputRef.current?.focus() - return - } - await renameFile(file, trimmedFileName) - void application.sync.sync() - props.navigation.goBack() - } - - useEffect(() => { - fileNameInputRef.current?.focus() - }, []) - - return ( - - - - - - - - - - ) -} diff --git a/packages/mobile/src/Screens/InputModal/InputModal.styled.ts b/packages/mobile/src/Screens/InputModal/InputModal.styled.ts deleted file mode 100644 index cd857a74f..000000000 --- a/packages/mobile/src/Screens/InputModal/InputModal.styled.ts +++ /dev/null @@ -1,15 +0,0 @@ -import styled from 'styled-components/native' - -export const Container = styled.View` - flex: 1; - background-color: ${({ theme }) => theme.stylekitBackgroundColor}; -` - -export const Input = styled.TextInput.attrs(({ theme }) => ({ - placeholderTextColor: theme.stylekitNeutralColor, -}))` - font-size: ${({ theme }) => theme.mainTextFontSize}px; - padding: 0px; - color: ${({ theme }) => theme.stylekitForegroundColor}; - height: 100%; -` diff --git a/packages/mobile/src/Screens/InputModal/PasscodeInputModal.tsx b/packages/mobile/src/Screens/InputModal/PasscodeInputModal.tsx deleted file mode 100644 index 27eeac12c..000000000 --- a/packages/mobile/src/Screens/InputModal/PasscodeInputModal.tsx +++ /dev/null @@ -1,135 +0,0 @@ -import { PasscodeKeyboardType } from '@Lib/ApplicationState' -import { ApplicationContext } from '@Root/ApplicationContext' -import { ButtonCell } from '@Root/Components/ButtonCell' -import { Option, SectionedOptionsTableCell } from '@Root/Components/SectionedOptionsTableCell' -import { SectionedTableCell } from '@Root/Components/SectionedTableCell' -import { TableSection } from '@Root/Components/TableSection' -import { ModalStackNavigationProp } from '@Root/ModalStack' -import { SCREEN_INPUT_MODAL_PASSCODE } from '@Root/Screens/screens' -import { MobileUnlockTiming } from '@standardnotes/snjs' -import { ThemeServiceContext } from '@Style/ThemeService' -import React, { useContext, useMemo, useRef, useState } from 'react' -import { Keyboard, KeyboardType, Platform, TextInput } from 'react-native' -import { Container, Input } from './InputModal.styled' - -type Props = ModalStackNavigationProp -export const PasscodeInputModal = (props: Props) => { - // Context - const application = useContext(ApplicationContext) - const themeService = useContext(ThemeServiceContext) - - // State - const [settingPassocode, setSettingPassocode] = useState(false) - const [text, setText] = useState('') - const [confirmText, setConfirmText] = useState('') - const [keyboardType, setKeyboardType] = useState('default') - - // Refs - const textRef = useRef(null) - const confirmTextRef = useRef(null) - - const onTextSubmit = () => { - if (!confirmText) { - confirmTextRef.current?.focus() - } else { - Keyboard.dismiss() - } - } - - const onSubmit = async () => { - if (settingPassocode) { - return - } - setSettingPassocode(true) - if (text !== confirmText) { - void application?.alertService?.alert( - 'The two values you entered do not match. Please try again.', - 'Invalid Confirmation', - 'OK', - ) - setSettingPassocode(false) - } else { - await application?.addPasscode(text) - await application?.getAppState().setPasscodeKeyboardType(keyboardType as PasscodeKeyboardType) - await application?.getAppState().setPasscodeTiming(MobileUnlockTiming.OnQuit) - setSettingPassocode(false) - props.navigation.goBack() - } - } - - const keyboardOptions: Option[] = useMemo( - () => [ - { - title: 'General', - key: 'default' as PasscodeKeyboardType, - selected: keyboardType === 'default', - }, - { - title: 'Numeric', - key: 'numeric' as PasscodeKeyboardType, - selected: keyboardType === 'numeric', - }, - ], - [keyboardType], - ) - - const onKeyboardTypeSelect = (option: Option) => { - setKeyboardType(option.key as KeyboardType) - } - - return ( - - - - - - - - - - - - - - - - ) -} diff --git a/packages/mobile/src/Screens/InputModal/TagInputModal.tsx b/packages/mobile/src/Screens/InputModal/TagInputModal.tsx deleted file mode 100644 index 882c4ed5d..000000000 --- a/packages/mobile/src/Screens/InputModal/TagInputModal.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import { useFocusEffect } from '@react-navigation/native' -import { ApplicationContext } from '@Root/ApplicationContext' -import { ButtonCell } from '@Root/Components/ButtonCell' -import { SectionedTableCell } from '@Root/Components/SectionedTableCell' -import { TableSection } from '@Root/Components/TableSection' -import { ModalStackNavigationProp } from '@Root/ModalStack' -import { SCREEN_INPUT_MODAL_TAG } from '@Root/Screens/screens' -import { SNNote, SNTag, TagMutator } from '@standardnotes/snjs' -import { ThemeServiceContext } from '@Style/ThemeService' -import React, { useCallback, useContext, useEffect, useRef, useState } from 'react' -import { TextInput } from 'react-native' -import { Container, Input } from './InputModal.styled' - -type Props = ModalStackNavigationProp -export const TagInputModal = (props: Props) => { - // Context - const application = useContext(ApplicationContext) - const themeService = useContext(ThemeServiceContext) - - // State - const [text, setText] = useState('') - - // Refs - const textRef = useRef(null) - - useEffect(() => { - if (props.route.params.tagUuid) { - const tag = application?.items.findItem(props.route.params.tagUuid) as SNTag - setText(tag.title) - } - }, [application, props.route.params.tagUuid]) - - useFocusEffect( - useCallback(() => { - setTimeout(() => { - textRef.current?.focus() - }, 1) - }, []), - ) - - const onSubmit = useCallback(async () => { - if (props.route.params.tagUuid) { - const tag = application?.items.findItem(props.route.params.tagUuid) as SNTag - await application?.mutator.changeItem(tag, (mutator) => { - const tagMutator = mutator as TagMutator - tagMutator.title = text - if (props.route.params.noteUuid) { - const note = application.items.findItem(props.route.params.noteUuid) - if (note) { - tagMutator.addNote(note as SNNote) - } - } - }) - } else { - const tag = await application!.mutator.findOrCreateTag(text) - if (props.route.params.noteUuid) { - await application?.mutator.changeItem(tag, (mutator) => { - const tagMutator = mutator as TagMutator - const note = application.items.findItem(props.route.params.noteUuid!) - if (note) { - tagMutator.addNote(note as SNNote) - } - }) - } - } - - void application?.sync.sync() - props.navigation.goBack() - }, [application, props.navigation, props.route.params.noteUuid, props.route.params.tagUuid, text]) - - return ( - - - - - - - - - - ) -} diff --git a/packages/mobile/src/Screens/InputModal/WorkspaceInputModal.tsx b/packages/mobile/src/Screens/InputModal/WorkspaceInputModal.tsx deleted file mode 100644 index 096f2ebb5..000000000 --- a/packages/mobile/src/Screens/InputModal/WorkspaceInputModal.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { ButtonCell } from '@Root/Components/ButtonCell' -import { SectionedTableCell } from '@Root/Components/SectionedTableCell' -import { TableSection } from '@Root/Components/TableSection' -import { useSafeApplicationContext } from '@Root/Hooks/useSafeApplicationContext' -import { ModalStackNavigationProp } from '@Root/ModalStack' -import { SCREEN_INPUT_MODAL_WORKSPACE_NAME } from '@Root/Screens/screens' -import { ThemeServiceContext } from '@Style/ThemeService' -import React, { FC, useContext, useEffect, useRef, useState } from 'react' -import { TextInput } from 'react-native' -import { Container, Input } from './InputModal.styled' - -type Props = ModalStackNavigationProp - -export const WorkspaceInputModal: FC = (props) => { - const { descriptor, renameWorkspace } = props.route.params - const themeService = useContext(ThemeServiceContext) - const application = useSafeApplicationContext() - - const workspaceNameInputRef = useRef(null) - - const [workspaceName, setWorkspaceName] = useState(descriptor.label) - - const onSubmit = async () => { - const trimmedWorkspaceName = workspaceName.trim() - if (trimmedWorkspaceName === '') { - setWorkspaceName(descriptor.label) - await application?.alertService.alert('Workspace name cannot be empty') - workspaceNameInputRef.current?.focus() - return - } - await renameWorkspace(descriptor, trimmedWorkspaceName) - void application.sync.sync() - props.navigation.goBack() - } - - useEffect(() => { - workspaceNameInputRef.current?.focus() - }, []) - - return ( - - - - - - - - - - ) -} diff --git a/packages/mobile/src/Screens/ManageSessions/ManageSessions.tsx b/packages/mobile/src/Screens/ManageSessions/ManageSessions.tsx deleted file mode 100644 index d7d4a2903..000000000 --- a/packages/mobile/src/Screens/ManageSessions/ManageSessions.tsx +++ /dev/null @@ -1,154 +0,0 @@ -import { ApplicationContext } from '@Root/ApplicationContext' -import { LoadingContainer, LoadingText } from '@Root/Screens/Notes/NoteList.styled' -import { ButtonType, RemoteSession, SessionStrings, UuidString } from '@standardnotes/snjs' -import { useCustomActionSheet } from '@Style/CustomActionSheet' -import React, { useCallback, useContext, useEffect, useState } from 'react' -import { FlatList, ListRenderItem, RefreshControl } from 'react-native' -import { useSafeAreaInsets } from 'react-native-safe-area-context' -import { ThemeContext } from 'styled-components' -import { SessionCell } from './SessionCell' - -const useSessions = (): [ - RemoteSession[], - () => void, - () => void, - boolean, - (uuid: UuidString) => Promise, - string, -] => { - // Context - const application = useContext(ApplicationContext) - - // State - const [sessions, setSessions] = useState([]) - const [refreshing, setRefreshing] = useState(false) - const [errorMessage, setErrorMessage] = useState('') - - const getSessions = useCallback(async () => { - const response = await application?.getSessions() - - if (!response) { - setErrorMessage('An unknown error occurred while loading sessions.') - return - } - - if ('error' in response || !response.data) { - if (response.error?.message) { - setErrorMessage(response.error.message) - } else { - setErrorMessage('An unknown error occurred while loading sessions.') - } - } else { - const newSessions = response.data as RemoteSession[] - setSessions(newSessions) - setErrorMessage('') - } - }, [application]) - - const refreshSessions = useCallback(async () => { - setRefreshing(true) - await getSessions() - setRefreshing(false) - }, [getSessions]) - - useEffect(() => { - void refreshSessions() - }, [application, refreshSessions]) - - async function revokeSession(uuid: UuidString) { - const response = await application?.revokeSession(uuid) - if (response && 'error' in response) { - if (response.error?.message) { - setErrorMessage(response.error?.message) - } else { - setErrorMessage('An unknown error occurred while revoking the session.') - } - } else { - setSessions(sessions.filter((session) => session.uuid !== uuid)) - } - } - - return [sessions, getSessions, refreshSessions, refreshing, revokeSession, errorMessage] -} - -export const ManageSessions: React.FC = () => { - // Context - const application = useContext(ApplicationContext) - const { showActionSheet } = useCustomActionSheet() - const theme = useContext(ThemeContext) - const insets = useSafeAreaInsets() - - const [sessions, getSessions, refreshSessions, refreshing, revokeSession, errorMessage] = useSessions() - - const onItemPress = (item: RemoteSession) => { - showActionSheet({ - title: item.device_info, - options: [ - { - text: 'Revoke', - destructive: true, - callback: () => showRevokeSessionAlert(item), - }, - ], - }) - } - - const showRevokeSessionAlert = useCallback( - async (item: RemoteSession) => { - const confirmed = await application?.alertService.confirm( - SessionStrings.RevokeText, - SessionStrings.RevokeTitle, - SessionStrings.RevokeConfirmButton, - ButtonType.Danger, - SessionStrings.RevokeCancelButton, - ) - if (confirmed) { - try { - await revokeSession(item.uuid) - getSessions() - } catch (e) { - void application?.alertService.alert('Action failed. Please try again.') - } - } - }, - [application?.alertService, getSessions, revokeSession], - ) - - const RenderItem: ListRenderItem | null | undefined = ({ item }) => { - return ( - onItemPress(item)} - title={item.device_info} - subTitle={item.updated_at.toLocaleDateString()} - currentSession={item.current} - disabled={item.current} - /> - ) - } - - if (errorMessage) { - return ( - - {errorMessage} - - ) - } - - return ( - - keyExtractor={(item) => item.uuid} - contentContainerStyle={{ paddingBottom: insets.bottom }} - initialNumToRender={7} - windowSize={7} - data={sessions} - refreshControl={ - - } - renderItem={RenderItem} - /> - ) -} diff --git a/packages/mobile/src/Screens/ManageSessions/SessionCell.tsx b/packages/mobile/src/Screens/ManageSessions/SessionCell.tsx deleted file mode 100644 index c47ff94c6..000000000 --- a/packages/mobile/src/Screens/ManageSessions/SessionCell.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { Props as TableCellProps, SectionedTableCellTouchableHighlight } from '@Root/Components/SectionedTableCell' -import React from 'react' -import styled, { css } from 'styled-components/native' - -type Props = { - testID?: string - disabled?: boolean - onPress: () => void - title: string - subTitle: string - currentSession: boolean -} - -const Container = styled(SectionedTableCellTouchableHighlight).attrs((props) => ({ - underlayColor: props.theme.stylekitBorderColor, -}))` - padding-top: ${12}px; - justify-content: center; -` -const ButtonContainer = styled.View`` - -type ButtonLabelProps = Pick -const ButtonLabel = styled.Text` - color: ${(props) => { - let color = props.theme.stylekitForegroundColor - if (props.disabled) { - color = 'gray' - } - return color - }}; - font-weight: bold; - font-size: ${(props) => props.theme.mainTextFontSize}px; - ${({ disabled }) => - disabled && - css` - opacity: 0.6; - `} -` -export const SubTitleText = styled.Text<{ current: boolean }>` - font-size: 14px; - margin-top: 4px; - color: ${({ theme, current }) => { - return current ? theme.stylekitInfoColor : theme.stylekitForegroundColor - }}; - opacity: 0.8; - line-height: 21px; -` - -export const SessionCell: React.FC = (props) => ( - - - {props.title} - - {props.currentSession ? 'Current session' : 'Signed in on ' + props.subTitle} - - - -) diff --git a/packages/mobile/src/Screens/NoteHistory/NoteHistory.styled.ts b/packages/mobile/src/Screens/NoteHistory/NoteHistory.styled.ts deleted file mode 100644 index 80ae9f1b0..000000000 --- a/packages/mobile/src/Screens/NoteHistory/NoteHistory.styled.ts +++ /dev/null @@ -1,17 +0,0 @@ -import styled from 'styled-components/native' - -export const Container = styled.View`` - -export const DateText = styled.Text` - font-size: 15px; - margin-top: 4px; - opacity: 0.8; - line-height: 21px; -` - -export const IosTabBarContainer = styled.View` - padding-top: 10px; - padding-bottom: 5px; - padding-left: 12px; - padding-right: 12px; -` diff --git a/packages/mobile/src/Screens/NoteHistory/NoteHistory.tsx b/packages/mobile/src/Screens/NoteHistory/NoteHistory.tsx deleted file mode 100644 index d44aeedd5..000000000 --- a/packages/mobile/src/Screens/NoteHistory/NoteHistory.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import SegmentedControl from '@react-native-community/segmented-control' -import { ApplicationContext } from '@Root/ApplicationContext' -import { HistoryStackNavigationProp } from '@Root/HistoryStack' -import { SCREEN_NOTE_HISTORY, SCREEN_NOTE_HISTORY_PREVIEW } from '@Root/Screens/screens' -import { NoteHistoryEntry, SNNote } from '@standardnotes/snjs' -import { ThemeServiceContext } from '@Style/ThemeService' -import React, { useContext, useState } from 'react' -import { Dimensions, Platform } from 'react-native' -import { NavigationState, Route, SceneRendererProps, TabBar, TabView } from 'react-native-tab-view' -import { ThemeContext } from 'styled-components' -import { IosTabBarContainer } from './NoteHistory.styled' -import { RemoteHistory } from './RemoteHistory' -import { SessionHistory } from './SessionHistory' - -const initialLayout = { width: Dimensions.get('window').width } - -type Props = HistoryStackNavigationProp -export const NoteHistory = (props: Props) => { - // Context - const application = useContext(ApplicationContext) - const theme = useContext(ThemeContext) - const themeService = useContext(ThemeServiceContext) - - // State - const [note] = useState(() => application?.items.findItem(props.route.params.noteUuid) as SNNote) - const [routes] = React.useState([ - { key: 'session', title: 'Session' }, - { key: 'remote', title: 'Remote' }, - ]) - const [index, setIndex] = useState(0) - - const openPreview = (_uuid: string, revision: NoteHistoryEntry, title: string) => { - props.navigation.navigate(SCREEN_NOTE_HISTORY_PREVIEW, { - title, - revision, - originalNoteUuid: note.uuid, - }) - } - - const renderScene = ({ route }: { route: { key: string; title: string } }) => { - switch (route.key) { - case 'session': - return - case 'remote': - return - default: - return null - } - } - - const renderTabBar = ( - tabBarProps: SceneRendererProps & { - navigationState: NavigationState - }, - ) => { - return Platform.OS === 'ios' && parseInt(Platform.Version as string, 10) >= 13 ? ( - - route.title)} - selectedIndex={tabBarProps.navigationState.index} - onChange={(event) => { - setIndex(event.nativeEvent.selectedSegmentIndex) - }} - /> - - ) : ( - - ) - } - - return ( - - ) -} diff --git a/packages/mobile/src/Screens/NoteHistory/NoteHistoryCell.tsx b/packages/mobile/src/Screens/NoteHistory/NoteHistoryCell.tsx deleted file mode 100644 index 1773f1b86..000000000 --- a/packages/mobile/src/Screens/NoteHistory/NoteHistoryCell.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { Props as TableCellProps, SectionedTableCellTouchableHighlight } from '@Root/Components/SectionedTableCell' -import React from 'react' -import styled, { css } from 'styled-components/native' - -type Props = { - testID?: string - disabled?: boolean - onPress: () => void - first?: boolean - last?: boolean - title: string - subTitle?: string -} - -const Container = styled(SectionedTableCellTouchableHighlight).attrs((props) => ({ - underlayColor: props.theme.stylekitBorderColor, -}))` - padding-top: ${12}px; - justify-content: center; -` -const ButtonContainer = styled.View`` - -type ButtonLabelProps = Pick -const ButtonLabel = styled.Text` - color: ${(props) => { - let color = props.theme.stylekitForegroundColor - if (props.disabled) { - color = 'gray' - } - return color - }}; - font-weight: bold; - font-size: ${(props) => props.theme.mainTextFontSize}px; - ${({ disabled }) => - disabled && - css` - opacity: 0.6; - `} -` -export const SubTitleText = styled.Text` - font-size: 14px; - margin-top: 4px; - color: ${({ theme }) => theme.stylekitForegroundColor}; - opacity: 0.8; - line-height: 21px; -` - -export const NoteHistoryCell: React.FC = (props) => ( - - - {props.title} - {props.subTitle && {props.subTitle}} - - -) diff --git a/packages/mobile/src/Screens/NoteHistory/NoteHistoryPreview.styled.ts b/packages/mobile/src/Screens/NoteHistory/NoteHistoryPreview.styled.ts deleted file mode 100644 index 12cfb9d24..000000000 --- a/packages/mobile/src/Screens/NoteHistory/NoteHistoryPreview.styled.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { Platform } from 'react-native' -import styled, { css } from 'styled-components/native' - -const PADDING = 14 -const NOTE_TITLE_HEIGHT = 50 - -export const Container = styled.View` - flex: 1; - background-color: ${({ theme }) => theme.stylekitBackgroundColor}; -` - -export const StyledTextView = styled.Text` - padding-top: 10px; - color: ${({ theme }) => theme.stylekitForegroundColor}; - padding-left: ${({ theme }) => theme.paddingLeft - (Platform.OS === 'ios' ? 5 : 0)}px; - padding-right: ${({ theme }) => theme.paddingLeft - (Platform.OS === 'ios' ? 5 : 0)}px; - /* padding-bottom: 10px; */ - ${Platform.OS === 'ios' && - css` - font-size: 17px; - `} - background-color: ${({ theme }) => theme.stylekitBackgroundColor}; - /* ${Platform.OS === 'ios' && 'padding-bottom: 10px'}; */ -` - -export const TextContainer = styled.ScrollView`` - -export const TitleContainer = styled.View` - border-bottom-color: ${({ theme }) => theme.stylekitBorderColor}; - border-bottom-width: 1px; - align-content: center; - justify-content: center; - height: ${NOTE_TITLE_HEIGHT}px; - padding-top: ${Platform.OS === 'ios' ? 5 : 12}px; - padding-left: ${PADDING}px; - padding-right: ${PADDING}px; -` - -export const Title = styled.Text` - font-weight: 600; - font-size: 16px; - color: ${({ theme }) => theme.stylekitForegroundColor}; -` diff --git a/packages/mobile/src/Screens/NoteHistory/NoteHistoryPreview.tsx b/packages/mobile/src/Screens/NoteHistory/NoteHistoryPreview.tsx deleted file mode 100644 index 88652b364..000000000 --- a/packages/mobile/src/Screens/NoteHistory/NoteHistoryPreview.tsx +++ /dev/null @@ -1,131 +0,0 @@ -import { ApplicationContext } from '@Root/ApplicationContext' -import { IoniconsHeaderButton } from '@Root/Components/IoniconsHeaderButton' -import { HistoryStackNavigationProp } from '@Root/HistoryStack' -import { SCREEN_COMPOSE, SCREEN_NOTES, SCREEN_NOTE_HISTORY_PREVIEW } from '@Root/Screens/screens' -import { ButtonType, PayloadEmitSource, SNNote } from '@standardnotes/snjs' -import { useCustomActionSheet } from '@Style/CustomActionSheet' -import { ELIPSIS } from '@Style/Icons' -import { ThemeService } from '@Style/ThemeService' -import React, { useCallback, useContext, useLayoutEffect } from 'react' -import { LogBox } from 'react-native' -import { HeaderButtons, Item } from 'react-navigation-header-buttons' -import { Container, StyledTextView, TextContainer, Title, TitleContainer } from './NoteHistoryPreview.styled' - -LogBox.ignoreLogs(['Non-serializable values were found in the navigation state']) - -type Props = HistoryStackNavigationProp -export const NoteHistoryPreview = ({ - navigation, - route: { - params: { revision, title, originalNoteUuid }, - }, -}: Props) => { - // Context - const application = useContext(ApplicationContext) - const { showActionSheet } = useCustomActionSheet() - - // State - - const restore = useCallback( - async (asCopy: boolean) => { - const originalNote = application!.items.findSureItem(originalNoteUuid) - - const run = async () => { - if (asCopy) { - await application?.mutator.duplicateItem(originalNote!, { - ...revision.payload.content, - title: revision.payload.content.title ? revision.payload.content.title + ' (copy)' : undefined, - }) - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - navigation.navigate(SCREEN_NOTES) - } else { - await application?.mutator.changeAndSaveItem( - originalNote, - (mutator) => { - mutator.setCustomContent(revision.payload.content) - }, - true, - PayloadEmitSource.RemoteRetrieved, - ) - if (application?.getAppState().isTabletDevice) { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - navigation.navigate(SCREEN_NOTES) - } else { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - navigation.navigate(SCREEN_COMPOSE) - } - } - } - - if (!asCopy) { - if (originalNote.locked) { - void application?.alertService.alert( - "This note has editing disabled. If you'd like to restore it to a previous revision, enable editing and try again.", - ) - return - } - const confirmed = await application?.alertService?.confirm( - "Are you sure you want to replace the current note's contents with what you see in this preview?", - 'Restore note', - 'Restore', - ButtonType.Info, - ) - if (confirmed) { - void run() - } - } else { - void run() - } - }, - [application, navigation, originalNoteUuid, revision.payload.content], - ) - - const onPress = useCallback(() => { - showActionSheet({ - title: title!, - options: [ - { - text: 'Restore', - callback: () => restore(false), - }, - { - text: 'Restore as copy', - callback: async () => restore(true), - }, - ], - }) - }, [showActionSheet, title, restore]) - - useLayoutEffect(() => { - navigation.setOptions({ - headerRight: () => ( - - - - ), - }) - }, [navigation, onPress]) - - return ( - - - {revision.payload.content.title} - - - - {revision.payload.content.text} - - - ) -} diff --git a/packages/mobile/src/Screens/NoteHistory/RemoteHistory.tsx b/packages/mobile/src/Screens/NoteHistory/RemoteHistory.tsx deleted file mode 100644 index 429bf436a..000000000 --- a/packages/mobile/src/Screens/NoteHistory/RemoteHistory.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import { ApplicationContext } from '@Root/ApplicationContext' -import { LoadingContainer, LoadingText } from '@Root/Screens/Notes/NoteList.styled' -import { NoteHistoryEntry, RevisionListEntry, SNNote } from '@standardnotes/snjs' -import React, { useCallback, useContext, useEffect, useState } from 'react' -import { FlatList, ListRenderItem } from 'react-native' -import { useSafeAreaInsets } from 'react-native-safe-area-context' -import { NoteHistoryCell } from './NoteHistoryCell' - -type Props = { - note: SNNote - onPress: (uuid: string, revision: NoteHistoryEntry, title: string) => void -} -export const RemoteHistory: React.FC = ({ note, onPress }) => { - // Context - const application = useContext(ApplicationContext) - const insets = useSafeAreaInsets() - - // State - const [remoteHistoryList, setRemoteHistoryList] = useState() - const [fetchingRemoteHistory, setFetchingRemoteHistory] = useState(false) - - useEffect(() => { - let isMounted = true - - const fetchRemoteHistoryList = async () => { - if (note) { - setFetchingRemoteHistory(true) - const newRemoteHistory = await application?.historyManager?.remoteHistoryForItem(note) - if (isMounted) { - setFetchingRemoteHistory(false) - setRemoteHistoryList(newRemoteHistory) - } - } - } - void fetchRemoteHistoryList() - - return () => { - isMounted = false - } - }, [application?.historyManager, note]) - - const onItemPress = useCallback( - async (item: RevisionListEntry) => { - const remoteRevision = await application?.historyManager!.fetchRemoteRevision(note, item) - if (remoteRevision) { - onPress(item.uuid, remoteRevision as NoteHistoryEntry, new Date(item.updated_at).toLocaleString()) - } else { - void application?.alertService!.alert( - 'The remote revision could not be loaded. Please try again later.', - 'Error', - ) - return - } - }, - [application?.alertService, application?.historyManager, note, onPress], - ) - - const renderItem: ListRenderItem | null | undefined = ({ item }) => { - return onItemPress(item)} title={new Date(item.updated_at).toLocaleString()} /> - } - - if (fetchingRemoteHistory || !remoteHistoryList || (remoteHistoryList && remoteHistoryList.length === 0)) { - const placeholderText = fetchingRemoteHistory ? 'Loading entries...' : 'No entries.' - return ( - - {placeholderText} - - ) - } - - return ( - - keyExtractor={(item) => item.uuid} - contentContainerStyle={{ paddingBottom: insets.bottom }} - initialNumToRender={10} - windowSize={10} - keyboardShouldPersistTaps={'never'} - data={remoteHistoryList} - renderItem={renderItem} - /> - ) -} diff --git a/packages/mobile/src/Screens/NoteHistory/SessionHistory.tsx b/packages/mobile/src/Screens/NoteHistory/SessionHistory.tsx deleted file mode 100644 index 9abab51ee..000000000 --- a/packages/mobile/src/Screens/NoteHistory/SessionHistory.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { ApplicationContext } from '@Root/ApplicationContext' -import { HistoryEntry, NoteHistoryEntry, SNNote } from '@standardnotes/snjs' -import React, { useCallback, useContext, useEffect, useState } from 'react' -import { FlatList, ListRenderItem } from 'react-native' -import { useSafeAreaInsets } from 'react-native-safe-area-context' -import { NoteHistoryCell } from './NoteHistoryCell' - -type Props = { - note: SNNote - onPress: (uuid: string, revision: NoteHistoryEntry, title: string) => void -} -export const SessionHistory: React.FC = ({ note, onPress }) => { - // Context - const application = useContext(ApplicationContext) - const insets = useSafeAreaInsets() - - // State - const [sessionHistory, setSessionHistory] = useState() - - useEffect(() => { - if (note) { - setSessionHistory(application?.historyManager?.sessionHistoryForItem(note)) - } - }, [application?.historyManager, note]) - - const onItemPress = useCallback( - (item: NoteHistoryEntry) => { - onPress(item.payload.uuid, item, item.previewTitle()) - }, - [onPress], - ) - - const RenderItem: ListRenderItem | null | undefined = ({ item }) => { - return ( - onItemPress(item)} - title={item.previewTitle()} - subTitle={item.previewSubTitle()} - /> - ) - } - - return ( - - keyExtractor={(item) => item.previewTitle()} - contentContainerStyle={{ paddingBottom: insets.bottom }} - initialNumToRender={10} - windowSize={10} - keyboardShouldPersistTaps={'never'} - data={sessionHistory as NoteHistoryEntry[]} - renderItem={RenderItem} - /> - ) -} diff --git a/packages/mobile/src/Screens/Notes/NoteCell.styled.ts b/packages/mobile/src/Screens/Notes/NoteCell.styled.ts deleted file mode 100644 index ff598ce17..000000000 --- a/packages/mobile/src/Screens/Notes/NoteCell.styled.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { hexToRGBA } from '@Style/Utils' -import { StyleSheet } from 'react-native' -import styled from 'styled-components/native' - -export const TouchableContainer = styled.TouchableWithoutFeedback`` -export const Container = styled.View<{ selected: boolean; distance: number }>` - display: flex; - flex-direction: row; - align-items: flex-start; - justify-content: space-between; - padding: ${(props) => props.distance}px 0 0 ${(props) => props.distance}px; - background-color: ${({ theme, selected }) => { - return selected ? theme.stylekitInfoColor : theme.stylekitBackgroundColor - }}; -` -export const NoteDataContainer = styled.View<{ distance: number }>` - border-bottom-color: ${({ theme }) => hexToRGBA(theme.stylekitBorderColor, 0.75)}; - border-bottom-width: 1px; - padding-bottom: ${(props) => props.distance}px; - flex-grow: 1; - flex-shrink: 1; - padding-right: ${(props) => props.distance}px; -` -export const DeletedText = styled.Text` - color: ${({ theme }) => theme.stylekitInfoColor}; - margin-bottom: 5px; -` -export const NoteText = styled.Text<{ selected: boolean }>` - font-size: 15px; - color: ${({ theme, selected }) => { - return selected ? theme.stylekitInfoContrastColor : theme.stylekitForegroundColor - }}; - opacity: 0.8; - line-height: 19px; -` -export const TitleText = styled.Text<{ selected: boolean }>` - font-weight: bold; - font-size: 16px; - color: ${({ theme, selected }) => { - return selected ? theme.stylekitInfoContrastColor : theme.stylekitForegroundColor - }}; - flex-grow: 1; - flex-shrink: 1; - margin-bottom: 4px; -` -export const TagsContainter = styled.View` - flex: 1; - flex-direction: row; - margin-top: 7px; -` -export const TagText = styled.Text<{ selected: boolean }>` - margin-right: 2px; - font-size: 12px; - color: ${({ theme, selected }) => { - return selected ? theme.stylekitInfoContrastColor : theme.stylekitForegroundColor - }}; - opacity: ${(props) => (props.selected ? 0.8 : 0.5)}; -` -export const DetailsText = styled(TagText)` - margin-right: 0; - margin-top: 5px; -` -export const FlexContainer = styled.View` - display: flex; - flex-direction: row; - justify-content: space-between; -` -export const NoteContentsContainer = styled.View` - display: flex; - flex-shrink: 1; -` -export const styles = StyleSheet.create({ - editorIcon: { - marginTop: 2, - marginRight: 10, - width: 16, - height: 16, - }, -}) diff --git a/packages/mobile/src/Screens/Notes/NoteCell.tsx b/packages/mobile/src/Screens/Notes/NoteCell.tsx deleted file mode 100644 index 6de1e5738..000000000 --- a/packages/mobile/src/Screens/Notes/NoteCell.tsx +++ /dev/null @@ -1,241 +0,0 @@ -import { useChangeNote, useDeleteNoteWithPrivileges, useProtectOrUnprotectNote } from '@Lib/SnjsHelperHooks' -import { ApplicationContext } from '@Root/ApplicationContext' -import { SnIcon } from '@Root/Components/SnIcon' -import { NoteCellIconFlags } from '@Root/Screens/Notes/NoteCellIconFlags' -import { CollectionSort, CollectionSortProperty, IconType, isNullOrUndefined, SNNote } from '@standardnotes/snjs' -import { CustomActionSheetOption, useCustomActionSheet } from '@Style/CustomActionSheet' -import { getTintColorForEditor } from '@Style/Utils' -import React, { useContext, useRef, useState } from 'react' -import { Text, View } from 'react-native' -import { ThemeContext } from 'styled-components' -import { - Container, - DetailsText, - FlexContainer, - NoteContentsContainer, - NoteDataContainer, - NoteText, - styles, - TitleText, - TouchableContainer, -} from './NoteCell.styled' -import { NoteCellFlags } from './NoteCellFlags' - -type Props = { - note: SNNote - highlighted?: boolean - onPressItem: (noteUuid: SNNote['uuid']) => void - hideDates: boolean - hidePreviews: boolean - hideEditorIcon: boolean - sortType: CollectionSortProperty -} - -export const NoteCell = ({ - note, - onPressItem, - highlighted, - sortType, - hideDates, - hidePreviews, - hideEditorIcon, -}: Props) => { - // Context - const application = useContext(ApplicationContext) - const theme = useContext(ThemeContext) - - const [changeNote] = useChangeNote(note) - const [protectOrUnprotectNote] = useProtectOrUnprotectNote(note) - - // State - const [selected, setSelected] = useState(false) - - // Ref - const selectionTimeout = useRef>() - const elementRef = useRef(null) - - const { showActionSheet } = useCustomActionSheet() - - const [deleteNote] = useDeleteNoteWithPrivileges( - note, - async () => { - await application?.mutator.deleteItem(note) - }, - () => { - void changeNote((mutator) => { - mutator.trashed = true - }, false) - }, - undefined, - ) - - const highlight = Boolean(selected || highlighted) - - const _onPress = () => { - setSelected(true) - selectionTimeout.current = setTimeout(() => { - setSelected(false) - onPressItem(note.uuid) - }, 25) - } - - const _onPressIn = () => { - setSelected(true) - } - - const _onPressOut = () => { - setSelected(false) - } - - const onLongPress = () => { - if (note.protected) { - showActionSheet({ - title: note.title, - options: [ - { - text: 'Note Protected', - }, - ], - anchor: elementRef.current ?? undefined, - }) - } else { - let options: CustomActionSheetOption[] = [] - - options.push({ - text: note.pinned ? 'Unpin' : 'Pin', - key: 'pin', - callback: () => - changeNote((mutator) => { - mutator.pinned = !note.pinned - }, false), - }) - - options.push({ - text: note.archived ? 'Unarchive' : 'Archive', - key: 'archive', - callback: () => { - if (note.locked) { - void application?.alertService.alert( - `This note has editing disabled. If you'd like to ${ - note.archived ? 'unarchive' : 'archive' - } it, enable editing on it, and try again.`, - ) - return - } - - void changeNote((mutator) => { - mutator.archived = !note.archived - }, false) - }, - }) - - options.push({ - text: note.locked ? 'Enable editing' : 'Prevent editing', - key: 'lock', - callback: () => - changeNote((mutator) => { - mutator.locked = !note.locked - }, false), - }) - - options.push({ - text: note.protected ? 'Unprotect' : 'Protect', - key: 'protect', - callback: async () => await protectOrUnprotectNote(), - }) - - if (!note.trashed) { - options.push({ - text: 'Move to Trash', - key: 'trash', - destructive: true, - callback: async () => deleteNote(false), - }) - } else { - options = options.concat([ - { - text: 'Restore', - key: 'restore-note', - callback: () => { - void changeNote((mutator) => { - mutator.trashed = false - }, false) - }, - }, - { - text: 'Delete permanently', - key: 'delete-forever', - destructive: true, - callback: async () => deleteNote(true), - }, - ]) - } - showActionSheet({ - title: note.title, - options, - anchor: elementRef.current ?? undefined, - }) - } - } - - const padding = 14 - const showPreview = !hidePreviews && !note.protected && !note.hidePreview - const hasPlainPreview = !isNullOrUndefined(note.preview_plain) && note.preview_plain.length > 0 - const showDetails = !hideDates || note.protected - - const editorForNote = application?.componentManager.editorForNote(note) - const [icon, tint] = application?.iconsController.getIconAndTintForNoteType( - editorForNote?.package_info.note_type, - ) as [IconType, number] - - return ( - - - {!hideEditorIcon && } - - - - - - {note.title.length > 0 ? {note.title} : } - {hasPlainPreview && showPreview && ( - - {note.preview_plain} - - )} - - {!hasPlainPreview && showPreview && note.text.length > 0 && ( - - {note.text} - - )} - - - - - {showDetails && ( - - {note.protected && ( - - Protected - {!hideDates && ' • '} - - )} - {!hideDates && ( - - {sortType === CollectionSort.UpdatedAt ? 'Modified ' + note.updatedAtString : note.createdAtString} - - )} - - )} - - - - ) -} diff --git a/packages/mobile/src/Screens/Notes/NoteCellFlags.tsx b/packages/mobile/src/Screens/Notes/NoteCellFlags.tsx deleted file mode 100644 index e69456559..000000000 --- a/packages/mobile/src/Screens/Notes/NoteCellFlags.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { SNNote } from '@standardnotes/snjs' -import React, { useContext } from 'react' -import { ThemeContext } from 'styled-components' -import styled from 'styled-components/native' - -type NoteFlag = { - text: string - color: string -} - -const FlagsContainer = styled.View` - flex-direction: row; - margin-bottom: 8px; -` -const FlagContainer = styled.View<{ color: string; selected: boolean }>` - background-color: ${({ theme, selected, color }) => { - return selected ? theme.stylekitInfoContrastColor : color - }}; - padding: 4px; - padding-left: 6px; - padding-right: 6px; - border-radius: 3px; - margin-right: 4px; -` -const FlagLabel = styled.Text<{ selected: boolean }>` - color: ${({ theme, selected }) => { - return selected ? theme.stylekitInfoColor : theme.stylekitInfoContrastColor - }}; - font-size: 10px; - font-weight: bold; -` - -export const NoteCellFlags = ({ note, highlight }: { note: SNNote; highlight: boolean }) => { - const theme = useContext(ThemeContext) - - const flags: NoteFlag[] = [] - - if (note.conflictOf) { - flags.push({ - text: 'Conflicted Copy', - color: theme.stylekitDangerColor, - }) - } - - return flags.length > 0 ? ( - - {flags.map((flag) => ( - - {flag.text} - - ))} - - ) : ( - <> - ) -} diff --git a/packages/mobile/src/Screens/Notes/NoteCellIconFlags.tsx b/packages/mobile/src/Screens/Notes/NoteCellIconFlags.tsx deleted file mode 100644 index f1cf7f80e..000000000 --- a/packages/mobile/src/Screens/Notes/NoteCellIconFlags.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { SnIcon } from '@Root/Components/SnIcon' -import { IconType, SNNote } from '@standardnotes/snjs' -import React, { useContext } from 'react' -import { ThemeContext } from 'styled-components' -import styled from 'styled-components/native' - -const FlagIconsContainer = styled.View` - display: flex; - flex-direction: row; - justify-content: flex-start; - margin-top: 2px; -` -type Props = { - note: SNNote -} - -type TFlagIcon = { - icon: IconType - fillColor?: string -} - -export const NoteCellIconFlags = ({ note }: Props) => { - const theme = useContext(ThemeContext) - const { stylekitCorn, stylekitDangerColor, stylekitInfoColor } = theme - - const flagIcons = [] as TFlagIcon[] - - if (note.archived) { - flagIcons.push({ - icon: 'archive', - fillColor: stylekitCorn, - }) - } - if (note.locked) { - flagIcons.push({ - icon: 'pencil-off', - fillColor: stylekitInfoColor, - }) - } - if (note.trashed) { - flagIcons.push({ - icon: 'trash-filled', - fillColor: stylekitDangerColor, - }) - } - if (note.pinned) { - flagIcons.push({ - icon: 'pin-filled', - fillColor: stylekitInfoColor, - }) - } - return flagIcons.length ? ( - - {flagIcons.map((flagIcon, index) => ( - - ))} - - ) : null -} diff --git a/packages/mobile/src/Screens/Notes/NoteList.styled.ts b/packages/mobile/src/Screens/Notes/NoteList.styled.ts deleted file mode 100644 index 12efbf3ad..000000000 --- a/packages/mobile/src/Screens/Notes/NoteList.styled.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { Platform, StyleSheet } from 'react-native' -import styled, { css } from 'styled-components/native' - -// no support for generic types in Flatlist -export const styles = StyleSheet.create({ - list: { - height: '100%', - }, - inputStyle: { - height: 30, - }, - androidSearch: { - height: 30, - }, -}) - -export const Container = styled.View` - background-color: ${(props) => props.theme.stylekitBackgroundColor}; - flex: 1; -` - -export const LoadingContainer = styled.View` - flex: 1; - align-items: center; - justify-content: center; -` - -interface LoadingTextProps { - textAlign?: 'left' | 'center' | 'right' | 'justify' -} - -export const LoadingText = styled.Text` - position: absolute; - opacity: 0.5; - color: ${(props) => props.theme.stylekitForegroundColor}; - text-align: ${(props) => props.textAlign ?? 'left'}; -` - -export const HeaderContainer = styled.View` - padding-top: 3px; - padding-left: 5px; - padding-right: 5px; -` - -export const SearchBarContainer = styled.View` - background-color: ${(props) => props.theme.stylekitBackgroundColor}; - z-index: 2; -` - -export const SearchOptionsContainer = styled.ScrollView` - display: flex; - flex-direction: row; - margin-left: 8px; - margin-bottom: 12px; - ${() => - Platform.OS === 'android' && - css` - padding-top: 4px; - `} -` diff --git a/packages/mobile/src/Screens/Notes/NoteList.tsx b/packages/mobile/src/Screens/Notes/NoteList.tsx deleted file mode 100644 index f699b36e3..000000000 --- a/packages/mobile/src/Screens/Notes/NoteList.tsx +++ /dev/null @@ -1,257 +0,0 @@ -import { AppStateEventType, AppStateType } from '@Lib/ApplicationState' -import { useSignedIn } from '@Lib/SnjsHelperHooks' -import { useFocusEffect, useNavigation } from '@react-navigation/native' -import { ApplicationContext } from '@Root/ApplicationContext' -import { AppStackNavigationProp } from '@Root/AppStack' -import { Chip } from '@Root/Components/Chip' -import { SearchBar } from '@Root/Components/SearchBar' -import { SCREEN_NOTES } from '@Root/Screens/screens' -import { CollectionSortProperty, SNNote } from '@standardnotes/snjs' -import React, { Dispatch, SetStateAction, useCallback, useContext, useEffect, useRef, useState } from 'react' -import { Animated, FlatList, ListRenderItem, RefreshControl } from 'react-native' -import { useSafeAreaInsets } from 'react-native-safe-area-context' -import IosSearchBar from 'react-native-search-bar' -import AndroidSearchBar from 'react-native-search-box' -import { ThemeContext } from 'styled-components' -import { NoteCell } from './NoteCell' -import { - Container, - HeaderContainer, - LoadingContainer, - LoadingText, - SearchBarContainer, - SearchOptionsContainer, - styles, -} from './NoteList.styled' -import { OfflineBanner } from './OfflineBanner' - -type Props = { - onSearchChange: (text: string) => void - onSearchCancel: () => void - searchText: string - searchOptions: { - selected: boolean - onPress: () => void - label: string - }[] - onPressItem: (noteUuid: SNNote['uuid']) => void - selectedNoteId: string | undefined - sortType: CollectionSortProperty - hideDates: boolean - hidePreviews: boolean - hideEditorIcon: boolean - decrypting: boolean - loading: boolean - hasRefreshControl: boolean - notes: SNNote[] - refreshing: boolean - onRefresh: () => void - shouldFocusSearch: boolean - setShouldFocusSearch: Dispatch> -} - -export const NoteList = (props: Props) => { - // Context - const [signedIn] = useSignedIn() - const application = useContext(ApplicationContext) - const theme = useContext(ThemeContext) - const insets = useSafeAreaInsets() - - const [collapseSearchBarOnBlur, setCollapseSearchBarOnBlur] = useState(true) - const [noteListScrolled, setNoteListScrolled] = useState(false) - - // Ref - const opacityAnimationValue = useRef(new Animated.Value(0)).current - const marginTopAnimationValue = useRef(new Animated.Value(-40)).current - const iosSearchBarInputRef = useRef(null) - const androidSearchBarInputRef = useRef(null) - const noteListRef = useRef(null) - - const navigation = useNavigation['navigation']>() - - const dismissKeyboard = () => { - iosSearchBarInputRef.current?.blur() - } - - useEffect(() => { - const removeBlurScreenListener = navigation.addListener('blur', () => { - setCollapseSearchBarOnBlur(false) - }) - - return removeBlurScreenListener - }) - - useEffect(() => { - const unsubscribeStateEventObserver = application?.getAppState().addStateEventObserver((state) => { - if (state === AppStateEventType.DrawerOpen) { - dismissKeyboard() - } - }) - - return unsubscribeStateEventObserver - }, [application]) - - const scrollListToTop = useCallback(() => { - if (noteListScrolled && props.notes && props.notes.length > 0) { - noteListRef.current?.scrollToIndex({ animated: false, index: 0 }) - setNoteListScrolled(false) - } - }, [noteListScrolled, props.notes]) - - useEffect(() => { - const unsubscribeTagChangedEventObserver = application?.getAppState().addStateChangeObserver((event) => { - if (event === AppStateType.TagChanged) { - scrollListToTop() - } - }) - - return unsubscribeTagChangedEventObserver - }, [application, scrollListToTop]) - - const { shouldFocusSearch, searchText } = props - - const focusSearch = useCallback(() => { - setCollapseSearchBarOnBlur(true) - - if (shouldFocusSearch) { - iosSearchBarInputRef.current?.focus() - androidSearchBarInputRef.current?.focus(searchText) - } - }, [shouldFocusSearch, searchText]) - - useFocusEffect(focusSearch) - - useFocusEffect( - useCallback(() => { - return dismissKeyboard - }, []), - ) - - const onChangeSearchText = (text: string) => { - props.onSearchChange(text) - scrollListToTop() - } - - const toggleSearchOptions = (showOptions: boolean) => { - Animated.parallel([ - Animated.timing(opacityAnimationValue, { - toValue: showOptions ? 1 : 0, - duration: 200, - useNativeDriver: false, - }), - Animated.timing(marginTopAnimationValue, { - toValue: showOptions ? 0 : -40, - duration: 200, - useNativeDriver: false, - }), - ]).start() - } - - const onSearchFocus = () => { - toggleSearchOptions(true) - props.setShouldFocusSearch(false) - } - - const onSearchBlur = () => { - toggleSearchOptions(false) - } - - const onScroll = () => { - setNoteListScrolled(true) - } - - const renderItem: ListRenderItem | null | undefined = ({ item }) => { - if (!item) { - return null - } - - return ( - - ) - } - let placeholderText = '' - if (props.decrypting) { - placeholderText = 'Decrypting notes...' - } else if (props.loading) { - placeholderText = 'Loading notes...' - } else if (props.notes.length === 0) { - placeholderText = 'No notes.' - } - return ( - - - - - - - {props.searchOptions.map(({ selected, onPress, label }, index) => ( - - ))} - - - item?.uuid || String(new Date().getTime())} - contentContainerStyle={[{ paddingBottom: insets.bottom }, props.notes.length > 0 ? {} : { height: '100%' }]} - initialNumToRender={6} - windowSize={6} - maxToRenderPerBatch={6} - ListEmptyComponent={() => { - return placeholderText.length > 0 ? ( - - {placeholderText} - - ) : null - }} - keyboardDismissMode={'interactive'} - keyboardShouldPersistTaps={'never'} - refreshControl={ - !props.hasRefreshControl ? undefined : ( - - ) - } - data={props.notes} - renderItem={renderItem} - extraData={signedIn} - ListHeaderComponent={() => {!signedIn && }} - onScroll={onScroll} - /> - - ) -} diff --git a/packages/mobile/src/Screens/Notes/Notes.styled.ts b/packages/mobile/src/Screens/Notes/Notes.styled.ts deleted file mode 100644 index 6d1aa7c9d..000000000 --- a/packages/mobile/src/Screens/Notes/Notes.styled.ts +++ /dev/null @@ -1,7 +0,0 @@ -import Icon from 'react-native-vector-icons/Ionicons' -import styled from 'styled-components/native' - -export const StyledIcon = styled(Icon)` - text-align-vertical: center; - margin-left: 2px; -` diff --git a/packages/mobile/src/Screens/Notes/Notes.tsx b/packages/mobile/src/Screens/Notes/Notes.tsx deleted file mode 100644 index e09da0121..000000000 --- a/packages/mobile/src/Screens/Notes/Notes.tsx +++ /dev/null @@ -1,543 +0,0 @@ -import { AppStateType } from '@Lib/ApplicationState' -import { useSignedIn, useSyncStatus } from '@Lib/SnjsHelperHooks' -import { useFocusEffect, useNavigation } from '@react-navigation/native' -import { AppStackNavigationProp } from '@Root/AppStack' -import { useSafeApplicationContext } from '@Root/Hooks/useSafeApplicationContext' -import { SCREEN_COMPOSE, SCREEN_NOTES, SCREEN_VIEW_PROTECTED_NOTE } from '@Root/Screens/screens' -import { - ApplicationEvent, - CollectionSort, - CollectionSortProperty, - ContentType, - PrefKey, - SmartView, - SNNote, - SNTag, - SystemViewId, - UuidString, -} from '@standardnotes/snjs' -import { ICON_ADD } from '@Style/Icons' -import { ThemeService } from '@Style/ThemeService' -import React, { useCallback, useContext, useEffect, useRef, useState } from 'react' -import FAB from 'react-native-fab' -import { ThemeContext } from 'styled-components' -import { NoteList } from './NoteList' -import { StyledIcon } from './Notes.styled' - -type SearchOptions = { - selected: boolean - onPress: () => void - label: string -}[] - -export const Notes = React.memo( - ({ isInTabletMode, keyboardHeight }: { isInTabletMode: boolean | undefined; keyboardHeight: number | undefined }) => { - const application = useSafeApplicationContext() - const theme = useContext(ThemeContext) - const navigation = useNavigation['navigation']>() - - const [loading, decrypting, refreshing, startRefreshing] = useSyncStatus() - const [signedIn] = useSignedIn() - - const [sortBy, setSortBy] = useState(() => - application.getLocalPreferences().getValue(PrefKey.MobileSortNotesBy, CollectionSort.CreatedAt), - ) - const [sortReverse, setSortReverse] = useState(() => - application.getLocalPreferences().getValue(PrefKey.MobileSortNotesReverse, false), - ) - const [hideDates, setHideDates] = useState(() => - application.getLocalPreferences().getValue(PrefKey.MobileNotesHideDate, false), - ) - const [hidePreviews, setHidePreviews] = useState(() => - application.getLocalPreferences().getValue(PrefKey.MobileNotesHideNotePreview, false), - ) - const [hideEditorIcon, setHideEditorIcon] = useState(() => - application.getLocalPreferences().getValue(PrefKey.MobileNotesHideEditorIcon, false), - ) - const [notes, setNotes] = useState([]) - const [selectedNoteId, setSelectedNoteId] = useState() - const [searchText, setSearchText] = useState('') - const [searchOptions, setSearchOptions] = useState([]) - const [includeProtectedNoteText, setIncludeProtectedNoteText] = useState( - () => !(application.hasProtectionSources() && !application.hasUnprotectedAccessSession()), - ) - const [includeArchivedNotes, setIncludeArchivedNotes] = useState(false) - const [includeTrashedNotes, setIncludeTrashedNotes] = useState(false) - const [includeProtectedStarted, setIncludeProtectedStarted] = useState(false) - const [shouldFocusSearch, setShouldFocusSearch] = useState(false) - - const haveDisplayOptions = useRef(false) - const protectionsEnabled = useRef(application.hasProtectionSources() && !application.hasUnprotectedAccessSession()) - - const reloadTitle = useCallback( - (newNotes?: SNNote[], newFilter?: string) => { - let title = '' - let subTitle: string | undefined - - const selectedTag = application.getAppState().selectedTag - - if (newNotes && (newFilter ?? searchText).length > 0) { - const resultCount = newNotes.length - title = resultCount === 1 ? `${resultCount} search result` : `${resultCount} search results` - } else if (selectedTag) { - title = selectedTag.title - if (selectedTag instanceof SNTag && selectedTag.parentId) { - const parents = application.items.getTagParentChain(selectedTag) - const hierarchy = parents.map((tag) => tag.title).join(' ⫽ ') - subTitle = hierarchy.length > 0 ? `in ${hierarchy}` : undefined - } - } - - navigation.setParams({ - title, - subTitle, - }) - }, - [application, navigation, searchText], - ) - - const openCompose = useCallback( - (newNote: boolean, noteUuid: UuidString, replaceScreen = false) => { - if (!isInTabletMode) { - if (replaceScreen) { - navigation.replace(SCREEN_COMPOSE, { - title: newNote ? 'Compose' : 'Note', - noteUuid, - }) - } else { - navigation.navigate(SCREEN_COMPOSE, { - title: newNote ? 'Compose' : 'Note', - noteUuid, - }) - } - } - }, - [navigation, isInTabletMode], - ) - - const openNote = useCallback( - async (noteUuid: SNNote['uuid'], replaceScreen = false) => { - await application.getAppState().openEditor(noteUuid) - openCompose(false, noteUuid, replaceScreen) - }, - [application, openCompose], - ) - - const onNoteSelect = useCallback( - async (noteUuid: SNNote['uuid']) => { - const note = application.items.findItem(noteUuid) - if (note) { - if (note.protected && !application.hasProtectionSources()) { - return navigation.navigate(SCREEN_VIEW_PROTECTED_NOTE, { - onPressView: () => openNote(noteUuid, true), - }) - } - if (await application.authorizeNoteAccess(note)) { - if (!isInTabletMode) { - await openNote(noteUuid) - } else { - /** - * @TODO: remove setTimeout after SNJS navigation feature - * https://app.asana.com/0/1201653402817596/1202360754617865 - */ - setTimeout(async () => { - await openNote(noteUuid) - }) - } - } - } - }, - [application, isInTabletMode, navigation, openNote], - ) - - useEffect(() => { - const removeBlurScreenListener = navigation.addListener('blur', () => { - if (includeProtectedStarted) { - setIncludeProtectedStarted(false) - setShouldFocusSearch(true) - } - }) - - return removeBlurScreenListener - }, [navigation, includeProtectedStarted]) - - useEffect(() => { - let mounted = true - const removeEditorObserver = application.editorGroup.addActiveControllerChangeObserver((activeEditor) => { - if (mounted) { - setSelectedNoteId(activeEditor?.item?.uuid) - } - }) - - return () => { - mounted = false - removeEditorObserver && removeEditorObserver() - } - }, [application]) - - /** - * Note that reloading display options destroys the current index and rebuilds it, - * so call sparingly. The runtime complexity of destroying and building - * an index is roughly O(n^2). - * There are optional parameters to force using the new values, - * use when React is too slow when updating the state. - */ - const reloadNotesDisplayOptions = useCallback( - ( - searchFilter?: string, - sortOptions?: { - sortBy?: CollectionSortProperty - sortReverse: boolean - }, - includeProtected?: boolean, - includeArchived?: boolean, - includeTrashed?: boolean, - ) => { - const tag = application.getAppState().selectedTag - const searchQuery = - searchText || searchFilter - ? { - query: searchFilter?.toLowerCase() ?? searchText.toLowerCase(), - includeProtectedNoteText: includeProtected ?? includeProtectedNoteText, - } - : undefined - - let applyFilters = false - if (typeof searchFilter !== 'undefined') { - applyFilters = searchFilter !== '' - } else if (typeof searchText !== 'undefined') { - applyFilters = searchText !== '' - } - - application.items.setPrimaryItemDisplayOptions({ - sortBy: sortOptions?.sortBy ?? sortBy, - sortDirection: sortOptions?.sortReverse ?? sortReverse ? 'asc' : 'dsc', - tags: tag instanceof SNTag ? [tag] : [], - views: tag instanceof SmartView ? [tag] : [], - searchQuery: searchQuery, - includeArchived: applyFilters && (includeArchived ?? includeArchivedNotes), - includeTrashed: applyFilters && (includeTrashed ?? includeTrashedNotes), - }) - }, - [ - application, - includeArchivedNotes, - includeProtectedNoteText, - includeTrashedNotes, - sortBy, - sortReverse, - searchText, - ], - ) - - const toggleIncludeProtected = useCallback(async () => { - const includeProtected = !includeProtectedNoteText - let allowToggling: boolean | undefined = true - - if (includeProtected) { - setIncludeProtectedStarted(true) - allowToggling = await application.authorizeSearchingProtectedNotesText() - } - - setIncludeProtectedStarted(false) - - if (allowToggling) { - reloadNotesDisplayOptions(undefined, undefined, includeProtected) - setIncludeProtectedNoteText(includeProtected) - } - }, [application, includeProtectedNoteText, reloadNotesDisplayOptions]) - - const toggleIncludeArchived = useCallback(() => { - const includeArchived = !includeArchivedNotes - reloadNotesDisplayOptions(undefined, undefined, undefined, includeArchived) - setIncludeArchivedNotes(includeArchived) - }, [includeArchivedNotes, reloadNotesDisplayOptions]) - - const toggleIncludeTrashed = useCallback(() => { - const includeTrashed = !includeTrashedNotes - reloadNotesDisplayOptions(undefined, undefined, undefined, undefined, includeTrashed) - setIncludeTrashedNotes(includeTrashed) - }, [includeTrashedNotes, reloadNotesDisplayOptions]) - - const reloadSearchOptions = useCallback(() => { - const protections = application.hasProtectionSources() && !application.hasUnprotectedAccessSession() - - if (protections !== protectionsEnabled.current) { - protectionsEnabled.current = !!protections - setIncludeProtectedNoteText(!protections) - } - - const selectedTag = application.getAppState().selectedTag - const options = [ - { - label: 'Include Protected Contents', - selected: includeProtectedNoteText, - onPress: toggleIncludeProtected, - }, - ] - - const isArchiveView = selectedTag instanceof SmartView && selectedTag.uuid === SystemViewId.ArchivedNotes - const isTrashView = selectedTag instanceof SmartView && selectedTag.uuid === SystemViewId.TrashedNotes - if (!isArchiveView && !isTrashView) { - setSearchOptions([ - ...options, - { - label: 'Archived', - selected: includeArchivedNotes, - onPress: toggleIncludeArchived, - }, - { - label: 'Trashed', - selected: includeTrashedNotes, - onPress: toggleIncludeTrashed, - }, - ]) - } else { - setSearchOptions(options) - } - }, [ - application, - includeProtectedNoteText, - includeArchivedNotes, - includeTrashedNotes, - toggleIncludeProtected, - toggleIncludeArchived, - toggleIncludeTrashed, - ]) - - const getFirstSelectableNote = useCallback((newNotes: SNNote[]) => newNotes.find((note) => !note.protected), []) - - const selectFirstNote = useCallback( - (newNotes: SNNote[]) => { - const note = getFirstSelectableNote(newNotes) - if (note && !loading && !decrypting) { - void onNoteSelect(note.uuid) - } - }, - [decrypting, getFirstSelectableNote, loading, onNoteSelect], - ) - - const selectNextOrCreateNew = useCallback( - (newNotes: SNNote[]) => { - const note = getFirstSelectableNote(newNotes) - if (note) { - void onNoteSelect(note.uuid) - } else { - application.getAppState().closeActiveEditor() - } - }, - [application, getFirstSelectableNote, onNoteSelect], - ) - - const reloadNotes = useCallback( - (reselectNote?: boolean, tagChanged?: boolean, searchFilter?: string) => { - const tag = application.getAppState().selectedTag - - if (!tag) { - return - } - - reloadSearchOptions() - - if (!haveDisplayOptions.current) { - haveDisplayOptions.current = true - reloadNotesDisplayOptions() - } - - const newNotes = application.items.getDisplayableNotes() - const renderedNotes: SNNote[] = newNotes - - setNotes(renderedNotes) - reloadTitle(renderedNotes, searchFilter) - - if (!application.getAppState().isTabletDevice || !reselectNote) { - return - } - - if (tagChanged) { - if (renderedNotes.length > 0) { - selectFirstNote(renderedNotes) - } else { - application.getAppState().closeActiveEditor() - } - } else { - const activeNote = application.getAppState().getActiveNoteController()?.item - - if (activeNote) { - const isTrashView = - application.getAppState().selectedTag instanceof SmartView && - application.getAppState().selectedTag.uuid === SystemViewId.TrashedNotes - - if (activeNote.trashed && !isTrashView) { - selectNextOrCreateNew(renderedNotes) - } - } else { - selectFirstNote(renderedNotes) - } - } - }, - [ - application, - reloadNotesDisplayOptions, - reloadSearchOptions, - reloadTitle, - selectFirstNote, - selectNextOrCreateNew, - ], - ) - - const onNoteCreate = useCallback(async () => { - const title = application.getAppState().isTabletDevice ? `Note ${notes.length + 1}` : undefined - const noteView = await application.getAppState().createEditor(title) - openCompose(true, noteView.item.uuid) - reloadNotes(true) - }, [application, notes.length, openCompose, reloadNotes]) - - const reloadPreferences = useCallback(async () => { - let newSortBy = application.getLocalPreferences().getValue(PrefKey.MobileSortNotesBy, CollectionSort.CreatedAt) - - if (newSortBy === CollectionSort.UpdatedAt || (newSortBy as string) === 'client_updated_at') { - newSortBy = CollectionSort.UpdatedAt - } - let displayOptionsChanged = false - const newSortReverse = application.getLocalPreferences().getValue(PrefKey.MobileSortNotesReverse, false) - const newHidePreview = application.getLocalPreferences().getValue(PrefKey.MobileNotesHideNotePreview, false) - const newHideDate = application.getLocalPreferences().getValue(PrefKey.MobileNotesHideDate, false) - const newHideEditorIcon = application.getLocalPreferences().getValue(PrefKey.MobileNotesHideEditorIcon, false) - - if (sortBy !== newSortBy) { - setSortBy(newSortBy) - displayOptionsChanged = true - } - if (sortReverse !== newSortReverse) { - setSortReverse(newSortReverse) - displayOptionsChanged = true - } - if (hidePreviews !== newHidePreview) { - setHidePreviews(newHidePreview) - displayOptionsChanged = true - } - if (hideDates !== newHideDate) { - setHideDates(newHideDate) - displayOptionsChanged = true - } - if (hideEditorIcon !== newHideEditorIcon) { - setHideEditorIcon(newHideEditorIcon) - displayOptionsChanged = true - } - - if (displayOptionsChanged) { - reloadNotesDisplayOptions(undefined, { - sortBy: newSortBy, - sortReverse: newSortReverse, - }) - } - reloadNotes() - }, [ - application, - sortBy, - sortReverse, - hidePreviews, - hideDates, - hideEditorIcon, - reloadNotes, - reloadNotesDisplayOptions, - ]) - - const onRefresh = useCallback(() => { - startRefreshing() - void application.sync.sync() - }, [application, startRefreshing]) - - const onSearchChange = useCallback( - (filter: string) => { - reloadNotesDisplayOptions(filter) - setSearchText(filter) - reloadNotes(undefined, undefined, filter) - }, - [reloadNotes, reloadNotesDisplayOptions], - ) - - useEffect(() => { - const removeEventObserver = application?.addSingleEventObserver(ApplicationEvent.PreferencesChanged, async () => { - await reloadPreferences() - }) - - return () => { - removeEventObserver?.() - } - }, [application, reloadPreferences]) - - useFocusEffect( - useCallback(() => { - void reloadPreferences() - }, [reloadPreferences]), - ) - - useEffect(() => { - const removeAppStateChangeHandler = application.getAppState().addStateChangeObserver((state) => { - if (state === AppStateType.TagChanged) { - reloadNotesDisplayOptions() - reloadNotes(true, true) - } - if (state === AppStateType.PreferencesChanged) { - void reloadPreferences() - } - }) - - const removeStreamNotes = application.streamItems([ContentType.Note], async () => { - /** If a note changes, it will be queried against the existing filter; - * we dont need to reload display options */ - reloadNotes(true) - }) - - const removeStreamTags = application.streamItems([ContentType.Tag], async () => { - /** A tag could have changed its relationships, so we need to reload the filter */ - reloadNotesDisplayOptions() - reloadNotes() - }) - - return () => { - removeStreamNotes() - removeStreamTags() - removeAppStateChangeHandler() - } - }, [application, reloadNotes, reloadNotesDisplayOptions, reloadPreferences]) - - return ( - <> - onSearchChange('')} - notes={notes} - sortType={sortBy} - decrypting={decrypting} - loading={loading} - hidePreviews={hidePreviews} - hideDates={hideDates} - hideEditorIcon={hideEditorIcon} - selectedNoteId={application.getAppState().isInTabletMode ? selectedNoteId : undefined} - searchOptions={searchOptions} - shouldFocusSearch={shouldFocusSearch} - setShouldFocusSearch={setShouldFocusSearch} - /> - } - /> - - ) - }, -) diff --git a/packages/mobile/src/Screens/Notes/OfflineBanner.styled.ts b/packages/mobile/src/Screens/Notes/OfflineBanner.styled.ts deleted file mode 100644 index 6c7dc921e..000000000 --- a/packages/mobile/src/Screens/Notes/OfflineBanner.styled.ts +++ /dev/null @@ -1,41 +0,0 @@ -import Icon from 'react-native-vector-icons/Ionicons' -import styled from 'styled-components/native' - -const MARGIN = 4 -const PADDING = 12 - -const Touchable = styled.TouchableWithoutFeedback`` -const Container = styled.View` - flex-direction: row; - margin: ${MARGIN}px; - padding: ${PADDING}px; - border-width: 1px; - border-radius: 4px; - border-color: ${(props) => props.theme.stylekitBorderColor}; -` -const CenterContainer = styled.View` - justify-content: center; -` -const UserIcon = styled(Icon)` - font-size: 24px; - color: ${(props) => props.theme.stylekitInfoColor}; -` -const ForwardIcon = styled(UserIcon)` - color: ${(props) => props.theme.stylekitNeutralColor}; -` -const TextContainer = styled.View` - flex: 1; - padding-left: ${PADDING}px; -` -const BoldText = styled.Text` - font-size: 15px; - font-weight: 600; - color: ${(props) => props.theme.stylekitForegroundColor}; -` -const SubText = styled.Text` - margin-top: 2px; - font-size: 11px; - color: ${(props) => props.theme.stylekitNeutralColor}; -` - -export { Touchable, Container, CenterContainer, UserIcon, ForwardIcon, TextContainer, BoldText, SubText } diff --git a/packages/mobile/src/Screens/Notes/OfflineBanner.tsx b/packages/mobile/src/Screens/Notes/OfflineBanner.tsx deleted file mode 100644 index cc4c6cd2d..000000000 --- a/packages/mobile/src/Screens/Notes/OfflineBanner.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { useNavigation } from '@react-navigation/native' -import { SCREEN_SETTINGS } from '@Root/Screens/screens' -import { ICON_FORWARD, ICON_USER } from '@Style/Icons' -import { ThemeService } from '@Style/ThemeService' -import React from 'react' -import { - BoldText, - CenterContainer, - Container, - ForwardIcon, - SubText, - TextContainer, - Touchable, - UserIcon, -} from './OfflineBanner.styled' - -const NOT_BACKED_UP_TEXT = 'Data not backed up' -const SIGN_IN_TEXT = 'Sign in or register to backup your notes' - -export const OfflineBanner: React.FC = () => { - const navigation = useNavigation() - const onPress = () => { - navigation.navigate(SCREEN_SETTINGS as never) - } - - return ( - - - - - - - {NOT_BACKED_UP_TEXT} - {SIGN_IN_TEXT} - - - - - - - ) -} diff --git a/packages/mobile/src/Screens/Root.styled.ts b/packages/mobile/src/Screens/Root.styled.ts deleted file mode 100644 index 133d2b9fc..000000000 --- a/packages/mobile/src/Screens/Root.styled.ts +++ /dev/null @@ -1,42 +0,0 @@ -import styled, { css } from 'styled-components/native' - -export const Container = styled.View` - flex: 1; - flex-direction: row; -` -export const NotesContainer = styled.View<{ - isInTabletMode?: boolean - notesListCollapsed?: boolean -}>` - ${({ isInTabletMode, notesListCollapsed, theme }) => { - return isInTabletMode - ? css` - border-right-color: ${theme.stylekitBorderColor}; - border-right-width: ${notesListCollapsed ? 0 : 1}px; - width: ${notesListCollapsed ? 0 : '40%'}; - ` - : css` - flex: 1; - ` - }} -` -export const ComposeContainer = styled.View` - flex: 1; -` - -export const ExpandTouchable = styled.TouchableHighlight.attrs(({ theme }) => ({ - underlayColor: theme.stylekitBackgroundColor, -}))` - justify-content: center; - position: absolute; - left: 0px; - padding: 7px; - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; - margin-top: -12px; -` - -export const iconNames = { - md: ['arrow-dropright', 'arrow-dropleft'], - ios: ['arrow-forward', 'arrow-back'], -} diff --git a/packages/mobile/src/Screens/Root.tsx b/packages/mobile/src/Screens/Root.tsx deleted file mode 100644 index 3de8d6298..000000000 --- a/packages/mobile/src/Screens/Root.tsx +++ /dev/null @@ -1,127 +0,0 @@ -import { AppStateEventType, AppStateType, TabletModeChangeData } from '@Lib/ApplicationState' -import { useIsLocked } from '@Lib/SnjsHelperHooks' -import { ApplicationContext } from '@Root/ApplicationContext' -import { NoteViewController } from '@standardnotes/snjs' -import { ThemeService } from '@Style/ThemeService' -import { hexToRGBA } from '@Style/Utils' -import React, { useContext, useEffect, useMemo, useState } from 'react' -import { LayoutChangeEvent } from 'react-native' -import Icon from 'react-native-vector-icons/Ionicons' -import { ThemeContext } from 'styled-components' -import { Compose } from './Compose/Compose' -import { Notes } from './Notes/Notes' -import { ComposeContainer, Container, ExpandTouchable, iconNames, NotesContainer } from './Root.styled' - -export const Root = () => { - const application = useContext(ApplicationContext) - const theme = useContext(ThemeContext) - const [isLocked] = useIsLocked() - - const [, setWidth] = useState(undefined) - const [height, setHeight] = useState(undefined) - const [, setX] = useState(undefined) - const [noteListCollapsed, setNoteListCollapsed] = useState(false) - const [activeNoteView, setActiveNoteView] = useState() - const [isInTabletMode, setIsInTabletMode] = useState(application?.getAppState().isInTabletMode) - const [keyboardHeight, setKeyboardHeight] = useState(undefined) - - useEffect(() => { - const removeStateObserver = application?.getAppState().addStateChangeObserver((state) => { - if (state === AppStateType.GainingFocus) { - void application.sync.sync() - } - }) - const removeApplicationStateEventHandler = application - ?.getAppState() - .addStateEventObserver((event: AppStateEventType, data: TabletModeChangeData | undefined) => { - if (event === AppStateEventType.TabletModeChange) { - const eventData = data as TabletModeChangeData - if (eventData.new_isInTabletMode && !eventData.old_isInTabletMode) { - setIsInTabletMode(true) - } else if (!eventData.new_isInTabletMode && eventData.old_isInTabletMode) { - setIsInTabletMode(false) - } - } - if (event === AppStateEventType.KeyboardChangeEvent) { - // need to refresh the height of the keyboard when it opens so that we can change the position - // of the sidebar collapse icon - if (application?.getAppState().isInTabletMode) { - setKeyboardHeight(application?.getAppState().getKeyboardHeight()) - } - } - }) - const removeNoteObserver = application?.editorGroup.addActiveControllerChangeObserver((activeController) => { - if (activeController instanceof NoteViewController) { - setActiveNoteView(activeController) - } else { - setActiveNoteView(undefined) - } - }) - - return () => { - if (removeApplicationStateEventHandler) { - removeApplicationStateEventHandler() - } - if (removeStateObserver) { - removeStateObserver() - } - if (removeNoteObserver) { - removeNoteObserver() - } - } - }, [application]) - - const collapseIconName = useMemo(() => { - const collapseIconPrefix = ThemeService.platformIconPrefix() - - return collapseIconPrefix + '-' + iconNames[collapseIconPrefix][noteListCollapsed ? 0 : 1] - }, [noteListCollapsed]) - - const onLayout = (e: LayoutChangeEvent) => { - const tempWidth = e.nativeEvent.layout.width - /** - If you're in tablet mode, but on an iPad where this app is running side by - side by another app, we only want to show the Compose window and not the - list, because there isn't enough space. - */ - const MinWidthToSplit = 450 - if (application?.getAppState().isTabletDevice) { - if (tempWidth < MinWidthToSplit) { - application?.getAppState().setTabletModeEnabled(false) - } else { - application?.getAppState().setTabletModeEnabled(true) - } - } - setWidth(tempWidth) - setHeight(e.nativeEvent.layout.height) - setX(e.nativeEvent.layout.x) - setIsInTabletMode(application?.getAppState().isInTabletMode) - setKeyboardHeight(application?.getAppState().getKeyboardHeight()) - } - - const toggleNoteList = () => { - setNoteListCollapsed((value) => !value) - } - - const collapseIconBottomPosition = (keyboardHeight ?? 0) > (height ?? 0) / 2 ? (keyboardHeight ?? 0) + 40 : '50%' - - if (isLocked) { - return null - } - - return ( - - - - - {activeNoteView && !activeNoteView.dealloced && isInTabletMode && ( - - - - - - - )} - - ) -} diff --git a/packages/mobile/src/Screens/Settings/Sections/AuthSection.styled.ts b/packages/mobile/src/Screens/Settings/Sections/AuthSection.styled.ts deleted file mode 100644 index 1f789dc82..000000000 --- a/packages/mobile/src/Screens/Settings/Sections/AuthSection.styled.ts +++ /dev/null @@ -1,23 +0,0 @@ -import styled from 'styled-components/native' - -const PADDING = 14 - -export const RegistrationDescription = styled.Text` - color: ${({ theme }) => theme.stylekitForegroundColor}; - font-size: ${({ theme }) => theme.mainTextFontSize}px; - padding-left: ${PADDING}px; - padding-right: ${PADDING}px; - margin-bottom: ${PADDING}px; -` - -export const RegistrationInput = styled.TextInput.attrs(({ theme }) => ({ - underlineColorAndroid: 'transparent', - placeholderTextColor: theme.stylekitNeutralColor, -}))` - font-size: ${({ theme }) => theme.mainTextFontSize}px; - padding: 0px; - color: ${({ theme }) => theme.stylekitForegroundColor}; - height: 100%; -` - -export const RegularView = styled.View`` diff --git a/packages/mobile/src/Screens/Settings/Sections/AuthSection.tsx b/packages/mobile/src/Screens/Settings/Sections/AuthSection.tsx deleted file mode 100644 index 894049675..000000000 --- a/packages/mobile/src/Screens/Settings/Sections/AuthSection.tsx +++ /dev/null @@ -1,254 +0,0 @@ -import { ApplicationContext } from '@Root/ApplicationContext' -import { ButtonCell } from '@Root/Components/ButtonCell' -import { SectionedAccessoryTableCell } from '@Root/Components/SectionedAccessoryTableCell' -import { SectionedTableCell } from '@Root/Components/SectionedTableCell' -import { SectionHeader } from '@Root/Components/SectionHeader' -import { TableSection } from '@Root/Components/TableSection' -import { ThemeServiceContext } from '@Style/ThemeService' -import React, { useCallback, useContext, useEffect, useState } from 'react' -import { Keyboard } from 'react-native' -import { RegistrationDescription, RegistrationInput, RegularView } from './AuthSection.styled' - -const DEFAULT_SIGN_IN_TEXT = 'Sign In' -const DEFAULT_REGISTER_TEXT = 'Register' -const SIGNIN_IN = 'Generating Keys...' - -type Props = { - title: string - signedIn: boolean -} - -export const AuthSection = (props: Props) => { - // Context - const application = useContext(ApplicationContext) - const themeService = useContext(ThemeServiceContext) - - // State - const [registering, setRegistering] = useState(false) - const [signingIn, setSigningIn] = useState(false) - const [strictSignIn, setStrictSignIn] = useState(false) - const [showAdvanced, setShowAdvanced] = useState(false) - const [email, setEmail] = useState('') - const [password, setPassword] = useState('') - const [server, setServer] = useState('') - const [passwordConfirmation, setPasswordConfirmation] = useState('') - const [confirmRegistration, setConfirmRegistration] = useState(false) - - // set initial server - useEffect(() => { - const getServer = async () => { - const host = await application?.getHost() - setServer(host!) - } - void getServer() - }, [application]) - - const updateServer = useCallback( - async (host: string) => { - setServer(host) - await application?.setCustomHost(host) - }, - [application], - ) - if (props.signedIn) { - return null - } - - const validate = () => { - if (!email) { - void application?.alertService?.alert('Please enter a valid email address.', 'Missing Email', 'OK') - return false - } - - if (!password) { - void application?.alertService?.alert('Please enter your password.', 'Missing Password', 'OK') - return false - } - - return true - } - - const signIn = async () => { - setSigningIn(true) - if (!validate()) { - setSigningIn(false) - return - } - Keyboard.dismiss() - const result = await application!.signIn(email, password, strictSignIn, undefined, true, false) - - if (result?.error) { - if (result?.error.message) { - void application?.alertService?.alert(result?.error.message) - } - setSigningIn(false) - return - } - - setSigningIn(false) - setPassword('') - setPasswordConfirmation('') - } - - const onRegisterPress = () => { - if (!validate()) { - return - } - setConfirmRegistration(true) - } - - const register = async () => { - setRegistering(true) - if (password !== passwordConfirmation) { - void application?.alertService?.alert( - 'The passwords you entered do not match. Please try again.', - "Passwords Don't Match", - 'OK', - ) - } else { - try { - Keyboard.dismiss() - await application!.register(email, password, undefined, true) - } catch (error) { - void application?.alertService?.alert((error as Error).message) - } - } - setRegistering(false) - } - - const _renderRegistrationConfirm = () => { - return ( - - - - - Due to the nature of our encryption, Standard Notes cannot offer password reset functionality. If you forget - your password, you will permanently lose access to your data. - - - - - - - - - { - setConfirmRegistration(false) - setPasswordConfirmation('') - setPassword('') - }} - /> - - ) - } - - const _renderDefaultContent = () => { - const keyboardApperance = themeService?.keyboardColorForActiveTheme() - - return ( - - {props.title && } - - <> - - - - - - - - - - - {(showAdvanced || !server) && ( - - - - - - - setStrictSignIn(!strictSignIn)} - text={'Use strict sign in'} - selected={() => { - return strictSignIn - }} - /> - - )} - - - - - - - {!showAdvanced && ( - setShowAdvanced(true)} /> - )} - - ) - } - - return ( - - {confirmRegistration && _renderRegistrationConfirm()} - - {!confirmRegistration && _renderDefaultContent()} - - ) -} diff --git a/packages/mobile/src/Screens/Settings/Sections/CompanySection.styled.ts b/packages/mobile/src/Screens/Settings/Sections/CompanySection.styled.ts deleted file mode 100644 index fe412ce72..000000000 --- a/packages/mobile/src/Screens/Settings/Sections/CompanySection.styled.ts +++ /dev/null @@ -1,10 +0,0 @@ -import styled from 'styled-components/native' - -export const Label = styled.Text` - color: ${({ theme }) => theme.stylekitNeutralColor}; - margin-top: 3px; -` -export const ContentContainer = styled.View` - display: flex; - flex-direction: column; -` diff --git a/packages/mobile/src/Screens/Settings/Sections/CompanySection.tsx b/packages/mobile/src/Screens/Settings/Sections/CompanySection.tsx deleted file mode 100644 index 36944217a..000000000 --- a/packages/mobile/src/Screens/Settings/Sections/CompanySection.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import { ApplicationState } from '@Lib/ApplicationState' -import { ApplicationContext } from '@Root/ApplicationContext' -import { ButtonCell } from '@Root/Components/ButtonCell' -import { SectionHeader } from '@Root/Components/SectionHeader' -import { TableSection } from '@Root/Components/TableSection' -import React, { useContext } from 'react' -import { Platform, Share } from 'react-native' -import { ContentContainer, Label } from './CompanySection.styled' - -const URLS = { - feedback: `mailto:help@standardnotes.com?subject=${Platform.OS === 'android' ? 'Android' : 'iOS'} app feedback (v${ - ApplicationState.version - })`, - learn_more: 'https://standardnotes.com', - privacy: 'https://standardnotes.com/privacy', - help: 'https://standardnotes.com/help', - rate: Platform.select({ - ios: 'https://itunes.apple.com/us/app/standard-notes/id1285392450?ls=1&mt=8', - android: 'market://details?id=com.standardnotes', - }) as string, -} - -type Props = { - title: string -} - -export const CompanySection = (props: Props) => { - const application = useContext(ApplicationContext) - const storeName = Platform.OS === 'android' ? 'Play Store' : 'App Store' - - const openUrl = (action: keyof typeof URLS) => { - application?.deviceInterface!.openUrl(URLS[action]) - } - - const shareEncryption = () => { - const title = 'The Unexpected Benefits of Encrypted Writing' - let message = Platform.OS === 'ios' ? title : '' - const url = 'https://standardnotes.com/why-encrypted' - // Android ignores url. iOS ignores title. - if (Platform.OS === 'android') { - message += '\n\nhttps://standardnotes.com/why-encrypted' - } - void application?.getAppState().performActionWithoutStateChangeImpact(() => { - void Share.share({ title: title, message: message, url: url }) - }) - } - - const shareWithFriend = () => { - const title = 'Standard Notes' - let message = 'Check out Standard Notes, a free, open-source, and completely encrypted notes app.' - const url = 'https://standardnotes.com' - // Android ignores url. iOS ignores title. - if (Platform.OS === 'android') { - message += '\n\nhttps://standardnotes.com' - } - void application?.getAppState().performActionWithoutStateChangeImpact(() => { - void Share.share({ title: title, message: message, url: url }) - }) - } - - return ( - - - - openUrl('help')}> - - - openUrl('feedback')}> - - - - - - - - - - - - - - openUrl('learn_more')}> - - - - openUrl('privacy')}> - - - - openUrl('rate')}> - - - - - - - ) -} diff --git a/packages/mobile/src/Screens/Settings/Sections/DeleteSection.tsx b/packages/mobile/src/Screens/Settings/Sections/DeleteSection.tsx deleted file mode 100644 index 1e9c5a20f..000000000 --- a/packages/mobile/src/Screens/Settings/Sections/DeleteSection.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { ApplicationContext } from '@Root/ApplicationContext' -import { ButtonCell } from '@Root/Components/ButtonCell' -import { SectionHeader } from '@Root/Components/SectionHeader' -import { TableSection } from '@Root/Components/TableSection' -import { ButtonType } from '@standardnotes/snjs' -import React, { useContext, useState } from 'react' -import { RegularView } from './AuthSection.styled' - -export const DeleteSection = () => { - const application = useContext(ApplicationContext) - const [deleting, setDeleting] = useState(false) - - const deleteAccount = async () => { - const message = - "This action is irreversible. After deletion completes, you will be signed out on all devices, and this application will exit. If you have an active paid subscription, cancel the subscription first. Otherwise, if you'd like to keep the subscription, you can re-register with the same email after deletion, and your subscription will be linked back up with your account." - const confirmed = await application!.alertService.confirm( - message, - 'Are you sure?', - 'Delete Account', - ButtonType.Danger, - ) - - if (!confirmed) { - return - } - - setDeleting(true) - - const result = await application!.user.deleteAccount() - if (result.error) { - void application!.alertService.alert('An error occurred while deleting your account. Please try again.') - } - } - - return ( - - - - - - - ) -} diff --git a/packages/mobile/src/Screens/Settings/Sections/EncryptionSection.styled.ts b/packages/mobile/src/Screens/Settings/Sections/EncryptionSection.styled.ts deleted file mode 100644 index 8831da196..000000000 --- a/packages/mobile/src/Screens/Settings/Sections/EncryptionSection.styled.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { SectionedTableCell } from '@Root/Components/SectionedTableCell' -import styled from 'styled-components/native' - -export const BaseView = styled.View`` - -export const StyledSectionedTableCell = styled(SectionedTableCell)` - padding-top: 12px; -` - -export const Title = styled.Text` - color: ${({ theme }) => theme.stylekitForegroundColor}; - font-size: 16px; - font-weight: bold; -` - -export const Subtitle = styled.Text` - color: ${({ theme }) => theme.stylekitNeutralColor}; - font-size: 14px; - margin-top: 4px; -` diff --git a/packages/mobile/src/Screens/Settings/Sections/EncryptionSection.tsx b/packages/mobile/src/Screens/Settings/Sections/EncryptionSection.tsx deleted file mode 100644 index 82019f785..000000000 --- a/packages/mobile/src/Screens/Settings/Sections/EncryptionSection.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import { useIsLocked } from '@Lib/SnjsHelperHooks' -import { ApplicationContext } from '@Root/ApplicationContext' -import { SectionHeader } from '@Root/Components/SectionHeader' -import { TableSection } from '@Root/Components/TableSection' -import { ContentType, StorageEncryptionPolicy } from '@standardnotes/snjs' -import React, { useContext, useEffect, useMemo, useState } from 'react' -import { BaseView, StyledSectionedTableCell, Subtitle, Title } from './EncryptionSection.styled' - -type Props = { - title: string - encryptionAvailable: boolean -} - -export const EncryptionSection = (props: Props) => { - // Context - const application = useContext(ApplicationContext) - const [isLocked] = useIsLocked() - - // State - const [protocolDisplayName, setProtocolDisplayName] = useState('') - - useEffect(() => { - if (!props.encryptionAvailable) { - return - } - - let mounted = true - const getProtocolDisplayName = async () => { - const displayName = (await application?.getProtocolEncryptionDisplayName()) ?? '' - if (mounted) { - setProtocolDisplayName(displayName) - } - } - void getProtocolDisplayName() - return () => { - mounted = false - } - }, [application, props.encryptionAvailable]) - - const textData = useMemo(() => { - const encryptionType = protocolDisplayName - let encryptionStatus = props.encryptionAvailable ? 'Enabled' : 'Not Enabled' - if (props.encryptionAvailable) { - encryptionStatus += ` | ${encryptionType}` - } else { - encryptionStatus += '. ' - encryptionStatus += - application?.getStorageEncryptionPolicy() === StorageEncryptionPolicy.Default - ? 'To enable encryption, sign in, register, or enable storage encryption.' - : 'Sign in, register, or add a local passcode to enable encryption.' - } - let sourceString - if (isLocked) { - return { title: '', text: '' } - } else { - sourceString = application?.hasAccount() ? 'Account Keys' : 'Passcode' - } - - const items = application!.items.getItems([ContentType.Note, ContentType.Tag]) - const itemsStatus = items.length + '/' + items.length + ' notes and tags encrypted' - - return { - encryptionStatus, - sourceString, - itemsStatus, - } - }, [application, props.encryptionAvailable, isLocked, protocolDisplayName]) - - return ( - - - - - - Encryption - {textData.encryptionStatus} - - - - {props.encryptionAvailable && ( - - - Encryption Source - {textData.sourceString} - - - )} - - {props.encryptionAvailable && ( - - - Items Encrypted - {textData.itemsStatus} - - - )} - - ) -} diff --git a/packages/mobile/src/Screens/Settings/Sections/FilesSection.styled.tsx b/packages/mobile/src/Screens/Settings/Sections/FilesSection.styled.tsx deleted file mode 100644 index 40f5fee27..000000000 --- a/packages/mobile/src/Screens/Settings/Sections/FilesSection.styled.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { SectionedTableCell } from '@Components/SectionedTableCell' -import { StyleSheet } from 'react-native' -import styled, { DefaultTheme } from 'styled-components/native' - -export const useFilesInPreferencesStyles = (theme: DefaultTheme) => { - return StyleSheet.create({ - progressBarContainer: { - backgroundColor: theme.stylekitSecondaryContrastBackgroundColor, - height: 8, - borderRadius: 8, - marginTop: 6, - }, - progressBar: { - backgroundColor: theme.stylekitInfoColor, - borderRadius: 8, - }, - }) -} - -export const StyledSectionedTableCell = styled(SectionedTableCell)` - padding-top: 12px; -` -export const Title = styled.Text` - color: ${({ theme }) => theme.stylekitForegroundColor}; - font-size: 16px; - font-weight: bold; -` -export const SubTitle = styled.Text` - margin-top: 4px; - font-size: 14px; - color: ${({ theme }) => theme.stylekitContrastForegroundColor}; - opacity: 0.6; -` diff --git a/packages/mobile/src/Screens/Settings/Sections/FilesSection.tsx b/packages/mobile/src/Screens/Settings/Sections/FilesSection.tsx deleted file mode 100644 index 45f8cd0c0..000000000 --- a/packages/mobile/src/Screens/Settings/Sections/FilesSection.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { SectionHeader } from '@Root/Components/SectionHeader' -import { TableSection } from '@Root/Components/TableSection' -import { useSafeApplicationContext } from '@Root/Hooks/useSafeApplicationContext' -import { - StyledSectionedTableCell, - SubTitle, - Title, - useFilesInPreferencesStyles, -} from '@Screens/Settings/Sections/FilesSection.styled' -import { formatSizeToReadableString } from '@standardnotes/filepicker' -import { SubscriptionSettingName } from '@standardnotes/snjs' -import React, { FC, useContext, useEffect, useState } from 'react' -import { View } from 'react-native' -import { ThemeContext } from 'styled-components' - -export const FilesSection: FC = () => { - const application = useSafeApplicationContext() - const theme = useContext(ThemeContext) - const styles = useFilesInPreferencesStyles(theme) - - const [filesUsedQuota, setFilesUsedQuota] = useState(0) - const [filesTotalQuota, setFilesTotalQuota] = useState(0) - - useEffect(() => { - const getQuota = async () => { - const { FileUploadBytesUsed, FileUploadBytesLimit } = SubscriptionSettingName - - const usedQuota = await application.settings.getSubscriptionSetting(FileUploadBytesUsed) - const totalQuota = await application.settings.getSubscriptionSetting(FileUploadBytesLimit) - - setFilesUsedQuota(usedQuota ? parseFloat(usedQuota) : 0) - setFilesTotalQuota(totalQuota ? parseFloat(totalQuota) : 0) - } - - getQuota().catch(console.error) - }, [application.settings]) - - const usedQuotaRatioPercent = Math.round((filesUsedQuota * 100) / filesTotalQuota) - - return ( - - - - - Storage Quota - - {formatSizeToReadableString(filesUsedQuota)} of {formatSizeToReadableString(filesTotalQuota)} used - - - - - - - - ) -} diff --git a/packages/mobile/src/Screens/Settings/Sections/NewMobilePreview.tsx b/packages/mobile/src/Screens/Settings/Sections/NewMobilePreview.tsx deleted file mode 100644 index 6ff7cfdf6..000000000 --- a/packages/mobile/src/Screens/Settings/Sections/NewMobilePreview.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { AlwaysOpenWebAppOnLaunchKey } from '@Lib/constants' -import { ApplicationContext } from '@Root/ApplicationContext' -import { ButtonCell } from '@Root/Components/ButtonCell' -import { SectionHeader } from '@Root/Components/SectionHeader' -import { TableSection } from '@Root/Components/TableSection' -import { ButtonType, StorageValueModes } from '@standardnotes/snjs' -import React, { useContext } from 'react' -import styled from 'styled-components/native' -import { Label } from './CompanySection.styled' -import { BaseView, StyledSectionedTableCell } from './EncryptionSection.styled' - -const Title = styled.Text` - color: ${({ theme }) => theme.stylekitForegroundColor}; - font-size: 16px; - font-weight: bold; -` - -export const NewMobileSection = () => { - const application = useContext(ApplicationContext) - - if (!application) { - return <> - } - - const optIn = async () => { - const confirmationText = - 'This will close the app and switch to the new mobile experience next time you open it. You will be able to switch back to the soon-to-be removed classic experience from the settings.' - - if ( - await application.alertService.confirm( - confirmationText, - 'Switch To New Mobile Experience?', - 'Switch', - ButtonType.Info, - ) - ) { - application.setValue(AlwaysOpenWebAppOnLaunchKey, true, StorageValueModes.Nonwrapped) - setTimeout(() => application.deviceInterface.performSoftReset(), 1000) - } - } - - return ( - - - - - - 🎉 New Mobile Experience Preview - - - - - - { - application?.deviceInterface!.openUrl( - 'https://blog.standardnotes.com/38384/our-new-mobile-experience-is-launching-soon', - ) - }} - > - - ) -} diff --git a/packages/mobile/src/Screens/Settings/Sections/OptionsSection.tsx b/packages/mobile/src/Screens/Settings/Sections/OptionsSection.tsx deleted file mode 100644 index 18011857b..000000000 --- a/packages/mobile/src/Screens/Settings/Sections/OptionsSection.tsx +++ /dev/null @@ -1,238 +0,0 @@ -import { useSignedIn } from '@Lib/SnjsHelperHooks' -import { useNavigation } from '@react-navigation/native' -import { ButtonCell } from '@Root/Components/ButtonCell' -import { SectionedAccessoryTableCell } from '@Root/Components/SectionedAccessoryTableCell' -import { SectionedOptionsTableCell } from '@Root/Components/SectionedOptionsTableCell' -import { SectionHeader } from '@Root/Components/SectionHeader' -import { TableSection } from '@Root/Components/TableSection' -import { useSafeApplicationContext } from '@Root/Hooks/useSafeApplicationContext' -import { ModalStackNavigationProp } from '@Root/ModalStack' -import { SCREEN_MANAGE_SESSIONS, SCREEN_SETTINGS } from '@Root/Screens/screens' -import { ButtonType, PrefKey } from '@standardnotes/snjs' -import moment from 'moment' -import React, { useCallback, useMemo, useState } from 'react' -import { Platform } from 'react-native' -import DocumentPicker from 'react-native-document-picker' -import RNFS from 'react-native-fs' - -type Props = { - title: string - encryptionAvailable: boolean -} - -export const OptionsSection = ({ title, encryptionAvailable }: Props) => { - // Context - const application = useSafeApplicationContext() - - const [signedIn] = useSignedIn() - const navigation = useNavigation['navigation']>() - - // State - const [importing, setImporting] = useState(false) - const [exporting, setExporting] = useState(false) - const [lastExportDate, setLastExportDate] = useState(() => - application?.getLocalPreferences().getValue(PrefKey.MobileLastExportDate, undefined), - ) - - const lastExportData = useMemo(() => { - if (lastExportDate) { - const formattedDate = moment(lastExportDate).format('lll') - const lastExportString = `Last exported on ${formattedDate}` - - // Date is stale if more than 7 days ago - const staleThreshold = 7 * 86400 - const stale = - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore date type issue - (new Date() - new Date(lastExportDate)) / 1000 > staleThreshold - return { - lastExportString, - stale, - } - } - return { - lastExportString: 'Your data has not yet been backed up.', - stale: false, - } - }, [lastExportDate]) - - const email = useMemo(() => { - if (signedIn) { - const user = application.getUser() - return user?.email - } - return - }, [application, signedIn]) - - const exportOptions = useMemo(() => { - return [ - { - title: 'Encrypted', - key: 'encrypted', - selected: encryptionAvailable, - }, - { title: 'Decrypted', key: 'decrypted', selected: true }, - ] - }, [encryptionAvailable]) - - const destroyLocalData = async () => { - let signoutText = - 'Signing out will remove all data from this device, including notes and tags. Make sure your data is synced before proceeding.' - - signoutText += '\n\nYour app will quit after sign out completes.' - - if (await application.alertService.confirm(signoutText, 'Sign Out?', 'Sign Out', ButtonType.Danger)) { - await application.user.signOut() - } - } - - const exportData = useCallback( - async (encrypted: boolean) => { - setExporting(true) - const result = await application.getBackupsService().export(encrypted) - if (result) { - const exportDate = new Date() - setLastExportDate(exportDate) - void application.getLocalPreferences().setUserPrefValue(PrefKey.MobileLastExportDate, exportDate) - } - setExporting(false) - }, - [application], - ) - - const readImportFile = async (fileUri: string): Promise => { - return RNFS.readFile(fileUri) - .then((result) => JSON.parse(result)) - .catch(() => { - void application.alertService.alert('Unable to open file. Ensure it is a proper JSON file and try again.') - }) - } - - const performImport = async (data: any) => { - const result = await application.mutator.importData(data) - if (!result) { - return - } else if ('error' in result) { - void application.alertService.alert(result.error.text) - } else if (result.errorCount) { - void application.alertService.alert( - `Import complete. ${result.errorCount} items were not imported because ` + - 'there was an error decrypting them. Make sure the password is correct and try again.', - ) - } else { - void application.alertService.alert('Your data has been successfully imported.') - } - } - - const onImportPress = async () => { - try { - const selectedFiles = await DocumentPicker.pick({ - type: [DocumentPicker.types.plainText], - }) - const selectedFile = selectedFiles[0] - const selectedFileURI = Platform.OS === 'ios' ? decodeURIComponent(selectedFile.uri) : selectedFile.uri - const data = await readImportFile(selectedFileURI) - if (!data) { - return - } - setImporting(true) - if (data.version || data.auth_params || data.keyParams) { - const version = data.version || data.keyParams?.version || data.auth_params?.version - if (application.protocolService.supportedVersions().includes(version)) { - await performImport(data) - } else { - void application.alertService.alert( - 'This backup file was created using an unsupported version of the application ' + - 'and cannot be imported here. Please update your application and try again.', - ) - } - } else { - await performImport(data) - } - } finally { - setImporting(false) - } - } - - const onExportPress = useCallback( - async (option: { key: string }) => { - const encrypted = option.key === 'encrypted' - if (encrypted && !encryptionAvailable) { - void application.alertService.alert( - 'You must be signed in, or have a local passcode set, to generate an encrypted export file.', - 'Not Available', - 'OK', - ) - return - } - void exportData(encrypted) - }, - [application?.alertService, encryptionAvailable, exportData], - ) - - const openManageSessions = useCallback(() => { - navigation.push(SCREEN_MANAGE_SESSIONS) - }, [navigation]) - - const showDataBackupAlert = useCallback(() => { - void application.alertService.alert( - 'Because you are using the app offline without a sync account, it is your responsibility to keep your data safe and backed up. It is recommended you export a backup of your data at least once a week, or, to sign up for a sync account so that your data is backed up automatically.', - 'No Backups Created', - 'OK', - ) - }, [application.alertService]) - - return ( - - - - {signedIn && ( - <> - - - - )} - - - - - - {!signedIn && ( - { - if (!lastExportDate || lastExportData.stale) { - showDataBackupAlert() - } - }} - tinted={!lastExportDate || lastExportData.stale} - text={lastExportData.lastExportString} - /> - )} - - ) -} diff --git a/packages/mobile/src/Screens/Settings/Sections/PreferencesSection.tsx b/packages/mobile/src/Screens/Settings/Sections/PreferencesSection.tsx deleted file mode 100644 index a3bf22ea7..000000000 --- a/packages/mobile/src/Screens/Settings/Sections/PreferencesSection.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import { SectionedAccessoryTableCell } from '@Root/Components/SectionedAccessoryTableCell' -import { SectionHeader } from '@Root/Components/SectionHeader' -import { TableSection } from '@Root/Components/TableSection' -import { useSafeApplicationContext } from '@Root/Hooks/useSafeApplicationContext' -import { CollectionSort, CollectionSortProperty, PrefKey } from '@standardnotes/snjs' -import React, { useMemo, useState } from 'react' - -export const PreferencesSection = () => { - // Context - const application = useSafeApplicationContext() - - // State - const [sortBy, setSortBy] = useState(() => - application.getPreference(PrefKey.MobileSortNotesBy, CollectionSort.CreatedAt), - ) - const [sortReverse, setSortReverse] = useState(() => - application.getLocalPreferences().getValue(PrefKey.MobileSortNotesReverse, false), - ) - const [hideDates, setHideDates] = useState(() => - application.getLocalPreferences().getValue(PrefKey.MobileNotesHideDate, false), - ) - const [hideEditorIcon, setHideEditorIcon] = useState(() => - application.getLocalPreferences().getValue(PrefKey.MobileNotesHideEditorIcon, false), - ) - const [hidePreviews, setHidePreviews] = useState(() => - application.getLocalPreferences().getValue(PrefKey.MobileNotesHideNotePreview, false), - ) - - const sortOptions = useMemo(() => { - return [ - { key: CollectionSort.CreatedAt, label: 'Date Added' }, - { key: CollectionSort.UpdatedAt, label: 'Date Modified' }, - { key: CollectionSort.Title, label: 'Title' }, - ] - }, []) - - const toggleReverseSort = () => { - void application.getLocalPreferences().setUserPrefValue(PrefKey.MobileSortNotesReverse, !sortReverse) - setSortReverse((value) => !value) - } - - const changeSortOption = (key: CollectionSortProperty) => { - void application.getLocalPreferences().setUserPrefValue(PrefKey.MobileSortNotesBy, key) - setSortBy(key) - } - const toggleNotesPreviewHidden = () => { - void application.getLocalPreferences().setUserPrefValue(PrefKey.MobileNotesHideNotePreview, !hidePreviews) - setHidePreviews((value) => !value) - } - const toggleNotesDateHidden = () => { - void application.getLocalPreferences().setUserPrefValue(PrefKey.MobileNotesHideDate, !hideDates) - setHideDates((value) => !value) - } - const toggleNotesEditorIconHidden = () => { - void application.getLocalPreferences().setUserPrefValue(PrefKey.MobileNotesHideEditorIcon, !hideEditorIcon) - setHideEditorIcon((value) => !value) - } - - return ( - <> - - - {sortOptions.map((option, i) => { - return ( - { - changeSortOption(option.key) - }} - text={option.label} - key={option.key} - first={i === 0} - last={i === sortOptions.length - 1} - selected={() => option.key === sortBy} - /> - ) - })} - - - - - - hidePreviews} - /> - - hideDates} - /> - - hideEditorIcon} - /> - - - ) -} diff --git a/packages/mobile/src/Screens/Settings/Sections/ProtectionsSection.styled.ts b/packages/mobile/src/Screens/Settings/Sections/ProtectionsSection.styled.ts deleted file mode 100644 index 00cb8ac84..000000000 --- a/packages/mobile/src/Screens/Settings/Sections/ProtectionsSection.styled.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { SectionedTableCell } from '@Root/Components/SectionedTableCell' -import styled from 'styled-components/native' - -export const BaseView = styled.View`` - -export const StyledSectionedTableCell = styled(SectionedTableCell)` - padding-top: 12px; -` - -export const SubText = styled.Text` - color: ${({ theme }) => theme.stylekitNeutralColor}; - font-size: 14px; - padding: 12px 14px; -` - -export const Subtitle = styled.Text` - color: ${({ theme }) => theme.stylekitNeutralColor}; - font-size: 14px; - margin-top: 4px; -` - -export const Title = styled.Text` - color: ${({ theme }) => theme.stylekitForegroundColor}; - font-size: 16px; - font-weight: bold; -` diff --git a/packages/mobile/src/Screens/Settings/Sections/ProtectionsSection.tsx b/packages/mobile/src/Screens/Settings/Sections/ProtectionsSection.tsx deleted file mode 100644 index 45753f880..000000000 --- a/packages/mobile/src/Screens/Settings/Sections/ProtectionsSection.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { useProtectionSessionExpiry } from '@Lib/SnjsHelperHooks' -import { ButtonCell } from '@Root/Components/ButtonCell' -import { SectionHeader } from '@Root/Components/SectionHeader' -import { TableSection } from '@Root/Components/TableSection' -import { useSafeApplicationContext } from '@Root/Hooks/useSafeApplicationContext' -import React from 'react' -import { BaseView, StyledSectionedTableCell, SubText, Subtitle, Title } from './ProtectionsSection.styled' - -type Props = { - title: string - protectionsAvailable?: boolean -} - -export const ProtectionsSection = (props: Props) => { - // Context - const application = useSafeApplicationContext() - // State - const [protectionsDisabledUntil] = useProtectionSessionExpiry() - - const protectionsEnabledSubtitle = protectionsDisabledUntil ? `Disabled until ${protectionsDisabledUntil}` : 'Enabled' - - const protectionsEnabledSubtext = - 'Actions like viewing protected notes, exporting decrypted backups, or revoking an active session, require additional authentication like entering your account password or application passcode.' - - const enableProtections = () => { - void application?.clearProtectionSession() - } - - return ( - - - - - Status - {props.protectionsAvailable ? protectionsEnabledSubtitle : 'Disabled'} - - - {props.protectionsAvailable && protectionsDisabledUntil && ( - - )} - {protectionsEnabledSubtext} - - ) -} diff --git a/packages/mobile/src/Screens/Settings/Sections/SecuritySection.styled.ts b/packages/mobile/src/Screens/Settings/Sections/SecuritySection.styled.ts deleted file mode 100644 index 7bb256205..000000000 --- a/packages/mobile/src/Screens/Settings/Sections/SecuritySection.styled.ts +++ /dev/null @@ -1,6 +0,0 @@ -import styled from 'styled-components/native' - -export const Title = styled.Text` - color: ${({ theme }) => theme.stylekitNeutralColor}; - margin-top: 2px; -` diff --git a/packages/mobile/src/Screens/Settings/Sections/SecuritySection.tsx b/packages/mobile/src/Screens/Settings/Sections/SecuritySection.tsx deleted file mode 100644 index 8d0435447..000000000 --- a/packages/mobile/src/Screens/Settings/Sections/SecuritySection.tsx +++ /dev/null @@ -1,247 +0,0 @@ -import { MobileDevice } from '@Lib/Interface' -import { useFocusEffect, useNavigation } from '@react-navigation/native' -import { ApplicationContext } from '@Root/ApplicationContext' -import { ButtonCell } from '@Root/Components/ButtonCell' -import { Option, SectionedOptionsTableCell } from '@Root/Components/SectionedOptionsTableCell' -import { SectionHeader } from '@Root/Components/SectionHeader' -import { TableSection } from '@Root/Components/TableSection' -import { ModalStackNavigationProp } from '@Root/ModalStack' -import { SCREEN_INPUT_MODAL_PASSCODE, SCREEN_SETTINGS } from '@Root/Screens/screens' -import { MobileUnlockTiming, StorageEncryptionPolicy } from '@standardnotes/snjs' -import React, { useCallback, useContext, useEffect, useState } from 'react' -import { Platform } from 'react-native' -import { Title } from './SecuritySection.styled' - -type Props = { - title: string - hasPasscode: boolean - encryptionAvailable: boolean - updateProtectionsAvailable: (...args: unknown[]) => unknown -} - -export const SecuritySection = (props: Props) => { - const navigation = useNavigation['navigation']>() - // Context - const application = useContext(ApplicationContext) - - // State - const [encryptionPolicy, setEncryptionPolicy] = useState(() => application?.getStorageEncryptionPolicy()) - const [encryptionPolictChangeInProgress, setEncryptionPolictChangeInProgress] = useState(false) - const [hasScreenshotPrivacy, setHasScreenshotPrivacy] = useState(false) - const [hasBiometrics, setHasBiometrics] = useState(false) - const [supportsBiometrics, setSupportsBiometrics] = useState(false) - const [biometricsTimingOptions, setBiometricsTimingOptions] = useState(() => - application!.protections.getMobileBiometricsTimingOptions(), - ) - const [passcodeTimingOptions, setPasscodeTimingOptions] = useState(() => - application!.protections.getMobilePasscodeTimingOptions(), - ) - - useEffect(() => { - let mounted = true - const getHasScreenshotPrivacy = async () => { - const hasScreenshotPrivacyEnabled = application?.protections.getMobileScreenshotPrivacyEnabled() - if (mounted) { - setHasScreenshotPrivacy(hasScreenshotPrivacyEnabled) - } - } - void getHasScreenshotPrivacy() - const getHasBiometrics = async () => { - const appHasBiometrics = application!.protections.hasBiometricsEnabled() - if (mounted) { - setHasBiometrics(appHasBiometrics) - } - } - void getHasBiometrics() - const hasBiometricsSupport = async () => { - const hasBiometricsAvailable = await ( - application?.deviceInterface as MobileDevice - ).getDeviceBiometricsAvailability() - if (mounted) { - setSupportsBiometrics(hasBiometricsAvailable) - } - } - void hasBiometricsSupport() - return () => { - mounted = false - } - }, [application]) - - useFocusEffect( - useCallback(() => { - if (props.hasPasscode) { - setPasscodeTimingOptions(() => application!.protections.getMobilePasscodeTimingOptions()) - } - }, [application, props.hasPasscode]), - ) - - const toggleEncryptionPolicy = async () => { - if (!props.encryptionAvailable) { - return - } - - if (encryptionPolicy === StorageEncryptionPolicy.Default) { - setEncryptionPolictChangeInProgress(true) - setEncryptionPolicy(StorageEncryptionPolicy.Disabled) - await application?.setStorageEncryptionPolicy(StorageEncryptionPolicy.Disabled) - setEncryptionPolictChangeInProgress(false) - } else if (encryptionPolicy === StorageEncryptionPolicy.Disabled) { - setEncryptionPolictChangeInProgress(true) - setEncryptionPolicy(StorageEncryptionPolicy.Default) - await application?.setStorageEncryptionPolicy(StorageEncryptionPolicy.Default) - setEncryptionPolictChangeInProgress(false) - } - } - - // State - const storageEncryptionTitle = props.encryptionAvailable - ? encryptionPolicy === StorageEncryptionPolicy.Default - ? 'Disable Storage Encryption' - : 'Enable Storage Encryption' - : 'Storage Encryption' - - let storageSubText = "Encrypts your data before saving to your device's local storage." - - if (props.encryptionAvailable) { - storageSubText += - encryptionPolicy === StorageEncryptionPolicy.Default - ? ' Disable to improve app start-up speed.' - : ' May decrease app start-up speed.' - } else { - storageSubText += ' Sign in, register, or add a local passcode to enable this option.' - } - - if (encryptionPolictChangeInProgress) { - storageSubText = 'Applying changes...' - } - - const screenshotPrivacyFeatureText = - Platform.OS === 'ios' ? 'Multitasking Privacy' : 'Multitasking/Screenshot Privacy' - - const screenshotPrivacyTitle = hasScreenshotPrivacy - ? `Disable ${screenshotPrivacyFeatureText}` - : `Enable ${screenshotPrivacyFeatureText}` - - const passcodeTitle = props.hasPasscode ? 'Disable Passcode Lock' : 'Enable Passcode Lock' - - const biometricTitle = hasBiometrics ? 'Disable Biometrics Lock' : 'Enable Biometrics Lock' - - const setBiometricsTiming = async (timing: MobileUnlockTiming) => { - await application?.getAppState().setBiometricsTiming(timing) - setBiometricsTimingOptions(() => application!.protections.getMobileBiometricsTimingOptions()) - } - - const setPasscodeTiming = async (timing: MobileUnlockTiming) => { - await application?.getAppState().setPasscodeTiming(timing) - setPasscodeTimingOptions(() => application!.protections.getMobilePasscodeTimingOptions()) - } - - const onScreenshotPrivacyPress = async () => { - const enable = !hasScreenshotPrivacy - setHasScreenshotPrivacy(enable) - await application?.getAppState().setScreenshotPrivacyEnabled(enable) - } - - const onPasscodePress = async () => { - if (props.hasPasscode) { - void disableAuthentication('passcode') - } else { - navigation.push(SCREEN_INPUT_MODAL_PASSCODE) - } - } - - const onBiometricsPress = async () => { - if (hasBiometrics) { - void disableAuthentication('biometrics') - } else { - setHasBiometrics(true) - await application?.protections.enableBiometrics() - await setBiometricsTiming(MobileUnlockTiming.OnQuit) - props.updateProtectionsAvailable() - } - } - - const disableBiometrics = useCallback(async () => { - if (await application?.protections.disableBiometrics()) { - setHasBiometrics(false) - props.updateProtectionsAvailable() - } - }, [application, props]) - - const disablePasscode = useCallback(async () => { - const hasAccount = Boolean(application?.hasAccount()) - let message - if (hasAccount) { - message = - 'Are you sure you want to disable your local passcode? This will not affect your encryption status, as your data is currently being encrypted through your sync account keys.' - } else { - message = 'Are you sure you want to disable your local passcode? This will disable encryption on your data.' - } - - const confirmed = await application?.alertService?.confirm( - message, - 'Disable Passcode', - 'Disable Passcode', - undefined, - ) - if (confirmed) { - await application?.removePasscode() - } - }, [application]) - - const disableAuthentication = useCallback( - async (authenticationMethod: 'passcode' | 'biometrics') => { - switch (authenticationMethod) { - case 'biometrics': { - void disableBiometrics() - break - } - case 'passcode': { - void disablePasscode() - break - } - } - }, - [disableBiometrics, disablePasscode], - ) - - return ( - - - - - {storageSubText} - - - - - - - - - {props.hasPasscode && ( - setPasscodeTiming(option.key as MobileUnlockTiming)} - /> - )} - - {hasBiometrics && ( - setBiometricsTiming(option.key as MobileUnlockTiming)} - /> - )} - - ) -} diff --git a/packages/mobile/src/Screens/Settings/Sections/WorkspacesSection.tsx b/packages/mobile/src/Screens/Settings/Sections/WorkspacesSection.tsx deleted file mode 100644 index f49409c51..000000000 --- a/packages/mobile/src/Screens/Settings/Sections/WorkspacesSection.tsx +++ /dev/null @@ -1,199 +0,0 @@ -import { SectionedAccessoryTableCell } from '@Components/SectionedAccessoryTableCell' -import { SectionHeader } from '@Components/SectionHeader' -import { useNavigation } from '@react-navigation/native' -import { TableSection } from '@Root/Components/TableSection' -import { useSafeApplicationContext } from '@Root/Hooks/useSafeApplicationContext' -import { useSafeApplicationGroupContext } from '@Root/Hooks/useSafeApplicationGroupContext' -import { ModalStackNavigationProp } from '@Root/ModalStack' -import { SCREEN_INPUT_MODAL_WORKSPACE_NAME, SCREEN_SETTINGS } from '@Screens/screens' -import { ApplicationDescriptor, ApplicationGroupEvent, ButtonType } from '@standardnotes/snjs' -import { CustomActionSheetOption, useCustomActionSheet } from '@Style/CustomActionSheet' -import React, { useCallback, useEffect, useState } from 'react' - -export const WorkspacesSection = () => { - const application = useSafeApplicationContext() - const appGroup = useSafeApplicationGroupContext() - const navigation = useNavigation['navigation']>() - - const [applicationDescriptors, setApplicationDescriptors] = useState([]) - - enum WorkspaceAction { - AddAnother = 'Add another workspace', - Activate = 'Activate', - Rename = 'Rename', - Remove = 'Remove', - SignOutAll = 'Sign out all workspaces', - } - - useEffect(() => { - let descriptors = appGroup.getDescriptors() - setApplicationDescriptors(descriptors) - - const removeAppGroupObserver = appGroup.addEventObserver((event) => { - if (event === ApplicationGroupEvent.DescriptorsDataChanged) { - descriptors = appGroup.getDescriptors() - setApplicationDescriptors(descriptors) - } - }) - - return () => { - removeAppGroupObserver() - } - }, [appGroup]) - - const { showActionSheet } = useCustomActionSheet() - - const getWorkspaceActionConfirmation = useCallback( - async (action: WorkspaceAction): Promise => { - const { Info, Danger } = ButtonType - const { AddAnother, Activate, Remove, SignOutAll } = WorkspaceAction - let message = '' - let buttonText = '' - let buttonType = Info - - switch (action) { - case Activate: - message = 'Your workspace will be ready for you when you come back.' - buttonText = 'Quit App' - break - case AddAnother: - message = 'Your new workspace will be ready for you when you come back.' - buttonText = 'Quit App' - break - case SignOutAll: - message = - 'Are you sure you want to sign out of all workspaces on this device? This action will restart the application.' - buttonText = 'Sign Out All' - break - case Remove: - message = - 'This action will remove this workspace and its related data from this device. Your synced data will not be affected.\n\nYour app will quit after workspace removal completes.' - buttonText = 'Delete Workspace' - buttonType = Danger - break - default: - break - } - return application.alertService.confirm(message, undefined, buttonText, buttonType) - }, - [WorkspaceAction, application.alertService], - ) - - const renameWorkspace = useCallback( - async (descriptor: ApplicationDescriptor, newName: string) => { - appGroup.renameDescriptor(descriptor, newName) - }, - [appGroup], - ) - - const signOutWorkspace = useCallback(async () => { - const confirmed = await getWorkspaceActionConfirmation(WorkspaceAction.Remove) - - if (!confirmed) { - return - } - - try { - await application.user.signOut() - } catch (error) { - console.error(error) - } - }, [WorkspaceAction.Remove, application.user, getWorkspaceActionConfirmation]) - - const openWorkspace = useCallback( - async (descriptor: ApplicationDescriptor) => { - const confirmed = await getWorkspaceActionConfirmation(WorkspaceAction.Activate) - if (!confirmed) { - return - } - - await appGroup.unloadCurrentAndActivateDescriptor(descriptor) - }, - [WorkspaceAction.Activate, appGroup, getWorkspaceActionConfirmation], - ) - - const getSingleWorkspaceItemOptions = useCallback( - (descriptor: ApplicationDescriptor) => { - const { Activate, Rename, Remove } = WorkspaceAction - const worskspaceItemOptions: CustomActionSheetOption[] = [] - - if (descriptor.primary) { - worskspaceItemOptions.push( - { - text: Rename, - callback: () => { - navigation.navigate(SCREEN_INPUT_MODAL_WORKSPACE_NAME, { - descriptor, - renameWorkspace, - }) - }, - }, - { - text: Remove, - destructive: true, - callback: signOutWorkspace, - }, - ) - } else { - worskspaceItemOptions.push({ - text: Activate, - callback: () => openWorkspace(descriptor), - }) - } - - return worskspaceItemOptions - }, - [WorkspaceAction, navigation, openWorkspace, renameWorkspace, signOutWorkspace], - ) - - const addAnotherWorkspace = useCallback(async () => { - const confirmed = await getWorkspaceActionConfirmation(WorkspaceAction.AddAnother) - if (!confirmed) { - return - } - - await appGroup.unloadCurrentAndCreateNewDescriptor() - }, [WorkspaceAction.AddAnother, appGroup, getWorkspaceActionConfirmation]) - - const signOutAllWorkspaces = useCallback(async () => { - try { - const confirmed = await getWorkspaceActionConfirmation(WorkspaceAction.SignOutAll) - if (!confirmed) { - return - } - await appGroup.signOutAllWorkspaces() - } catch (error) { - console.error(error) - } - }, [WorkspaceAction.SignOutAll, appGroup, getWorkspaceActionConfirmation]) - - return ( - - - {applicationDescriptors.map((descriptor, index) => { - return ( - { - const singleItemOptions = getSingleWorkspaceItemOptions(descriptor) - - showActionSheet({ - title: '', - options: singleItemOptions, - }) - }} - key={descriptor.identifier} - text={descriptor.label} - first={index === 0} - selected={() => descriptor.primary} - /> - ) - })} - - - - ) -} diff --git a/packages/mobile/src/Screens/Settings/Settings.styled.ts b/packages/mobile/src/Screens/Settings/Settings.styled.ts deleted file mode 100644 index 298e35f06..000000000 --- a/packages/mobile/src/Screens/Settings/Settings.styled.ts +++ /dev/null @@ -1,5 +0,0 @@ -import styled from 'styled-components/native' - -export const Container = styled.ScrollView` - background-color: ${({ theme }) => theme.stylekitBackgroundColor}; -` diff --git a/packages/mobile/src/Screens/Settings/Settings.tsx b/packages/mobile/src/Screens/Settings/Settings.tsx deleted file mode 100644 index 4ba4814b0..000000000 --- a/packages/mobile/src/Screens/Settings/Settings.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { useSignedIn } from '@Lib/SnjsHelperHooks' -import { useSafeApplicationContext } from '@Root/Hooks/useSafeApplicationContext' -import { ModalStackNavigationProp } from '@Root/ModalStack' -import { SCREEN_SETTINGS } from '@Root/Screens/screens' -import { FilesSection } from '@Screens/Settings/Sections/FilesSection' -import { WorkspacesSection } from '@Screens/Settings/Sections/WorkspacesSection' -import { ApplicationEvent, FeatureIdentifier, FeatureStatus } from '@standardnotes/snjs' -import React, { useCallback, useEffect, useState } from 'react' -import { AuthSection } from './Sections/AuthSection' -import { CompanySection } from './Sections/CompanySection' -import { DeleteSection } from './Sections/DeleteSection' -import { EncryptionSection } from './Sections/EncryptionSection' -import { NewMobileSection } from './Sections/NewMobilePreview' -import { OptionsSection } from './Sections/OptionsSection' -import { PreferencesSection } from './Sections/PreferencesSection' -import { ProtectionsSection } from './Sections/ProtectionsSection' -import { SecuritySection } from './Sections/SecuritySection' -import { Container } from './Settings.styled' - -type Props = ModalStackNavigationProp -export const Settings = (props: Props) => { - // Context - const application = useSafeApplicationContext() - - // State - const [hasPasscode, setHasPasscode] = useState(() => Boolean(application.hasPasscode())) - const [protectionsAvailable, setProtectionsAvailable] = useState(application.hasProtectionSources()) - const [encryptionAvailable, setEncryptionAvailable] = useState(() => application.isEncryptionAvailable()) - - const updateProtectionsAvailable = useCallback(() => { - setProtectionsAvailable(application.hasProtectionSources()) - }, [application]) - - useEffect(() => { - const removeApplicationEventSubscriber = application.addEventObserver(async (event) => { - if (event === ApplicationEvent.KeyStatusChanged) { - setHasPasscode(Boolean(application.hasPasscode())) - updateProtectionsAvailable() - setEncryptionAvailable(() => application.isEncryptionAvailable()) - } - }) - return () => { - removeApplicationEventSubscriber && removeApplicationEventSubscriber() - } - }, [application, updateProtectionsAvailable]) - - const goBack = useCallback(() => { - props.navigation.goBack() - }, [props.navigation]) - - const [signedIn] = useSignedIn(goBack) - - const isEntitledToFiles = application.features.getFeatureStatus(FeatureIdentifier.Files) === FeatureStatus.Entitled - - return ( - - - - - - - {application.hasAccount() && isEntitledToFiles && } - - - - - {application.hasAccount() && } - - ) -} diff --git a/packages/mobile/src/Screens/SideMenu/Files.styled.ts b/packages/mobile/src/Screens/SideMenu/Files.styled.ts deleted file mode 100644 index 13a9119f2..000000000 --- a/packages/mobile/src/Screens/SideMenu/Files.styled.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { SnIcon } from '@Root/Components/SnIcon' -import { SideMenuCell } from '@Root/Screens/SideMenu/SideMenuCell' -import { Platform, StyleSheet } from 'react-native' -import styled from 'styled-components/native' - -export const styles = StyleSheet.create({ - cellContentStyle: { - flexShrink: 0, - }, - learnMoreIcon: { - marginTop: Platform.OS === 'ios' ? -6 : -3, - }, -}) -export const SNIconStyled = styled(SnIcon)` - margin-left: 8px; -` -export const FilesContainer = styled.View` - margin-top: 10px; -` -export const FileItemContainer = styled.View` - margin-bottom: 18px; -` -export const IconsContainer = styled.View` - flex-direction: row; - margin-top: ${() => (Platform.OS === 'ios' ? 0 : '5px')}; -` -export const SideMenuCellStyled = styled(SideMenuCell)` - min-height: 22px; -` -export const SideMenuCellAttachNewFile = styled(SideMenuCellStyled)` - margin-bottom: 14px; -` -export const SideMenuCellShowAllFiles = styled(SideMenuCellStyled)` - margin-bottom: 8px; -` diff --git a/packages/mobile/src/Screens/SideMenu/Files.tsx b/packages/mobile/src/Screens/SideMenu/Files.tsx deleted file mode 100644 index 31933f0fd..000000000 --- a/packages/mobile/src/Screens/SideMenu/Files.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { SnIcon } from '@Components/SnIcon' -import { useNavigation } from '@react-navigation/native' -import { AppStackNavigationProp } from '@Root/AppStack' -import { useFiles } from '@Root/Hooks/useFiles' -import { useSafeApplicationContext } from '@Root/Hooks/useSafeApplicationContext' -import { SCREEN_COMPOSE, SCREEN_UPLOADED_FILES_LIST } from '@Root/Screens/screens' -import { - FileItemContainer, - FilesContainer, - IconsContainer, - SideMenuCellAttachNewFile, - SideMenuCellShowAllFiles, - SideMenuCellStyled, - SNIconStyled, - styles, -} from '@Root/Screens/SideMenu/Files.styled' -import { SideMenuOptionIconDescriptionType } from '@Root/Screens/SideMenu/SideMenuSection' -import { SideMenuCell } from '@Screens/SideMenu/SideMenuCell' -import { UploadedFileItemActionType } from '@Screens/UploadedFilesList/UploadedFileItemAction' -import { FeatureIdentifier, FeatureStatus, SNNote } from '@standardnotes/snjs' -import React, { FC } from 'react' - -type Props = { - note: SNNote -} - -export const Files: FC = ({ note }) => { - const application = useSafeApplicationContext() - const filesService = application.getFilesService() - - const navigation = useNavigation['navigation']>() - const { showActionsMenu, handlePressAttachFile, attachedFiles, handleFileAction } = useFiles({ note }) - - const isEntitledToFiles = application.features.getFeatureStatus(FeatureIdentifier.Files) === FeatureStatus.Entitled - - const openFilesScreen = () => { - navigation.navigate(SCREEN_UPLOADED_FILES_LIST, { note }) - } - - if (!isEntitledToFiles) { - return ( - application.deviceInterface.openUrl('https://standardnotes.com/plans')} - iconDesc={{ - side: 'left', - type: SideMenuOptionIconDescriptionType.CustomComponent, - value: , - }} - /> - ) - } - - return ( - - {attachedFiles.sort(filesService.sortByName).map((file) => { - const iconType = application.iconsController.getIconForFileType(file.mimeType) - - return ( - - { - void handleFileAction({ - type: UploadedFileItemActionType.PreviewFile, - payload: file, - }) - }} - onLongPress={() => showActionsMenu(file)} - iconDesc={{ - side: 'right', - type: SideMenuOptionIconDescriptionType.CustomComponent, - value: ( - - {file.protected && } - - - ), - }} - cellContentStyle={styles.cellContentStyle} - /> - - ) - })} - handlePressAttachFile()} /> - openFilesScreen()} - cellContentStyle={styles.cellContentStyle} - /> - - ) -} diff --git a/packages/mobile/src/Screens/SideMenu/Listed.styled.ts b/packages/mobile/src/Screens/SideMenu/Listed.styled.ts deleted file mode 100644 index eaf24903e..000000000 --- a/packages/mobile/src/Screens/SideMenu/Listed.styled.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Platform, StyleSheet } from 'react-native' -import styled from 'styled-components/native' - -export const styles = StyleSheet.create({ - blogItemIcon: { - marginTop: Platform.OS === 'ios' ? -6 : -3, - }, - loadingIndicator: { - alignSelf: 'flex-start', - }, - blogActionInProgressIndicator: { - marginTop: -5, - marginLeft: 6, - transform: [ - { - scale: 0.8, - }, - ], - }, -}) -export const CreateBlogContainer = styled.View` - margin-bottom: 8px; -` -export const CantLoadActionsText = styled.Text` - font-size: 12px; - margin-top: -12px; - margin-bottom: 10px; - opacity: 0.7; - color: ${({ theme }) => theme.stylekitContrastForegroundColor}; -` -export const ListedItemRow = styled.View` - display: flex; - flex-direction: row; - align-items: center; -` diff --git a/packages/mobile/src/Screens/SideMenu/Listed.tsx b/packages/mobile/src/Screens/SideMenu/Listed.tsx deleted file mode 100644 index 32621282b..000000000 --- a/packages/mobile/src/Screens/SideMenu/Listed.tsx +++ /dev/null @@ -1,190 +0,0 @@ -import { SnIcon } from '@Root/Components/SnIcon' -import { useSafeApplicationContext } from '@Root/Hooks/useSafeApplicationContext' -import { CantLoadActionsText, CreateBlogContainer, ListedItemRow, styles } from '@Root/Screens/SideMenu/Listed.styled' -import { SideMenuCell } from '@Root/Screens/SideMenu/SideMenuCell' -import { SideMenuOptionIconDescriptionType } from '@Root/Screens/SideMenu/SideMenuSection' -import { Action, ButtonType, ListedAccount, ListedAccountInfo, SNNote } from '@standardnotes/snjs' -import { useCustomActionSheet } from '@Style/CustomActionSheet' -import React, { FC, useCallback, useEffect, useState } from 'react' -import { ActivityIndicator, FlatList, View } from 'react-native' - -type TProps = { - note: SNNote -} - -type TListedAccountItem = ListedAccountInfo | Pick - -export const Listed: FC = ({ note }) => { - const application = useSafeApplicationContext() - - const [isLoading, setIsLoading] = useState(false) - const [isActionInProgress, setIsActionInProgress] = useState(false) - const [isRequestingAccount, setIsRequestingAccount] = useState(false) - - const [listedAccounts, setListedAccounts] = useState([]) - const [listedAccountDetails, setListedAccountDetails] = useState([]) - const [authorUrlWithInProgressAction, setAuthorUrlWithInProgressAction] = useState(null) - - const { showActionSheet } = useCustomActionSheet() - - const getListedAccountsDetails = useCallback( - async (accounts: ListedAccount[]) => { - const listedAccountsArray: TListedAccountItem[] = [] - - for (const listedAccountItem of accounts) { - const listedItemInfo = await application.getListedAccountInfo(listedAccountItem, note?.uuid) - - listedAccountsArray.push(listedItemInfo ? listedItemInfo : { display_name: listedAccountItem.authorId }) - } - return listedAccountsArray - }, - [application, note?.uuid], - ) - - const reloadListedAccounts = useCallback(async () => { - setIsLoading(true) - const accounts = await application.getListedAccounts() - setListedAccounts(accounts) - - setListedAccountDetails((await getListedAccountsDetails(accounts)) || []) - setIsLoading(false) - }, [application, getListedAccountsDetails]) - - const registerNewAccount = useCallback(() => { - if (isRequestingAccount) { - return - } - - const requestAccount = async () => { - setIsRequestingAccount(true) - const account = await application.requestNewListedAccount() - if (account) { - const openSettings = await application.alertService.confirm( - 'Your new Listed blog has been successfully created!' + - ' You can publish a new post to your blog from Standard Notes via the' + - ' Actions menu in the editor pane. Open your blog settings to begin setting it up.', - undefined, - 'Open Settings', - ButtonType.Info, - 'Later', - ) - void reloadListedAccounts() - - if (openSettings) { - const info = await application.getListedAccountInfo(account) - if (info) { - application.deviceInterface.openUrl(info?.settings_url) - } - } - } - setIsRequestingAccount(false) - } - - void requestAccount() - }, [application, isRequestingAccount, reloadListedAccounts]) - - useEffect(() => { - const loadListedData = async () => { - await reloadListedAccounts() - } - void loadListedData() - }, [reloadListedAccounts]) - - const doesListedItemHaveActions = (item: TListedAccountItem): item is ListedAccountInfo => { - return (item as ListedAccountInfo).author_url !== undefined - } - - const showActionsMenu = (item: TListedAccountItem, index: number) => { - if (!doesListedItemHaveActions(item)) { - void application.alertService.alert('Unable to load actions.') - return - } - - showActionSheet({ - title: item.display_name, - options: item.actions.map((action) => ({ - text: (action as Action).label, - callback: async () => { - setIsActionInProgress(true) - setAuthorUrlWithInProgressAction(item.author_url) - - const response = await application.actionsManager.runAction(action as Action, note) - - if (!response || response.error) { - setIsActionInProgress(false) - setAuthorUrlWithInProgressAction(null) - return - } - const listedDetails = (await getListedAccountsDetails(listedAccounts)) as TListedAccountItem[] - setListedAccountDetails(listedDetails) - - showActionsMenu(listedDetails[index], index) - setIsActionInProgress(false) - setAuthorUrlWithInProgressAction(null) - }, - })), - }) - } - - return ( - - {isLoading && } - {listedAccountDetails.length > 0 && ( - { - if (!item) { - return null - } - return ( - - - showActionsMenu(item, index)} - iconDesc={{ - side: 'left', - type: SideMenuOptionIconDescriptionType.CustomComponent, - value: , - }} - /> - {isActionInProgress && (item as ListedAccountInfo).author_url === authorUrlWithInProgressAction && ( - - )} - - {!isLoading && !doesListedItemHaveActions(item) && ( - Unable to load actions - )} - - ) - }} - /> - )} - - - , - }} - /> - {isRequestingAccount && } - - - application.deviceInterface.openUrl('https://listed.to')} - iconDesc={{ - side: 'left', - type: SideMenuOptionIconDescriptionType.CustomComponent, - value: , - }} - /> - - - - ) -} diff --git a/packages/mobile/src/Screens/SideMenu/MainSideMenu.styled.ts b/packages/mobile/src/Screens/SideMenu/MainSideMenu.styled.ts deleted file mode 100644 index abf551a04..000000000 --- a/packages/mobile/src/Screens/SideMenu/MainSideMenu.styled.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { useMemo } from 'react' -import { Platform, SafeAreaView, StatusBar, StyleSheet } from 'react-native' -import styled, { css, DefaultTheme } from 'styled-components/native' - -// We want top color to be different from bottom color of safe area. -// See https://stackoverflow.com/questions/47725607/react-native-safeareaview-background-color-how-to-assign-two-different-backgro -export const FirstSafeAreaView = styled(SafeAreaView)` - flex: 0; - background-color: ${({ theme }) => theme.stylekitContrastBackgroundColor}; - ${Platform.OS === 'android' && - css` - margin-top: ${StatusBar.currentHeight}px; - `}; -` -export const MainSafeAreaView = styled(SafeAreaView)` - flex: 1; - background-color: ${({ theme }) => theme.stylekitBackgroundColor}; - color: ${({ theme }) => theme.stylekitForegroundColor}; -` - -/** Styled doesn't support FlatList types */ -export const useStyles = (theme: DefaultTheme) => { - return useMemo( - () => - StyleSheet.create({ - sections: { - padding: 15, - flex: 1, - backgroundColor: theme.stylekitBackgroundColor, - }, - }), - [theme.stylekitBackgroundColor], - ) -} diff --git a/packages/mobile/src/Screens/SideMenu/MainSideMenu.tsx b/packages/mobile/src/Screens/SideMenu/MainSideMenu.tsx deleted file mode 100644 index 95c3c9506..000000000 --- a/packages/mobile/src/Screens/SideMenu/MainSideMenu.tsx +++ /dev/null @@ -1,295 +0,0 @@ -import { AppStateType } from '@Lib/ApplicationState' -import { useNavigation } from '@react-navigation/native' -import { ApplicationContext } from '@Root/ApplicationContext' -import { SCREEN_SETTINGS } from '@Root/Screens/screens' -import { MobileTheme } from '@Root/Style/MobileTheme' -import { ContentType, SmartView, SNTag, SNTheme } from '@standardnotes/snjs' -import { CustomActionSheetOption, useCustomActionSheet } from '@Style/CustomActionSheet' -import { ICON_BRUSH, ICON_SETTINGS } from '@Style/Icons' -import { ThemeService, ThemeServiceContext } from '@Style/ThemeService' -import React, { Fragment, useCallback, useContext, useEffect, useMemo, useState } from 'react' -import { Platform } from 'react-native' -import FAB from 'react-native-fab' -import { FlatList } from 'react-native-gesture-handler' -import DrawerLayout from 'react-native-gesture-handler/DrawerLayout' -import Icon from 'react-native-vector-icons/Ionicons' -import { ThemeContext } from 'styled-components' -import { FirstSafeAreaView, MainSafeAreaView, useStyles } from './MainSideMenu.styled' -import { SideMenuHero } from './SideMenuHero' -import { SideMenuOption, SideMenuOptionIconDescriptionType, SideMenuSection } from './SideMenuSection' -import { TagSelectionList } from './TagSelectionList' - -type Props = { - drawerRef: DrawerLayout | null -} - -export const MainSideMenu = React.memo(({ drawerRef }: Props) => { - // Context - const theme = useContext(ThemeContext) - const themeService = useContext(ThemeServiceContext) - const application = useContext(ApplicationContext) - const navigation = useNavigation() - const { showActionSheet } = useCustomActionSheet() - // State - const [selectedTag, setSelectedTag] = useState(() => application!.getAppState().getSelectedTag()) - const [themes, setThemes] = useState([]) - const styles = useStyles(theme) - - useEffect(() => { - const removeTagChangeObserver = application!.getAppState().addStateChangeObserver((state) => { - if (state === AppStateType.TagChanged) { - setSelectedTag(application!.getAppState().getSelectedTag()) - } - }) - return removeTagChangeObserver - }) - - const onSystemThemeSelect = useCallback( - async (selectedTheme: MobileTheme) => { - themeService?.activateSystemTheme(selectedTheme.uuid) - }, - [themeService], - ) - - const onThemeSelect = useCallback( - async (selectedTheme: SNTheme) => { - void themeService?.activateExternalTheme(selectedTheme) - }, - [themeService], - ) - - const onThemeLongPress = useCallback( - async (themeId: string, name: string, snTheme?: SNTheme) => { - const options: CustomActionSheetOption[] = [] - /** - * If this theme is a mobile theme, allow it to be set as the preferred - * option for light/dark mode. - */ - if ((snTheme && !snTheme.getNotAvailOnMobile()) || !snTheme) { - const activeLightTheme = await themeService?.getThemeForMode('light') - const lightThemeAction = activeLightTheme === themeId ? 'Current' : 'Set as' - const lightName = ThemeService.doesDeviceSupportDarkMode() ? 'Light' : 'Active' - const text = `${lightThemeAction} ${lightName} Theme` - options.push({ - text, - callback: () => { - if (snTheme) { - void themeService?.assignExternalThemeForMode(snTheme, 'light') - } else { - void themeService?.assignThemeForMode(themeId, 'light') - } - }, - }) - } - /** - * Only display a dark mode option if this device supports dark mode. - */ - if (ThemeService.doesDeviceSupportDarkMode()) { - const activeDarkTheme = await themeService?.getThemeForMode('dark') - const darkThemeAction = activeDarkTheme === themeId ? 'Current' : 'Set as' - const text = `${darkThemeAction} Dark Theme` - options.push({ - text, - callback: () => { - if (snTheme) { - void themeService?.assignExternalThemeForMode(snTheme, 'dark') - } else { - void themeService?.assignThemeForMode(themeId, 'dark') - } - }, - }) - } - /** - * System themes cannot be redownloaded. - */ - if (snTheme) { - options.push({ - text: 'Redownload', - callback: async () => { - const confirmed = await application?.alertService.confirm( - 'Themes are cached when downloaded. To retrieve the latest version, press Redownload.', - 'Redownload Theme', - 'Redownload', - ) - if (confirmed) { - void themeService?.downloadThemeAndReload(snTheme) - } - }, - }) - } - showActionSheet({ - title: name, - options, - }) - }, - [application?.alertService, showActionSheet, themeService], - ) - - useEffect(() => { - const unsubscribeStreamThemes = application?.streamItems(ContentType.Theme, () => { - const newItems = application.items.getItems(ContentType.Theme) - setThemes(newItems as SNTheme[]) - }) - - return unsubscribeStreamThemes - }, [application]) - - const iconDescriptorForTheme = (currentTheme: SNTheme | MobileTheme) => { - const desc = { - type: SideMenuOptionIconDescriptionType.Circle, - side: 'right' as const, - } - - const dockIcon = currentTheme.package_info && currentTheme.package_info.dock_icon - - if (dockIcon && dockIcon.type === 'circle') { - Object.assign(desc, { - backgroundColor: dockIcon.background_color, - borderColor: dockIcon.border_color, - }) - } else { - Object.assign(desc, { - backgroundColor: theme.stylekitInfoColor, - borderColor: theme.stylekitInfoColor, - }) - } - - return desc - } - - const themeOptions = useMemo(() => { - const options: SideMenuOption[] = themeService! - .systemThemes() - .map((systemTheme) => ({ - text: systemTheme?.name, - key: systemTheme?.uuid, - iconDesc: iconDescriptorForTheme(systemTheme), - dimmed: false, - onSelect: () => onSystemThemeSelect(systemTheme), - onLongPress: () => onThemeLongPress(systemTheme?.uuid, systemTheme?.name), - selected: themeService!.activeThemeId === systemTheme?.uuid, - })) - .concat( - themes - .sort((a, b) => a.name.localeCompare(b.name)) - .map((mapTheme) => ({ - text: mapTheme.name, - key: mapTheme.uuid, - iconDesc: iconDescriptorForTheme(mapTheme), - dimmed: !!mapTheme.getNotAvailOnMobile(), - onSelect: () => onThemeSelect(mapTheme), - onLongPress: () => onThemeLongPress(mapTheme?.uuid, mapTheme?.name, mapTheme), - selected: themeService!.activeThemeId === mapTheme.uuid, - })), - ) - - if (options.length === themeService!.systemThemes().length) { - options.push({ - text: 'Get More Themes', - key: 'get-theme', - iconDesc: { - type: SideMenuOptionIconDescriptionType.Icon, - name: ThemeService.nameForIcon(ICON_BRUSH), - side: 'right', - size: 17, - }, - onSelect: () => { - application?.deviceInterface?.openUrl('https://standardnotes.com/plans') - }, - }) - } - - return options - // We want to also track activeThemeId - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [themeService, themeService?.activeThemeId, themes, onSystemThemeSelect, onThemeSelect]) - - const onTagSelect = useCallback( - async (tag: SNTag | SmartView) => { - if (tag.conflictOf) { - void application!.mutator.changeAndSaveItem(tag, (mutator) => { - mutator.conflictOf = undefined - }) - } - application?.getAppState().setSelectedTag(tag, true) - drawerRef?.closeDrawer() - }, - [application, drawerRef], - ) - - const openSettings = () => { - drawerRef?.closeDrawer() - navigation?.navigate(SCREEN_SETTINGS as never) - } - - const outOfSyncPressed = async () => { - const confirmed = await application!.alertService!.confirm( - "We've detected that the data in the current application session may " + - 'not match the data on the server. This can happen due to poor ' + - 'network conditions, or if a large note fails to download on your ' + - 'device. To resolve this issue, we recommend first creating a backup ' + - 'of your data in the Settings screen, then signing out of your account ' + - 'and signing back in.', - 'Potentially Out of Sync', - 'Open Settings', - undefined, - ) - if (confirmed) { - openSettings() - } - } - - const selectedTags: SNTag[] | SmartView[] = useMemo( - () => (selectedTag ? ([selectedTag] as SNTag[] | SmartView[]) : []), - [selectedTag], - ) - - return ( - - - - - ({ - key, - themeOptions, - onTagSelect, - selectedTags, - }))} - renderItem={({ item, index }) => { - return index === 0 ? ( - - ) : index === 1 ? ( - - - - ) : index === 2 ? ( - - - - ) : null - }} - /> - } - /> - - - ) -}) diff --git a/packages/mobile/src/Screens/SideMenu/NoteSideMenu.styled.ts b/packages/mobile/src/Screens/SideMenu/NoteSideMenu.styled.ts deleted file mode 100644 index 4b0559e14..000000000 --- a/packages/mobile/src/Screens/SideMenu/NoteSideMenu.styled.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { useMemo } from 'react' -import { StyleSheet } from 'react-native' -import { ScrollView } from 'react-native-gesture-handler' -import { SafeAreaView } from 'react-native-safe-area-context' -import styled, { DefaultTheme } from 'styled-components/native' - -export const SafeAreaContainer = styled(SafeAreaView)` - flex: 1; - background-color: ${({ theme }) => theme.stylekitBackgroundColor}; - color: ${({ theme }) => theme.stylekitForegroundColor}; -` - -export const StyledList = styled(ScrollView)` - padding: 15px; - background-color: ${({ theme }) => theme.stylekitBackgroundColor}; -` - -export const useStyles = (theme: DefaultTheme) => { - return useMemo( - () => - StyleSheet.create({ - sections: { - padding: 15, - backgroundColor: theme.stylekitBackgroundColor, - }, - }), - [theme.stylekitBackgroundColor], - ) -} diff --git a/packages/mobile/src/Screens/SideMenu/NoteSideMenu.tsx b/packages/mobile/src/Screens/SideMenu/NoteSideMenu.tsx deleted file mode 100644 index dd2ec975e..000000000 --- a/packages/mobile/src/Screens/SideMenu/NoteSideMenu.tsx +++ /dev/null @@ -1,675 +0,0 @@ -import { associateComponentWithNote } from '@Lib/ComponentManager' -import { useChangeNote, useDeleteNoteWithPrivileges, useProtectOrUnprotectNote } from '@Lib/SnjsHelperHooks' -import { useFocusEffect, useNavigation } from '@react-navigation/native' -import { AppStackNavigationProp } from '@Root/AppStack' -import { useSafeApplicationContext } from '@Root/Hooks/useSafeApplicationContext' -import { SCREEN_COMPOSE, SCREEN_INPUT_MODAL_TAG, SCREEN_NOTE_HISTORY } from '@Root/Screens/screens' -import { Files } from '@Root/Screens/SideMenu/Files' -import { Listed } from '@Root/Screens/SideMenu/Listed' -import { - ApplicationEvent, - ButtonType, - ComponentArea, - ComponentMutator, - ContentType, - FeatureIdentifier, - FeatureStatus, - FindNativeFeature, - NoteMutator, - NoteViewController, - PayloadEmitSource, - PrefKey, - SmartView, - SNComponent, - SNNote, - SNTag, -} from '@standardnotes/snjs' -import { useCustomActionSheet } from '@Style/CustomActionSheet' -import { - ICON_ARCHIVE, - ICON_BOOKMARK, - ICON_FINGER_PRINT, - ICON_HISTORY, - ICON_LOCK, - ICON_MEDICAL, - ICON_PRICE_TAG, - ICON_SHARE, - ICON_TRASH, -} from '@Style/Icons' -import { ThemeService } from '@Style/ThemeService' -import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react' -import { Platform, Share } from 'react-native' -import FAB from 'react-native-fab' -import { FlatList } from 'react-native-gesture-handler' -import DrawerLayout from 'react-native-gesture-handler/DrawerLayout' -import Icon from 'react-native-vector-icons/Ionicons' -import { ThemeContext } from 'styled-components' -import { SafeAreaContainer, useStyles } from './NoteSideMenu.styled' -import { SideMenuOption, SideMenuOptionIconDescriptionType, SideMenuSection } from './SideMenuSection' -import { TagSelectionList } from './TagSelectionList' - -function sortAlphabetically(array: SNComponent[]): SNComponent[] { - return array.sort((a, b) => { - const aName = FindNativeFeature(a.identifier)?.name || a.name - const bName = FindNativeFeature(b.identifier)?.name || b.name - return aName.toLowerCase() < bName.toLowerCase() ? -1 : 1 - }) -} - -type Props = { - drawerRef: DrawerLayout | null - drawerOpen: boolean -} - -function useEditorComponents(): SNComponent[] { - const application = useSafeApplicationContext() - const [components, setComponents] = useState([]) - useEffect(() => { - const removeComponentsObserver = application.streamItems(ContentType.Component, () => { - const displayComponents = sortAlphabetically(application.componentManager.componentsForArea(ComponentArea.Editor)) - setComponents(displayComponents) - }) - return () => { - if (application) { - removeComponentsObserver() - } - } - }, [application]) - - return components -} - -export const NoteSideMenu = React.memo((props: Props) => { - // Context - const theme = useContext(ThemeContext) - const application = useSafeApplicationContext() - - const navigation = useNavigation['navigation']>() - const { showActionSheet } = useCustomActionSheet() - const styles = useStyles(theme) - - // State - const [editor, setEditor] = useState(undefined) - const [note, setNote] = useState(undefined) - const [selectedTags, setSelectedTags] = useState([]) - const [attachedFilesLength, setAttachedFilesLength] = useState(0) - - const [shouldAddTagHierarchy, setShouldAddTagHierachy] = useState(() => - application.getPreference(PrefKey.NoteAddToParentFolders, true), - ) - - useEffect(() => { - const removeEventObserver = application.addSingleEventObserver(ApplicationEvent.PreferencesChanged, async () => { - setShouldAddTagHierachy(application.getPreference(PrefKey.NoteAddToParentFolders, true)) - }) - - return () => { - removeEventObserver() - } - }, [application]) - - const components = useEditorComponents() - - const [changeNote] = useChangeNote(note, editor) - const [protectOrUnprotectNote] = useProtectOrUnprotectNote(note, editor) - - const [deleteNote] = useDeleteNoteWithPrivileges( - note!, - async () => { - await application.mutator.deleteItem(note!) - props.drawerRef?.closeDrawer() - if (!application.getAppState().isInTabletMode) { - navigation.popToTop() - } - }, - () => { - void changeNote((mutator) => { - mutator.trashed = true - }, false) - props.drawerRef?.closeDrawer() - if (!application.getAppState().isInTabletMode) { - navigation.popToTop() - } - }, - editor, - ) - - useEffect(() => { - if (!note) { - setAttachedFilesLength(0) - return - } - setAttachedFilesLength(application.items.getSortedFilesLinkingToItem(note).length) - }, [application, note]) - - useEffect(() => { - if (!note) { - return - } - const removeFilesObserver = application.streamItems(ContentType.File, () => { - setAttachedFilesLength(application.items.getSortedFilesLinkingToItem(note).length) - }) - return () => { - removeFilesObserver() - } - }, [application, note]) - - useEffect(() => { - let mounted = true - if ((!editor || props.drawerOpen) && mounted) { - const initialEditor = application.editorGroup.activeItemViewController as NoteViewController - const tempNote = initialEditor?.item - setEditor(initialEditor) - setNote(tempNote) - } - return () => { - mounted = false - } - }, [application, editor, props.drawerOpen]) - - useEffect(() => { - let mounted = true - const removeEditorObserver = application.editorGroup.addActiveControllerChangeObserver(() => { - if (mounted) { - const activeController = application.editorGroup.activeItemViewController as NoteViewController - setNote(activeController?.item) - setEditor(activeController) - } - }) - - return () => { - mounted = false - removeEditorObserver && removeEditorObserver() - } - }, [application]) - - const reloadTags = useCallback(() => { - if (note) { - const tags = application.getAppState().getNoteTags(note) - setSelectedTags(tags) - } - }, [application, note]) - - useEffect(() => { - let mounted = true - const removeObserver = editor?.addNoteInnerValueChangeObserver((newNote, source) => { - if (mounted && props.drawerOpen) { - if (source !== PayloadEmitSource.ComponentRetrieved) { - setNote(newNote) - } - } - }) - return () => { - if (removeObserver) { - removeObserver() - } - mounted = false - } - }, [editor, note?.uuid, props.drawerOpen, reloadTags]) - - useEffect(() => { - let isMounted = true - const removeTagsObserver = application.streamItems(ContentType.Tag, () => { - if (!note) { - return - } - if (isMounted && props.drawerOpen) { - reloadTags() - } - return () => { - isMounted = false - removeTagsObserver && removeTagsObserver() - } - }) - }, [application, note, props.drawerOpen, reloadTags]) - - const disassociateComponentWithCurrentNote = useCallback( - async (component: SNComponent) => { - if (note) { - return application.mutator.changeItem(component, (m) => { - const mutator = m as ComponentMutator - mutator.removeAssociatedItemId(note.uuid) - mutator.disassociateWithItem(note.uuid) - }) - } - return - }, - [application, note], - ) - - const onEditorPress = useCallback( - async (selectedComponent?: SNComponent) => { - if (!note) { - return - } - if (note?.locked) { - void application.alertService.alert( - "This note has editing disabled. If you'd like to edit its options, enable editing on it, and try again.", - ) - return - } - if (editor?.isTemplateNote) { - await editor?.insertTemplatedNote() - } - const activeEditorComponent = application.componentManager.editorForNote(note) - props.drawerRef?.closeDrawer() - if (!selectedComponent) { - if (!note?.prefersPlainEditor) { - await application.mutator.changeItem( - note, - (mutator) => { - const noteMutator = mutator as NoteMutator - noteMutator.prefersPlainEditor = true - }, - false, - ) - } - if (activeEditorComponent?.isExplicitlyEnabledForItem(note.uuid) || activeEditorComponent?.isMobileDefault) { - await disassociateComponentWithCurrentNote(activeEditorComponent) - } - } else if (selectedComponent.area === ComponentArea.Editor) { - const currentEditor = activeEditorComponent - if (currentEditor && selectedComponent !== currentEditor) { - await disassociateComponentWithCurrentNote(currentEditor) - } - const prefersPlain = note.prefersPlainEditor - if (prefersPlain) { - await application.mutator.changeItem( - note, - (mutator) => { - const noteMutator = mutator as NoteMutator - noteMutator.prefersPlainEditor = false - }, - false, - ) - } - await associateComponentWithNote(application, selectedComponent, note) - } - /** Dirtying can happen above */ - void application.sync.sync() - }, - [application, disassociateComponentWithCurrentNote, editor, note, props.drawerRef], - ) - - const onEdtiorLongPress = useCallback( - async (component?: SNComponent) => { - const currentDefault = application.componentManager - .componentsForArea(ComponentArea.Editor) - .filter((e) => e.isMobileDefault)[0] - - let isDefault = false - if (!component) { - // System editor - if (currentDefault) { - isDefault = false - } - } else { - isDefault = component.isMobileDefault - } - - let action = isDefault ? 'Remove as Mobile Default' : 'Set as Mobile Default' - if (!component && !currentDefault) { - // Long pressing on plain editor while it is default, no actions available - action = 'Is Mobile Default' - } - - const setAsDefault = () => { - if (currentDefault) { - void application.mutator.changeItem(currentDefault, (m) => { - const mutator = m as ComponentMutator - mutator.isMobileDefault = false - }) - } - - if (component) { - void application.mutator.changeAndSaveItem(component, (m) => { - const mutator = m as ComponentMutator - mutator.isMobileDefault = true - }) - } - } - - const removeAsDefault = () => { - void application.mutator.changeItem(currentDefault, (m) => { - const mutator = m as ComponentMutator - mutator.isMobileDefault = false - }) - } - - showActionSheet({ - title: component?.name ?? 'Plain text', - options: [ - { - text: action, - callback: () => { - if (!component) { - setAsDefault() - } else { - if (isDefault) { - removeAsDefault() - } else { - setAsDefault() - } - } - }, - }, - ], - }) - }, - [application, showActionSheet], - ) - - const editors = useMemo(() => { - if (!note) { - return [] - } - const componentEditor = application.componentManager.editorForNote(note) - const options: SideMenuOption[] = [ - { - text: 'Plain text', - key: 'plain-editor', - selected: !componentEditor, - onSelect: () => { - void onEditorPress(undefined) - }, - onLongPress: () => { - void onEdtiorLongPress(undefined) - }, - }, - ] - components.map((component) => { - options.push({ - text: FindNativeFeature(component.identifier)?.name || component.name, - subtext: component.isMobileDefault ? 'Mobile Default' : undefined, - key: component.uuid || component.name, - selected: component.uuid === componentEditor?.uuid, - onSelect: () => { - void onEditorPress(component) - }, - onLongPress: () => { - void onEdtiorLongPress(component) - }, - }) - }) - if (options.length === 1) { - options.push({ - text: 'Unlock More Types', - key: 'get-editors', - iconDesc: { - type: SideMenuOptionIconDescriptionType.Icon, - name: ThemeService.nameForIcon(ICON_MEDICAL), - side: 'right', - size: 17, - }, - onSelect: () => { - application.deviceInterface?.openUrl('https://standardnotes.com/plans') - }, - }) - } - return options - }, [note, application, components, onEditorPress, onEdtiorLongPress]) - - useFocusEffect( - useCallback(() => { - let mounted = true - if (mounted) { - reloadTags() - } - - return () => { - mounted = false - } - }, [reloadTags]), - ) - - const leaveEditor = useCallback(() => { - props.drawerRef?.closeDrawer() - navigation.goBack() - }, [props.drawerRef, navigation]) - - const isEntitledToFiles = application.features.getFeatureStatus(FeatureIdentifier.Files) === FeatureStatus.Entitled - - const noteOptions = useMemo(() => { - if (!note) { - return - } - - const pinOption = note.pinned ? 'Unpin' : 'Pin' - const pinEvent = () => - changeNote((mutator) => { - mutator.pinned = !note.pinned - }, false) - - const archiveOption = note.archived ? 'Unarchive' : 'Archive' - const archiveEvent = () => { - if (note.locked) { - void application.alertService.alert( - `This note has editing disabled. If you'd like to ${archiveOption.toLowerCase()} it, enable editing on it, and try again.`, - ) - return - } - void changeNote((mutator) => { - mutator.archived = !note.archived - }, false) - leaveEditor() - } - - const lockOption = note.locked ? 'Enable editing' : 'Prevent editing' - const lockEvent = () => - changeNote((mutator) => { - mutator.locked = !note.locked - }, false) - - const protectOption = note.protected ? 'Remove password protection' : 'Password protect' - const protectEvent = async () => await protectOrUnprotectNote() - - const openSessionHistory = () => { - if (!editor?.isTemplateNote) { - props.drawerRef?.closeDrawer() - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - navigation.navigate('HistoryStack', { - screen: SCREEN_NOTE_HISTORY, - params: { noteUuid: note.uuid }, - }) - } - } - - const shareNote = () => { - if (note) { - void application.getAppState().performActionWithoutStateChangeImpact(() => { - void Share.share({ - title: note.title, - message: note.text, - }) - }) - } - } - - const rawOptions = [ - { text: pinOption, onSelect: pinEvent, icon: ICON_BOOKMARK }, - { text: archiveOption, onSelect: archiveEvent, icon: ICON_ARCHIVE }, - { text: lockOption, onSelect: lockEvent, icon: ICON_LOCK }, - { text: protectOption, onSelect: protectEvent, icon: ICON_FINGER_PRINT }, - { - text: 'History', - onSelect: openSessionHistory, - icon: ICON_HISTORY, - }, - { text: 'Share', onSelect: shareNote, icon: ICON_SHARE }, - ] - - if (!note.trashed) { - rawOptions.push({ - text: 'Move to Trash', - onSelect: async () => deleteNote(false), - icon: ICON_TRASH, - }) - } - - let options: SideMenuOption[] = rawOptions.map((rawOption) => ({ - text: rawOption.text, - key: rawOption.icon, - iconDesc: { - type: SideMenuOptionIconDescriptionType.Icon, - side: 'right' as const, - name: ThemeService.nameForIcon(rawOption.icon), - }, - onSelect: rawOption.onSelect, - })) - - if (note.trashed) { - options = options.concat([ - { - text: 'Restore', - key: 'restore-note', - onSelect: () => { - void changeNote((mutator) => { - mutator.trashed = false - }, false) - }, - }, - { - text: 'Delete permanently', - textClass: 'danger' as const, - key: 'delete-forever', - onSelect: async () => deleteNote(true), - }, - { - text: 'Empty Trash', - textClass: 'danger' as const, - key: 'empty trash', - onSelect: async () => { - const count = application.items.trashedItems.length - const confirmed = await application.alertService?.confirm( - `Are you sure you want to permanently delete ${count} notes?`, - 'Empty Trash', - 'Delete', - ButtonType.Danger, - ) - if (confirmed) { - await application.mutator.emptyTrash() - props.drawerRef?.closeDrawer() - if (!application.getAppState().isInTabletMode) { - navigation.popToTop() - } - void application.sync.sync() - } - }, - }, - ]) - } - - return options - }, [ - application, - changeNote, - deleteNote, - editor?.isTemplateNote, - leaveEditor, - navigation, - note, - props.drawerRef, - protectOrUnprotectNote, - ]) - - const onTagSelect = useCallback( - async (tag: SNTag | SmartView, addTagHierachy: boolean) => { - const isSelected = selectedTags.findIndex((selectedTag) => selectedTag.uuid === tag.uuid) > -1 - - if (note) { - if (isSelected) { - await application.mutator.changeItem(tag, (mutator) => { - mutator.removeItemAsRelationship(note) - }) - } else { - await application.items.addTagToNote(note, tag as SNTag, addTagHierachy) - } - } - reloadTags() - void application.sync.sync() - }, - [application, note, reloadTags, selectedTags], - ) - - if (!editor || !note) { - return null - } - - enum MenuSections { - FilesSection = 'files-section', - OptionsSection = 'options-section', - EditorsSection = 'editors-section', - ListedSection = 'listed-section', - TagsSection = 'tags-section', - } - - return ( - - ({ - key, - noteOptions, - editorComponents: editors, - onTagSelect, - selectedTags, - }))} - renderItem={({ item }) => { - const { OptionsSection, EditorsSection, ListedSection, TagsSection, FilesSection } = MenuSections - - if (item.key === FilesSection) { - let collapsedLabel = 'Tap to expand' - - if (isEntitledToFiles) { - collapsedLabel = `${attachedFilesLength ? `${attachedFilesLength}` : 'No'} attached file${ - attachedFilesLength === 1 ? '' : 's' - }` - } - return ( - - - - ) - } - if (item.key === OptionsSection) { - return - } - if (item.key === EditorsSection) { - return - } - if (item.key === ListedSection) { - return ( - - - - ) - } - if (item.key === TagsSection) { - return ( - - item.onTagSelect(tag, shouldAddTagHierarchy)} - selectedTags={item.selectedTags} - emptyPlaceholder={'Create a new tag using the tag button in the bottom right corner.'} - /> - - ) - } - return null - }} - /> - - navigation.navigate(SCREEN_INPUT_MODAL_TAG, { noteUuid: note.uuid })} - visible={true} - size={30} - iconTextComponent={} - /> - - ) -}) diff --git a/packages/mobile/src/Screens/SideMenu/SideMenuCell.styled.ts b/packages/mobile/src/Screens/SideMenu/SideMenuCell.styled.ts deleted file mode 100644 index d308d1936..000000000 --- a/packages/mobile/src/Screens/SideMenu/SideMenuCell.styled.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { Platform } from 'react-native' -import styled, { css } from 'styled-components/native' - -export const Touchable = styled.TouchableOpacity<{ isSubtext: boolean }>` - min-height: ${(props) => (props.isSubtext ? 52 : 42)}px; -` -export const CellContent = styled.View<{ - iconSide: 'right' | 'left' | null -}>` - flex: 1; - flex-direction: row; - align-items: center; - ${({ iconSide }) => - iconSide === 'right' && - css` - justify-content: space-between; - `} -` -const IconContainer = styled.View` - justify-content: center; -` -export const IconContainerLeft = styled(IconContainer)` - margin-right: 6px; -` -export const IconContainerRight = styled(IconContainer)` - justify-content: space-between; - margin-left: 6px; - margin-right: 4px; - height: 100%; -` -export const TextContainer = styled.View<{ - isSubtext: boolean - selected?: boolean -}>` - min-height: ${(props) => (props.isSubtext ? 38 : 24)}px; - margin-left: 6px; - flex-shrink: 1; - ${({ selected, theme }) => - selected && - css` - border-bottom-color: ${theme.stylekitInfoColor}; - border-bottom-width: 2px; - `} -` -const BaseText = styled.Text` - ${() => - Platform.OS === 'android' && - css` - font-family: 'Roboto'; - `} -` -export const Text = styled(BaseText)<{ textColor?: string }>` - color: ${({ theme, textColor }) => textColor ?? theme.stylekitContrastForegroundColor}; - font-weight: bold; - font-size: 15px; - padding-bottom: 0px; -` -export const SubTextContainer = styled.View`` -export const SubText = styled(BaseText)` - color: ${({ theme }) => theme.stylekitContrastForegroundColor}; - opacity: 0.75; - font-size: 12px; - margin-top: -5px; - margin-bottom: 3px; -` -export const IconGraphicContainer = styled.View` - margin-top: -3px; - width: 20px; - flex: 1; - justify-content: center; - align-items: center; -` -export const IconCircleContainer = styled(IconGraphicContainer)` - margin-top: -5px; -` -export const IconAscii = styled.Text` - font-size: 15px; - font-weight: bold; - color: ${({ theme }) => theme.stylekitNeutralColor}; - opacity: 0.6; - margin-top: -4px; -` -export const RegularText = styled.Text`` diff --git a/packages/mobile/src/Screens/SideMenu/SideMenuCell.tsx b/packages/mobile/src/Screens/SideMenu/SideMenuCell.tsx deleted file mode 100644 index d047fa0a9..000000000 --- a/packages/mobile/src/Screens/SideMenu/SideMenuCell.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { Circle } from '@Root/Components/Circle' -import React, { useContext } from 'react' -import Icon from 'react-native-vector-icons/Ionicons' -import { ThemeContext } from 'styled-components' -import { - CellContent, - IconAscii, - IconCircleContainer, - IconContainerLeft, - IconContainerRight, - IconGraphicContainer, - RegularText, - SubText, - SubTextContainer, - Text, - TextContainer, - Touchable, -} from './SideMenuCell.styled' -import { SideMenuOption, SideMenuOptionIconDescriptionType } from './SideMenuSection' - -const renderIcon = (desc: SideMenuOption['iconDesc'], color: string) => { - if (!desc) { - return null - } - - if (desc.type === SideMenuOptionIconDescriptionType.Icon && desc.name) { - return ( - - - - ) - } - if (desc.type === SideMenuOptionIconDescriptionType.Ascii) { - return {desc.value} - } - if (desc.type === SideMenuOptionIconDescriptionType.Circle) { - return ( - - - - ) - } - if (desc.type === SideMenuOptionIconDescriptionType.CustomComponent) { - return desc.value - } - return * -} - -export const SideMenuCell: React.FC = (props) => { - const theme = useContext(ThemeContext) - const colorForTextClass = (textClass: SideMenuOption['textClass']) => { - if (!textClass) { - return undefined - } - - return { - info: theme.stylekitInfoColor, - danger: theme.stylekitDangerColor, - warning: theme.stylekitWarningColor, - }[textClass] - } - - const hasIcon = props.iconDesc - const iconSide = hasIcon && props.iconDesc?.side ? props.iconDesc.side : hasIcon ? 'left' : null - return ( - - - {iconSide === 'left' && ( - {renderIcon(props.iconDesc, theme.stylekitInfoColor)} - )} - - - {props.subtext && ( - - {props.subtext} - - )} - {props.text} - - - {props.children} - - {iconSide === 'right' && ( - {renderIcon(props.iconDesc, theme.stylekitInfoColor)} - )} - - - ) -} diff --git a/packages/mobile/src/Screens/SideMenu/SideMenuHero.styled.ts b/packages/mobile/src/Screens/SideMenu/SideMenuHero.styled.ts deleted file mode 100644 index 1cd72e2d4..000000000 --- a/packages/mobile/src/Screens/SideMenu/SideMenuHero.styled.ts +++ /dev/null @@ -1,41 +0,0 @@ -import styled from 'styled-components/native' - -export const Cell = styled.View` - background-color: ${({ theme }) => theme.stylekitContrastBackgroundColor}; - border-bottom-color: ${({ theme }) => theme.stylekitContrastBorderColor}; - border-bottom-width: 1px; - padding: 15px; - padding-top: 10px; - padding-bottom: 12px; - padding-right: 25px; -` -export const Touchable = styled.TouchableOpacity`` -export const Title = styled.Text` - font-weight: bold; - font-size: 16px; - color: ${({ theme }) => theme.stylekitContrastForegroundColor}; - margin-bottom: 3px; -` -export const SubTitle = styled.Text` - font-size: 13px; - color: ${({ theme }) => theme.stylekitContrastForegroundColor}; - opacity: 0.6; -` -export const OutOfSyncContainer = styled.TouchableOpacity` - flex: 1; - margin-top: 5px; - margin-bottom: 5px; - flex-direction: row; - align-items: center; -` -export const IconCircle = styled.View` - margin-top: 10px; - width: 15px; -` -export const OutOfSyncLabel = styled.Text` - margin-top: 10px; - font-size: 13px; - height: 15px; - color: ${({ theme }) => theme.stylekitWarningColor}; - font-weight: bold; -` diff --git a/packages/mobile/src/Screens/SideMenu/SideMenuHero.tsx b/packages/mobile/src/Screens/SideMenu/SideMenuHero.tsx deleted file mode 100644 index dea801c00..000000000 --- a/packages/mobile/src/Screens/SideMenu/SideMenuHero.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { useIsLocked, useOutOfSync, useSignedIn } from '@Lib/SnjsHelperHooks' -import { ApplicationContext } from '@Root/ApplicationContext' -import { Circle } from '@Root/Components/Circle' -import { ContentType } from '@standardnotes/snjs' -import React, { useContext, useEffect, useMemo, useState } from 'react' -import { ViewProps } from 'react-native' -import { ThemeContext } from 'styled-components' -import { Cell, IconCircle, OutOfSyncContainer, OutOfSyncLabel, SubTitle, Title, Touchable } from './SideMenuHero.styled' - -type Props = { - onPress: () => void - onOutOfSyncPress: () => void - testID: ViewProps['testID'] -} - -export const SideMenuHero: React.FC = (props) => { - // Context - const application = useContext(ApplicationContext) - const theme = useContext(ThemeContext) - - // State - const [signedIn] = useSignedIn() - const [isLocked] = useIsLocked() - const [isOutOfSync] = useOutOfSync() - const [itemsCount, setItemsCount] = useState(0) - - useEffect(() => { - const observedContentTypes = [ContentType.Note, ContentType.Tag] - const removeStreamItems = application?.streamItems(observedContentTypes, (_items) => { - const notesAndTagsCount = application?.items.getItems(observedContentTypes).length ?? 0 - - if (notesAndTagsCount !== itemsCount) { - setItemsCount(notesAndTagsCount) - } - }) - - return removeStreamItems - }, [application, itemsCount]) - - const textData = useMemo(() => { - const hasEncryption = application?.isEncryptionAvailable() - if (!signedIn) { - return { - title: 'Data Not Backed Up', - text: hasEncryption - ? 'Sign in or register to enable sync to your other devices.' - : 'Sign in or register to add encryption and enable sync to your other devices.', - } - } else if (!isLocked) { - const user = application?.getUser() - const email = user?.email - const itemsStatus = itemsCount + '/' + itemsCount + ' notes and tags encrypted' - return { - title: email, - text: itemsStatus, - } - } else { - return { text: '', title: '' } - } - }, [application, signedIn, itemsCount, isLocked]) - - return ( - - - {textData.title} - - - {textData.text} - - {isOutOfSync && ( - - - - - Potentially Out of Sync - - )} - - ) -} diff --git a/packages/mobile/src/Screens/SideMenu/SideMenuSection.styled.ts b/packages/mobile/src/Screens/SideMenu/SideMenuSection.styled.ts deleted file mode 100644 index 92fd7c18d..000000000 --- a/packages/mobile/src/Screens/SideMenu/SideMenuSection.styled.ts +++ /dev/null @@ -1,19 +0,0 @@ -import styled from 'styled-components/native' - -export const Root = styled.View` - padding-bottom: 6px; -` -export const Header = styled.TouchableOpacity<{ collapsed: boolean }>` - height: ${(props) => (props.collapsed ? 50 : 22)}px; -` -export const Title = styled.Text` - color: ${({ theme }) => theme.stylekitInfoColor}; - font-size: 13px; - font-weight: 700; -` -export const CollapsedLabel = styled.Text` - font-size: 12px; - opacity: 0.7; - margin-top: 3px; - color: ${({ theme }) => theme.stylekitContrastForegroundColor}; -` diff --git a/packages/mobile/src/Screens/SideMenu/SideMenuSection.tsx b/packages/mobile/src/Screens/SideMenu/SideMenuSection.tsx deleted file mode 100644 index d849171b1..000000000 --- a/packages/mobile/src/Screens/SideMenu/SideMenuSection.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import React, { ReactElement, useMemo, useState } from 'react' -import { StyleProp, ViewStyle } from 'react-native' -import { SideMenuCell } from './SideMenuCell' -import { CollapsedLabel, Header, Root, Title } from './SideMenuSection.styled' - -export enum SideMenuOptionIconDescriptionType { - Icon = 'icon', - Ascii = 'ascii', - Circle = 'circle', - CustomComponent = 'custom-component', -} - -export type SideMenuOption = { - text: string - subtext?: string - textClass?: 'info' | 'danger' | 'warning' - key?: string - iconDesc?: { - type: SideMenuOptionIconDescriptionType - side?: 'left' | 'right' - name?: string - value?: string | ReactElement - backgroundColor?: string - borderColor?: string - size?: number - } - dimmed?: boolean - selected?: boolean - onSelect?: () => void | Promise - onLongPress?: () => void - style?: StyleProp - cellContentStyle?: StyleProp -} - -type Props = { - title: string - customCollapsedLabel?: string - collapsed?: boolean - options?: SideMenuOption[] -} - -export const SideMenuSection: React.FC = React.memo((props) => { - const [collapsed, setCollapsed] = useState(Boolean(props.collapsed)) - const options = useMemo(() => { - return props.options || [] - }, [props.options]) - const collapsedLabel = - props.customCollapsedLabel || - (options.length > 0 ? 'Tap to expand ' + options.length + ' options' : 'Tap to expand') - return ( - -
setCollapsed(!collapsed)}> - <> - {props.title} - {collapsed && {collapsedLabel}} - -
- - {!collapsed && ( - <> - {options.map((option) => { - return ( - - ) - })} - {props.children} - - )} -
- ) -}) diff --git a/packages/mobile/src/Screens/SideMenu/TagSelectionList.styled.ts b/packages/mobile/src/Screens/SideMenu/TagSelectionList.styled.ts deleted file mode 100644 index d424a04a8..000000000 --- a/packages/mobile/src/Screens/SideMenu/TagSelectionList.styled.ts +++ /dev/null @@ -1,8 +0,0 @@ -import styled from 'styled-components/native' - -export const EmptyPlaceholder = styled.Text` - color: ${({ theme }) => theme.stylekitForegroundColor}; - opacity: 0.6; - padding-right: 30px; - line-height: 18px; -` diff --git a/packages/mobile/src/Screens/SideMenu/TagSelectionList.tsx b/packages/mobile/src/Screens/SideMenu/TagSelectionList.tsx deleted file mode 100644 index 8624344c3..000000000 --- a/packages/mobile/src/Screens/SideMenu/TagSelectionList.tsx +++ /dev/null @@ -1,157 +0,0 @@ -import { useNavigation } from '@react-navigation/native' -import { AppStackNavigationProp } from '@Root/AppStack' -import { useSafeApplicationContext } from '@Root/Hooks/useSafeApplicationContext' -import { SCREEN_COMPOSE, SCREEN_INPUT_MODAL_TAG } from '@Root/Screens/screens' -import { SideMenuOptionIconDescriptionType } from '@Root/Screens/SideMenu/SideMenuSection' -import { ButtonType, ContentType, FindItem, SmartView, SNTag } from '@standardnotes/snjs' -import { useCustomActionSheet } from '@Style/CustomActionSheet' -import React, { useCallback, useEffect, useState } from 'react' -import { FlatList, ListRenderItem } from 'react-native' -import { SideMenuCell } from './SideMenuCell' -import { EmptyPlaceholder } from './TagSelectionList.styled' - -type Props = { - contentType: ContentType.Tag | ContentType.SmartView - onTagSelect: (tag: SNTag | SmartView) => void - selectedTags: SNTag[] | SmartView[] - emptyPlaceholder?: string - hasBottomPadding?: boolean -} - -export const TagSelectionList = React.memo( - ({ contentType, onTagSelect, selectedTags, emptyPlaceholder, hasBottomPadding }: Props) => { - // Context - const application = useSafeApplicationContext() - const navigation = useNavigation['navigation']>() - const { showActionSheet } = useCustomActionSheet() - - // State - const [tags, setTags] = useState(() => { - return contentType === ContentType.SmartView ? application.items.getSmartViews() : [] - }) - - const reloadTags = useCallback(() => { - if (contentType === ContentType.SmartView) { - setTags(application.items.getSmartViews()) - } else { - setTags(application.items.getDisplayableTags()) - } - }, [application, contentType]) - - const streamTags = useCallback( - () => - application.streamItems(contentType, ({ removed }) => { - reloadTags() - - if (application?.getAppState().selectedTag) { - if (FindItem(removed, application.getAppState().selectedTag.uuid)) { - application.getAppState().setSelectedTag(application.items.getSmartViews()[0], true) - } - } - }), - [application, contentType, reloadTags], - ) - - useEffect(() => { - const removeStreamTags = streamTags() - - return removeStreamTags - }, [application, contentType, streamTags]) - - const onTagLongPress = (tag: SNTag | SmartView) => { - showActionSheet({ - title: tag.title, - options: [ - { - text: 'Rename', - callback: () => - navigation.navigate(SCREEN_INPUT_MODAL_TAG, { - tagUuid: tag.uuid, - }), - }, - { - text: 'Delete', - destructive: true, - callback: async () => { - const confirmed = await application?.alertService.confirm( - 'Are you sure you want to delete this tag? Deleting a tag will not delete its notes.', - undefined, - 'Delete', - ButtonType.Danger, - ) - if (confirmed) { - await application.mutator.deleteItem(tag) - } - }, - }, - ], - }) - } - - const isRootTag = (tag: SNTag | SmartView): boolean => - tag instanceof SmartView || !application.items.getTagParent(tag) - - const showFolders = contentType === ContentType.Tag - const renderedTags = showFolders ? (tags as SNTag[]).filter(isRootTag) : tags - - const renderItem: ListRenderItem = ({ item }) => { - const title = item.title - - let children: SNTag[] = [] - - if (showFolders && item instanceof SNTag) { - const rawChildren = application.items.getTagChildren(item).map((tag) => tag.uuid) - children = (tags as SNTag[]).filter((tag: SNTag) => rawChildren.includes(tag.uuid)) - } - - const isSelected = selectedTags.some((selectedTag: SNTag | SmartView) => selectedTag.uuid === item.uuid) - - return ( - <> - onTagSelect(item)} - onLongPress={() => onTagLongPress(item)} - text={title} - iconDesc={{ - side: 'left', - type: SideMenuOptionIconDescriptionType.Ascii, - value: '#', - }} - key={item.uuid} - selected={isSelected} - /> - {children && ( - childTag.uuid} - renderItem={renderItem} - /> - )} - - ) - } - - return ( - <> - item.uuid} - renderItem={renderItem} - /> - {tags.length === 0 && {emptyPlaceholder}} - - ) - }, -) diff --git a/packages/mobile/src/Screens/UploadedFilesList/UploadedFileItem.styled.ts b/packages/mobile/src/Screens/UploadedFilesList/UploadedFileItem.styled.ts deleted file mode 100644 index c501a601f..000000000 --- a/packages/mobile/src/Screens/UploadedFilesList/UploadedFileItem.styled.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { SnIcon } from '@Root/Components/SnIcon' -import { Text } from '@Screens/SideMenu/SideMenuCell.styled' -import { hexToRGBA } from '@Style/Utils' -import { StyleSheet } from 'react-native' -import styled from 'styled-components/native' - -export const uploadedFileItemStyles = StyleSheet.create({ - lockIcon: { - marginLeft: 8, - }, -}) - -export const FileDataContainer = styled.View` - align-items: flex-start; - flex-direction: row; - padding-top: 12px; -` -export const FileIconContainer = styled.View` - margin-top: 2px; - margin-right: 16px; -` -export const FileDetailsWithExtraIconsContainer = styled.View` - flex-direction: row; - flex-shrink: 1; - flex-grow: 1; - align-items: center; - border-bottom-color: ${({ theme }) => hexToRGBA(theme.stylekitBorderColor, 0.75)}; - border-bottom-width: 1px; - padding-bottom: 12px; -` -export const LockIconStyled = styled(SnIcon)` - background-color: green; - display: none; -` -export const FileDetailsContainer = styled.View` - flex-shrink: 1; -` -export const FileName = styled(Text)` - font-weight: normal; - font-size: 16px; - margin-bottom: 4px; -` -export const FileDateAndSizeContainer = styled.View` - flex-direction: row; - align-items: center; -` -export const FileDateAndSize = styled.Text` - color: ${({ theme }) => { - return theme.stylekitForegroundColor - }}; - opacity: 0.5; - font-weight: normal; - font-size: 12px; -` diff --git a/packages/mobile/src/Screens/UploadedFilesList/UploadedFileItem.tsx b/packages/mobile/src/Screens/UploadedFilesList/UploadedFileItem.tsx deleted file mode 100644 index ef7c3489d..000000000 --- a/packages/mobile/src/Screens/UploadedFilesList/UploadedFileItem.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import { AppStackNavigationProp } from '@Root/AppStack' -import { SnIcon } from '@Root/Components/SnIcon' -import { useFiles } from '@Root/Hooks/useFiles' -import { useSafeApplicationContext } from '@Root/Hooks/useSafeApplicationContext' -import { SCREEN_COMPOSE } from '@Root/Screens/screens' -import { UploadedFileItemActionType } from '@Screens/UploadedFilesList/UploadedFileItemAction' -import { formatSizeToReadableString } from '@standardnotes/filepicker' -import { FileItem, SNNote } from '@standardnotes/snjs' -import React, { FC, useContext, useEffect, useState } from 'react' -import { TouchableOpacity, View } from 'react-native' -import { ThemeContext } from 'styled-components' -import { - FileDataContainer, - FileDateAndSize, - FileDateAndSizeContainer, - FileDetailsContainer, - FileDetailsWithExtraIconsContainer, - FileIconContainer, - FileName, - uploadedFileItemStyles, -} from './UploadedFileItem.styled' - -export type UploadedFileItemProps = { - file: FileItem - note: SNNote - isAttachedToNote: boolean -} - -export type TAppStackNavigationProp = AppStackNavigationProp['navigation'] - -export const UploadedFileItem: FC = ({ file, note }) => { - const application = useSafeApplicationContext() - const theme = useContext(ThemeContext) - - const { showActionsMenu, handleFileAction } = useFiles({ note }) - - const [fileName, setFileName] = useState(file.name) - - useEffect(() => { - setFileName(file.name) - }, [file.name]) - - const iconType = application.iconsController.getIconForFileType(file.mimeType) - - return ( - { - void handleFileAction({ - type: UploadedFileItemActionType.PreviewFile, - payload: file, - }) - }} - onLongPress={() => showActionsMenu(file)} - > - - - - - - - - {fileName} - - - {file.created_at.toLocaleString()} · {formatSizeToReadableString(file.decryptedSize)} - - {file.protected && ( - - )} - - - - - - - ) -} diff --git a/packages/mobile/src/Screens/UploadedFilesList/UploadedFileItemAction.ts b/packages/mobile/src/Screens/UploadedFilesList/UploadedFileItemAction.ts deleted file mode 100644 index e961472aa..000000000 --- a/packages/mobile/src/Screens/UploadedFilesList/UploadedFileItemAction.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { FileItem } from '@standardnotes/snjs' - -export enum UploadedFileItemActionType { - AttachFileToNote, - DetachFileToNote, - DeleteFile, - ShareFile, - DownloadFile, - RenameFile, - ToggleFileProtection, - PreviewFile, -} - -export type UploadedFileItemAction = { - type: UploadedFileItemActionType - payload: FileItem -} diff --git a/packages/mobile/src/Screens/UploadedFilesList/UploadedFilesList.styled.ts b/packages/mobile/src/Screens/UploadedFilesList/UploadedFilesList.styled.ts deleted file mode 100644 index b8259f75e..000000000 --- a/packages/mobile/src/Screens/UploadedFilesList/UploadedFilesList.styled.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { StyleSheet } from 'react-native' -import { useSafeAreaInsets } from 'react-native-safe-area-context' -import styled from 'styled-components/native' - -export const useUploadedFilesListStyles = () => { - const insets = useSafeAreaInsets() - - return StyleSheet.create({ - centeredView: { - justifyContent: 'flex-start', - alignItems: 'center', - flexShrink: 1, - flexGrow: 1, - paddingBottom: insets.bottom, - }, - header: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - marginBottom: 4, - }, - headerTabContainer: { - flexDirection: 'row', - }, - noAttachmentsIconContainer: { - alignItems: 'center', - marginTop: 24, - }, - noAttachmentsIcon: { - marginTop: 24, - marginBottom: 24, - }, - }) -} - -export const UploadFilesListContainer = styled.View` - margin-top: 12px; - padding-right: 16px; - padding-left: 16px; - width: 100%; - height: 100%; -` -export const HeaderTabItem = styled.View<{ - isActive: boolean - isLeftTab?: boolean -}>` - align-items: center; - padding: 8px; - flex-grow: 1; - background-color: ${({ theme, isActive }) => { - return isActive ? theme.stylekitInfoColor : theme.stylekitInfoContrastColor - }}; - border-width: 1px; - border-color: ${({ theme }) => theme.stylekitInfoColor}; - border-top-right-radius: ${({ isLeftTab }) => (isLeftTab ? 0 : '8px')}; - border-bottom-right-radius: ${({ isLeftTab }) => (isLeftTab ? 0 : '8px')}; - border-top-left-radius: ${({ isLeftTab }) => (isLeftTab ? '8px' : 0)}; - border-bottom-left-radius: ${({ isLeftTab }) => (isLeftTab ? '8px' : 0)}; - margin-left: ${({ isLeftTab }) => (isLeftTab ? 0 : '-1px')}; -` -export const TabText = styled.Text<{ isActive: boolean }>` - font-weight: bold; - color: ${({ isActive, theme }) => { - return isActive ? theme.stylekitInfoContrastColor : theme.stylekitInfoColor - }}; -` diff --git a/packages/mobile/src/Screens/UploadedFilesList/UploadedFilesList.tsx b/packages/mobile/src/Screens/UploadedFilesList/UploadedFilesList.tsx deleted file mode 100644 index 560938595..000000000 --- a/packages/mobile/src/Screens/UploadedFilesList/UploadedFilesList.tsx +++ /dev/null @@ -1,151 +0,0 @@ -import { useNavigation } from '@react-navigation/native' -import { SearchBar } from '@Root/Components/SearchBar' -import { SnIcon } from '@Root/Components/SnIcon' -import { useFiles } from '@Root/Hooks/useFiles' -import { ModalStackNavigationProp } from '@Root/ModalStack' -import { SCREEN_UPLOADED_FILES_LIST } from '@Root/Screens/screens' -import { UploadedFileItem } from '@Root/Screens/UploadedFilesList/UploadedFileItem' -import { - HeaderTabItem, - TabText, - UploadFilesListContainer, - useUploadedFilesListStyles, -} from '@Root/Screens/UploadedFilesList/UploadedFilesList.styled' -import { FileItem } from '@standardnotes/snjs' -import { ICON_ATTACH } from '@Style/Icons' -import { ThemeService } from '@Style/ThemeService' -import React, { FC, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react' -import { FlatList, ListRenderItem, Text, View } from 'react-native' -import FAB from 'react-native-fab' -import IosSearchBar from 'react-native-search-bar' -import AndroidSearchBar from 'react-native-search-box' -import Icon from 'react-native-vector-icons/Ionicons' -import { ThemeContext } from 'styled-components' - -export enum Tabs { - AttachedFiles, - AllFiles, -} - -type Props = ModalStackNavigationProp - -export const UploadedFilesList: FC = (props) => { - const { AttachedFiles, AllFiles } = Tabs - const { note } = props.route.params - - const theme = useContext(ThemeContext) - - const styles = useUploadedFilesListStyles() - const navigation = useNavigation() - - const [currentTab, setCurrentTab] = useState(AllFiles) - const [searchString, setSearchString] = useState('') - const [filesListScrolled, setFilesListScrolled] = useState(false) - - const iosSearchBarInputRef = useRef(null) - const androidSearchBarInputRef = useRef(null) - const filesListRef = useRef(null) - - const { attachedFiles, allFiles, handlePressAttachFile } = useFiles({ - note, - }) - - const filesList = currentTab === Tabs.AttachedFiles ? attachedFiles : allFiles - - const filteredList = useMemo(() => { - return searchString - ? filesList.filter((file) => file.name.toLowerCase().includes(searchString.toLowerCase())) - : filesList - }, [filesList, searchString]) - - useEffect(() => { - let screenTitle = 'Files' - if (searchString) { - const filesCount = filteredList.length - screenTitle = `${filesCount} search result${filesCount !== 1 ? 's' : ''}` - } - navigation.setOptions({ - title: screenTitle, - }) - }, [filteredList.length, navigation, searchString]) - - const scrollListToTop = useCallback(() => { - if (filesListScrolled && filteredList.length > 0) { - filesListRef.current?.scrollToIndex({ animated: false, index: 0 }) - setFilesListScrolled(false) - } - }, [filesListScrolled, filteredList.length]) - - const handleFilter = useCallback( - (textToSearch: string) => { - setSearchString(textToSearch) - scrollListToTop() - }, - [scrollListToTop], - ) - - const { centeredView, header, headerTabContainer, noAttachmentsIcon, noAttachmentsIconContainer } = styles - - const onScroll = () => { - if (filesListScrolled) { - return - } - setFilesListScrolled(true) - } - - const renderItem: ListRenderItem = ({ item }) => { - return - } - - return ( - - - - - setCurrentTab(AttachedFiles)} - > - Attached - - setCurrentTab(AllFiles)}> - All files - - - - - handleFilter('')} - iosSearchBarInputRef={iosSearchBarInputRef} - androidSearchBarInputRef={androidSearchBarInputRef} - /> - - - {filteredList.length > 0 ? ( - item.uuid} - onScroll={onScroll} - /> - ) : ( - - - {searchString ? 'No files found' : 'No files attached to this note'} - - )} - handlePressAttachFile(currentTab)} - visible={true} - size={30} - iconTextComponent={} - /> - - - ) -} diff --git a/packages/mobile/src/Screens/ViewProtectedNote/ViewProtectedNote.styled.ts b/packages/mobile/src/Screens/ViewProtectedNote/ViewProtectedNote.styled.ts deleted file mode 100644 index d1fb49950..000000000 --- a/packages/mobile/src/Screens/ViewProtectedNote/ViewProtectedNote.styled.ts +++ /dev/null @@ -1,23 +0,0 @@ -import styled from 'styled-components/native' - -export const Container = styled.View` - flex: 1; - background-color: ${({ theme }) => theme.stylekitBackgroundColor}; - display: flex; - justify-content: center; - padding: 20px; -` - -export const Title = styled.Text` - font-size: 20px; - font-weight: bold; - text-align: center; - color: ${({ theme }) => theme.stylekitForegroundColor}; -` - -export const Text = styled.Text` - margin: 8px 0 24px; - font-size: 14px; - text-align: center; - color: ${({ theme }) => theme.stylekitParagraphTextColor}; -` diff --git a/packages/mobile/src/Screens/ViewProtectedNote/ViewProtectedNote.tsx b/packages/mobile/src/Screens/ViewProtectedNote/ViewProtectedNote.tsx deleted file mode 100644 index 7c96acb3d..000000000 --- a/packages/mobile/src/Screens/ViewProtectedNote/ViewProtectedNote.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { useFocusEffect } from '@react-navigation/native' -import { ApplicationContext } from '@Root/ApplicationContext' -import { AppStackNavigationProp } from '@Root/AppStack' -import { Button } from '@Root/Components/Button' -import { SCREEN_SETTINGS, SCREEN_VIEW_PROTECTED_NOTE } from '@Root/Screens/screens' -import React, { useCallback, useContext } from 'react' -import { Container, Text, Title } from './ViewProtectedNote.styled' - -type Props = AppStackNavigationProp - -export const ViewProtectedNote = ({ - route: { - params: { onPressView }, - }, - navigation, -}: Props) => { - const application = useContext(ApplicationContext) - - const onPressGoToSettings = () => { - navigation.navigate(SCREEN_SETTINGS) - } - - const checkProtectionSources = useCallback(() => { - const hasProtectionSources = application?.hasProtectionSources() - if (hasProtectionSources) { - onPressView() - } - }, [application, onPressView]) - - useFocusEffect(checkProtectionSources) - - return ( - - This note is protected - Add a passcode or biometrics lock, or create an account, to require authentication to view this note. -