diff --git a/package-lock.json b/package-lock.json index 14b0f2e61..53986fe21 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,9 +12,9 @@ "@babel/runtime": "7.16.0", "@sentry/browser": "6.13.3", "@stremio/stremio-colors": "4.0.1", - "@stremio/stremio-core-web": "0.43.0", + "@stremio/stremio-core-web": "0.44.6", "@stremio/stremio-icons": "3.0.5", - "@stremio/stremio-video": "0.0.20-rc.4", + "@stremio/stremio-video": "0.0.23", "a-color-picker": "1.2.1", "bowser": "2.11.0", "buffer": "6.0.3", @@ -22,13 +22,17 @@ "eventemitter3": "4.0.7", "filter-invalid-dom-props": "2.1.0", "lodash.debounce": "4.0.8", + "lodash.intersection": "4.4.0", "lodash.isequal": "4.5.0", "lodash.throttle": "4.1.1", + "magnet-uri": "6.2.0", "prop-types": "15.7.2", - "react": "16.12.0", - "react-dom": "16.12.0", - "react-focus-lock": "2.2.1", - "spatial-navigation-polyfill": "git+https://git@github.com/Stremio/spatial-navigation.git#64871b1422466f5f45d24ebc8bbd315b2ebab6a6" + "react": "18.2.0", + "react-dom": "18.2.0", + "react-focus-lock": "2.9.1", + "react-is": "18.2.0", + "spatial-navigation-polyfill": "git+https://git@github.com/Stremio/spatial-navigation.git#64871b1422466f5f45d24ebc8bbd315b2ebab6a6", + "url": "0.11.0" }, "devDependencies": { "@babel/core": "7.16.0", @@ -54,7 +58,8 @@ "terser-webpack-plugin": "5.2.4", "webpack": "5.61.0", "webpack-cli": "4.9.1", - "webpack-dev-server": "4.7.4" + "webpack-dev-server": "4.7.4", + "workbox-webpack-plugin": "^6.5.3" } }, "node_modules/@babel/code-frame": { @@ -283,12 +288,12 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", - "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dev": true, "dependencies": { - "@babel/types": "^7.16.0" + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -326,9 +331,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", - "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.6.tgz", + "integrity": "sha512-gvZnm1YAAxh13eJdkb9EWHBnF3eAub3XTLCZEehHT2kWxiKVRL64+ae5Y6Ivne0mVHmMYKT+xWgZO+gQhuLUBg==", "dev": true, "engines": { "node": ">=6.9.0" @@ -400,9 +405,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.15.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", - "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", "dev": true, "engines": { "node": ">=6.9.0" @@ -1722,12 +1727,12 @@ } }, "node_modules/@babel/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.0.tgz", - "integrity": "sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg==", + "version": "7.18.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.7.tgz", + "integrity": "sha512-QG3yxTcTIBoAcQmkCs+wAPYZhu7Dk9rXKacINfNbdJDNERTbLQbHGyVG8q/YGMPeCJRIhSY0+fTc5+xuh6WPSQ==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.15.7", + "@babel/helper-validator-identifier": "^7.18.6", "to-fast-properties": "^2.0.0" }, "engines": { @@ -2514,6 +2519,85 @@ "node": ">= 8" } }, + "node_modules/@rollup/plugin-babel": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", + "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.10.4", + "@rollup/pluginutils": "^3.1.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "@types/babel__core": "^7.1.9", + "rollup": "^1.20.0||^2.0.0" + }, + "peerDependenciesMeta": { + "@types/babel__core": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", + "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "@types/resolve": "1.17.1", + "builtin-modules": "^3.1.0", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/plugin-replace": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", + "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" + }, + "peerDependencies": { + "rollup": "^1.20.0 || ^2.0.0" + } + }, + "node_modules/@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "dependencies": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/pluginutils/node_modules/@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, "node_modules/@sentry/browser": { "version": "6.13.3", "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.13.3.tgz", @@ -2613,22 +2697,11 @@ "integrity": "sha512-yT3No1gIWKLV2BhQIeSgG94EzXxmEqXJLulO+pFpziqWNUbmmEKeE+nRvW5wtoIK4SLy+v0bLd0b6HBH3KFfWw==" }, "node_modules/@stremio/stremio-core-web": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@stremio/stremio-core-web/-/stremio-core-web-0.43.0.tgz", - "integrity": "sha512-EXr2PQpviUS4kF7gRUnTFDshsDh4gh/pp/ACaIgqXe6qZS4YlmPhLtXDxDKdBnulhjABW29GVul/vuuiEtff3w==", + "version": "0.44.6", + "resolved": "https://registry.npmjs.org/@stremio/stremio-core-web/-/stremio-core-web-0.44.6.tgz", + "integrity": "sha512-Mxc6oRKgTuXU80JEacJIe4TphccZUJkyHTMUZnUx9sotVetGX+EJsyvr+HLKNMDGJHx5xcwGT/BUikdyQR/Lpw==", "dependencies": { - "@babel/runtime": "7.15.4" - } - }, - "node_modules/@stremio/stremio-core-web/node_modules/@babel/runtime": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.4.tgz", - "integrity": "sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==", - "dependencies": { - "regenerator-runtime": "^0.13.4" - }, - "engines": { - "node": ">=6.9.0" + "@babel/runtime": "7.16.0" } }, "node_modules/@stremio/stremio-icons": { @@ -2637,15 +2710,16 @@ "integrity": "sha512-knlcBibqJW2mbEgid6YEeQN9FPkIGAEtozYWqzKWeHd2DPY2nl8kYX2pMQpa2Db/RVSqbVstu/gdey5TtSgGYw==" }, "node_modules/@stremio/stremio-video": { - "version": "0.0.20-rc.4", - "resolved": "https://registry.npmjs.org/@stremio/stremio-video/-/stremio-video-0.0.20-rc.4.tgz", - "integrity": "sha512-hRVXSH/3MsdQ2GNE56FqaUDT39PELoHV1BGRO9gLPIAJSX+nMlTs1eupGuGVcBdCnqPwEfZyRgpG0lRAmjLrRw==", + "version": "0.0.23", + "resolved": "https://registry.npmjs.org/@stremio/stremio-video/-/stremio-video-0.0.23.tgz", + "integrity": "sha512-2k9x28k6U5I4vrhTMo9hn+69s7tzTjVO9Wo2Ss8uufysfjuiQFWeJZkUJJgFEY0rWbCoJdfH6KVoMTcQLdHIwA==", "dependencies": { + "buffer": "6.0.3", "color": "4.2.3", "deep-freeze": "0.0.1", "eventemitter3": "4.0.7", "hat": "0.0.3", - "hls.js": "https://github.com/Stremio/hls.js/releases/download/v1.0.10-patch2/hls.js-1.0.10-patch2.tgz", + "hls.js": "https://github.com/Stremio/hls.js/releases/download/v1.2.3-patch1/hls.js-1.2.3-patch1.tgz", "lodash.clonedeep": "4.5.0", "magnet-uri": "6.2.0", "url": "0.11.0", @@ -2653,6 +2727,18 @@ "vtt.js": "github:jaruba/vtt.js#e4f5f5603730866bacb174a93f51b734c9f29e6a" } }, + "node_modules/@surma/rollup-plugin-off-main-thread": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", + "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", + "dev": true, + "dependencies": { + "ejs": "^3.1.6", + "json5": "^2.2.0", + "magic-string": "^0.25.0", + "string.prototype.matchall": "^4.0.6" + } + }, "node_modules/@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -2905,6 +2991,15 @@ "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", "dev": true }, + "node_modules/@types/resolve": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/retry": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", @@ -2945,6 +3040,12 @@ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, + "node_modules/@types/trusted-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", + "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==", + "dev": true + }, "node_modules/@types/ws": { "version": "8.2.2", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.2.tgz", @@ -3545,6 +3646,15 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/autoprefixer": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.0.tgz", @@ -3970,26 +4080,31 @@ "dev": true }, "node_modules/browserslist": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.5.tgz", - "integrity": "sha512-I3ekeB92mmpctWBoLXe0d5wPS2cBuRvvW0JyyJHMrk9/HmP2ZjrTboNAZ8iuGqaEIlKguljbQY32OkOJIRrgoA==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.1.tgz", + "integrity": "sha512-Nq8MFCSrnJXSc88yliwlzQe3qNe3VntIjhsArW9IJOEPSHNx23FalwApUVbzAWABLhYJJ7y8AynWI/XM8OdfjQ==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], "dependencies": { - "caniuse-lite": "^1.0.30001271", - "electron-to-chromium": "^1.3.878", - "escalade": "^3.1.1", - "node-releases": "^2.0.1", - "picocolors": "^1.0.0" + "caniuse-lite": "^1.0.30001359", + "electron-to-chromium": "^1.4.172", + "node-releases": "^2.0.5", + "update-browserslist-db": "^1.0.4" }, "bin": { "browserslist": "cli.js" }, "engines": { "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" } }, "node_modules/bser": { @@ -4036,6 +4151,18 @@ "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", "dev": true }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", @@ -4105,14 +4232,20 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001274", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001274.tgz", - "integrity": "sha512-+Nkvv0fHyhISkiMIjnyjmf5YJcQ1IQHZN6U9TLUMroWR38FNwpsC51Gb68yueafX1V6ifOisInSgP9WJFS13ew==", + "version": "1.0.30001363", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001363.tgz", + "integrity": "sha512-HpQhpzTGGPVMnCjIomjt+jvyUu8vNFo3TaDiZ/RcoTrlOq/5+tC8zHdsbgFB6MxmaY+jCpsH09aD80Bb4Ow3Sg==", "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] }, "node_modules/chalk": { "version": "2.4.2", @@ -4372,6 +4505,15 @@ "node": ">= 10" } }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -4600,12 +4742,12 @@ } }, "node_modules/core-js-compat": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.19.0.tgz", - "integrity": "sha512-R09rKZ56ccGBebjTLZHvzDxhz93YPT37gBm6qUhnwj3Kt7aCjjZWD1injyNbyeFHxNKfeZBSyds6O9n3MKq1sw==", + "version": "3.23.3", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.23.3.tgz", + "integrity": "sha512-WSzUs2h2vvmKsacLHNTdpyOC9k43AEhcGoFlVgCY4L7aw98oSBKtPL6vD0/TqZjRWRQYdDSLkzZIni4Crbbiqw==", "dev": true, "dependencies": { - "browserslist": "^4.17.5", + "browserslist": "^4.21.0", "semver": "7.0.0" }, "funding": { @@ -4658,6 +4800,15 @@ "node": ">= 8" } }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/css-color-names": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-1.0.1.tgz", @@ -5258,10 +5409,25 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, + "node_modules/ejs": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", + "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", + "dev": true, + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/electron-to-chromium": { - "version": "1.3.885", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.885.tgz", - "integrity": "sha512-JXKFJcVWrdHa09n4CNZYfYaK6EW5aAew7/wr3L1OnsD1L+JHL+RCtd7QgIsxUbFPeTwPlvnpqNNTOLkoefmtXg==", + "version": "1.4.180", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.180.tgz", + "integrity": "sha512-7at5ash3FD9U5gPa3/wPr6OdiZd/zBjvDZaaHBpcqFOFUhZiWnb7stkqk8xUFL9H9nk7Yok5vCCNK8wyC/+f8A==", "dev": true }, "node_modules/emittery": { @@ -5947,6 +6113,12 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -6216,6 +6388,36 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -6334,9 +6536,20 @@ "dev": true }, "node_modules/focus-lock": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/focus-lock/-/focus-lock-0.6.8.tgz", - "integrity": "sha512-vkHTluRCoq9FcsrldC0ulQHiyBYgVJB2CX53I8r0nTC6KnEij7Of0jpBspjt3/CuNb6fyoj3aOh9J2HgQUM0og==" + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/focus-lock/-/focus-lock-0.11.2.tgz", + "integrity": "sha512-pZ2bO++NWLHhiKkgP1bEXHhR1/OjVcSvlCJ98aNJDFeb7H5OOQaO+SKOZle6041O9rv2tmbrO4JzClAvDUHf0g==", + "dependencies": { + "tslib": "^2.0.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/focus-lock/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "node_modules/follow-redirects": { "version": "1.14.8", @@ -6403,6 +6616,30 @@ "node": ">= 0.6" } }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fs-extra/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/fs-monkey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", @@ -6473,6 +6710,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", + "dev": true + }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -6669,9 +6912,10 @@ } }, "node_modules/hls.js": { - "version": "1.0.10-patch2", - "resolved": "https://github.com/Stremio/hls.js/releases/download/v1.0.10-patch2/hls.js-1.0.10-patch2.tgz", - "integrity": "sha512-bH1VH0kcnlOCVdcXaTgPk06k63yP+w29XEQ7e4PNoLcVogm1MxnS20GBNXmjlqL8PsDHVUdzrn4Tcf/TzYWxYA==" + "version": "1.2.3-patch1.0.canary.8609", + "resolved": "https://github.com/Stremio/hls.js/releases/download/v1.2.3-patch1/hls.js-1.2.3-patch1.tgz", + "integrity": "sha512-b/WMwSXyV6QvoGYotzzrG0ldRW8mOzqxEhPDd+as4haAx78tmxoVkdYYtVKZ8MiJcMa6j00lfx7ti/2HlO5ByQ==", + "license": "Apache-2.0" }, "node_modules/hpack.js": { "version": "2.1.6", @@ -6931,6 +7175,12 @@ "postcss": "^8.1.0" } }, + "node_modules/idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==", + "dev": true + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -7240,6 +7490,12 @@ "node": ">=0.10.0" } }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true + }, "node_modules/is-negative-zero": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", @@ -7276,6 +7532,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-path-cwd": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", @@ -7354,6 +7619,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-resolvable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", @@ -7562,6 +7836,100 @@ "node": ">=8" } }, + "node_modules/jake": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", + "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "dev": true, + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jake/node_modules/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, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jake/node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "node_modules/jake/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jake/node_modules/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, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jake/node_modules/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 + }, + "node_modules/jake/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jake/node_modules/supports-color": { + "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, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/jest": { "version": "27.3.1", "resolved": "https://registry.npmjs.org/jest/-/jest-27.3.1.tgz", @@ -9342,6 +9710,12 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -9369,6 +9743,36 @@ "node": ">=6" } }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonfile/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/jsx-ast-utils": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz", @@ -9595,6 +9999,11 @@ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" }, + "node_modules/lodash.intersection": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.intersection/-/lodash.intersection-4.4.0.tgz", + "integrity": "sha512-N+L0cCfnqMv6mxXtSPeKt+IavbOBBSiAEkKyLasZ8BVcP9YXQgxLO12oPR8OyURwKV8l5vJKiE1M8aS70heuMg==" + }, "node_modules/lodash.isequal": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", @@ -9612,6 +10021,12 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true + }, "node_modules/lodash.throttle": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", @@ -9667,6 +10082,15 @@ "node": ">=10" } }, + "node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, "node_modules/magnet-uri": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/magnet-uri/-/magnet-uri-6.2.0.tgz", @@ -10032,9 +10456,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", - "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz", + "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==", "dev": true }, "node_modules/normalize-path": { @@ -11212,6 +11636,18 @@ "node": ">= 0.8.0" } }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/pretty-error": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", @@ -11293,6 +11729,11 @@ "react-is": "^16.8.1" } }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -11417,63 +11858,65 @@ } }, "node_modules/react": { - "version": "16.12.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.12.0.tgz", - "integrity": "sha512-fglqy3k5E+81pA8s+7K0/T3DBCF0ZDOher1elBFzF7O6arXJgzyu/FW+COxFvAWXJoJN9KIZbT2LXlukwphYTA==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2" + "loose-envify": "^1.1.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/react-clientside-effect": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/react-clientside-effect/-/react-clientside-effect-1.2.5.tgz", - "integrity": "sha512-2bL8qFW1TGBHozGGbVeyvnggRpMjibeZM2536AKNENLECutp2yfs44IL8Hmpn8qjFQ2K7A9PnYf3vc7aQq/cPA==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/react-clientside-effect/-/react-clientside-effect-1.2.6.tgz", + "integrity": "sha512-XGGGRQAKY+q25Lz9a/4EPqom7WRjz3z9R2k4jhVKA/puQFH/5Nt27vFZYql4m4NVNdUvX8PS3O7r/Zzm7cjUlg==", "dependencies": { "@babel/runtime": "^7.12.13" }, "peerDependencies": { - "react": "^15.3.0 || ^16.0.0 || ^17.0.0" + "react": "^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" } }, "node_modules/react-dom": { - "version": "16.12.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.12.0.tgz", - "integrity": "sha512-LMxFfAGrcS3kETtQaCkTKjMiifahaMySFDn71fZUNpPHZQEzmk/GiAeIT8JSOrHB23fnuCOMruL2a8NYlw+8Gw==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", "dependencies": { "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.18.0" + "scheduler": "^0.23.0" }, "peerDependencies": { - "react": "^16.0.0" + "react": "^18.2.0" } }, "node_modules/react-focus-lock": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/react-focus-lock/-/react-focus-lock-2.2.1.tgz", - "integrity": "sha512-47g0xYcCTZccdzKRGufepY8oZ3W1Qg+2hn6u9SHZ0zUB6uz/4K4xJe7yYFNZ1qT6m+2JDm82F6QgKeBTbjW4PQ==", + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/react-focus-lock/-/react-focus-lock-2.9.1.tgz", + "integrity": "sha512-pSWOQrUmiKLkffPO6BpMXN7SNKXMsuOakl652IBuALAu1esk+IcpJyM+ALcYzPTTFz1rD0R54aB9A4HuP5t1Wg==", "dependencies": { "@babel/runtime": "^7.0.0", - "focus-lock": "^0.6.6", + "focus-lock": "^0.11.2", "prop-types": "^15.6.2", - "react-clientside-effect": "^1.2.2", - "use-callback-ref": "^1.2.1", - "use-sidecar": "^1.0.1" + "react-clientside-effect": "^1.2.6", + "use-callback-ref": "^1.3.0", + "use-sidecar": "^1.1.2" }, "peerDependencies": { - "react": "^16.8.0" + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "node_modules/readable-stream": { "version": "3.6.0", @@ -11746,6 +12189,80 @@ "rimraf": "bin.js" } }, + "node_modules/rollup": { + "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-terser": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "jest-worker": "^26.2.1", + "serialize-javascript": "^4.0.0", + "terser": "^5.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0" + } + }, + "node_modules/rollup-plugin-terser/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/rollup-plugin-terser/node_modules/jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/rollup-plugin-terser/node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/rollup-plugin-terser/node_modules/supports-color": { + "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, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -11801,12 +12318,11 @@ } }, "node_modules/scheduler": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.18.0.tgz", - "integrity": "sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "loose-envify": "^1.1.0" } }, "node_modules/schema-utils": { @@ -12131,6 +12647,12 @@ "websocket-driver": "^0.7.4" } }, + "node_modules/source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -12168,6 +12690,12 @@ "node": ">=0.10.0" } }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, "node_modules/spatial-navigation-polyfill": { "version": "1.2.0", "resolved": "git+https://git@github.com/Stremio/spatial-navigation.git#64871b1422466f5f45d24ebc8bbd315b2ebab6a6", @@ -12327,6 +12855,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dev": true, + "dependencies": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -12348,6 +12890,15 @@ "node": ">=8" } }, + "node_modules/strip-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", + "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", @@ -12506,6 +13057,45 @@ "node": ">=6" } }, + "node_modules/temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tempy": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", + "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", + "dev": true, + "dependencies": { + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/terminal-link": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", @@ -12878,6 +13468,18 @@ "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", "dev": true }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -12896,6 +13498,42 @@ "node": ">= 0.8" } }, + "node_modules/upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true, + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz", + "integrity": "sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -12924,15 +13562,18 @@ } }, "node_modules/use-callback-ref": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.2.5.tgz", - "integrity": "sha512-gN3vgMISAgacF7sqsLPByqoePooY3n2emTH59Ur5d/M8eg4WTWu1xp8i8DHjohftIyEx0S08RiYxbffr4j8Peg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.0.tgz", + "integrity": "sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w==", + "dependencies": { + "tslib": "^2.0.0" + }, "engines": { - "node": ">=8.5.0" + "node": ">=10" }, "peerDependencies": { - "@types/react": "^16.8.0 || ^17.0.0", - "react": "^16.8.0 || ^17.0.0" + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -12940,21 +13581,37 @@ } } }, + "node_modules/use-callback-ref/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, "node_modules/use-sidecar": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.0.5.tgz", - "integrity": "sha512-k9jnrjYNwN6xYLj1iaGhonDghfvmeTmYjAiGvOr7clwKfPjMXJf4/HOr7oT5tJwYafgp2tG2l3eZEOfoELiMcA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", + "integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==", "dependencies": { "detect-node-es": "^1.1.0", - "tslib": "^1.9.3" + "tslib": "^2.0.0" }, "engines": { - "node": ">=8.5.0" + "node": ">=10" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0" + "@types/react": "^16.9.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, + "node_modules/use-sidecar/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -13689,6 +14346,321 @@ "node": ">=0.10.0" } }, + "node_modules/workbox-background-sync": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.5.4.tgz", + "integrity": "sha512-0r4INQZMyPky/lj4Ou98qxcThrETucOde+7mRGJl13MPJugQNKeZQOdIJe/1AchOP23cTqHcN/YVpD6r8E6I8g==", + "dev": true, + "dependencies": { + "idb": "^7.0.1", + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-broadcast-update": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.5.4.tgz", + "integrity": "sha512-I/lBERoH1u3zyBosnpPEtcAVe5lwykx9Yg1k6f8/BGEPGaMMgZrwVrqL1uA9QZ1NGGFoyE6t9i7lBjOlDhFEEw==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-build": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.5.4.tgz", + "integrity": "sha512-kgRevLXEYvUW9WS4XoziYqZ8Q9j/2ziJYEtTrjdz5/L/cTUa2XfyMP2i7c3p34lgqJ03+mTiz13SdFef2POwbA==", + "dev": true, + "dependencies": { + "@apideck/better-ajv-errors": "^0.3.1", + "@babel/core": "^7.11.1", + "@babel/preset-env": "^7.11.0", + "@babel/runtime": "^7.11.2", + "@rollup/plugin-babel": "^5.2.0", + "@rollup/plugin-node-resolve": "^11.2.1", + "@rollup/plugin-replace": "^2.4.1", + "@surma/rollup-plugin-off-main-thread": "^2.2.3", + "ajv": "^8.6.0", + "common-tags": "^1.8.0", + "fast-json-stable-stringify": "^2.1.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", + "lodash": "^4.17.20", + "pretty-bytes": "^5.3.0", + "rollup": "^2.43.1", + "rollup-plugin-terser": "^7.0.0", + "source-map": "^0.8.0-beta.0", + "stringify-object": "^3.3.0", + "strip-comments": "^2.0.1", + "tempy": "^0.6.0", + "upath": "^1.2.0", + "workbox-background-sync": "6.5.4", + "workbox-broadcast-update": "6.5.4", + "workbox-cacheable-response": "6.5.4", + "workbox-core": "6.5.4", + "workbox-expiration": "6.5.4", + "workbox-google-analytics": "6.5.4", + "workbox-navigation-preload": "6.5.4", + "workbox-precaching": "6.5.4", + "workbox-range-requests": "6.5.4", + "workbox-recipes": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4", + "workbox-streams": "6.5.4", + "workbox-sw": "6.5.4", + "workbox-window": "6.5.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/workbox-build/node_modules/@apideck/better-ajv-errors": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz", + "integrity": "sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==", + "dev": true, + "dependencies": { + "json-schema": "^0.4.0", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "ajv": ">=8" + } + }, + "node_modules/workbox-build/node_modules/ajv": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz", + "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/workbox-build/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/workbox-build/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/workbox-build/node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dev": true, + "dependencies": { + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/workbox-build/node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/workbox-build/node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "node_modules/workbox-build/node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/workbox-cacheable-response": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.5.4.tgz", + "integrity": "sha512-DCR9uD0Fqj8oB2TSWQEm1hbFs/85hXXoayVwFKLVuIuxwJaihBsLsp4y7J9bvZbqtPJ1KlCkmYVGQKrBU4KAug==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-core": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.4.tgz", + "integrity": "sha512-OXYb+m9wZm8GrORlV2vBbE5EC1FKu71GGp0H4rjmxmF4/HLbMCoTFws87M3dFwgpmg0v00K++PImpNQ6J5NQ6Q==", + "dev": true + }, + "node_modules/workbox-expiration": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.5.4.tgz", + "integrity": "sha512-jUP5qPOpH1nXtjGGh1fRBa1wJL2QlIb5mGpct3NzepjGG2uFFBn4iiEBiI9GUmfAFR2ApuRhDydjcRmYXddiEQ==", + "dev": true, + "dependencies": { + "idb": "^7.0.1", + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-google-analytics": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.5.4.tgz", + "integrity": "sha512-8AU1WuaXsD49249Wq0B2zn4a/vvFfHkpcFfqAFHNHwln3jK9QUYmzdkKXGIZl9wyKNP+RRX30vcgcyWMcZ9VAg==", + "dev": true, + "dependencies": { + "workbox-background-sync": "6.5.4", + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "node_modules/workbox-navigation-preload": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.5.4.tgz", + "integrity": "sha512-IIwf80eO3cr8h6XSQJF+Hxj26rg2RPFVUmJLUlM0+A2GzB4HFbQyKkrgD5y2d84g2IbJzP4B4j5dPBRzamHrng==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-precaching": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.5.4.tgz", + "integrity": "sha512-hSMezMsW6btKnxHB4bFy2Qfwey/8SYdGWvVIKFaUm8vJ4E53JAY+U2JwLTRD8wbLWoP6OVUdFlXsTdKu9yoLTg==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "node_modules/workbox-range-requests": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-6.5.4.tgz", + "integrity": "sha512-Je2qR1NXCFC8xVJ/Lux6saH6IrQGhMpDrPXWZWWS8n/RD+WZfKa6dSZwU+/QksfEadJEr/NfY+aP/CXFFK5JFg==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-recipes": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.5.4.tgz", + "integrity": "sha512-QZNO8Ez708NNwzLNEXTG4QYSKQ1ochzEtRLGaq+mr2PyoEIC1xFW7MrWxrONUxBFOByksds9Z4//lKAX8tHyUA==", + "dev": true, + "dependencies": { + "workbox-cacheable-response": "6.5.4", + "workbox-core": "6.5.4", + "workbox-expiration": "6.5.4", + "workbox-precaching": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "node_modules/workbox-routing": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.4.tgz", + "integrity": "sha512-apQswLsbrrOsBUWtr9Lf80F+P1sHnQdYodRo32SjiByYi36IDyL2r7BH1lJtFX8fwNHDa1QOVY74WKLLS6o5Pg==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-strategies": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.4.tgz", + "integrity": "sha512-DEtsxhx0LIYWkJBTQolRxG4EI0setTJkqR4m7r4YpBdxtWJH1Mbg01Cj8ZjNOO8etqfA3IZaOPHUxCs8cBsKLw==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-streams": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.5.4.tgz", + "integrity": "sha512-FXKVh87d2RFXkliAIheBojBELIPnWbQdyDvsH3t74Cwhg0fDheL1T8BqSM86hZvC0ZESLsznSYWw+Va+KVbUzg==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4" + } + }, + "node_modules/workbox-sw": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.5.4.tgz", + "integrity": "sha512-vo2RQo7DILVRoH5LjGqw3nphavEjK4Qk+FenXeUsknKn14eCNedHOXWbmnvP4ipKhlE35pvJ4yl4YYf6YsJArA==", + "dev": true + }, + "node_modules/workbox-webpack-plugin": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-webpack-plugin/-/workbox-webpack-plugin-6.5.4.tgz", + "integrity": "sha512-LmWm/zoaahe0EGmMTrSLUi+BjyR3cdGEfU3fS6PN1zKFYbqAKuQ+Oy/27e4VSXsyIwAw8+QDfk1XHNGtZu9nQg==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "^2.1.0", + "pretty-bytes": "^5.4.1", + "upath": "^1.2.0", + "webpack-sources": "^1.4.3", + "workbox-build": "6.5.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "webpack": "^4.4.0 || ^5.9.0" + } + }, + "node_modules/workbox-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workbox-webpack-plugin/node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/workbox-window": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-6.5.4.tgz", + "integrity": "sha512-HnLZJDwYBE+hpG25AQBO8RUWBJRaCsI9ksQJEp3aCOFCaG5kqaToAYXFRAHxzRluM2cQbGzdQF5rjKPWPA1fug==", + "dev": true, + "dependencies": { + "@types/trusted-types": "^2.0.2", + "workbox-core": "6.5.4" + } + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -14023,12 +14995,12 @@ } }, "@babel/helper-module-imports": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", - "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dev": true, "requires": { - "@babel/types": "^7.16.0" + "@babel/types": "^7.18.6" } }, "@babel/helper-module-transforms": { @@ -14057,9 +15029,9 @@ } }, "@babel/helper-plugin-utils": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", - "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.6.tgz", + "integrity": "sha512-gvZnm1YAAxh13eJdkb9EWHBnF3eAub3XTLCZEehHT2kWxiKVRL64+ae5Y6Ivne0mVHmMYKT+xWgZO+gQhuLUBg==", "dev": true }, "@babel/helper-remap-async-to-generator": { @@ -14113,9 +15085,9 @@ } }, "@babel/helper-validator-identifier": { - "version": "7.15.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", - "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", "dev": true }, "@babel/helper-validator-option": { @@ -15003,12 +15975,12 @@ } }, "@babel/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.0.tgz", - "integrity": "sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg==", + "version": "7.18.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.7.tgz", + "integrity": "sha512-QG3yxTcTIBoAcQmkCs+wAPYZhu7Dk9rXKacINfNbdJDNERTbLQbHGyVG8q/YGMPeCJRIhSY0+fTc5+xuh6WPSQ==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.15.7", + "@babel/helper-validator-identifier": "^7.18.6", "to-fast-properties": "^2.0.0" } }, @@ -15603,6 +16575,59 @@ "fastq": "^1.6.0" } }, + "@rollup/plugin-babel": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", + "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.10.4", + "@rollup/pluginutils": "^3.1.0" + } + }, + "@rollup/plugin-node-resolve": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", + "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.1.0", + "@types/resolve": "1.17.1", + "builtin-modules": "^3.1.0", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.19.0" + } + }, + "@rollup/plugin-replace": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", + "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" + } + }, + "@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "requires": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "dependencies": { + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + } + } + }, "@sentry/browser": { "version": "6.13.3", "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.13.3.tgz", @@ -15684,21 +16709,11 @@ "integrity": "sha512-yT3No1gIWKLV2BhQIeSgG94EzXxmEqXJLulO+pFpziqWNUbmmEKeE+nRvW5wtoIK4SLy+v0bLd0b6HBH3KFfWw==" }, "@stremio/stremio-core-web": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@stremio/stremio-core-web/-/stremio-core-web-0.43.0.tgz", - "integrity": "sha512-EXr2PQpviUS4kF7gRUnTFDshsDh4gh/pp/ACaIgqXe6qZS4YlmPhLtXDxDKdBnulhjABW29GVul/vuuiEtff3w==", + "version": "0.44.6", + "resolved": "https://registry.npmjs.org/@stremio/stremio-core-web/-/stremio-core-web-0.44.6.tgz", + "integrity": "sha512-Mxc6oRKgTuXU80JEacJIe4TphccZUJkyHTMUZnUx9sotVetGX+EJsyvr+HLKNMDGJHx5xcwGT/BUikdyQR/Lpw==", "requires": { - "@babel/runtime": "7.15.4" - }, - "dependencies": { - "@babel/runtime": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.4.tgz", - "integrity": "sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==", - "requires": { - "regenerator-runtime": "^0.13.4" - } - } + "@babel/runtime": "7.16.0" } }, "@stremio/stremio-icons": { @@ -15707,15 +16722,16 @@ "integrity": "sha512-knlcBibqJW2mbEgid6YEeQN9FPkIGAEtozYWqzKWeHd2DPY2nl8kYX2pMQpa2Db/RVSqbVstu/gdey5TtSgGYw==" }, "@stremio/stremio-video": { - "version": "0.0.20-rc.4", - "resolved": "https://registry.npmjs.org/@stremio/stremio-video/-/stremio-video-0.0.20-rc.4.tgz", - "integrity": "sha512-hRVXSH/3MsdQ2GNE56FqaUDT39PELoHV1BGRO9gLPIAJSX+nMlTs1eupGuGVcBdCnqPwEfZyRgpG0lRAmjLrRw==", + "version": "0.0.23", + "resolved": "https://registry.npmjs.org/@stremio/stremio-video/-/stremio-video-0.0.23.tgz", + "integrity": "sha512-2k9x28k6U5I4vrhTMo9hn+69s7tzTjVO9Wo2Ss8uufysfjuiQFWeJZkUJJgFEY0rWbCoJdfH6KVoMTcQLdHIwA==", "requires": { + "buffer": "6.0.3", "color": "4.2.3", "deep-freeze": "0.0.1", "eventemitter3": "4.0.7", "hat": "0.0.3", - "hls.js": "https://github.com/Stremio/hls.js/releases/download/v1.0.10-patch2/hls.js-1.0.10-patch2.tgz", + "hls.js": "https://github.com/Stremio/hls.js/releases/download/v1.2.3-patch1/hls.js-1.2.3-patch1.tgz", "lodash.clonedeep": "4.5.0", "magnet-uri": "6.2.0", "url": "0.11.0", @@ -15723,6 +16739,18 @@ "vtt.js": "github:jaruba/vtt.js#e4f5f5603730866bacb174a93f51b734c9f29e6a" } }, + "@surma/rollup-plugin-off-main-thread": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", + "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", + "dev": true, + "requires": { + "ejs": "^3.1.6", + "json5": "^2.2.0", + "magic-string": "^0.25.0", + "string.prototype.matchall": "^4.0.6" + } + }, "@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -15969,6 +16997,15 @@ "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", "dev": true }, + "@types/resolve": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/retry": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", @@ -16009,6 +17046,12 @@ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, + "@types/trusted-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", + "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==", + "dev": true + }, "@types/ws": { "version": "8.2.2", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.2.tgz", @@ -16501,6 +17544,12 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true + }, "autoprefixer": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.0.tgz", @@ -16829,16 +17878,15 @@ "dev": true }, "browserslist": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.5.tgz", - "integrity": "sha512-I3ekeB92mmpctWBoLXe0d5wPS2cBuRvvW0JyyJHMrk9/HmP2ZjrTboNAZ8iuGqaEIlKguljbQY32OkOJIRrgoA==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.1.tgz", + "integrity": "sha512-Nq8MFCSrnJXSc88yliwlzQe3qNe3VntIjhsArW9IJOEPSHNx23FalwApUVbzAWABLhYJJ7y8AynWI/XM8OdfjQ==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001271", - "electron-to-chromium": "^1.3.878", - "escalade": "^3.1.1", - "node-releases": "^2.0.1", - "picocolors": "^1.0.0" + "caniuse-lite": "^1.0.30001359", + "electron-to-chromium": "^1.4.172", + "node-releases": "^2.0.5", + "update-browserslist-db": "^1.0.4" } }, "bser": { @@ -16871,6 +17919,12 @@ "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", "dev": true }, + "builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true + }, "bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", @@ -16930,9 +17984,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001274", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001274.tgz", - "integrity": "sha512-+Nkvv0fHyhISkiMIjnyjmf5YJcQ1IQHZN6U9TLUMroWR38FNwpsC51Gb68yueafX1V6ifOisInSgP9WJFS13ew==", + "version": "1.0.30001363", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001363.tgz", + "integrity": "sha512-HpQhpzTGGPVMnCjIomjt+jvyUu8vNFo3TaDiZ/RcoTrlOq/5+tC8zHdsbgFB6MxmaY+jCpsH09aD80Bb4Ow3Sg==", "dev": true }, "chalk": { @@ -17142,6 +18196,12 @@ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "dev": true }, + "common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "dev": true + }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -17312,12 +18372,12 @@ } }, "core-js-compat": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.19.0.tgz", - "integrity": "sha512-R09rKZ56ccGBebjTLZHvzDxhz93YPT37gBm6qUhnwj3Kt7aCjjZWD1injyNbyeFHxNKfeZBSyds6O9n3MKq1sw==", + "version": "3.23.3", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.23.3.tgz", + "integrity": "sha512-WSzUs2h2vvmKsacLHNTdpyOC9k43AEhcGoFlVgCY4L7aw98oSBKtPL6vD0/TqZjRWRQYdDSLkzZIni4Crbbiqw==", "dev": true, "requires": { - "browserslist": "^4.17.5", + "browserslist": "^4.21.0", "semver": "7.0.0" }, "dependencies": { @@ -17359,6 +18419,12 @@ "which": "^2.0.1" } }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true + }, "css-color-names": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-1.0.1.tgz", @@ -17819,10 +18885,19 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, + "ejs": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", + "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", + "dev": true, + "requires": { + "jake": "^10.8.5" + } + }, "electron-to-chromium": { - "version": "1.3.885", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.885.tgz", - "integrity": "sha512-JXKFJcVWrdHa09n4CNZYfYaK6EW5aAew7/wr3L1OnsD1L+JHL+RCtd7QgIsxUbFPeTwPlvnpqNNTOLkoefmtXg==", + "version": "1.4.180", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.180.tgz", + "integrity": "sha512-7at5ash3FD9U5gPa3/wPr6OdiZd/zBjvDZaaHBpcqFOFUhZiWnb7stkqk8xUFL9H9nk7Yok5vCCNK8wyC/+f8A==", "dev": true }, "emittery": { @@ -18329,6 +19404,12 @@ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true }, + "estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -18548,6 +19629,35 @@ "flat-cache": "^3.0.4" } }, + "filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "requires": { + "minimatch": "^5.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -18646,9 +19756,19 @@ "dev": true }, "focus-lock": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/focus-lock/-/focus-lock-0.6.8.tgz", - "integrity": "sha512-vkHTluRCoq9FcsrldC0ulQHiyBYgVJB2CX53I8r0nTC6KnEij7Of0jpBspjt3/CuNb6fyoj3aOh9J2HgQUM0og==" + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/focus-lock/-/focus-lock-0.11.2.tgz", + "integrity": "sha512-pZ2bO++NWLHhiKkgP1bEXHhR1/OjVcSvlCJ98aNJDFeb7H5OOQaO+SKOZle6041O9rv2tmbrO4JzClAvDUHf0g==", + "requires": { + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + } + } }, "follow-redirects": { "version": "1.14.8", @@ -18685,6 +19805,26 @@ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", "dev": true }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "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 + } + } + }, "fs-monkey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", @@ -18739,6 +19879,12 @@ "has-symbols": "^1.0.1" } }, + "get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", + "dev": true + }, "get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -18877,8 +20023,8 @@ "dev": true }, "hls.js": { - "version": "https://github.com/Stremio/hls.js/releases/download/v1.0.10-patch2/hls.js-1.0.10-patch2.tgz", - "integrity": "sha512-bH1VH0kcnlOCVdcXaTgPk06k63yP+w29XEQ7e4PNoLcVogm1MxnS20GBNXmjlqL8PsDHVUdzrn4Tcf/TzYWxYA==" + "version": "https://github.com/Stremio/hls.js/releases/download/v1.2.3-patch1/hls.js-1.2.3-patch1.tgz", + "integrity": "sha512-b/WMwSXyV6QvoGYotzzrG0ldRW8mOzqxEhPDd+as4haAx78tmxoVkdYYtVKZ8MiJcMa6j00lfx7ti/2HlO5ByQ==" }, "hpack.js": { "version": "2.1.6", @@ -19075,6 +20221,12 @@ "dev": true, "requires": {} }, + "idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==", + "dev": true + }, "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -19277,6 +20429,12 @@ "is-extglob": "^2.1.1" } }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true + }, "is-negative-zero": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", @@ -19298,6 +20456,12 @@ "has-tostringtag": "^1.0.0" } }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", + "dev": true + }, "is-path-cwd": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", @@ -19352,6 +20516,12 @@ "has-tostringtag": "^1.0.0" } }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", + "dev": true + }, "is-resolvable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", @@ -19510,6 +20680,75 @@ "istanbul-lib-report": "^3.0.0" } }, + "jake": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", + "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "dev": true, + "requires": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "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.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.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 + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "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" + } + } + } + }, "jest": { "version": "27.3.1", "resolved": "https://registry.npmjs.org/jest/-/jest-27.3.1.tgz", @@ -20840,6 +22079,12 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, + "json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -20861,6 +22106,30 @@ "minimist": "^1.2.5" } }, + "jsonfile": { + "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": "^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 + } + } + }, + "jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "dev": true + }, "jsx-ast-utils": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz", @@ -21030,6 +22299,11 @@ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" }, + "lodash.intersection": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.intersection/-/lodash.intersection-4.4.0.tgz", + "integrity": "sha512-N+L0cCfnqMv6mxXtSPeKt+IavbOBBSiAEkKyLasZ8BVcP9YXQgxLO12oPR8OyURwKV8l5vJKiE1M8aS70heuMg==" + }, "lodash.isequal": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", @@ -21047,6 +22321,12 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true + }, "lodash.throttle": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", @@ -21098,6 +22378,15 @@ "yallist": "^4.0.0" } }, + "magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.8" + } + }, "magnet-uri": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/magnet-uri/-/magnet-uri-6.2.0.tgz", @@ -21372,9 +22661,9 @@ "dev": true }, "node-releases": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", - "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz", + "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==", "dev": true }, "normalize-path": { @@ -22183,6 +23472,12 @@ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, + "pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "dev": true + }, "pretty-error": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", @@ -22249,6 +23544,13 @@ "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.8.1" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } } }, "proxy-addr": { @@ -22340,51 +23642,47 @@ } }, "react": { - "version": "16.12.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.12.0.tgz", - "integrity": "sha512-fglqy3k5E+81pA8s+7K0/T3DBCF0ZDOher1elBFzF7O6arXJgzyu/FW+COxFvAWXJoJN9KIZbT2LXlukwphYTA==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2" + "loose-envify": "^1.1.0" } }, "react-clientside-effect": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/react-clientside-effect/-/react-clientside-effect-1.2.5.tgz", - "integrity": "sha512-2bL8qFW1TGBHozGGbVeyvnggRpMjibeZM2536AKNENLECutp2yfs44IL8Hmpn8qjFQ2K7A9PnYf3vc7aQq/cPA==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/react-clientside-effect/-/react-clientside-effect-1.2.6.tgz", + "integrity": "sha512-XGGGRQAKY+q25Lz9a/4EPqom7WRjz3z9R2k4jhVKA/puQFH/5Nt27vFZYql4m4NVNdUvX8PS3O7r/Zzm7cjUlg==", "requires": { "@babel/runtime": "^7.12.13" } }, "react-dom": { - "version": "16.12.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.12.0.tgz", - "integrity": "sha512-LMxFfAGrcS3kETtQaCkTKjMiifahaMySFDn71fZUNpPHZQEzmk/GiAeIT8JSOrHB23fnuCOMruL2a8NYlw+8Gw==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", "requires": { "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.18.0" + "scheduler": "^0.23.0" } }, "react-focus-lock": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/react-focus-lock/-/react-focus-lock-2.2.1.tgz", - "integrity": "sha512-47g0xYcCTZccdzKRGufepY8oZ3W1Qg+2hn6u9SHZ0zUB6uz/4K4xJe7yYFNZ1qT6m+2JDm82F6QgKeBTbjW4PQ==", + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/react-focus-lock/-/react-focus-lock-2.9.1.tgz", + "integrity": "sha512-pSWOQrUmiKLkffPO6BpMXN7SNKXMsuOakl652IBuALAu1esk+IcpJyM+ALcYzPTTFz1rD0R54aB9A4HuP5t1Wg==", "requires": { "@babel/runtime": "^7.0.0", - "focus-lock": "^0.6.6", + "focus-lock": "^0.11.2", "prop-types": "^15.6.2", - "react-clientside-effect": "^1.2.2", - "use-callback-ref": "^1.2.1", - "use-sidecar": "^1.0.1" + "react-clientside-effect": "^1.2.6", + "use-callback-ref": "^1.3.0", + "use-sidecar": "^1.1.2" } }, "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "readable-stream": { "version": "3.6.0", @@ -22594,6 +23892,64 @@ "glob": "^7.1.3" } }, + "rollup": { + "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, + "rollup-plugin-terser": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "jest-worker": "^26.2.1", + "serialize-javascript": "^4.0.0", + "terser": "^5.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "supports-color": { + "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" + } + } + } + }, "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -22632,12 +23988,11 @@ } }, "scheduler": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.18.0.tgz", - "integrity": "sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "loose-envify": "^1.1.0" } }, "schema-utils": { @@ -22917,6 +24272,12 @@ "websocket-driver": "^0.7.4" } }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -22947,6 +24308,12 @@ } } }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, "spatial-navigation-polyfill": { "version": "git+https://git@github.com/Stremio/spatial-navigation.git#64871b1422466f5f45d24ebc8bbd315b2ebab6a6", "integrity": "sha512-zREQWdiN2VSugD90lq0uBsSBjT/YtytCijN83V6LEJTRmAe/fMYUtjUtYr7UvBrSPxfnSM54BNq9r2kKFTJvlQ==", @@ -23080,6 +24447,17 @@ "define-properties": "^1.1.3" } }, + "stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dev": true, + "requires": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + } + }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -23095,6 +24473,12 @@ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true }, + "strip-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", + "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==", + "dev": true + }, "strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", @@ -23214,6 +24598,32 @@ "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true }, + "temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "dev": true + }, + "tempy": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", + "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", + "dev": true, + "requires": { + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + }, + "dependencies": { + "type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "dev": true + } + } + }, "terminal-link": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", @@ -23485,6 +24895,15 @@ "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", "dev": true }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "requires": { + "crypto-random-string": "^2.0.0" + } + }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -23497,6 +24916,22 @@ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", "dev": true }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz", + "integrity": "sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -23524,18 +24959,34 @@ } }, "use-callback-ref": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.2.5.tgz", - "integrity": "sha512-gN3vgMISAgacF7sqsLPByqoePooY3n2emTH59Ur5d/M8eg4WTWu1xp8i8DHjohftIyEx0S08RiYxbffr4j8Peg==", - "requires": {} + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.0.tgz", + "integrity": "sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w==", + "requires": { + "tslib": "^2.0.0" + }, + "dependencies": { + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + } + } }, "use-sidecar": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.0.5.tgz", - "integrity": "sha512-k9jnrjYNwN6xYLj1iaGhonDghfvmeTmYjAiGvOr7clwKfPjMXJf4/HOr7oT5tJwYafgp2tG2l3eZEOfoELiMcA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", + "integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==", "requires": { "detect-node-es": "^1.1.0", - "tslib": "^1.9.3" + "tslib": "^2.0.0" + }, + "dependencies": { + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + } } }, "util-deprecate": { @@ -24062,6 +25513,297 @@ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true }, + "workbox-background-sync": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.5.4.tgz", + "integrity": "sha512-0r4INQZMyPky/lj4Ou98qxcThrETucOde+7mRGJl13MPJugQNKeZQOdIJe/1AchOP23cTqHcN/YVpD6r8E6I8g==", + "dev": true, + "requires": { + "idb": "^7.0.1", + "workbox-core": "6.5.4" + } + }, + "workbox-broadcast-update": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.5.4.tgz", + "integrity": "sha512-I/lBERoH1u3zyBosnpPEtcAVe5lwykx9Yg1k6f8/BGEPGaMMgZrwVrqL1uA9QZ1NGGFoyE6t9i7lBjOlDhFEEw==", + "dev": true, + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-build": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.5.4.tgz", + "integrity": "sha512-kgRevLXEYvUW9WS4XoziYqZ8Q9j/2ziJYEtTrjdz5/L/cTUa2XfyMP2i7c3p34lgqJ03+mTiz13SdFef2POwbA==", + "dev": true, + "requires": { + "@apideck/better-ajv-errors": "^0.3.1", + "@babel/core": "^7.11.1", + "@babel/preset-env": "^7.11.0", + "@babel/runtime": "^7.11.2", + "@rollup/plugin-babel": "^5.2.0", + "@rollup/plugin-node-resolve": "^11.2.1", + "@rollup/plugin-replace": "^2.4.1", + "@surma/rollup-plugin-off-main-thread": "^2.2.3", + "ajv": "^8.6.0", + "common-tags": "^1.8.0", + "fast-json-stable-stringify": "^2.1.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", + "lodash": "^4.17.20", + "pretty-bytes": "^5.3.0", + "rollup": "^2.43.1", + "rollup-plugin-terser": "^7.0.0", + "source-map": "^0.8.0-beta.0", + "stringify-object": "^3.3.0", + "strip-comments": "^2.0.1", + "tempy": "^0.6.0", + "upath": "^1.2.0", + "workbox-background-sync": "6.5.4", + "workbox-broadcast-update": "6.5.4", + "workbox-cacheable-response": "6.5.4", + "workbox-core": "6.5.4", + "workbox-expiration": "6.5.4", + "workbox-google-analytics": "6.5.4", + "workbox-navigation-preload": "6.5.4", + "workbox-precaching": "6.5.4", + "workbox-range-requests": "6.5.4", + "workbox-recipes": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4", + "workbox-streams": "6.5.4", + "workbox-sw": "6.5.4", + "workbox-window": "6.5.4" + }, + "dependencies": { + "@apideck/better-ajv-errors": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz", + "integrity": "sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==", + "dev": true, + "requires": { + "json-schema": "^0.4.0", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" + } + }, + "ajv": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz", + "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dev": true, + "requires": { + "whatwg-url": "^7.0.0" + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, + "workbox-cacheable-response": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.5.4.tgz", + "integrity": "sha512-DCR9uD0Fqj8oB2TSWQEm1hbFs/85hXXoayVwFKLVuIuxwJaihBsLsp4y7J9bvZbqtPJ1KlCkmYVGQKrBU4KAug==", + "dev": true, + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-core": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.4.tgz", + "integrity": "sha512-OXYb+m9wZm8GrORlV2vBbE5EC1FKu71GGp0H4rjmxmF4/HLbMCoTFws87M3dFwgpmg0v00K++PImpNQ6J5NQ6Q==", + "dev": true + }, + "workbox-expiration": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.5.4.tgz", + "integrity": "sha512-jUP5qPOpH1nXtjGGh1fRBa1wJL2QlIb5mGpct3NzepjGG2uFFBn4iiEBiI9GUmfAFR2ApuRhDydjcRmYXddiEQ==", + "dev": true, + "requires": { + "idb": "^7.0.1", + "workbox-core": "6.5.4" + } + }, + "workbox-google-analytics": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.5.4.tgz", + "integrity": "sha512-8AU1WuaXsD49249Wq0B2zn4a/vvFfHkpcFfqAFHNHwln3jK9QUYmzdkKXGIZl9wyKNP+RRX30vcgcyWMcZ9VAg==", + "dev": true, + "requires": { + "workbox-background-sync": "6.5.4", + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "workbox-navigation-preload": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.5.4.tgz", + "integrity": "sha512-IIwf80eO3cr8h6XSQJF+Hxj26rg2RPFVUmJLUlM0+A2GzB4HFbQyKkrgD5y2d84g2IbJzP4B4j5dPBRzamHrng==", + "dev": true, + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-precaching": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.5.4.tgz", + "integrity": "sha512-hSMezMsW6btKnxHB4bFy2Qfwey/8SYdGWvVIKFaUm8vJ4E53JAY+U2JwLTRD8wbLWoP6OVUdFlXsTdKu9yoLTg==", + "dev": true, + "requires": { + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "workbox-range-requests": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-6.5.4.tgz", + "integrity": "sha512-Je2qR1NXCFC8xVJ/Lux6saH6IrQGhMpDrPXWZWWS8n/RD+WZfKa6dSZwU+/QksfEadJEr/NfY+aP/CXFFK5JFg==", + "dev": true, + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-recipes": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.5.4.tgz", + "integrity": "sha512-QZNO8Ez708NNwzLNEXTG4QYSKQ1ochzEtRLGaq+mr2PyoEIC1xFW7MrWxrONUxBFOByksds9Z4//lKAX8tHyUA==", + "dev": true, + "requires": { + "workbox-cacheable-response": "6.5.4", + "workbox-core": "6.5.4", + "workbox-expiration": "6.5.4", + "workbox-precaching": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "workbox-routing": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.4.tgz", + "integrity": "sha512-apQswLsbrrOsBUWtr9Lf80F+P1sHnQdYodRo32SjiByYi36IDyL2r7BH1lJtFX8fwNHDa1QOVY74WKLLS6o5Pg==", + "dev": true, + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-strategies": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.4.tgz", + "integrity": "sha512-DEtsxhx0LIYWkJBTQolRxG4EI0setTJkqR4m7r4YpBdxtWJH1Mbg01Cj8ZjNOO8etqfA3IZaOPHUxCs8cBsKLw==", + "dev": true, + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-streams": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.5.4.tgz", + "integrity": "sha512-FXKVh87d2RFXkliAIheBojBELIPnWbQdyDvsH3t74Cwhg0fDheL1T8BqSM86hZvC0ZESLsznSYWw+Va+KVbUzg==", + "dev": true, + "requires": { + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4" + } + }, + "workbox-sw": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.5.4.tgz", + "integrity": "sha512-vo2RQo7DILVRoH5LjGqw3nphavEjK4Qk+FenXeUsknKn14eCNedHOXWbmnvP4ipKhlE35pvJ4yl4YYf6YsJArA==", + "dev": true + }, + "workbox-webpack-plugin": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-webpack-plugin/-/workbox-webpack-plugin-6.5.4.tgz", + "integrity": "sha512-LmWm/zoaahe0EGmMTrSLUi+BjyR3cdGEfU3fS6PN1zKFYbqAKuQ+Oy/27e4VSXsyIwAw8+QDfk1XHNGtZu9nQg==", + "dev": true, + "requires": { + "fast-json-stable-stringify": "^2.1.0", + "pretty-bytes": "^5.4.1", + "upath": "^1.2.0", + "webpack-sources": "^1.4.3", + "workbox-build": "6.5.4" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + } + } + }, + "workbox-window": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-6.5.4.tgz", + "integrity": "sha512-HnLZJDwYBE+hpG25AQBO8RUWBJRaCsI9ksQJEp3aCOFCaG5kqaToAYXFRAHxzRluM2cQbGzdQF5rjKPWPA1fug==", + "dev": true, + "requires": { + "@types/trusted-types": "^2.0.2", + "workbox-core": "6.5.4" + } + }, "wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", diff --git a/package.json b/package.json index ba2f0d977..28ece56cd 100755 --- a/package.json +++ b/package.json @@ -15,9 +15,9 @@ "@babel/runtime": "7.16.0", "@sentry/browser": "6.13.3", "@stremio/stremio-colors": "4.0.1", - "@stremio/stremio-core-web": "0.43.0", + "@stremio/stremio-core-web": "0.44.6", "@stremio/stremio-icons": "3.0.5", - "@stremio/stremio-video": "0.0.20-rc.4", + "@stremio/stremio-video": "0.0.23", "a-color-picker": "1.2.1", "bowser": "2.11.0", "buffer": "6.0.3", @@ -25,13 +25,17 @@ "eventemitter3": "4.0.7", "filter-invalid-dom-props": "2.1.0", "lodash.debounce": "4.0.8", + "lodash.intersection": "4.4.0", "lodash.isequal": "4.5.0", "lodash.throttle": "4.1.1", + "magnet-uri": "6.2.0", "prop-types": "15.7.2", - "react": "16.12.0", - "react-dom": "16.12.0", - "react-focus-lock": "2.2.1", - "spatial-navigation-polyfill": "git+https://git@github.com/Stremio/spatial-navigation.git#64871b1422466f5f45d24ebc8bbd315b2ebab6a6" + "react": "18.2.0", + "react-dom": "18.2.0", + "react-focus-lock": "2.9.1", + "react-is": "18.2.0", + "spatial-navigation-polyfill": "git+https://git@github.com/Stremio/spatial-navigation.git#64871b1422466f5f45d24ebc8bbd315b2ebab6a6", + "url": "0.11.0" }, "devDependencies": { "@babel/core": "7.16.0", diff --git a/src/App/App.js b/src/App/App.js index a07435d2b..c0a79b727 100644 --- a/src/App/App.js +++ b/src/App/App.js @@ -3,30 +3,32 @@ require('spatial-navigation-polyfill'); const React = require('react'); const { Router } = require('stremio-router'); -const { Core, Shell, Chromecast, KeyboardShortcuts, ServicesProvider } = require('stremio/services'); +const { Core, Shell, Chromecast, DragAndDrop, KeyboardShortcuts, ServicesProvider } = require('stremio/services'); const { NotFound } = require('stremio/routes'); -const { ToastProvider, sanitizeLocationPath, CONSTANTS } = require('stremio/common'); -const CoreEventsToaster = require('./CoreEventsToaster'); +const { ToastProvider, CONSTANTS } = require('stremio/common'); +const ServicesToaster = require('./ServicesToaster'); +const DeepLinkHandler = require('./DeepLinkHandler'); const ErrorDialog = require('./ErrorDialog'); const routerViewsConfig = require('./routerViewsConfig'); const styles = require('./styles'); -window.core_imports = { - app_version: process.env.VERSION, - shell_version: null, - sanitize_location_path: sanitizeLocationPath -}; - const App = () => { const onPathNotMatch = React.useCallback(() => { return NotFound; }, []); - const services = React.useMemo(() => ({ - core: new Core(), - shell: new Shell(), - chromecast: new Chromecast(), - keyboardShortcuts: new KeyboardShortcuts() - }), []); + const services = React.useMemo(() => { + const core = new Core({ + appVersion: process.env.VERSION, + shellVersion: null + }); + return { + core, + shell: new Shell(), + chromecast: new Chromecast(), + keyboardShortcuts: new KeyboardShortcuts(), + dragAndDrop: new DragAndDrop({ core }) + }; + }, []); const [initialized, setInitialized] = React.useState(false); React.useEffect(() => { let prevPath = window.location.hash.slice(1); @@ -74,12 +76,14 @@ const App = () => { services.shell.start(); services.chromecast.start(); services.keyboardShortcuts.start(); + services.dragAndDrop.start(); window.services = services; return () => { services.core.stop(); services.shell.stop(); services.chromecast.stop(); services.keyboardShortcuts.stop(); + services.dragAndDrop.stop(); services.core.off('stateChanged', onCoreStateChanged); services.shell.off('stateChanged', onShellStateChanged); services.chromecast.off('stateChanged', onChromecastStateChange); @@ -93,6 +97,18 @@ const App = () => { action: 'PullAddonsFromAPI' } }); + services.core.transport.dispatch({ + action: 'Ctx', + args: { + action: 'PullUserFromAPI' + } + }); + services.core.transport.dispatch({ + action: 'Ctx', + args: { + action: 'SyncLibraryWithAPI' + } + }); } }, [initialized]); return ( @@ -104,7 +120,8 @@ const App = () => { : - + + { - const { core } = useServices(); - const toast = useToast(); - React.useEffect(() => { - const onCoreEvent = ({ event, args }) => { - if (event === 'Error') { - toast.show({ - type: 'error', - title: args.source.event, - message: args.error.message, - timeout: 4000 - }); - } - }; - core.transport.on('CoreEvent', onCoreEvent); - return () => { - core.transport.off('CoreEvent', onCoreEvent); - }; - }, []); - return null; -}; - -module.exports = CoreEventsToaster; diff --git a/src/App/DeepLinkHandler.js b/src/App/DeepLinkHandler.js new file mode 100644 index 000000000..9f055ef46 --- /dev/null +++ b/src/App/DeepLinkHandler.js @@ -0,0 +1,22 @@ +// Copyright (C) 2017-2022 Smart code 203358507 + +const React = require('react'); +const { withCoreSuspender, useStreamingServer } = require('stremio/common'); + +const DeepLinkHandler = () => { + const streamingServer = useStreamingServer(); + React.useEffect(() => { + if (streamingServer.torrent !== null) { + const [, { type, content }] = streamingServer.torrent; + if (type === 'Ready') { + const [, deepLinks] = content; + if (typeof deepLinks.metaDetailsVideos === 'string') { + window.location = deepLinks.metaDetailsVideos; + } + } + } + }, [streamingServer.torrent]); + return null; +}; + +module.exports = withCoreSuspender(DeepLinkHandler); diff --git a/src/App/ServicesToaster.js b/src/App/ServicesToaster.js new file mode 100644 index 000000000..43b076c9a --- /dev/null +++ b/src/App/ServicesToaster.js @@ -0,0 +1,69 @@ +// Copyright (C) 2017-2022 Smart code 203358507 + +const React = require('react'); +const { useServices } = require('stremio/services'); +const { useToast } = require('stremio/common'); + +const ServicesToaster = () => { + const { core, dragAndDrop } = useServices(); + const toast = useToast(); + React.useEffect(() => { + const onCoreEvent = ({ event, args }) => { + switch (event) { + case 'Error': { + if (args.source.event === 'UserPulledFromAPI' && args.source.args.uid === null) { + break; + } + + if (args.source.event === 'LibrarySyncWithAPIPlanned' && args.source.args.uid === null) { + break; + } + + toast.show({ + type: 'error', + title: args.source.event, + message: args.error.message, + timeout: 4000, + dataset: { + type: 'CoreEvent' + } + }); + break; + } + case 'TorrentParsed': { + toast.show({ + type: 'success', + title: 'Torrent file parsed', + timeout: 4000 + }); + break; + } + case 'MagnetParsed': { + toast.show({ + type: 'success', + title: 'Magnet link parsed', + timeout: 4000 + }); + break; + } + } + }; + const onDragAndDropError = (error) => { + toast.show({ + type: 'error', + title: error.message, + message: error.file?.name, + timeout: 4000 + }); + }; + core.transport.on('CoreEvent', onCoreEvent); + dragAndDrop.on('error', onDragAndDropError); + return () => { + core.transport.off('CoreEvent', onCoreEvent); + dragAndDrop.off('error', onDragAndDropError); + }; + }, []); + return null; +}; + +module.exports = ServicesToaster; diff --git a/src/App/styles.less b/src/App/styles.less index e9a01575a..1d24672ab 100644 --- a/src/App/styles.less +++ b/src/App/styles.less @@ -5,6 +5,7 @@ @import (reference) '~@stremio/stremio-colors/less/stremio-colors.less'; :global { + @import (once, less) '~stremio/common/animations.less'; @import (once, less) '~stremio-router/styles.css'; } diff --git a/src/common/AddonDetailsModal/AddonDetailsModal.js b/src/common/AddonDetailsModal/AddonDetailsModal.js index 25a4acd54..2c417a142 100644 --- a/src/common/AddonDetailsModal/AddonDetailsModal.js +++ b/src/common/AddonDetailsModal/AddonDetailsModal.js @@ -3,6 +3,7 @@ const React = require('react'); const PropTypes = require('prop-types'); const ModalDialog = require('stremio/common/ModalDialog'); +const { withCoreSuspender } = require('stremio/common/CoreSuspender'); const { useServices } = require('stremio/services'); const AddonDetailsWithRemoteAndLocalAddon = withRemoteAndLocalAddon(require('./AddonDetails')); const useAddonDetails = require('./useAddonDetails'); @@ -144,4 +145,18 @@ AddonDetailsModal.propTypes = { onCloseRequest: PropTypes.func }; -module.exports = AddonDetailsModal; +const AddonDetailsModalFallback = ({ onCloseRequest }) => ( + +
+ Loading addon manifest +
+
+); + +AddonDetailsModalFallback.propTypes = AddonDetailsModal.propTypes; + +module.exports = withCoreSuspender(AddonDetailsModal, AddonDetailsModalFallback); diff --git a/src/common/AddonDetailsModal/useAddonDetails.js b/src/common/AddonDetailsModal/useAddonDetails.js index b0bf251d3..e13ac1007 100644 --- a/src/common/AddonDetailsModal/useAddonDetails.js +++ b/src/common/AddonDetailsModal/useAddonDetails.js @@ -3,12 +3,6 @@ const React = require('react'); const useModelState = require('stremio/common/useModelState'); -const init = () => ({ - selected: null, - localAddon: null, - remoteAddon: null -}); - const useAddonDetails = (transportUrl) => { const action = React.useMemo(() => { if (typeof transportUrl === 'string') { @@ -27,7 +21,7 @@ const useAddonDetails = (transportUrl) => { }; } }, [transportUrl]); - return useModelState({ model: 'addon_details', action, init }); + return useModelState({ model: 'addon_details', action }); }; module.exports = useAddonDetails; diff --git a/src/common/CoreSuspender.js b/src/common/CoreSuspender.js new file mode 100644 index 000000000..94ec7475f --- /dev/null +++ b/src/common/CoreSuspender.js @@ -0,0 +1,78 @@ +// Copyright (C) 2017-2022 Smart code 203358507 + +const React = require('react'); +const { useServices } = require('stremio/services'); + +const CoreSuspenderContext = React.createContext(null); + +CoreSuspenderContext.displayName = 'CoreSuspenderContext'; + +function wrapPromise(promise) { + let status = 'pending'; + let result; + const suspender = promise.then( + (resp) => { + status = 'success'; + result = resp; + }, + (error) => { + status = 'error'; + result = error; + } + ); + return { + read() { + if (status === 'pending') { + throw suspender; + } else if (status === 'error') { + throw result; + } else if (status === 'success') { + return result; + } + } + }; +} + +const useCoreSuspender = () => { + return React.useContext(CoreSuspenderContext); +}; + +const withCoreSuspender = (Component, Fallback = () => { }) => { + return function withCoreSuspender(props) { + const { core } = useServices(); + const parentSuspender = useCoreSuspender(); + const [render, setRender] = React.useState(parentSuspender === null); + const statesRef = React.useRef({}); + const streamsRef = React.useRef({}); + const getState = React.useCallback((model) => { + if (!statesRef.current[model]) { + statesRef.current[model] = wrapPromise(core.transport.getState(model)); + } + + return statesRef.current[model].read(); + }, []); + const decodeStream = React.useCallback((stream) => { + if (!streamsRef.current[stream]) { + streamsRef.current[stream] = wrapPromise(core.transport.decodeStream(stream)); + } + + return streamsRef.current[stream].read(); + }, []); + const suspender = React.useMemo(() => ({ getState, decodeStream }), []); + React.useLayoutEffect(() => { + if (!render) { + setRender(true); + } + }, []); + return render ? + }> + + + + + : + null; + }; +}; + +module.exports = { withCoreSuspender, useCoreSuspender }; diff --git a/src/common/DelayedRenderer/DelayedRenderer.js b/src/common/DelayedRenderer/DelayedRenderer.js new file mode 100644 index 000000000..eb4bea81f --- /dev/null +++ b/src/common/DelayedRenderer/DelayedRenderer.js @@ -0,0 +1,23 @@ +// Copyright (C) 2017-2022 Smart code 203358507 + +const React = require('react'); +const PropTypes = require('prop-types'); + +const DelayedRenderer = ({ children, delay }) => { + const [render, setRender] = React.useState(false); + React.useEffect(() => { + const timeout = setTimeout(() => { + setRender(true); + }, delay); + return () => { + clearTimeout(timeout); + }; + }, []); + return render ? children : null; +}; + +DelayedRenderer.propTypes = { + children: PropTypes.node +}; + +module.exports = DelayedRenderer; diff --git a/src/common/DelayedRenderer/index.js b/src/common/DelayedRenderer/index.js new file mode 100644 index 000000000..97d3811dd --- /dev/null +++ b/src/common/DelayedRenderer/index.js @@ -0,0 +1,5 @@ +// Copyright (C) 2017-2022 Smart code 203358507 + +const DelayedRenderer = require('./DelayedRenderer'); + +module.exports = DelayedRenderer; diff --git a/src/common/NavBar/HorizontalNavBar/NavMenu/NavMenu.js b/src/common/NavBar/HorizontalNavBar/NavMenu/NavMenu.js index 3a7b3a73c..7e511ee0d 100644 --- a/src/common/NavBar/HorizontalNavBar/NavMenu/NavMenu.js +++ b/src/common/NavBar/HorizontalNavBar/NavMenu/NavMenu.js @@ -3,22 +3,14 @@ const React = require('react'); const PropTypes = require('prop-types'); const classnames = require('classnames'); -const Icon = require('@stremio/stremio-icons/dom'); const { useRouteFocused } = require('stremio-router'); -const { useServices } = require('stremio/services'); -const Button = require('stremio/common/Button'); const Popup = require('stremio/common/Popup'); const useBinaryState = require('stremio/common/useBinaryState'); -const useFullscreen = require('stremio/common/useFullscreen'); -const useProfile = require('stremio/common/useProfile'); -const styles = require('./styles'); +const NavMenuContent = require('./NavMenuContent'); const NavMenu = (props) => { - const { core } = useServices(); const routeFocused = useRouteFocused(); - const profile = useProfile(); const [menuOpen, , closeMenu, toggleMenu] = useBinaryState(false); - const [fullscreen, requestFullscreen, exitFullscreen] = useFullscreen(); const popupLabelOnClick = React.useCallback((event) => { if (!event.nativeEvent.togglePopupPrevented) { toggleMenu(); @@ -27,14 +19,6 @@ const NavMenu = (props) => { const popupMenuOnClick = React.useCallback((event) => { event.nativeEvent.togglePopupPrevented = true; }, []); - const logoutButtonOnClick = React.useCallback(() => { - core.transport.dispatch({ - action: 'Ctx', - args: { - action: 'Logout' - } - }); - }, []); const renderLabel = React.useMemo(() => ({ ref, className, children }) => ( props.renderLabel({ ref, @@ -44,65 +28,8 @@ const NavMenu = (props) => { }) ), [menuOpen, popupLabelOnClick, props.renderLabel]); const renderMenu = React.useCallback(() => ( -
-
-
-
-
{profile.auth === null ? 'Anonymous user' : profile.auth.user.email}
-
- -
-
- -
-
- - - - - -
-
- - - -
-
- ), [profile, fullscreen]); + + ), []); React.useEffect(() => { if (!routeFocused) { closeMenu(); @@ -111,6 +38,7 @@ const NavMenu = (props) => { return ( { + const { core } = useServices(); + const profile = useProfile(); + const { createTorrentFromMagnet } = useTorrent(); + const [fullscreen, requestFullscreen, exitFullscreen] = useFullscreen(); + const logoutButtonOnClick = React.useCallback(() => { + core.transport.dispatch({ + action: 'Ctx', + args: { + action: 'Logout' + } + }); + }, []); + const onPlayMagnetLinkClick = React.useCallback(async () => { + try { + const clipboardText = await navigator.clipboard.readText(); + createTorrentFromMagnet(clipboardText); + } catch(e) { + console.error(e); + } + }, []); + return ( +
+
+
+
+
{profile.auth === null ? 'Anonymous user' : profile.auth.user.email}
+
+ +
+
+ +
+
+ + + + +
+
+ + + +
+
+ ); +}; + +NavMenuContent.propTypes = { + onClick: PropTypes.func +}; + +const NavMenuContentFallback = () => ( +
+); + +module.exports = withCoreSuspender(NavMenuContent, NavMenuContentFallback); diff --git a/src/common/NavBar/HorizontalNavBar/SearchBar/SearchBar.js b/src/common/NavBar/HorizontalNavBar/SearchBar/SearchBar.js index 1d1268d17..dd76c8e84 100644 --- a/src/common/NavBar/HorizontalNavBar/SearchBar/SearchBar.js +++ b/src/common/NavBar/HorizontalNavBar/SearchBar/SearchBar.js @@ -7,16 +7,25 @@ const Icon = require('@stremio/stremio-icons/dom'); const { useRouteFocused } = require('stremio-router'); const Button = require('stremio/common/Button'); const TextInput = require('stremio/common/TextInput'); +const useTorrent = require('stremio/common/useTorrent'); +const { withCoreSuspender } = require('stremio/common/CoreSuspender'); const styles = require('./styles'); const SearchBar = ({ className, query, active }) => { const routeFocused = useRouteFocused(); + const { createTorrentFromMagnet } = useTorrent(); const searchInputRef = React.useRef(null); const searchBarOnClick = React.useCallback(() => { if (!active) { window.location = '#/search'; } }, [active]); + const queryInputOnChange = React.useCallback(() => { + try { + createTorrentFromMagnet(searchInputRef.current.value); + // eslint-disable-next-line no-empty + } catch { } + }, []); const queryInputOnSubmit = React.useCallback(() => { if (searchInputRef.current !== null) { const queryParams = new URLSearchParams([['search', searchInputRef.current.value]]); @@ -40,6 +49,7 @@ const SearchBar = ({ className, query, active }) => { placeholder={'Search or paste link'} defaultValue={query} tabIndex={-1} + onChange={queryInputOnChange} onSubmit={queryInputOnSubmit} /> : @@ -60,4 +70,17 @@ SearchBar.propTypes = { active: PropTypes.bool }; -module.exports = SearchBar; +const SearchBarFallback = ({ className }) => ( + +); + +SearchBarFallback.propTypes = SearchBar.propTypes; + +module.exports = withCoreSuspender(SearchBar, SearchBarFallback); diff --git a/src/common/StreamingServerWarning/StreamingServerWarning.js b/src/common/StreamingServerWarning/StreamingServerWarning.js index 3ffff03c4..b0775b2e6 100644 --- a/src/common/StreamingServerWarning/StreamingServerWarning.js +++ b/src/common/StreamingServerWarning/StreamingServerWarning.js @@ -6,6 +6,7 @@ const PropTypes = require('prop-types'); const classnames = require('classnames'); const Button = require('stremio/common/Button'); const useProfile = require('stremio/common/useProfile'); +const { withCoreSuspender } = require('stremio/common/CoreSuspender'); const styles = require('./styles'); const StreamingServerWarning = ({ className }) => { @@ -39,6 +40,12 @@ const StreamingServerWarning = ({ className }) => { } }); }, [profile.settings]); + + if (!isNaN(profile.settings.streamingServerWarningDismissed.getTime()) && + profile.settings.streamingServerWarningDismissed.getTime() > Date.now()) { + return null; + } + return (
Streaming server is not available.
@@ -56,4 +63,4 @@ StreamingServerWarning.propTypes = { className: PropTypes.string }; -module.exports = StreamingServerWarning; +module.exports = withCoreSuspender(StreamingServerWarning); diff --git a/src/common/Toast/ToastProvider.js b/src/common/Toast/ToastProvider.js index 571f79c14..b022c1665 100644 --- a/src/common/Toast/ToastProvider.js +++ b/src/common/Toast/ToastProvider.js @@ -28,32 +28,48 @@ const ToastProvider = ({ className, children }) => { clearTimeout(event.dataset.id); dispatch({ type: 'remove', id: event.dataset.id }); }, []); - const toast = React.useMemo(() => ({ - show: (item) => { - const timeout = typeof item.timeout === 'number' && !isNaN(item.timeout) ? - item.timeout - : - DEFAULT_TIMEOUT; - const id = setTimeout(() => { - dispatch({ type: 'remove', id }); - }, timeout); - dispatch({ - type: 'add', - item: { - ...item, - id, - dataset: { - ...item.dataset, - id - }, - onClose: itemOnClose + const toast = React.useMemo(() => { + const filters = []; + return { + addFilter: (filter) => { + filters.push(filter); + }, + removeFilter: (filter) => { + const index = filters.indexOf(filter); + if (index > -1) { + filters.splice(index, 1); } - }); - }, - clear: () => { - dispatch({ type: 'clear' }); - } - }), []); + }, + show: (item) => { + if (filters.some((filter) => filter(item))) { + return; + } + + const timeout = typeof item.timeout === 'number' && !isNaN(item.timeout) ? + item.timeout + : + DEFAULT_TIMEOUT; + const id = setTimeout(() => { + dispatch({ type: 'remove', id }); + }, timeout); + dispatch({ + type: 'add', + item: { + ...item, + id, + dataset: { + ...item.dataset, + id + }, + onClose: itemOnClose + } + }); + }, + clear: () => { + dispatch({ type: 'clear' }); + } + }; + }, []); return ( {container instanceof HTMLElement ? children : null} diff --git a/src/common/animations.less b/src/common/animations.less new file mode 100644 index 000000000..9173a625b --- /dev/null +++ b/src/common/animations.less @@ -0,0 +1,22 @@ +// Copyright (C) 2017-2022 Smart code 203358507 + +:global(.animation-fade-in) { + :local { + animation-name: fade-in; + } + + animation-timing-function: ease-in-out; + animation-duration: 100ms; +} + +@keyframes fade-in { + 0% { + opacity: 0.6; + transform: translateY(0.2vh); + } + + 100% { + opacity: 1; + transform: translateY(0); + } +} \ No newline at end of file diff --git a/src/common/index.js b/src/common/index.js index 1ee08108c..90c266e64 100644 --- a/src/common/index.js +++ b/src/common/index.js @@ -4,6 +4,7 @@ const AddonDetailsModal = require('./AddonDetailsModal'); const Button = require('./Button'); const Checkbox = require('./Checkbox'); const ColorInput = require('./ColorInput'); +const DelayedRenderer = require('./DelayedRenderer'); const Image = require('./Image'); const LibItem = require('./LibItem'); const MainNavBars = require('./MainNavBars'); @@ -24,27 +25,27 @@ const TextInput = require('./TextInput'); const { ToastProvider, useToast } = require('./Toast'); const comparatorWithPriorities = require('./comparatorWithPriorities'); const CONSTANTS = require('./CONSTANTS'); +const { withCoreSuspender, useCoreSuspender } = require('./CoreSuspender'); const getVisibleChildrenRange = require('./getVisibleChildrenRange'); const languageNames = require('./languageNames'); const routesRegexp = require('./routesRegexp'); -const sanitizeLocationPath = require('./sanitizeLocationPath'); const useAnimationFrame = require('./useAnimationFrame'); const useBinaryState = require('./useBinaryState'); -const useDeepEqualEffect = require('./useDeepEqualEffect'); const useDeepEqualMemo = require('./useDeepEqualMemo'); -const useDeepEqualState = require('./useDeepEqualState'); const useFullscreen = require('./useFullscreen'); const useLiveRef = require('./useLiveRef'); const useModelState = require('./useModelState'); const useOnScrollToBottom = require('./useOnScrollToBottom'); const useProfile = require('./useProfile'); const useStreamingServer = require('./useStreamingServer'); +const useTorrent = require('./useTorrent'); module.exports = { AddonDetailsModal, Button, Checkbox, ColorInput, + DelayedRenderer, Image, LibItem, MainNavBars, @@ -67,19 +68,19 @@ module.exports = { useToast, comparatorWithPriorities, CONSTANTS, + withCoreSuspender, + useCoreSuspender, getVisibleChildrenRange, languageNames, routesRegexp, - sanitizeLocationPath, useAnimationFrame, useBinaryState, - useDeepEqualEffect, useDeepEqualMemo, - useDeepEqualState, useFullscreen, useLiveRef, useModelState, useOnScrollToBottom, useProfile, - useStreamingServer + useStreamingServer, + useTorrent }; diff --git a/src/common/routesRegexp.js b/src/common/routesRegexp.js index d15bc7d46..21ad98662 100644 --- a/src/common/routesRegexp.js +++ b/src/common/routesRegexp.js @@ -26,7 +26,7 @@ const routesRegexp = { urlParamsNames: [] }, metadetails: { - regexp: /^\/metadetails\/([^/]*)\/([^/]*)(?:\/([^/]*))?$/, + regexp: /^\/(?:metadetails|detail)\/([^/]*)\/([^/]*)(?:\/([^/]*))?$/, urlParamsNames: ['type', 'id', 'videoId'] }, addons: { diff --git a/src/common/sanitizeLocationPath.js b/src/common/sanitizeLocationPath.js deleted file mode 100644 index e45f1e15b..000000000 --- a/src/common/sanitizeLocationPath.js +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (C) 2017-2022 Smart code 203358507 - -const UrlUtils = require('url'); -const routesRegexp = require('stremio/common/routesRegexp'); - -const sanitizeLocationPath = (path) => { - const { href, pathname, search } = UrlUtils.parse(path); - if (typeof pathname === 'string') { - const matches = pathname.match(routesRegexp.player.regexp); - if (matches) { - if (typeof matches[2] === 'string') { - return `/player/***/***/${matches[3]}/${matches[4]}/${matches[5]}/${matches[6]}${typeof search === 'string' ? search : ''}`; - } else { - return `/player/***${typeof search === 'string' ? search : ''}`; - } - } - } - - return href; -}; - -module.exports = sanitizeLocationPath; diff --git a/src/common/useDeepEqualEffect.js b/src/common/useDeepEqualEffect.js deleted file mode 100644 index 095576356..000000000 --- a/src/common/useDeepEqualEffect.js +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (C) 2017-2022 Smart code 203358507 - -const React = require('react'); -const useDeepEqualMemo = require('stremio/common/useDeepEqualMemo'); - -const useDeepEqualEffect = (cb, deps) => { - React.useEffect(cb, [useDeepEqualMemo(() => ({}), deps)]); -}; - -module.exports = useDeepEqualEffect; diff --git a/src/common/useDeepEqualState.js b/src/common/useDeepEqualState.js deleted file mode 100644 index edd762b46..000000000 --- a/src/common/useDeepEqualState.js +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (C) 2017-2022 Smart code 203358507 - -const React = require('react'); -const isEqual = require('lodash.isequal'); - -const useDeepEqualState = (initialState) => { - return React.useReducer( - (prevState, nextState) => { - return isEqual(prevState, nextState) ? - prevState - : - nextState; - }, - undefined, - () => { - return typeof initialState === 'function' ? - initialState() - : - initialState; - } - ); -}; - -module.exports = useDeepEqualState; diff --git a/src/common/useModelState.js b/src/common/useModelState.js index 75e2ab634..a2a630237 100644 --- a/src/common/useModelState.js +++ b/src/common/useModelState.js @@ -3,16 +3,19 @@ const React = require('react'); const throttle = require('lodash.throttle'); const isEqual = require('lodash.isequal'); +const intersection = require('lodash.intersection'); +const { useCoreSuspender } = require('stremio/common/CoreSuspender'); const { useRouteFocused } = require('stremio-router'); const { useServices } = require('stremio/services'); -const useModelState = ({ init, action, ...args }) => { +const useModelState = ({ action, ...args }) => { const { core } = useServices(); const routeFocused = useRouteFocused(); const mountedRef = React.useRef(false); - const [model, timeout, map] = React.useMemo(() => { - return [args.model, args.timeout, args.map]; + const [model, timeout, map, deps] = React.useMemo(() => { + return [args.model, args.timeout, args.map, args.deps]; }, []); + const { getState } = useCoreSuspender(); const [state, setState] = React.useReducer( (prevState, nextState) => { return Object.keys(prevState).reduce((result, key) => { @@ -22,35 +25,41 @@ const useModelState = ({ init, action, ...args }) => { }, undefined, () => { - return typeof init === 'function' ? - init() - : - init; + if (typeof map === 'function') { + return map(getState(model)); + } else { + return getState(model); + } } ); - React.useLayoutEffect(() => { + React.useInsertionEffect(() => { if (action) { core.transport.dispatch(action, model); } }, [action]); - React.useLayoutEffect(() => { + React.useInsertionEffect(() => { return () => { core.transport.dispatch({ action: 'Unload' }, model); }; }, []); - React.useLayoutEffect(() => { - const onNewStateThrottled = throttle(() => { - const state = core.transport.getState(model); + React.useInsertionEffect(() => { + const onNewState = async (models) => { + if (models.indexOf(model) === -1 && (!Array.isArray(deps) || intersection(deps, models).length === 0)) { + return; + } + + const state = await core.transport.getState(model); if (typeof map === 'function') { setState(map(state)); } else { setState(state); } - }, timeout); + }; + const onNewStateThrottled = throttle(onNewState, timeout); if (routeFocused) { core.transport.on('NewState', onNewStateThrottled); if (mountedRef.current) { - onNewStateThrottled.call(); + onNewState([model]); } } return () => { @@ -58,7 +67,7 @@ const useModelState = ({ init, action, ...args }) => { core.transport.off('NewState', onNewStateThrottled); }; }, [routeFocused]); - React.useLayoutEffect(() => { + React.useInsertionEffect(() => { mountedRef.current = true; }, []); return state; diff --git a/src/common/useProfile.js b/src/common/useProfile.js index cbd60b36c..371a4df12 100644 --- a/src/common/useProfile.js +++ b/src/common/useProfile.js @@ -1,7 +1,5 @@ // Copyright (C) 2017-2022 Smart code 203358507 -const React = require('react'); -const { useServices } = require('stremio/services'); const useModelState = require('stremio/common/useModelState'); const map = (ctx) => ({ @@ -18,12 +16,7 @@ const map = (ctx) => ({ }); const useProfile = () => { - const { core } = useServices(); - const init = React.useCallback(() => { - const ctx = core.transport.getState('ctx'); - return map(ctx); - }, []); - return useModelState({ model: 'ctx', init, map }); + return useModelState({ model: 'ctx', map }); }; module.exports = useProfile; diff --git a/src/common/useStreamingServer.js b/src/common/useStreamingServer.js index a8cf71596..00dd0cee1 100644 --- a/src/common/useStreamingServer.js +++ b/src/common/useStreamingServer.js @@ -1,15 +1,9 @@ // Copyright (C) 2017-2022 Smart code 203358507 -const React = require('react'); -const { useServices } = require('stremio/services'); const useModelState = require('stremio/common/useModelState'); const useStreamingServer = () => { - const { core } = useServices(); - const init = React.useCallback(() => { - return core.transport.getState('streaming_server'); - }, []); - return useModelState({ model: 'streaming_server', init }); + return useModelState({ model: 'streaming_server' }); }; module.exports = useStreamingServer; diff --git a/src/common/useTorrent.js b/src/common/useTorrent.js new file mode 100644 index 000000000..6ecfe4de6 --- /dev/null +++ b/src/common/useTorrent.js @@ -0,0 +1,50 @@ +// Copyright (C) 2017-2022 Smart code 203358507 + +const React = require('react'); +const magnet = require('magnet-uri'); +const { useServices } = require('stremio/services'); +const useToast = require('stremio/common/Toast/useToast'); +const useStreamingServer = require('stremio/common/useStreamingServer'); + +const useTorrent = () => { + const { core } = useServices(); + const streamingServer = useStreamingServer(); + const toast = useToast(); + const createTorrentTimeout = React.useRef(null); + const createTorrentFromMagnet = React.useCallback((text) => { + const parsed = magnet.decode(text); + if (parsed && typeof parsed.infoHash === 'string') { + core.transport.dispatch({ + action: 'StreamingServer', + args: { + action: 'CreateTorrent', + args: text + } + }); + clearTimeout(createTorrentTimeout.current); + createTorrentTimeout.current = setTimeout(() => { + toast.show({ + type: 'error', + title: 'It\'s taking a long time to get metadata from the torrent.', + timeout: 10000 + }); + }, 10000); + } + }, []); + React.useEffect(() => { + if (streamingServer.torrent !== null) { + const [, { type }] = streamingServer.torrent; + if (type === 'Ready') { + clearTimeout(createTorrentTimeout.current); + } + } + }, [streamingServer.torrent]); + React.useEffect(() => { + return () => clearTimeout(createTorrentTimeout.current); + }, []); + return { + createTorrentFromMagnet + }; +}; + +module.exports = useTorrent; diff --git a/src/index.html b/src/index.html index 9367c7652..79a09fbb5 100644 --- a/src/index.html +++ b/src/index.html @@ -4,6 +4,8 @@ + + diff --git a/src/index.js b/src/index.js index f148f603b..27840b0d0 100755 --- a/src/index.js +++ b/src/index.js @@ -12,10 +12,11 @@ if (browser?.platform?.type === 'desktop') { } const React = require('react'); -const ReactDOM = require('react-dom'); +const ReactDOM = require('react-dom/client'); const App = require('./App'); -ReactDOM.render(, document.getElementById('app')); +const root = ReactDOM.createRoot(document.getElementById('app')); +root.render(); if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { window.addEventListener('load', () => { diff --git a/src/router/RouteFocusedContext/RouteFocusedContext.js b/src/router/RouteFocusedContext/RouteFocusedContext.js index 22b283398..520b6ec28 100644 --- a/src/router/RouteFocusedContext/RouteFocusedContext.js +++ b/src/router/RouteFocusedContext/RouteFocusedContext.js @@ -2,7 +2,7 @@ const React = require('react'); -const RouteFocusedContext = React.createContext(false); +const RouteFocusedContext = React.createContext(true); RouteFocusedContext.displayName = 'RouteFocusedContext'; diff --git a/src/routes/Addons/Addons.js b/src/routes/Addons/Addons.js index 1a889ae50..aa513daaf 100644 --- a/src/routes/Addons/Addons.js +++ b/src/routes/Addons/Addons.js @@ -2,8 +2,9 @@ const React = require('react'); const PropTypes = require('prop-types'); +const classnames = require('classnames'); const Icon = require('@stremio/stremio-icons/dom'); -const { AddonDetailsModal, Button, Image, Multiselect, MainNavBars, TextInput, SearchBar, SharePrompt, ModalDialog, useBinaryState } = require('stremio/common'); +const { AddonDetailsModal, Button, Image, Multiselect, MainNavBars, TextInput, SearchBar, SharePrompt, ModalDialog, useBinaryState, withCoreSuspender } = require('stremio/common'); const Addon = require('./Addon'); const useInstalledAddons = require('./useInstalledAddons'); const useRemoteAddons = require('./useRemoteAddons'); @@ -118,7 +119,7 @@ const Addons = ({ urlParams, queryParams }) => { .map((addon, index) => ( { .map((addon, index) => ( ( + +); + +module.exports = withCoreSuspender(Addons, AddonsFallback); diff --git a/src/routes/Addons/useInstalledAddons.js b/src/routes/Addons/useInstalledAddons.js index 8be193982..fc649c772 100644 --- a/src/routes/Addons/useInstalledAddons.js +++ b/src/routes/Addons/useInstalledAddons.js @@ -1,14 +1,9 @@ // Copyright (C) 2017-2022 Smart code 203358507 const React = require('react'); -const { useServices } = require('stremio/services'); const { useModelState } = require('stremio/common'); const useInstalledAddons = (urlParams) => { - const { core } = useServices(); - const init = React.useMemo(() => { - return core.transport.getState('installed_addons'); - }, []); const action = React.useMemo(() => { if (typeof urlParams.transportUrl !== 'string' && typeof urlParams.catalogId !== 'string') { return { @@ -28,7 +23,7 @@ const useInstalledAddons = (urlParams) => { }; } }, [urlParams]); - return useModelState({ model: 'installed_addons', action, init }); + return useModelState({ model: 'installed_addons', action }); }; module.exports = useInstalledAddons; diff --git a/src/routes/Addons/useRemoteAddons.js b/src/routes/Addons/useRemoteAddons.js index f6bc023d1..b3f74516e 100644 --- a/src/routes/Addons/useRemoteAddons.js +++ b/src/routes/Addons/useRemoteAddons.js @@ -3,15 +3,6 @@ const React = require('react'); const { useModelState } = require('stremio/common'); -const init = () => ({ - selected: null, - selectable: { - catalogs: [], - types: [] - }, - catalog: null, -}); - const useRemoteAddons = (urlParams) => { const action = React.useMemo(() => { if (typeof urlParams.type === 'string' && typeof urlParams.transportUrl === 'string' && typeof urlParams.catalogId === 'string') { @@ -38,7 +29,7 @@ const useRemoteAddons = (urlParams) => { }; } }, [urlParams]); - return useModelState({ model: 'remote_addons', action, init }); + return useModelState({ model: 'remote_addons', action, deps: ['ctx'] }); }; module.exports = useRemoteAddons; diff --git a/src/routes/Board/Board.js b/src/routes/Board/Board.js index 0aca6964b..d01666448 100644 --- a/src/routes/Board/Board.js +++ b/src/routes/Board/Board.js @@ -3,7 +3,7 @@ const React = require('react'); const classnames = require('classnames'); const debounce = require('lodash.debounce'); -const { MainNavBars, MetaRow, LibItem, MetaItem, StreamingServerWarning, useProfile, useStreamingServer, getVisibleChildrenRange } = require('stremio/common'); +const { MainNavBars, MetaRow, LibItem, MetaItem, StreamingServerWarning, useStreamingServer, withCoreSuspender, getVisibleChildrenRange } = require('stremio/common'); const useBoard = require('./useBoard'); const useContinueWatchingPreview = require('./useContinueWatchingPreview'); const styles = require('./styles'); @@ -11,7 +11,6 @@ const styles = require('./styles'); const THRESHOLD = 5; const Board = () => { - const profile = useProfile(); const streamingServer = useStreamingServer(); const continueWatchingPreview = useContinueWatchingPreview(); const [board, loadBoardRows] = useBoard(); @@ -42,7 +41,7 @@ const Board = () => { { continueWatchingPreview.libraryItems.length > 0 ? { return ( { return ( { return ( @@ -91,8 +90,7 @@ const Board = () => {
{ - streamingServer.settings !== null && streamingServer.settings.type === 'Err' && - (isNaN(profile.settings.streamingServerWarningDismissed.getTime()) || profile.settings.streamingServerWarningDismissed.getTime() < Date.now()) ? + streamingServer.settings !== null && streamingServer.settings.type === 'Err' ? : null @@ -101,4 +99,10 @@ const Board = () => { ); }; -module.exports = Board; +const BoardFallback = () => ( +
+ +
+); + +module.exports = withCoreSuspender(Board, BoardFallback); diff --git a/src/routes/Board/useBoard.js b/src/routes/Board/useBoard.js index 1233b9a10..6e3540ab6 100644 --- a/src/routes/Board/useBoard.js +++ b/src/routes/Board/useBoard.js @@ -4,11 +4,6 @@ const React = require('react'); const { useServices } = require('stremio/services'); const { useModelState } = require('stremio/common'); -const init = () => ({ - selected: null, - catalogs: [] -}); - const useBoard = () => { const { core } = useServices(); const action = React.useMemo(() => ({ @@ -27,7 +22,7 @@ const useBoard = () => { } }, 'board'); }, []); - const board = useModelState({ model: 'board', timeout: 1500, action, init }); + const board = useModelState({ model: 'board', timeout: 1500, action }); return [board, loadRange]; }; diff --git a/src/routes/Board/useContinueWatchingPreview.js b/src/routes/Board/useContinueWatchingPreview.js index a505ef737..f7f623587 100644 --- a/src/routes/Board/useContinueWatchingPreview.js +++ b/src/routes/Board/useContinueWatchingPreview.js @@ -1,15 +1,9 @@ // Copyright (C) 2017-2022 Smart code 203358507 -const React = require('react'); -const { useServices } = require('stremio/services'); const { useModelState } = require('stremio/common'); const useContinueWatchingPreview = () => { - const { core } = useServices(); - const init = React.useMemo(() => { - return core.transport.getState('continue_watching_preview'); - }, []); - return useModelState({ model: 'continue_watching_preview', init }); + return useModelState({ model: 'continue_watching_preview' }); }; module.exports = useContinueWatchingPreview; diff --git a/src/routes/Discover/Discover.js b/src/routes/Discover/Discover.js index d2e2ce462..688eb072a 100644 --- a/src/routes/Discover/Discover.js +++ b/src/routes/Discover/Discover.js @@ -5,7 +5,7 @@ const PropTypes = require('prop-types'); const classnames = require('classnames'); const Icon = require('@stremio/stremio-icons/dom'); const { useServices } = require('stremio/services'); -const { AddonDetailsModal, Button, MainNavBars, MetaItem, Image, MetaPreview, Multiselect, ModalDialog, CONSTANTS, useBinaryState, useOnScrollToBottom } = require('stremio/common'); +const { AddonDetailsModal, DelayedRenderer, Button, MainNavBars, MetaItem, Image, MetaPreview, Multiselect, ModalDialog, CONSTANTS, useBinaryState, useOnScrollToBottom, withCoreSuspender } = require('stremio/common'); const useDiscover = require('./useDiscover'); const useSelectableInputs = require('./useSelectableInputs'); const styles = require('./styles'); @@ -75,37 +75,26 @@ const Discover = ({ urlParams, queryParams }) => { closeAddonModal(); setSelectedMetaItemIndex(0); }, [discover.selected]); - const metaItemsContainerRef = React.useRef(); - React.useEffect(() => { - if (discover.catalog?.content.type === 'Loading') { - metaItemsContainerRef.current.scrollTop = 0; - } - }, [discover.catalog]); return (
- { - discover.defaultRequest ? -
- {selectInputs.map(({ title, options, selected, renderLabelText, onSelect }, index) => ( - - ))} - -
- : - null - } +
+ {selectInputs.map(({ title, options, selected, renderLabelText, onSelect }, index) => ( + + ))} + +
{ discover.catalog !== null && !discover.catalog.installed ?
@@ -119,10 +108,12 @@ const Discover = ({ urlParams, queryParams }) => { } { discover.catalog === null ? -
- {' -
No catalog selected!
-
+ +
+ {' +
No catalog selected!
+
+
: discover.catalog.content.type === 'Err' ?
@@ -131,7 +122,7 @@ const Discover = ({ urlParams, queryParams }) => {
: discover.catalog.content.type === 'Loading' ? -
+
{Array(CONSTANTS.CATALOG_PAGE_SIZE).fill(null).map((_, index) => (
@@ -142,7 +133,7 @@ const Discover = ({ urlParams, queryParams }) => { ))}
: -
+
{discover.catalog.content.content.map((metaItem, index) => ( { }
{ - inputsModalOpen && discover.defaultRequest ? + inputsModalOpen ? {selectInputs.map(({ title, options, selected, renderLabelText, onSelect }, index) => ( ( + +); + +module.exports = withCoreSuspender(Discover, DiscoverFallback); diff --git a/src/routes/Discover/useDiscover.js b/src/routes/Discover/useDiscover.js index 895b98910..c1555646c 100644 --- a/src/routes/Discover/useDiscover.js +++ b/src/routes/Discover/useDiscover.js @@ -5,18 +5,6 @@ const UrlUtils = require('url'); const { useServices } = require('stremio/services'); const { useModelState } = require('stremio/common'); -const init = () => ({ - selected: null, - selectable: { - types: [], - catalogs: [], - extra: [], - nextPage: false - }, - catalog: null, - defaultRequest: null, -}); - const map = (discover) => ({ ...discover, catalog: discover.catalog !== null && discover.catalog.content.type === 'Ready' ? @@ -67,25 +55,20 @@ const useDiscover = (urlParams, queryParams) => { }; } } else { - const discover = core.transport.getState('discover'); - if (discover.defaultRequest !== null) { - return { - action: 'Load', - args: { - model: 'CatalogWithFilters', - args: { - request: discover.defaultRequest - } - } - }; - } + return { + action: 'Load', + args: { + model: 'CatalogWithFilters', + args: null + } + }; } return { action: 'Unload' }; }, [urlParams, queryParams]); - const discover = useModelState({ model: 'discover', action, map, init }); + const discover = useModelState({ model: 'discover', action, map, deps: ['ctx'] }); return [discover, loadNextPage]; }; diff --git a/src/routes/Intro/Intro.js b/src/routes/Intro/Intro.js index a97a113f8..4e2fb74cd 100644 --- a/src/routes/Intro/Intro.js +++ b/src/routes/Intro/Intro.js @@ -186,7 +186,6 @@ const Intro = ({ queryParams }) => { tos: state.termsAccepted, privacy: state.privacyPolicyAccepted, marketing: state.marketingAccepted, - time: new Date(), from: 'web' } } diff --git a/src/routes/Library/Library.js b/src/routes/Library/Library.js index b350ce170..c2790824e 100644 --- a/src/routes/Library/Library.js +++ b/src/routes/Library/Library.js @@ -5,7 +5,7 @@ const PropTypes = require('prop-types'); const classnames = require('classnames'); const Icon = require('@stremio/stremio-icons/dom'); const NotFound = require('stremio/routes/NotFound'); -const { Button, Multiselect, MainNavBars, LibItem, Image, ModalDialog, PaginationInput, useProfile, routesRegexp, useBinaryState } = require('stremio/common'); +const { Button, DelayedRenderer, Multiselect, MainNavBars, LibItem, Image, ModalDialog, PaginationInput, useProfile, routesRegexp, useBinaryState, withCoreSuspender } = require('stremio/common'); const useLibrary = require('./useLibrary'); const useSelectableInputs = require('./useSelectableInputs'); const styles = require('./styles'); @@ -85,14 +85,16 @@ const Library = ({ model, urlParams, queryParams }) => {
: library.selected === null ? -
- {' -
{model === 'library' ? 'Library' : 'Continue Watching'} not loaded!
-
+ +
+ {' +
{model === 'library' ? 'Library' : 'Continue Watching'} not loaded!
+
+
: library.catalog.length === 0 ?
@@ -104,7 +106,7 @@ const Library = ({ model, urlParams, queryParams }) => {
Empty {model === 'library' ? 'Library' : 'Continue Watching'}
: -
+
{library.catalog.map((libItem, index) => ( ))} @@ -132,4 +134,10 @@ Library.propTypes = { queryParams: PropTypes.instanceOf(URLSearchParams) }; -module.exports = withModel(Library); +const LibraryFallback = ({ model }) => ( + +); + +LibraryFallback.propTypes = Library.propTypes; + +module.exports = withModel(withCoreSuspender(Library, LibraryFallback)); diff --git a/src/routes/Library/useLibrary.js b/src/routes/Library/useLibrary.js index cff44771d..d882d889b 100644 --- a/src/routes/Library/useLibrary.js +++ b/src/routes/Library/useLibrary.js @@ -3,17 +3,6 @@ const React = require('react'); const { useModelState } = require('stremio/common'); -const init = () => ({ - selected: null, - selectable: { - types: [], - sorts: [], - prevPage: null, - nextPage: null - }, - catalog: [] -}); - const useLibrary = (model, urlParams, queryParams) => { const action = React.useMemo(() => ({ action: 'Load', @@ -28,7 +17,7 @@ const useLibrary = (model, urlParams, queryParams) => { } } }), [urlParams, queryParams]); - return useModelState({ model, action, init }); + return useModelState({ model, action }); }; module.exports = useLibrary; diff --git a/src/routes/MetaDetails/MetaDetails.js b/src/routes/MetaDetails/MetaDetails.js index 602bdd3c8..144ef6c6c 100644 --- a/src/routes/MetaDetails/MetaDetails.js +++ b/src/routes/MetaDetails/MetaDetails.js @@ -2,8 +2,9 @@ const React = require('react'); const PropTypes = require('prop-types'); +const classnames = require('classnames'); const { useServices } = require('stremio/services'); -const { VerticalNavBar, HorizontalNavBar, MetaPreview, ModalDialog, Image } = require('stremio/common'); +const { VerticalNavBar, HorizontalNavBar, MetaPreview, ModalDialog, Image, DelayedRenderer, withCoreSuspender } = require('stremio/common'); const StreamsList = require('./StreamsList'); const VideosList = require('./VideosList'); const useMetaDetails = require('./useMetaDetails'); @@ -86,10 +87,12 @@ const MetaDetails = ({ urlParams, queryParams }) => { } { metaPath === null ? -
- {' -
No meta was selected!
-
+ +
+ {' +
No meta was selected!
+
+
: metaDetails.metaItem === null ?
@@ -122,7 +125,7 @@ const MetaDetails = ({ urlParams, queryParams }) => { null } ( +
+ +
+); + +module.exports = withCoreSuspender(MetaDetails, MetaDetailsFallback); diff --git a/src/routes/MetaDetails/StreamsList/StreamsList.js b/src/routes/MetaDetails/StreamsList/StreamsList.js index e62c26633..4c061ef73 100644 --- a/src/routes/MetaDetails/StreamsList/StreamsList.js +++ b/src/routes/MetaDetails/StreamsList/StreamsList.js @@ -4,32 +4,70 @@ const React = require('react'); const PropTypes = require('prop-types'); const classnames = require('classnames'); const Icon = require('@stremio/stremio-icons/dom'); -const { Button, Image } = require('stremio/common'); +const { Button, Image, Multiselect } = require('stremio/common'); const { useServices } = require('stremio/services'); const Stream = require('./Stream'); const styles = require('./styles'); +const ALL_ADDONS_KEY = 'ALL'; + const StreamsList = ({ className, ...props }) => { const { core } = useServices(); - const streams = React.useMemo(() => { + const [selectedAddon, setSelectedAddon] = React.useState(ALL_ADDONS_KEY); + const onAddonSelected = React.useCallback((event) => { + setSelectedAddon(event.value); + }, []); + const streamsByAddon = React.useMemo(() => { return props.streams .filter((streams) => streams.content.type === 'Ready') - .map((streams) => { - return streams.content.content.map((stream) => ({ - ...stream, - onClick: () => { - core.transport.analytics({ - event: 'StreamClicked', - args: { - stream - } - }); - }, - addonName: streams.addon.manifest.name - })); - }) - .flat(1); + .reduce((streamsByAddon, streams) => { + streamsByAddon[streams.addon.transportUrl] = { + addon: streams.addon, + streams: streams.content.content.map((stream) => ({ + ...stream, + onClick: () => { + core.transport.analytics({ + event: 'StreamClicked', + args: { + stream + } + }); + }, + addonName: streams.addon.manifest.name + })) + }; + + return streamsByAddon; + }, {}); }, [props.streams]); + const filteredStreams = React.useMemo(() => { + return selectedAddon === ALL_ADDONS_KEY ? + Object.values(streamsByAddon).map(({ streams }) => streams).flat(1) + : + streamsByAddon[selectedAddon] ? + streamsByAddon[selectedAddon].streams + : + []; + }, [streamsByAddon, selectedAddon]); + const selectableOptions = React.useMemo(() => { + return { + title: 'Select Addon', + options: [ + { + value: ALL_ADDONS_KEY, + label: 'All', + title: 'All' + }, + ...Object.keys(streamsByAddon).map((transportUrl) => ({ + value: transportUrl, + label: streamsByAddon[transportUrl].addon.manifest.name, + title: streamsByAddon[transportUrl].addon.manifest.name, + })) + ], + selected: [selectedAddon], + onSelect: onAddonSelected + }; + }, [streamsByAddon, selectedAddon]); return (
{ @@ -45,26 +83,37 @@ const StreamsList = ({ className, ...props }) => {
No streams were found!
: - streams.length === 0 ? + filteredStreams.length === 0 ?
: -
- {streams.map((stream, index) => ( - - ))} -
+ + { + Object.keys(streamsByAddon).length > 1 ? + + : + null + } +
+ {filteredStreams.map((stream, index) => ( + + ))} +
+
} + { + nextVideo !== null ? + + : + null + } - + { + metaItem?.content?.videos?.length > 0 ? + + : + null + }
@@ -149,6 +181,7 @@ ControlBar.propTypes = { subtitlesTracks: PropTypes.array, audioTracks: PropTypes.array, metaItem: PropTypes.object, + nextVideo: PropTypes.object, onPlayRequested: PropTypes.func, onPauseRequested: PropTypes.func, onMuteRequested: PropTypes.func, @@ -156,7 +189,8 @@ ControlBar.propTypes = { onVolumeChangeRequested: PropTypes.func, onSeekRequested: PropTypes.func, onToggleSubtitlesMenu: PropTypes.func, - onToggleInfoMenu: PropTypes.func + onToggleInfoMenu: PropTypes.func, + onToggleVideosMenu: PropTypes.func }; module.exports = ControlBar; diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index 913037b0e..a8f7c2c3f 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -6,11 +6,12 @@ const classnames = require('classnames'); const debounce = require('lodash.debounce'); const { useRouteFocused } = require('stremio-router'); const { useServices } = require('stremio/services'); -const { HorizontalNavBar, Button, useFullscreen, useBinaryState, useToast, useStreamingServer } = require('stremio/common'); +const { HorizontalNavBar, Button, useFullscreen, useBinaryState, useToast, useStreamingServer, withCoreSuspender } = require('stremio/common'); const Icon = require('@stremio/stremio-icons/dom'); const BufferingLoader = require('./BufferingLoader'); const ControlBar = require('./ControlBar'); const InfoMenu = require('./InfoMenu'); +const VideosMenu = require('./VideosMenu'); const SubtitlesMenu = require('./SubtitlesMenu'); const Video = require('./Video'); const usePlayer = require('./usePlayer'); @@ -18,14 +19,14 @@ const useSettings = require('./useSettings'); const styles = require('./styles'); const Player = ({ urlParams, queryParams }) => { - const { core, chromecast } = useServices(); + const { chromecast, shell } = useServices(); const [forceTranscoding, maxAudioChannels] = React.useMemo(() => { return [ queryParams.has('forceTranscoding'), queryParams.has('maxAudioChannels') ? parseInt(queryParams.get('maxAudioChannels'), 10) : null ]; }, [queryParams]); - const [player, updateLibraryItemState, pushToLibrary] = usePlayer(urlParams); + const [player, timeChanged, pausedChanged, ended, pushToLibrary] = usePlayer(urlParams); const [settings, updateSettings] = useSettings(); const streamingServer = useStreamingServer(); const routeFocused = useRouteFocused(); @@ -38,10 +39,12 @@ const Player = ({ urlParams, queryParams }) => { const setImmersedDebounced = React.useCallback(debounce(setImmersed, 3000), []); const [subtitlesMenuOpen, , closeSubtitlesMenu, toggleSubtitlesMenu] = useBinaryState(false); const [infoMenuOpen, , closeInfoMenu, toggleInfoMenu] = useBinaryState(false); + const [videosMenuOpen, , closeVideosMenu, toggleVideosMenu] = useBinaryState(false); const [error, setError] = React.useState(null); const [videoState, setVideoState] = React.useReducer( (videoState, nextVideoState) => ({ ...videoState, ...nextVideoState }), { + manifest: null, stream: null, paused: null, time: null, @@ -75,6 +78,7 @@ const Player = ({ urlParams, queryParams }) => { } }, []); const onImplementationChanged = React.useCallback((manifest) => { + setVideoState({ manifest }); manifest.props.forEach((propName) => { dispatch({ type: 'observeProp', propName }); }); @@ -93,16 +97,8 @@ const Player = ({ urlParams, queryParams }) => { setVideoState({ [propName]: propValue }); }, []); const onEnded = React.useCallback(() => { + ended(); pushToLibrary(); - if (player.libraryItem !== null) { - core.transport.dispatch({ - action: 'Ctx', - args: { - action: 'RewindLibraryItem', - args: player.libraryItem._id - } - }); - } if (player.nextVideo !== null) { window.location.replace( typeof player.nextVideo.deepLinks.player === 'string' ? @@ -204,6 +200,9 @@ const Player = ({ urlParams, queryParams }) => { if (!event.nativeEvent.infoMenuClosePrevented) { closeInfoMenu(); } + if (!event.nativeEvent.videosMenuClosePrevented) { + closeVideosMenu(); + } }, []); const onContainerMouseMove = React.useCallback((event) => { setImmersed(false); @@ -224,7 +223,8 @@ const Player = ({ urlParams, queryParams }) => { setError(null); if (player.selected === null) { dispatch({ type: 'command', commandName: 'unload' }); - } else if (streamingServer.baseUrl !== null && streamingServer.baseUrl.type !== 'Loading' && player.metaItem !== null && player.metaItem.type !== 'Loading') { + } else if (streamingServer.baseUrl !== null && streamingServer.baseUrl.type !== 'Loading' && + (player.selected.metaRequest === null || (player.metaItem !== null && player.metaItem.type !== 'Loading'))) { dispatch({ type: 'command', commandName: 'load', @@ -263,6 +263,7 @@ const Player = ({ urlParams, queryParams }) => { } }, { chromecastTransport: chromecast.active ? chromecast.transport : null, + shellTransport: shell.active ? shell.transport : null, }); } }, [streamingServer.baseUrl, player.selected, player.metaItem, forceTranscoding, maxAudioChannels, casting]); @@ -301,10 +302,17 @@ const Player = ({ urlParams, queryParams }) => { dispatch({ type: 'setProp', propName: 'extraSubtitlesOutlineColor', propValue: settings.subtitlesOutlineColor }); }, [settings.subtitlesOutlineColor]); React.useEffect(() => { - if (videoState.time !== null && !isNaN(videoState.time) && videoState.duration !== null && !isNaN(videoState.duration)) { - updateLibraryItemState(videoState.time, videoState.duration); + if (videoState.time !== null && !isNaN(videoState.time) && + videoState.duration !== null && !isNaN(videoState.duration) && + videoState.manifest !== null && typeof videoState.manifest.name === 'string') { + timeChanged(videoState.time, videoState.duration, videoState.manifest.name); } - }, [videoState.time, videoState.duration]); + }, [videoState.time, videoState.duration, videoState.manifest]); + React.useEffect(() => { + if (videoState.paused !== null) { + pausedChanged(videoState.paused); + } + }, [videoState.paused]); React.useEffect(() => { if ((!Array.isArray(videoState.subtitlesTracks) || videoState.subtitlesTracks.length === 0) && (!Array.isArray(videoState.extraSubtitlesTracks) || videoState.extraSubtitlesTracks.length === 0) && @@ -315,6 +323,7 @@ const Player = ({ urlParams, queryParams }) => { React.useEffect(() => { if (player.metaItem === null || player.metaItem.type !== 'Ready') { closeInfoMenu(); + closeVideosMenu(); } }, [player.metaItem]); React.useEffect(() => { @@ -326,6 +335,8 @@ const Player = ({ urlParams, queryParams }) => { }; }, []); React.useEffect(() => { + const toastFilter = (item) => item?.dataset?.type === 'CoreEvent'; + toast.addFilter(toastFilter); const onCastStateChange = () => { setCasting(chromecast.active && chromecast.transport.getCastState() === cast.framework.CastState.CONNECTED); }; @@ -341,6 +352,7 @@ const Player = ({ urlParams, queryParams }) => { chromecast.on('stateChanged', onChromecastServiceStateChange); onChromecastServiceStateChange(); return () => { + toast.removeFilter(toastFilter); chromecast.off('stateChanged', onChromecastServiceStateChange); if (chromecast.active) { chromecast.transport.off( @@ -396,6 +408,7 @@ const Player = ({ urlParams, queryParams }) => { } case 'KeyS': { closeInfoMenu(); + closeVideosMenu(); if ((Array.isArray(videoState.subtitlesTracks) && videoState.subtitlesTracks.length > 0) || (Array.isArray(videoState.extraSubtitlesTracks) && videoState.extraSubtitlesTracks.length > 0) || (Array.isArray(videoState.audioTracks) && videoState.audioTracks.length > 0)) { @@ -406,15 +419,26 @@ const Player = ({ urlParams, queryParams }) => { } case 'KeyI': { closeSubtitlesMenu(); + closeVideosMenu(); if (player.metaItem !== null && player.metaItem.type === 'Ready') { toggleInfoMenu(); } break; } + case 'KeyV': { + closeInfoMenu(); + closeSubtitlesMenu(); + if (player.metaItem !== null && player.metaItem.type === 'Ready') { + toggleVideosMenu(); + } + + break; + } case 'Escape': { closeSubtitlesMenu(); closeInfoMenu(); + closeVideosMenu(); break; } } @@ -425,7 +449,7 @@ const Player = ({ urlParams, queryParams }) => { return () => { window.removeEventListener('keydown', onKeyDown); }; - }, [player.metaItem, settings.seekTimeDuration, routeFocused, subtitlesMenuOpen, infoMenuOpen, videoState.paused, videoState.time, videoState.volume, videoState.audioTracks, videoState.subtitlesTracks, videoState.extraSubtitlesTracks, toggleSubtitlesMenu, toggleInfoMenu]); + }, [player.metaItem, settings.seekTimeDuration, routeFocused, subtitlesMenuOpen, infoMenuOpen, videoState.paused, videoState.time, videoState.volume, videoState.audioTracks, videoState.subtitlesTracks, videoState.extraSubtitlesTracks, toggleSubtitlesMenu, toggleInfoMenu, toggleVideosMenu]); React.useLayoutEffect(() => { return () => { setImmersedDebounced.cancel(); @@ -434,7 +458,7 @@ const Player = ({ urlParams, queryParams }) => { }; }, []); return ( -
{ subtitlesTracks={videoState.subtitlesTracks.concat(videoState.extraSubtitlesTracks)} audioTracks={videoState.audioTracks} metaItem={player.metaItem} + nextVideo={player.nextVideo} onPlayRequested={onPlayRequested} onPauseRequested={onPauseRequested} onMuteRequested={onMuteRequested} @@ -510,6 +535,7 @@ const Player = ({ urlParams, queryParams }) => { onSeekRequested={onSeekRequested} onToggleSubtitlesMenu={toggleSubtitlesMenu} onToggleInfoMenu={toggleInfoMenu} + onToggleVideosMenu={toggleVideosMenu} onMouseMove={onBarMouseMove} onMouseOver={onBarMouseMove} /> @@ -551,6 +577,16 @@ const Player = ({ urlParams, queryParams }) => { : null } + { + videosMenuOpen ? + + : + null + }
); }; @@ -567,4 +603,8 @@ Player.propTypes = { queryParams: PropTypes.instanceOf(URLSearchParams) }; -module.exports = Player; +const PlayerFallback = () => ( +
+); + +module.exports = withCoreSuspender(Player, PlayerFallback); diff --git a/src/routes/Player/VideosMenu/VideosMenu.js b/src/routes/Player/VideosMenu/VideosMenu.js new file mode 100644 index 000000000..219a329c2 --- /dev/null +++ b/src/routes/Player/VideosMenu/VideosMenu.js @@ -0,0 +1,51 @@ +// Copyright (C) 2017-2022 Smart code 203358507 + +const React = require('react'); +const PropTypes = require('prop-types'); +const classnames = require('classnames'); +const Video = require('../../MetaDetails/VideosList/Video'); +const styles = require('./styles'); + +const VideosMenu = ({ className, metaItem, seriesInfo }) => { + const onMouseDown = React.useCallback((event) => { + event.nativeEvent.videosMenuClosePrevented = true; + }, []); + const videos = React.useMemo(() => { + return seriesInfo && typeof seriesInfo.season === 'number' && Array.isArray(metaItem.videos) ? + metaItem.videos.filter(({ season }) => season === seriesInfo.season) + : + metaItem.videos; + }, [metaItem, seriesInfo]); + return ( +
+ { + videos.map((video, index) => ( +
+ ); +}; + +VideosMenu.propTypes = { + className: PropTypes.string, + metaItem: PropTypes.object, + seriesInfo: PropTypes.shape({ + season: PropTypes.number, + episode: PropTypes.number, + }), +}; + +module.exports = VideosMenu; diff --git a/src/routes/Player/VideosMenu/index.js b/src/routes/Player/VideosMenu/index.js new file mode 100644 index 000000000..e604ab4cc --- /dev/null +++ b/src/routes/Player/VideosMenu/index.js @@ -0,0 +1,5 @@ +// Copyright (C) 2017-2022 Smart code 203358507 + +const VideosMenu = require('./VideosMenu'); + +module.exports = VideosMenu; diff --git a/src/routes/Player/VideosMenu/styles.less b/src/routes/Player/VideosMenu/styles.less new file mode 100644 index 000000000..47444c72a --- /dev/null +++ b/src/routes/Player/VideosMenu/styles.less @@ -0,0 +1,5 @@ +// Copyright (C) 2017-2022 Smart code 203358507 + +.videos-menu-container { + width: 30rem; +} \ No newline at end of file diff --git a/src/routes/Player/usePlayer.js b/src/routes/Player/usePlayer.js index 0e728b51f..9acd16396 100644 --- a/src/routes/Player/usePlayer.js +++ b/src/routes/Player/usePlayer.js @@ -2,18 +2,7 @@ const React = require('react'); const { useServices } = require('stremio/services'); -const { useModelState } = require('stremio/common'); - -const init = () => ({ - selected: null, - metaItem: null, - subtitles: [], - nextVideo: null, - seriesInfo: null, - libraryItem: null, - title: null, - addon: null, -}); +const { useModelState, useCoreSuspender } = require('stremio/common'); const map = (player) => ({ ...player, @@ -45,8 +34,9 @@ const map = (player) => ({ const usePlayer = (urlParams) => { const { core } = useServices(); + const { decodeStream } = useCoreSuspender(); + const stream = decodeStream(urlParams.stream); const action = React.useMemo(() => { - const stream = core.transport.decodeStream(urlParams.stream); if (stream !== null) { return { action: 'Load', @@ -96,12 +86,12 @@ const usePlayer = (urlParams) => { }; } }, [urlParams]); - const updateLibraryItemState = React.useCallback((time, duration) => { + const timeChanged = React.useCallback((time, duration, device) => { core.transport.dispatch({ action: 'Player', args: { - action: 'UpdateLibraryItemState', - args: { time, duration } + action: 'TimeChanged', + args: { time, duration, device } } }, 'player'); }, []); @@ -113,8 +103,25 @@ const usePlayer = (urlParams) => { } }, 'player'); }, []); - const player = useModelState({ model: 'player', action, init, map }); - return [player, updateLibraryItemState, pushToLibrary]; + const ended = React.useCallback(() => { + core.transport.dispatch({ + action: 'Player', + args: { + action: 'Ended' + } + }, 'player'); + }, []); + const pausedChanged = React.useCallback((paused) => { + core.transport.dispatch({ + action: 'Player', + args: { + action: 'PausedChanged', + args: { paused } + } + }, 'player'); + }, []); + const player = useModelState({ model: 'player', action, map }); + return [player, timeChanged, pausedChanged, ended, pushToLibrary]; }; module.exports = usePlayer; diff --git a/src/routes/Search/Search.js b/src/routes/Search/Search.js index 47fb15cba..bea2e7606 100644 --- a/src/routes/Search/Search.js +++ b/src/routes/Search/Search.js @@ -5,7 +5,7 @@ const PropTypes = require('prop-types'); const classnames = require('classnames'); const debounce = require('lodash.debounce'); const Icon = require('@stremio/stremio-icons/dom'); -const { Image, MainNavBars, MetaRow, MetaItem, useDeepEqualMemo, getVisibleChildrenRange } = require('stremio/common'); +const { Image, MainNavBars, MetaRow, MetaItem, useDeepEqualMemo, withCoreSuspender, getVisibleChildrenRange } = require('stremio/common'); const useSearch = require('./useSearch'); const styles = require('./styles'); @@ -47,7 +47,7 @@ const Search = ({ queryParams }) => {
{ query === null ? -
+
Search for movies, series, YouTube and TV channels
@@ -74,7 +74,7 @@ const Search = ({ queryParams }) => { return ( { return ( { return ( @@ -115,4 +115,10 @@ Search.propTypes = { queryParams: PropTypes.instanceOf(URLSearchParams) }; -module.exports = Search; +const SearchFallback = ({ queryParams }) => ( + +); + +SearchFallback.propTypes = Search.propTypes; + +module.exports = withCoreSuspender(Search, SearchFallback); diff --git a/src/routes/Search/useSearch.js b/src/routes/Search/useSearch.js index d1ff8e79c..40a46fb76 100644 --- a/src/routes/Search/useSearch.js +++ b/src/routes/Search/useSearch.js @@ -4,37 +4,33 @@ const React = require('react'); const { useModelState } = require('stremio/common'); const { useServices } = require('stremio/services'); -const init = () => ({ - selected: null, - catalogs: [] -}); - const useSearch = (queryParams) => { const { core } = useServices(); - React.useEffect(() => { - let timerId = setTimeout(emitSearchEvent, 500); - function emitSearchEvent() { - timerId = null; - const state = core.transport.getState('search'); - if (state.selected !== null) { - const [, query] = state.selected.extra.find(([name]) => name === 'search'); - const responses = state.catalogs.filter((catalog) => catalog.content?.type === 'Ready'); - core.transport.analytics({ - event: 'Search', - args: { - query, - responsesCount: responses.length - } - }); - } - } - return () => { - if (timerId !== null) { - clearTimeout(timerId); - emitSearchEvent(); - } - }; - }, [queryParams.get('search')]); + // TODO: refactor this to be in stremio-core-web + // React.useEffect(() => { + // let timerId = setTimeout(emitSearchEvent, 500); + // function emitSearchEvent() { + // timerId = null; + // const state = core.transport.getState('search'); + // if (state.selected !== null) { + // const [, query] = state.selected.extra.find(([name]) => name === 'search'); + // const responses = state.catalogs.filter((catalog) => catalog.content?.type === 'Ready'); + // core.transport.analytics({ + // event: 'Search', + // args: { + // query, + // responsesCount: responses.length + // } + // }); + // } + // } + // return () => { + // if (timerId !== null) { + // clearTimeout(timerId); + // emitSearchEvent(); + // } + // }; + // }, [queryParams.get('search')]); const action = React.useMemo(() => { if (queryParams.has('search') && queryParams.get('search').length > 0) { return { @@ -63,7 +59,7 @@ const useSearch = (queryParams) => { } }, 'search'); }, []); - const search = useModelState({ model: 'search', action, init }); + const search = useModelState({ model: 'search', action }); return [search, loadRange]; }; diff --git a/src/routes/Settings/Settings.js b/src/routes/Settings/Settings.js index bffa9da66..9ca68fd52 100644 --- a/src/routes/Settings/Settings.js +++ b/src/routes/Settings/Settings.js @@ -6,7 +6,7 @@ const throttle = require('lodash.throttle'); const Icon = require('@stremio/stremio-icons/dom'); const { useRouteFocused } = require('stremio-router'); const { useServices } = require('stremio/services'); -const { Button, Checkbox, MainNavBars, Multiselect, ColorInput, TextInput, ModalDialog, useProfile, useStreamingServer, useBinaryState } = require('stremio/common'); +const { Button, Checkbox, MainNavBars, Multiselect, ColorInput, TextInput, ModalDialog, useProfile, useStreamingServer, useBinaryState, withCoreSuspender } = require('stremio/common'); const useProfileSettingsInputs = require('./useProfileSettingsInputs'); const useStreamingServerSettingsInputs = require('./useStreamingServerSettingsInputs'); const styles = require('./styles'); @@ -14,6 +14,7 @@ const styles = require('./styles'); const GENERAL_SECTION = 'general'; const PLAYER_SECTION = 'player'; const STREAMING_SECTION = 'streaming'; +const SHORTCUTS_SECTION = 'shortcuts'; const Settings = () => { const { core } = useServices(); @@ -93,10 +94,12 @@ const Settings = () => { const generalSectionRef = React.useRef(null); const playerSectionRef = React.useRef(null); const streamingServerSectionRef = React.useRef(null); + const shortcutsSectionRef = React.useRef(null); const sections = React.useMemo(() => ([ { ref: generalSectionRef, id: GENERAL_SECTION }, { ref: playerSectionRef, id: PLAYER_SECTION }, { ref: streamingServerSectionRef, id: STREAMING_SECTION }, + { ref: shortcutsSectionRef, id: SHORTCUTS_SECTION }, ]), []); const [selectedSectionId, setSelectedSectionId] = React.useState(GENERAL_SECTION); const updateSelectedSectionId = React.useCallback(() => { @@ -131,7 +134,7 @@ const Settings = () => { }, [routeFocused]); return ( -
+
+
App Version: {process.env.VERSION}
{ @@ -424,6 +430,107 @@ const Settings = () => { null }
+
+
Shortcuts
+
+
+
Play / Pause
+
+
+ Space +
+
+
+
+
Seek Forward
+
+
+ +
or
+ ⇧ Shift +
+
+ +
+
+
+
+
Seek Backward
+
+
+ +
or
+ ⇧ Shift +
+
+ +
+
+
+
+
Volume Up
+
+
+ +
+
+
+
+
Volume Down
+
+
+ +
+
+
+
+
Toggle Subtitles Menu
+
+
+ S +
+
+
+
+
Toggle Info Menu
+
+
+ I +
+
+
+
+
Toggle Fullscreen
+
+
+ F +
+
+
+
+
Navigate Between Menus
+
+
+ 1 +
to
+ 5 +
+
+
+
+
Go to Search
+
+
+ 0 +
+
+
+
+
Close Menu or Modal
+
+
+ Esc +
+
+
{ @@ -449,4 +556,8 @@ const Settings = () => { ); }; -module.exports = Settings; +const SettingsFallback = () => ( + +); + +module.exports = withCoreSuspender(Settings, SettingsFallback); diff --git a/src/routes/Settings/styles.less b/src/routes/Settings/styles.less index be058dd23..7e297080a 100644 --- a/src/routes/Settings/styles.less +++ b/src/routes/Settings/styles.less @@ -315,6 +315,30 @@ } } } + + &.shortcut-container { + justify-content: center; + padding: 0; + overflow: visible; + + kbd { + flex: 0 1 auto; + height: 2.5rem; + min-width: 2.5rem; + line-height: 2.5rem; + padding: 0 1rem; + font-weight: 500; + color: @color-secondaryvariant1-90; + border-radius: 0.25em; + box-shadow: 0 4px 0 1px @color-background-40; + background-color: @color-background; + } + + .label { + margin: 0 1rem; + color: @color-secondaryvariant1-90; + } + } } } } diff --git a/src/routes/Settings/useProfileSettingsInputs.js b/src/routes/Settings/useProfileSettingsInputs.js index 5534fd6e4..57f444d01 100644 --- a/src/routes/Settings/useProfileSettingsInputs.js +++ b/src/routes/Settings/useProfileSettingsInputs.js @@ -5,6 +5,7 @@ const { CONSTANTS, languageNames, useDeepEqualMemo } = require('stremio/common') const useProfileSettingsInputs = (profile) => { const { core } = useServices(); + // TODO combine those useDeepEqualMemo in one const interfaceLanguageSelect = useDeepEqualMemo(() => ({ options: Object.keys(languageNames).map((code) => ({ value: code, diff --git a/src/routes/Settings/useStreamingServerSettingsInputs.js b/src/routes/Settings/useStreamingServerSettingsInputs.js index 0318d0f49..8e1e3405c 100644 --- a/src/routes/Settings/useStreamingServerSettingsInputs.js +++ b/src/routes/Settings/useStreamingServerSettingsInputs.js @@ -18,10 +18,10 @@ const cacheSizeToString = (size) => { const TORRENT_PROFILES = { default: { - btDownloadSpeedHardLimit: 2621440, - btDownloadSpeedSoftLimit: 1677721.6, + btDownloadSpeedHardLimit: 3670016, + btDownloadSpeedSoftLimit: 2621440, btHandshakeTimeout: 20000, - btMaxConnections: 35, + btMaxConnections: 55, btMinPeersForStable: 5, btRequestTimeout: 4000 }, @@ -40,11 +40,20 @@ const TORRENT_PROFILES = { btMaxConnections: 200, btMinPeersForStable: 10, btRequestTimeout: 4000 + }, + 'ultra fast': { + btDownloadSpeedHardLimit: 78643200, + btDownloadSpeedSoftLimit: 8388608, + btHandshakeTimeout: 25000, + btMaxConnections: 400, + btMinPeersForStable: 10, + btRequestTimeout: 6000 } }; const useStreamingServerSettingsInputs = (streamingServer) => { const { core } = useServices(); + // TODO combine those useDeepEqualMemo in one const cacheSizeSelect = useDeepEqualMemo(() => { if (streamingServer.settings === null || streamingServer.settings.type !== 'Ready') { return null; diff --git a/src/services/Core/Core.js b/src/services/Core/Core.js index 9716cf2b3..e033396d5 100644 --- a/src/services/Core/Core.js +++ b/src/services/Core/Core.js @@ -3,7 +3,7 @@ const EventEmitter = require('eventemitter3'); const CoreTransport = require('./CoreTransport'); -function Core() { +function Core(args) { let active = false; let error = null; let starting = false; @@ -66,7 +66,7 @@ function Core() { } starting = true; - transport = new CoreTransport(); + transport = new CoreTransport(args); transport.on('init', onTransportInit); transport.on('error', onTransportError); onStateChanged(); diff --git a/src/services/Core/CoreTransport.js b/src/services/Core/CoreTransport.js index 95a8cff34..954dc88dd 100644 --- a/src/services/Core/CoreTransport.js +++ b/src/services/Core/CoreTransport.js @@ -1,19 +1,22 @@ // Copyright (C) 2017-2022 Smart code 203358507 const EventEmitter = require('eventemitter3'); -const { default: initialize_api, initialize_runtime, get_state, get_debug_state, dispatch, analytics, decode_stream } = require('@stremio/stremio-core-web'); +const Bridge = require('@stremio/stremio-core-web/bridge'); -function CoreTransport() { +function CoreTransport(args) { const events = new EventEmitter(); + const worker = new Worker(`${process.env.COMMIT_HASH}/scripts/worker.js`); + const bridge = new Bridge(window, worker); - initialize_api(require('@stremio/stremio-core-web/stremio_core_web_bg.wasm')) - .then(() => initialize_runtime(({ name, args }) => { - try { - events.emit(name, args); - } catch (error) { - console.error('CoreTransport', error); - } - })) + window.onCoreEvent = ({ name, args }) => { + try { + events.emit(name, args); + } catch (error) { + console.error('CoreTransport', error); + } + }; + + bridge.call(['init'], [args]) .then(() => { try { events.emit('init'); @@ -34,28 +37,20 @@ function CoreTransport() { this.removeAllListeners = function() { events.removeAllListeners(); }; - this.getState = function(field) { - return get_state(field); + this.getState = async function(field) { + return bridge.call(['getState'], [field]); }; - this.getDebugState = function() { - return get_debug_state(); + this.getDebugState = async function() { + return bridge.call(['getDebugState'], []); }; - this.dispatch = function(action, field) { - try { - dispatch(action, field); - } catch (error) { - console.error('CoreTransport', error); - } + this.dispatch = async function(action, field) { + return bridge.call(['dispatch'], [action, field, location.hash]); }; - this.analytics = function(event) { - try { - analytics(event); - } catch (error) { - console.error('CoreTransport', error); - } + this.analytics = async function(event) { + return bridge.call(['analytics'], [event, location.hash]); }; - this.decodeStream = function(stream) { - return decode_stream(stream); + this.decodeStream = async function(stream) { + return bridge.call(['decodeStream'], [stream]); }; } diff --git a/src/services/DragAndDrop/DragAndDrop.js b/src/services/DragAndDrop/DragAndDrop.js new file mode 100644 index 000000000..a503911d8 --- /dev/null +++ b/src/services/DragAndDrop/DragAndDrop.js @@ -0,0 +1,89 @@ +// Copyright (C) 2017-2022 Smart code 203358507 + +const EventEmitter = require('eventemitter3'); + +function DragAndDrop({ core }) { + let active = false; + + const events = new EventEmitter(); + + function onDragOver(event) { + event.preventDefault(); + } + async function onDrop(event) { + event.preventDefault(); + if (event.dataTransfer.files instanceof FileList && event.dataTransfer.files.length > 0) { + const file = event.dataTransfer.files[0]; + switch (file.type) { + case 'application/x-bittorrent': { + try { + const torrent = await file.arrayBuffer(); + core.transport.dispatch({ + action: 'StreamingServer', + args: { + action: 'CreateTorrent', + args: Array.from(new Uint8Array(torrent)) + } + }); + } catch (error) { + events.emit('error', { + message: 'Failed to process file', + file: { + name: file.name, + type: file.type + } + }); + } + break; + } + default: { + events.emit('error', { + message: 'Unsupported file', + file: { + name: file.name, + type: file.type + } + }); + } + } + } + } + function onStateChanged() { + events.emit('stateChanged'); + } + + Object.defineProperties(this, { + active: { + configurable: false, + enumerable: true, + get: function() { + return active; + } + } + }); + + this.start = function() { + if (active) { + return; + } + + window.addEventListener('dragover', onDragOver); + window.addEventListener('drop', onDrop); + active = true; + onStateChanged(); + }; + this.stop = function() { + window.removeEventListener('dragover', onDragOver); + window.removeEventListener('drop', onDrop); + active = false; + onStateChanged(); + }; + this.on = function(name, listener) { + events.on(name, listener); + }; + this.off = function(name, listener) { + events.off(name, listener); + }; +} + +module.exports = DragAndDrop; diff --git a/src/services/DragAndDrop/index.js b/src/services/DragAndDrop/index.js new file mode 100644 index 000000000..2bc7650af --- /dev/null +++ b/src/services/DragAndDrop/index.js @@ -0,0 +1,5 @@ +// Copyright (C) 2017-2022 Smart code 203358507 + +const DragAndDrop = require('./DragAndDrop'); + +module.exports = DragAndDrop; diff --git a/src/services/Shell/Shell.js b/src/services/Shell/Shell.js index bb4d9051f..1e0c31943 100644 --- a/src/services/Shell/Shell.js +++ b/src/services/Shell/Shell.js @@ -1,14 +1,31 @@ // Copyright (C) 2017-2022 Smart code 203358507 const EventEmitter = require('eventemitter3'); +const ShellTransport = require('./ShellTransport'); function Shell() { let active = false; let error = null; let starting = false; + let transport = null; const events = new EventEmitter(); + function onTransportInit() { + active = true; + error = null; + starting = false; + onStateChanged(); + } + function onTransportInitError(err) { + console.error(err); + active = false; + error = new Error(err); + starting = false; + onStateChanged(); + transport = null; + } + function onStateChanged() { events.emit('stateChanged'); } @@ -34,6 +51,13 @@ function Shell() { get: function() { return starting; } + }, + transport: { + configurable: false, + enumerable: true, + get: function() { + return transport; + } } }); @@ -43,8 +67,10 @@ function Shell() { } active = false; - error = new Error('Stremio Shell API not available'); - starting = false; + starting = true; + transport = new ShellTransport(); + transport.on('init', onTransportInit); + transport.on('init-error', onTransportInitError); onStateChanged(); }; this.stop = function() { diff --git a/src/services/Shell/ShellTransport.js b/src/services/Shell/ShellTransport.js new file mode 100644 index 000000000..ff2ac845c --- /dev/null +++ b/src/services/Shell/ShellTransport.js @@ -0,0 +1,121 @@ +// Copyright (C) 2017-2022 Smart code 203358507 + +const EventEmitter = require('eventemitter3'); + +let shellAvailable = false; +const shellEvents = new EventEmitter(); + +const QtMsgTypes = { + signal: 1, + propertyUpdate: 2, + init: 3, + idle: 4, + debug: 5, + invokeMethod: 6, + connectToSignal: 7, + disconnectFromSignal: 8, + setProperty: 9, + response: 10, +}; +const QtObjId = 'transport'; // the ID of our transport object + +window.initShellComm = function () { + delete window.initShellComm; + shellEvents.emit('availabilityChanged'); +}; + +const initialize = () => { + if(!window.qt) return Promise.reject('Qt API not found'); + return new Promise((resolve) => { + function onShellAvailabilityChanged() { + shellEvents.off('availabilityChanged', onShellAvailabilityChanged); + shellAvailable = true; + resolve(); + } + if (shellAvailable) { + onShellAvailabilityChanged(); + } else { + shellEvents.on('availabilityChanged', onShellAvailabilityChanged); + } + }); +}; + +function ShellTransport() { + const events = new EventEmitter(); + + this.props = {}; + + const shell = this; + initialize() + .then(() => { + const transport = window.qt && window.qt.webChannelTransport; + if (!transport) throw 'no viable transport found (qt.webChannelTransport)'; + + let id = 0; + function send(msg) { + msg.id = id++; + transport.send(JSON.stringify(msg)); + } + + transport.onmessage = function (message) { + const msg = JSON.parse(message.data); + if (msg.id === 0) { + const obj = msg.data[QtObjId]; + + obj.properties.slice(1).forEach(function (prop) { + shell.props[prop[1]] = prop[3]; + }); + if (typeof shell.props.shellVersion === 'string') { + shell.shellVersionArr = ( + shell.props.shellVersion.match(/(\d+)\.(\d+)\.(\d+)/) || [] + ) + .slice(1, 4) + .map(Number); + } + events.emit('received-props', shell.props); + + obj.signals.forEach(function (sig) { + send({ + type: QtMsgTypes.connectToSignal, + object: QtObjId, + signal: sig[1], + }); + }); + + const onEvent = obj.methods.filter(function (x) { + return x[0] === 'onEvent'; + })[0]; + + shell.send = function (ev, args) { + send({ + type: QtMsgTypes.invokeMethod, + object: QtObjId, + method: onEvent[1], + args: [ev, args || {}], + }); + }; + + shell.send('app-ready', {}); // signal that we're ready to take events + } + + if (msg.object === QtObjId && msg.type === QtMsgTypes.signal) + events.emit(msg.args[0], msg.args[1]); + events.emit('init'); + }; + send({ type: QtMsgTypes.init }); + }) .catch((error) => { + events.emit('init-error', error); + }); + + this.on = function(name, listener) { + events.on(name, listener); + }; + this.off = function(name, listener) { + events.off(name, listener); + }; + this.removeAllListeners = function() { + events.removeAllListeners(); + }; +} + +module.exports = ShellTransport; diff --git a/src/services/index.js b/src/services/index.js index fb944e199..3ed0767f0 100644 --- a/src/services/index.js +++ b/src/services/index.js @@ -2,6 +2,7 @@ const Chromecast = require('./Chromecast'); const Core = require('./Core'); +const DragAndDrop = require('./DragAndDrop'); const KeyboardShortcuts = require('./KeyboardShortcuts'); const { ServicesProvider, useServices } = require('./ServicesContext'); const Shell = require('./Shell'); @@ -9,6 +10,7 @@ const Shell = require('./Shell'); module.exports = { Chromecast, Core, + DragAndDrop, KeyboardShortcuts, ServicesProvider, useServices, diff --git a/webpack.config.js b/webpack.config.js index c9c9952d6..93cff5e93 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -16,7 +16,10 @@ const COMMIT_HASH = execSync('git rev-parse HEAD').toString().trim(); module.exports = (env, argv) => ({ mode: argv.mode, devtool: argv.mode === 'production' ? 'source-map' : 'eval-source-map', - entry: './src/index.js', + entry: { + main: './src/index.js', + worker: './node_modules/@stremio/stremio-core-web/worker.js' + }, output: { path: path.join(__dirname, 'build'), filename: `${COMMIT_HASH}/scripts/[name].js`