update resourceStatus

This commit is contained in:
PhilReact 2025-06-24 11:26:58 +03:00
parent 28093534b8
commit 4249241ab7
10 changed files with 115 additions and 420 deletions

321
package-lock.json generated
View File

@ -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",

View File

@ -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",

View File

@ -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" && (
<CircularProgress color="secondary" />
{status !== "NOT_PUBLISHED" && status !== "FAILED_TO_DOWNLOAD" && (
<CircularProgress sx={{
color: 'white'
}} />
)}
{status && (
<Typography
variant="subtitle2"
component="div"
sx={{
color: "white",
fontSize: "15px",
textAlign: "center",
fontFamily: "sans-serif"
}}
>
@ -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...</>
)}
</Typography>
)}
{status === 'FAILED_TO_DOWNLOAD' && (
<Button variant="outlined" onClick={downloadResource} sx={{
color: 'white'
}}>Try again</Button>
)}
</Box>
)}
{(status === 'INITIAL') && (
<>
<Box
position="absolute"
top={0}
left={0}
right={0}
bottom={0}
display="flex"
justifyContent="center"
alignItems="center"
zIndex={500}
bgcolor="rgba(0, 0, 0, 0.6)"
<IconButton
onClick={() => {
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)',
}}
>
<PlayArrow
@ -112,7 +123,7 @@ export const LoadingVideo = ({
color: "white",
}}
/>
</Box>
</IconButton>
</>
)}
</>

View File

@ -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 | string>(null);
const location = useContext(LocationContext);
const location = useLocation()
const locationRef = useRef<string | null>(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}
/>
<VideoElement
ref={videoRef}
tabIndex={-1}
className="video-js"
src={isReady && startPlay ? resourceUrl || undefined : undefined}
poster={startPlay ? "" : poster}
poster={poster}
onTimeUpdate={updateProgress}
autoPlay={autoPlay}
onClick={handleClickVideoElement}

View File

@ -44,7 +44,7 @@ export const useVideoPlayerController = (props: UseVideoControls) => {
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
};
};

View File

@ -28,7 +28,6 @@ interface GlobalContextType {
identifierOperations: ReturnType<typeof useIdentifiers>;
persistentOperations: ReturnType<typeof usePersistentStore>;
indexOperations: ReturnType<typeof useIndexes>;
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<GlobalContextType | null>(null);
export const LocationContext = createContext<Location | null>(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 (
<LocationContext.Provider value={location}>
<GlobalContext.Provider value={contextValue}>
<GlobalPipPlayer />
@ -115,7 +108,6 @@ export const GlobalProvider = ({
{children}
</GlobalContext.Provider>
</LocationContext.Provider>
);
};

View File

@ -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<HTMLDivElement | null>(null);
const context = useContext(GlobalContext);
const navigate = context?.navigate;
const navigate = useNavigate()
const videoNode = useRef<HTMLVideoElement>(null);
const hideTimeoutRef = useRef<number | null>(null);
const { setProgress } = useProgressStore();

View File

@ -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]);
};

View File

@ -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';

View File

@ -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);
}