feat: allow to drop local subtitles

This commit is contained in:
Tim 2025-01-08 20:41:55 +01:00
parent 89b6526555
commit 3df8eb65d0
7 changed files with 74 additions and 5 deletions

View file

@ -41,6 +41,11 @@ const ICON_FOR_TYPE = new Map([
['other', 'movies'],
]);
const SUPPORTED_LOCAL_SUBTITLES = [
'application/x-subrip',
'text/vtt',
];
const EXTERNAL_PLAYERS = [
{
label: 'EXTERNAL_PLAYER_DISABLED',
@ -113,6 +118,7 @@ module.exports = {
WRITERS_LINK_CATEGORY,
TYPE_PRIORITIES,
ICON_FOR_TYPE,
SUPPORTED_LOCAL_SUBTITLES,
EXTERNAL_PLAYERS,
WHITELISTED_HOSTS,
};

View file

@ -13,6 +13,7 @@ const languages = require('./languages');
const routesRegexp = require('./routesRegexp');
const useAnimationFrame = require('./useAnimationFrame');
const useBinaryState = require('./useBinaryState');
const { default: onFileDrop } = require('./onFileDrop');
const useFullscreen = require('./useFullscreen');
const useLiveRef = require('./useLiveRef');
const useModelState = require('./useModelState');
@ -41,6 +42,7 @@ module.exports = {
routesRegexp,
useAnimationFrame,
useBinaryState,
onFileDrop,
useFullscreen,
useLiveRef,
useModelState,

31
src/common/onFileDrop.ts Normal file
View file

@ -0,0 +1,31 @@
import { useEffect } from 'react';
const onFileDrop = (types: string[], callback: (file: File) => void) => {
const onDragOver = (event: DragEvent) => {
event.preventDefault();
};
const onDrop = (event: DragEvent) => {
event.preventDefault();
if (event.dataTransfer && event.dataTransfer.files.length > 0) {
const file = event.dataTransfer.files[0];
if (types.includes(file.type)) {
callback(file);
}
}
};
useEffect(() => {
window.addEventListener('dragover', onDragOver);
window.addEventListener('drop', onDrop);
return () => {
window.removeEventListener('dragover', onDragOver);
window.removeEventListener('drop', onDrop);
};
}, []);
};
export default onFileDrop;

View file

@ -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,7 +133,10 @@ 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
});
}, []);
@ -270,6 +273,11 @@ const Player = ({ urlParams, queryParams }) => {
event.nativeEvent.immersePrevented = true;
}, []);
onFileDrop(CONSTANTS.SUPPORTED_LOCAL_SUBTITLES, async (file) => {
const buffer = await file.arrayBuffer();
video.addLocalSubtitles(file.name, buffer);
});
React.useEffect(() => {
setError(null);
video.unload();

View file

@ -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) => {
</Button>
{subtitlesLanguages.map((lang, index) => (
<Button key={index} title={languages.label(lang)} className={classnames(styles['language-option'], { 'selected': selectedSubtitlesLanguage === lang })} data-lang={lang} onClick={subtitlesLanguageOnClick}>
<div className={styles['language-label']}>{languages.label(lang)}</div>
<div className={styles['language-label']}>
{
lang === 'local' ? t('LOCAL_SUBTITLES') : languages.label(lang)
}
</div>
{
selectedSubtitlesLanguage === lang ?
<div className={styles['icon']} />

View file

@ -79,6 +79,17 @@ const useVideo = () => {
});
};
const addLocalSubtitles = (filename, buffer) => {
dispatch({
type: 'command',
commandName: 'addLocalSubtitles',
commandArgs: {
filename,
buffer,
},
});
};
const setProp = (name, value) => {
dispatch({ type: 'setProp', propName: name, propValue: value });
};
@ -136,6 +147,7 @@ const useVideo = () => {
load,
unload,
addExtraSubtitlesTracks,
addLocalSubtitles,
setProp,
};
};

View file

@ -36,6 +36,10 @@ function DragAndDrop({ core }) {
}
break;
}
case 'application/x-subrip':
break;
case 'text/vtt':
break;
default: {
events.emit('error', {
message: 'Unsupported file',