mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-07-26 19:22:13 +00:00
Add ASS subtitle controls
This commit is contained in:
parent
51f4db1e04
commit
a1d7118696
7 changed files with 44 additions and 15 deletions
|
|
@ -21,8 +21,16 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.25rem;
|
gap: 0.25rem;
|
||||||
|
|
||||||
|
.variant-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.variant-label {
|
.variant-label {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
font-size: 1.1rem;
|
font-size: 1.1rem;
|
||||||
line-height: 1.5rem;
|
line-height: 1.5rem;
|
||||||
color: var(--primary-foreground-color);
|
color: var(--primary-foreground-color);
|
||||||
|
|
@ -31,6 +39,16 @@
|
||||||
overflow: hidden;
|
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 {
|
.variant-origin {
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
color: var(--color-placeholder-text);
|
color: var(--color-placeholder-text);
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ type SubtitlesTrack = {
|
||||||
embedded?: boolean,
|
embedded?: boolean,
|
||||||
local?: boolean,
|
local?: boolean,
|
||||||
exclusive?: boolean,
|
exclusive?: boolean,
|
||||||
|
ass?: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
@ -28,6 +29,7 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const hasValidLabel = (label?: string) => label && label.length > 0 && !label.startsWith('http');
|
const hasValidLabel = (label?: string) => label && label.length > 0 && !label.startsWith('http');
|
||||||
|
const ASS_BADGE = 'ASS';
|
||||||
|
|
||||||
const SubtitleVariant = ({ track, selected, onSelect }: Props) => {
|
const SubtitleVariant = ({ track, selected, onSelect }: Props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
@ -73,8 +75,11 @@ const SubtitleVariant = ({ track, selected, onSelect }: Props) => {
|
||||||
className={classNames(styles['variant-option'], { 'selected': selected })}
|
className={classNames(styles['variant-option'], { 'selected': selected })}
|
||||||
>
|
>
|
||||||
<div className={styles['info']}>
|
<div className={styles['info']}>
|
||||||
<div className={styles['variant-label']}>
|
<div className={styles['variant-title']}>
|
||||||
{variantLabel}
|
<div className={styles['variant-label']}>
|
||||||
|
{variantLabel}
|
||||||
|
</div>
|
||||||
|
{track.ass ? <div className={styles['ass-badge']}>{ASS_BADGE}</div> : null}
|
||||||
</div>
|
</div>
|
||||||
<div className={styles['variant-origin']}>
|
<div className={styles['variant-origin']}>
|
||||||
{t(track.origin)}
|
{t(track.origin)}
|
||||||
|
|
|
||||||
|
|
@ -226,7 +226,7 @@ const SubtitlesMenu = React.memo(React.forwardRef((props, ref) => {
|
||||||
step={25}
|
step={25}
|
||||||
min={SUBTITLES_SIZES[0]}
|
min={SUBTITLES_SIZES[0]}
|
||||||
max={SUBTITLES_SIZES[SUBTITLES_SIZES.length - 1]}
|
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}
|
onChange={onSubtitlesSizeChanged}
|
||||||
/>
|
/>
|
||||||
<Stepper
|
<Stepper
|
||||||
|
|
@ -237,7 +237,7 @@ const SubtitlesMenu = React.memo(React.forwardRef((props, ref) => {
|
||||||
step={1}
|
step={1}
|
||||||
min={0}
|
min={0}
|
||||||
max={100}
|
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}
|
onChange={onSubtitlesOffsetChanged}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -255,7 +255,8 @@ SubtitlesMenu.propTypes = {
|
||||||
subtitlesTracks: PropTypes.arrayOf(PropTypes.shape({
|
subtitlesTracks: PropTypes.arrayOf(PropTypes.shape({
|
||||||
id: PropTypes.string.isRequired,
|
id: PropTypes.string.isRequired,
|
||||||
lang: PropTypes.string.isRequired,
|
lang: PropTypes.string.isRequired,
|
||||||
origin: PropTypes.string.isRequired
|
origin: PropTypes.string.isRequired,
|
||||||
|
ass: PropTypes.bool
|
||||||
})),
|
})),
|
||||||
selectedSubtitlesTrackId: PropTypes.string,
|
selectedSubtitlesTrackId: PropTypes.string,
|
||||||
subtitlesOffset: PropTypes.number,
|
subtitlesOffset: PropTypes.number,
|
||||||
|
|
@ -268,12 +269,14 @@ SubtitlesMenu.propTypes = {
|
||||||
url: PropTypes.string,
|
url: PropTypes.string,
|
||||||
embedded: PropTypes.bool,
|
embedded: PropTypes.bool,
|
||||||
local: PropTypes.bool,
|
local: PropTypes.bool,
|
||||||
exclusive: PropTypes.bool
|
exclusive: PropTypes.bool,
|
||||||
|
ass: PropTypes.bool
|
||||||
})),
|
})),
|
||||||
selectedExtraSubtitlesTrackId: PropTypes.string,
|
selectedExtraSubtitlesTrackId: PropTypes.string,
|
||||||
extraSubtitlesOffset: PropTypes.number,
|
extraSubtitlesOffset: PropTypes.number,
|
||||||
extraSubtitlesDelay: PropTypes.number,
|
extraSubtitlesDelay: PropTypes.number,
|
||||||
extraSubtitlesSize: PropTypes.number,
|
extraSubtitlesSize: PropTypes.number,
|
||||||
|
assSubtitlesStylingActive: PropTypes.bool,
|
||||||
onSubtitlesTrackSelected: PropTypes.func,
|
onSubtitlesTrackSelected: PropTypes.func,
|
||||||
onExtraSubtitlesTrackSelected: PropTypes.func,
|
onExtraSubtitlesTrackSelected: PropTypes.func,
|
||||||
onSubtitlesOffsetChanged: 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,
|
embedded?: boolean,
|
||||||
local?: boolean,
|
local?: boolean,
|
||||||
exclusive?: boolean,
|
exclusive?: boolean,
|
||||||
|
ass?: boolean,
|
||||||
buffer?: ArrayBuffer,
|
buffer?: ArrayBuffer,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -29,6 +30,7 @@ type VideoSubtitleState = {
|
||||||
extraSubtitlesOffset: number | null,
|
extraSubtitlesOffset: number | null,
|
||||||
extraSubtitlesDelay: number | null,
|
extraSubtitlesDelay: number | null,
|
||||||
extraSubtitlesSize: number | null,
|
extraSubtitlesSize: number | null,
|
||||||
|
assSubtitlesStylingActive: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
type VideoEvents = {
|
type VideoEvents = {
|
||||||
|
|
@ -74,6 +76,7 @@ type SubtitlesMenuProps = {
|
||||||
extraSubtitlesOffset: number | null,
|
extraSubtitlesOffset: number | null,
|
||||||
extraSubtitlesDelay: number | null,
|
extraSubtitlesDelay: number | null,
|
||||||
extraSubtitlesSize: number | null,
|
extraSubtitlesSize: number | null,
|
||||||
|
assSubtitlesStylingActive: boolean,
|
||||||
onSubtitlesTrackSelected: (track: SubtitleTrack | null) => void,
|
onSubtitlesTrackSelected: (track: SubtitleTrack | null) => void,
|
||||||
onExtraSubtitlesTrackSelected: (track: SubtitleTrack | null) => void,
|
onExtraSubtitlesTrackSelected: (track: SubtitleTrack | null) => void,
|
||||||
onSubtitlesOffsetChanged: (offset: number) => void,
|
onSubtitlesOffsetChanged: (offset: number) => void,
|
||||||
|
|
|
||||||
|
|
@ -353,6 +353,7 @@ const useSubtitles = ({
|
||||||
extraSubtitlesOffset: video.state.extraSubtitlesOffset,
|
extraSubtitlesOffset: video.state.extraSubtitlesOffset,
|
||||||
extraSubtitlesDelay: video.state.extraSubtitlesDelay,
|
extraSubtitlesDelay: video.state.extraSubtitlesDelay,
|
||||||
extraSubtitlesSize: video.state.extraSubtitlesSize,
|
extraSubtitlesSize: video.state.extraSubtitlesSize,
|
||||||
|
assSubtitlesStylingActive: video.state.assSubtitlesStylingActive,
|
||||||
onSubtitlesTrackSelected: selectEmbeddedTrack,
|
onSubtitlesTrackSelected: selectEmbeddedTrack,
|
||||||
onExtraSubtitlesTrackSelected: selectExtraTrack,
|
onExtraSubtitlesTrackSelected: selectExtraTrack,
|
||||||
onSubtitlesOffsetChanged: changeOffset,
|
onSubtitlesOffsetChanged: changeOffset,
|
||||||
|
|
@ -372,6 +373,7 @@ const useSubtitles = ({
|
||||||
video.state.extraSubtitlesOffset,
|
video.state.extraSubtitlesOffset,
|
||||||
video.state.extraSubtitlesSize,
|
video.state.extraSubtitlesSize,
|
||||||
video.state.extraSubtitlesTracks,
|
video.state.extraSubtitlesTracks,
|
||||||
|
video.state.assSubtitlesStylingActive,
|
||||||
video.state.selectedExtraSubtitlesTrackId,
|
video.state.selectedExtraSubtitlesTrackId,
|
||||||
video.state.selectedSubtitlesTrackId,
|
video.state.selectedSubtitlesTrackId,
|
||||||
video.state.subtitlesOffset,
|
video.state.subtitlesOffset,
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ const useVideo = () => {
|
||||||
extraSubtitlesTextColor: null,
|
extraSubtitlesTextColor: null,
|
||||||
extraSubtitlesBackgroundColor: null,
|
extraSubtitlesBackgroundColor: null,
|
||||||
extraSubtitlesOutlineColor: null,
|
extraSubtitlesOutlineColor: null,
|
||||||
|
assSubtitlesStylingActive: false,
|
||||||
fullscreen: null,
|
fullscreen: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,12 @@ const Player = forwardRef<HTMLDivElement, Props>(({ profile }: Props, ref) => {
|
||||||
{...subtitlesOutlineColorInput}
|
{...subtitlesOutlineColorInput}
|
||||||
/>
|
/>
|
||||||
</Option>
|
</Option>
|
||||||
|
<Option label={'SETTINGS_ASS_SUBTITLES_STYLING'}>
|
||||||
|
<Toggle
|
||||||
|
tabIndex={-1}
|
||||||
|
{...assSubtitlesStylingToggle}
|
||||||
|
/>
|
||||||
|
</Option>
|
||||||
</Category>
|
</Category>
|
||||||
<Category icon={'volume-medium'} label={'SETTINGS_SECTION_AUDIO'}>
|
<Category icon={'volume-medium'} label={'SETTINGS_SECTION_AUDIO'}>
|
||||||
<Option label={'SETTINGS_DEFAULT_AUDIO_TRACK'}>
|
<Option label={'SETTINGS_DEFAULT_AUDIO_TRACK'}>
|
||||||
|
|
@ -159,15 +165,6 @@ const Player = forwardRef<HTMLDivElement, Props>(({ profile }: Props, ref) => {
|
||||||
/>
|
/>
|
||||||
</Option>
|
</Option>
|
||||||
}
|
}
|
||||||
{
|
|
||||||
shell.active &&
|
|
||||||
<Option label={'SETTINGS_ASS_SUBTITLES_STYLING'}>
|
|
||||||
<Toggle
|
|
||||||
tabIndex={-1}
|
|
||||||
{...assSubtitlesStylingToggle}
|
|
||||||
/>
|
|
||||||
</Option>
|
|
||||||
}
|
|
||||||
</Category>
|
</Category>
|
||||||
</Section>
|
</Section>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue