Skip to content

Commit

Permalink
Top / bottom setting for individual subtitles (#508)
Browse files Browse the repository at this point in the history
* extension: Add topSubtitleParams as a separate container

* settings + extension: assign subtitle tracks to their position

* add topOffset setting

* fix blur not working

* localise

* cleanup

* test fixes

* only render respective overlays if they're actually enabled

* subtitlesElementOverlay => bottomSubtitlesElementOverlay

* update cacheHtml()

* subtitlePositionOffset => bottomSubtitlePositionOffset

* review comments

* pretty

* test fixes

* remove file comitted by mistake

* review comments: fix track disappearing
  • Loading branch information
artjomsR authored Oct 18, 2024
1 parent 0b29719 commit b39cef5
Show file tree
Hide file tree
Showing 22 changed files with 274 additions and 161 deletions.
12 changes: 8 additions & 4 deletions common/app/components/VideoPlayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -344,9 +344,12 @@ export default function VideoPlayer({
const [subtitlePlayerHidden, setSubtitlePlayerHidden] = useState<boolean>(false);
const [appBarHidden, setAppBarHidden] = useState<boolean>(playbackPreferences.theaterMode);
const [subtitleAlignment, setSubtitleAlignment] = useState<SubtitleAlignment>(subtitleSettings.subtitleAlignment);
const [subtitlePositionOffset, setSubtitlePositionOffset] = useState<number>(
const [bottomSubtitlePositionOffset, setBottomSubtitlePositionOffset] = useState<number>(
subtitleSettings.subtitlePositionOffset
);
const [topSubtitlePositionOffset, setTopSubtitlePositionOffset] = useState<number>(
subtitleSettings.topSubtitlePositionOffset
);
const showSubtitlesRef = useRef<IndexedSubtitleModel[]>([]);
showSubtitlesRef.current = showSubtitles;
const clock = useMemo<Clock>(() => new Clock(), []);
Expand All @@ -369,7 +372,8 @@ export default function VideoPlayer({

useEffect(() => {
setSubtitleAlignment(subtitleSettings.subtitleAlignment);
setSubtitlePositionOffset(subtitleSettings.subtitlePositionOffset);
setBottomSubtitlePositionOffset(subtitleSettings.subtitlePositionOffset);
setTopSubtitlePositionOffset(subtitleSettings.topSubtitlePositionOffset);
}, [subtitleSettings]);

const autoPauseContext = useMemo(() => {
Expand Down Expand Up @@ -1319,8 +1323,8 @@ export default function VideoPlayer({
<div
style={{
...(subtitleAlignment === 'bottom'
? { bottom: subtitlePositionOffset }
: { top: subtitlePositionOffset }),
? { bottom: bottomSubtitlePositionOffset }
: { top: topSubtitlePositionOffset }),
...(subtitleSettings.subtitlesWidth === -1
? {}
: { width: `${subtitleSettings.subtitlesWidth}%` }),
Expand Down
25 changes: 22 additions & 3 deletions common/app/hooks/use-playback-preferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,32 @@ import PlaybackPreferences from '../services/playback-preferences';
import ChromeExtension from '../services/chrome-extension';

export const usePlaybackPreferences = (settings: SubtitleSettings & MiscSettings, extension: ChromeExtension) => {
const { rememberSubtitleOffset, lastSubtitleOffset, subtitleAlignment, subtitlePositionOffset } = settings;
const {
rememberSubtitleOffset,
lastSubtitleOffset,
subtitleAlignment,
subtitlePositionOffset,
topSubtitlePositionOffset,
} = settings;
return useMemo(
() =>
new PlaybackPreferences(
{ rememberSubtitleOffset, lastSubtitleOffset, subtitleAlignment, subtitlePositionOffset },
{
rememberSubtitleOffset,
lastSubtitleOffset,
subtitleAlignment,
subtitlePositionOffset,
topSubtitlePositionOffset,
},
extension
),
[rememberSubtitleOffset, lastSubtitleOffset, subtitleAlignment, subtitlePositionOffset, extension]
[
rememberSubtitleOffset,
lastSubtitleOffset,
subtitleAlignment,
subtitlePositionOffset,
topSubtitlePositionOffset,
extension,
]
);
};
1 change: 1 addition & 0 deletions common/app/services/playback-preferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ interface PlaybackPrefSettings {
lastSubtitleOffset: number;
subtitleAlignment: SubtitleAlignment;
subtitlePositionOffset: number;
topSubtitlePositionOffset: number;
}

export default class PlaybackPreferences {
Expand Down
6 changes: 4 additions & 2 deletions common/app/services/video-channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,8 @@ export default class VideoChannel {
imageBasedSubtitleScaleFactor,
subtitleAlignment,
subtitleTracksV2,
subtitlePositionOffset,
subtitlePositionOffset: bottomSubtitlePositionOffset,
topSubtitlePositionOffset,
subtitlesWidth,
} = settings;
const message: SubtitleSettingsToVideoMessage = {
Expand All @@ -420,7 +421,8 @@ export default class VideoChannel {
imageBasedSubtitleScaleFactor,
subtitleAlignment,
subtitleTracksV2,
subtitlePositionOffset,
subtitlePositionOffset: bottomSubtitlePositionOffset,
topSubtitlePositionOffset,
subtitlesWidth,
},
};
Expand Down
91 changes: 56 additions & 35 deletions common/components/SettingsForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -790,8 +790,8 @@ export default function SettingsForm({
track3Field,
ankiFieldSettings,
subtitlePreview,
subtitlePositionOffset,
subtitleAlignment,
subtitlePositionOffset: subtitlePositionOffset,
topSubtitlePositionOffset,
subtitlesWidth,
audioPaddingStart,
audioPaddingEnd,
Expand Down Expand Up @@ -852,6 +852,7 @@ export default function SettingsForm({
subtitleFontFamily,
subtitleCustomStyles,
subtitleBlur,
subtitleAlignment,
} = textSubtitleSettingsForTrack(settings, selectedSubtitleAppearanceTrack);

const handleAddCustomField = useCallback(
Expand Down Expand Up @@ -1870,6 +1871,42 @@ export default function SettingsForm({
</Tooltip>
)}

{subtitleAlignment !== undefined && (
<>
<FormLabel className={classes.top} component="legend">
{t('settings.subtitleAlignment')}
</FormLabel>
<RadioGroup row>
<LabelWithHoverEffect
control={
<Radio
checked={subtitleAlignment === 'bottom'}
value={'bottom'}
onChange={(event) =>
event.target.checked &&
handleSubtitleTextSettingChanged('subtitleAlignment', 'bottom')
}
/>
}
label={t('settings.subtitleAlignmentBottom')}
/>
<LabelWithHoverEffect
control={
<Radio
checked={subtitleAlignment === 'top'}
value={'top'}
onChange={(event) =>
event.target.checked &&
handleSubtitleTextSettingChanged('subtitleAlignment', 'top')
}
/>
}
label={t('settings.subtitleAlignmentTop')}
/>
</RadioGroup>
</>
)}

{subtitleCustomStyles !== undefined && (
<>
{subtitleCustomStyles.map((customStyle, index) => {
Expand Down Expand Up @@ -1909,39 +1946,6 @@ export default function SettingsForm({

{selectedSubtitleAppearanceTrack === undefined && (
<>
<div className={classes.subtitleSetting}>
<FormLabel className={classes.top} component="legend">
{t('settings.subtitleAlignment')}
</FormLabel>
<RadioGroup row>
<LabelWithHoverEffect
control={
<Radio
checked={subtitleAlignment === 'bottom'}
value={'bottom'}
onChange={(event) =>
event.target.checked &&
handleSettingChanged('subtitleAlignment', 'bottom')
}
/>
}
label={t('settings.subtitleAlignmentBottom')}
/>
<LabelWithHoverEffect
control={
<Radio
checked={subtitleAlignment === 'top'}
value={'top'}
onChange={(event) =>
event.target.checked &&
handleSettingChanged('subtitleAlignment', 'top')
}
/>
}
label={t('settings.subtitleAlignmentTop')}
/>
</RadioGroup>
</div>
<div className={classes.subtitleSetting}>
<TextField
className={classes.textField}
Expand All @@ -1959,6 +1963,23 @@ export default function SettingsForm({
}
/>
</div>
<div className={classes.subtitleSetting}>
<TextField
className={classes.textField}
type="number"
color="secondary"
fullWidth
label={t('settings.topSubtitlePositionOffset')}
value={topSubtitlePositionOffset}
inputProps={{
min: 0,
step: 1,
}}
onChange={(e) =>
handleSettingChanged('topSubtitlePositionOffset', Number(e.target.value))
}
/>
</div>
{(!extensionInstalled || extensionSupportsSubtitlesWidthSetting) && (
<div className={classes.subtitleSetting}>
<TextField
Expand Down
3 changes: 3 additions & 0 deletions common/components/SubtitlePreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ const SubtitlePreviewInput = ({ text, className, textSubtitleSettings, onTextCha
subtitleFontFamily,
subtitleCustomStyles,
subtitleBlur,
subtitleAlignment,
} = textSubtitleSettings;

const subtitlePreviewStyles = useMemo(
Expand All @@ -75,6 +76,7 @@ const SubtitlePreviewInput = ({ text, className, textSubtitleSettings, onTextCha
subtitleFontFamily,
subtitleCustomStyles,
subtitleBlur,
subtitleAlignment,
}),
[
subtitleColor,
Expand All @@ -89,6 +91,7 @@ const SubtitlePreviewInput = ({ text, className, textSubtitleSettings, onTextCha
subtitleFontFamily,
subtitleCustomStyles,
subtitleBlur,
subtitleAlignment,
]
);

Expand Down
1 change: 1 addition & 0 deletions common/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@
"subtitleShadowThickness": "Subtitle Shadow Thickness",
"subtitleOutlineThicknessHelperText": "Adds an outline around subtitle text. If this causes overlapping lines, try using a different font.",
"subtitlePositionOffset": "Untertitelabstand vom unteren Bildschirmrand",
"topSubtitlePositionOffset": "Untertitelabstand vom oberer Bildschirmrand",
"subtitleAlignment": "Untertitel-Position",
"subtitleAlignmentBottom": "Unten",
"subtitleAlignmentTop": "Oben",
Expand Down
1 change: 1 addition & 0 deletions common/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@
"subtitleShadowThickness": "Subtitle Shadow Thickness",
"subtitleOutlineThicknessHelperText": "Adds an outline around subtitle text. If this causes overlapping lines, try using a different font.",
"subtitlePositionOffset": "Subtitle position offset from bottom",
"topSubtitlePositionOffset": "Subtitle position offset from top",
"subtitleAlignment": "Subtitle Alignment",
"subtitleAlignmentBottom": "Bottom",
"subtitleAlignmentTop": "Top",
Expand Down
3 changes: 2 additions & 1 deletion common/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,8 @@
"subtitleShadowThickness": "Grosor del Sombreado de los Subtítulos",
"subtitleOutlineThicknessHelperText": "Agrega un contorno al texto de los subtítulos. Si esto causa líneas superpuestas, trata de usar otra fuente.",
"subtitlePositionOffset": "Distancia de los subtítulos desde el borde inferior",
"subtitleAlignment": "Alineación de Subtítulos",
"subtitleAlignment": "Subtitle position offset from bottom",
"topSubtitlePositionOffset": "Subtitle position offset from top",
"subtitleAlignmentBottom": "Inferior",
"subtitleAlignmentTop": "Superior",
"subtitleBlur": "Desenfoque de subtítulos",
Expand Down
3 changes: 2 additions & 1 deletion common/locales/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,8 @@
"subtitleShadowColor": "字幕の影の色",
"subtitleShadowThickness": "字幕の影の太さ",
"subtitleOutlineThicknessHelperText": "字幕に縁取りが追加される。縁取りの線が重なっているように見える場合、別のフォントを試してみてください。",
"subtitlePositionOffset": "字幕表示位置の調整",
"subtitlePositionOffset": "Subtitle position offset from bottom",
"topSubtitlePositionOffset": "Subtitle position offset from top",
"subtitleAlignment": "字幕の表示位置",
"subtitleAlignmentBottom": "下部",
"subtitleAlignmentTop": "上部",
Expand Down
3 changes: 2 additions & 1 deletion common/locales/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,8 @@
"subtitleShadowColor": "Kolor cienia napisów",
"subtitleShadowThickness": "Wielkość cienia napisów",
"subtitleOutlineThicknessHelperText": "Dodaje obwódkę wokół napisów. Jeżeli to ustawienie powoduje nakładanie się linii tekstu, spróbuj użyć innej czcionki.",
"subtitlePositionOffset": "Przesunięcie pozycji napisów",
"subtitlePositionOffset": "Subtitle position offset from bottom",
"topSubtitlePositionOffset": "Subtitle position offset from top",
"subtitleAlignment": "Wyrównanie napisów",
"subtitleAlignmentBottom": "Dół",
"subtitleAlignmentTop": "Góra",
Expand Down
1 change: 1 addition & 0 deletions common/locales/pt_BR.json
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@
"subtitleShadowThickness": "Expessura da sombra da legenda",
"subtitleOutlineThicknessHelperText": "Adiciona um contorno ao redor do texto da legenda. Se isso causar sobreposição de linhas, tente usar uma fonte diferente.",
"subtitlePositionOffset": "Deslocamento da posição da legenda a partir da parte inferior",
"topSubtitlePositionOffset": "Deslocamento da posição da legenda a partir da parte superior",
"subtitleAlignment": "Alinhamento da legenda",
"subtitleAlignmentBottom": "Inferior",
"subtitleAlignmentTop": "Superior",
Expand Down
1 change: 1 addition & 0 deletions common/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@
"subtitleShadowThickness": "Толщина тени субтитров",
"subtitleOutlineThicknessHelperText": "Добавляет контур вокруг текста субтитров. Если это приводит к перекрытию строк, попробуйте использовать другой шрифт.",
"subtitlePositionOffset": "Отступ субтитров от нижнего края",
"topSubtitlePositionOffset": "Отступ субтитров от верхнего края",
"subtitleAlignment": "Выравнивание субтитров",
"subtitleAlignmentBottom": "По нижнему краю",
"subtitleAlignmentTop": "По верхнему краю",
Expand Down
1 change: 1 addition & 0 deletions common/locales/zh_CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@
"subtitleShadowThickness": "Subtitle Shadow Thickness",
"subtitleOutlineThicknessHelperText": "在字幕文本周围添加轮廓线。如果这会导致线条重叠,请尝试使用其他字体。",
"subtitlePositionOffset": "字幕位置从底部偏移",
"topSubtitlePositionOffset": "字幕位置从顶部偏移",
"subtitleAlignment": "字幕对齐方式",
"subtitleAlignmentBottom": "底部",
"subtitleAlignmentTop": "顶部",
Expand Down
3 changes: 2 additions & 1 deletion common/settings/settings-import-export.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,13 @@ it('validates exported settings', () => {
subtitleBackgroundOpacity: 0,
subtitleFontFamily: 'ToppanBunkyuMidashiGothicStdN-ExtraBold',
subtitleBlur: true,
subtitleAlignment: 'bottom',
subtitleCustomStyles: [],
},
],
subtitlePreview: 'アあ安Aa',
subtitlePositionOffset: 71,
subtitleAlignment: 'bottom',
topSubtitlePositionOffset: 71,
audioPaddingStart: 0,
audioPaddingEnd: 500,
maxImageWidth: 480,
Expand Down
3 changes: 3 additions & 0 deletions common/settings/settings-import-export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,9 @@ const settingsSchema = {
subtitlePositionOffset: {
type: 'number',
},
topSubtitlePositionOffset: {
type: 'number',
},
subtitleAlignment: {
type: 'string',
},
Expand Down
Loading

0 comments on commit b39cef5

Please sign in to comment.