mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-08-16 15:44:49 +00:00
Merge pull request #1339 from Stremio/feat/ass-subtitle-controls
Some checks failed
Build / build (push) Has been cancelled
Some checks failed
Build / build (push) Has been cancelled
This commit is contained in:
commit
1748dc1a3e
11 changed files with 65 additions and 24 deletions
|
|
@ -23,7 +23,7 @@
|
|||
"@stremio/stremio-colors": "5.2.0",
|
||||
"@stremio/stremio-core-web": "0.61.0",
|
||||
"@stremio/stremio-icons": "5.10.0",
|
||||
"@stremio/stremio-video": "0.0.90",
|
||||
"@stremio/stremio-video": "0.0.93",
|
||||
"a-color-picker": "1.2.1",
|
||||
"bowser": "2.14.1",
|
||||
"buffer": "6.0.3",
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ importers:
|
|||
specifier: 5.10.0
|
||||
version: 5.10.0
|
||||
'@stremio/stremio-video':
|
||||
specifier: 0.0.90
|
||||
version: 0.0.90
|
||||
specifier: 0.0.93
|
||||
version: 0.0.93
|
||||
a-color-picker:
|
||||
specifier: 1.2.1
|
||||
version: 1.2.1
|
||||
|
|
@ -1417,6 +1417,10 @@ packages:
|
|||
'@sinonjs/fake-timers@10.3.0':
|
||||
resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==}
|
||||
|
||||
'@stremio/libass-wasm@https://github.com/Stremio/JavascriptSubtitlesOctopus/releases/download/v4.2.6/stremio-libass-wasm-4.2.6.tgz':
|
||||
resolution: {integrity: sha512-oHIud2ukVu4/tfrQNrd8vzd6Su0zV8FCatLjuEznf533AW+hj59Eg1g9y2mllpd+GmXrSzf/DNr9jJhYQAg5Gg==, tarball: https://github.com/Stremio/JavascriptSubtitlesOctopus/releases/download/v4.2.6/stremio-libass-wasm-4.2.6.tgz}
|
||||
version: 4.2.6
|
||||
|
||||
'@stremio/stremio-colors@5.2.0':
|
||||
resolution: {integrity: sha512-dYlPgu9W/H7c9s1zmW5tiDnRenaUa4Hg1QCyOg1lhOcgSfM/bVTi5nnqX+IfvGTTUNA0zgzh8hI3o3miwnZxTg==}
|
||||
|
||||
|
|
@ -1426,8 +1430,8 @@ packages:
|
|||
'@stremio/stremio-icons@5.10.0':
|
||||
resolution: {integrity: sha512-Zw/vGC3D2yeQfk8xv/tfMJTDvbCPOI91tBg4XpR2+EgbZSX8Xvm7Vz457PIhFPhTAwdOPHp0VX0M3gzjbt0zOg==}
|
||||
|
||||
'@stremio/stremio-video@0.0.90':
|
||||
resolution: {integrity: sha512-5I4T6GRFaK9fbPwz98bBNScBNpWBSrczkFt+qmhEJ8Tq9INdaah5OQd+hsZTEJIs7dR28M5nvMHpB4owx1UWDg==}
|
||||
'@stremio/stremio-video@0.0.93':
|
||||
resolution: {integrity: sha512-/R6rHh/lekHK4ZjCeMb4O27iOXQo36jek0kfzbbpYw/3yXf9yWxX+LWK5hajBFeZWitOm8GMSnDlkb31LIeIeg==}
|
||||
|
||||
'@stylistic/eslint-plugin-jsx@4.4.1':
|
||||
resolution: {integrity: sha512-83SInq4u7z71vWwGG+6ViOtlOmZ6tSrDkMPhrvdBBTGMLA0gs22WSdhQ4vZP3oJ5Xg4ythvqeUiFSedvVxzhyA==}
|
||||
|
|
@ -6483,6 +6487,8 @@ snapshots:
|
|||
dependencies:
|
||||
'@sinonjs/commons': 3.0.1
|
||||
|
||||
'@stremio/libass-wasm@https://github.com/Stremio/JavascriptSubtitlesOctopus/releases/download/v4.2.6/stremio-libass-wasm-4.2.6.tgz': {}
|
||||
|
||||
'@stremio/stremio-colors@5.2.0': {}
|
||||
|
||||
'@stremio/stremio-core-web@0.61.0':
|
||||
|
|
@ -6491,8 +6497,9 @@ snapshots:
|
|||
|
||||
'@stremio/stremio-icons@5.10.0': {}
|
||||
|
||||
'@stremio/stremio-video@0.0.90':
|
||||
'@stremio/stremio-video@0.0.93':
|
||||
dependencies:
|
||||
'@stremio/libass-wasm': https://github.com/Stremio/JavascriptSubtitlesOctopus/releases/download/v4.2.6/stremio-libass-wasm-4.2.6.tgz
|
||||
buffer: 6.0.3
|
||||
color: 4.2.3
|
||||
deep-freeze: 0.0.1
|
||||
|
|
|
|||
1
src/common/Platform/shell/shell.d.ts
vendored
1
src/common/Platform/shell/shell.d.ts
vendored
|
|
@ -23,6 +23,7 @@ interface Shell {
|
|||
|
||||
type ShellCapabilities = {
|
||||
gpuVideoProcessing: boolean;
|
||||
nativeAssSubtitles: boolean;
|
||||
};
|
||||
|
||||
type ShellState = {
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ const useShell = (): Shell => {
|
|||
});
|
||||
const [capabilities, setCapabilities] = useState<ShellCapabilities>({
|
||||
gpuVideoProcessing: false,
|
||||
nativeAssSubtitles: false,
|
||||
});
|
||||
|
||||
const on = (name: string, listener: (arg: any) => void) => events.on(name, listener);
|
||||
|
|
@ -91,15 +92,18 @@ const useShell = (): Shell => {
|
|||
|
||||
if (event.type === ShellEventType.INIT) {
|
||||
const { data } = event as ShellEventInit;
|
||||
const [, [,,, version], [,,, gpuVideoProcessing] = []] = data.transport.properties;
|
||||
const shellProperties = Object.fromEntries(data.transport.properties
|
||||
.filter((property) => property.length >= 4 && property[1])
|
||||
.map(([, name,, value]) => [name, value]));
|
||||
|
||||
setState((state) => ({
|
||||
...state,
|
||||
initialized: true,
|
||||
version,
|
||||
version: shellProperties.shellVersion ?? null,
|
||||
}));
|
||||
setCapabilities({
|
||||
gpuVideoProcessing: gpuVideoProcessing === 'true',
|
||||
gpuVideoProcessing: shellProperties.gpuVideoProcessing === 'true',
|
||||
nativeAssSubtitles: shellProperties.nativeAssSubtitles === 'true',
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,8 +21,16 @@
|
|||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
|
||||
.variant-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.variant-label {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
font-size: 1.1rem;
|
||||
line-height: 1.5rem;
|
||||
color: var(--primary-foreground-color);
|
||||
|
|
@ -31,6 +39,16 @@
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ass-badge {
|
||||
flex: none;
|
||||
padding: 0.1rem 0.3rem;
|
||||
border: 1px solid var(--color-placeholder-text);
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.65rem;
|
||||
line-height: 0.8rem;
|
||||
color: var(--color-placeholder-text);
|
||||
}
|
||||
|
||||
.variant-origin {
|
||||
font-size: 0.9rem;
|
||||
color: var(--color-placeholder-text);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ type SubtitlesTrack = {
|
|||
embedded?: boolean,
|
||||
local?: boolean,
|
||||
exclusive?: boolean,
|
||||
ass?: boolean,
|
||||
};
|
||||
|
||||
type Props = {
|
||||
|
|
@ -28,6 +29,7 @@ type Props = {
|
|||
};
|
||||
|
||||
const hasValidLabel = (label?: string) => label && label.length > 0 && !label.startsWith('http');
|
||||
const ASS_BADGE = 'ASS';
|
||||
|
||||
const SubtitleVariant = ({ track, selected, onSelect }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
|
|
@ -73,8 +75,11 @@ const SubtitleVariant = ({ track, selected, onSelect }: Props) => {
|
|||
className={classNames(styles['variant-option'], { 'selected': selected })}
|
||||
>
|
||||
<div className={styles['info']}>
|
||||
<div className={styles['variant-label']}>
|
||||
{variantLabel}
|
||||
<div className={styles['variant-title']}>
|
||||
<div className={styles['variant-label']}>
|
||||
{variantLabel}
|
||||
</div>
|
||||
{track.ass ? <div className={styles['ass-badge']}>{ASS_BADGE}</div> : null}
|
||||
</div>
|
||||
<div className={styles['variant-origin']}>
|
||||
{t(track.origin)}
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ const SubtitlesMenu = React.memo(React.forwardRef((props, ref) => {
|
|||
step={25}
|
||||
min={SUBTITLES_SIZES[0]}
|
||||
max={SUBTITLES_SIZES[SUBTITLES_SIZES.length - 1]}
|
||||
disabled={(props.selectedSubtitlesTrackId && props.subtitlesSize === null) || (props.selectedExtraSubtitlesTrackId && props.extraSubtitlesSize === null)}
|
||||
disabled={props.assSubtitlesStylingActive || (props.selectedSubtitlesTrackId && props.subtitlesSize === null) || (props.selectedExtraSubtitlesTrackId && props.extraSubtitlesSize === null)}
|
||||
onChange={onSubtitlesSizeChanged}
|
||||
/>
|
||||
<Stepper
|
||||
|
|
@ -237,7 +237,7 @@ const SubtitlesMenu = React.memo(React.forwardRef((props, ref) => {
|
|||
step={1}
|
||||
min={0}
|
||||
max={100}
|
||||
disabled={(props.selectedSubtitlesTrackId && props.subtitlesOffset === null) || (props.selectedExtraSubtitlesTrackId && props.extraSubtitlesOffset === null)}
|
||||
disabled={props.assSubtitlesStylingActive || (props.selectedSubtitlesTrackId && props.subtitlesOffset === null) || (props.selectedExtraSubtitlesTrackId && props.extraSubtitlesOffset === null)}
|
||||
onChange={onSubtitlesOffsetChanged}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -255,7 +255,8 @@ SubtitlesMenu.propTypes = {
|
|||
subtitlesTracks: PropTypes.arrayOf(PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
lang: PropTypes.string.isRequired,
|
||||
origin: PropTypes.string.isRequired
|
||||
origin: PropTypes.string.isRequired,
|
||||
ass: PropTypes.bool
|
||||
})),
|
||||
selectedSubtitlesTrackId: PropTypes.string,
|
||||
subtitlesOffset: PropTypes.number,
|
||||
|
|
@ -268,12 +269,14 @@ SubtitlesMenu.propTypes = {
|
|||
url: PropTypes.string,
|
||||
embedded: PropTypes.bool,
|
||||
local: PropTypes.bool,
|
||||
exclusive: PropTypes.bool
|
||||
exclusive: PropTypes.bool,
|
||||
ass: PropTypes.bool
|
||||
})),
|
||||
selectedExtraSubtitlesTrackId: PropTypes.string,
|
||||
extraSubtitlesOffset: PropTypes.number,
|
||||
extraSubtitlesDelay: PropTypes.number,
|
||||
extraSubtitlesSize: PropTypes.number,
|
||||
assSubtitlesStylingActive: PropTypes.bool,
|
||||
onSubtitlesTrackSelected: PropTypes.func,
|
||||
onExtraSubtitlesTrackSelected: PropTypes.func,
|
||||
onSubtitlesOffsetChanged: PropTypes.func,
|
||||
|
|
|
|||
3
src/routes/Player/useSubtitles.d.ts
vendored
3
src/routes/Player/useSubtitles.d.ts
vendored
|
|
@ -10,6 +10,7 @@ type SubtitleTrack = {
|
|||
embedded?: boolean,
|
||||
local?: boolean,
|
||||
exclusive?: boolean,
|
||||
ass?: boolean,
|
||||
buffer?: ArrayBuffer,
|
||||
};
|
||||
|
||||
|
|
@ -30,6 +31,7 @@ type VideoSubtitleState = {
|
|||
extraSubtitlesOffset: number | null,
|
||||
extraSubtitlesDelay: number | null,
|
||||
extraSubtitlesSize: number | null,
|
||||
assSubtitlesStylingActive: boolean,
|
||||
};
|
||||
|
||||
type VideoEvents = {
|
||||
|
|
@ -76,6 +78,7 @@ type SubtitlesMenuProps = {
|
|||
extraSubtitlesOffset: number | null,
|
||||
extraSubtitlesDelay: number | null,
|
||||
extraSubtitlesSize: number | null,
|
||||
assSubtitlesStylingActive: boolean,
|
||||
onSubtitlesTrackSelected: (track: SubtitleTrack | null) => void,
|
||||
onExtraSubtitlesTrackSelected: (track: SubtitleTrack | null) => void,
|
||||
onSubtitlesOffsetChanged: (offset: number) => void,
|
||||
|
|
|
|||
|
|
@ -560,6 +560,7 @@ const useSubtitles = ({
|
|||
extraSubtitlesOffset: video.state.extraSubtitlesOffset,
|
||||
extraSubtitlesDelay: video.state.extraSubtitlesDelay,
|
||||
extraSubtitlesSize: video.state.extraSubtitlesSize,
|
||||
assSubtitlesStylingActive: video.state.assSubtitlesStylingActive,
|
||||
onSubtitlesTrackSelected: selectEmbeddedTrack,
|
||||
onExtraSubtitlesTrackSelected: selectExtraTrack,
|
||||
onSubtitlesOffsetChanged: changeOffset,
|
||||
|
|
@ -579,6 +580,7 @@ const useSubtitles = ({
|
|||
video.state.extraSubtitlesOffset,
|
||||
video.state.extraSubtitlesSize,
|
||||
video.state.extraSubtitlesTracks,
|
||||
video.state.assSubtitlesStylingActive,
|
||||
video.state.selectedExtraSubtitlesTrackId,
|
||||
video.state.selectedSubtitlesTrackId,
|
||||
video.state.subtitlesOffset,
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ const useVideo = () => {
|
|||
extraSubtitlesTextColor: null,
|
||||
extraSubtitlesBackgroundColor: null,
|
||||
extraSubtitlesOutlineColor: null,
|
||||
assSubtitlesStylingActive: false,
|
||||
fullscreen: null,
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,12 @@ const Player = forwardRef<HTMLDivElement, Props>(({ profile }: Props, ref) => {
|
|||
{...subtitlesOutlineColorInput}
|
||||
/>
|
||||
</Option>
|
||||
<Option label={'SETTINGS_ASS_SUBTITLES_STYLING'}>
|
||||
<Toggle
|
||||
tabIndex={-1}
|
||||
{...assSubtitlesStylingToggle}
|
||||
/>
|
||||
</Option>
|
||||
</Category>
|
||||
<Category icon={'volume-medium'} label={'SETTINGS_SECTION_AUDIO'}>
|
||||
<Option label={'SETTINGS_DEFAULT_AUDIO_TRACK'}>
|
||||
|
|
@ -159,15 +165,6 @@ const Player = forwardRef<HTMLDivElement, Props>(({ profile }: Props, ref) => {
|
|||
/>
|
||||
</Option>
|
||||
}
|
||||
{
|
||||
shell.active &&
|
||||
<Option label={'SETTINGS_ASS_SUBTITLES_STYLING'}>
|
||||
<Toggle
|
||||
tabIndex={-1}
|
||||
{...assSubtitlesStylingToggle}
|
||||
/>
|
||||
</Option>
|
||||
}
|
||||
</Category>
|
||||
</Section>
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue