Add ASS subtitle controls

This commit is contained in:
Timothy Z. 2026-07-18 23:52:37 +03:00
parent 51f4db1e04
commit a1d7118696
7 changed files with 44 additions and 15 deletions

View file

@ -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);

View file

@ -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)}

View file

@ -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,

View file

@ -10,6 +10,7 @@ type SubtitleTrack = {
embedded?: boolean,
local?: boolean,
exclusive?: boolean,
ass?: boolean,
buffer?: ArrayBuffer,
};
@ -29,6 +30,7 @@ type VideoSubtitleState = {
extraSubtitlesOffset: number | null,
extraSubtitlesDelay: number | null,
extraSubtitlesSize: number | null,
assSubtitlesStylingActive: boolean,
};
type VideoEvents = {
@ -74,6 +76,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,

View file

@ -353,6 +353,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,
@ -372,6 +373,7 @@ const useSubtitles = ({
video.state.extraSubtitlesOffset,
video.state.extraSubtitlesSize,
video.state.extraSubtitlesTracks,
video.state.assSubtitlesStylingActive,
video.state.selectedExtraSubtitlesTrackId,
video.state.selectedSubtitlesTrackId,
video.state.subtitlesOffset,

View file

@ -40,6 +40,7 @@ const useVideo = () => {
extraSubtitlesTextColor: null,
extraSubtitlesBackgroundColor: null,
extraSubtitlesOutlineColor: null,
assSubtitlesStylingActive: false,
fullscreen: null,
});

View file

@ -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>
);