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