mirror of
https://github.com/zoriya/react-native-omni.git
synced 2026-08-05 05:36:17 +00:00
Init videojs v10 implementation
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
"name": "react-native-omni",
|
||||
"dependencies": {
|
||||
"@expo/config-plugins": "^10.0.2",
|
||||
"@videojs/react": "^10.0.0-beta.24",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "2.4.10",
|
||||
@@ -477,6 +478,26 @@
|
||||
|
||||
"@sinonjs/fake-timers": ["@sinonjs/fake-timers@10.3.0", "", { "dependencies": { "@sinonjs/commons": "^3.0.0" } }, "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA=="],
|
||||
|
||||
"@svta/cml-608": ["@svta/cml-608@1.0.1", "", {}, "sha512-Y/Ier9VPUSOBnf0bJqdDyTlPrt4dDB+jk5mYHa1bnD2kcRl8qn7KkW3PRuj4w1aVN+BS2eHmsLxodt7P2hylUg=="],
|
||||
|
||||
"@svta/cml-cmcd": ["@svta/cml-cmcd@1.0.1", "", { "peerDependencies": { "@svta/cml-cta": "1.0.1", "@svta/cml-structured-field-values": "1.0.1", "@svta/cml-utils": "1.0.1" } }, "sha512-eox305g+QUJgXqOLVrbgxeQHCgl90ewwQ9O2bIoo7m+hanR8Xswu5CknFnT5qqIbLOHfw80ug+raycoAFHTQ+w=="],
|
||||
|
||||
"@svta/cml-cmsd": ["@svta/cml-cmsd@1.0.1", "", { "peerDependencies": { "@svta/cml-cta": "1.0.1", "@svta/cml-structured-field-values": "1.0.1", "@svta/cml-utils": "1.0.1" } }, "sha512-+nIB8PuSfb/qw+xGaArPhNqPm84tBJUbe3H1DnPL5QUsjSUI7mUIUQwAtRV1ZdEu0+80g9i0op79woB0OIwr/g=="],
|
||||
|
||||
"@svta/cml-cta": ["@svta/cml-cta@1.0.1", "", { "peerDependencies": { "@svta/cml-structured-field-values": "1.0.1", "@svta/cml-utils": "1.0.1" } }, "sha512-jcXqNIPv26bmFxIOFh8/c3+6WLH4qBjKpq9qTQcggDPoHuV1YBydMsJLOnYPDeK8rNMKcAkFLbnDRvyJthu5yw=="],
|
||||
|
||||
"@svta/cml-dash": ["@svta/cml-dash@1.0.1", "", { "peerDependencies": { "@svta/cml-utils": "1.0.1" } }, "sha512-lYnD1I7FUbbQND+xICI+kcRaRXuT+whKk27R8m8me5VMVu2sMsAMc7Yui6l9sxw2cBKt8pSETPYRm/1+n4LZkw=="],
|
||||
|
||||
"@svta/cml-id3": ["@svta/cml-id3@1.0.1", "", { "peerDependencies": { "@svta/cml-utils": "1.0.1" } }, "sha512-90fGlL1qRI88CcaB89k6NG6cC3kky4Eu2jwqU4HefqK+S5k2OASUxf8JXkGz+DsdaiY7sh51vGPYdolfBZS7ug=="],
|
||||
|
||||
"@svta/cml-request": ["@svta/cml-request@1.0.1", "", { "peerDependencies": { "@svta/cml-utils": "1.0.1", "@svta/cml-xml": "1.0.1" } }, "sha512-enL19BuXUjFkDDDF9jdNwUclMNPRsagnjGAetVC7xcmpDMpEx+ZLgsDip6BFNg5p6izSEk/OyujTWW1r8bDNiA=="],
|
||||
|
||||
"@svta/cml-structured-field-values": ["@svta/cml-structured-field-values@1.0.1", "", { "peerDependencies": { "@svta/cml-utils": "1.0.1" } }, "sha512-Kibciki59Pon3Pn/sl5uyrbJcSpZQDKqdCfDrokBvOdLoqqcd0oFrkEPsZBiuuIODX1CB80612xe8hopeFDyBA=="],
|
||||
|
||||
"@svta/cml-utils": ["@svta/cml-utils@1.0.1", "", {}, "sha512-kso3curTJfp00I1mKFoBliBApjn4aPE+wF8cPucf7TrSDVWZDeLLuF14ASmUE9m7rnrqTTK4878VvmXaXcCCfQ=="],
|
||||
|
||||
"@svta/cml-xml": ["@svta/cml-xml@1.0.1", "", { "peerDependencies": { "@svta/cml-utils": "1.0.1" } }, "sha512-11LkJa5kDEcsRMWkVI1ABH3KLCxGoiSVe4kQ293ItVj8ncTTQ7htmCGiJDjS+Cmy35UgF3e/vc0ysJIiWRTx2g=="],
|
||||
|
||||
"@ts-morph/common": ["@ts-morph/common@0.28.1", "", { "dependencies": { "minimatch": "^10.0.1", "path-browserify": "^1.0.1", "tinyglobby": "^0.2.14" } }, "sha512-W74iWf7ILp1ZKNYXY5qbddNaml7e9Sedv5lvU1V8lftlitkc9Pq1A+jlH23ltDgWYeZFFEqGCD1Ies9hqu3O+g=="],
|
||||
|
||||
"@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="],
|
||||
@@ -531,6 +552,16 @@
|
||||
|
||||
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-XJ9UD9+bbDo4a4epraTwG3TsNPeiB9aShrUneAVXy8q4LuwowN+qu89/6ByLMINqvIMeI9H9hOHQtg/ijrYXzQ=="],
|
||||
|
||||
"@videojs/core": ["@videojs/core@10.0.0-beta.24", "", { "dependencies": { "@videojs/spf": "10.0.0-beta.24", "@videojs/store": "10.0.0-beta.24", "@videojs/utils": "10.0.0-beta.24", "dashjs": "^5.0.0", "hls.js": "^1.6.7", "mux-embed": "^5.17.10" } }, "sha512-v18EkiyxNkLvCccZ3yPWO5J2OLWehTueNywhLFcLLltfLqO6OvKG2Gg2RUVYFcOEWS5e9CpUmrXOVAWUzYAuMw=="],
|
||||
|
||||
"@videojs/react": ["@videojs/react@10.0.0-beta.24", "", { "dependencies": { "@videojs/core": "10.0.0-beta.24", "@videojs/spf": "10.0.0-beta.24", "@videojs/store": "10.0.0-beta.24", "@videojs/utils": "10.0.0-beta.24" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" } }, "sha512-+K2QkZiYfmUz7YREJwLZbCqj5q6xeCGCKU9qBl9v1tqlAhkxbPeCY0ltSv2AHij4v/zxGSjMrRgqpjsphHK2Ow=="],
|
||||
|
||||
"@videojs/spf": ["@videojs/spf@10.0.0-beta.24", "", { "dependencies": { "@videojs/utils": "10.0.0-beta.24", "signal-polyfill": "^0.2.2" } }, "sha512-ACTOHzhCoTJLndyX5lq+k7A3Q9gaJeEdtjgVfbYvV/F8OwEA1zT5gGJnG/bbHC81yI/w51b+YneB8pGJutUTjw=="],
|
||||
|
||||
"@videojs/store": ["@videojs/store@10.0.0-beta.24", "", { "dependencies": { "@videojs/utils": "10.0.0-beta.24" }, "peerDependencies": { "@videojs/element": "10.0.0-beta.24", "react": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@videojs/element", "react"] }, "sha512-gFAozvxGTviFpKVwsrNAo2cNjTcwRDg/AwLs4Gft/XqxSggD7CxilZ9d6W1nTxAbcSMPvrySmnW8wuGtbbPyEw=="],
|
||||
|
||||
"@videojs/utils": ["@videojs/utils@10.0.0-beta.24", "", {}, "sha512-sQvsawB1pQiYJxkGnrdxWrcfmEvjjmGSDcrt47OmI0FQx40GseO+QMzm3XvGuxmy6KOKneCfegHFBt+Ez0MKLw=="],
|
||||
|
||||
"@vscode/sudo-prompt": ["@vscode/sudo-prompt@9.3.2", "", {}, "sha512-gcXoCN00METUNFeQOFJ+C9xUI0DKB+0EGMVg7wbVYRHBw2Eq3fKisDZOkRdOz3kqXRKOENMfShPOmypw1/8nOw=="],
|
||||
|
||||
"@xmldom/xmldom": ["@xmldom/xmldom@0.8.13", "", {}, "sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw=="],
|
||||
@@ -621,6 +652,12 @@
|
||||
|
||||
"baseline-browser-mapping": ["baseline-browser-mapping@2.10.15", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-1nfKCq9wuAZFTkA2ey/3OXXx7GzFjLdkTiFVNwlJ9WqdI706CZRIhEqjuwanjMIja+84jDLa9rcyZDPDiVkASQ=="],
|
||||
|
||||
"bcp-47": ["bcp-47@2.1.0", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w=="],
|
||||
|
||||
"bcp-47-match": ["bcp-47-match@2.0.3", "", {}, "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ=="],
|
||||
|
||||
"bcp-47-normalize": ["bcp-47-normalize@2.3.0", "", { "dependencies": { "bcp-47": "^2.0.0", "bcp-47-match": "^2.0.0" } }, "sha512-8I/wfzqQvttUFz7HVJgIZ7+dj3vUaIyIxYXaTRP1YWoSDfzt6TUmxaKZeuXR62qBmYr+nvuWINFRl6pZ5DlN4Q=="],
|
||||
|
||||
"big-integer": ["big-integer@1.6.52", "", {}, "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg=="],
|
||||
|
||||
"bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="],
|
||||
@@ -677,6 +714,8 @@
|
||||
|
||||
"code-block-writer": ["code-block-writer@13.0.3", "", {}, "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg=="],
|
||||
|
||||
"codem-isoboxer": ["codem-isoboxer@0.3.10", "", {}, "sha512-eNk3TRV+xQMJ1PEj0FQGY8KD4m0GPxT487XJ+Iftm7mVa9WpPFDMWqPt+46buiP5j5Wzqe5oMIhqBcAeKfygSA=="],
|
||||
|
||||
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
||||
|
||||
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
|
||||
@@ -707,6 +746,8 @@
|
||||
|
||||
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
|
||||
|
||||
"dashjs": ["dashjs@5.1.1", "", { "dependencies": { "@svta/cml-608": "1.0.1", "@svta/cml-cmcd": "1.0.1", "@svta/cml-cmsd": "1.0.1", "@svta/cml-dash": "1.0.1", "@svta/cml-id3": "1.0.1", "@svta/cml-request": "1.0.1", "@svta/cml-xml": "1.0.1", "bcp-47-match": "^2.0.3", "bcp-47-normalize": "^2.3.0", "codem-isoboxer": "0.3.10", "fast-deep-equal": "3.1.3", "html-entities": "^2.5.2", "imsc": "^1.1.5", "localforage": "^1.10.0", "path-browserify": "^1.0.1", "ua-parser-js": "^1.0.37" } }, "sha512-BzNXlUgzEjhuZ5M5hlSp1qIyQHZ7NpXAR0loP9DAAFVZj/ntL1DHeZ7qp/L3bvI4rq50X5indkAZQ3zEHWJoCA=="],
|
||||
|
||||
"data-view-buffer": ["data-view-buffer@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ=="],
|
||||
|
||||
"data-view-byte-length": ["data-view-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ=="],
|
||||
@@ -939,6 +980,10 @@
|
||||
|
||||
"hermes-parser": ["hermes-parser@0.32.0", "", { "dependencies": { "hermes-estree": "0.32.0" } }, "sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw=="],
|
||||
|
||||
"hls.js": ["hls.js@1.6.16", "", {}, "sha512-VSIRpLfRwlAAdGL4wiTucx2ScRipo0ed1FBatWkyt832jC4CReKstga6yIhYVwGu9LOBjuX9wzmRMeQdBJtzEA=="],
|
||||
|
||||
"html-entities": ["html-entities@2.6.0", "", {}, "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ=="],
|
||||
|
||||
"http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="],
|
||||
|
||||
"https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="],
|
||||
@@ -953,8 +998,12 @@
|
||||
|
||||
"image-size": ["image-size@1.2.1", "", { "dependencies": { "queue": "6.0.2" }, "bin": { "image-size": "bin/image-size.js" } }, "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw=="],
|
||||
|
||||
"immediate": ["immediate@3.0.6", "", {}, "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="],
|
||||
|
||||
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
|
||||
|
||||
"imsc": ["imsc@1.1.5", "", { "dependencies": { "sax": "1.2.1" } }, "sha512-V8je+CGkcvGhgl2C1GlhqFFiUOIEdwXbXLiu1Fcubvvbo+g9inauqT3l0pNYXGoLPBj3jxtZz9t+wCopMkwadQ=="],
|
||||
|
||||
"imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
|
||||
|
||||
"indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="],
|
||||
@@ -969,6 +1018,10 @@
|
||||
|
||||
"is-absolute": ["is-absolute@1.0.0", "", { "dependencies": { "is-relative": "^1.0.0", "is-windows": "^1.0.1" } }, "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA=="],
|
||||
|
||||
"is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="],
|
||||
|
||||
"is-alphanumerical": ["is-alphanumerical@2.0.1", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw=="],
|
||||
|
||||
"is-array-buffer": ["is-array-buffer@3.0.5", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A=="],
|
||||
|
||||
"is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="],
|
||||
@@ -987,6 +1040,8 @@
|
||||
|
||||
"is-date-object": ["is-date-object@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg=="],
|
||||
|
||||
"is-decimal": ["is-decimal@2.0.1", "", {}, "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="],
|
||||
|
||||
"is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="],
|
||||
|
||||
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
|
||||
@@ -1115,10 +1170,14 @@
|
||||
|
||||
"levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
|
||||
|
||||
"lie": ["lie@3.1.1", "", { "dependencies": { "immediate": "~3.0.5" } }, "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw=="],
|
||||
|
||||
"lighthouse-logger": ["lighthouse-logger@1.4.2", "", { "dependencies": { "debug": "^2.6.9", "marky": "^1.2.2" } }, "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g=="],
|
||||
|
||||
"lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="],
|
||||
|
||||
"localforage": ["localforage@1.10.0", "", { "dependencies": { "lie": "3.1.1" } }, "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg=="],
|
||||
|
||||
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
|
||||
|
||||
"lodash": ["lodash@4.18.1", "", {}, "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q=="],
|
||||
@@ -1197,6 +1256,8 @@
|
||||
|
||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||
|
||||
"mux-embed": ["mux-embed@5.18.1", "", {}, "sha512-ePsHjiEKY+FgrSBiMmaF+LOtTQSSBWv/1zqpREQFN96JE93xlsArT/MEi30yKOE06MgjOlL70YI750molu3y7g=="],
|
||||
|
||||
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
|
||||
|
||||
"negotiator": ["negotiator@0.6.4", "", {}, "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w=="],
|
||||
@@ -1323,6 +1384,8 @@
|
||||
|
||||
"react-devtools-core": ["react-devtools-core@6.1.5", "", { "dependencies": { "shell-quote": "^1.6.1", "ws": "^7" } }, "sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA=="],
|
||||
|
||||
"react-dom": ["react-dom@19.2.6", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.6" } }, "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g=="],
|
||||
|
||||
"react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
|
||||
|
||||
"react-native": ["react-native@0.84.1", "", { "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native/assets-registry": "0.84.1", "@react-native/codegen": "0.84.1", "@react-native/community-cli-plugin": "0.84.1", "@react-native/gradle-plugin": "0.84.1", "@react-native/js-polyfills": "0.84.1", "@react-native/normalize-colors": "0.84.1", "@react-native/virtualized-lists": "0.84.1", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", "babel-jest": "^29.7.0", "babel-plugin-syntax-hermes-parser": "0.32.0", "base64-js": "^1.5.1", "commander": "^12.0.0", "flow-enums-runtime": "^0.0.6", "hermes-compiler": "250829098.0.9", "invariant": "^2.2.4", "jest-environment-node": "^29.7.0", "memoize-one": "^5.0.0", "metro-runtime": "^0.83.3", "metro-source-map": "^0.83.3", "nullthrows": "^1.1.1", "pretty-format": "^29.7.0", "promise": "^8.3.0", "react-devtools-core": "^6.1.5", "react-refresh": "^0.14.0", "regenerator-runtime": "^0.13.2", "scheduler": "0.27.0", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "tinyglobby": "^0.2.15", "whatwg-fetch": "^3.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "peerDependencies": { "@types/react": "^19.1.1", "react": "^19.2.3" }, "optionalPeers": ["@types/react"], "bin": { "react-native": "cli.js" } }, "sha512-0PjxOyXRu3tZ8EobabxSukvhKje2HJbsZikR0U+pvS0pYZza2hXKjcSBiBdFN4h9D0S3v6a8kkrDK6WTRKMwzg=="],
|
||||
@@ -1423,6 +1486,8 @@
|
||||
|
||||
"signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
|
||||
|
||||
"signal-polyfill": ["signal-polyfill@0.2.2", "", {}, "sha512-p63Y4Er5/eMQ9RHg0M0Y64NlsQKpiu6MDdhBXpyywRuWiPywhJTpKJ1iB5K2hJEbFZ0BnDS7ZkJ+0AfTuL37Rg=="],
|
||||
|
||||
"simple-plist": ["simple-plist@1.3.1", "", { "dependencies": { "bplist-creator": "0.1.0", "bplist-parser": "0.3.1", "plist": "^3.0.5" } }, "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw=="],
|
||||
|
||||
"sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
|
||||
@@ -1519,6 +1584,8 @@
|
||||
|
||||
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||
|
||||
"ua-parser-js": ["ua-parser-js@1.0.41", "", { "bin": { "ua-parser-js": "script/cli.js" } }, "sha512-LbBDqdIC5s8iROCUjMbW1f5dJQTEFB1+KO9ogbvlb3nm9n4YHa5p4KTvFPWvh2Hs8gZMBuiB1/8+pdfe/tDPug=="],
|
||||
|
||||
"unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="],
|
||||
|
||||
"unc-path-regex": ["unc-path-regex@0.1.2", "", {}, "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg=="],
|
||||
@@ -1727,6 +1794,8 @@
|
||||
|
||||
"import-fresh/resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
|
||||
|
||||
"imsc/sax": ["sax@1.2.1", "", {}, "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA=="],
|
||||
|
||||
"is-git-dirty/execa": ["execa@4.1.0", "", { "dependencies": { "cross-spawn": "^7.0.0", "get-stream": "^5.0.0", "human-signals": "^1.1.1", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^4.0.0", "onetime": "^5.1.0", "signal-exit": "^3.0.2", "strip-final-newline": "^2.0.0" } }, "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA=="],
|
||||
|
||||
"is-git-repository/execa": ["execa@4.1.0", "", { "dependencies": { "cross-spawn": "^7.0.0", "get-stream": "^5.0.0", "human-signals": "^1.1.1", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^4.0.0", "onetime": "^5.1.0", "signal-exit": "^3.0.2", "strip-final-newline": "^2.0.0" } }, "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA=="],
|
||||
|
||||
+2
-1
@@ -56,7 +56,8 @@
|
||||
"registry": "https://registry.npmjs.org/"
|
||||
},
|
||||
"dependencies": {
|
||||
"@expo/config-plugins": "^10.0.2"
|
||||
"@expo/config-plugins": "^10.0.2",
|
||||
"@videojs/react": "^10.0.0-beta.24"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "2.4.10",
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { usePlayer } from "./provider.web";
|
||||
import type { OmniEvents } from "./types/events";
|
||||
import type { OmniPlayerState, PlayerStatus } from "./types/player";
|
||||
|
||||
export const useEvent = <Event extends keyof OmniEvents>(
|
||||
event: Event,
|
||||
callback: OmniEvents[Event],
|
||||
) => {
|
||||
const player = usePlayer();
|
||||
const callbackRef = useRef(callback);
|
||||
callbackRef.current = callback;
|
||||
|
||||
useEffect(() => {
|
||||
const store = player.store;
|
||||
const media = store.state.media as any;
|
||||
|
||||
if (!media) return;
|
||||
|
||||
switch (event) {
|
||||
case "end": {
|
||||
const handler = () => (callbackRef.current as OmniEvents["end"])();
|
||||
media.addEventListener("ended", handler);
|
||||
return () => media.removeEventListener("ended", handler);
|
||||
}
|
||||
case "error": {
|
||||
const handler = () => {
|
||||
const error = store.state.error;
|
||||
(callbackRef.current as OmniEvents["error"])(
|
||||
error?.message ?? "Unknown error",
|
||||
error?.message ?? "Unknown error",
|
||||
);
|
||||
};
|
||||
media.addEventListener("error", handler);
|
||||
return () => media.removeEventListener("error", handler);
|
||||
}
|
||||
case "prev": {
|
||||
const handler = () => (callbackRef.current as OmniEvents["prev"])();
|
||||
store.state.onPrev = handler;
|
||||
return () => {
|
||||
if (store.state.onPrev === handler) store.state.onPrev = undefined;
|
||||
};
|
||||
}
|
||||
case "next": {
|
||||
const handler = () => (callbackRef.current as OmniEvents["next"])();
|
||||
store.state.onNext = handler;
|
||||
return () => {
|
||||
if (store.state.onNext === handler) store.state.onNext = undefined;
|
||||
};
|
||||
}
|
||||
case "videoTrackChange": {
|
||||
const handler = () => {
|
||||
if (!media.videoTracks?.length) return;
|
||||
for (let i = 0; i < media.videoTracks.length; i++) {
|
||||
const track = media.videoTracks[i];
|
||||
if (track?.enabled) {
|
||||
(callbackRef.current as OmniEvents["videoTrackChange"])({
|
||||
id: track.id || `video-${i}`,
|
||||
label: track.label,
|
||||
language: track.language,
|
||||
selected: true,
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
media.videoTracks?.addEventListener("change", handler);
|
||||
return () =>
|
||||
media.videoTracks?.removeEventListener("change", handler);
|
||||
}
|
||||
case "audioTrackChange": {
|
||||
const handler = () => {
|
||||
if (!media.audioTracks?.length) return;
|
||||
for (let i = 0; i < media.audioTracks.length; i++) {
|
||||
const track = media.audioTracks[i];
|
||||
if (track?.enabled) {
|
||||
(callbackRef.current as OmniEvents["audioTrackChange"])({
|
||||
id: track.id || `audio-${i}`,
|
||||
label: track.label,
|
||||
language: track.language,
|
||||
selected: true,
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
media.audioTracks?.addEventListener("change", handler);
|
||||
return () =>
|
||||
media.audioTracks?.removeEventListener("change", handler);
|
||||
}
|
||||
case "subtitleChange": {
|
||||
const handler = () => {
|
||||
if (!media.textTracks?.length) return;
|
||||
for (let i = 0; i < media.textTracks.length; i++) {
|
||||
const track = media.textTracks[i];
|
||||
if (track?.mode === "showing") {
|
||||
(callbackRef.current as OmniEvents["subtitleChange"])({
|
||||
id: track.id || `text-${i}`,
|
||||
label: track.label,
|
||||
language: track.language,
|
||||
selected: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
(callbackRef.current as OmniEvents["subtitleChange"])(undefined);
|
||||
};
|
||||
media.textTracks?.addEventListener("cuechange", handler);
|
||||
return () =>
|
||||
media.textTracks?.removeEventListener("cuechange", handler);
|
||||
}
|
||||
case "audioFocusChange":
|
||||
case "renditionChange":
|
||||
return;
|
||||
}
|
||||
}, [player, event]);
|
||||
};
|
||||
|
||||
export function usePlayerState<Key extends keyof OmniPlayerState>(
|
||||
key: Key,
|
||||
): OmniPlayerState[Key];
|
||||
export function usePlayerState(
|
||||
key: "currentTime",
|
||||
refresh?: number,
|
||||
): OmniPlayerState["currentTime"];
|
||||
export function usePlayerState<Key extends keyof OmniPlayerState>(
|
||||
key: Key,
|
||||
refresh?: number,
|
||||
): OmniPlayerState[Key] {
|
||||
const player = usePlayer();
|
||||
const store = player.store;
|
||||
const [ret, setState] = useState<any>(player[key]);
|
||||
|
||||
useEffect(() => {
|
||||
switch (key) {
|
||||
case "currentTime":
|
||||
case "buffered":
|
||||
case "duration":
|
||||
case "playbackRate":
|
||||
case "volume": {
|
||||
setState(store.state[key]);
|
||||
const handler = () => setState(store.state[key]);
|
||||
const unsub = store.subscribe(handler);
|
||||
return unsub;
|
||||
}
|
||||
case "isPlaying":
|
||||
case "muted":
|
||||
case "isAutoQuality": {
|
||||
setState(player[key]);
|
||||
const handler = () => setState(player[key]);
|
||||
const unsub = store.subscribe(handler);
|
||||
return unsub;
|
||||
}
|
||||
case "status": {
|
||||
const prevRef = { current: player.status as PlayerStatus };
|
||||
setState(prevRef.current);
|
||||
const int = setInterval(() => {
|
||||
const status = player.status;
|
||||
if (status !== prevRef.current) {
|
||||
prevRef.current = status;
|
||||
setState(status);
|
||||
}
|
||||
}, 100);
|
||||
return () => clearInterval(int);
|
||||
}
|
||||
}
|
||||
}, [player, key, store]);
|
||||
|
||||
if (key === "currentTime") refresh ??= 1;
|
||||
useEffect(() => {
|
||||
if (!refresh || refresh <= 0) return;
|
||||
const int = setInterval(() => {
|
||||
setState(player[key]);
|
||||
}, refresh * 1000);
|
||||
return () => clearInterval(int);
|
||||
}, [refresh, key, player]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
import { createPlayer } from "@videojs/react";
|
||||
import { videoFeatures } from "@videojs/react/video";
|
||||
import {
|
||||
createContext,
|
||||
type ReactNode,
|
||||
useContext,
|
||||
useEffect,
|
||||
} from "react";
|
||||
import type { PlayerStatus, Rendition, Track } from "./types/player";
|
||||
import type { Source } from "./types/source";
|
||||
import { useLazyRef } from "./utils/lazy-ref";
|
||||
|
||||
export const VideoPlayer = createPlayer({ features: videoFeatures });
|
||||
|
||||
const PlayerCtx = createContext<WebOmniPlayer>(null!);
|
||||
|
||||
export const OmniProvider = ({
|
||||
children,
|
||||
source,
|
||||
showNotification = false,
|
||||
}: {
|
||||
source: Source;
|
||||
children: ReactNode;
|
||||
showNotification?: boolean;
|
||||
}) => {
|
||||
return (
|
||||
<VideoPlayer.Provider>
|
||||
<PlayerInitializer source={source} showNotification={showNotification}>
|
||||
{children}
|
||||
</PlayerInitializer>
|
||||
</VideoPlayer.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
const PlayerInitializer = ({
|
||||
children,
|
||||
source,
|
||||
showNotification,
|
||||
}: {
|
||||
children: ReactNode;
|
||||
source: Source;
|
||||
showNotification: boolean;
|
||||
}) => {
|
||||
const store = VideoPlayer.usePlayer();
|
||||
const player = useLazyRef(() => new WebOmniPlayer(store, source));
|
||||
|
||||
useEffect(() => {
|
||||
player.updateSource(source);
|
||||
}, [source]);
|
||||
|
||||
useEffect(() => {
|
||||
player.showNotification = showNotification;
|
||||
}, [showNotification]);
|
||||
|
||||
return <PlayerCtx.Provider value={player}>{children}</PlayerCtx.Provider>;
|
||||
};
|
||||
|
||||
export const usePlayer = () => useContext(PlayerCtx);
|
||||
|
||||
class WebOmniPlayer {
|
||||
private _store: any;
|
||||
private _source: Source;
|
||||
private _showNotification = false;
|
||||
|
||||
constructor(store: any, source: Source) {
|
||||
this._store = store;
|
||||
this._source = source;
|
||||
}
|
||||
|
||||
get store() {
|
||||
return this._store;
|
||||
}
|
||||
|
||||
setMediaElement(media: HTMLVideoElement | null) {
|
||||
if (media) {
|
||||
this.setupSubtitleTracks(media);
|
||||
}
|
||||
}
|
||||
|
||||
updateSource(source: Source) {
|
||||
this._source = source;
|
||||
}
|
||||
|
||||
get source(): Source {
|
||||
return this._source;
|
||||
}
|
||||
|
||||
set source(source: Source) {
|
||||
this.updateSource(source);
|
||||
}
|
||||
|
||||
get showNotification(): boolean {
|
||||
return this._showNotification;
|
||||
}
|
||||
|
||||
set showNotification(value: boolean) {
|
||||
this._showNotification = value;
|
||||
}
|
||||
|
||||
get status(): PlayerStatus {
|
||||
const state = this._store.state;
|
||||
if (state.error) return "error";
|
||||
if (state.canPlay) return "readyToPlay";
|
||||
if (this._source.src.length > 0) return "loading";
|
||||
return "idle";
|
||||
}
|
||||
|
||||
get isPlaying(): boolean {
|
||||
return !this._store.state.paused && !this._store.state.ended;
|
||||
}
|
||||
|
||||
get currentTime(): number {
|
||||
return this._store.state.currentTime;
|
||||
}
|
||||
|
||||
get buffered(): number {
|
||||
const buffered = this._store.state.buffered;
|
||||
if (!buffered || buffered.length === 0) return 0;
|
||||
const lastRange = buffered[buffered.length - 1];
|
||||
return lastRange ? lastRange[1] : 0;
|
||||
}
|
||||
|
||||
get duration(): number {
|
||||
return this._store.state.duration;
|
||||
}
|
||||
|
||||
get playbackRate(): number {
|
||||
return this._store.state.playbackRate;
|
||||
}
|
||||
|
||||
set playbackRate(rate: number) {
|
||||
this._store.setPlaybackRate(rate);
|
||||
}
|
||||
|
||||
get volume(): number {
|
||||
return this._store.state.volume;
|
||||
}
|
||||
|
||||
set volume(vol: number) {
|
||||
this._store.setVolume(vol);
|
||||
}
|
||||
|
||||
get muted(): boolean {
|
||||
return this._store.state.muted;
|
||||
}
|
||||
|
||||
set muted(value: boolean) {
|
||||
if (value !== this.muted) {
|
||||
this._store.toggleMuted();
|
||||
}
|
||||
}
|
||||
|
||||
get isAutoQuality(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
play(): void {
|
||||
this._store.play();
|
||||
}
|
||||
|
||||
pause(): void {
|
||||
this._store.pause();
|
||||
}
|
||||
|
||||
seekBy(offset: number): void {
|
||||
this._store.seek(this.currentTime + offset).catch(() => {});
|
||||
}
|
||||
|
||||
playPrev(): void {
|
||||
this._store.state.onPrev?.();
|
||||
}
|
||||
|
||||
playNext(): void {
|
||||
this._store.state.onNext?.();
|
||||
}
|
||||
|
||||
get hasPrev(): boolean {
|
||||
return this._source.metadata?.hasPrev ?? false;
|
||||
}
|
||||
|
||||
get hasNext(): boolean {
|
||||
return this._source.metadata?.hasNext ?? false;
|
||||
}
|
||||
|
||||
get videos(): Track[] {
|
||||
const media = this._store.state.media;
|
||||
if (!media?.videoTracks) return [];
|
||||
return Array.from(media.videoTracks).map(
|
||||
(track: any, i: number) => ({
|
||||
id: track.id || `video-${i}`,
|
||||
label: track.label,
|
||||
language: track.language,
|
||||
selected: track.enabled,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
selectVideo(video: Track): void {
|
||||
const media = this._store.state.media;
|
||||
if (!media?.videoTracks) return;
|
||||
for (let i = 0; i < media.videoTracks.length; i++) {
|
||||
media.videoTracks[i].enabled = media.videoTracks[i].id === video.id;
|
||||
}
|
||||
}
|
||||
|
||||
get audios(): Track[] {
|
||||
const media = this._store.state.media;
|
||||
if (!media?.audioTracks) return [];
|
||||
return Array.from(media.audioTracks).map((track: any, i: number) => ({
|
||||
id: track.id || `audio-${i}`,
|
||||
label: track.label,
|
||||
language: track.language,
|
||||
selected: track.enabled,
|
||||
}));
|
||||
}
|
||||
|
||||
selectAudio(audio: Track): void {
|
||||
const media = this._store.state.media;
|
||||
if (!media?.audioTracks) return;
|
||||
for (let i = 0; i < media.audioTracks.length; i++) {
|
||||
media.audioTracks[i].enabled = media.audioTracks[i].id === audio.id;
|
||||
}
|
||||
}
|
||||
|
||||
get subtitles(): Track[] {
|
||||
const sourceSubtitles = this._source.subtitles.map((s) => ({
|
||||
id: s.id,
|
||||
label: s.label,
|
||||
language: s.language,
|
||||
selected: false,
|
||||
}));
|
||||
|
||||
const media = this._store.state.media as any;
|
||||
if (!media?.textTracks) return sourceSubtitles;
|
||||
|
||||
const mediaTracks: Track[] = [];
|
||||
for (let i = 0; i < media.textTracks.length; i++) {
|
||||
const track = media.textTracks[i];
|
||||
if (track && (track.kind === "subtitles" || track.kind === "captions")) {
|
||||
mediaTracks.push({
|
||||
id: track.id || `text-${i}`,
|
||||
label: track.label,
|
||||
language: track.language,
|
||||
selected: track.mode === "showing",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return sourceSubtitles.length > 0 ? sourceSubtitles : mediaTracks;
|
||||
}
|
||||
|
||||
selectSubtitle(subtitle?: Track): void {
|
||||
const media = this._store.state.media as any;
|
||||
if (!media?.textTracks) return;
|
||||
for (let i = 0; i < media.textTracks.length; i++) {
|
||||
const track = media.textTracks[i];
|
||||
if (track && (track.kind === "subtitles" || track.kind === "captions")) {
|
||||
track.mode = subtitle && (track.id === subtitle.id || track.label === subtitle.label)
|
||||
? "showing"
|
||||
: "hidden";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get rendition(): Rendition[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
selectRendition(_rendition?: Rendition): void {
|
||||
// Auto quality is handled by videojs/HLS
|
||||
}
|
||||
|
||||
private setupSubtitleTracks(media: HTMLVideoElement) {
|
||||
const existingTracks = media.querySelectorAll("track");
|
||||
existingTracks.forEach((t) => t.remove());
|
||||
|
||||
for (const subtitle of this._source.subtitles) {
|
||||
const track = document.createElement("track");
|
||||
track.kind = "subtitles";
|
||||
track.src = subtitle.link;
|
||||
if (subtitle.label) track.label = subtitle.label;
|
||||
if (subtitle.language) track.srclang = subtitle.language;
|
||||
track.id = subtitle.id;
|
||||
media.appendChild(track);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import "@videojs/react/video/skin.css";
|
||||
|
||||
import { memo, useEffect, useRef } from "react";
|
||||
import { Video } from "@videojs/react/video";
|
||||
import type { CSSProperties } from "react";
|
||||
import { VideoPlayer, usePlayer } from "./provider.web";
|
||||
import type { OmniViewProps } from "./types/view";
|
||||
|
||||
export const OmniView = memo(
|
||||
({
|
||||
style,
|
||||
autoplay,
|
||||
autoPip,
|
||||
}: OmniViewProps & { style: CSSProperties }) => {
|
||||
const player = usePlayer();
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const media = containerRef.current?.querySelector("video");
|
||||
(player as any).setMediaElement(media ?? null);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!autoPip) return;
|
||||
const media = containerRef.current?.querySelector("video");
|
||||
if (media && document.pictureInPictureEnabled) {
|
||||
media.requestPictureInPicture().catch(() => {});
|
||||
}
|
||||
}, [autoPip]);
|
||||
|
||||
const src = player.source.src[0]?.uri;
|
||||
|
||||
return (
|
||||
<VideoPlayer.Container ref={containerRef} style={style}>
|
||||
{src && (
|
||||
<Video
|
||||
src={src}
|
||||
autoPlay={autoplay}
|
||||
playsInline
|
||||
crossOrigin="anonymous"
|
||||
/>
|
||||
)}
|
||||
</VideoPlayer.Container>
|
||||
);
|
||||
},
|
||||
);
|
||||
+2
-2
@@ -6,9 +6,9 @@
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"jsx": "react-jsx",
|
||||
"lib": ["esnext"],
|
||||
"lib": ["esnext", "dom"],
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"moduleResolution": "bundler",
|
||||
"noEmit": false,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitReturns": true,
|
||||
|
||||
Reference in New Issue
Block a user