From a1d7118696aca929419bd8ed9e7aaeabf72e82e1 Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Sat, 18 Jul 2026 23:52:37 +0300 Subject: [PATCH] Add ASS subtitle controls --- .../SubtitleVariant/SubtitleVariant.less | 18 ++++++++++++++++++ .../SubtitleVariant/SubtitleVariant.tsx | 9 +++++++-- .../Player/SubtitlesMenu/SubtitlesMenu.js | 11 +++++++---- src/routes/Player/useSubtitles.d.ts | 3 +++ src/routes/Player/useSubtitles.ts | 2 ++ src/routes/Player/useVideo.js | 1 + src/routes/Settings/Player/Player.tsx | 15 ++++++--------- 7 files changed, 44 insertions(+), 15 deletions(-) diff --git a/src/routes/Player/SubtitlesMenu/SubtitleVariant/SubtitleVariant.less b/src/routes/Player/SubtitlesMenu/SubtitleVariant/SubtitleVariant.less index 600b79658..58700053d 100644 --- a/src/routes/Player/SubtitlesMenu/SubtitleVariant/SubtitleVariant.less +++ b/src/routes/Player/SubtitlesMenu/SubtitleVariant/SubtitleVariant.less @@ -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); diff --git a/src/routes/Player/SubtitlesMenu/SubtitleVariant/SubtitleVariant.tsx b/src/routes/Player/SubtitlesMenu/SubtitleVariant/SubtitleVariant.tsx index 9bd8f909c..bc9bc5268 100644 --- a/src/routes/Player/SubtitlesMenu/SubtitleVariant/SubtitleVariant.tsx +++ b/src/routes/Player/SubtitlesMenu/SubtitleVariant/SubtitleVariant.tsx @@ -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 })} >
-
- {variantLabel} +
+
+ {variantLabel} +
+ {track.ass ?
{ASS_BADGE}
: null}
{t(track.origin)} diff --git a/src/routes/Player/SubtitlesMenu/SubtitlesMenu.js b/src/routes/Player/SubtitlesMenu/SubtitlesMenu.js index a71969bd5..d40cf0874 100644 --- a/src/routes/Player/SubtitlesMenu/SubtitlesMenu.js +++ b/src/routes/Player/SubtitlesMenu/SubtitlesMenu.js @@ -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} /> { 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} />
@@ -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, diff --git a/src/routes/Player/useSubtitles.d.ts b/src/routes/Player/useSubtitles.d.ts index 93084e7b2..cacec3742 100644 --- a/src/routes/Player/useSubtitles.d.ts +++ b/src/routes/Player/useSubtitles.d.ts @@ -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, diff --git a/src/routes/Player/useSubtitles.ts b/src/routes/Player/useSubtitles.ts index 26de76d74..f21282ecc 100644 --- a/src/routes/Player/useSubtitles.ts +++ b/src/routes/Player/useSubtitles.ts @@ -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, diff --git a/src/routes/Player/useVideo.js b/src/routes/Player/useVideo.js index 570888ff1..aeeca59e2 100644 --- a/src/routes/Player/useVideo.js +++ b/src/routes/Player/useVideo.js @@ -40,6 +40,7 @@ const useVideo = () => { extraSubtitlesTextColor: null, extraSubtitlesBackgroundColor: null, extraSubtitlesOutlineColor: null, + assSubtitlesStylingActive: false, fullscreen: null, }); diff --git a/src/routes/Settings/Player/Player.tsx b/src/routes/Settings/Player/Player.tsx index 29883e91d..317fd9aa9 100644 --- a/src/routes/Settings/Player/Player.tsx +++ b/src/routes/Settings/Player/Player.tsx @@ -66,6 +66,12 @@ const Player = forwardRef(({ profile }: Props, ref) => { {...subtitlesOutlineColorInput} /> + } - { - shell.active && - - } );