mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-03-11 21:27:05 +00:00
Merge branch 'development' of https://github.com/Stremio/stremio-web into feat/calendar
This commit is contained in:
commit
ef28d744e2
17 changed files with 128 additions and 47 deletions
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
|
@ -37,7 +37,7 @@ jobs:
|
|||
# "--parrents where no error if existing, make parent directories as needed."
|
||||
- run: mkdir -p ./build/${{ github.head_ref || github.ref_name }}
|
||||
- name: Deploy to GitHub Pages
|
||||
if: github.repository == 'Stremio/stremio-web' && github.actor != 'dependabot[bot]'
|
||||
if: github.event.pull_request.head.repo.fork == false && github.actor != 'dependabot[bot]'
|
||||
uses: peaceiris/actions-gh-pages@v4
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
|
|
|||
26
package-lock.json
generated
26
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "stremio",
|
||||
"version": "5.0.0-beta.12",
|
||||
"version": "5.0.0-beta.13",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "stremio",
|
||||
"version": "5.0.0-beta.12",
|
||||
"version": "5.0.0-beta.13",
|
||||
"license": "gpl-2.0",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.16.0",
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
"@stremio/stremio-colors": "5.0.1",
|
||||
"@stremio/stremio-core-web": "0.48.0",
|
||||
"@stremio/stremio-icons": "5.2.0",
|
||||
"@stremio/stremio-video": "0.0.38",
|
||||
"@stremio/stremio-video": "0.0.46",
|
||||
"a-color-picker": "1.2.1",
|
||||
"bowser": "2.11.0",
|
||||
"buffer": "6.0.3",
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
"react-i18next": "^12.1.1",
|
||||
"react-is": "18.2.0",
|
||||
"spatial-navigation-polyfill": "github:Stremio/spatial-navigation#64871b1422466f5f45d24ebc8bbd315b2ebab6a6",
|
||||
"stremio-translations": "github:Stremio/stremio-translations#378218c9617f3e763ba5f6755e4d39c1c158747d",
|
||||
"stremio-translations": "github:Stremio/stremio-translations#57d66ecc8e2df4e73a613dc5e17123ce62ae63f7",
|
||||
"url": "0.11.0",
|
||||
"use-long-press": "^3.1.5"
|
||||
},
|
||||
|
|
@ -3135,7 +3135,6 @@
|
|||
"version": "0.48.0",
|
||||
"resolved": "https://registry.npmjs.org/@stremio/stremio-core-web/-/stremio-core-web-0.48.0.tgz",
|
||||
"integrity": "sha512-UEVxb5weAIZ22Hz0iNKM8O1QkALcLShG9AyCe1P2WhZhyiridbwE7MtP5itBtLcLm9f/D6UeRrpUWMCS01n18Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.24.1"
|
||||
}
|
||||
|
|
@ -3164,9 +3163,9 @@
|
|||
"integrity": "sha512-rABlPBTFF17QcSm/4IizVoE/jh+REt+waqA0RvIxuGjQppXlvj7CalqVvTam0CC2wgY00zNG1v/9kVHUDVzo4Q=="
|
||||
},
|
||||
"node_modules/@stremio/stremio-video": {
|
||||
"version": "0.0.38",
|
||||
"resolved": "https://registry.npmjs.org/@stremio/stremio-video/-/stremio-video-0.0.38.tgz",
|
||||
"integrity": "sha512-ev9z3YdMcZAsTQjEwOLfqB9EI8GdbQzwSGMZIOLPR/7/Ce7BQIctwDnEtTLgPmCsRpYZsqOD1PiBwU9tiDHZ8w==",
|
||||
"version": "0.0.46",
|
||||
"resolved": "https://registry.npmjs.org/@stremio/stremio-video/-/stremio-video-0.0.46.tgz",
|
||||
"integrity": "sha512-U15CGB6CrUZKq3IKcEouAEH2RQoLy2+BI/hDStEYEACxlRlFaavKPI2opl37muh9TY089RnZVBYAM3yDidBZdg==",
|
||||
"dependencies": {
|
||||
"buffer": "6.0.3",
|
||||
"color": "4.2.3",
|
||||
|
|
@ -3178,7 +3177,7 @@
|
|||
"magnet-uri": "6.2.0",
|
||||
"url": "0.11.0",
|
||||
"video-name-parser": "1.4.6",
|
||||
"vtt.js": "github:jaruba/vtt.js#e4f5f5603730866bacb174a93f51b734c9f29e6a"
|
||||
"vtt.js": "github:jaruba/vtt.js#84d33d157848407d790d78423dacc41a096294f0"
|
||||
}
|
||||
},
|
||||
"node_modules/@stylistic/eslint-plugin": {
|
||||
|
|
@ -13733,8 +13732,9 @@
|
|||
},
|
||||
"node_modules/stremio-translations": {
|
||||
"version": "1.44.9",
|
||||
"resolved": "git+ssh://git@github.com/Stremio/stremio-translations.git#378218c9617f3e763ba5f6755e4d39c1c158747d",
|
||||
"integrity": "sha512-3GboN8JS2LgrdIVK/gW+n6r1kLrGG+D/tWkRv8PJo2mZLzh49HTzS2u7XXUSkNmA4AGUyEf8QRjyBhlOg8JNTQ=="
|
||||
"resolved": "git+ssh://git@github.com/Stremio/stremio-translations.git#57d66ecc8e2df4e73a613dc5e17123ce62ae63f7",
|
||||
"integrity": "sha512-Q3Q++Tx3quu71tgTfS8CEP6CajdGyig92SdtRyGMsLHHkgBgzP9ggYBUHVbKAfXcKUegABIkW8CxMueEw758Xg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/string_decoder": {
|
||||
"version": "1.1.1",
|
||||
|
|
@ -14894,8 +14894,8 @@
|
|||
},
|
||||
"node_modules/vtt.js": {
|
||||
"version": "0.13.0",
|
||||
"resolved": "git+ssh://git@github.com/jaruba/vtt.js.git#e4f5f5603730866bacb174a93f51b734c9f29e6a",
|
||||
"integrity": "sha512-RXV60lPGrmjuRcV/jRuydLC2thMaMlmK4Vc3DtBmVSotFA3986sgW0H5AH9IUmHzQo4bFR2gELYLcfwVh7Dqow==",
|
||||
"resolved": "git+ssh://git@github.com/jaruba/vtt.js.git#84d33d157848407d790d78423dacc41a096294f0",
|
||||
"integrity": "sha512-N/WeijIW9oiGmfqWdEcNqSblzfnXR8dfsBRNPIG9YYFhIBU0Y2c7w8Sfl0bDOZVhjA5qHbwoHx6SxDgRLiraTQ==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/w3c-hr-time": {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "stremio",
|
||||
"displayName": "Stremio",
|
||||
"version": "5.0.0-beta.12",
|
||||
"version": "5.0.0-beta.13",
|
||||
"author": "Smart Code OOD",
|
||||
"private": true,
|
||||
"license": "gpl-2.0",
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
"@stremio/stremio-colors": "5.0.1",
|
||||
"@stremio/stremio-core-web": "0.48.0",
|
||||
"@stremio/stremio-icons": "5.2.0",
|
||||
"@stremio/stremio-video": "0.0.38",
|
||||
"@stremio/stremio-video": "0.0.46",
|
||||
"a-color-picker": "1.2.1",
|
||||
"bowser": "2.11.0",
|
||||
"buffer": "6.0.3",
|
||||
|
|
@ -40,7 +40,7 @@
|
|||
"react-i18next": "^12.1.1",
|
||||
"react-is": "18.2.0",
|
||||
"spatial-navigation-polyfill": "github:Stremio/spatial-navigation#64871b1422466f5f45d24ebc8bbd315b2ebab6a6",
|
||||
"stremio-translations": "github:Stremio/stremio-translations#378218c9617f3e763ba5f6755e4d39c1c158747d",
|
||||
"stremio-translations": "github:Stremio/stremio-translations#57d66ecc8e2df4e73a613dc5e17123ce62ae63f7",
|
||||
"url": "0.11.0",
|
||||
"use-long-press": "^3.1.5"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ const EXTERNAL_PLAYERS = [
|
|||
},
|
||||
];
|
||||
|
||||
const WHITELISTED_HOSTS = ['stremio.com', 'strem.io', 'stremio.zendesk.com', 'google.com', 'youtube.com', 'twitch.tv', 'twitter.com', 'netflix.com', 'adex.network', 'amazon.com', 'forms.gle'];
|
||||
const WHITELISTED_HOSTS = ['stremio.com', 'strem.io', 'stremio.zendesk.com', 'google.com', 'youtube.com', 'twitch.tv', 'twitter.com', 'x.com', 'netflix.com', 'adex.network', 'amazon.com', 'forms.gle'];
|
||||
|
||||
module.exports = {
|
||||
CHROMECAST_RECEIVER_APP_ID,
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@ const Image = ({ className, src, alt, fallbackSrc, renderFallback, ...props }) =
|
|||
typeof renderFallback === 'function' ?
|
||||
renderFallback()
|
||||
:
|
||||
<img {...props} className={className} src={fallbackSrc} alt={alt} />
|
||||
<img {...props} className={className} src={fallbackSrc} alt={alt} loading='lazy'/>
|
||||
:
|
||||
<img {...props} className={className} src={src} alt={alt} onError={onError} />;
|
||||
<img {...props} className={className} src={src} alt={alt} loading='lazy' onError={onError} />;
|
||||
};
|
||||
|
||||
Image.propTypes = {
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ const ModalDialog = ({ className, title, buttons, children, dataset, onCloseRequ
|
|||
:
|
||||
null
|
||||
}
|
||||
<div className={styles['modal-dialog-content']}>
|
||||
<div className={styles['body-container']}>
|
||||
{children}
|
||||
</div>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@
|
|||
.modal-dialog-content {
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
overflow-y: auto;
|
||||
|
||||
.title-container {
|
||||
flex: 1 0 auto;
|
||||
|
|
@ -78,7 +79,7 @@
|
|||
color: var(--primary-foreground-color);
|
||||
}
|
||||
|
||||
.modal-dialog-content {
|
||||
.body-container {
|
||||
flex: 1;
|
||||
align-self: stretch;
|
||||
overflow-y: auto;
|
||||
|
|
@ -157,9 +158,11 @@
|
|||
z-index: 0;
|
||||
padding: 0 1.5rem;
|
||||
|
||||
.buttons-container {
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
.modal-dialog-content {
|
||||
.buttons-container {
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@
|
|||
max-height: 2.4em;
|
||||
font-weight: 500;
|
||||
color: var(--primary-foreground-color);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.icon {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@
|
|||
"name": "български език",
|
||||
"codes": ["bg-BG", "bul"]
|
||||
},
|
||||
{
|
||||
"name": "বাংলা",
|
||||
"codes": ["bn-Bd", "ben"]
|
||||
},
|
||||
{
|
||||
"name": "català",
|
||||
"codes": ["ca-CA", "cat"]
|
||||
|
|
@ -75,6 +79,14 @@
|
|||
"name": "italiano",
|
||||
"codes": ["it-IT", "ita"]
|
||||
},
|
||||
{
|
||||
"name": "日本語 (にほんご)",
|
||||
"codes": ["ja-JP", "jpn"]
|
||||
},
|
||||
{
|
||||
"name": "한국어",
|
||||
"codes": ["ko-KR", "kor"]
|
||||
},
|
||||
{
|
||||
"name": "македонски јазик",
|
||||
"codes": ["mk-MK", "mkd"]
|
||||
|
|
@ -135,6 +147,10 @@
|
|||
"name": "українська мова",
|
||||
"codes": ["uk-UA", "ukr"]
|
||||
},
|
||||
{
|
||||
"name": "Tiếng Việt",
|
||||
"codes": ["vi-VN", "vie"]
|
||||
},
|
||||
{
|
||||
"name": "中文(中华人民共和国)",
|
||||
"codes": ["zh-CN", "zho"]
|
||||
|
|
@ -147,4 +163,4 @@
|
|||
"name": "中文(台灣)",
|
||||
"codes": ["zh-TW", "zho"]
|
||||
}
|
||||
]
|
||||
]
|
||||
|
|
|
|||
|
|
@ -58,7 +58,6 @@
|
|||
|
||||
.addon-name {
|
||||
width: 7rem;
|
||||
max-height: 3.6em;
|
||||
font-size: 1.1rem;
|
||||
text-align: left;
|
||||
color: var(--primary-foreground-color);
|
||||
|
|
|
|||
|
|
@ -108,7 +108,6 @@
|
|||
|
||||
.select-input-container {
|
||||
min-width: 40%;
|
||||
flex: 0 0 auto;
|
||||
flex-grow: 1;
|
||||
background: none;
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ const Video = ({ className, id, title, thumbnail, episode, released, upcoming, w
|
|||
}, []);
|
||||
const toggleWatchedOnClick = React.useCallback((event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
closeMenu();
|
||||
core.transport.dispatch({
|
||||
action: 'MetaDetails',
|
||||
|
|
@ -116,7 +117,7 @@ const Video = ({ className, id, title, thumbnail, episode, released, upcoming, w
|
|||
}
|
||||
<div className={styles['upcoming-watched-container']}>
|
||||
{
|
||||
upcoming ?
|
||||
upcoming && !watched ?
|
||||
<div className={styles['upcoming-container']}>
|
||||
<div className={styles['flag-label']}>Upcoming</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
return queryParams.has('forceTranscoding');
|
||||
}, [queryParams]);
|
||||
|
||||
const [player, videoParamsChanged, timeChanged, pausedChanged, ended, nextVideo] = usePlayer(urlParams);
|
||||
const [player, videoParamsChanged, timeChanged, seek, pausedChanged, ended, nextVideo] = usePlayer(urlParams);
|
||||
const [settings, updateSettings] = useSettings();
|
||||
const streamingServer = useStreamingServer();
|
||||
const statistics = useStatistics(player, streamingServer);
|
||||
|
|
@ -42,6 +42,8 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
const routeFocused = useRouteFocused();
|
||||
const toast = useToast();
|
||||
|
||||
const [seeking, setSeeking] = React.useState(false);
|
||||
|
||||
const [casting, setCasting] = React.useState(() => {
|
||||
return chromecast.active && chromecast.transport.getCastState() === cast.framework.CastState.CONNECTED;
|
||||
});
|
||||
|
|
@ -136,6 +138,7 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
|
||||
const onPlayRequested = React.useCallback(() => {
|
||||
video.setProp('paused', false);
|
||||
setSeeking(false);
|
||||
}, []);
|
||||
|
||||
const onPlayRequestedDebounced = React.useCallback(debounce(onPlayRequested, 200), []);
|
||||
|
|
@ -159,7 +162,8 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
|
||||
const onSeekRequested = React.useCallback((time) => {
|
||||
video.setProp('time', time);
|
||||
}, []);
|
||||
seek(time, video.state.duration, video.state.manifest?.name);
|
||||
}, [video.state.duration, video.state.manifest]);
|
||||
|
||||
const onPlaybackSpeedChanged = React.useCallback((rate) => {
|
||||
video.setProp('playbackSpeed', rate);
|
||||
|
|
@ -342,12 +346,8 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
}, [settings.subtitlesOutlineColor]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (video.state.time !== null && !isNaN(video.state.time) &&
|
||||
video.state.duration !== null && !isNaN(video.state.duration) &&
|
||||
video.state.manifest !== null && typeof video.state.manifest.name === 'string') {
|
||||
timeChanged(video.state.time, video.state.duration, video.state.manifest.name);
|
||||
}
|
||||
}, [video.state.time, video.state.duration, video.state.manifest]);
|
||||
!seeking && timeChanged(video.state.time, video.state.duration, video.state.manifest?.name);
|
||||
}, [video.state.time, video.state.duration, video.state.manifest, seeking]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (video.state.paused !== null) {
|
||||
|
|
@ -468,6 +468,7 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
if (!menusOpen && !nextVideoPopupOpen && video.state.paused !== null) {
|
||||
if (video.state.paused) {
|
||||
onPlayRequested();
|
||||
setSeeking(false);
|
||||
} else {
|
||||
onPauseRequested();
|
||||
}
|
||||
|
|
@ -478,6 +479,7 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
case 'ArrowRight': {
|
||||
if (!menusOpen && !nextVideoPopupOpen && video.state.time !== null) {
|
||||
const seekDuration = event.shiftKey ? settings.seekShortTimeDuration : settings.seekTimeDuration;
|
||||
setSeeking(true);
|
||||
onSeekRequested(video.state.time + seekDuration);
|
||||
}
|
||||
|
||||
|
|
@ -486,6 +488,7 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
case 'ArrowLeft': {
|
||||
if (!menusOpen && !nextVideoPopupOpen && video.state.time !== null) {
|
||||
const seekDuration = event.shiftKey ? settings.seekShortTimeDuration : settings.seekTimeDuration;
|
||||
setSeeking(true);
|
||||
onSeekRequested(video.state.time - seekDuration);
|
||||
}
|
||||
|
||||
|
|
@ -553,6 +556,11 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
}
|
||||
}
|
||||
};
|
||||
const onKeyUp = (event) => {
|
||||
if (event.code === 'ArrowRight' || event.code === 'ArrowLeft') {
|
||||
setSeeking(false);
|
||||
}
|
||||
};
|
||||
const onWheel = ({ deltaY }) => {
|
||||
if (deltaY > 0) {
|
||||
if (!menusOpen && video.state.volume !== null) {
|
||||
|
|
@ -566,10 +574,12 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
};
|
||||
if (routeFocused) {
|
||||
window.addEventListener('keydown', onKeyDown);
|
||||
window.addEventListener('keyup', onKeyUp);
|
||||
window.addEventListener('wheel', onWheel);
|
||||
}
|
||||
return () => {
|
||||
window.removeEventListener('keydown', onKeyDown);
|
||||
window.removeEventListener('keyup', onKeyUp);
|
||||
window.removeEventListener('wheel', onWheel);
|
||||
};
|
||||
}, [player.metaItem, player.selected, streamingServer.statistics, settings.seekTimeDuration, settings.seekShortTimeDuration, routeFocused, menusOpen, nextVideoPopupOpen, video.state.paused, video.state.time, video.state.volume, video.state.audioTracks, video.state.subtitlesTracks, video.state.extraSubtitlesTracks, video.state.playbackSpeed, toggleSubtitlesMenu, toggleInfoMenu, toggleVideosMenu, toggleStatisticsMenu]);
|
||||
|
|
|
|||
|
|
@ -204,7 +204,15 @@ const SubtitlesMenu = React.memo((props) => {
|
|||
<div className={styles['variants-list']}>
|
||||
{subtitlesTracksForLanguage.map((track, index) => (
|
||||
<Button key={index} title={track.label} className={classnames(styles['variant-option'], { 'selected': props.selectedSubtitlesTrackId === track.id || props.selectedExtraSubtitlesTrackId === track.id })} data-id={track.id} data-origin={track.origin} data-embedded={track.embedded} onClick={subtitlesTrackOnClick}>
|
||||
<div className={styles['variant-label']}>{track.origin}</div>
|
||||
<div className={styles['variant-label']}>
|
||||
{
|
||||
typeof track.label === 'string' && !track.label.startsWith('http') ?
|
||||
track.label
|
||||
:
|
||||
track.lang
|
||||
}
|
||||
<div className={styles['variant-origin']}>{t(track.origin)}</div>
|
||||
</div>
|
||||
{
|
||||
props.selectedSubtitlesTrackId === track.id || props.selectedExtraSubtitlesTrackId === track.id ?
|
||||
<div className={styles['icon']} />
|
||||
|
|
|
|||
|
|
@ -47,6 +47,15 @@
|
|||
color: var(--primary-foreground-color);
|
||||
}
|
||||
|
||||
.language-label, .variant-label, .variant-origin {
|
||||
text-wrap: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.variant-label .variant-origin {
|
||||
color: var(--color-placeholder-text);
|
||||
}
|
||||
|
||||
.icon {
|
||||
flex: none;
|
||||
width: 0.5rem;
|
||||
|
|
|
|||
11
src/routes/Player/usePlayer.d.ts
vendored
11
src/routes/Player/usePlayer.d.ts
vendored
|
|
@ -1,2 +1,11 @@
|
|||
declare const usePlayer: (urlParams: UrlParams, videoParams: any) => [Player, (time: number, duration: number, device: string) => void, (paused: boolean) => void, () => void, () => void];
|
||||
declare const usePlayer: (urlParams: UrlParams) => [
|
||||
Player,
|
||||
videoParamsChanged: (videoParams: { hash: string | null, size: number | null, filename: string | null }) => void,
|
||||
timeChanged: (time: number, duration: number, device: string) => void,
|
||||
seek: (time: number, duration: number, device: string) => void,
|
||||
pausedChanged: (paused: boolean) => void, () => void, () => void,
|
||||
ended: () => void,
|
||||
nextVideo: () => void,
|
||||
];
|
||||
|
||||
export = usePlayer;
|
||||
|
|
|
|||
|
|
@ -96,14 +96,37 @@ const usePlayer = (urlParams) => {
|
|||
}, 'player');
|
||||
}, []);
|
||||
const timeChanged = React.useCallback((time, duration, device) => {
|
||||
core.transport.dispatch({
|
||||
action: 'Player',
|
||||
args: {
|
||||
action: 'TimeChanged',
|
||||
args: { time, duration, device }
|
||||
}
|
||||
}, 'player');
|
||||
if (typeof time === 'number' && typeof duration === 'number' && typeof device === 'string') {
|
||||
core.transport.dispatch({
|
||||
action: 'Player',
|
||||
args: {
|
||||
action: 'TimeChanged',
|
||||
args: {
|
||||
time: Math.round(time),
|
||||
duration,
|
||||
device,
|
||||
}
|
||||
}
|
||||
}, 'player');
|
||||
}
|
||||
}, []);
|
||||
|
||||
const seek = React.useCallback((time, duration, device) => {
|
||||
if (typeof time === 'number' && typeof duration === 'number' && typeof device === 'string') {
|
||||
core.transport.dispatch({
|
||||
action: 'Player',
|
||||
args: {
|
||||
action: 'Seek',
|
||||
args: {
|
||||
time: Math.round(time),
|
||||
duration,
|
||||
device,
|
||||
}
|
||||
}
|
||||
}, 'player');
|
||||
}
|
||||
}, []);
|
||||
|
||||
const ended = React.useCallback(() => {
|
||||
core.transport.dispatch({
|
||||
action: 'Player',
|
||||
|
|
@ -129,8 +152,9 @@ const usePlayer = (urlParams) => {
|
|||
}
|
||||
}, 'player');
|
||||
}, []);
|
||||
|
||||
const player = useModelState({ model: 'player', action, map });
|
||||
return [player, videoParamsChanged, timeChanged, pausedChanged, ended, nextVideo];
|
||||
return [player, videoParamsChanged, timeChanged, seek, pausedChanged, ended, nextVideo];
|
||||
};
|
||||
|
||||
module.exports = usePlayer;
|
||||
|
|
|
|||
Loading…
Reference in a new issue