diff options
author | Ajay Ramachandran <[email protected]> | 2021-01-17 14:46:56 -0500 |
---|---|---|
committer | Ajay Ramachandran <[email protected]> | 2021-01-17 14:46:56 -0500 |
commit | b66ea934f9b1dfc963f8f2db0d2be081c2a9f2ad (patch) | |
tree | 9ea1216f3f78a6a69c742da5c91d6557217bfc0e | |
parent | bbda730f78241cc905587bbf6137c8736593a43d (diff) | |
parent | d2f377c8d745c5c8f4e2ede2ea7b930cb4d1c670 (diff) | |
download | SponsorBlock-b66ea934f9b1dfc963f8f2db0d2be081c2a9f2ad.tar.gz SponsorBlock-b66ea934f9b1dfc963f8f2db0d2be081c2a9f2ad.zip |
Merge branch 'master' of https://github.com/ajayyy/SponsorBlock into fosefx-eslint-ci
56 files changed, 2566 insertions, 1347 deletions
diff --git a/.eslintrc.js b/.eslintrc.js index 3ea331c5..64b64a12 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -20,10 +20,8 @@ module.exports = { plugins: ["react", "@typescript-eslint"], rules: { // TODO: Remove warn rules when not needed anymore - "@typescript-eslint/no-this-alias": "warn", "no-self-assign": "off", "@typescript-eslint/no-empty-interface": "off", - "@typescript-eslint/ban-types": "warn", }, settings: { react: { diff --git a/manifest/manifest.json b/manifest/manifest.json index 32aefd3b..c25f2275 100644 --- a/manifest/manifest.json +++ b/manifest/manifest.json @@ -1,7 +1,7 @@ { "name": "__MSG_fullName__", "short_name": "SponsorBlock", - "version": "2.0.10.1", + "version": "2.0.11.2", "default_locale": "en", "description": "__MSG_Description__", "content_scripts": [{ @@ -46,7 +46,6 @@ ], "permissions": [ "storage", - "notifications", "https://sponsor.ajay.app/*" ], "optional_permissions": [ diff --git a/package-lock.json b/package-lock.json index 16885c02..961ca2ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -318,9 +318,9 @@ } }, "@babel/polyfill": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.10.4.tgz", - "integrity": "sha512-8BYcnVqQ5kMD2HXoHInBH7H1b/uP3KdnwCYXOqFnXqguOyuu443WXusbIUbWEfY3Z0Txk0M1uG/8YuAMhNl6zg==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.12.1.tgz", + "integrity": "sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g==", "dev": true, "requires": { "core-js": "^2.6.5", @@ -328,9 +328,9 @@ } }, "@babel/runtime": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz", - "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==", + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz", + "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==", "dev": true, "requires": { "regenerator-runtime": "^0.13.4" @@ -419,6 +419,53 @@ } } }, + "@devicefarmer/adbkit": { + "version": "2.11.3", + "resolved": "https://registry.npmjs.org/@devicefarmer/adbkit/-/adbkit-2.11.3.tgz", + "integrity": "sha512-rsgWREAvSRQjdP9/3GoAV6Tq+o97haywgbTfCgt5yUqiDpaaq3hlH9FTo9XsdG8x+Jd0VQ9nTC2IXsDu8JGRSA==", + "dev": true, + "requires": { + "@devicefarmer/adbkit-logcat": "^1.1.0", + "@devicefarmer/adbkit-monkey": "~1.0.1", + "bluebird": "~2.9.24", + "commander": "^2.3.0", + "debug": "~2.6.3", + "node-forge": "^0.10.0", + "split": "~0.3.3" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "@devicefarmer/adbkit-logcat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@devicefarmer/adbkit-logcat/-/adbkit-logcat-1.1.0.tgz", + "integrity": "sha512-K90P5gUXM/w+yzLvJIRQ+tJooNU6ipUPPQkljtPJ0laR66TGtpt4Gqsjm0n9dPHK1W5KGgU1R5wnCd6RTSlPNA==", + "dev": true + }, + "@devicefarmer/adbkit-monkey": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@devicefarmer/adbkit-monkey/-/adbkit-monkey-1.0.1.tgz", + "integrity": "sha512-HilPrVrCosYWqSyjfpDtaaN1kJwdlBpS+IAflP3z+e7nsEgk3JGJf1Vg0NgHJooTf5HDfXSyZqMVg+5jvXCK0g==", + "dev": true, + "requires": { + "async": "~0.2.9" + } + }, "@eslint/eslintrc": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.2.tgz", @@ -1551,6 +1598,15 @@ "@types/yargs": "^13.0.0" } }, + "@mdn/browser-compat-data": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-2.0.7.tgz", + "integrity": "sha512-GeeM827DlzFFidn1eKkMBiqXFD2oLsnZbaiGhByPl0vcapsRzUL+t9hDoov1swc9rB2jw64R+ihtzC8qOE9wXw==", + "dev": true, + "requires": { + "extend": "3.0.2" + } + }, "@nodelib/fs.scandir": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", @@ -1835,6 +1891,15 @@ "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==", "dev": true }, + "@types/yauzl": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz", + "integrity": "sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@typescript-eslint/eslint-plugin": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.9.1.tgz", @@ -2224,9 +2289,9 @@ } }, "acorn-jsx": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz", - "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", "dev": true }, "acorn-walk": { @@ -2235,100 +2300,51 @@ "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", "dev": true }, - "adbkit": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/adbkit/-/adbkit-2.11.1.tgz", - "integrity": "sha512-hDTiRg9NX3HQt7WoDAPCplUpvzr4ZzQa2lq7BdTTJ/iOZ6O7YNAs6UYD8sFAiBEcYHDRIyq3cm9sZP6uZnhvXw==", - "dev": true, - "requires": { - "adbkit-logcat": "^1.1.0", - "adbkit-monkey": "~1.0.1", - "bluebird": "~2.9.24", - "commander": "^2.3.0", - "debug": "~2.6.3", - "node-forge": "^0.7.1", - "split": "~0.3.3" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "adbkit-logcat": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/adbkit-logcat/-/adbkit-logcat-1.1.0.tgz", - "integrity": "sha1-Adf5sM75CTowvLOwB+//MBUIli8=", - "dev": true - }, - "adbkit-monkey": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/adbkit-monkey/-/adbkit-monkey-1.0.1.tgz", - "integrity": "sha1-8pG+cBou/FZ6Y/x6pq/N7TFDC+E=", - "dev": true, - "requires": { - "async": "~0.2.9" - } - }, "addons-linter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/addons-linter/-/addons-linter-2.1.0.tgz", - "integrity": "sha512-ISCPobK6VdQ+5btMf1abkuD/9V+6RjnpJAVmEzjxDitk7HY03mLXVhA8SoD0XgngrI6cFlM2/i4OxfY4dHokpw==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/addons-linter/-/addons-linter-2.13.1.tgz", + "integrity": "sha512-OWMuABpZRNeru38oOjn7QYOF0JOXJQXG9c3r4ILTRwTBeSu3LtfgCh9/7zLVgTYPbTs7Qy6h23u4Sel65uSnUQ==", "dev": true, "requires": { - "@babel/runtime": "7.10.5", - "ajv": "6.12.3", + "@babel/runtime": "7.12.5", + "@mdn/browser-compat-data": "2.0.7", + "addons-scanner-utils": "4.0.0", + "ajv": "6.12.6", "ajv-merge-patch": "4.1.0", "chalk": "4.1.0", "cheerio": "1.0.0-rc.3", "columnify": "1.5.4", "common-tags": "1.8.0", "deepmerge": "4.2.2", - "dispensary": "0.52.0", - "es6-promisify": "6.1.1", - "eslint": "7.5.0", - "eslint-plugin-no-unsanitized": "3.1.2", - "eslint-visitor-keys": "1.3.0", - "espree": "7.2.0", + "dispensary": "0.59.0", + "eslint": "7.14.0", + "eslint-plugin-no-unsanitized": "3.1.4", + "eslint-visitor-keys": "2.0.0", + "espree": "7.3.0", "esprima": "4.0.1", - "first-chunk-stream": "4.0.0", "fluent-syntax": "0.13.0", - "fsevents": "2.1.3", + "fsevents": "2.2.1", "glob": "7.1.6", "is-mergeable-object": "1.1.1", "jed": "1.1.1", - "mdn-browser-compat-data": "1.0.31", "os-locale": "5.0.0", - "pino": "6.4.0", - "postcss": "7.0.32", + "pino": "6.7.0", + "postcss": "8.1.10", "probe-image-size": "5.0.0", "relaxed-json": "1.0.3", "semver": "7.3.2", "source-map-support": "0.5.19", - "strip-bom-stream": "4.0.0", "tosource": "1.0.0", - "upath": "1.2.0", - "whatwg-url": "8.1.0", - "yargs": "15.4.1", + "upath": "2.0.1", + "whatwg-url": "8.4.0", + "yargs": "16.1.1", "yauzl": "2.10.0" }, "dependencies": { "ajv": { - "version": "6.12.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", - "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -2338,12 +2354,11 @@ } }, "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -2357,6 +2372,17 @@ "supports-color": "^7.1.0" } }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2384,22 +2410,23 @@ } }, "eslint": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.5.0.tgz", - "integrity": "sha512-vlUP10xse9sWt9SGRtcr1LAC67BENcQMFeV+w5EvLEoFe3xJ8cF1Skd0msziRx/VMC+72B4DxreCE+OR12OA6Q==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.14.0.tgz", + "integrity": "sha512-5YubdnPXrlrYAFCKybPuHIAH++PINe1pmKNc5wQRB9HSbqIK1ywAnntE3Wwua4giKu0bjligf1gLF6qxMGOYRA==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", + "@eslint/eslintrc": "^0.2.1", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.0.1", "doctrine": "^3.0.0", "enquirer": "^2.3.5", - "eslint-scope": "^5.1.0", + "eslint-scope": "^5.1.1", "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^1.3.0", - "espree": "^7.2.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.0", "esquery": "^1.2.0", "esutils": "^2.0.2", "file-entry-cache": "^5.0.1", @@ -2437,6 +2464,12 @@ "estraverse": "^4.1.1" } }, + "eslint-visitor-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", + "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", + "dev": true + }, "esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", @@ -2486,6 +2519,13 @@ "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", "dev": true }, + "fsevents": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.2.1.tgz", + "integrity": "sha512-bTLYHSeC0UH/EFXS9KqWnXuOl/wHK5Z/d+ghd5AsFMYN7wIGkUCOJyzy88+wJKkZPGON8u4Z9f6U4FdgURE9qA==", + "dev": true, + "optional": true + }, "globals": { "version": "12.4.0", "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", @@ -2593,9 +2633,9 @@ } }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -2610,6 +2650,23 @@ "prelude-ls": "^1.2.1" } }, + "upath": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz", + "integrity": "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==", + "dev": true + }, + "whatwg-url": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.4.0.tgz", + "integrity": "sha512-vwTUFf6V4zhcPkWp/4CQPr1TW9Ml6SF4lVyaIMBdJw5i6qUUJ1QWM4Z6YYVkfka0OUIzVo/0aNtGVGk256IKWw==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^2.0.2", + "webidl-conversions": "^6.1.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -2618,6 +2675,66 @@ "requires": { "isexe": "^2.0.0" } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", + "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==", + "dev": true + }, + "yargs": { + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.1.1.tgz", + "integrity": "sha512-hAD1RcFP/wfgfxgMVswPE+z3tlPFtxG8/yWUrG2i17sTWGCGqWnxKcLTF4cUKDUK8fzokwsmO9H0TDkRbMHy8w==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true + } + } + }, + "addons-scanner-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/addons-scanner-utils/-/addons-scanner-utils-4.0.0.tgz", + "integrity": "sha512-+BfePzqoo/7Nhum9LONGsga2xhNJYb+6k6j819pzcd2tqaaqDUJu+3lz4CQQYFcD8QoolB3ksfZcCPymleFq0A==", + "dev": true, + "requires": { + "@types/yauzl": "2.9.1", + "common-tags": "1.8.0", + "first-chunk-stream": "3.0.0", + "strip-bom-stream": "4.0.0", + "upath": "2.0.1", + "yauzl": "2.10.0" + }, + "dependencies": { + "upath": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz", + "integrity": "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==", + "dev": true } } }, @@ -2765,76 +2882,52 @@ "dev": true }, "archiver": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", - "integrity": "sha1-/2YrSnggFJSj7lRNOjP+dJZQnrw=", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.0.2.tgz", + "integrity": "sha512-Tq3yV/T4wxBsD2Wign8W9VQKhaUxzzRmjEiSoOK0SLqPgDP/N1TKdYyBeIEu56T4I9iO4fKTTR0mN9NWkBA0sg==", "dev": true, "requires": { - "archiver-utils": "^1.3.0", - "async": "^2.0.0", + "archiver-utils": "^2.1.0", + "async": "^3.2.0", "buffer-crc32": "^0.2.1", - "glob": "^7.0.0", - "lodash": "^4.8.0", - "readable-stream": "^2.0.0", - "tar-stream": "^1.5.0", - "zip-stream": "^1.2.0" + "readable-stream": "^3.6.0", + "readdir-glob": "^1.0.0", + "tar-stream": "^2.1.4", + "zip-stream": "^4.0.0" }, "dependencies": { "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==", "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } } } }, "archiver-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz", - "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", "dev": true, "requires": { - "glob": "^7.0.0", - "graceful-fs": "^4.1.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", "lazystream": "^1.0.0", - "lodash": "^4.8.0", - "normalize-path": "^2.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", "readable-stream": "^2.0.0" }, "dependencies": { + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -4129,55 +4222,14 @@ } }, "bl": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", - "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.3.tgz", + "integrity": "sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg==", "dev": true, "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - } + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" } }, "bluebird": { @@ -4215,12 +4267,11 @@ }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -4256,9 +4307,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -4415,31 +4466,15 @@ } }, "buffer": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", - "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "dev": true, "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, - "buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "dev": true, - "requires": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } - }, - "buffer-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", - "dev": true - }, "buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", @@ -4452,12 +4487,6 @@ "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=", "dev": true }, - "buffer-fill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", - "dev": true - }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -4819,9 +4848,9 @@ "dev": true }, "cli-boxes": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz", - "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", "dev": true }, "cliui": { @@ -4896,6 +4925,12 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, + "colorette": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", + "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==", + "dev": true + }, "colors": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz", @@ -4962,46 +4997,22 @@ "dev": true }, "compress-commons": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", - "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.0.2.tgz", + "integrity": "sha512-qhd32a9xgzmpfoga1VQEiLEwdKZ6Plnpx5UCgIsf89FSolyJ7WnifY4Gtjgv5WR6hWAyRaHxC5MiEhU/38U70A==", "dev": true, "requires": { - "buffer-crc32": "^0.2.1", - "crc32-stream": "^2.0.0", - "normalize-path": "^2.0.0", - "readable-stream": "^2.0.0" + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.1", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" }, "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } } } }, @@ -5505,55 +5516,24 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, - "crc": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", - "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "crc-32": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz", + "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==", "dev": true, "requires": { - "buffer": "^5.1.0" + "exit-on-epipe": "~1.0.1", + "printj": "~1.1.0" } }, "crc32-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", - "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.1.tgz", + "integrity": "sha512-FN5V+weeO/8JaXsamelVYO1PHyeCsuL3HcG4cqsj0ceARcocxalaShCsohZMSAF+db7UYFwBy1rARK/0oFItUw==", "dev": true, "requires": { - "crc": "^3.4.4", - "readable-stream": "^2.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" } }, "create-ecdh": { @@ -5784,9 +5764,9 @@ "dev": true }, "deepcopy": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/deepcopy/-/deepcopy-2.0.0.tgz", - "integrity": "sha512-d5ZK7pJw7F3k6M5vqDjGiiUS9xliIyWkdzBjnPhnSeRGjkYOGZMCFkdKVwV/WiHOe0NwzB8q+iDo7afvSf0arA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/deepcopy/-/deepcopy-2.1.0.tgz", + "integrity": "sha512-8cZeTb1ZKC3bdSCP6XOM1IsTczIO73fdqtwa2B0N15eAz7gmyhQo+mc5gnFuulsgN3vIQYmTgbmQVKalH1dKvQ==", "dev": true, "requires": { "type-detect": "^4.0.8" @@ -5926,25 +5906,107 @@ } }, "dispensary": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/dispensary/-/dispensary-0.52.0.tgz", - "integrity": "sha512-A13TTo/2yaK/Z3So4OdzodBTbyTMpqVOH15cbmUuKvl+T1cOLn0VGQjibrG9cELa9mkLfhjFodqYQWkOGkG9Ig==", + "version": "0.59.0", + "resolved": "https://registry.npmjs.org/dispensary/-/dispensary-0.59.0.tgz", + "integrity": "sha512-JSnh4AhtYgwoyUHtunZbAhklkD9IeNacK1IDlrAJSZjzBMGFoTp9+Nggg+ITJ+F1geXc04DZ55ixnjFr5Ozknw==", "dev": true, "requires": { "async": "~3.2.0", "natural-compare-lite": "~1.4.0", - "pino": "~6.4.0", + "pino": "~6.7.0", "request": "~2.88.0", "sha.js": "~2.4.4", "source-map-support": "~0.5.4", - "yargs": "~15.4.0" + "yargs": "~16.1.0" }, "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, "async": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==", "dev": true + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", + "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==", + "dev": true + }, + "yargs": { + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.1.1.tgz", + "integrity": "sha512-hAD1RcFP/wfgfxgMVswPE+z3tlPFtxG8/yWUrG2i17sTWGCGqWnxKcLTF4cUKDUK8fzokwsmO9H0TDkRbMHy8w==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true } } }, @@ -6016,9 +6078,9 @@ } }, "dot-prop": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz", - "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", "dev": true, "requires": { "is-obj": "^2.0.0" @@ -6240,6 +6302,12 @@ "integrity": "sha512-HBL8I3mIki5C1Cc9QjKUenHtnG0A5/xA8Q/AllRcfiwl2CZFXGK7ddBiCoRwAix4i2KxcQfjtIVcrVbB3vbmwg==", "dev": true }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, "escape-goat": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", @@ -6547,9 +6615,9 @@ } }, "eslint-plugin-no-unsanitized": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-3.1.2.tgz", - "integrity": "sha512-KPShfliA3Uy9qqwQx35P1fwIOeJjZkb0FbMMUFztRYRposzaynsM8JCEb952fqkidROl1kpqY80uSvn+TcWkQQ==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-3.1.4.tgz", + "integrity": "sha512-WF1+eZo2Sh+bQNjZuVNwT0dA61zuJORsLh+1Sww7+O6GOPw+WPWIIRfTWNqrmaXaDMhM4SXAqYPcNlhRMiH13g==", "dev": true }, "eslint-plugin-react": { @@ -6618,12 +6686,12 @@ "dev": true }, "espree": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.2.0.tgz", - "integrity": "sha512-H+cQ3+3JYRMEIOl87e7QdHX70ocly5iW4+dttuR8iYSPr/hXKFb+7dBsZ7+u1adC4VrnPlTkv0+OwuPnDop19g==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz", + "integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==", "dev": true, "requires": { - "acorn": "^7.3.1", + "acorn": "^7.4.0", "acorn-jsx": "^5.2.0", "eslint-visitor-keys": "^1.3.0" } @@ -6720,6 +6788,12 @@ "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", "dev": true }, + "exit-on-epipe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", + "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==", + "dev": true + }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -7067,9 +7141,9 @@ "dev": true }, "fast-redact": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-2.0.0.tgz", - "integrity": "sha512-zxpkULI9W9MNTK2sJ3BpPQrTEXFNESd2X6O1tXMFpK/XM0G5c5Rll2EVYZH2TqI3xRGK/VaJ+eEOt7pnENJpeA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.0.0.tgz", + "integrity": "sha512-a/S/Hp6aoIjx7EmugtzLqXmcNsyFszqbt6qQ99BdG61QjBZF6shNis0BYR6TsZOQ1twYc0FN2Xdhwwbv6+KD0w==", "dev": true }, "fast-safe-stringify": { @@ -7181,13 +7255,13 @@ } }, "firefox-profile": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/firefox-profile/-/firefox-profile-2.0.0.tgz", - "integrity": "sha512-BPfcUISOV6+UwF6uqo5QS8iuFL6XZvHCm+1iuynIJ7fe1zea69Is77/n/098fp0a9sZ94lvT8rpYB15S/riSaA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/firefox-profile/-/firefox-profile-4.0.0.tgz", + "integrity": "sha512-Vw31AsjfLDbcApMDwwnhZcz3tWjV6lxB9BNf84FaV44rZXtU87cVbFMBzPEtrJdUDbwPYiuYzprp6yksYGwjSw==", "dev": true, "requires": { "adm-zip": "~0.4.x", - "archiver": "~2.1.0", + "archiver": "~5.0.2", "async": "~2.5.0", "fs-extra": "~4.0.2", "ini": "~1.3.3", @@ -7228,9 +7302,9 @@ } }, "first-chunk-stream": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-4.0.0.tgz", - "integrity": "sha512-8TOz/mJp7+zc2HN63vnJHotwceq4gQI1+/gdJVnJcG4dEB96oUxw7wV9We4QKjSFWUc/V0ADDfaGba5cDoG6EA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-3.0.0.tgz", + "integrity": "sha512-LNRvR4hr/S8cXXkIY5pTgVP7L3tq6LlYWcg9nWBuW7o1NMxKZo6oOVa/6GIekMGI0Iw7uC+HWimMe9u/VAeKqw==", "dev": true }, "flat-cache": { @@ -7407,13 +7481,21 @@ }, "dependencies": { "jsonfile": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz", - "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, "requires": { "graceful-fs": "^4.1.6", - "universalify": "^1.0.0" + "universalify": "^2.0.0" + }, + "dependencies": { + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } } }, "universalify": { @@ -7619,12 +7701,20 @@ } }, "global-dirs": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz", - "integrity": "sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz", + "integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==", "dev": true, "requires": { - "ini": "^1.3.5" + "ini": "1.3.7" + }, + "dependencies": { + "ini": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", + "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", + "dev": true + } } }, "global-modules": { @@ -8116,10 +8206,13 @@ } }, "is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", - "dev": true + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", + "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", + "dev": true, + "requires": { + "call-bind": "^1.0.0" + } }, "is-arrayish": { "version": "0.2.1", @@ -8278,9 +8371,9 @@ "dev": true }, "is-npm": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", - "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", "dev": true }, "is-number": { @@ -11595,6 +11688,24 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==" }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", + "dev": true + }, + "lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=", + "dev": true + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", + "dev": true + }, "lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -11649,6 +11760,12 @@ "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", "dev": true }, + "lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=", + "dev": true + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -11750,15 +11867,6 @@ "safe-buffer": "^5.1.2" } }, - "mdn-browser-compat-data": { - "version": "1.0.31", - "resolved": "https://registry.npmjs.org/mdn-browser-compat-data/-/mdn-browser-compat-data-1.0.31.tgz", - "integrity": "sha512-GVQQYWgoH3jbBaIy8M4hrg34qaNpPedtZvwAjUmkpHq4FXKKCea8Ji5rlS32YJSU9dt7TPvuWWX7Cce5mZyFPA==", - "dev": true, - "requires": { - "extend": "3.0.2" - } - }, "mem": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/mem/-/mem-5.1.1.tgz", @@ -12017,9 +12125,9 @@ } }, "moment": { - "version": "2.27.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz", - "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==", + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", "dev": true, "optional": true }, @@ -12123,6 +12231,12 @@ "dev": true, "optional": true }, + "nanoid": { + "version": "3.1.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", + "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "dev": true + }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -12180,9 +12294,9 @@ "dev": true }, "node-forge": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.6.tgz", - "integrity": "sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", "dev": true }, "node-int64": { @@ -12284,6 +12398,7 @@ "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-7.0.2.tgz", "integrity": "sha512-ux+n4hPVETuTL8+daJXTOC6uKLgMsl1RYfFv7DKRzyvzBapqco0rZZ9g72ZN8VS6V+gvNYHYa/ofcCY8fkJWsA==", "dev": true, + "optional": true, "requires": { "growly": "^1.3.0", "is-wsl": "^2.2.0", @@ -12297,13 +12412,15 @@ "version": "7.3.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "dev": true + "dev": true, + "optional": true }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "optional": true, "requires": { "isexe": "^2.0.0" } @@ -12416,13 +12533,13 @@ "dev": true }, "object-is": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz", - "integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.4.tgz", + "integrity": "sha512-1ZvAZ4wlF7IyPVOcE1Omikt7UpaFlOQq0HlSti+ZvDH3UiD2brwGMwDbyV43jao2bKJ+4+WdPJHSd7kgzKYVqg==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" } }, "object-keys": { @@ -12636,9 +12753,9 @@ } }, "open": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-7.1.0.tgz", - "integrity": "sha512-lLPI5KgOwEYCDKXf4np7y1PBEkj7HYIyP2DY8mVDRnx0VIIu6bNrRB0R66TuO7Mack6EnTNLm4uvcl1UoklTpA==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/open/-/open-7.3.0.tgz", + "integrity": "sha512-mgLwQIx2F/ye9SmbrUkurZCnkoXyXyu9EbHtJZrICjVAJfyMArdHp3KkixGdZx1ZHFPNIwl0DDM1dFFqXbTLZw==", "dev": true, "requires": { "is-docker": "^2.0.0", @@ -12693,9 +12810,9 @@ } }, "execa": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.3.tgz", - "integrity": "sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", "dev": true, "requires": { "cross-spawn": "^7.0.0", @@ -13024,23 +13141,23 @@ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" }, "pino": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-6.4.0.tgz", - "integrity": "sha512-TRDp5fJKRBtVlxd4CTox3rJL+TzwQztB/VNmT5n87zFgKVU7ztnmZkcX1zypPP+3ZZcveOTYKJy74UXdVBaXFQ==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-6.7.0.tgz", + "integrity": "sha512-vPXJ4P9rWCwzlTJt+f0Ni4THc3DWyt8iDDCO4edQ8narTu6hnpzdXu8FqeSJCGndl1W6lfbYQUQihUO54y66Lw==", "dev": true, "requires": { - "fast-redact": "^2.0.0", + "fast-redact": "^3.0.0", "fast-safe-stringify": "^2.0.7", "flatstr": "^1.0.12", "pino-std-serializers": "^2.4.2", "quick-format-unescaped": "^4.0.1", - "sonic-boom": "^1.0.0" + "sonic-boom": "^1.0.2" } }, "pino-std-serializers": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-2.4.2.tgz", - "integrity": "sha512-WaL504dO8eGs+vrK+j4BuQQq6GLKeCCcHaMB2ItygzVURcL1CycwNEUHTD/lHFHs/NL5qAz2UKrjYWXKSf4aMQ==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-2.5.0.tgz", + "integrity": "sha512-wXqbqSrIhE58TdrxxlfLwU9eDhrzppQDvGhBEr1gYbzzM4KKo3Y63gSjiDXRKLVS2UOXdPNR2v+KnQgNrs+xUg==", "dev": true }, "pirates": { @@ -13067,25 +13184,15 @@ "dev": true }, "postcss": { - "version": "7.0.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", - "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==", + "version": "8.1.10", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.1.10.tgz", + "integrity": "sha512-iBXEV5VTTYaRRdxiFYzTtuv2lGMQBExqkZKSzkJe+Fl6rvQrA/49UVGKqB+LG54hpW/TtDBMGds8j33GFNW7pg==", "dev": true, "requires": { - "chalk": "^2.4.2", + "colorette": "^1.2.1", + "nanoid": "^3.1.18", "source-map": "^0.6.1", - "supports-color": "^6.1.0" - }, - "dependencies": { - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } + "vfile-location": "^3.2.0" } }, "prelude-ls": { @@ -13120,6 +13227,12 @@ } } }, + "printj": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", + "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==", + "dev": true + }, "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", @@ -13248,9 +13361,9 @@ "dev": true }, "pupa": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.0.1.tgz", - "integrity": "sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", "dev": true, "requires": { "escape-goat": "^2.0.0" @@ -13435,6 +13548,15 @@ "util-deprecate": "^1.0.1" } }, + "readdir-glob": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.1.tgz", + "integrity": "sha512-91/k1EzZwDx6HbERR+zucygRFfiPl2zkIYZtv3Jjr6Mn7SkKcVct8aVO+sSRiGMc6fLf72du3d92/uY63YPdEA==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, "readdirp": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", @@ -13503,9 +13625,9 @@ } }, "registry-auth-token": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.0.tgz", - "integrity": "sha512-P+lWzPrsgfN+UEpDS3U8AQKg/UjZX6mQSJueZj3EK+vNESoqBSpBUD3gmu4sF9lOsjXWjF11dQKUqemf3veq1w==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", + "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", "dev": true, "requires": { "rc": "^1.2.8" @@ -14032,14 +14154,14 @@ } }, "sign-addon": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/sign-addon/-/sign-addon-2.0.6.tgz", - "integrity": "sha512-/8SQPNCrrZKMthdDf1IfI4XMbq8k9YsiiMyVeQL8xhhQSsZho6ZvEUBFSA70N0eznLZyab3k1d2CNOchYRYA6Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/sign-addon/-/sign-addon-3.1.0.tgz", + "integrity": "sha512-zZ7nKc5/3QWM3skYBosGDvYQf2jkKhW2u8BELrZoN1wgCSOnwsV9T47Vx9uaNbA3CyZ+V9XSA0tDVHoV1QfVPw==", "dev": true, "requires": { "common-tags": "1.8.0", "core-js": "3.6.5", - "deepcopy": "2.0.0", + "deepcopy": "2.1.0", "es6-error": "4.1.1", "es6-promisify": "6.1.1", "jsonwebtoken": "8.5.1", @@ -14245,9 +14367,9 @@ } }, "sonic-boom": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.1.0.tgz", - "integrity": "sha512-JyOf+Xt7GBN4tAic/DD1Bitw6OMgSHAnswhPeOiLpfRoSjPNjEIi73UF3OxHzhSNn9WavxGuCZzprFCGFSNwog==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.3.0.tgz", + "integrity": "sha512-4nX6OYvOYr6R76xfQKi6cZpTO3YSWe/vd+QdIfoH0lBy0MnPkeAbb2rRWgmgADkXUeCKPwO1FZAKlAVWAadELw==", "dev": true, "requires": { "atomic-sleep": "^1.0.0", @@ -14733,14 +14855,6 @@ "requires": { "first-chunk-stream": "^3.0.0", "strip-bom-buf": "^2.0.0" - }, - "dependencies": { - "first-chunk-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-3.0.0.tgz", - "integrity": "sha512-LNRvR4hr/S8cXXkIY5pTgVP7L3tq6LlYWcg9nWBuW7o1NMxKZo6oOVa/6GIekMGI0Iw7uC+HWimMe9u/VAeKqw==", - "dev": true - } } }, "strip-eof": { @@ -14880,56 +14994,22 @@ } }, "tar-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", - "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.4.tgz", + "integrity": "sha512-o3pS2zlG4gxr67GmFYBLlq+dM8gyRGUOvsrHclSkvtVtQbjV0s/+ZE8OpICbaj8clrX3tjeHngYGP7rweaBnuw==", "dev": true, "requires": { - "bl": "^1.0.0", - "buffer-alloc": "^1.2.0", - "end-of-stream": "^1.0.0", + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", - "readable-stream": "^2.3.0", - "to-buffer": "^1.1.1", - "xtend": "^4.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" } }, "term-size": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz", - "integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", + "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", "dev": true }, "terminal-link": { @@ -15106,12 +15186,6 @@ "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", "dev": true }, - "to-buffer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", - "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", - "dev": true - }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -15597,43 +15671,44 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true + "dev": true, + "optional": true }, "update-notifier": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.0.tgz", - "integrity": "sha512-w3doE1qtI0/ZmgeoDoARmI5fjDoT93IfKgEGqm26dGUOh8oNpaSTsGNdYRN/SjOuo10jcJGwkEL3mroKzktkew==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.0.0.tgz", + "integrity": "sha512-8tqsiVrMv7aZsKNSjqA6DdBLKJpZG1hRpkj1RbOJu1PgyP69OX+EInAnP1EK/ShX5YdPFgwWdk19oquZ0HTM8g==", "dev": true, "requires": { "boxen": "^4.2.0", - "chalk": "^3.0.0", + "chalk": "^4.1.0", "configstore": "^5.0.1", "has-yarn": "^2.1.0", "import-lazy": "^2.1.0", "is-ci": "^2.0.0", "is-installed-globally": "^0.3.1", - "is-npm": "^4.0.0", + "is-npm": "^5.0.0", "is-yarn-global": "^0.3.0", "latest-version": "^5.0.0", "pupa": "^2.0.1", + "semver": "^7.3.2", "semver-diff": "^3.1.1", "xdg-basedir": "^4.0.0" }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -15661,14 +15736,38 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } } }, @@ -15794,6 +15893,12 @@ "extsprintf": "^1.2.0" } }, + "vfile-location": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.2.0.tgz", + "integrity": "sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA==", + "dev": true + }, "vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", @@ -15985,17 +16090,17 @@ } }, "web-ext": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/web-ext/-/web-ext-5.0.0.tgz", - "integrity": "sha512-K5rzVijxNbOjxv+au1Sj7J82s1/CCyBQ9bhJE9TWdOD3OLELhC3bWJHyNJ1u2sT+kf8guaJjFvPnd6WG67PHtw==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/web-ext/-/web-ext-5.4.1.tgz", + "integrity": "sha512-AnTjSFtvidZfmVYzvceM/XixsigiWU3l66UzcxgXxXhOoEQU5ZHlXFGVJdHEYfkI5SnEyDG+WlhsdTUHNLOXJw==", "dev": true, "requires": { - "@babel/polyfill": "7.10.4", - "@babel/runtime": "7.10.5", + "@babel/polyfill": "7.12.1", + "@babel/runtime": "7.12.5", "@cliqz-oss/firefox-client": "0.3.1", "@cliqz-oss/node-firefox-connect": "1.2.1", - "adbkit": "2.11.1", - "addons-linter": "2.1.0", + "@devicefarmer/adbkit": "2.11.3", + "addons-linter": "2.13.1", "bunyan": "1.8.14", "camelcase": "6.0.0", "chrome-launcher": "0.13.4", @@ -16003,22 +16108,22 @@ "decamelize": "4.0.0", "es6-error": "4.1.1", "event-to-promise": "0.8.0", - "firefox-profile": "2.0.0", + "firefox-profile": "4.0.0", "fs-extra": "9.0.1", "fx-runner": "1.0.13", "import-fresh": "3.2.1", "mkdirp": "1.0.4", "multimatch": "4.0.0", "mz": "2.7.0", - "node-notifier": "7.0.2", - "open": "7.1.0", + "node-notifier": "8.0.0", + "open": "7.3.0", "parse-json": "5.0.1", - "sign-addon": "2.0.6", + "sign-addon": "3.1.0", "source-map-support": "0.5.19", "strip-bom": "4.0.0", "strip-json-comments": "3.1.1", "tmp": "0.2.1", - "update-notifier": "4.1.0", + "update-notifier": "5.0.0", "watchpack": "1.7.4", "ws": "7.3.1", "yargs": "15.4.1", @@ -16037,12 +16142,35 @@ "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, "mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true }, + "node-notifier": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.0.tgz", + "integrity": "sha512-46z7DUmcjoYdaWyXouuFNNfUo6eFa94t23c53c+lG/9Cvauk4a98rAUp9672X5dxGdQmLpPzTxzu8f/OeEPaFA==", + "dev": true, + "requires": { + "growly": "^1.3.0", + "is-wsl": "^2.2.0", + "semver": "^7.3.2", + "shellwords": "^0.1.1", + "uuid": "^8.3.0", + "which": "^2.0.2" + } + }, "parse-json": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.1.tgz", @@ -16055,6 +16183,15 @@ "lines-and-columns": "^1.1.6" } }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, "source-map-support": { "version": "0.5.19", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", @@ -16064,6 +16201,21 @@ "buffer-from": "^1.0.0", "source-map": "^0.6.0" } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } } }, @@ -16678,47 +16830,14 @@ } }, "zip-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz", - "integrity": "sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ=", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.0.4.tgz", + "integrity": "sha512-a65wQ3h5gcQ/nQGWV1mSZCEzCML6EK/vyVPcrPNynySP1j3VBbQKh3nhC8CbORb+jfl2vXvh56Ul5odP1bAHqw==", "dev": true, "requires": { - "archiver-utils": "^1.3.0", - "compress-commons": "^1.2.0", - "lodash": "^4.8.0", - "readable-stream": "^2.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } + "archiver-utils": "^2.1.0", + "compress-commons": "^4.0.2", + "readable-stream": "^3.6.0" } } } diff --git a/package.json b/package.json index c47b602e..36161a3d 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "ts-jest": "^26.2.0", "ts-loader": "^6.2.1", "typescript": "~3.7.3", - "web-ext": "^5.0.0", + "web-ext": "^5.4.1", "webpack": "~4.41.2", "webpack-cli": "~3.3.10", "webpack-merge": "~4.2.2" diff --git a/public/_locales/bg/messages.json b/public/_locales/bg/messages.json index 8ea6ea2a..013552c6 100644 --- a/public/_locales/bg/messages.json +++ b/public/_locales/bg/messages.json @@ -34,12 +34,6 @@ "Loading": { "message": "Зареждане..." }, - "Mins": { - "message": "Минути" - }, - "Secs": { - "message": "Секунди" - }, "Hide": { "message": "Никога не показвай" }, @@ -88,9 +82,6 @@ "submitCheck": { "message": "Сигурни ли сте, че искате да подадете това?" }, - "here": { - "message": "тук" - }, "discordAdvert": { "message": "Елате в официалния Discord сървър за да давате предложения!" }, diff --git a/public/_locales/ca/messages.json b/public/_locales/ca/messages.json index f87bd11e..7ec14f73 100644 --- a/public/_locales/ca/messages.json +++ b/public/_locales/ca/messages.json @@ -40,12 +40,6 @@ "Loading": { "message": "Carregant..." }, - "Mins": { - "message": "Minuts" - }, - "Secs": { - "message": "Segons" - }, "Hide": { "message": "No mostris mai" } diff --git a/public/_locales/cs/messages.json b/public/_locales/cs/messages.json index d0dbcc81..39f80714 100644 --- a/public/_locales/cs/messages.json +++ b/public/_locales/cs/messages.json @@ -40,12 +40,6 @@ "Loading": { "message": "Načítání..." }, - "Mins": { - "message": "Minuty" - }, - "Secs": { - "message": "Sekundy" - }, "Hide": { "message": "Nikdy nezobrazovat" }, @@ -121,6 +115,12 @@ "submitCheck": { "message": "Opravdu to chcete odeslat?" }, + "whitelistChannel": { + "message": "Přidat kanál do výjimek" + }, + "removeFromWhitelist": { + "message": "Odebrat kanál z výjimek" + }, "voteOnTime": { "message": "Hlasovat pro segment" }, @@ -133,9 +133,6 @@ "viewLeaderboard": { "message": "Žebříček" }, - "here": { - "message": "zde" - }, "recordTimesDescription": { "message": "Odeslat" }, @@ -575,6 +572,10 @@ "chooseACategory": { "message": "Vyberte kategorii" }, + "enableThisCategoryFirst": { + "message": "Pro odeslání segmentů v kategorii \"{0}\" to nejprve musíte povolit v nastavení. Nyní budete přesměrováni do nastavení.", + "description": "Used when submitting segments to only let them select a certain category if they have it enabled in the options." + }, "youMustSelectACategory": { "message": "Musíte vybrat kategorii pro všechny odeslané segmenty!" }, diff --git a/public/_locales/da/messages.json b/public/_locales/da/messages.json index 1f005634..85ab9d66 100644 --- a/public/_locales/da/messages.json +++ b/public/_locales/da/messages.json @@ -40,12 +40,6 @@ "Loading": { "message": "Indlæser..." }, - "Mins": { - "message": "Minutter" - }, - "Secs": { - "message": "Sekunder" - }, "Hide": { "message": "Vis aldrig" }, diff --git a/public/_locales/de/messages.json b/public/_locales/de/messages.json index cc1c9ab1..5e4700c4 100644 --- a/public/_locales/de/messages.json +++ b/public/_locales/de/messages.json @@ -4,7 +4,7 @@ "description": "Name of the extension." }, "Description": { - "message": "Überspringe gesponserte Videosegmente, Betteln um Abonnenten und mehr in YouTube Videos. Melde gesponserte Videosegmente in Videos, die du guckst, um anderen Zeit zu sparen.", + "message": "Überspringe Sponsoren, betteln um Abonnenten und mehr in YouTube Videos. Melde Sponsoren in Videos, die du guckst, um anderen Zeit zu sparen.", "description": "Description of the extension." }, "400": { @@ -40,12 +40,6 @@ "Loading": { "message": "Laden..." }, - "Mins": { - "message": "Minuten" - }, - "Secs": { - "message": "Sekunden" - }, "Hide": { "message": "Verstecken" }, @@ -86,7 +80,7 @@ "message": "Segment endet jetzt" }, "noVideoID": { - "message": "Kein YouTube-Video gefunden.\nWenn dies falsch ist, aktualisieren Sie den Tab." + "message": "Kein YouTube-Video gefunden.\nWenn dies falsch ist, aktualisiere den Tab." }, "success": { "message": "Geschafft!" @@ -121,11 +115,33 @@ "submitCheck": { "message": "Bist du sicher, dass du dies übermitteln willst?" }, + "whitelistChannel": { + "message": "Kanal zur Whitelist hinzufügen" + }, + "removeFromWhitelist": { + "message": "Kanal von der Whitelist entfernen" + }, "voteOnTime": { "message": "Über ein Segment abstimmen" }, - "here": { - "message": "hier" + "Submissions": { + "message": "Beiträge" + }, + "savedPeopleFrom": { + "message": "Andere Nutzer bewahrt vor: " + }, + "viewLeaderboard": { + "message": "Rangliste" + }, + "recordTimesDescription": { + "message": "Senden" + }, + "submissionEditHint": { + "message": "Die Bearbeitung von Beiträgen wird angezeigt, nachdem du auf Senden klickst", + "description": "Appears in the popup to inform them that editing has been moved to the video player." + }, + "popupHint": { + "message": "Tipp: Du kannst Tastenkombinationen für das Senden in den Optionen festlegen" }, "clearTimesButton": { "message": "Zeiten löschen" @@ -136,6 +152,9 @@ "publicStats": { "message": "So wirst du in der öffentlichen Rangliste angezeigt. Siehe" }, + "Username": { + "message": "Benutzername" + }, "setUsername": { "message": "Alias festlegen" }, @@ -231,6 +250,12 @@ "0": { "message": "Zeitüberschreibung. Überprüfe deine Internetverbindung. Bist du mit dem Internet verbunden, ist der Server wahrscheinlich offline." }, + "disableSkipping": { + "message": "Überspringen ist aktiviert" + }, + "enableSkipping": { + "message": "Überspringen ist deaktiviert" + }, "yourWork": { "message": "Deine Statistik", "description": "Used to describe the section that will show you the statistics from your submissions." @@ -268,6 +293,9 @@ "showTimeWithSkipsDescription": { "message": "Diese Zeit wird in Klammern neben der kompletten Videodauer im YouTube-Videoplayer angezeigt. Dies betrifft auch Segmente, die als \"In Suchleiste anzeigen\" markiert sind." }, + "youHaveSkipped": { + "message": "Du übersprangst " + }, "youHaveSaved": { "message": " und erspartest dir damit " }, @@ -283,6 +311,12 @@ "hoursLower": { "message": "Stunden" }, + "youHaveSavedTime": { + "message": "Du erspartest anderen" + }, + "youHaveSavedTimeEnd": { + "message": " ihres Lebens" + }, "statusReminder": { "message": "Du kannst den Serverstatus auf https://status.sponsor.ajay.app überprüfen." }, @@ -314,10 +348,10 @@ "message": "Invidious-Kompatibilität" }, "supportInvidiousDescription": { - "message": "Invidious (https://invidio.us) ist ein Drittanbieter-YouTube-Client. Um SponsorBlock mit Invidious verwenden zu können, musst du die zusätzlichen Berechtigungen akzeptieren. Dies funktioniert NICHT in Chrome's Inkognitomodus oder anderen Chromium-Varianten." + "message": "Invidious (invidio.us) ist ein Drittanbieter-YouTube-Client. Um Support zu aktivieren, müssen Sie die zusätzlichen Berechtigungen akzeptieren. Dies funktioniert NICHT im Incongnito-modus auf Chrome und anderen Chromium-Varianten." }, "optionsInfo": { - "message": "Zu überspringende Videosegmente auswählen, automatisches Überspringen, Knöpfe ein- & ausblenden und noch viel mehr." + "message": "Zu überspringende Kategorien auswählen, automatisches Überspringen, Tasten ein- & ausblenden und noch viel mehr." }, "addInvidiousInstance": { "message": "Invidious-Instanzen hinzufügen" @@ -524,10 +558,10 @@ "message": "Betatest-Server aktivieren" }, "whatEnableTestingServer": { - "message": "Deine Einreichungen und Bewertungen/Meldungen werden NICHT an den Hauptserver übertragen. Benutze diese Option also nur für Tests." + "message": "Deine Beiträge und Bewertungen/Meldungen werden NICHT an den Hauptserver übertragen. Benutze diese Option also nur für Tests." }, "testingServerWarning": { - "message": "Alle Einreichungen und Bewertungen/Meldungen werden NICHT an den Hauptserver übertragen. Deaktiviere die Betatest-Server Option um Einreichungen an den Hauptserver zu senden." + "message": "Alle Beiträge und Bewertungen/Meldungen werden NICHT an den Hauptserver übertragen. Deaktiviere die Betatest-Server Option um Einreichungen an den Hauptserver zu senden." }, "bracketNow": { "message": "(jetzt)" @@ -538,6 +572,10 @@ "chooseACategory": { "message": "Wähle eine Kategorie" }, + "enableThisCategoryFirst": { + "message": "Um Segmente aus der Kategorie \"{0}\" zu senden, musst du diese in den Optionen aktivieren. Du wirst jetzt zu den Optionen weitergeleitet.", + "description": "Used when submitting segments to only let them select a certain category if they have it enabled in the options." + }, "youMustSelectACategory": { "message": "Du musst eine Kategorie für jedes zu übermittelnde Segment auswählen!" }, @@ -598,5 +636,8 @@ }, "unsubmittedWarningDescription": { "message": "Zeigt eine Benachrichtigung an, wenn du ein Video mit nicht übertragenden Segmenten verlässt." + }, + "help": { + "message": "Hilfe" } } diff --git a/public/_locales/el/messages.json b/public/_locales/el/messages.json index 13b9ac79..cf8b08f2 100644 --- a/public/_locales/el/messages.json +++ b/public/_locales/el/messages.json @@ -24,12 +24,6 @@ "Loading": { "message": "Φόρτωση..." }, - "Mins": { - "message": "Λεπτά" - }, - "Secs": { - "message": "Δευτερόλεπτα" - }, "Hide": { "message": "Να μην εμφανίζεται ποτέ" }, @@ -51,9 +45,6 @@ "clearTimes": { "message": "Καθαρισμός τμημάτων" }, - "here": { - "message": "εδώ" - }, "Options": { "message": "Επιλογές" }, diff --git a/public/_locales/en/messages.json b/public/_locales/en/messages.json index c6d5db91..d631d2cc 100644 --- a/public/_locales/en/messages.json +++ b/public/_locales/en/messages.json @@ -40,12 +40,6 @@ "Loading": { "message": "Loading..." }, - "Mins": { - "message": "Minutes" - }, - "Secs": { - "message": "Seconds" - }, "Hide": { "message": "Never Show" }, @@ -103,9 +97,6 @@ "wantToSubmit": { "message": "Do you want to submit for video id" }, - "leftTimes": { - "message": "You seem to have left some segments unsubmitted. Go back to that page to submit them (they are not deleted)." - }, "clearTimes": { "message": "Clear Segments" }, @@ -139,9 +130,6 @@ "viewLeaderboard": { "message": "Leaderboard" }, - "here": { - "message": "here" - }, "recordTimesDescription": { "message": "Submit" }, @@ -244,6 +232,9 @@ "message": "If you still don't like it, hit the never show button.", "description": "The second line of the message displayed after the notice was upgraded." }, + "setSkipShortcut": { + "message": "Set key for skipping a segment" + }, "setStartSponsorShortcut": { "message": "Set key for start segment keybind" }, @@ -581,6 +572,10 @@ "chooseACategory": { "message": "Choose a Category" }, + "enableThisCategoryFirst": { + "message": "To submit segments with the category of \"{0}\", you must enable it in the options. You will be redirected to the options now.", + "description": "Used when submitting segments to only let them select a certain category if they have it enabled in the options." + }, "youMustSelectACategory": { "message": "You must select a category for all segments you are submitting!" }, @@ -636,12 +631,6 @@ "categoryUpdate2": { "message": "Open the options to skip intros, outros, merch, etc." }, - "unsubmittedWarning": { - "message": "Unsubmitted Segments Notification" - }, - "unsubmittedWarningDescription": { - "message": "Send a notification when you leave a video with segments that are not uploaded" - }, "help": { "message": "Help" } diff --git a/public/_locales/es/messages.json b/public/_locales/es/messages.json index 6ba74da4..0b8f3c24 100644 --- a/public/_locales/es/messages.json +++ b/public/_locales/es/messages.json @@ -40,12 +40,6 @@ "Loading": { "message": "Cargando..." }, - "Mins": { - "message": "Minutos" - }, - "Secs": { - "message": "Segundos" - }, "Hide": { "message": "Nunca Mostrar" }, @@ -128,14 +122,11 @@ "message": "Solicitudes" }, "savedPeopleFrom": { - "message": "Has salvado a gente de " + "message": "Tú salvado personas de " }, "viewLeaderboard": { "message": "Tablas de clasificación" }, - "here": { - "message": "aquí" - }, "recordTimesDescription": { "message": "Enviar" }, @@ -156,7 +147,7 @@ "message": "Esto se utiliza en la página de estadísticas públicas para mostrar cuánto has contribuido. Véala" }, "Username": { - "message": "Nombre de usario" + "message": "Usuario" }, "setUsername": { "message": "Escoger Nombre De Usuario" @@ -297,7 +288,7 @@ "message": "Esta duración aparece entre paréntesis junto al tiempo actual del video, debajo de la barra de navegación. Esta muestra la duración total del vídeo menos cualquier segmento eliminado. Esto incluye los segmentos marcados como solo \"Mostrar en la barra de navegación\"." }, "youHaveSkipped": { - "message": "Lo has saltado " + "message": "Los has saltado " }, "youHaveSaved": { "message": "Te has ahorrado " diff --git a/public/_locales/et/messages.json b/public/_locales/et/messages.json index 0967ef42..c9135746 100644 --- a/public/_locales/et/messages.json +++ b/public/_locales/et/messages.json @@ -1 +1,613 @@ -{} +{ + "fullName": { + "message": "SponsorBlock YouTube'ile - jäta sponsorid vahele", + "description": "Name of the extension." + }, + "Description": { + "message": "Jäta sponsorid, tellimise palumine ja muud YouTube'i videote tüütused vahele. Teata vaadatavate videote sponsoritest, et säästa teiste aega.", + "description": "Description of the extension." + }, + "400": { + "message": "Server ütles, et see taotlus oli sobimatu" + }, + "429": { + "message": "Sa oled sellele ühele videole liiga palju sponsoriaegu saatnud, kas oled kindel, et neid on tõesti nii palju?" + }, + "409": { + "message": "See on juba varasemalt saadetud" + }, + "channelWhitelisted": { + "message": "Kanal lubamisnimekirjas!" + }, + "Segment": { + "message": "segmendi" + }, + "Segments": { + "message": "segmenti" + }, + "upvoteButtonInfo": { + "message": "Anna segmendile poolthääl" + }, + "reportButtonTitle": { + "message": "Teavita" + }, + "reportButtonInfo": { + "message": "Teavita sellest segmendist kui sobimatust." + }, + "Dismiss": { + "message": "Sulge" + }, + "Loading": { + "message": "Laadimine..." + }, + "Hide": { + "message": "Ära näita kunagi" + }, + "hitGoBack": { + "message": "Vajuta \"tühista vahelejätmine\", et jõuda sinna, kust tulid." + }, + "unskip": { + "message": "Tühista vahelejätmine" + }, + "reskip": { + "message": "Jäta uuesti vahele" + }, + "paused": { + "message": "Pausil" + }, + "manualPaused": { + "message": "Taimer peatatud" + }, + "confirmMSG": { + "message": "Üksikute väärtuste muutmiseks või kustutamiseks vajuta infonuppu või ava laienduse hüpik, vajutades selle ikoonile üleval paremal nurgas." + }, + "clearThis": { + "message": "Kas soovid tõesti selle tühjendada?\n\n" + }, + "Unknown": { + "message": "Sinu sponsoriaegade saatmisel esines tõrge, palun proovi hiljem uuesti." + }, + "sponsorFound": { + "message": "Sellel videol on andmebaasis segmente!" + }, + "sponsor404": { + "message": "Segmente ei leitud" + }, + "sponsorStart": { + "message": "Segment algab nüüd" + }, + "sponsorEnd": { + "message": "Segment lõpeb nüüd" + }, + "noVideoID": { + "message": "YouTube'i videot ei leitud.\nKui see ei vasta tõele, laadi kaart uuesti." + }, + "success": { + "message": "Õnnestus!" + }, + "voted": { + "message": "Hääletatud!" + }, + "serverDown": { + "message": "Tundub, et server on maas. Anna sellest koheselt arendajale teada." + }, + "connectionError": { + "message": "Ühendusega esines tõrge. Veakood: " + }, + "wantToSubmit": { + "message": "Kas soovid segmendid saata video IDle" + }, + "leftTimes": { + "message": "Sul tunduvad olevat mõned segmendid esitamata. Nende esitamiseks mine sellele lehele tagasi (need ei ole kustutatud)." + }, + "clearTimes": { + "message": "Tühjenda segmendid" + }, + "openPopup": { + "message": "Ava SponsorBlocki hüpik" + }, + "closePopup": { + "message": "Sulge hüpik" + }, + "SubmitTimes": { + "message": "Esita segmendid" + }, + "submitCheck": { + "message": "Kas soovid kindlasti selle saata?" + }, + "whitelistChannel": { + "message": "Lisa kanal lubamisnimekirja" + }, + "removeFromWhitelist": { + "message": "Eemalda kanal lubamisnimekirjast" + }, + "voteOnTime": { + "message": "Hääleta segmendi sobivust" + }, + "Submissions": { + "message": "Saadetud segmendid" + }, + "savedPeopleFrom": { + "message": "Oled inimeste aega säästnud " + }, + "viewLeaderboard": { + "message": "Edetabel" + }, + "recordTimesDescription": { + "message": "Saada" + }, + "submissionEditHint": { + "message": "Segmendi töötlemine avaneb pärast saatmist", + "description": "Appears in the popup to inform them that editing has been moved to the video player." + }, + "popupHint": { + "message": "Vihje: sa võid saatmiseks määrata valikutes klaviatuuriotseteid" + }, + "clearTimesButton": { + "message": "Tühjenda ajad" + }, + "submitTimesButton": { + "message": "Saada ajad" + }, + "publicStats": { + "message": "Seda kasutatakse avaliku statistika lehel, et näidata välja, kui palju oled panustanud. Vaata seda" + }, + "Username": { + "message": "Kasutajanimi" + }, + "setUsername": { + "message": "Määra kasutajanimi" + }, + "discordAdvert": { + "message": "Tule liitu ametliku Discordi serveriga, et anda soovitusi ja tagasisidet!" + }, + "hideThis": { + "message": "Peida see" + }, + "Options": { + "message": "Valikud" + }, + "showButtons": { + "message": "Kuva YouTube'i mängijal nupud" + }, + "hideButtons": { + "message": "Peida YouTube'i mängijal nupud" + }, + "hideButtonsDescription": { + "message": "See peidab nupud, mis kuvatakse YouTube'i mängijal vahelejätmiste segmentide saatmiseks." + }, + "showInfoButton": { + "message": "Kuva YouTube'i mängijal infonupp" + }, + "hideInfoButton": { + "message": "Peida YouTube'i mängijal infonupp" + }, + "whatInfoButton": { + "message": "See on see nupp, mis avab YouTube'i lehel hüpiku." + }, + "hideDeleteButton": { + "message": "Peida YouTube'i mängijal kustutusnupp" + }, + "showDeleteButton": { + "message": "Kuva YouTube'i mängijal kustutusnupp" + }, + "whatDeleteButton": { + "message": "YouTube'i mängija nupp, mis tühjendab kõik sinu praeguse video saatmata segmendid." + }, + "enableViewTracking": { + "message": "Luba vahelejätmiste arvu jälgimine" + }, + "whatViewTracking": { + "message": "See funktsioon jälgib, milliseid segmente sa oled vahele jätnud, et kasutajad teaksid, kui palju nende sisestus on teisi aidanud ning et koos poolthäältega veenduda rämpsu mittesattumises andmebaasi. Laiendus saadab iga segmendi vahelejätmisel serverisse sõnumi. Loodetavasti enamus inimesi ei muuda seda seadistust, et vaatamisarvud oleksid täpsed. :)" + }, + "enableQueryByHashPrefix": { + "message": "Küsi räsi eesliite järgi" + }, + "whatQueryByHashPrefix": { + "message": "VideoID järgi segmentide küsimise asemel saadetakse videoID räsi 4 esimest märki ning server saadab tagasi kõigi sarnaste räsidega videote andmed." + }, + "enableRefetchWhenNotFound": { + "message": "Too segmendid uutel videotel uuesti" + }, + "whatRefetchWhenNotFound": { + "message": "Kui video on uus ning segmente ei leitud, proovitakse vaatamise ajal iga paari minuti tagant uuesti segmente tuua." + }, + "showNotice": { + "message": "Kuva märkus uuesti" + }, + "longDescription": { + "message": "SponsorBlock lubab sul vahele jätta sponsorid, vaheajad, kanali tellimise meeldetuletused ja muud YouTube'i videote tüütud kohad. SponsorBlock on rahva ühistööna toimiv brauserilaiendus, mis lubab igaühel saata sponsoreeritud segmendi algus- ja lõpuaegu ning teiste video segmentide aegu. Kui üks inimene saadab sponsoreeritud segmendi, jätavad teised laienduse kasutajad kohe selle vahele. Laiendus võimaldab ka muusikavideotel mitte-muusika jaotised vahele jätta.", + "description": "Full description of the extension on the store pages." + }, + "website": { + "message": "Veebileht", + "description": "Used on Firefox Store Page" + }, + "sourceCode": { + "message": "Lähtekood", + "description": "Used on Firefox Store Page" + }, + "noticeUpdate": { + "message": "Teavitus on uuendatud!", + "description": "The first line of the message displayed after the notice was upgraded." + }, + "noticeUpdate2": { + "message": "Kui sulle see ikka ei meeldi, vajuta \"ära näita kunagi\" nuppu.", + "description": "The second line of the message displayed after the notice was upgraded." + }, + "setStartSponsorShortcut": { + "message": "Seadista segmendi alustamise klahv" + }, + "setSubmitKeybind": { + "message": "Seadista segmendi saatmise klahv" + }, + "keybindDescription": { + "message": "Vali klahv, seda vajutades" + }, + "keybindDescriptionComplete": { + "message": "Otsetee on seatud: " + }, + "disableSkipping": { + "message": "Vahelejätmine on lubatud" + }, + "enableSkipping": { + "message": "Vahelejätmine on keelatud" + }, + "yourWork": { + "message": "Sinu töö", + "description": "Used to describe the section that will show you the statistics from your submissions." + }, + "502": { + "message": "Server paistab olevat ülekoormatud. Proovi uuesti mõne sekundi pärast." + }, + "errorCode": { + "message": "Veakood: " + }, + "skip": { + "message": "Jäta vahele" + }, + "skip_category": { + "message": "Jätad {0} vahele?" + }, + "skipped": { + "message": "Vahelejäetud" + }, + "disableAutoSkip": { + "message": "Keela automaatne vahelejätmine" + }, + "enableAutoSkip": { + "message": "Luba automaatne vahelejätmine" + }, + "audioNotification": { + "message": "Heliteavitus vahelejätmisel" + }, + "showTimeWithSkips": { + "message": "Kuva vahelejäetud segmentidega aeg" + }, + "youHaveSkipped": { + "message": "Oled vahele jätnud " + }, + "youHaveSaved": { + "message": "Oled enda aega säästnud " + }, + "minLower": { + "message": "minut" + }, + "minsLower": { + "message": "minutit" + }, + "hourLower": { + "message": "tund" + }, + "hoursLower": { + "message": "tundi" + }, + "youHaveSavedTime": { + "message": "Oled inimestel säästnud" + }, + "youHaveSavedTimeEnd": { + "message": " nende ajast" + }, + "statusReminder": { + "message": "Serveri oleku saamiseks vaata status.sponsor.ajay.app" + }, + "changeUserID": { + "message": "Impordi/ekspordi oma UserID" + }, + "whatChangeUserID": { + "message": "Seda tuleks privaatsena hoida. See on nagu parool ning seda ei tohiks kellegagi jagada. Kui kellelgi see on, saavad nad sinuna esineda." + }, + "setUserID": { + "message": "Seadista UserID" + }, + "userIDChangeWarning": { + "message": "Hoiatus: UserID muutmine on püsiv. Kas soovid kindlasti seda teha? Igaks juhuks soovitame eelmise UserID varundada." + }, + "createdBy": { + "message": "Autor" + }, + "autoSkip": { + "message": "Autom. vahelejätmine" + }, + "showSkipNotice": { + "message": "Kuva segmendi vahelejätmisel teatis" + }, + "keybindCurrentlySet": { + "message": ". Hetkel on selleks määratud:" + }, + "supportInvidious": { + "message": "Invidiouse tugi" + }, + "supportInvidiousDescription": { + "message": "Invidious (invidio.us) on kolmanda osapoole YouTube'i klient. Selle toe lubamiseks pead nõustuma lisalubadega. See EI tööta inkognito-režiimis nii Chromes kui ka teistes Chromiumi brauserites." + }, + "optionsInfo": { + "message": "Luba Invidiouse tugi, keela automaatne vahelejätmine, peida nupud ja muud valikud." + }, + "addInvidiousInstance": { + "message": "Lisa Invidiouse eksemplar" + }, + "addInvidiousInstanceDescription": { + "message": "Lisa kohandatud Invidiouse eksemplar. See tuleb vormistada AINULT domeeniga. Näide:\ninvidious.ajay.app" + }, + "add": { + "message": "Lisa" + }, + "addInvidiousInstanceError": { + "message": "See on sobimatu domeen. Siia tuleks kirjutada AINULT domeeniosa, nt invidious.ajay.app" + }, + "resetInvidiousInstance": { + "message": "Lähtesta Invidiouse eksemplaride nimekiri" + }, + "resetInvidiousInstanceAlert": { + "message": "Lähtestad Invidiouse eksemplaride nimekirja" + }, + "currentInstances": { + "message": "Praegused eksemplarid:" + }, + "minDuration": { + "message": "Minimaalne kestus (sekundit):" + }, + "minDurationDescription": { + "message": "Segmendid, mis on lühemad kui määratud väärtus ei jäeta vahele või ei kuvata mängijal." + }, + "showUploadButton": { + "message": "Kuva üleslaadimisnupp" + }, + "whatUploadButton": { + "message": "See nupp kuvatakse YouTube'i mängijal, kui oled ajatempli ära valinud ning saatmiseks valmis." + }, + "customServerAddress": { + "message": "SponsorBlocki serveri aadress" + }, + "save": { + "message": "Salvesta" + }, + "reset": { + "message": "Lähtesta" + }, + "customAddressError": { + "message": "Aadress ei ole õiges vormingus. Veendu, et sul on alguses http:// või https:// ning lõpus ei ole kaldkriipsu." + }, + "areYouSureReset": { + "message": "Kas soovid kindlasti selle lähtestada?" + }, + "confirmPrivacy": { + "message": "See video on registrivälisena tuvastatud. Klõpsa \"tühista\", kui ei soovi otsida vahelejätmise segmente." + }, + "unlistedCheck": { + "message": "Ignoreeri registriväliseid/privaatsed videoid" + }, + "whatUnlistedCheck": { + "message": "See valik aeglustab veidi SponsorBlocki. Vahelejätmise segmentide hankimiseks saadetakse video ID serverisse. Kui oled mures registriväliste videote IDde internetti saatmise üle, luba see valik." + }, + "mobileUpdateInfo": { + "message": "m.youtube.com on nüüd toetatud" + }, + "exportOptions": { + "message": "Impordi/ekspordi kõik valikud" + }, + "whatExportOptions": { + "message": "See on sinu kogu seadistus JSON-formaadis. Selle hulgas on ka UserID, seega jaga seda targalt." + }, + "setOptions": { + "message": "Määra valikud" + }, + "incorrectlyFormattedOptions": { + "message": "See JSON ei ole korralikult vormistatud. Sinu valikuid ei muudetud." + }, + "confirmNoticeTitle": { + "message": "Saada segment" + }, + "submit": { + "message": "Saada" + }, + "cancel": { + "message": "Katkesta" + }, + "delete": { + "message": "Kustuta" + }, + "preview": { + "message": "Eelvaade" + }, + "inspect": { + "message": "Inspekteeri" + }, + "edit": { + "message": "Muuda" + }, + "copyDebugInformation": { + "message": "Kopeeri silumisteave lõikelauale" + }, + "copyDebugInformationFailed": { + "message": "Lõikelauale kirjutamine ebaõnnestus" + }, + "theKey": { + "message": "Klahv" + }, + "keyAlreadyUsed": { + "message": "on juba teisele tegevusele määratud. Palun vali teine klahv." + }, + "to": { + "message": "kuni", + "description": "Used between segments. Example: 1:20 to 1:30" + }, + "category_sponsor": { + "message": "Sponsor" + }, + "category_sponsor_description": { + "message": "Tasulised promod, tasulised viited ja otsesed reklaamid. Pole mõeldud enesepromo või tasuta petitsioonide/autorite/veebilehtede/toodete mainimiste puhul." + }, + "category_intro": { + "message": "Vaheaeg/sissejuhatav animatsioon" + }, + "category_intro_description": { + "message": "Tegeliku sisuta intervall. Võib olla paus, seisev pilt, korduv animatsioon. Seda ei peaks kasutama üleminekutel, milles on teabega sisu." + }, + "category_intro_short": { + "message": "Vaheaeg" + }, + "category_outro": { + "message": "Lõpukaardid/-tiitrid" + }, + "category_outro_description": { + "message": "Tiitrid või YouTube'i lõpukaardid. Pole mõeldud informatsiooniga järelduste jaoks." + }, + "category_interaction": { + "message": "Tegutsemise meeldetuletus (kanali tellimine)" + }, + "category_interaction_description": { + "message": "Lühike sisukeskne meeldetuletus anda videole meeldib, tellida kanalit või jälgida autorit. Kui see on pikk või millegi kindlaga seotud, peaks see olema enesepromo all." + }, + "category_interaction_short": { + "message": "Tegutsemise meeldetuletus" + }, + "category_selfpromo": { + "message": "Tasumata/enesepromo" + }, + "category_selfpromo_description": { + "message": "Sarnaneb \"sponsorile\", ent on mõeldud tasumata või enesepromo jaoks. Selle alla kuuluvad jaotised oma müüdava kauba, annetuste ja koostööpartnerite kohta." + }, + "category_music_offtopic": { + "message": "Muusika: mitte-muusika jaotis" + }, + "category_music_offtopic_description": { + "message": "Ainult muusikavideotes kasutamiseks. Sisaldab muusikavideote sissejuhatusi ja väljajuhatusi." + }, + "category_music_offtopic_short": { + "message": "Mitte-muusika" + }, + "category_livestream_messages": { + "message": "Otseülekanne: annetuste ja sõnumite lugemine" + }, + "category_livestream_messages_short": { + "message": "Sõnumite lugemine" + }, + "disable": { + "message": "Keela" + }, + "manualSkip": { + "message": "Käsitsi vahelejätmine" + }, + "showOverlay": { + "message": "Kuva mängija ajaribal" + }, + "colorFormatIncorrect": { + "message": "Sinu värv on sobimatult vormistatud. See peaks olema 3- või 6-numbriline 16-kümmendsüsteemis kood, arvu ees trellid." + }, + "previewColor": { + "message": "Värvi eelvaade", + "description": "Referring to submissions that have not been sent to the server yet." + }, + "seekBarColor": { + "message": "Ajariba värv" + }, + "category": { + "message": "Kategooria" + }, + "skipOption": { + "message": "Vahelejätmise valik", + "description": "Used on the options page to describe the ways to skip the segment (auto skip, manual, etc.)" + }, + "enableTestingServer": { + "message": "Luba beetatestimise server" + }, + "whatEnableTestingServer": { + "message": "Sinu saadetud segmendid ja hääled EI LÄHE põhiserveri alla. Kasuta seda vaid katsetamiseks." + }, + "bracketNow": { + "message": "(nüüd)" + }, + "moreCategories": { + "message": "Rohkem kategooriaid" + }, + "chooseACategory": { + "message": "Vali kategooria" + }, + "enableThisCategoryFirst": { + "message": "Kategooriaga \"{0}\" segmentide saatmiseks pead selle enne valikutes lubama. Sind suunatakse nüüd valikutesse.", + "description": "Used when submitting segments to only let them select a certain category if they have it enabled in the options." + }, + "youMustSelectACategory": { + "message": "Sa pead enne saatmist igale segmendile kategooria valima!" + }, + "bracketEnd": { + "message": "(lõpp)" + }, + "hiddenDueToDownvote": { + "message": "peidetud: vastuhääl" + }, + "hiddenDueToDuration": { + "message": "peidetud: liiga lühike" + }, + "channelDataNotFound": { + "message": "Kanali ID pole veel laaditud." + }, + "adblockerIssue": { + "message": "Tundub, et miski segab SponsorBlocki video andmete hankimise võimalust. See on ilmselt sinu reklaamiblokeerija. Palun vaata https://github.com/ajayyy/SponsorBlock/wiki/Fix-Ad-Blocker-Blocking-SponsorBlock's-Requests" + }, + "itCouldBeAdblockerIssue": { + "message": "Kui see jätkub, võib see olla põhjustatud sinu reklaamiblokeerijast. Palun vaata https://github.com/ajayyy/SponsorBlock/wiki/Fix-Ad-Blocker-Blocking-SponsorBlock's-Requests" + }, + "forceChannelCheck": { + "message": "Sunnitud kanalikontroll enne vahelejätmist" + }, + "forceChannelCheckPopup": { + "message": "Kaalu valiku \"Sunnitud kanalikontroll enne vahelejätmist\" lubamist" + }, + "downvoteDescription": { + "message": "Sobimatu/vale ajastus" + }, + "incorrectCategory": { + "message": "Vale kategooria" + }, + "nonMusicCategoryOnMusic": { + "message": "See video on muusikana kategoriseeritud. Kas oled kindel, et sellel on sponsor? Kui see on tegelikult \"mitte-muusika segment\", ava laienduse valikud ning luba see kategooria. Seejärel saad selle segmendi saata \"mitte-muusika\" kategoorias. Segaduse korral palun loe üle juhised." + }, + "multipleSegments": { + "message": "Mitu segmenti" + }, + "guidelines": { + "message": "Juhised" + }, + "readTheGuidelines": { + "message": "Loe juhiseid!!", + "description": "Show the first time they submit or if they are \"high risk\"" + }, + "categoryUpdate1": { + "message": "Kategooriad on siin!" + }, + "categoryUpdate2": { + "message": "Ava valikud, et jätta vahele vaheaegu, müüdavat kaupa jms." + }, + "unsubmittedWarning": { + "message": "Saatmata segmentide teatis" + }, + "unsubmittedWarningDescription": { + "message": "Saada teavitus, kui lahkud videost segmentidega, mis ei ole üleslaaditud" + }, + "help": { + "message": "Abi" + } +} diff --git a/public/_locales/fa/messages.json b/public/_locales/fa/messages.json index c842c6ab..97e64a57 100644 --- a/public/_locales/fa/messages.json +++ b/public/_locales/fa/messages.json @@ -30,12 +30,6 @@ "Loading": { "message": "درحال بارگذاری..." }, - "Mins": { - "message": "دقیقه" - }, - "Secs": { - "message": "ثانیه" - }, "Hide": { "message": "هرگز نمایش نده" }, @@ -102,9 +96,6 @@ "voteOnTime": { "message": "رأی دهی به یک بخش" }, - "here": { - "message": "اینجا" - }, "clearTimesButton": { "message": "حذف دفعات" }, diff --git a/public/_locales/fi/messages.json b/public/_locales/fi/messages.json index 4d21be54..d574ce8b 100644 --- a/public/_locales/fi/messages.json +++ b/public/_locales/fi/messages.json @@ -40,12 +40,6 @@ "Loading": { "message": "Ladataan..." }, - "Mins": { - "message": "Minuuttia" - }, - "Secs": { - "message": "Sekuntia" - }, "Hide": { "message": "Älä näytä koskaan" }, @@ -121,9 +115,6 @@ "voteOnTime": { "message": "Äänestä Segmenttiä" }, - "here": { - "message": "tässä" - }, "clearTimesButton": { "message": "Tyhjennä ajat" }, diff --git a/public/_locales/fr/messages.json b/public/_locales/fr/messages.json index 6ea0935a..83b3df21 100644 --- a/public/_locales/fr/messages.json +++ b/public/_locales/fr/messages.json @@ -40,12 +40,6 @@ "Loading": { "message": "Chargement..." }, - "Mins": { - "message": "Minutes" - }, - "Secs": { - "message": "Secondes" - }, "Hide": { "message": "Ne plus montrer" }, @@ -80,7 +74,7 @@ "message": "Aucun segment trouvé" }, "sponsorStart": { - "message": "Début du segement" + "message": "Début du segment" }, "sponsorEnd": { "message": "Fin du segment" @@ -121,11 +115,33 @@ "submitCheck": { "message": "Êtes-vous sûr de vouloir soumettre ces segments?" }, + "whitelistChannel": { + "message": "Whitelister la chaîne" + }, + "removeFromWhitelist": { + "message": "Enlever la chaîne de la liste blanche" + }, "voteOnTime": { "message": "Voter pour un segment" }, - "here": { - "message": "ici" + "Submissions": { + "message": "Contributions" + }, + "savedPeopleFrom": { + "message": "Vous avez sauvé les utilisateurs de " + }, + "viewLeaderboard": { + "message": "Classement" + }, + "recordTimesDescription": { + "message": "Envoyer" + }, + "submissionEditHint": { + "message": "Le menu d'édition du segment apparaîtra après que vous ayez cliqué sur envoyer", + "description": "Appears in the popup to inform them that editing has been moved to the video player." + }, + "popupHint": { + "message": "Astuce : Vous pouvez configurer des raccourcis clavier dans les options" }, "clearTimesButton": { "message": "Supprimer les temps" @@ -234,6 +250,12 @@ "0": { "message": "Délai de connexion dépassé. Vérifiez votre connexion internet. Si votre connexion internet fonctionne, le serveur est probablement surchargé ou hors service." }, + "disableSkipping": { + "message": "Le saut de segment est activé" + }, + "enableSkipping": { + "message": "Le saut de segment est désactivé" + }, "yourWork": { "message": "Votre travail", "description": "Used to describe the section that will show you the statistics from your submissions." @@ -289,6 +311,9 @@ "hoursLower": { "message": "heures" }, + "youHaveSavedTime": { + "message": "Les utilisateurs ont gagné" + }, "statusReminder": { "message": "Vérifiez status.sponsor.ajay.app pour le status du serveur." }, diff --git a/public/_locales/hr/messages.json b/public/_locales/hr/messages.json index 1a84577d..6b6e40cb 100644 --- a/public/_locales/hr/messages.json +++ b/public/_locales/hr/messages.json @@ -40,12 +40,6 @@ "Loading": { "message": "Učitavanje..." }, - "Mins": { - "message": "Minute" - }, - "Secs": { - "message": "Sekunde" - }, "Hide": { "message": "Nikad ne prikazuj" }, @@ -118,9 +112,6 @@ "voteOnTime": { "message": "Glasaj za isječak" }, - "here": { - "message": "ovdje" - }, "clearTimesButton": { "message": "Očisti vremena" }, diff --git a/public/_locales/hu/messages.json b/public/_locales/hu/messages.json index d85b805e..b04e4252 100644 --- a/public/_locales/hu/messages.json +++ b/public/_locales/hu/messages.json @@ -40,12 +40,6 @@ "Loading": { "message": "Betöltés..." }, - "Mins": { - "message": "Perc" - }, - "Secs": { - "message": "Másodperc" - }, "Hide": { "message": "Ne mutassa többé" }, @@ -121,9 +115,6 @@ "voteOnTime": { "message": "Szavazzon a szegmensről" }, - "here": { - "message": "itt" - }, "clearTimesButton": { "message": "Időpontok törlése" }, diff --git a/public/_locales/id/messages.json b/public/_locales/id/messages.json index 82b8a82b..84e3982c 100644 --- a/public/_locales/id/messages.json +++ b/public/_locales/id/messages.json @@ -40,12 +40,6 @@ "Loading": { "message": "Memuat..." }, - "Mins": { - "message": "Menit" - }, - "Secs": { - "message": "Detik" - }, "Hide": { "message": "Jangan tampilkan" }, @@ -85,6 +79,9 @@ "sponsorEnd": { "message": "Segmen Berakhir Sekarang" }, + "noVideoID": { + "message": "Video YouTube tidak ditemukan.\nJika ini salah, segarkan tab." + }, "success": { "message": "Sukses!" }, @@ -118,11 +115,33 @@ "submitCheck": { "message": "Apakah anda yakin ingin mengirim ini?" }, + "whitelistChannel": { + "message": "Saluran daftar putih" + }, + "removeFromWhitelist": { + "message": "Hapus saluran dari daftar putih" + }, "voteOnTime": { "message": "Beri Segmen Vote" }, - "here": { - "message": "disini" + "Submissions": { + "message": "Kiriman" + }, + "savedPeopleFrom": { + "message": "Anda telah menyelamatkan orang dari " + }, + "viewLeaderboard": { + "message": "Papan peringkat" + }, + "recordTimesDescription": { + "message": "Kirim" + }, + "submissionEditHint": { + "message": "Pengeditan bagian akan muncul setelah anda mengklik kirim", + "description": "Appears in the popup to inform them that editing has been moved to the video player." + }, + "popupHint": { + "message": "Petunjuk: Anda dapat mengatur keybinds untuk dikirim dalam opsi" }, "clearTimesButton": { "message": "Hapus Waktu" @@ -133,6 +152,9 @@ "publicStats": { "message": "Ini digunakan di halaman statistik publik untuk menampilkan berapa banyak anda berkontribusi. Lihat disini" }, + "Username": { + "message": "Nama pengguna" + }, "setUsername": { "message": "Atur Nama Pengguna" }, @@ -228,6 +250,12 @@ "0": { "message": "Koneksi Timeout. Cek koneksi internet anda. Jika internet anda berfungsi, server mungkin kewalahan atau down." }, + "disableSkipping": { + "message": "Melewati diaktifkan" + }, + "enableSkipping": { + "message": "Melewati dinonaktifkan" + }, "yourWork": { "message": "Hasil Kerja Anda", "description": "Used to describe the section that will show you the statistics from your submissions." @@ -265,6 +293,9 @@ "showTimeWithSkipsDescription": { "message": "Waktu ini muncul di dalam kurung disamping waktu asli di bilah waktu. Ini menunjukkan durasi total video yang tidak termasuk segmen apapun. Ini termasuk segmen yang ditandai hanya \"Tampilkan Di Bilah Waktu\"." }, + "youHaveSkipped": { + "message": "Anda telah melewatkan " + }, "youHaveSaved": { "message": "Anda sudah menghemat waktu " }, @@ -280,6 +311,12 @@ "hoursLower": { "message": "jam" }, + "youHaveSavedTime": { + "message": "Anda telah menyelamatkan orang" + }, + "youHaveSavedTimeEnd": { + "message": " dalam hidup mereka" + }, "statusReminder": { "message": "Cek status.sponsor.ajay.app untuk status server." }, @@ -535,6 +572,10 @@ "chooseACategory": { "message": "Pilih Kategori" }, + "enableThisCategoryFirst": { + "message": "Untuk mengirimkan segmen dengan kategori \"{0}\", Anda harus mengaktifkannya di opsi. Anda akan diarahkan ke opsi sekarang.", + "description": "Used when submitting segments to only let them select a certain category if they have it enabled in the options." + }, "youMustSelectACategory": { "message": "Anda harus memilih kategori untuk semua segmen yang anda kirimkan!" }, @@ -595,5 +636,8 @@ }, "unsubmittedWarningDescription": { "message": "Tampilkan notifikasi saat kamu meninggalkan video dengan segmen yang belum diunggah" + }, + "help": { + "message": "Bantuan" } } diff --git a/public/_locales/it/messages.json b/public/_locales/it/messages.json index 9b270b0a..a0255b69 100644 --- a/public/_locales/it/messages.json +++ b/public/_locales/it/messages.json @@ -40,12 +40,6 @@ "Loading": { "message": "Caricamento..." }, - "Mins": { - "message": "Minuti" - }, - "Secs": { - "message": "Secondi" - }, "Hide": { "message": "Non mostrare più" }, @@ -133,9 +127,6 @@ "viewLeaderboard": { "message": "Classifica" }, - "here": { - "message": "qui" - }, "recordTimesDescription": { "message": "Invia" }, diff --git a/public/_locales/ja/messages.json b/public/_locales/ja/messages.json index d55ab42d..bcd793b9 100644 --- a/public/_locales/ja/messages.json +++ b/public/_locales/ja/messages.json @@ -21,12 +21,6 @@ "Loading": { "message": "読み込み中..." }, - "Mins": { - "message": "分" - }, - "Secs": { - "message": "秒" - }, "unskip": { "message": "スキップしない" }, @@ -39,9 +33,6 @@ "closePopup": { "message": "ポップアップを閉じる" }, - "here": { - "message": "こちら" - }, "Options": { "message": "オプション" }, diff --git a/public/_locales/ko/messages.json b/public/_locales/ko/messages.json index 707c30d8..1feacece 100644 --- a/public/_locales/ko/messages.json +++ b/public/_locales/ko/messages.json @@ -40,12 +40,6 @@ "Loading": { "message": "로딩 중..." }, - "Mins": { - "message": "분" - }, - "Secs": { - "message": "초" - }, "Hide": { "message": "보지 않기" }, @@ -85,6 +79,9 @@ "sponsorEnd": { "message": "광고 구간 끝" }, + "noVideoID": { + "message": "찾은 유튜브 비디오가 없습니다.\n이 것이 틀리다면, 텝을 새로고침 하세요." + }, "success": { "message": "성공!" }, @@ -118,12 +115,15 @@ "submitCheck": { "message": "정말로 제출하시겠습니까?" }, + "whitelistChannel": { + "message": "화이트리스트 체널" + }, + "removeFromWhitelist": { + "message": "항목을 화이트리스트에서 삭제하기" + }, "voteOnTime": { "message": "구간 투표" }, - "here": { - "message": "링크" - }, "clearTimesButton": { "message": "시간 초기화" }, @@ -595,5 +595,8 @@ }, "unsubmittedWarningDescription": { "message": "업로드되지 않은 구간이 있는 영상이 있을 때 알림을 보냅니다" + }, + "help": { + "message": "도움" } } diff --git a/public/_locales/ml/messages.json b/public/_locales/ml/messages.json index 89bba4c9..66e5561f 100644 --- a/public/_locales/ml/messages.json +++ b/public/_locales/ml/messages.json @@ -40,12 +40,6 @@ "Loading": { "message": "ലോഡിംഗ്..." }, - "Mins": { - "message": "മിനിറ്റ്" - }, - "Secs": { - "message": "സെക്കൻഡ്" - }, "Hide": { "message": "ഒരിക്കലും കാണിക്കരുത്" }, @@ -85,6 +79,9 @@ "sponsorEnd": { "message": "സെഗ്മെന്റ് ഇപ്പോൾ അവസാനിക്കുന്നു" }, + "noVideoID": { + "message": "YouTube വീഡിയോകളൊന്നും കണ്ടെത്തിയില്ല.\nഇത് തെറ്റാണെങ്കിൽ, ടാബ് പുതുക്കുക." + }, "success": { "message": "വിജയം!" }, @@ -118,11 +115,33 @@ "submitCheck": { "message": "ഇത് സമർപ്പിക്കാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്നുണ്ടോ?" }, + "whitelistChannel": { + "message": "വൈറ്റ്ലിസ്റ്റ് ചാനൽ" + }, + "removeFromWhitelist": { + "message": "വൈറ്റ്ലിസ്റ്റിൽ നിന്ന് ചാനൽ നീക്കംചെയ്യുക" + }, "voteOnTime": { "message": "ഒരു സെഗ്മെന്റിൽ വോട്ടുചെയ്യുക" }, - "here": { - "message": "ഇവിടെ" + "Submissions": { + "message": "സമർപ്പിക്കലുകൾ" + }, + "savedPeopleFrom": { + "message": "നിങ്ങൾ ആളുകളെ സംരക്ഷിച്ചു " + }, + "viewLeaderboard": { + "message": "ലീഡർബോർഡ്" + }, + "recordTimesDescription": { + "message": "സമർപ്പിക്കുക" + }, + "submissionEditHint": { + "message": "സമർപ്പിക്കുക ക്ലിക്കുചെയ്തതിനുശേഷം വിഭാഗം എഡിറ്റിംഗ് ദൃശ്യമാകും", + "description": "Appears in the popup to inform them that editing has been moved to the video player." + }, + "popupHint": { + "message": "സൂചന: ഓപ്ഷനുകളിൽ സമർപ്പിക്കുന്നതിന് നിങ്ങൾക്ക് കീബൈൻഡുകൾ സജ്ജമാക്കാൻ കഴിയും" }, "clearTimesButton": { "message": "ടൈംസ് മായ്ക്കുക" @@ -133,6 +152,9 @@ "publicStats": { "message": "നിങ്ങൾ എത്രമാത്രം സംഭാവന നൽകി എന്ന് കാണിക്കുന്നതിന് ഇത് പൊതു സ്ഥിതിവിവരക്കണക്ക് പേജിൽ ഉപയോഗിക്കുന്നു. അത് കാണുക" }, + "Username": { + "message": "ഉപയോക്തൃനാമം" + }, "setUsername": { "message": "ഉപയോക്തൃനാമം സജ്ജമാക്കുക" }, @@ -228,6 +250,12 @@ "0": { "message": "കണക്ഷൻ കാലഹരണപ്പെട്ടു. നിങ്ങളുടെ ഇന്റർനെറ്റ് കണക്ഷൻ പരിശോധിക്കുക. നിങ്ങളുടെ ഇൻറർനെറ്റ് പ്രവർത്തിക്കുന്നുണ്ടെങ്കിൽ, സെർവർ ഓവർലോഡ് അല്ലെങ്കിൽ ഡ. ൺ ആയിരിക്കാം." }, + "disableSkipping": { + "message": "ഒഴിവാക്കൽ പ്രാപ്തമാക്കി" + }, + "enableSkipping": { + "message": "ഒഴിവാക്കുന്നത് പ്രവർത്തനരഹിതമാക്കി" + }, "yourWork": { "message": "നിങ്ങളുടെ ജോലി", "description": "Used to describe the section that will show you the statistics from your submissions." @@ -265,6 +293,9 @@ "showTimeWithSkipsDescription": { "message": "സീക്ക്ബാറിന് താഴെയുള്ള നിലവിലെ സമയത്തിന് അടുത്തുള്ള ബ്രാക്കറ്റുകളിൽ ഈ സമയം ദൃശ്യമാകുന്നു. ഏത് സെഗ്മെന്റുകളുടെയും മൈനസ് മൊത്തം വീഡിയോ ദൈർഘ്യം ഇത് കാണിക്കുന്നു. \"സീക്ക്ബാറിൽ കാണിക്കുക\" എന്ന് മാത്രം അടയാളപ്പെടുത്തിയ സെഗ്മെന്റുകൾ ഇതിൽ ഉൾപ്പെടുന്നു." }, + "youHaveSkipped": { + "message": "നിങ്ങൾ ഒഴിവാക്കി " + }, "youHaveSaved": { "message": "നിങ്ങൾ സ്വയം രക്ഷിച്ചു " }, @@ -280,6 +311,12 @@ "hoursLower": { "message": "മണിക്കൂറുകൾ" }, + "youHaveSavedTime": { + "message": "നിങ്ങൾ ആളുകളെ സംരക്ഷിച്ചു" + }, + "youHaveSavedTimeEnd": { + "message": " അവരുടെ ജീവിതത്തിന്റെ" + }, "statusReminder": { "message": "സെർവർ നിലയ്ക്കായി status.sponsor.ajay.app പരിശോധിക്കുക." }, @@ -535,6 +572,10 @@ "chooseACategory": { "message": "ഒരു വിഭാഗം തിരഞ്ഞെടുക്കുക" }, + "enableThisCategoryFirst": { + "message": "\"{0}\" വിഭാഗത്തിൽ സെഗ്മെന്റുകൾ സമർപ്പിക്കുന്നതിന്, നിങ്ങൾ ഇത് ഓപ്ഷനുകളിൽ പ്രവർത്തനക്ഷമമാക്കണം. നിങ്ങളെ ഇപ്പോൾ ഓപ്ഷനുകളിലേക്ക് റീഡയറക്ട് ചെയ്യും.", + "description": "Used when submitting segments to only let them select a certain category if they have it enabled in the options." + }, "youMustSelectACategory": { "message": "നിങ്ങൾ സമർപ്പിക്കുന്ന എല്ലാ സെഗ്മെന്റുകൾക്കും നിങ്ങൾ ഒരു വിഭാഗം തിരഞ്ഞെടുക്കണം!" }, @@ -595,5 +636,8 @@ }, "unsubmittedWarningDescription": { "message": "അപ്ലോഡ് ചെയ്യാത്ത സെഗ്മെന്റുകളുള്ള ഒരു വീഡിയോ നിങ്ങൾ ഉപേക്ഷിക്കുമ്പോൾ ഒരു അറിയിപ്പ് അയയ്ക്കുക" + }, + "help": { + "message": "സഹായം" } } diff --git a/public/_locales/ms/messages.json b/public/_locales/ms/messages.json index b0c946f4..09d305b3 100644 --- a/public/_locales/ms/messages.json +++ b/public/_locales/ms/messages.json @@ -40,12 +40,6 @@ "Loading": { "message": "Memuat..." }, - "Mins": { - "message": "Minit" - }, - "Secs": { - "message": "Detik" - }, "Hide": { "message": "Jangan Tunjukkan" }, @@ -85,6 +79,9 @@ "sponsorEnd": { "message": "Segmen Berakhir Sekarang" }, + "noVideoID": { + "message": "Tiada video YouTube dijumpai.\nSekiranya ini tidak betul, muat semula tab." + }, "success": { "message": "Berjaya!" }, @@ -118,11 +115,33 @@ "submitCheck": { "message": "Adakah anda pasti mahu menghantarnya?" }, + "whitelistChannel": { + "message": "Saluran senarai putih" + }, + "removeFromWhitelist": { + "message": "Alih keluar saluran dari senarai putih" + }, "voteOnTime": { "message": "Undi Segmen" }, - "here": { - "message": "di sini" + "Submissions": { + "message": "Penyerahan" + }, + "savedPeopleFrom": { + "message": "Anda telah menyelamatkan orang dari " + }, + "viewLeaderboard": { + "message": "Papan pendahulu" + }, + "recordTimesDescription": { + "message": "Hantar" + }, + "submissionEditHint": { + "message": "Penyuntingan bahagian akan muncul setelah anda mengklik hantar", + "description": "Appears in the popup to inform them that editing has been moved to the video player." + }, + "popupHint": { + "message": "Petunjuk: Anda boleh menetapkan kunci untuk dihantar dalam pilihan" }, "clearTimesButton": { "message": "Jelas Masa" @@ -133,6 +152,9 @@ "publicStats": { "message": "Ini digunakan di halaman statistik awam untuk menunjukkan berapa banyak yang anda sumbangkan. Lihatlah" }, + "Username": { + "message": "Nama pengguna" + }, "setUsername": { "message": "Tetapkan Nama Pengguna" }, @@ -228,6 +250,12 @@ "0": { "message": "Masa sambungan telah tamat. Periksa sambungan internet anda. Sekiranya internet anda berfungsi, pelayan mungkin berlebihan atau tidak berfungsi." }, + "disableSkipping": { + "message": "Melangkau diaktifkan" + }, + "enableSkipping": { + "message": "Melangkau dilumpuhkan" + }, "yourWork": { "message": "Kerja awak", "description": "Used to describe the section that will show you the statistics from your submissions." @@ -265,6 +293,9 @@ "showTimeWithSkipsDescription": { "message": "Kali ini muncul dalam tanda kurung di sebelah waktu semasa di bawah bar carian. Ini menunjukkan jumlah durasi video tolak segmen mana pun. Ini merangkumi segmen yang ditandai sebagai \"Show In Seekbar\" sahaja." }, + "youHaveSkipped": { + "message": "Anda telah melangkau " + }, "youHaveSaved": { "message": "Anda telah menyelamatkan diri " }, @@ -280,6 +311,12 @@ "hoursLower": { "message": "jam" }, + "youHaveSavedTime": { + "message": "Anda telah menyelamatkan orang" + }, + "youHaveSavedTimeEnd": { + "message": " kehidupan mereka" + }, "statusReminder": { "message": "Periksa status.sponsor.ajay.app untuk status pelayan." }, @@ -535,6 +572,10 @@ "chooseACategory": { "message": "Pilih Kategori" }, + "enableThisCategoryFirst": { + "message": "Untuk menghantar segmen dengan kategori \"{0}\", anda mesti mengaktifkannya dalam pilihan. Anda akan diarahkan ke pilihan sekarang.", + "description": "Used when submitting segments to only let them select a certain category if they have it enabled in the options." + }, "youMustSelectACategory": { "message": "Anda mesti memilih kategori untuk semua segmen yang anda kirimkan!" }, @@ -595,5 +636,8 @@ }, "unsubmittedWarningDescription": { "message": "Kirim pemberitahuan ketika anda meninggalkan video dengan segmen yang tidak diunggah" + }, + "help": { + "message": "Bantuan" } } diff --git a/public/_locales/nl/messages.json b/public/_locales/nl/messages.json index 94821d0d..0e7bce2f 100644 --- a/public/_locales/nl/messages.json +++ b/public/_locales/nl/messages.json @@ -4,7 +4,7 @@ "description": "Name of the extension." }, "Description": { - "message": "Overslaan van sponsoring, abonneer-herinneringen en meer in YouTube-video's. Rapporteer sponsors in video's die u bekijkt om anderen tijd te besparen.", + "message": "Overslaan van sponsors, vragen om te abonneren en meer in YouTube-video's. Rapporteer sponsors in video's die u bekijkt om anderen tijd te besparen.", "description": "Description of the extension." }, "400": { @@ -14,7 +14,7 @@ "message": "U heeft te veel sponsortijdstippen ingediend voor deze video. Weet u zeker dat er zoveel zijn?" }, "409": { - "message": "Dit is al een keer ingediend" + "message": "Dit is al eerder ingediend" }, "channelWhitelisted": { "message": "Kanaal gewhitelist!" @@ -40,12 +40,6 @@ "Loading": { "message": "Laden..." }, - "Mins": { - "message": "Minuten" - }, - "Secs": { - "message": "Seconden" - }, "Hide": { "message": "Nooit weergeven" }, @@ -139,9 +133,6 @@ "viewLeaderboard": { "message": "Ranglijst" }, - "here": { - "message": "hier" - }, "recordTimesDescription": { "message": "Indienen" }, @@ -581,6 +572,10 @@ "chooseACategory": { "message": "Een categorie kiezen" }, + "enableThisCategoryFirst": { + "message": "Om segmenten met de categorie \"{0}\" in te dienen, moet u deze in de opties inschakelen. U wordt nu doorgestuurd naar de opties.", + "description": "Used when submitting segments to only let them select a certain category if they have it enabled in the options." + }, "youMustSelectACategory": { "message": "U moet een categorie selecteren voor alle segmenten die u indient!" }, diff --git a/public/_locales/pl/messages.json b/public/_locales/pl/messages.json index 3ca776e6..379ad1be 100644 --- a/public/_locales/pl/messages.json +++ b/public/_locales/pl/messages.json @@ -40,12 +40,6 @@ "Loading": { "message": "Ładowanie..." }, - "Mins": { - "message": "Minuty" - }, - "Secs": { - "message": "Sekundy" - }, "Hide": { "message": "Nie pokazuj więcej" }, @@ -65,10 +59,10 @@ "message": "Timer zatrzymany" }, "confirmMSG": { - "message": "Żeby zmienić lub usunąć wartości, kliknij na guzik informacji lub otwórz okienko rozszerzenia klikając w ikonę rozszerzenia znajdującą się w prawym górnym rogu." + "message": "Aby edytować lub usuwać poszczególne wartości, kliknij na przycisk informacyjny lub otwórz okienko rozszerzenia, klikając na ikonę rozszerzenia w prawym górnym rogu." }, "clearThis": { - "message": "Jesteś pewien, że chcesz to usunąć?\n\n" + "message": "Czy na pewno chcesz to usunąć?\n\n" }, "Unknown": { "message": "Wystąpił błąd podczas przesyłania twojego segmentu. Proszę spróbować ponownie później." @@ -86,7 +80,7 @@ "message": "Koniec segmentu" }, "noVideoID": { - "message": "Nie znaleziono filmu YouTube.\nJeśli jest to niepoprawne, odśwież stronę." + "message": "Nie znaleziono filmu YouTube.\nJeśli jest to nieprawidłowe, odśwież stronę." }, "success": { "message": "Sukces!" @@ -101,10 +95,10 @@ "message": "Błąd z połączeniem. Kod błędu: " }, "wantToSubmit": { - "message": "Czy chcesz zamieścić dla filmu o ID" + "message": "Czy chcesz coś zamieścić dla filmu o ID" }, "leftTimes": { - "message": "Wygląda na to, że zostawiłeś pewne niewysłane segmenty. Cofnij się do tamtej strony, by je zamieścić (nie zostały usunięte)." + "message": "Wygląda na to, że pozostawiono pewne niewysłane segmenty. Cofnij się do tamtej strony, aby je zamieścić (nie zostały usunięte)." }, "clearTimes": { "message": "Wyczyść segmenty" @@ -139,14 +133,11 @@ "viewLeaderboard": { "message": "Ranking" }, - "here": { - "message": "tutaj" - }, "recordTimesDescription": { "message": "Wyślij" }, "submissionEditHint": { - "message": "Edycja sekcji pojawi się po kliknięciu wyślij", + "message": "Edycja sekcji pojawi się po kliknięciu", "description": "Appears in the popup to inform them that editing has been moved to the video player." }, "popupHint": { @@ -366,7 +357,7 @@ "message": "Dodaj instancje Invidious" }, "addInvidiousInstanceDescription": { - "message": "Dodaj niestandardową instancje Invidious. W formie domeny. Na przykład: invidious.ajay.app" + "message": "Dodaj niestandardową instancję Invidious. Musi to być w formie samej domeny. Przykładowo: invidious.ajay.app" }, "add": { "message": "Dodaj" @@ -581,6 +572,10 @@ "chooseACategory": { "message": "Wybierz kategorię" }, + "enableThisCategoryFirst": { + "message": "Aby przesyłać segmenty o kategorii \"{0}\", musisz ją włączyć w opcjach. Zostaniesz przekierowany do ustawień.", + "description": "Used when submitting segments to only let them select a certain category if they have it enabled in the options." + }, "youMustSelectACategory": { "message": "Musisz wybrać kategorię dla każdego segmentu, który zamieszczasz!" }, diff --git a/public/_locales/pt_BR/messages.json b/public/_locales/pt_BR/messages.json index 56f1e7b5..c731a886 100644 --- a/public/_locales/pt_BR/messages.json +++ b/public/_locales/pt_BR/messages.json @@ -40,12 +40,6 @@ "Loading": { "message": "Carregando..." }, - "Mins": { - "message": "Minutos" - }, - "Secs": { - "message": "Segundos" - }, "Hide": { "message": "Nunca mostrar" }, @@ -85,6 +79,9 @@ "sponsorEnd": { "message": "O segmento termina agora" }, + "noVideoID": { + "message": "Nenhum vídeo do YouTube encontrado.\nSe isto estiver incorreto, atualize a aba." + }, "success": { "message": "Sucesso!" }, @@ -118,11 +115,33 @@ "submitCheck": { "message": "Você tem certeza que deseja enviar isto?" }, + "whitelistChannel": { + "message": "Canal na lista branca" + }, + "removeFromWhitelist": { + "message": "Remover canal da lista branca" + }, "voteOnTime": { "message": "Votar Em Um Segmento" }, - "here": { - "message": "aqui" + "Submissions": { + "message": "Envios" + }, + "savedPeopleFrom": { + "message": "Você salvou pessoas de " + }, + "viewLeaderboard": { + "message": "Classificação" + }, + "recordTimesDescription": { + "message": "Enviar" + }, + "submissionEditHint": { + "message": "A edição da seção aparecerá depois que você clicar em enviar", + "description": "Appears in the popup to inform them that editing has been moved to the video player." + }, + "popupHint": { + "message": "Dica: Você pode configurar os atalhos de tecla para enviar nas opções" }, "clearTimesButton": { "message": "Limpar Intervalos" @@ -133,6 +152,9 @@ "publicStats": { "message": "Isso é usado na página pública de estatísticas que mostra o quanto você já contríbuíu. Veja-a" }, + "Username": { + "message": "Usuário" + }, "setUsername": { "message": "Definir nome de usuário" }, @@ -228,6 +250,12 @@ "0": { "message": "Tempo limite de conexão excedida. Cheque a sua conexão de internet. Se a sua internet estiver funcionando, o servidor está sobrecarregado ou fora do ar." }, + "disableSkipping": { + "message": "Pular está habilitado" + }, + "enableSkipping": { + "message": "Pular está desabilitado" + }, "yourWork": { "message": "Suas submissões", "description": "Used to describe the section that will show you the statistics from your submissions." @@ -265,6 +293,9 @@ "showTimeWithSkipsDescription": { "message": "Esta vez aparece em parênteses ao lado da hora atual abaixo da barra de procura. Isto mostra a duração total do vídeo menos qualquer segmento. Isto inclui segmentos marcados como apenas \"Mostrar em Seekbar\"." }, + "youHaveSkipped": { + "message": "Você pulou " + }, "youHaveSaved": { "message": "Você poupou " }, @@ -280,6 +311,12 @@ "hoursLower": { "message": "horas" }, + "youHaveSavedTime": { + "message": "Você poupou das pessoas" + }, + "youHaveSavedTimeEnd": { + "message": " de suas vidas" + }, "statusReminder": { "message": "Verifique status.sponsor.ajay.app para o status do servidor." }, @@ -535,6 +572,10 @@ "chooseACategory": { "message": "Selecione uma Categoria" }, + "enableThisCategoryFirst": { + "message": "Para enviar os segmentos com a categoria de \"{0}\", você deve ativá-lo nas opções. Você será redirecionado para as opções agora.", + "description": "Used when submitting segments to only let them select a certain category if they have it enabled in the options." + }, "youMustSelectACategory": { "message": "Você deve selecionar uma categoria para todos os segmentos que você está enviando!" }, @@ -595,5 +636,8 @@ }, "unsubmittedWarningDescription": { "message": "Enviar uma notificação quando você sair de um vídeo com segmentos que não foram enviados" + }, + "help": { + "message": "Ajuda" } } diff --git a/public/_locales/pt_PT/messages.json b/public/_locales/pt_PT/messages.json index 5fe21149..9b8a507e 100644 --- a/public/_locales/pt_PT/messages.json +++ b/public/_locales/pt_PT/messages.json @@ -24,12 +24,6 @@ "Loading": { "message": "A carregar..." }, - "Mins": { - "message": "Minutos" - }, - "Secs": { - "message": "Segundos" - }, "Hide": { "message": "Nunca mostrar" }, @@ -69,9 +63,6 @@ "submitCheck": { "message": "Tem a certeza que pretende submeter?" }, - "here": { - "message": "aqui" - }, "clearTimesButton": { "message": "Limpar Intervalos" }, diff --git a/public/_locales/ro/messages.json b/public/_locales/ro/messages.json index ed4b270c..cc9095c9 100644 --- a/public/_locales/ro/messages.json +++ b/public/_locales/ro/messages.json @@ -40,12 +40,6 @@ "Loading": { "message": "Se încarcă..." }, - "Mins": { - "message": "Minute" - }, - "Secs": { - "message": "Secunde" - }, "Hide": { "message": "Nu mai afișa niciodată" }, @@ -121,9 +115,6 @@ "voteOnTime": { "message": "Votează pe un Segment" }, - "here": { - "message": "aici" - }, "clearTimesButton": { "message": "Șterge Timpii" }, diff --git a/public/_locales/ru/messages.json b/public/_locales/ru/messages.json index 0f901b3b..bebe4078 100644 --- a/public/_locales/ru/messages.json +++ b/public/_locales/ru/messages.json @@ -40,14 +40,8 @@ "Loading": { "message": "Загрузка..." }, - "Mins": { - "message": "мин" - }, - "Secs": { - "message": "сек" - }, "Hide": { - "message": "Никогда не показывать" + "message": "Больше не показывать" }, "hitGoBack": { "message": "Нажмите «Назад», чтобы вернуться обратно." @@ -121,6 +115,12 @@ "submitCheck": { "message": "Вы уверены, что хотите отправить эту информацию?" }, + "whitelistChannel": { + "message": "Добавить канал в белый список" + }, + "removeFromWhitelist": { + "message": "Удалить канал из белого списка" + }, "voteOnTime": { "message": "Проголосовать за сегмент" }, @@ -133,9 +133,6 @@ "viewLeaderboard": { "message": "Доска почёта" }, - "here": { - "message": "здесь" - }, "recordTimesDescription": { "message": "Отправить" }, @@ -204,7 +201,7 @@ "message": "Эта возможность отслеживает, какие сегменты Вы пропустили, чтобы помочь пользователям узнать, насколько их вклад помог другим, и, наряду с голосами, используется как метрика, чтобы убедиться, что спам не попадает в базу данных. Расширение отправляет сообщение на сервер каждый раз, когда Вы пропускаете сегмент. Надеемся, большая часть пользователей не поменяет эту настройку, так что у нас будет точная статистика просмотров. :)" }, "enableQueryByHashPrefix": { - "message": "Поиск по части хэша" + "message": "Запрос по префиксу хэша" }, "whatQueryByHashPrefix": { "message": "Вместо отправки на сервер ID видео, для получения сегментов будут использоваться первые 4 символа хэша ID. Сервер вернёт данные для всех видео с похожими хэшами." @@ -575,6 +572,10 @@ "chooseACategory": { "message": "Выберите категорию" }, + "enableThisCategoryFirst": { + "message": "Чтобы отправить сегменты категории \"{0}\", вы должны включить её в настройках. Сейчас вы будете туда перенаправлены.", + "description": "Used when submitting segments to only let them select a certain category if they have it enabled in the options." + }, "youMustSelectACategory": { "message": "Вы должны выбрать категорию для всех сегментов, которые вы отправляете!" }, diff --git a/public/_locales/sk/messages.json b/public/_locales/sk/messages.json index 5af1c183..1926dddd 100644 --- a/public/_locales/sk/messages.json +++ b/public/_locales/sk/messages.json @@ -24,12 +24,6 @@ "Loading": { "message": "Načítavanie..." }, - "Mins": { - "message": "Minúty" - }, - "Secs": { - "message": "Sekundy" - }, "Hide": { "message": "Nikdy nezobrazovať" }, @@ -72,9 +66,6 @@ "closePopup": { "message": "Zavrieť okno" }, - "here": { - "message": "tu" - }, "hideThis": { "message": "Skryť" }, diff --git a/public/_locales/sv/messages.json b/public/_locales/sv/messages.json index 4aedc8ed..e2d10d85 100644 --- a/public/_locales/sv/messages.json +++ b/public/_locales/sv/messages.json @@ -40,12 +40,6 @@ "Loading": { "message": "Laddar..." }, - "Mins": { - "message": "Minuter" - }, - "Secs": { - "message": "Sekunder" - }, "Hide": { "message": "Visa Aldrig" }, @@ -121,18 +115,24 @@ "submitCheck": { "message": "Är du säker på att du vill rapportera detta?" }, + "whitelistChannel": { + "message": "Vitlistkanal" + }, + "removeFromWhitelist": { + "message": "Ta bort kanal från vitlistan" + }, "voteOnTime": { "message": "Rösta på ett segment" }, + "Submissions": { + "message": "Inskickade" + }, "savedPeopleFrom": { "message": "Du har sparat andra från " }, "viewLeaderboard": { "message": "Topplista" }, - "here": { - "message": "här" - }, "recordTimesDescription": { "message": "Skicka" }, @@ -196,6 +196,12 @@ "enableQueryByHashPrefix": { "message": "Fråga efter hash-prefix" }, + "enableRefetchWhenNotFound": { + "message": "Uppdatera segment på nya videor" + }, + "whatRefetchWhenNotFound": { + "message": "Om videon är ny och inga segment hittades då kommer den att uppdatera med några minuter mellanrum medan du tittar på videon." + }, "showNotice": { "message": "Visa Notisen Igen" }, @@ -476,6 +482,9 @@ "category_interaction": { "message": "Interaktionspåminnelse (Prenumerera)" }, + "category_interaction_short": { + "message": "Interaktionspåminnelse" + }, "category_selfpromo": { "message": "Obetald/självbefodran" }, @@ -488,6 +497,9 @@ "category_music_offtopic_short": { "message": "Icke-musik" }, + "category_livestream_messages": { + "message": "Liveström: Donations-/meddelandeavläsningar" + }, "category_livestream_messages_short": { "message": "Läser meddelande" }, @@ -500,6 +512,9 @@ "showOverlay": { "message": "Visa Lager Ovanpå Spelare" }, + "colorFormatIncorrect": { + "message": "Din färg är felaktigt formaterad. Det ska vara en 3- eller 6-siffrig hex-kod med en siffra i början." + }, "previewColor": { "message": "Förhandsgranskningsfärg", "description": "Referring to submissions that have not been sent to the server yet." @@ -532,6 +547,10 @@ "chooseACategory": { "message": "Välj en kategori" }, + "enableThisCategoryFirst": { + "message": "För att skicka segment med kategorin \"{0}\" måste du först aktivera det i alternativen. Du kommer nu att bli omdirigerad till alternativen.", + "description": "Used when submitting segments to only let them select a certain category if they have it enabled in the options." + }, "youMustSelectACategory": { "message": "Du måste välja en kategori för alla segment du skickar in!" }, @@ -565,6 +584,9 @@ "incorrectCategory": { "message": "Fel kategori" }, + "nonMusicCategoryOnMusic": { + "message": "Den här videon kategoriseras som musik. Är du säker på att denna har en sponsor? Om detta faktiskt är ett \"icke-musiksegment\", öppna tilläggsalternativen och aktivera denna kategori. Då kan du skicka in detta segment som \"icke-musik\" i stället för sponsor. Läs riktlinjerna om något är oklart." + }, "multipleSegments": { "message": "Flera segment" }, diff --git a/public/_locales/ta/messages.json b/public/_locales/ta/messages.json index 704cf680..535478ea 100644 --- a/public/_locales/ta/messages.json +++ b/public/_locales/ta/messages.json @@ -40,12 +40,6 @@ "Loading": { "message": "ஏற்றுகிறது..." }, - "Mins": { - "message": "நிமிடம்" - }, - "Secs": { - "message": "நொடிகள்" - }, "Hide": { "message": "ஒருபோதும் அனுமதிக்காதே" }, @@ -85,6 +79,9 @@ "sponsorEnd": { "message": "பிரிவு இப்போது முடிகிறது" }, + "noVideoID": { + "message": "YouTube வீடியோ எதுவும் கிடைக்கவில்லை.\nஇது தவறாக இருந்தால், தாவலைப் புதுப்பிக்கவும்." + }, "success": { "message": "வெற்றி!" }, @@ -118,11 +115,33 @@ "submitCheck": { "message": "இதை நிச்சயமாக சமர்ப்பிக்க விரும்புகிறீர்களா?" }, + "whitelistChannel": { + "message": "அனுமதிப்பட்டியல் சேனல்" + }, + "removeFromWhitelist": { + "message": "அனுமதிப்பட்டியலில் இருந்து சேனலை அகற்று" + }, "voteOnTime": { "message": "ஒரு பிரிவில் வாக்களியுங்கள்" }, - "here": { - "message": "இங்கே" + "Submissions": { + "message": "சமர்ப்பிப்புகள்" + }, + "savedPeopleFrom": { + "message": "நீங்கள் மக்களை காப்பாற்றியுள்ளீர்கள் " + }, + "viewLeaderboard": { + "message": "லீடர்போர்டு" + }, + "recordTimesDescription": { + "message": "சமர்ப்பிக்கவும்" + }, + "submissionEditHint": { + "message": "நீங்கள் சமர்ப்பி என்பதைக் கிளிக் செய்த பிறகு பிரிவு எடிட்டிங் தோன்றும்", + "description": "Appears in the popup to inform them that editing has been moved to the video player." + }, + "popupHint": { + "message": "குறிப்பு: விருப்பங்களில் சமர்ப்பிக்க விசைப்பலகைகளை அமைக்கலாம்" }, "clearTimesButton": { "message": "நேரங்களை அழி" @@ -133,6 +152,9 @@ "publicStats": { "message": "நீங்கள் எவ்வளவு பங்களித்தீர்கள் என்பதைக் காட்ட இது பொது புள்ளிவிவரங்கள் பக்கத்தில் பயன்படுத்தப்படுகிறது. அதை பார்" }, + "Username": { + "message": "பயனர்பெயர்" + }, "setUsername": { "message": "பயனர்பெயரை அமைக்கவும்" }, @@ -228,6 +250,12 @@ "0": { "message": "இணைப்பு நேரம் முடிந்தது. உங்கள் இணைய இணைப்பைச் சரிபார்க்கவும். உங்கள் இணையம் இயங்கினால், சேவையகம் அதிக சுமை அல்லது கீழே இருக்கும்." }, + "disableSkipping": { + "message": "ஸ்கிப்பிங் இயக்கப்பட்டது" + }, + "enableSkipping": { + "message": "ஸ்கிப்பிங் முடக்கப்பட்டுள்ளது" + }, "yourWork": { "message": "உங்கள் வேலை", "description": "Used to describe the section that will show you the statistics from your submissions." @@ -265,6 +293,9 @@ "showTimeWithSkipsDescription": { "message": "இந்த நேரம் தற்போதைய நேரத்திற்கு அடுத்த அடைப்புக்குறிக்குள் தோன்றும். இது எந்தவொரு வீடியோவிற்கும் கழித்த மொத்த வீடியோ கால அளவைக் காட்டுகிறது. இதில் \"சீக்பாரில் காண்பி\" என்று மட்டுமே குறிக்கப்பட்ட பகுதிகள் அடங்கும்." }, + "youHaveSkipped": { + "message": "நீங்கள் தவிர்த்துவிட்டீர்கள் " + }, "youHaveSaved": { "message": "உங்களை நீங்களே காப்பாற்றிக் கொண்டீர்கள் " }, @@ -280,6 +311,12 @@ "hoursLower": { "message": "மணி" }, + "youHaveSavedTime": { + "message": "நீங்கள் மக்களைக் காப்பாற்றியுள்ளீர்கள்" + }, + "youHaveSavedTimeEnd": { + "message": " அவர்களின் வாழ்க்கையில்" + }, "statusReminder": { "message": "சேவையக நிலைக்கு status.sponsor.ajay.app ஐச் சரிபார்க்கவும்." }, @@ -535,6 +572,10 @@ "chooseACategory": { "message": "ஒரு வகையைத் தேர்வுசெய்க" }, + "enableThisCategoryFirst": { + "message": "\"{0}\" வகையுடன் பிரிவுகளைச் சமர்ப்பிக்க, நீங்கள் அதை விருப்பங்களில் இயக்க வேண்டும். நீங்கள் இப்போது விருப்பங்களுக்கு திருப்பி விடப்படுவீர்கள்.", + "description": "Used when submitting segments to only let them select a certain category if they have it enabled in the options." + }, "youMustSelectACategory": { "message": "நீங்கள் சமர்ப்பிக்கும் அனைத்து பிரிவுகளுக்கும் ஒரு வகையைத் தேர்ந்தெடுக்க வேண்டும்!" }, @@ -595,5 +636,8 @@ }, "unsubmittedWarningDescription": { "message": "பதிவேற்றப்படாத பிரிவுகளுடன் வீடியோவை விட்டு வெளியேறும்போது அறிவிப்பை அனுப்பவும்" + }, + "help": { + "message": "உதவி" } } diff --git a/public/_locales/te/messages.json b/public/_locales/te/messages.json index b7b49aa4..0ef6e887 100644 --- a/public/_locales/te/messages.json +++ b/public/_locales/te/messages.json @@ -40,12 +40,6 @@ "Loading": { "message": "లోడ్ అవుతుంది..." }, - "Mins": { - "message": "నిమిషాలు" - }, - "Secs": { - "message": "సెకన్లు" - }, "Hide": { "message": "నెవర్ షో" }, @@ -85,6 +79,9 @@ "sponsorEnd": { "message": "సెగ్మెంట్ ఇప్పుడు ముగుస్తుంది" }, + "noVideoID": { + "message": "YouTube వీడియో కనుగొనబడలేదు.\nఇది తప్పు అయితే, టాబ్ను రిఫ్రెష్ చేయండి." + }, "success": { "message": "విజయం!" }, @@ -118,11 +115,33 @@ "submitCheck": { "message": "మీరు దీన్ని ఖచ్చితంగా సమర్పించాలనుకుంటున్నారా?" }, + "whitelistChannel": { + "message": "వైట్లిస్ట్ ఛానెల్" + }, + "removeFromWhitelist": { + "message": "వైట్లిస్ట్ నుండి ఛానెల్ని తొలగించండి" + }, "voteOnTime": { "message": "ఒక విభాగంలో ఓటు వేయండి" }, - "here": { - "message": "ఇక్కడ" + "Submissions": { + "message": "సమర్పణలు" + }, + "savedPeopleFrom": { + "message": "మీరు ప్రజలను రక్షించారు " + }, + "viewLeaderboard": { + "message": "లీడర్బోర్డ్" + }, + "recordTimesDescription": { + "message": "సమర్పించండి" + }, + "submissionEditHint": { + "message": "మీరు సమర్పించు క్లిక్ చేసిన తర్వాత విభాగం సవరణ కనిపిస్తుంది", + "description": "Appears in the popup to inform them that editing has been moved to the video player." + }, + "popupHint": { + "message": "సూచన: మీరు ఎంపికలలో సమర్పించడానికి కీబైండ్లను సెటప్ చేయవచ్చు" }, "clearTimesButton": { "message": "టైమ్స్ క్లియర్" @@ -133,6 +152,9 @@ "publicStats": { "message": "మీరు ఎంత సహకరించారో చూపించడానికి ఇది పబ్లిక్ గణాంకాల పేజీలో ఉపయోగించబడుతుంది. ఇది చూడు" }, + "Username": { + "message": "వినియోగదారు పేరు" + }, "setUsername": { "message": "వినియోగదారు పేరును సెట్ చేయండి" }, @@ -228,6 +250,12 @@ "0": { "message": "అనుసంధాన సమయం సమాప్తం. మీ ఇంటర్నెట్ కనెక్షన్ను తనిఖీ చేయండి. మీ ఇంటర్నెట్ పనిచేస్తుంటే, సర్వర్ ఓవర్లోడ్ లేదా డౌన్ అయి ఉండవచ్చు." }, + "disableSkipping": { + "message": "దాటవేయడం ప్రారంభించబడింది" + }, + "enableSkipping": { + "message": "దాటవేయడం నిలిపివేయబడింది" + }, "yourWork": { "message": "నీ పని", "description": "Used to describe the section that will show you the statistics from your submissions." @@ -265,6 +293,9 @@ "showTimeWithSkipsDescription": { "message": "ఈ సమయం సీక్ బార్ క్రింద ప్రస్తుత సమయం పక్కన బ్రాకెట్లలో కనిపిస్తుంది. ఇది మొత్తం వీడియో వ్యవధి మైనస్ ఏదైనా విభాగాలను చూపుతుంది. ఇందులో \"సీక్బార్లో చూపించు\" అని మాత్రమే గుర్తించబడిన విభాగాలు ఉన్నాయి." }, + "youHaveSkipped": { + "message": "మీరు దాటవేశారు " + }, "youHaveSaved": { "message": "మీరు మీరే రక్షించుకున్నారు " }, @@ -280,6 +311,12 @@ "hoursLower": { "message": "గంటలు" }, + "youHaveSavedTime": { + "message": "మీరు ప్రజలను రక్షించారు" + }, + "youHaveSavedTimeEnd": { + "message": " వారి జీవితాల" + }, "statusReminder": { "message": "సర్వర్ స్థితి కోసం status.sponsor.ajay.app ని తనిఖీ చేయండి." }, @@ -535,6 +572,10 @@ "chooseACategory": { "message": "వర్గాన్ని ఎంచుకోండి" }, + "enableThisCategoryFirst": { + "message": "\"{0}\" వర్గంతో విభాగాలను సమర్పించడానికి, మీరు దీన్ని ఎంపికలలో ప్రారంభించాలి. మీరు ఇప్పుడు ఎంపికలకు మళ్ళించబడతారు.", + "description": "Used when submitting segments to only let them select a certain category if they have it enabled in the options." + }, "youMustSelectACategory": { "message": "మీరు సమర్పించే అన్ని విభాగాల కోసం మీరు తప్పనిసరిగా ఒక వర్గాన్ని ఎంచుకోవాలి!" }, @@ -595,5 +636,8 @@ }, "unsubmittedWarningDescription": { "message": "మీరు అప్లోడ్ చేయని విభాగాలతో వీడియోను వదిలివేసినప్పుడు నోటిఫికేషన్ పంపండి" + }, + "help": { + "message": "సహాయం" } } diff --git a/public/_locales/th/messages.json b/public/_locales/th/messages.json index d0bbb3a0..ad230bd8 100644 --- a/public/_locales/th/messages.json +++ b/public/_locales/th/messages.json @@ -40,12 +40,6 @@ "Loading": { "message": "กำลังโหลด..." }, - "Mins": { - "message": "นาที" - }, - "Secs": { - "message": "วินาที" - }, "Hide": { "message": "ไม่แสดงเสมอ" }, @@ -70,9 +64,6 @@ "sponsor404": { "message": "ไม่พบส่วนในวีดีโอนี้" }, - "here": { - "message": "ที่นี่" - }, "clearTimesButton": { "message": "ล้างเวลา" } diff --git a/public/_locales/tr/messages.json b/public/_locales/tr/messages.json index 3a65682a..5620332b 100644 --- a/public/_locales/tr/messages.json +++ b/public/_locales/tr/messages.json @@ -23,7 +23,7 @@ "message": "kısım" }, "Segments": { - "message": "kısımlar" + "message": "kısım" }, "upvoteButtonInfo": { "message": "Bu öneriye oy ver" @@ -40,12 +40,6 @@ "Loading": { "message": "Yükleniyor..." }, - "Mins": { - "message": "Dakika" - }, - "Secs": { - "message": "Saniye" - }, "Hide": { "message": "Asla Gösterme" }, @@ -74,7 +68,7 @@ "message": "Sponsor sürelerini yollarken bir sorun oluştur, lütfen tekrar deneyin." }, "sponsorFound": { - "message": "Bu videonun veri tabanımızda kısımları mevcut!" + "message": "Bu video için veritabanımızda kısımlar mevcut!" }, "sponsor404": { "message": "Kısımlar bulunamadı" @@ -85,6 +79,9 @@ "sponsorEnd": { "message": "Kısım Şimdi Bitiyor" }, + "noVideoID": { + "message": "YouTube videosu bulunamadı.\nHatalı olduğunu düşünüyorsanız sayfayı yenileyin." + }, "success": { "message": "Başarılı!" }, @@ -118,11 +115,33 @@ "submitCheck": { "message": "Bunu göndermek istediğinize emin misiniz?" }, + "whitelistChannel": { + "message": "Kanalı beyaz listeye ekle" + }, + "removeFromWhitelist": { + "message": "Kanalı beyaz listeden çıkar" + }, "voteOnTime": { "message": "Bir Kısmı Oyla" }, - "here": { - "message": "burada" + "Submissions": { + "message": "Gönderimleriniz" + }, + "savedPeopleFrom": { + "message": "İnsanları şu kadar kısımdan kurtardınız " + }, + "viewLeaderboard": { + "message": "Lider Tablosu" + }, + "recordTimesDescription": { + "message": "Gönder" + }, + "submissionEditHint": { + "message": "Kısım düzenlemesi Gönder'e tıkladığınızda görünecek", + "description": "Appears in the popup to inform them that editing has been moved to the video player." + }, + "popupHint": { + "message": "İpucu: Gönderim için ayarlardan kısayol tuşu atayabilirsiniz" }, "clearTimesButton": { "message": "Süreleri Temizle" @@ -133,6 +152,9 @@ "publicStats": { "message": "Bu, ne kadar katkı sağladığınızı göstermek için herkese açık istatistik sayfasında kullanılacaktır. Görün" }, + "Username": { + "message": "Kullanıcı adı" + }, "setUsername": { "message": "Kullanıcı Adı Belirle" }, @@ -228,6 +250,12 @@ "0": { "message": "Bağlantı zaman aşımına uğradı. İnternet bağlantınızı kontrol ediniz. Eğer internetiniz çalışıyor ise, büyük ihtimalle sunucuya erişilemiyor veya sunucuya aşırı yüklenilmiş olabilir." }, + "disableSkipping": { + "message": "Atlama etkin" + }, + "enableSkipping": { + "message": "Atlama devre dışı" + }, "yourWork": { "message": "Çalışmalarınız", "description": "Used to describe the section that will show you the statistics from your submissions." @@ -265,6 +293,9 @@ "showTimeWithSkipsDescription": { "message": "Bu süre, video ilerleme çubuğunun altındaki geçerli zamanın yanında parantez içinde görüntülenir. Bu, videodaki kısımların silinmiş toplam video süresini gösterir. Bu, yalnızca \"Video İlerleme Çubuğunda Göster\" olarak işaretlenen kısımları içerir." }, + "youHaveSkipped": { + "message": "Şu kadar kısım atladınız " + }, "youHaveSaved": { "message": "Şu kadar süre kazandınız " }, @@ -280,6 +311,12 @@ "hoursLower": { "message": "saat" }, + "youHaveSavedTime": { + "message": "İnsanların şu kadar vaktini kurtardınız:" + }, + "youHaveSavedTimeEnd": { + "message": " ömürden" + }, "statusReminder": { "message": "Sunucu durumu için status.sponsor.ajay.app kontrol edin." }, @@ -535,6 +572,10 @@ "chooseACategory": { "message": "Bir Kategori Seç" }, + "enableThisCategoryFirst": { + "message": "\"{0}\" kategorisinde bir kısım göndermek için onu ayarlardan açmalısınız. Ayarlara yönlendiriliyorsunuz.", + "description": "Used when submitting segments to only let them select a certain category if they have it enabled in the options." + }, "youMustSelectACategory": { "message": "Göndereceğin tüm kısımlar için bir kategori seçmelisin!" }, @@ -595,5 +636,8 @@ }, "unsubmittedWarningDescription": { "message": "Bir videodan kısımları göndermeden ayrılırsan bir bildirim gönderir" + }, + "help": { + "message": "Yardım" } } diff --git a/public/_locales/uk/messages.json b/public/_locales/uk/messages.json index dadeea83..dc736b4d 100644 --- a/public/_locales/uk/messages.json +++ b/public/_locales/uk/messages.json @@ -40,12 +40,6 @@ "Loading": { "message": "Завантаження..." }, - "Mins": { - "message": "хв" - }, - "Secs": { - "message": "сек" - }, "Hide": { "message": "Не відображати" }, @@ -85,6 +79,9 @@ "sponsorEnd": { "message": "Сегмент закінчується тут" }, + "noVideoID": { + "message": "Відео YouTube, не знайдено.\nЯкщо це не так, поновіть вкладку." + }, "success": { "message": "Успіх!" }, @@ -118,11 +115,33 @@ "submitCheck": { "message": "Ви впевнені, що хочете надіслати цю інформацію?" }, + "whitelistChannel": { + "message": "Додати канал в білий список" + }, + "removeFromWhitelist": { + "message": "Видалити канал з білого списку" + }, "voteOnTime": { "message": "Проголосувати за сегмент" }, - "here": { - "message": "тут" + "Submissions": { + "message": "Надіслано сегментів" + }, + "savedPeopleFrom": { + "message": "Ви допомогли людям пропустити " + }, + "viewLeaderboard": { + "message": "Дошка пошани" + }, + "recordTimesDescription": { + "message": "Надіслати" + }, + "submissionEditHint": { + "message": "Редагування сегментів з'явиться після натискання на кнопку \"Надіслати\"", + "description": "Appears in the popup to inform them that editing has been moved to the video player." + }, + "popupHint": { + "message": "Підказка: Ви можете налаштувати комбінації клавіш для надсилання в опціях" }, "clearTimesButton": { "message": "Очистити час" @@ -133,6 +152,9 @@ "publicStats": { "message": "Воно використовується на публічній сторінці статистики, щоб показати Ваш внесок. Її можна подивитися" }, + "Username": { + "message": "Ім'я користувача" + }, "setUsername": { "message": "Встановити ім'я користувача" }, @@ -228,6 +250,12 @@ "0": { "message": "Таймаут підключення. Перевірте ваше з'єднання з інтернетом. Якщо ваш інтернет працює, сервер, швидше за все, перевантажений або лежить." }, + "disableSkipping": { + "message": "Пропуск увімкнено" + }, + "enableSkipping": { + "message": "Пропуск вимкнено" + }, "yourWork": { "message": "Ваша робота", "description": "Used to describe the section that will show you the statistics from your submissions." @@ -265,6 +293,9 @@ "showTimeWithSkipsDescription": { "message": "Ця тривалість відображається в дужках поруч з фактичної під смугою прокрутки. Показує тривалість відео без сегментів. Включає сегменти, для яких вибрано \"Відображати в смузі прокрутки\"." }, + "youHaveSkipped": { + "message": "Ви пропустили " + }, "youHaveSaved": { "message": "Ви заощадили " }, @@ -280,6 +311,12 @@ "hoursLower": { "message": "годин" }, + "youHaveSavedTime": { + "message": "Ви заощадили людям" + }, + "youHaveSavedTimeEnd": { + "message": " їх життів" + }, "statusReminder": { "message": "Дивіться стан сервера на status.sponsor.ajay.app." }, @@ -535,6 +572,10 @@ "chooseACategory": { "message": "Оберіть категорію" }, + "enableThisCategoryFirst": { + "message": "Щоб надіслати сегменти категорії \"{0}\", ви повинні включити її в налаштуваннях. Зараз ви будете туди перенаправлені.", + "description": "Used when submitting segments to only let them select a certain category if they have it enabled in the options." + }, "youMustSelectACategory": { "message": "Ви повинні обрати категорію для всіх сегментів, які ви відправляєте!" }, @@ -595,5 +636,8 @@ }, "unsubmittedWarningDescription": { "message": "Надсилати повідомлення, коли ви йдете зі сторінки відео, сегменти до якого Ви не надіслали" + }, + "help": { + "message": "Допомога" } } diff --git a/public/_locales/vi/messages.json b/public/_locales/vi/messages.json index 28c7d6ba..7674d396 100644 --- a/public/_locales/vi/messages.json +++ b/public/_locales/vi/messages.json @@ -40,12 +40,6 @@ "Loading": { "message": "Đang tải..." }, - "Mins": { - "message": "Phút" - }, - "Secs": { - "message": "Giây" - }, "Hide": { "message": "Không hiển thị nữa" }, @@ -121,9 +115,6 @@ "voteOnTime": { "message": "Bầu chọn một đoạn quảng cáo" }, - "here": { - "message": "ở đây" - }, "clearTimesButton": { "message": "Xóa thời gian" }, diff --git a/public/_locales/zh_CN/messages.json b/public/_locales/zh_CN/messages.json index fbdcf951..ba786fa8 100644 --- a/public/_locales/zh_CN/messages.json +++ b/public/_locales/zh_CN/messages.json @@ -30,12 +30,6 @@ "Loading": { "message": "加载中..." }, - "Mins": { - "message": "分钟" - }, - "Secs": { - "message": "秒" - }, "Hide": { "message": "不再显示" }, @@ -81,9 +75,6 @@ "submitCheck": { "message": "您确定要提交它吗?" }, - "here": { - "message": "这里" - }, "clearTimesButton": { "message": "清除时间" }, diff --git a/public/_locales/zh_TW/messages.json b/public/_locales/zh_TW/messages.json index 7d679662..f2f9d982 100644 --- a/public/_locales/zh_TW/messages.json +++ b/public/_locales/zh_TW/messages.json @@ -40,12 +40,6 @@ "Loading": { "message": "載入中…" }, - "Mins": { - "message": "分" - }, - "Secs": { - "message": "秒" - }, "Hide": { "message": "永不顯示" }, @@ -85,6 +79,9 @@ "sponsorEnd": { "message": "片段現在結束" }, + "noVideoID": { + "message": "找不到 YouTube 影片。\n如果這是不正確的,重新整理此分頁" + }, "success": { "message": "成功!" }, @@ -118,11 +115,33 @@ "submitCheck": { "message": "您確定要提交這個嗎?" }, + "whitelistChannel": { + "message": "將頻道列入白名單" + }, + "removeFromWhitelist": { + "message": "將頻道從白名單移除" + }, "voteOnTime": { "message": "為分段投票" }, - "here": { - "message": "這裡" + "Submissions": { + "message": "提交數" + }, + "savedPeopleFrom": { + "message": "您已為大家節省 " + }, + "viewLeaderboard": { + "message": "排行榜" + }, + "recordTimesDescription": { + "message": "提交" + }, + "submissionEditHint": { + "message": "段落編輯會在您提交之後出現", + "description": "Appears in the popup to inform them that editing has been moved to the video player." + }, + "popupHint": { + "message": "小提醒:你可以為提交在設定裡綁定一個按鍵" }, "clearTimesButton": { "message": "清除時間" @@ -133,6 +152,9 @@ "publicStats": { "message": "這會被公開的統計頁面來展示您的貢獻。查看它" }, + "Username": { + "message": "使用者名稱" + }, "setUsername": { "message": "設定使用者名稱" }, @@ -228,6 +250,12 @@ "0": { "message": "連線超時。請檢查您的網路連線。若您的網路運作正常,則可能是伺服器超載或離線" }, + "disableSkipping": { + "message": "跳過已啟用" + }, + "enableSkipping": { + "message": "跳過已停用" + }, "yourWork": { "message": "您的成果", "description": "Used to describe the section that will show you the statistics from your submissions." @@ -241,6 +269,9 @@ "skip": { "message": "略過" }, + "skip_category": { + "message": "跳過 {0}?" + }, "skipped": { "message": "已跳過" }, @@ -262,6 +293,9 @@ "showTimeWithSkipsDescription": { "message": "這個時間會出現在現在時間旁邊的括號內。這會顯示總影片長度減掉任何片段後的結果。這只會包含標為\"在時間條中顯示\"的片段" }, + "youHaveSkipped": { + "message": "您已跳過 " + }, "youHaveSaved": { "message": "您為自己節省了 " }, @@ -277,6 +311,12 @@ "hoursLower": { "message": "小時" }, + "youHaveSavedTime": { + "message": "您已為大家節省" + }, + "youHaveSavedTimeEnd": { + "message": " 的生命。" + }, "statusReminder": { "message": "在 status.sponsor.ajay.app 檢查伺服器狀態" }, @@ -592,5 +632,8 @@ }, "unsubmittedWarningDescription": { "message": "在您離開含有未提交的片段的影片時寄送通知" + }, + "help": { + "message": "幫助" } } diff --git a/public/content.css b/public/content.css index 62420f2c..a9a6c6eb 100644 --- a/public/content.css +++ b/public/content.css @@ -11,11 +11,6 @@ z-index: 40; } -.sbHidden { - display: none !important; -} - - .previewbar { display: inline-block; height: 100%; @@ -23,12 +18,29 @@ /* Preview Bar page hacks */ -.sbTooltipTwoTitleThumbnailOffset { - bottom: -5px !important; +.ytp-tooltip:not(.sponsorCategoryTooltipVisible) .sponsorCategoryTooltip { + display: none !important; +} + +.ytp-tooltip.sponsorCategoryTooltipVisible { + transform: translateY(-1em) !important; +} + +.ytp-big-mode .ytp-tooltip.sponsorCategoryTooltipVisible { + transform: translateY(-2em) !important; +} + +#movie_player:not(.ytp-big-mode) .ytp-tooltip.sponsorCategoryTooltipVisible > .ytp-tooltip-text-wrapper { + transform: translateY(1em) !important; +} + +.ytp-big-mode .ytp-tooltip.sponsorCategoryTooltipVisible > .ytp-tooltip-text-wrapper { + transform: translateY(0.5em) !important; } -.sbTooltipOneTitleThumbnailOffset { - bottom: 10px !important; +.ytp-big-mode .ytp-tooltip.sponsorCategoryTooltipVisible > .ytp-tooltip-text-wrapper > .ytp-tooltip-text { + display: block !important; + transform: translateY(1em) !important; } /* */ diff --git a/public/options/options.html b/public/options/options.html index 04620a9e..5907c07b 100644 --- a/public/options/options.html +++ b/public/options/options.html @@ -83,6 +83,27 @@ <br/> <br/> + + <div option-type="keybind-change" sync-option="skipKeybind"> + <div class="option-button trigger-button"> + __MSG_setSkipShortcut__ + </div> + + <div class="option-hidden-section hidden"> + <br/> + + <div class="medium-description keybind-status"> + __MSG_keybindDescription__ + </div> + + <span class="medium-description bold keybind-status-key"> + + </span> + </div> + </div> + + <br/> + <br/> <div option-type="keybind-change" sync-option="startSponsorKeybind"> <div class="option-button trigger-button"> @@ -152,23 +173,6 @@ <br/> <br/> - <div option-type="toggle" sync-option="unsubmittedWarning"> - <label class="switch-container" label-name="__MSG_unsubmittedWarning__"> - <label class="switch"> - <input type="checkbox" checked> - <span class="slider round"></span> - </label> - </label> - - <br/> - <br/> - - <div class="small-description">__MSG_unsubmittedWarningDescription__</div> - </div> - - <br/> - <br/> - <div option-type="toggle" sync-option="forceChannelCheck"> <label class="switch-container" label-name="__MSG_forceChannelCheck__"> <label class="switch"> diff --git a/public/popup.css b/public/popup.css index dcad93b0..2aa096a6 100644 --- a/public/popup.css +++ b/public/popup.css @@ -10,6 +10,18 @@ display: none !important; } +@media only screen and (max-width: 600px) { + #sponsorBlockPopupBody { + width: 100%; + } +} + +#sponsorBlockPopupBody { + margin: auto; + width: 374px; + background: var(--sb-main-bg-color); +} + #sponsorblockPopup { color: var(--sb-main-fg-color); font-family: 'Source Sans Pro', sans-serif; diff --git a/public/popup.html b/public/popup.html index 33119900..1b472959 100644 --- a/public/popup.html +++ b/public/popup.html @@ -2,9 +2,11 @@ <title>__MSG_openPopup__</title> <link id="sponsorBlockPopupFont" rel="stylesheet" type="text/css" href="/libs/Source+Sans+Pro.css"> <link id="sponsorBlockStyleSheet" rel="stylesheet" type="text/css" href="popup.css"> + + <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> -<body style="margin: auto; width: 374px; background: var(--sb-main-bg-color);"> +<body id="sponsorBlockPopupBody"> <div id="sponsorblockPopup" class="sponsorBlockPageBody preload"> <div class="logoText bottomSpace"> <img src="icons/IconSponsorBlocker256px.png" height="40px" id="sponsorBlockPopupLogo"> diff --git a/src/background.ts b/src/background.ts index e9643667..ea011576 100644 --- a/src/background.ts +++ b/src/background.ts @@ -52,16 +52,6 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) { //this allows the callback to be called later return true; - case "alertPrevious": - if (Config.config.unsubmittedWarning) { - chrome.notifications.create("stillThere" + Math.random(), { - type: "basic", - title: chrome.i18n.getMessage("wantToSubmit") + " " + request.previousVideoID + "?", - message: chrome.i18n.getMessage("leftTimes"), - iconUrl: "./icons/LogoSponsorBlocker256px.png" - }); - } - break; case "registerContentScript": registerFirefoxContentScript(request); return false; diff --git a/src/components/NoticeComponent.tsx b/src/components/NoticeComponent.tsx index 9fff3be4..3867fa0a 100644 --- a/src/components/NoticeComponent.tsx +++ b/src/components/NoticeComponent.tsx @@ -8,6 +8,8 @@ export interface NoticeProps { timed?: boolean, idSuffix?: string, + videoSpeed?: () => number, + fadeIn?: boolean, // Callback for when this is closed @@ -19,7 +21,7 @@ export interface NoticeProps { export interface NoticeState { noticeTitle: string, - maxCountdownTime?: () => number, + maxCountdownTime: () => number, countdownTime: number, countdownText: string, @@ -28,6 +30,8 @@ export interface NoticeState { class NoticeComponent extends React.Component<NoticeProps, NoticeState> { countdownInterval: NodeJS.Timeout; + intervalVideoSpeed: number; + idSuffix: string; amountOfPreviousNotices: number; @@ -71,7 +75,9 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> { return ( <table id={"sponsorSkipNotice" + this.idSuffix} - className={"sponsorSkipObject sponsorSkipNotice" + (this.props.fadeIn ? " sponsorSkipNoticeFadeIn" : "")} + className={"sponsorSkipObject sponsorSkipNotice" + + (this.props.fadeIn ? " sponsorSkipNoticeFadeIn" : "") + + (this.amountOfPreviousNotices > 0 ? " secondSkipNotice" : "")} style={noticeStyle} onMouseEnter={() => this.timerMouseEnter()} onMouseLeave={() => this.timerMouseLeave()}> @@ -152,7 +158,11 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> { countdown(): void { if (!this.props.timed) return; - const countdownTime = this.state.countdownTime - 1; + const countdownTime = Math.min(this.state.countdownTime - 1, this.state.maxCountdownTime()); + + if (this.props.videoSpeed && this.intervalVideoSpeed != this.props.videoSpeed()) { + this.setupInterval(); + } if (countdownTime <= 0) { //remove this from setInterval @@ -175,12 +185,19 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> { countdownTime }) } + + removeFadeAnimation(): void { + //remove the fade out class if it exists + const notice = document.getElementById("sponsorSkipNotice" + this.idSuffix); + notice.classList.remove("sponsorSkipNoticeFadeOut"); + notice.style.animation = "none"; + } pauseCountdown(): void { if (!this.props.timed) return; //remove setInterval - clearInterval(this.countdownInterval); + if (this.countdownInterval) clearInterval(this.countdownInterval); this.countdownInterval = null; //reset countdown and inform the user @@ -189,10 +206,7 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> { countdownText: this.state.countdownManuallyPaused ? chrome.i18n.getMessage("manualPaused") : chrome.i18n.getMessage("paused") }); - //remove the fade out class if it exists - const notice = document.getElementById("sponsorSkipNotice" + this.idSuffix); - notice.classList.remove("sponsorSkipNoticeFadeOut"); - notice.style.animation = "none"; + this.removeFadeAnimation(); } startCountdown(): void { @@ -206,16 +220,29 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> { countdownText: null }); - this.countdownInterval = setInterval(this.countdown.bind(this), 1000); + this.setupInterval(); + } + + setupInterval(): void { + if (this.countdownInterval) clearInterval(this.countdownInterval); + + const intervalDuration = this.props.videoSpeed ? 1000 / this.props.videoSpeed() : 1000; + this.countdownInterval = setInterval(this.countdown.bind(this), intervalDuration); + + if (this.props.videoSpeed) this.intervalVideoSpeed = this.props.videoSpeed(); } resetCountdown(): void { if (!this.props.timed) return; + this.setupInterval(); + this.setState({ countdownTime: this.state.maxCountdownTime(), countdownText: null }); + + this.removeFadeAnimation(); } /** diff --git a/src/components/SkipNoticeComponent.tsx b/src/components/SkipNoticeComponent.tsx index cd7b8205..b4f31932 100644 --- a/src/components/SkipNoticeComponent.tsx +++ b/src/components/SkipNoticeComponent.tsx @@ -5,7 +5,7 @@ import { ContentContainer, SponsorHideType, SponsorTime } from "../types"; import NoticeComponent from "./NoticeComponent"; import NoticeTextSelectionComponent from "./NoticeTextSectionComponent"; -enum SkipNoticeAction { +export enum SkipNoticeAction { None, Upvote, Downvote, @@ -24,23 +24,23 @@ export interface SkipNoticeProps { } export interface SkipNoticeState { - noticeTitle: string; + noticeTitle?: string; - messages: string[]; - messageOnClick: (event: React.MouseEvent) => unknown; + messages?: string[]; + messageOnClick?: (event: React.MouseEvent) => unknown; - countdownTime: number; - maxCountdownTime: () => number; - countdownText: string; + countdownTime?: number; + maxCountdownTime?: () => number; + countdownText?: string; - unskipText: string; - unskipCallback: (index: number) => void; + unskipText?: string; + unskipCallback?: (index: number) => void; - downvoting: boolean; - choosingCategory: boolean; - thanksForVotingText: string; //null until the voting buttons should be hidden + downvoting?: boolean; + choosingCategory?: boolean; + thanksForVotingText?: string; //null until the voting buttons should be hidden - actionState: SkipNoticeAction; + actionState?: SkipNoticeAction; } class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeState> { @@ -91,13 +91,6 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta } this.idSuffix += this.amountOfPreviousNotices; - if (this.amountOfPreviousNotices > 0) { - //another notice exists - - const previousNotice = document.getElementsByClassName("sponsorSkipNotice")[0]; - previousNotice.classList.add("secondSkipNotice") - } - // Setup state this.state = { noticeTitle, @@ -148,6 +141,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta fadeIn={true} timed={true} maxCountdownTime={this.state.maxCountdownTime} + videoSpeed={() => this.contentContainer().v?.playbackRate} ref={this.noticeRef} closeListener={() => this.closeListener()}> @@ -203,7 +197,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta style={{marginLeft: "4px"}} onClick={() => this.prepAction(SkipNoticeAction.Unskip)}> - {this.state.unskipText} + {this.state.unskipText + " (" + Config.config.skipKeybind + ")"} </button> </td> @@ -444,10 +438,9 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta } getUnskippedModeInfo(index: number, buttonText: string): SkipNoticeState { - const self = this; - const maxCountdownTime = function() { - const sponsorTime = self.segments[index]; - const duration = Math.round((sponsorTime.segment[1] - self.contentContainer().v.currentTime) * (1 / self.contentContainer().v.playbackRate)); + const maxCountdownTime = () => { + const sponsorTime = this.segments[index]; + const duration = Math.round((sponsorTime.segment[1] - this.contentContainer().v.currentTime) * (1 / this.contentContainer().v.playbackRate)); return Math.max(duration, 4); }; @@ -464,21 +457,23 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta reskip(index: number): void { this.contentContainer().reskipSponsorTime(this.segments[index]); - //reset countdown - this.setState({ + const newState: SkipNoticeState = { unskipText: chrome.i18n.getMessage("unskip"), unskipCallback: this.unskip.bind(this), maxCountdownTime: () => 4, countdownTime: 4 - }); + }; // See if the title should be changed if (!this.autoSkip) { - this.setState({ - noticeTitle: chrome.i18n.getMessage("noticeTitle") - }); - } + newState.noticeTitle = chrome.i18n.getMessage("noticeTitle"); + } + + //reset countdown + this.setState(newState, () => { + this.noticeRef.current.resetCountdown(); + }); } afterVote(segment: SponsorTime, type: number, category: string): void { diff --git a/src/components/SponsorTimeEditComponent.tsx b/src/components/SponsorTimeEditComponent.tsx index 89b5d48e..e00813ca 100644 --- a/src/components/SponsorTimeEditComponent.tsx +++ b/src/components/SponsorTimeEditComponent.tsx @@ -23,6 +23,8 @@ export interface SponsorTimeEditState { sponsorTimeEdits: [string, string]; } +const DEFAULT_CATEGORY = "chooseACategory"; + class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, SponsorTimeEditState> { idSuffix: string; @@ -217,27 +219,17 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo getCategoryOptions(): React.ReactElement[] { const elements = [( - <option value={"chooseACategory"} - key={"chooseACategory"}> - {chrome.i18n.getMessage("chooseACategory")} + <option value={DEFAULT_CATEGORY} + key={DEFAULT_CATEGORY}> + {chrome.i18n.getMessage(DEFAULT_CATEGORY)} </option> )]; - for (const category of Config.config.categorySelections) { - elements.push( - <option value={category.name} - key={category.name}> - {chrome.i18n.getMessage("category_" + category.name)} - </option> - ); - } - - if (elements.length < CompileConfig.categoryList.length) { - // Add show more button + for (const category of CompileConfig.categoryList) { elements.push( - <option value={"moreCategories"} - key={"moreCategories"}> - {chrome.i18n.getMessage("moreCategories")} + <option value={category} + key={category}> + {chrome.i18n.getMessage("category_" + category)} </option> ); } @@ -247,15 +239,20 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo categorySelectionChange(event: React.ChangeEvent<HTMLSelectElement>): void { // See if show more categories was pressed - if (event.target.value === "moreCategories") { - // Open options page - chrome.runtime.sendMessage({"message": "openConfig"}); - - // Reset option to previous - event.target.value = this.props.contentContainer().sponsorTimesSubmitting[this.props.index].category; + if (!Config.config.categorySelections.some((category) => category.name === event.target.value)) { + const chosenCategory = event.target.value; + event.target.value = DEFAULT_CATEGORY; + + // Alert that they have to enable this category first + if (confirm(chrome.i18n.getMessage("enableThisCategoryFirst") + .replace("{0}", chrome.i18n.getMessage("category_" + chosenCategory)))) { + // Open options page + chrome.runtime.sendMessage({"message": "openConfig"}); + } + return; } - + this.saveEditTimes(); } diff --git a/src/config.ts b/src/config.ts index 2a40dbf6..5723db12 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,5 +1,5 @@ import * as CompileConfig from "../config.json"; -import { CategorySelection, CategorySkipOption, PreviewBarOption, SponsorTime, StorageChangesObject } from "./types"; +import { CategorySelection, CategorySkipOption, PreviewBarOption, SponsorTime, StorageChangesObject, UnEncodedSegmentTimes as UnencodedSegmentTimes } from "./types"; import Utils from "./utils"; const utils = new Utils(); @@ -10,6 +10,7 @@ interface SBConfig { defaultCategory: string, whitelistedChannels: string[], forceChannelCheck: boolean, + skipKeybind: string, startSponsorKeybind: string, submitKeybind: string, minutesSaved: number, @@ -17,7 +18,6 @@ interface SBConfig { sponsorTimesContributed: number, submissionCountSinceCategories: number, // New count used to show the "Read The Guidelines!!" message showTimeWithSkips: boolean, - unsubmittedWarning: boolean, disableSkipping: boolean, trackViewCount: boolean, dontShowNotice: boolean, @@ -65,7 +65,7 @@ export interface SBObject { config: SBConfig; // Functions - encodeStoredItem<T>(data: T): T | Array<any>; + encodeStoredItem<T>(data: T): T | UnencodedSegmentTimes; convertJSON(): void; } @@ -143,6 +143,7 @@ const Config: SBObject = { defaultCategory: "chooseACategory", whitelistedChannels: [], forceChannelCheck: false, + skipKeybind: "Enter", startSponsorKeybind: ";", submitKeybind: "'", minutesSaved: 0, @@ -150,7 +151,6 @@ const Config: SBObject = { sponsorTimesContributed: 0, submissionCountSinceCategories: 0, showTimeWithSkips: true, - unsubmittedWarning: true, disableSkipping: false, trackViewCount: true, dontShowNotice: false, @@ -247,10 +247,10 @@ const Config: SBObject = { * * @param data */ -function encodeStoredItem<T>(data: T): T | Array<any> { +function encodeStoredItem<T>(data: T): T | UnencodedSegmentTimes { // if data is SBMap convert to json for storing if(!(data instanceof SBMap)) return data; - return Array.from(data.entries()); + return Array.from(data.entries()).filter((element) => element[1] === []); // Remove empty entries } /** @@ -265,7 +265,7 @@ function decodeStoredItem<T>(id: string, data: T): T | SBMap<string, SponsorTime if (Config.defaults[id] instanceof SBMap) { try { if (!Array.isArray(data)) return data; - return new SBMap(id, data); + return new SBMap(id, data as UnencodedSegmentTimes); } catch(e) { console.error("Failed to parse SBMap: " + id); } @@ -395,7 +395,7 @@ function migrateOldFormats(config: SBConfig) { // Migrate old "sponsorTimes" if (config["sponsorTimes"]) { - let jsonData: any = config["sponsorTimes"]; + let jsonData: unknown = config["sponsorTimes"]; // Check if data is stored in the old format for SBMap (a JSON string) if (typeof jsonData === "string") { diff --git a/src/content.ts b/src/content.ts index be96ef29..9e9332e6 100644 --- a/src/content.ts +++ b/src/content.ts @@ -8,21 +8,23 @@ const utils = new Utils(); import runThePopup from "./popup"; -import PreviewBar from "./js-components/previewBar"; +import PreviewBar, {PreviewBarSegment} from "./js-components/previewBar"; import SkipNotice from "./render/SkipNotice"; import SkipNoticeComponent from "./components/SkipNoticeComponent"; import SubmissionNotice from "./render/SubmissionNotice"; +import { Message, MessageResponse } from "./messageTypes"; // Hack to get the CSS loaded on permission-based sites (Invidious) utils.wait(() => Config.config !== null, 5000, 10).then(addCSS); //was sponsor data found when doing SponsorsLookup let sponsorDataFound = false; -let previousVideoID: VideoID = null; //the actual sponsorTimes if loaded and UUIDs associated with them let sponsorTimes: SponsorTime[] = null; //what video id are these sponsors for let sponsorVideoID: VideoID = null; +// List of open skip notices +const skipNotices: SkipNotice[] = []; // JSON video info let videoInfo: VideoInfo = null; @@ -35,11 +37,13 @@ let channelID: string; let currentSkipSchedule: NodeJS.Timeout = null; let seekListenerSetUp = false -/** @type {Array[boolean]} Has the sponsor been skipped */ +/** Has the sponsor been skipped */ let sponsorSkipped: boolean[] = []; //the video let video: HTMLVideoElement; +// List of videos that have had event listeners added to them +const videoRootsWithEventListeners: HTMLDivElement[] = []; let onInvidious; let onMobileYouTube; @@ -99,6 +103,7 @@ const skipNoticeContentContainer: ContentContainer = () => ({ unskipSponsorTime, sponsorTimes, sponsorTimesSubmitting, + skipNotices, v: video, sponsorVideoID, reskipSponsorTime, @@ -115,7 +120,7 @@ const skipNoticeContentContainer: ContentContainer = () => ({ //get messages from the background script and the popup chrome.runtime.onMessage.addListener(messageListener); -function messageListener(request: any, sender: unknown, sendResponse: (response: any) => void): void { +function messageListener(request: Message, sender: unknown, sendResponse: (response: MessageResponse) => void): void { //messages from popup script switch(request.message){ case "update": @@ -172,7 +177,6 @@ function messageListener(request: any, sender: unknown, sendResponse: (response: break; case "submitTimes": submitSponsorTimes(); - break; } } @@ -198,28 +202,6 @@ if (!Config.configListeners.includes(contentConfigUpdateListener)) { Config.configListeners.push(contentConfigUpdateListener); } -//check for hotkey pressed -document.onkeydown = function(e: KeyboardEvent){ - const key = e.key; - - const video = document.getElementById("movie_player"); - - const startSponsorKey = Config.config.startSponsorKeybind; - - const submitKey = Config.config.submitKeybind; - - //is the video in focus, otherwise they could be typing a comment - if (document.activeElement === video) { - if(key == startSponsorKey){ - //semicolon - startSponsorClicked(); - } else if (key == submitKey) { - //single quote - submitSponsorTimes(); - } - } -} - function resetValues() { lastCheckTime = 0; lastCheckVideoTime = -1; @@ -234,7 +216,7 @@ function resetValues() { //empty the preview bar if (previewBar !== null) { - previewBar.set([], [], 0); + previewBar.clear(); } //reset sponsor data found check @@ -293,36 +275,23 @@ async function videoIDChange(id) { if (onMobileYouTube) { // Mobile YouTube workaround const observer = new MutationObserver(handleMobileControlsMutations); - - observer.observe(document.getElementById("player-control-container"), { - attributes: true, - childList: true, - subtree: true - }); + let controlsContainer = null; + + utils.wait(() => { + controlsContainer = document.getElementById("player-control-container") + return controlsContainer !== null + }).then(() => { + observer.observe(document.getElementById("player-control-container"), { + attributes: true, + childList: true, + subtree: true + }); + }).catch(); } else { utils.wait(getControls).then(createPreviewBar); } } - //warn them if they had unsubmitted times - if (previousVideoID != null) { - //get the sponsor times from storage - const sponsorTimes = Config.config.segmentTimes.get(previousVideoID); - if (sponsorTimes != undefined && sponsorTimes.length > 0 && new URL(document.URL).host !== "music.youtube.com") { - //warn them that they have unsubmitted sponsor times - chrome.runtime.sendMessage({ - message: "alertPrevious", - previousVideoID: previousVideoID - }); - } - - //set the previous video id to the currentID - previousVideoID = id; - } else { - //set the previous id now, don't wait for chrome.storage.get - previousVideoID = id; - } - //close popup closeInfoMenu(); @@ -352,23 +321,13 @@ async function videoIDChange(id) { } function handleMobileControlsMutations(): void { - const mobileYouTubeSelector = ".progress-bar-background"; - - updateVisibilityOfPlayerControlsButton().then((createdButtons) => { - if (createdButtons) { - if (sponsorTimesSubmitting != null && sponsorTimesSubmitting.length > 0 && sponsorTimesSubmitting[sponsorTimesSubmitting.length - 1].segment.length >= 2) { - changeStartSponsorButton(true, true); - } else if (sponsorTimesSubmitting != null && sponsorTimesSubmitting.length > 0 && sponsorTimesSubmitting[sponsorTimesSubmitting.length - 1].segment.length < 2) { - changeStartSponsorButton(false, true); - } else { - changeStartSponsorButton(true, false); - } - } - }); - if (previewBar !== null) { if (document.body.contains(previewBar.container)) { - updatePreviewBarPositionMobile(document.getElementsByClassName(mobileYouTubeSelector)[0] as HTMLElement); + const progressBarBackground = document.querySelector<HTMLElement>(".progress-bar-background"); + + if (progressBarBackground !== null) { + updatePreviewBarPositionMobile(progressBarBackground); + } return; } else { @@ -399,11 +358,11 @@ function createPreviewBar(): void { ]; for (const selector of progressElementSelectors) { - const el = document.querySelectorAll(selector); + const el = document.querySelector<HTMLElement>(selector); + + if (el) { + previewBar = new PreviewBar(el, onMobileYouTube, onInvidious); - if (el && el.length && el[0]) { - previewBar = new PreviewBar(el[0] as HTMLElement, onMobileYouTube, onInvidious); - updatePreviewBar(); break; @@ -536,6 +495,8 @@ async function sponsorsLookup(id: string) { return; } + addHotkeyListener(); + if (!durationListenerSetUp) { durationListenerSetUp = true; @@ -752,18 +713,18 @@ function startSkipScheduleCheckingForStartSponsors() { /** * Get the video info for the current tab from YouTube */ -function getVideoInfo() { - sendRequestToCustomServer('GET', "https://www.youtube.com/get_video_info?video_id=" + sponsorVideoID, function(xmlhttp) { - if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { - const decodedData = decodeURIComponent(xmlhttp.responseText).match(/player_response=([^&]*)/)[1]; - if (!decodedData) { - console.error("[SB] Failed at getting video info from YouTube."); - return; - } +async function getVideoInfo(): Promise<void> { + const result = await utils.asyncRequestToCustomServer("GET", "https://www.youtube.com/get_video_info?video_id=" + sponsorVideoID); - videoInfo = JSON.parse(decodedData); + if (result.ok) { + const decodedData = decodeURIComponent(result.responseText).match(/player_response=([^&]*)/)[1]; + if (!decodedData) { + console.error("[SB] Failed at getting video info from YouTube."); + return; } - }); + + videoInfo = JSON.parse(decodedData); + } } function getYouTubeVideoID(url: string) { @@ -818,39 +779,46 @@ function updatePreviewBarPositionMobile(parent: HTMLElement) { } function updatePreviewBar(): void { - if(isAdPlaying) { - previewBar.set([], [], 0); + if (previewBar === null) return; + + if (isAdPlaying) { + previewBar.clear(); return; } - if (previewBar === null || video === null) return; + if (video === null) return; - let localSponsorTimes = sponsorTimes; - if (localSponsorTimes == null) localSponsorTimes = []; + const previewBarSegments: PreviewBarSegment[] = []; - const allSponsorTimes = localSponsorTimes.concat(sponsorTimesSubmitting); - - //create an array of the sponsor types - const types = []; - for (let i = 0; i < localSponsorTimes.length; i++) { - if (localSponsorTimes[i].hidden === SponsorHideType.Visible) { - types.push(localSponsorTimes[i].category); - } else { - // Don't show this sponsor - types.push(null); - } - } - for (let i = 0; i < sponsorTimesSubmitting.length; i++) { - types.push("preview-" + sponsorTimesSubmitting[i].category); + if (sponsorTimes) { + sponsorTimes.forEach((segment) => { + if (segment.hidden !== SponsorHideType.Visible) return; + + previewBarSegments.push({ + segment: segment.segment as [number, number], + category: segment.category, + preview: false, + }); + }); } - previewBar.set(utils.getSegmentsFromSponsorTimes(allSponsorTimes), types, video.duration) + sponsorTimesSubmitting.forEach((segment) => { + previewBarSegments.push({ + segment: segment.segment as [number, number], + category: segment.category, + preview: true, + }); + }); + + previewBar.set(previewBarSegments, video.duration) if (Config.config.showTimeWithSkips) { - showTimeWithoutSkips(allSponsorTimes); + const skippedDuration = utils.getTimestampsDuration(previewBarSegments.map(({segment}) => segment)); + + showTimeWithoutSkips(skippedDuration); } - //update last video id + // Update last video id lastPreviewBarUpdate = sponsorVideoID; } @@ -1013,7 +981,7 @@ function skipToTime(v: HTMLVideoElement, skipTime: number[], skippingSegments: S if (openNotice) { //send out the message saying that a sponsor message was skipped if (!Config.config.dontShowNotice || !autoSkip) { - new SkipNotice(skippingSegments, autoSkip, skipNoticeContentContainer); + skipNotices.push(new SkipNotice(skippingSegments, autoSkip, skipNoticeContentContainer)); } } @@ -1052,6 +1020,8 @@ function unskipSponsorTime(segment: SponsorTime) { function reskipSponsorTime(segment: SponsorTime) { video.currentTime = segment.segment[1]; + + startSponsorSchedule(true, segment.segment[1], false); } function createButton(baseID, title, callback, imageName, isDraggable=false): boolean { @@ -1131,6 +1101,7 @@ async function updateVisibilityOfPlayerControlsButton(): Promise<boolean> { if (!sponsorVideoID) return false; const createdButtons = await createButtons(); + if (!createdButtons) return; if (Config.config.hideVideoPlayerControls || onInvidious) { document.getElementById("startSponsorButton").style.display = "none"; @@ -1181,6 +1152,7 @@ function startSponsorClicked() { if (sponsorTimesSubmitting.length > 0 && sponsorTimesSubmitting[sponsorTimesSubmitting.length - 1].segment.length < 2) { //it is an end time sponsorTimesSubmitting[sponsorTimesSubmitting.length - 1].segment[1] = getRealCurrentTime(); + sponsorTimesSubmitting[sponsorTimesSubmitting.length - 1].segment.sort((a, b) => a > b ? 1 : (a < b ? -1 : 0)); } else { //it is a start time sponsorTimesSubmitting.push({ @@ -1222,8 +1194,8 @@ function updateSponsorTimesSubmitting(getFromConfig = true) { } } -async function changeStartSponsorButton(showStartSponsor, uploadButtonVisible) { - if(!sponsorVideoID) return false; +async function changeStartSponsorButton(showStartSponsor: boolean, uploadButtonVisible: boolean): Promise<boolean> { + if(!sponsorVideoID || onMobileYouTube) return false; //if it isn't visible, there is no data const shouldHide = (uploadButtonVisible && !(Config.config.hideDeleteButtonPlayerControls || onInvidious)) ? "unset" : "none" @@ -1423,7 +1395,7 @@ function dontShowNoticeAgain() { closeAllSkipNotices(); } -function sponsorMessageStarted(callback) { +function sponsorMessageStarted(callback: (response: MessageResponse) => void) { video = document.querySelector('video'); //send back current time @@ -1555,6 +1527,41 @@ function getSegmentsMessage(sponsorTimes: SponsorTime[]): string { return sponsorTimesMessage; } +function addHotkeyListener(): boolean { + const videoRoot = document.getElementById("movie_player") as HTMLDivElement; + + if (!videoRootsWithEventListeners.includes(videoRoot)) { + videoRoot.addEventListener("keydown", hotkeyListener); + videoRootsWithEventListeners.push(videoRoot); + return true; + } + + return false; +} + +function hotkeyListener(e: KeyboardEvent): void { + const key = e.key; + + const skipKey = Config.config.skipKeybind; + const startSponsorKey = Config.config.startSponsorKeybind; + const submitKey = Config.config.submitKeybind; + + switch (key) { + case skipKey: + if (skipNotices.length > 0) { + const latestSkipNotice = skipNotices[skipNotices.length - 1]; + latestSkipNotice.toggleSkip.call(latestSkipNotice); + } + break; + case startSponsorKey: + startSponsorClicked(); + break; + case submitKey: + submitSponsorTimes(); + break; + } +} + /** * Is this an unlisted YouTube video. * Assumes that the the privacy info is available. @@ -1616,37 +1623,28 @@ function updateAdFlag(): void { } } -function showTimeWithoutSkips(allSponsorTimes): void { +function showTimeWithoutSkips(skippedDuration: number): void { if (onMobileYouTube || onInvidious) return; - let skipDuration = 0; - - // Calculate skipDuration based from the segments in the preview bar - for (let i = 0; i < allSponsorTimes.length; i++) { - // If an end time exists - if (allSponsorTimes[i].segment[1]) { - skipDuration += allSponsorTimes[i].segment[1] - allSponsorTimes[i].segment[0]; - } - - } - - // YouTube player time display - const display = document.getElementsByClassName("ytp-time-display notranslate")[0]; - if (!display) return; - - const formatedTime = utils.getFormattedTime(video.duration - skipDuration); - - const durationID = "sponsorBlockDurationAfterSkips"; + if (isNaN(skippedDuration) || skippedDuration < 0) { + skippedDuration = 0; + } + + // YouTube player time display + const display = document.querySelector(".ytp-time-display.notranslate"); + if (!display) return; + + const durationID = "sponsorBlockDurationAfterSkips"; let duration = document.getElementById(durationID); - // Create span if needed - if(duration === null) { - duration = document.createElement('span'); + // Create span if needed + if (duration === null) { + duration = document.createElement('span'); duration.id = durationID; duration.classList.add("ytp-time-duration"); - display.appendChild(duration); - } - - duration.innerText = (skipDuration <= 0 || isNaN(skipDuration) || formatedTime.includes("NaN")) ? "" : " ("+formatedTime+")"; + display.appendChild(duration); + } + + duration.innerText = skippedDuration <= 0 ? "" : " (" + utils.getFormattedTime(video.duration - skippedDuration) + ")"; } diff --git a/src/js-components/previewBar.ts b/src/js-components/previewBar.ts index a1f4e2c3..7f011f0d 100644 --- a/src/js-components/previewBar.ts +++ b/src/js-components/previewBar.ts @@ -1,6 +1,6 @@ /* - This is based on code from VideoSegments. - https://github.com/videosegments/videosegments/commits/f1e111bdfe231947800c6efdd51f62a4e7fef4d4/segmentsbar/segmentsbar.js +This is based on code from VideoSegments. +https://github.com/videosegments/videosegments/commits/f1e111bdfe231947800c6efdd51f62a4e7fef4d4/segmentsbar/segmentsbar.js */ 'use strict'; @@ -9,179 +9,218 @@ import Config from "../config"; import Utils from "../utils"; const utils = new Utils(); +const TOOLTIP_VISIBLE_CLASS = 'sponsorCategoryTooltipVisible'; + +export interface PreviewBarSegment { + segment: [number, number]; + category: string; + preview: boolean; +} + class PreviewBar { - container: HTMLUListElement; - parent: HTMLElement; - onMobileYouTube: boolean; - onInvidious: boolean; - - timestamps: number[][]; - types: string[]; - - constructor(parent: HTMLElement, onMobileYouTube: boolean, onInvidious: boolean) { - this.container = document.createElement('ul'); - this.container.id = 'previewbar'; - this.parent = parent; - - this.onMobileYouTube = onMobileYouTube; - this.onInvidious = onInvidious; - - this.updatePosition(parent); - - this.setupHoverText(); - } - - setupHoverText(): void { - if (this.onMobileYouTube || this.onInvidious) return; - - const seekBar = document.querySelector(".ytp-progress-bar-container"); - - // Create label placeholder - const tooltipTextWrapper = document.querySelector(".ytp-tooltip-text-wrapper"); - const titleTooltip = document.querySelector(".ytp-tooltip-title"); - const categoryTooltip = document.createElement("div"); - categoryTooltip.className = "sbHidden ytp-tooltip-title"; - categoryTooltip.id = "sponsor-block-category-tooltip" - - tooltipTextWrapper.insertBefore(categoryTooltip, titleTooltip.nextSibling); - - let mouseOnSeekBar = false; - - seekBar.addEventListener("mouseenter", () => { - mouseOnSeekBar = true; - }); - - seekBar.addEventListener("mouseleave", () => { - mouseOnSeekBar = false; - categoryTooltip.classList.add("sbHidden"); - }); - - const observer = new MutationObserver((mutations) => { - if (!mouseOnSeekBar) return; - - // See if mutation observed is only this ID (if so, ignore) - if (mutations.length == 1 && (mutations[0].target as HTMLElement).id === "sponsor-block-category-tooltip") { - return; - } - - const tooltips = document.querySelectorAll(".ytp-tooltip-text"); - for (const tooltip of tooltips) { - const splitData = tooltip.textContent.split(":"); - if (splitData.length === 2 && !isNaN(parseInt(splitData[0])) && !isNaN(parseInt(splitData[1]))) { - // Add label - const timeInSeconds = parseInt(splitData[0]) * 60 + parseInt(splitData[1]); - - // Find category at that location - let category = null; - for (let i = 0; i < this.timestamps?.length; i++) { - if (this.timestamps[i][0] < timeInSeconds && this.timestamps[i][1] > timeInSeconds){ - category = this.types[i]; - } - } - - if (category === null && !categoryTooltip.classList.contains("sbHidden")) { - categoryTooltip.classList.add("sbHidden"); - tooltipTextWrapper.classList.remove("sbTooltipTwoTitleThumbnailOffset"); - tooltipTextWrapper.classList.remove("sbTooltipOneTitleThumbnailOffset"); - } else if (category !== null) { - categoryTooltip.classList.remove("sbHidden"); - categoryTooltip.textContent = utils.shortCategoryName(category) - || (chrome.i18n.getMessage("preview") + " " + utils.shortCategoryName(category.split("preview-")[1])); - - // There is a title now - tooltip.classList.remove("ytp-tooltip-text-no-title"); - - // Add the correct offset for the number of titles there are - if (titleTooltip.textContent !== "") { - if (!tooltipTextWrapper.classList.contains("sbTooltipTwoTitleThumbnailOffset")) { - tooltipTextWrapper.classList.add("sbTooltipTwoTitleThumbnailOffset"); - } - } else if (!tooltipTextWrapper.classList.contains("sbTooltipOneTitleThumbnailOffset")) { - tooltipTextWrapper.classList.add("sbTooltipOneTitleThumbnailOffset"); - } - } - - break; - } - } - }); - - observer.observe(tooltipTextWrapper, { - childList: true, - subtree: true - }); - } - - updatePosition(parent: HTMLElement): void { - //below the seek bar - // this.parent.insertAdjacentElement("afterEnd", this.container); - - this.parent = parent; - - if (this.onMobileYouTube) { - parent.style.backgroundColor = "rgba(255, 255, 255, 0.3)"; - parent.style.opacity = "1"; - - this.container.style.transform = "none"; - } - - //on the seek bar - this.parent.insertAdjacentElement("afterbegin", this.container); - } - - updateColor(segment: string, color: string, opacity: string): void { - const bars = <NodeListOf<HTMLElement>> document.querySelectorAll('[data-vs-segment-type=' + segment + ']'); - for (const bar of bars) { - bar.style.backgroundColor = color; - bar.style.opacity = opacity; - } - } - - set(timestamps: number[][], types: string[], duration: number): void { - while (this.container.firstChild) { - this.container.removeChild(this.container.firstChild); - } - - if (!timestamps || !types) { - return; - } - - this.timestamps = timestamps; - this.types = types; - - // to avoid rounding error resulting in width more than 100% - duration = Math.floor(duration * 100) / 100; - let width; - for (let i = 0; i < timestamps.length; i++) { - if (types[i] == null) continue; - - width = (timestamps[i][1] - timestamps[i][0]) / duration * 100; - width = Math.floor(width * 100) / 100; - - const bar = this.createBar(); - bar.setAttribute('data-vs-segment-type', types[i]); - - bar.style.backgroundColor = Config.config.barTypes[types[i]].color; - if (!this.onMobileYouTube) bar.style.opacity = Config.config.barTypes[types[i]].opacity; - bar.style.width = width + '%'; - bar.style.left = (timestamps[i][0] / duration * 100) + "%"; - bar.style.position = "absolute" - - this.container.insertAdjacentElement("beforeend", bar); - } - } - - createBar(): HTMLLIElement { - const bar = document.createElement('li'); - bar.classList.add('previewbar'); - bar.innerHTML = ' '; - return bar; - } - - remove(): void { - this.container.remove(); - this.container = undefined; - } + container: HTMLUListElement; + categoryTooltip?: HTMLDivElement; + tooltipContainer?: HTMLElement; + + parent: HTMLElement; + onMobileYouTube: boolean; + onInvidious: boolean; + + segments: PreviewBarSegment[] = []; + videoDuration = 0; + + constructor(parent: HTMLElement, onMobileYouTube: boolean, onInvidious: boolean) { + this.container = document.createElement('ul'); + this.container.id = 'previewbar'; + + this.parent = parent; + this.onMobileYouTube = onMobileYouTube; + this.onInvidious = onInvidious; + + this.updatePosition(parent); + + this.setupHoverText(); + } + + setupHoverText(): void { + if (this.onMobileYouTube || this.onInvidious) return; + + // Create label placeholder + this.categoryTooltip = document.createElement("div"); + this.categoryTooltip.className = "ytp-tooltip-title sponsorCategoryTooltip"; + + const tooltipTextWrapper = document.querySelector(".ytp-tooltip-text-wrapper"); + if (!tooltipTextWrapper || !tooltipTextWrapper.parentElement) return; + + // Grab the tooltip from the text wrapper as the tooltip doesn't have its classes on init + this.tooltipContainer = tooltipTextWrapper.parentElement; + const titleTooltip = tooltipTextWrapper.querySelector(".ytp-tooltip-title"); + if (!this.tooltipContainer || !titleTooltip) return; + + tooltipTextWrapper.insertBefore(this.categoryTooltip, titleTooltip.nextSibling); + + const seekBar = document.querySelector(".ytp-progress-bar-container"); + if (!seekBar) return; + + let mouseOnSeekBar = false; + + seekBar.addEventListener("mouseenter", () => { + mouseOnSeekBar = true; + }); + + seekBar.addEventListener("mouseleave", () => { + mouseOnSeekBar = false; + }); + + const observer = new MutationObserver((mutations) => { + if (!mouseOnSeekBar || !this.categoryTooltip || !this.tooltipContainer) return; + + // If the mutation observed is only for our tooltip text, ignore + if (mutations.length === 1 && (mutations[0].target as HTMLElement).classList.contains("sponsorCategoryTooltip")) { + return; + } + + const tooltipTextElements = tooltipTextWrapper.querySelectorAll(".ytp-tooltip-text"); + let timeInSeconds: number | null = null; + let noYoutubeChapters = false; + + for (const tooltipTextElement of tooltipTextElements) { + if (tooltipTextElement.classList.contains('ytp-tooltip-text-no-title')) noYoutubeChapters = true; + + const tooltipText = tooltipTextElement.textContent; + if (tooltipText === null || tooltipText.length === 0) continue; + + timeInSeconds = utils.getFormattedTimeToSeconds(tooltipText); + + if (timeInSeconds !== null) break; + } + + if (timeInSeconds === null) return; + + // Find the segment at that location, using the shortest if multiple found + let segment: PreviewBarSegment | null = null; + let currentSegmentLength = Infinity; + + for (const seg of this.segments) { + if (seg.segment[0] <= timeInSeconds && seg.segment[1] > timeInSeconds) { + const segmentLength = seg.segment[1] - seg.segment[0]; + + if (segmentLength < currentSegmentLength) { + currentSegmentLength = segmentLength; + segment = seg; + } + } + } + + if (segment === null && this.tooltipContainer.classList.contains(TOOLTIP_VISIBLE_CLASS)) { + this.tooltipContainer.classList.remove(TOOLTIP_VISIBLE_CLASS); + } else if (segment !== null) { + this.tooltipContainer.classList.add(TOOLTIP_VISIBLE_CLASS); + + if (segment.preview) { + this.categoryTooltip.textContent = chrome.i18n.getMessage("preview") + " " + utils.shortCategoryName(segment.category); + } else { + this.categoryTooltip.textContent = utils.shortCategoryName(segment.category); + } + + // Use the class if the timestamp text uses it to prevent overlapping + this.categoryTooltip.classList.toggle("ytp-tooltip-text-no-title", noYoutubeChapters); + } + }); + + observer.observe(tooltipTextWrapper, { + childList: true, + subtree: true, + }); + } + + updatePosition(parent: HTMLElement): void { + this.parent = parent; + + if (this.onMobileYouTube) { + parent.style.backgroundColor = "rgba(255, 255, 255, 0.3)"; + parent.style.opacity = "1"; + + this.container.style.transform = "none"; + } + + // On the seek bar + this.parent.prepend(this.container); + } + + // TODO: call on config changes + updateColor(segmentType: string, color: string, opacity: number): void { + const bars = <NodeListOf<HTMLElement>> document.querySelectorAll('[data-vs-segment-type=' + segmentType + ']'); + + for (const bar of bars) { + bar.style.backgroundColor = color; + bar.style.opacity = String(opacity); + } + } + + clear(): void { + this.videoDuration = 0; + this.segments = []; + + while (this.container.firstChild) { + this.container.removeChild(this.container.firstChild); + } + } + + set(segments: PreviewBarSegment[], videoDuration: number): void { + this.clear(); + + if (!segments) return; + + this.segments = segments; + this.videoDuration = videoDuration; + + this.segments.sort(({segment: a}, {segment: b}) => { + // Sort longer segments before short segments to make shorter segments render later + return (b[1] - b[0]) - (a[1] - a[0]); + }).forEach((segment) => { + const bar = this.createBar(segment); + + this.container.appendChild(bar); + }); + } + + createBar({category, preview, segment}: PreviewBarSegment): HTMLLIElement { + const bar = document.createElement('li'); + bar.classList.add('previewbar'); + bar.innerHTML = ' '; + + const barSegmentType = (preview ? 'preview-' : '') + category; + + bar.setAttribute('data-vs-segment-type', barSegmentType); + + bar.style.backgroundColor = Config.config.barTypes[barSegmentType].color; + if (!this.onMobileYouTube) bar.style.opacity = Config.config.barTypes[barSegmentType].opacity; + + bar.style.position = "absolute"; + bar.style.width = this.timeToPercentage(segment[1] - segment[0]); + bar.style.left = this.timeToPercentage(segment[0]); + + return bar; + } + + remove(): void { + this.container.remove(); + + if (this.categoryTooltip) { + this.categoryTooltip.remove(); + this.categoryTooltip = undefined; + } + + if (this.tooltipContainer) { + this.tooltipContainer.classList.remove(TOOLTIP_VISIBLE_CLASS); + this.tooltipContainer = undefined; + } + } + + timeToPercentage(time: number): string { + return Math.min(100, time / this.videoDuration * 100) + '%'; + } } -export default PreviewBar;
\ No newline at end of file +export default PreviewBar; diff --git a/src/messageTypes.ts b/src/messageTypes.ts new file mode 100644 index 00000000..cd1914a8 --- /dev/null +++ b/src/messageTypes.ts @@ -0,0 +1,63 @@ +// +// Message and Response Types +// + +import { SponsorTime } from "./types"; + +interface BaseMessage { + from?: string; +} + +interface DefaultMessage { + message: + "update" + | "sponsorStart" + | "sponsorDataChanged" + | "isInfoFound" + | "getVideoID" + | "getChannelID" + | "isChannelWhitelisted" + | "submitTimes"; +} + +interface BoolValueMessage { + message: "whitelistChange"; + value: boolean; +} + +interface ChangeStartSponsorButtonMessage { + message: "changeStartSponsorButton"; + showStartSponsor: boolean; + uploadButtonVisible: boolean; +} + +export type Message = BaseMessage & (DefaultMessage | BoolValueMessage | ChangeStartSponsorButtonMessage); + +interface IsInfoFoundMessageResponse { + found: boolean; + sponsorTimes: SponsorTime[]; +} + +interface GetVideoIdResponse { + videoID: string; +} + +interface GetChannelIDResponse { + channelID: string; +} + +interface SponsorStartResponse { + time: number; +} + +interface IsChannelWhitelistedResponse { + value: boolean; +} + +export type MessageResponse = + IsInfoFoundMessageResponse + | GetVideoIdResponse + | GetChannelIDResponse + | SponsorStartResponse + | IsChannelWhitelistedResponse; + diff --git a/src/popup.ts b/src/popup.ts index 42859d3c..db34325c 100644 --- a/src/popup.ts +++ b/src/popup.ts @@ -2,11 +2,12 @@ import Config from "./config"; import Utils from "./utils"; import { SponsorTime, SponsorHideType } from "./types"; +import { Message, MessageResponse } from "./messageTypes"; const utils = new Utils(); interface MessageListener { - (request: any, sender: unknown, callback: (response: any) => void): void; -} + (request: Message, sender: unknown, sendResponse: (response: MessageResponse) => void): void; +} class MessageHandler { messageListener: MessageListener; @@ -15,7 +16,7 @@ class MessageHandler { this.messageListener = messageListener; } - sendMessage(id: number, request, callback?) { + sendMessage(id: number, request: Message, callback?) { if (this.messageListener) { this.messageListener(request, null, callback); } else { diff --git a/src/render/SkipNotice.tsx b/src/render/SkipNotice.tsx index ac66cae4..526d2d1c 100644 --- a/src/render/SkipNotice.tsx +++ b/src/render/SkipNotice.tsx @@ -1,7 +1,7 @@ import * as React from "react"; import * as ReactDOM from "react-dom"; -import SkipNoticeComponent from "../components/SkipNoticeComponent"; +import SkipNoticeComponent, { SkipNoticeAction } from "../components/SkipNoticeComponent"; import { SponsorTime, ContentContainer } from "../types"; class SkipNotice { @@ -15,6 +15,8 @@ class SkipNotice { skipNoticeRef: React.MutableRefObject<SkipNoticeComponent>; constructor(segments: SponsorTime[], autoSkip = false, contentContainer: ContentContainer) { + this.skipNoticeRef = React.createRef(); + this.segments = segments; this.autoSkip = autoSkip; this.contentContainer = contentContainer; @@ -67,6 +69,13 @@ class SkipNotice { ReactDOM.unmountComponentAtNode(this.noticeElement); this.noticeElement.remove(); + + const skipNotices = this.contentContainer().skipNotices; + skipNotices.splice(skipNotices.indexOf(this), 1); + } + + toggleSkip(): void { + this.skipNoticeRef.current.prepAction(SkipNoticeAction.Unskip); } } diff --git a/src/types.ts b/src/types.ts index 64afe352..dd870f37 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,13 +1,15 @@ import SubmissionNotice from "./render/SubmissionNotice"; import SkipNoticeComponent from "./components/SkipNoticeComponent"; +import SkipNotice from "./render/SkipNotice"; -interface ContentContainer { +export interface ContentContainer { (): { vote: (type: number, UUID: string, category?: string, skipNotice?: SkipNoticeComponent) => void, dontShowNoticeAgain: () => void, unskipSponsorTime: (segment: SponsorTime) => void, sponsorTimes: SponsorTime[], sponsorTimesSubmitting: SponsorTime[], + skipNotices: SkipNotice[], v: HTMLVideoElement, sponsorVideoID, reskipSponsorTime: (segment: SponsorTime) => void, @@ -22,34 +24,34 @@ interface ContentContainer { } } -interface FetchResponse { +export interface FetchResponse { responseText: string, status: number, ok: boolean } -interface VideoDurationResponse { +export interface VideoDurationResponse { duration: number; } -enum CategorySkipOption { +export enum CategorySkipOption { ShowOverlay, ManualSkip, AutoSkip } -interface CategorySelection { +export interface CategorySelection { name: string; option: CategorySkipOption } -enum SponsorHideType { +export enum SponsorHideType { Visible = undefined, Downvoted = 1, MinimumDuration } -interface SponsorTime { +export interface SponsorTime { segment: number[]; UUID: string; @@ -58,13 +60,13 @@ interface SponsorTime { hidden?: SponsorHideType; } -interface PreviewBarOption { +export interface PreviewBarOption { color: string, opacity: string } -interface Registration { +export interface Registration { message: string, id: string, allFrames: boolean, @@ -73,12 +75,12 @@ interface Registration { matches: string[] } -interface BackgroundScriptContainer { +export interface BackgroundScriptContainer { registerFirefoxContentScript: (opts: Registration) => void, unregisterFirefoxContentScript: (id: string) => void } -interface VideoInfo { +export interface VideoInfo { responseContext: { serviceTrackingParams: Array<{service: string, params: Array<{key: string, value: string}>}>, webResponseContextExtensionData: { @@ -154,22 +156,8 @@ interface VideoInfo { messages: unknown; } -type VideoID = string; - -type StorageChangesObject = { [key: string]: chrome.storage.StorageChange }; - -export { - FetchResponse, - VideoDurationResponse, - ContentContainer, - CategorySelection, - CategorySkipOption, - SponsorTime, - VideoID, - SponsorHideType, - PreviewBarOption, - Registration, - BackgroundScriptContainer, - VideoInfo, - StorageChangesObject, -}; +export type VideoID = string; + +export type StorageChangesObject = { [key: string]: chrome.storage.StorageChange }; + +export type UnEncodedSegmentTimes = [string, SponsorTime[]][];
\ No newline at end of file diff --git a/src/utils.ts b/src/utils.ts index c15d3ff6..6d7af44d 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -54,18 +54,16 @@ class Utils { setupExtraSitePermissions(callback: (granted: boolean) => void): void { // Request permission let permissions = ["declarativeContent"]; - if (this.isFirefox()) permissions = []; - - const self = this; + if (this.isFirefox()) permissions = []; chrome.permissions.request({ origins: this.getInvidiousInstancesRegex(), permissions: permissions - }, async function (granted) { + }, async (granted) => { if (granted) { - self.setupExtraSiteContentScripts(); + this.setupExtraSiteContentScripts(); } else { - self.removeExtraSiteRegistration(); + this.removeExtraSiteRegistration(); } callback(granted); @@ -80,7 +78,6 @@ class Utils { * For now, it is just SB.config.invidiousInstances. */ setupExtraSiteContentScripts(): void { - const self = this; if (this.isFirefox()) { const firefoxJS = []; @@ -107,9 +104,9 @@ class Utils { chrome.runtime.sendMessage(registration); } } else { - chrome.declarativeContent.onPageChanged.removeRules(["invidious"], function() { + chrome.declarativeContent.onPageChanged.removeRules(["invidious"], () => { const conditions = []; - for (const regex of self.getInvidiousInstancesRegex()) { + for (const regex of this.getInvidiousInstancesRegex()) { conditions.push(new chrome.declarativeContent.PageStateMatcher({ pageUrl: { urlMatches: regex } })); @@ -121,8 +118,8 @@ class Utils { conditions, actions: [new chrome.declarativeContent.RequestContentScript({ allFrames: true, - js: self.js, - css: self.css + js: this.js, + css: this.css })] }; @@ -157,17 +154,54 @@ class Utils { } /** - * Gets just the timestamps from a sponsorTimes array - * - * @param sponsorTimes + * Merges any overlapping timestamp ranges into single segments and returns them as a new array. */ - getSegmentsFromSponsorTimes(sponsorTimes: SponsorTime[]): number[][] { - const segments: number[][] = []; - for (const sponsorTime of sponsorTimes) { - segments.push(sponsorTime.segment); - } + getMergedTimestamps(timestamps: number[][]): [number, number][] { + let deduped: [number, number][] = []; + + // Cases ([] = another segment, <> = current range): + // [<]>, <[>], <[]>, [<>], [<][>] + timestamps.forEach((range) => { + // Find segments the current range overlaps + const startOverlaps = deduped.findIndex((other) => range[0] >= other[0] && range[0] <= other[1]); + const endOverlaps = deduped.findIndex((other) => range[1] >= other[0] && range[1] <= other[1]); + + if (~startOverlaps && ~endOverlaps) { + // [<][>] Both the start and end of this range overlap another segment + // [<>] This range is already entirely contained within an existing segment + if (startOverlaps === endOverlaps) return; + + // Remove the range with the higher index first to avoid the index shifting + const other1 = deduped.splice(Math.max(startOverlaps, endOverlaps), 1)[0]; + const other2 = deduped.splice(Math.min(startOverlaps, endOverlaps), 1)[0]; + + // Insert a new segment spanning the start and end of the range + deduped.push([Math.min(other1[0], other2[0]), Math.max(other1[1], other2[1])]); + } else if (~startOverlaps) { + // [<]> The start of this range overlaps another segment, extend its end + deduped[startOverlaps][1] = range[1]; + } else if (~endOverlaps) { + // <[>] The end of this range overlaps another segment, extend its beginning + deduped[endOverlaps][0] = range[0]; + } else { + // No overlaps, just push in a copy + deduped.push(range.slice() as [number, number]); + } - return segments; + // <[]> Remove other segments contained within this range + deduped = deduped.filter((other) => !(other[0] > range[0] && other[1] < range[1])); + }); + + return deduped; + } + + /** + * Returns the total duration of the timestamps, taking into account overlaps. + */ + getTimestampsDuration(timestamps: number[][]): number { + return this.getMergedTimestamps(timestamps).reduce((acc, range) => { + return acc + range[1] - range[0]; + }, 0); } getSponsorIndexFromUUID(sponsorTimes: SponsorTime[], UUID: string): number { |