diff --git a/package-lock.json b/package-lock.json
index d0c7ad763..642d0ea73 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "stremio",
- "version": "5.0.0-beta.17",
+ "version": "5.0.0-beta.18",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "stremio",
- "version": "5.0.0-beta.17",
+ "version": "5.0.0-beta.18",
"license": "gpl-2.0",
"dependencies": {
"@babel/runtime": "7.26.0",
@@ -14,7 +14,7 @@
"@stremio/stremio-colors": "5.2.0",
"@stremio/stremio-core-web": "0.48.5",
"@stremio/stremio-icons": "5.4.1",
- "@stremio/stremio-video": "0.0.52",
+ "@stremio/stremio-video": "0.0.53",
"a-color-picker": "1.2.1",
"bowser": "2.11.0",
"buffer": "6.0.3",
@@ -36,7 +36,7 @@
"react-i18next": "^15.1.3",
"react-is": "18.3.1",
"spatial-navigation-polyfill": "github:Stremio/spatial-navigation#64871b1422466f5f45d24ebc8bbd315b2ebab6a6",
- "stremio-translations": "github:Stremio/stremio-translations#a0f50634202f748a57907b645d2cd92fbaa479dd",
+ "stremio-translations": "github:Stremio/stremio-translations#62bcc6e8f44258203c7375af59210771efb6f634",
"url": "0.11.4",
"use-long-press": "^3.2.0"
},
@@ -3409,10 +3409,9 @@
]
},
"node_modules/@stremio/stremio-video": {
- "version": "0.0.52",
- "resolved": "https://registry.npmjs.org/@stremio/stremio-video/-/stremio-video-0.0.52.tgz",
- "integrity": "sha512-OlHC8FIvYEyGXcNAM4W044Dqx6CmGb5BV3fDU361SyUjO9gKXXUWdL7LwmwHeWFeuy2sK1MEg4AT2JPptvJ0rg==",
- "license": "MIT",
+ "version": "0.0.53",
+ "resolved": "https://registry.npmjs.org/@stremio/stremio-video/-/stremio-video-0.0.53.tgz",
+ "integrity": "sha512-hSlk8GqMdk4N8VbcdvduYqWVZsQLgHyU7GfFmd1k+t0pSpDKAhI3C6dohG5Sr09CKCjHa8D1rls+CwMNPXLSGw==",
"dependencies": {
"buffer": "6.0.3",
"color": "4.2.3",
@@ -13374,8 +13373,8 @@
},
"node_modules/stremio-translations": {
"version": "1.44.9",
- "resolved": "git+ssh://git@github.com/Stremio/stremio-translations.git#a0f50634202f748a57907b645d2cd92fbaa479dd",
- "integrity": "sha512-JJpd1JJet3T6/VTNdZ2NZ7uvHJ4zkuyqo5BnTcDGqLVNO/OpicGqKhZjE4WGSgmuhsfPBU8T0ICCfzKu2xpvKg==",
+ "resolved": "git+ssh://git@github.com/Stremio/stremio-translations.git#62bcc6e8f44258203c7375af59210771efb6f634",
+ "integrity": "sha512-8Sc5Qvd4IiObwGXkmj1XFXFavUc15My5po6G48HHDBbp42SVc5I/t7h+1yxW1A81byyBCXbL23a9iU9v49vpQA==",
"license": "MIT"
},
"node_modules/string_decoder": {
diff --git a/package.json b/package.json
index e80305bc9..9ccb0cee8 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "stremio",
"displayName": "Stremio",
- "version": "5.0.0-beta.17",
+ "version": "5.0.0-beta.18",
"author": "Smart Code OOD",
"private": true,
"license": "gpl-2.0",
@@ -18,7 +18,7 @@
"@stremio/stremio-colors": "5.2.0",
"@stremio/stremio-core-web": "0.48.5",
"@stremio/stremio-icons": "5.4.1",
- "@stremio/stremio-video": "0.0.52",
+ "@stremio/stremio-video": "0.0.53",
"a-color-picker": "1.2.1",
"bowser": "2.11.0",
"buffer": "6.0.3",
@@ -40,7 +40,7 @@
"react-i18next": "^15.1.3",
"react-is": "18.3.1",
"spatial-navigation-polyfill": "github:Stremio/spatial-navigation#64871b1422466f5f45d24ebc8bbd315b2ebab6a6",
- "stremio-translations": "github:Stremio/stremio-translations#a0f50634202f748a57907b645d2cd92fbaa479dd",
+ "stremio-translations": "github:Stremio/stremio-translations#62bcc6e8f44258203c7375af59210771efb6f634",
"url": "0.11.4",
"use-long-press": "^3.2.0"
},
diff --git a/src/App/App.js b/src/App/App.js
index 730e75f28..6dc2d6e0b 100644
--- a/src/App/App.js
+++ b/src/App/App.js
@@ -6,10 +6,11 @@ const { useTranslation } = require('react-i18next');
const { Router } = require('stremio-router');
const { Core, Shell, Chromecast, DragAndDrop, KeyboardShortcuts, ServicesProvider } = require('stremio/services');
const { NotFound } = require('stremio/routes');
-const { PlatformProvider, ToastProvider, TooltipProvider, CONSTANTS, withCoreSuspender } = require('stremio/common');
+const { FileDropProvider, PlatformProvider, ToastProvider, TooltipProvider, CONSTANTS, withCoreSuspender } = require('stremio/common');
const ServicesToaster = require('./ServicesToaster');
const DeepLinkHandler = require('./DeepLinkHandler');
const SearchParamsHandler = require('./SearchParamsHandler');
+const { default: UpdaterBanner } = require('./UpdaterBanner');
const ErrorDialog = require('./ErrorDialog');
const withProtectedRoutes = require('./withProtectedRoutes');
const routerViewsConfig = require('./routerViewsConfig');
@@ -165,14 +166,17 @@ const App = () => {
-
-
-
-
+
+
+
+
+
+
+
diff --git a/src/App/UpdaterBanner/UpdaterBanner.less b/src/App/UpdaterBanner/UpdaterBanner.less
new file mode 100644
index 000000000..9928fb493
--- /dev/null
+++ b/src/App/UpdaterBanner/UpdaterBanner.less
@@ -0,0 +1,46 @@
+.updater-banner {
+ height: 4rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 1rem;
+ padding: 0 1rem;
+ font-size: 1rem;
+ font-weight: bold;
+ color: var(--primary-foreground-color);
+ background-color: var(--primary-accent-color);
+
+ .button {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+ height: 2.5rem;
+ padding: 0 1rem;
+ border-radius: var(--border-radius);
+ color: var(--primary-background-color);
+ background-color: var(--primary-foreground-color);
+ transition: all 0.1s ease-out;
+
+ &:hover {
+ color: var(--primary-foreground-color);
+ background-color: transparent;
+ box-shadow: inset 0 0 0 0.15rem var(--primary-foreground-color);
+ }
+ }
+
+ .close {
+ position: absolute;
+ right: 0;
+ height: 4rem;
+ width: 4rem;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+
+ .icon {
+ height: 2rem;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/App/UpdaterBanner/UpdaterBanner.tsx b/src/App/UpdaterBanner/UpdaterBanner.tsx
new file mode 100644
index 000000000..3d421deb5
--- /dev/null
+++ b/src/App/UpdaterBanner/UpdaterBanner.tsx
@@ -0,0 +1,50 @@
+import React, { useEffect } from 'react';
+import Icon from '@stremio/stremio-icons/react';
+import { useTranslation } from 'react-i18next';
+import { useServices } from 'stremio/services';
+import { useBinaryState, useShell } from 'stremio/common';
+import { Button, Transition } from 'stremio/components';
+import styles from './UpdaterBanner.less';
+
+type Props = {
+ className: string,
+};
+
+const UpdaterBanner = ({ className }: Props) => {
+ const { t } = useTranslation();
+ const { shell } = useServices();
+ const shellTransport = useShell();
+ const [visible, show, hide] = useBinaryState(false);
+
+ const onInstallClick = () => {
+ shellTransport.send('autoupdater-notif-clicked');
+ };
+
+ useEffect(() => {
+ shell.transport && shell.transport.on('autoupdater-show-notif', show);
+
+ return () => {
+ shell.transport && shell.transport.off('autoupdater-show-notif', show);
+ };
+ }, []);
+
+ return (
+
+
+
+
+ { t('UPDATER_TITLE') }
+
+
+
+
+
+
+ );
+};
+
+export default UpdaterBanner;
diff --git a/src/App/UpdaterBanner/index.ts b/src/App/UpdaterBanner/index.ts
new file mode 100644
index 000000000..e4306ecb2
--- /dev/null
+++ b/src/App/UpdaterBanner/index.ts
@@ -0,0 +1,2 @@
+import UpdaterBanner from './UpdaterBanner';
+export default UpdaterBanner;
diff --git a/src/App/styles.less b/src/App/styles.less
index a413ed163..77ba398f1 100644
--- a/src/App/styles.less
+++ b/src/App/styles.less
@@ -202,12 +202,32 @@ html {
background-color: var(--modal-background-color);
box-shadow: var(--outer-glow);
transition: opacity 0.1s ease-out;
+ }
+
+ .file-drop-container {
+ position: fixed;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ border-radius: 1rem;
+ border: 0.5rem dashed transparent;
+ pointer-events: none;
+ transition: border-color 0.25s ease-out;
&:global(.active) {
- transition-delay: 0.25s;
+ border-color: var(--primary-accent-color);
}
}
+ .updater-banner-container {
+ z-index: 1;
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ }
+
.router {
width: 100%;
height: 100%;
diff --git a/src/common/CONSTANTS.js b/src/common/CONSTANTS.js
index 727c152fa..8e4e3efdc 100644
--- a/src/common/CONSTANTS.js
+++ b/src/common/CONSTANTS.js
@@ -41,6 +41,16 @@ const ICON_FOR_TYPE = new Map([
['other', 'movies'],
]);
+const MIME_SIGNATURES = {
+ 'application/x-subrip': ['310D0A', '310A'],
+ 'text/vtt': ['574542565454'],
+};
+
+const SUPPORTED_LOCAL_SUBTITLES = [
+ 'application/x-subrip',
+ 'text/vtt',
+];
+
const EXTERNAL_PLAYERS = [
{
label: 'EXTERNAL_PLAYER_DISABLED',
@@ -113,6 +123,8 @@ module.exports = {
WRITERS_LINK_CATEGORY,
TYPE_PRIORITIES,
ICON_FOR_TYPE,
+ MIME_SIGNATURES,
+ SUPPORTED_LOCAL_SUBTITLES,
EXTERNAL_PLAYERS,
WHITELISTED_HOSTS,
};
diff --git a/src/common/FileDrop/FileDrop.tsx b/src/common/FileDrop/FileDrop.tsx
new file mode 100644
index 000000000..aae4e146b
--- /dev/null
+++ b/src/common/FileDrop/FileDrop.tsx
@@ -0,0 +1,91 @@
+import React, { createContext, useCallback, useContext, useEffect, useState } from 'react';
+import classNames from 'classnames';
+import { isFileType } from './utils';
+
+export type FileType = string;
+export type FileDropListener = (filename: string, buffer: ArrayBuffer) => void;
+
+type FileDropContext = {
+ on: (type: FileType, listener: FileDropListener) => void,
+ off: (type: FileType, listener: FileDropListener) => void,
+};
+
+const FileDropContext = createContext({} as FileDropContext);
+
+type Props = {
+ className: string,
+ children: JSX.Element,
+};
+
+const FileDropProvider = ({ className, children }: Props) => {
+ const [listeners, setListeners] = useState<[FileType, FileDropListener][]>([]);
+ const [active, setActive] = useState(false);
+
+ const onDragOver = (event: DragEvent) => {
+ event.preventDefault();
+ setActive(true);
+ };
+
+ const onDragLeave = () => {
+ setActive(false);
+ };
+
+ const onDrop = useCallback((event: DragEvent) => {
+ event.preventDefault();
+ const { dataTransfer } = event;
+
+ if (dataTransfer && dataTransfer?.files.length > 0) {
+ const file = dataTransfer.files[0];
+
+ file
+ .arrayBuffer()
+ .then((buffer) => {
+ listeners
+ .filter(([type]) => file.type ? type === file.type : isFileType(buffer, type))
+ .forEach(([, listerner]) => listerner(file.name, buffer));
+ });
+ }
+
+ setActive(false);
+ }, [listeners]);
+
+ const on = (type: FileType, listener: FileDropListener) => {
+ setListeners((listeners) => {
+ return [...listeners, [type, listener]];
+ });
+ };
+
+ const off = (type: FileType, listener: FileDropListener) => {
+ setListeners((listeners) => {
+ return listeners.filter(([key, value]) => key !== type && value !== listener);
+ });
+ };
+
+ useEffect(() => {
+ window.addEventListener('dragover', onDragOver);
+ window.addEventListener('dragleave', onDragLeave);
+ window.addEventListener('drop', onDrop);
+
+ return () => {
+ window.removeEventListener('dragover', onDragOver);
+ window.removeEventListener('dragleave', onDragLeave);
+ window.removeEventListener('drop', onDrop);
+ };
+ }, [onDrop]);
+
+ return (
+
+ { children }
+
+
+ );
+};
+
+const useFileDrop = () => {
+ return useContext(FileDropContext);
+};
+
+export {
+ FileDropProvider,
+ useFileDrop,
+};
diff --git a/src/common/FileDrop/index.ts b/src/common/FileDrop/index.ts
new file mode 100644
index 000000000..41acfbfd7
--- /dev/null
+++ b/src/common/FileDrop/index.ts
@@ -0,0 +1,8 @@
+import { FileDropProvider, useFileDrop } from './FileDrop';
+import onFileDrop from './onFileDrop';
+
+export {
+ FileDropProvider,
+ useFileDrop,
+ onFileDrop,
+};
diff --git a/src/common/FileDrop/onFileDrop.ts b/src/common/FileDrop/onFileDrop.ts
new file mode 100644
index 000000000..339b0219b
--- /dev/null
+++ b/src/common/FileDrop/onFileDrop.ts
@@ -0,0 +1,14 @@
+import { useEffect } from 'react';
+import { type FileType, type FileDropListener, useFileDrop } from './FileDrop';
+
+const onFileDrop = (types: FileType[], listener: FileDropListener) => {
+ const { on, off } = useFileDrop();
+
+ useEffect(() => {
+ types.forEach((type) => on(type, listener));
+
+ return () => types.forEach((type) => off(type, listener));
+ }, []);
+};
+
+export default onFileDrop;
diff --git a/src/common/FileDrop/utils.ts b/src/common/FileDrop/utils.ts
new file mode 100644
index 000000000..f9996aed3
--- /dev/null
+++ b/src/common/FileDrop/utils.ts
@@ -0,0 +1,19 @@
+import { MIME_SIGNATURES } from 'stremio/common/CONSTANTS';
+
+const SIGNATURES = MIME_SIGNATURES as Record;
+
+const isFileType = (buffer: ArrayBuffer, type: string) => {
+ const signatures = SIGNATURES[type];
+
+ return signatures.some((signature) => {
+ const array = new Uint8Array(buffer);
+ const signatureBuffer = Buffer.from(signature, 'hex');
+ const bufferToCompare = array.subarray(0, signatureBuffer.length);
+
+ return Buffer.compare(signatureBuffer, bufferToCompare) === 0;
+ });
+};
+
+export {
+ isFileType,
+};
diff --git a/src/common/Platform/Platform.tsx b/src/common/Platform/Platform.tsx
index 41e74b24f..2212303e4 100644
--- a/src/common/Platform/Platform.tsx
+++ b/src/common/Platform/Platform.tsx
@@ -1,6 +1,6 @@
import React, { createContext, useContext } from 'react';
import { WHITELISTED_HOSTS } from 'stremio/common/CONSTANTS';
-import useShell from './useShell';
+import useShell from 'stremio/common/useShell';
import { name, isMobile } from './device';
interface PlatformContext {
diff --git a/src/common/animations.less b/src/common/animations.less
index c7a30d2fb..91dbe386d 100644
--- a/src/common/animations.less
+++ b/src/common/animations.less
@@ -69,6 +69,19 @@
transform: translateX(100%);
}
+.slide-up-enter {
+ transform: translateY(100%);
+}
+
+.slide-up-active {
+ transform: translateY(0%);
+ transition: transform 0.3s cubic-bezier(0.32, 0, 0.67, 0);
+}
+
+.slide-up-exit {
+ transform: translateY(100%);
+}
+
@keyframes fade-in-no-motion {
0% {
opacity: 0;
diff --git a/src/common/index.js b/src/common/index.js
index 4c514dfbe..4acf8b056 100644
--- a/src/common/index.js
+++ b/src/common/index.js
@@ -1,5 +1,6 @@
// Copyright (C) 2017-2023 Smart code 203358507
+const { FileDropProvider, onFileDrop } = require('./FileDrop');
const { PlatformProvider, usePlatform } = require('./Platform');
const { ToastProvider, useToast } = require('./Toast');
const { TooltipProvider, Tooltip } = require('./Tooltips');
@@ -19,11 +20,14 @@ const useModelState = require('./useModelState');
const useNotifications = require('./useNotifications');
const useOnScrollToBottom = require('./useOnScrollToBottom');
const useProfile = require('./useProfile');
+const { default: useShell } = require('./useShell');
const useStreamingServer = require('./useStreamingServer');
const useTorrent = require('./useTorrent');
const useTranslate = require('./useTranslate');
module.exports = {
+ FileDropProvider,
+ onFileDrop,
PlatformProvider,
usePlatform,
ToastProvider,
@@ -47,6 +51,7 @@ module.exports = {
useNotifications,
useOnScrollToBottom,
useProfile,
+ useShell,
useStreamingServer,
useTorrent,
useTranslate,
diff --git a/src/common/Platform/useShell.ts b/src/common/useShell.ts
similarity index 100%
rename from src/common/Platform/useShell.ts
rename to src/common/useShell.ts
diff --git a/src/components/EventModal/EventModal.js b/src/components/EventModal/EventModal.js
index 917190ba1..f4e46b199 100644
--- a/src/components/EventModal/EventModal.js
+++ b/src/components/EventModal/EventModal.js
@@ -2,7 +2,8 @@
const React = require('react');
const { useTranslation } = require('react-i18next');
-const { Button, ModalDialog } = require('stremio/components');
+const { default: Button } = require('stremio/components/Button');
+const ModalDialog = require('stremio/components/ModalDialog');
const useEvents = require('./useEvents');
const styles = require('./styles');
const { default: Icon } = require('@stremio/stremio-icons/react');
diff --git a/src/routes/Player/ControlBar/ControlBar.js b/src/routes/Player/ControlBar/ControlBar.js
index 0fa6de1a4..745e2bd49 100644
--- a/src/routes/Player/ControlBar/ControlBar.js
+++ b/src/routes/Player/ControlBar/ControlBar.js
@@ -138,6 +138,7 @@ const ControlBar = ({
diff --git a/src/routes/Player/ControlBar/VolumeSlider/VolumeSlider.js b/src/routes/Player/ControlBar/VolumeSlider/VolumeSlider.js
index 420f4ba41..a65ebfe9c 100644
--- a/src/routes/Player/ControlBar/VolumeSlider/VolumeSlider.js
+++ b/src/routes/Player/ControlBar/VolumeSlider/VolumeSlider.js
@@ -8,7 +8,7 @@ const { useRouteFocused } = require('stremio-router');
const { Slider } = require('stremio/components');
const styles = require('./styles');
-const VolumeSlider = ({ className, volume, onVolumeChangeRequested }) => {
+const VolumeSlider = ({ className, volume, onVolumeChangeRequested, muted }) => {
const disabled = volume === null || isNaN(volume);
const routeFocused = useRouteFocused();
const [slidingVolume, setSlidingVolume] = React.useState(null);
@@ -45,7 +45,9 @@ const VolumeSlider = ({ className, volume, onVolumeChangeRequested }) => {
className={classnames(className, styles['volume-slider'], { 'active': slidingVolume !== null })}
value={
!disabled ?
- slidingVolume !== null ? slidingVolume : volume
+ !muted ?
+ slidingVolume !== null ? slidingVolume : volume
+ : 0
:
100
}
@@ -61,7 +63,8 @@ const VolumeSlider = ({ className, volume, onVolumeChangeRequested }) => {
VolumeSlider.propTypes = {
className: PropTypes.string,
volume: PropTypes.number,
- onVolumeChangeRequested: PropTypes.func
+ onVolumeChangeRequested: PropTypes.func,
+ muted: PropTypes.bool,
};
module.exports = VolumeSlider;
diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js
index c76a8dcae..5ad3aa40b 100644
--- a/src/routes/Player/Player.js
+++ b/src/routes/Player/Player.js
@@ -8,7 +8,7 @@ const langs = require('langs');
const { useTranslation } = require('react-i18next');
const { useRouteFocused } = require('stremio-router');
const { useServices } = require('stremio/services');
-const { useFullscreen, useBinaryState, useToast, useStreamingServer, withCoreSuspender } = require('stremio/common');
+const { onFileDrop, useFullscreen, useBinaryState, useToast, useStreamingServer, withCoreSuspender, CONSTANTS } = require('stremio/common');
const { HorizontalNavBar, Transition } = require('stremio/components');
const BufferingLoader = require('./BufferingLoader');
const VolumeChangeIndicator = require('./VolumeChangeIndicator');
@@ -133,11 +133,20 @@ const Player = ({ urlParams, queryParams }) => {
toast.show({
type: 'success',
title: t('PLAYER_SUBTITLES_LOADED'),
- message: track.exclusive ? t('PLAYER_SUBTITLES_LOADED_EXCLUSIVE') : t('PLAYER_SUBTITLES_LOADED_ORIGIN', { origin: track.origin }),
+ message:
+ track.exclusive ? t('PLAYER_SUBTITLES_LOADED_EXCLUSIVE') :
+ track.local ? t('PLAYER_SUBTITLES_LOADED_LOCAL') :
+ t('PLAYER_SUBTITLES_LOADED_ORIGIN', { origin: track.origin }),
timeout: 3000
});
}, []);
+ const onExtraSubtitlesTrackAdded = React.useCallback((track) => {
+ if (track.local) {
+ video.setExtraSubtitlesTrack(track.id);
+ }
+ }, []);
+
const onPlayRequested = React.useCallback(() => {
video.setProp('paused', false);
setSeeking(false);
@@ -172,13 +181,11 @@ const Player = ({ urlParams, queryParams }) => {
}, []);
const onSubtitlesTrackSelected = React.useCallback((id) => {
- video.setProp('selectedSubtitlesTrackId', id);
- video.setProp('selectedExtraSubtitlesTrackId', null);
+ video.setSubtitlesTrack(id);
}, []);
const onExtraSubtitlesTrackSelected = React.useCallback((id) => {
- video.setProp('selectedSubtitlesTrackId', null);
- video.setProp('selectedExtraSubtitlesTrackId', id);
+ video.setExtraSubtitlesTrack(id);
}, []);
const onAudioTrackSelected = React.useCallback((id) => {
@@ -270,6 +277,10 @@ const Player = ({ urlParams, queryParams }) => {
event.nativeEvent.immersePrevented = true;
}, []);
+ onFileDrop(CONSTANTS.SUPPORTED_LOCAL_SUBTITLES, async (filename, buffer) => {
+ video.addLocalSubtitles(filename, buffer);
+ });
+
React.useEffect(() => {
setError(null);
video.unload();
@@ -296,6 +307,7 @@ const Player = ({ urlParams, queryParams }) => {
0,
forceTranscoding: forceTranscoding || casting,
maxAudioChannels: settings.surroundSound ? 32 : 2,
+ hardwareDecoding: settings.hardwareDecoding,
streamingServerURL: streamingServer.baseUrl ?
casting ?
streamingServer.baseUrl
@@ -303,7 +315,7 @@ const Player = ({ urlParams, queryParams }) => {
streamingServer.selected.transportUrl
:
null,
- seriesInfo: player.seriesInfo
+ seriesInfo: player.seriesInfo,
}, {
chromecastTransport: chromecast.active ? chromecast.transport : null,
shellTransport: shell.active ? shell.transport : null,
@@ -586,6 +598,7 @@ const Player = ({ urlParams, queryParams }) => {
video.events.on('ended', onEnded);
video.events.on('subtitlesTrackLoaded', onSubtitlesTrackLoaded);
video.events.on('extraSubtitlesTrackLoaded', onExtraSubtitlesTrackLoaded);
+ video.events.on('extraSubtitlesTrackAdded', onExtraSubtitlesTrackAdded);
video.events.on('implementationChanged', onImplementationChanged);
return () => {
@@ -593,6 +606,7 @@ const Player = ({ urlParams, queryParams }) => {
video.events.off('ended', onEnded);
video.events.off('subtitlesTrackLoaded', onSubtitlesTrackLoaded);
video.events.off('extraSubtitlesTrackLoaded', onExtraSubtitlesTrackLoaded);
+ video.events.off('extraSubtitlesTrackAdded', onExtraSubtitlesTrackAdded);
video.events.off('implementationChanged', onImplementationChanged);
};
}, []);
diff --git a/src/routes/Player/SubtitlesMenu/SubtitlesMenu.js b/src/routes/Player/SubtitlesMenu/SubtitlesMenu.js
index 44cd20864..b1e15a52f 100644
--- a/src/routes/Player/SubtitlesMenu/SubtitlesMenu.js
+++ b/src/routes/Player/SubtitlesMenu/SubtitlesMenu.js
@@ -10,11 +10,13 @@ const styles = require('./styles');
const { t } = require('i18next');
const ORIGIN_PRIORITIES = {
+ 'LOCAL': 3,
'EMBEDDED': 2,
- 'EXCLUSIVE': 1
+ 'EXCLUSIVE': 1,
};
const LANGUAGE_PRIORITIES = {
- 'eng': 1
+ 'local': 2,
+ 'eng': 1,
};
const SubtitlesMenu = React.memo((props) => {
@@ -161,7 +163,11 @@ const SubtitlesMenu = React.memo((props) => {
{subtitlesLanguages.map((lang, index) => (