diff --git a/package-lock.json b/package-lock.json index 33e931e..8b52d04 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,15 @@ { "name": "qapp-core", - "version": "1.0.31", + "version": "1.0.34", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "qapp-core", - "version": "1.0.31", + "version": "1.0.34", "license": "MIT", "dependencies": { "@tanstack/react-virtual": "^3.13.2", - "bloom-filters": "^3.0.4", "buffer": "^6.0.3", "compressorjs": "^1.2.1", "crypto-js": "^4.2.0", @@ -49,7 +48,6 @@ "@emotion/styled": "^11.14.0", "@mui/icons-material": "^7.0.1", "@mui/material": "^7.0.1", - "mediainfo.js": "^0.3.5", "react": "^19.0.0", "react-dom": "^19.1.0", "react-router-dom": "^7.6.2" @@ -1422,11 +1420,6 @@ "@types/react": "*" } }, - "node_modules/@types/seedrandom": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-3.0.8.tgz", - "integrity": "sha512-TY1eezMU2zH2ozQoAFAQFOPpvP15g+ZgSfTZt31AUUH/Rxtnz3H+A/Sv1Snw2/amp//omibc+AEkTaA8KUeOLQ==" - }, "node_modules/@types/trusted-types": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", @@ -1589,14 +1582,6 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "node_modules/base64-arraybuffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", - "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -1616,24 +1601,6 @@ } ] }, - "node_modules/bloom-filters": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/bloom-filters/-/bloom-filters-3.0.4.tgz", - "integrity": "sha512-BdnPWo2OpYhlvuP2fRzJBdioMCkm7Zp0HCf8NJgF5Mbyqy7VQ/CnTiVWMMyq4EZCBHwj0Kq6098gW2/3RsZsrA==", - "dependencies": { - "@types/seedrandom": "^3.0.8", - "base64-arraybuffer": "^1.0.2", - "is-buffer": "^2.0.5", - "lodash": "^4.17.21", - "long": "^5.2.0", - "reflect-metadata": "^0.1.13", - "seedrandom": "^3.0.5", - "xxhashjs": "^0.2.2" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/blueimp-canvas-to-blob": { "version": "3.29.0", "resolved": "https://registry.npmjs.org/blueimp-canvas-to-blob/-/blueimp-canvas-to-blob-3.29.0.tgz", @@ -1758,100 +1725,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", - "peer": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/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==", - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT", - "peer": true - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "peer": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", @@ -1865,6 +1738,7 @@ "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" }, @@ -1875,7 +1749,8 @@ "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==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "node_modules/commander": { "version": "4.1.1", @@ -2027,11 +1902,6 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, - "node_modules/cuint": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", - "integrity": "sha512-d4ZVpCW31eWwCMe1YT3ur7mUDnTXbgwyzaL320DrcRT45rfjYxkt5QWLrmOJ+/UEAI2+fQgKe/fCjR8l4TpRgw==" - }, "node_modules/dayjs": { "version": "1.11.13", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", @@ -2156,16 +2026,6 @@ "@esbuild/win32-x64": "0.25.2" } }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -2286,16 +2146,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", - "peer": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, "node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -2495,28 +2345,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "engines": { - "node": ">=4" - } - }, "node_modules/is-core-module": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", @@ -2545,6 +2373,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { "node": ">=8" } @@ -2677,22 +2506,12 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, "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/long": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.1.tgz", - "integrity": "sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==" - }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -2721,22 +2540,6 @@ "global": "^4.4.0" } }, - "node_modules/mediainfo.js": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/mediainfo.js/-/mediainfo.js-0.3.5.tgz", - "integrity": "sha512-frLJzKOoAUC0sbPzmg9VOR+WFbNj5CarbTuOzXeH9cOl33haU/CGcyXUTWK00HPXCVS2N5eT0o0dirVxaPIOIw==", - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "yargs": "^17.7.2" - }, - "bin": { - "mediainfo.js": "dist/esm/cli.js" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/meow": { "version": "12.1.1", "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", @@ -3415,26 +3218,11 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/reflect-metadata": { - "version": "0.1.14", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz", - "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==" - }, "node_modules/regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/resolve": { "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", @@ -3542,11 +3330,6 @@ "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", "license": "MIT" }, - "node_modules/seedrandom": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", - "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" - }, "node_modules/set-cookie-parser": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", @@ -4111,98 +3894,6 @@ "node": ">=8" } }, - "node_modules/xxhashjs": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.2.tgz", - "integrity": "sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==", - "dependencies": { - "cuint": "^0.2.2" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "license": "ISC", - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "license": "MIT", - "peer": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "license": "ISC", - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT", - "peer": true - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "peer": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/zustand": { "version": "4.5.6", "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.6.tgz", diff --git a/package.json b/package.json index 654c6da..92df552 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,6 @@ }, "dependencies": { "@tanstack/react-virtual": "^3.13.2", - "bloom-filters": "^3.0.4", "buffer": "^6.0.3", "compressorjs": "^1.2.1", "crypto-js": "^4.2.0", diff --git a/src/components/VideoPlayer/LoadingVideo.tsx b/src/components/VideoPlayer/LoadingVideo.tsx index 4d83a5b..b8e1c5b 100644 --- a/src/components/VideoPlayer/LoadingVideo.tsx +++ b/src/components/VideoPlayer/LoadingVideo.tsx @@ -1,4 +1,4 @@ -import { Box, CircularProgress, Typography } from "@mui/material"; +import { alpha, Box, Button, CircularProgress, IconButton, Typography } from "@mui/material"; import { PlayArrow } from "@mui/icons-material"; import { Status } from "../../state/publishes"; @@ -10,9 +10,11 @@ interface LoadingVideoProps { isReady: boolean isLoading: boolean togglePlay: ()=> void + startPlay: boolean, + downloadResource: ()=> void } export const LoadingVideo = ({ - status, percentLoaded, isReady, isLoading, togglePlay + status, percentLoaded, isReady, isLoading, togglePlay, startPlay, downloadResource }: LoadingVideoProps) => { const getDownloadProgress = (percentLoaded: number) => { @@ -29,12 +31,12 @@ export const LoadingVideo = ({ top={0} left={0} right={0} - bottom={status === "READY" ? "55px " : 0} + bottom={0} display="flex" justifyContent="center" alignItems="center" - zIndex={25} - bgcolor="rgba(0, 0, 0, 0.6)" + zIndex={500} + bgcolor={alpha('#000000', !startPlay ? 0 : 0.95)} sx={{ display: "flex", flexDirection: "column", @@ -42,18 +44,21 @@ export const LoadingVideo = ({ height: "100%", }} > - {status !== "NOT_PUBLISHED" && ( - + {status !== "NOT_PUBLISHED" && status !== "FAILED_TO_DOWNLOAD" && ( + )} {status && ( @@ -71,38 +76,44 @@ export const LoadingVideo = ({ ) : status === "DOWNLOADED" ? ( <>Download Completed: building video... - ) : status !== "READY" ? ( + ) : status === "FAILED_TO_DOWNLOAD" ? ( + <>Unable to fetch video chunks from peers + ) : ( <> {getDownloadProgress( percentLoaded )} - ) : ( - <>Fetching video... )} )} + {status === 'FAILED_TO_DOWNLOAD' && ( + + )} )} {(status === 'INITIAL') && ( <> - { togglePlay(); }} + sx={{ cursor: "pointer", + borderRadius: "10px", + position:"absolute", + top:0, + left:0, + right:0, + bottom:0, + zIndex: 501, + background: 'rgba(0,0,0,0.3)', }} > - + )} diff --git a/src/components/VideoPlayer/VideoPlayer.tsx b/src/components/VideoPlayer/VideoPlayer.tsx index 882dbc5..c6e40a0 100644 --- a/src/components/VideoPlayer/VideoPlayer.tsx +++ b/src/components/VideoPlayer/VideoPlayer.tsx @@ -32,7 +32,6 @@ import convert from "srt-webvtt"; import { TimelineActionsComponent } from "./TimelineActionsComponent"; import { PlayBackMenu } from "./VideoControls"; import { useGlobalPlayerStore } from "../../state/pip"; -import { LocationContext } from "../../context/GlobalProvider"; import { alpha, Box, @@ -42,6 +41,7 @@ import { ListItem, } from "@mui/material"; import { MobileControls } from "./MobileControls"; +import { useLocation } from "react-router-dom"; export async function srtBase64ToVttBlobUrl( base64Srt: string @@ -160,7 +160,7 @@ export const VideoPlayer = ({ const [isOpenSubtitleManage, setIsOpenSubtitleManage] = useState(false); const subtitleBtnRef = useRef(null); const [currentSubTrack, setCurrentSubTrack] = useState(null); - const location = useContext(LocationContext); + const location = useLocation() const locationRef = useRef(null); const [isOpenPlaybackMenu, setIsOpenPlaybackmenu] = useState(false); @@ -190,6 +190,7 @@ export const VideoPlayer = ({ onSelectPlaybackRate, seekTo, togglePictureInPicture, + downloadResource } = useVideoPlayerController({ autoPlay, playerRef, @@ -849,13 +850,15 @@ export const VideoPlayer = ({ status={status} percentLoaded={percentLoaded} isLoading={isLoading} + startPlay={startPlay} + downloadResource={downloadResource} /> { const { playbackSettings, setPlaybackRate, setVolume } = useVideoStore(); const { getProgress } = useProgressStore(); - const { isReady, resourceUrl, status, percentLoaded } = useResourceStatus({ + const { isReady, resourceUrl, status, percentLoaded, downloadResource } = useResourceStatus({ resource: !startedFetch ? null : qortalVideoResource, retryAttempts, }); @@ -326,6 +326,6 @@ const togglePlay = useCallback(async () => { isReady, resourceUrl, startPlay, - status, percentLoaded, showControlsFullScreen, onSelectPlaybackRate: updatePlaybackRate, seekTo, togglePictureInPicture + status, percentLoaded, showControlsFullScreen, onSelectPlaybackRate: updatePlaybackRate, seekTo, togglePictureInPicture, downloadResource }; }; diff --git a/src/context/GlobalProvider.tsx b/src/context/GlobalProvider.tsx index d130677..32c31d5 100644 --- a/src/context/GlobalProvider.tsx +++ b/src/context/GlobalProvider.tsx @@ -28,7 +28,6 @@ interface GlobalContextType { identifierOperations: ReturnType; persistentOperations: ReturnType; indexOperations: ReturnType; - navigate: NavigateFunction } // ✅ Define Config Type for Hook Options @@ -40,15 +39,13 @@ interface GlobalProviderProps { appName: string; publicSalt: string; }; - navigate: NavigateFunction - location: Location + toastStyle?: CSSProperties; } // ✅ Create Context with Proper Type export const GlobalContext = createContext(null); -export const LocationContext = createContext(null); @@ -57,8 +54,6 @@ export const GlobalProvider = ({ children, config, toastStyle = {}, - navigate, - location }: GlobalProviderProps) => { // ✅ Call hooks and pass in options dynamically const auth = useAuth(config?.auth || {}); @@ -84,9 +79,8 @@ export const GlobalProvider = ({ identifierOperations, persistentOperations, indexOperations, - navigate }), - [auth, lists, appInfo, identifierOperations, persistentOperations, navigate] + [auth, lists, appInfo, identifierOperations, persistentOperations] ); const { clearOldProgress } = useProgressStore(); @@ -95,7 +89,6 @@ export const GlobalProvider = ({ }, []); return ( - @@ -115,7 +108,6 @@ export const GlobalProvider = ({ {children} - ); }; diff --git a/src/hooks/useGlobalPipPlayer.tsx b/src/hooks/useGlobalPipPlayer.tsx index 308ebac..b673ecc 100644 --- a/src/hooks/useGlobalPipPlayer.tsx +++ b/src/hooks/useGlobalPipPlayer.tsx @@ -12,6 +12,7 @@ import PauseIcon from "@mui/icons-material/Pause"; import OpenInFullIcon from "@mui/icons-material/OpenInFull"; import { GlobalContext } from "../context/GlobalProvider"; import { isTouchDevice } from "../components/VideoPlayer/VideoPlayer"; +import { useNavigate } from "react-router-dom"; export const GlobalPipPlayer = () => { const { videoSrc, @@ -29,7 +30,7 @@ export const GlobalPipPlayer = () => { const containerRef = useRef(null); const context = useContext(GlobalContext); - const navigate = context?.navigate; + const navigate = useNavigate() const videoNode = useRef(null); const hideTimeoutRef = useRef(null); const { setProgress } = useProgressStore(); diff --git a/src/hooks/useResourceStatus.tsx b/src/hooks/useResourceStatus.tsx index 8059edd..1eb0ad5 100644 --- a/src/hooks/useResourceStatus.tsx +++ b/src/hooks/useResourceStatus.tsx @@ -21,8 +21,9 @@ export const useResourceStatus = ({ statusRef.current = status }, [status]) const downloadResource = useCallback( - ({ service, name, identifier }: QortalGetMetadata, build?: boolean) => { + ({ service, name, identifier }: QortalGetMetadata, build?: boolean, isRecalling?: boolean) => { try { + console.log('started2') if(statusRef.current && statusRef.current?.status === 'READY'){ if (intervalRef.current) { clearInterval(intervalRef.current); @@ -30,9 +31,12 @@ export const useResourceStatus = ({ if (timeoutRef.current) { clearTimeout(timeoutRef.current); } + intervalRef.current = null; + timeoutRef.current = null; return } - setResourceStatus( + if(!isRecalling){ + setResourceStatus( { service, name, identifier }, { "status": "SEARCHING", @@ -41,6 +45,7 @@ export const useResourceStatus = ({ "percentLoaded": 0 } ); + } let isCalling = false; let percentLoaded = 0; let timer = 24; @@ -73,6 +78,8 @@ export const useResourceStatus = ({ if (timeoutRef.current) { clearTimeout(timeoutRef.current); } + intervalRef.current = null; + timeoutRef.current = null; setResourceStatus( { service, name, identifier }, { @@ -80,7 +87,7 @@ export const useResourceStatus = ({ status: "FAILED_TO_DOWNLOAD", } ); - + return; } tries = tries + 1; @@ -124,7 +131,7 @@ export const useResourceStatus = ({ timeoutRef.current = setTimeout(() => { isCalling = false; - downloadResource({ name, service, identifier }, true); + downloadResource({ name, service, identifier }, true, true); }, 25000); return; @@ -140,18 +147,25 @@ export const useResourceStatus = ({ } ); } - + console.log('res?.status', res?.status) // Check if progress is 100% and clear interval if true if (res?.status === "READY") { + if (intervalRef.current) { + console.log('clearing 11') clearInterval(intervalRef.current); } if (timeoutRef.current) { + console.log('clearing 22') clearTimeout(timeoutRef.current); } + intervalRef.current = null; + timeoutRef.current = null; setResourceStatus({service, name, identifier}, { ...res, }) + console.log('returned') + return } if (res?.status === "DOWNLOADED") { const url = `/arbitrary/resource/status/${service}/${name}/${identifier}?build=true`; @@ -164,18 +178,30 @@ export const useResourceStatus = ({ res = await resCall.json(); } }; - callFunction(); - intervalRef.current = setInterval(async () => { - callFunction(); - }, 5000); + callFunction(); + + if (!intervalRef.current) { + intervalRef.current = setInterval(callFunction, 5000); + } } catch (error) { console.error("Error during resource fetch:", error); } + return ()=> { + if (intervalRef.current) { + clearInterval(intervalRef.current); + intervalRef.current = null + } + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + timeoutRef.current = null + } + } }, [retryAttempts] ); useEffect(() => { if (resource?.identifier && resource?.name && resource?.service) { + statusRef.current = null downloadResource({ service: resource?.service, name: resource?.name, @@ -185,9 +211,11 @@ export const useResourceStatus = ({ return ()=> { if(intervalRef.current){ clearInterval(intervalRef.current) + intervalRef.current = null } if(timeoutRef.current){ clearTimeout(timeoutRef.current) + timeoutRef.current = null } } }, [ @@ -197,6 +225,29 @@ export const useResourceStatus = ({ downloadResource, ]); + const handledownloadResource = useCallback(()=> { +if (resource?.identifier && resource?.name && resource?.service) { + if(intervalRef.current){ + clearInterval(intervalRef.current) + intervalRef.current = null + } + if(timeoutRef.current){ + clearTimeout(timeoutRef.current) + timeoutRef.current = null + } + + downloadResource({ + service: resource?.service, + name: resource?.name, + identifier: resource?.identifier, + }); + } + + }, [resource?.identifier, + resource?.name, + resource?.service, + downloadResource]) + const resourceUrl = resource ? `/arbitrary/${resource.service}/${resource.name}/${resource.identifier}` : null; return useMemo(() => ({ @@ -206,6 +257,7 @@ export const useResourceStatus = ({ percentLoaded: status?.percentLoaded || 0, isReady: status?.status === 'READY', resourceUrl, - }), [status?.status, status?.localChunkCount, status?.totalChunkCount, status?.percentLoaded, resourceUrl]); + downloadResource: handledownloadResource + }), [status?.status, status?.localChunkCount, status?.totalChunkCount, status?.percentLoaded, resourceUrl, downloadResource]); }; diff --git a/src/index.ts b/src/index.ts index 7eff849..55d1860 100644 --- a/src/index.ts +++ b/src/index.ts @@ -16,7 +16,7 @@ export { IndexCategory } from './state/indexes'; export { hashWordWithoutPublicSalt } from './utils/encryption'; export { createAvatarLink } from './utils/qortal'; export { objectToBase64 } from './utils/base64'; -export { generateBloomFilterBase64, isInsideBloom } from './utils/bloomFilter'; + export { addAndEncryptSymmetricKeys, decryptWithSymmetricKeys, encryptWithSymmetricKeys } from './utils/encryption'; export { base64ToObject } from './utils/publish'; export { formatTimestamp } from './utils/time'; diff --git a/src/utils/bloomFilter.ts b/src/utils/bloomFilter.ts deleted file mode 100644 index 3d324da..0000000 --- a/src/utils/bloomFilter.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { base64ToObject } from './base64'; -import { Buffer } from 'buffer' - -// Polyfill Buffer first -if (!(globalThis as any).Buffer) { - ;(globalThis as any).Buffer = Buffer -} - -async function getBloomFilter() { - const { BloomFilter } = await import('bloom-filters') - return BloomFilter -} - - - - - - export async function generateBloomFilterBase64(values: string[]) { - const maxItems = 100 - if (values.length > maxItems) { - throw new Error(`Max ${maxItems} items allowed`) - } - - // Create filter for the expected number of items and desired false positive rate - const BloomFilter = await getBloomFilter() - const bloom = BloomFilter.create(values.length, 0.025) // ~0.04% FPR - - for (const value of values) { - bloom.add(value) - } - - // Convert filter to JSON, then to base64 - const json = bloom.saveAsJSON() - const jsonString = JSON.stringify(json) - const base64 = Buffer.from(jsonString).toString('base64') - - const size = Buffer.byteLength(jsonString) - if (size > 238) { - throw new Error(`Bloom filter exceeds 230 bytes: ${size}`) - } - - return base64 - } - - -export async function isInsideBloom(base64Bloom: string, userPublicKey: string) { - const base64ToJson = base64ToObject(base64Bloom) - const BloomFilter = await getBloomFilter() - const bloom = BloomFilter.fromJSON(base64ToJson) - - - return bloom.has(userPublicKey); - } - \ No newline at end of file