mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Add subtitle setting for native vs custom element (#5737)
* Fixed subtitles styling in firefox. * Fixed subtitles styling in firefox. * Initial changes to support native or custom styling. * Changes to support native or custom styling. * linting changes. * Changes to support native or custom styling. * Changes to support native or custom styling. * minor changes. * indentation changes and simplification changes. * minor changes. --------- Co-authored-by: Bill Thornton <thornbill@users.noreply.github.com>
This commit is contained in:
parent
9d63a715eb
commit
2689c51b84
4 changed files with 85 additions and 42 deletions
|
@ -26,6 +26,7 @@ import template from './subtitlesettings.template.html';
|
||||||
|
|
||||||
function getSubtitleAppearanceObject(context) {
|
function getSubtitleAppearanceObject(context) {
|
||||||
return {
|
return {
|
||||||
|
subtitleStyling: context.querySelector('#selectSubtitleStyling').value,
|
||||||
textSize: context.querySelector('#selectTextSize').value,
|
textSize: context.querySelector('#selectTextSize').value,
|
||||||
textWeight: context.querySelector('#selectTextWeight').value,
|
textWeight: context.querySelector('#selectTextWeight').value,
|
||||||
dropShadow: context.querySelector('#selectDropShadow').value,
|
dropShadow: context.querySelector('#selectDropShadow').value,
|
||||||
|
@ -51,6 +52,8 @@ function loadForm(context, user, userSettings, appearanceSettings, apiClient) {
|
||||||
|
|
||||||
context.querySelector('#selectSubtitlePlaybackMode').dispatchEvent(new CustomEvent('change', {}));
|
context.querySelector('#selectSubtitlePlaybackMode').dispatchEvent(new CustomEvent('change', {}));
|
||||||
|
|
||||||
|
context.querySelector('#selectSubtitleStyling').value = appearanceSettings.subtitleStyling || 'Auto';
|
||||||
|
context.querySelector('#selectSubtitleStyling').dispatchEvent(new CustomEvent('change', {}));
|
||||||
context.querySelector('#selectTextSize').value = appearanceSettings.textSize || '';
|
context.querySelector('#selectTextSize').value = appearanceSettings.textSize || '';
|
||||||
context.querySelector('#selectTextWeight').value = appearanceSettings.textWeight || 'normal';
|
context.querySelector('#selectTextWeight').value = appearanceSettings.textWeight || 'normal';
|
||||||
context.querySelector('#selectDropShadow').value = appearanceSettings.dropShadow || '';
|
context.querySelector('#selectDropShadow').value = appearanceSettings.dropShadow || '';
|
||||||
|
@ -117,6 +120,16 @@ function onSubtitleModeChange(e) {
|
||||||
view.querySelector('.subtitles' + this.value + 'Help').classList.remove('hide');
|
view.querySelector('.subtitles' + this.value + 'Help').classList.remove('hide');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onSubtitleStyleChange(e) {
|
||||||
|
const view = dom.parentWithClass(e.target, 'subtitlesettings');
|
||||||
|
|
||||||
|
const subtitleStylingHelperElements = view.querySelectorAll('.subtitleStylingHelp');
|
||||||
|
subtitleStylingHelperElements.forEach((elem)=>{
|
||||||
|
elem.classList.add('hide');
|
||||||
|
});
|
||||||
|
view.querySelector(`.subtitleStyling${this.value}Help`).classList.remove('hide');
|
||||||
|
}
|
||||||
|
|
||||||
function onSubtitleBurnInChange(e) {
|
function onSubtitleBurnInChange(e) {
|
||||||
const view = dom.parentWithClass(e.target, 'subtitlesettings');
|
const view = dom.parentWithClass(e.target, 'subtitlesettings');
|
||||||
const fieldRenderPgs = view.querySelector('.fldRenderPgs');
|
const fieldRenderPgs = view.querySelector('.fldRenderPgs');
|
||||||
|
@ -180,6 +193,7 @@ function embed(options, self) {
|
||||||
options.element.querySelector('form').addEventListener('submit', self.onSubmit.bind(self));
|
options.element.querySelector('form').addEventListener('submit', self.onSubmit.bind(self));
|
||||||
|
|
||||||
options.element.querySelector('#selectSubtitlePlaybackMode').addEventListener('change', onSubtitleModeChange);
|
options.element.querySelector('#selectSubtitlePlaybackMode').addEventListener('change', onSubtitleModeChange);
|
||||||
|
options.element.querySelector('#selectSubtitleStyling').addEventListener('change', onSubtitleStyleChange);
|
||||||
options.element.querySelector('#selectSubtitleBurnIn').addEventListener('change', onSubtitleBurnInChange);
|
options.element.querySelector('#selectSubtitleBurnIn').addEventListener('change', onSubtitleBurnInChange);
|
||||||
options.element.querySelector('#selectTextSize').addEventListener('change', onAppearanceFieldChange);
|
options.element.querySelector('#selectTextSize').addEventListener('change', onAppearanceFieldChange);
|
||||||
options.element.querySelector('#selectTextWeight').addEventListener('change', onAppearanceFieldChange);
|
options.element.querySelector('#selectTextWeight').addEventListener('change', onAppearanceFieldChange);
|
||||||
|
|
|
@ -77,6 +77,17 @@
|
||||||
<div class="fieldDescription">${SubtitleAppearanceSettingsAlsoPassedToCastDevices}</div>
|
<div class="fieldDescription">${SubtitleAppearanceSettingsAlsoPassedToCastDevices}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="selectContainer">
|
||||||
|
<select is="emby-select" id="selectSubtitleStyling" label="${LabelSubtitleStyling}">
|
||||||
|
<option value="Auto">${Auto}</option>
|
||||||
|
<option value="Custom">${Custom}</option>
|
||||||
|
<option value="Native">${Native}</option>
|
||||||
|
</select>
|
||||||
|
<div class="fieldDescription subtitleStylingAutoHelp subtitleStylingHelp hide">${AutoSubtitleStylingHelp}</div>
|
||||||
|
<div class="fieldDescription subtitleStylingCustomHelp subtitleStylingHelp hide">${CustomSubtitleStylingHelp}</div>
|
||||||
|
<div class="fieldDescription subtitleStylingNativeHelp subtitleStylingHelp hide">${NativeSubtitleStylingHelp}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="selectContainer">
|
<div class="selectContainer">
|
||||||
<select is="emby-select" id="selectTextSize" label="${LabelTextSize}">
|
<select is="emby-select" id="selectTextSize" label="${LabelTextSize}">
|
||||||
<option value="smaller">${Smaller}</option>
|
<option value="smaller">${Smaller}</option>
|
||||||
|
|
|
@ -1349,31 +1349,44 @@ export class HtmlVideoPlayer {
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
requiresCustomSubtitlesElement() {
|
requiresCustomSubtitlesElement(userSettings) {
|
||||||
// after a system update, ps4 isn't showing anything when creating a track element dynamically
|
const subtitleAppearance = userSettings.getSubtitleAppearanceSettings();
|
||||||
// going to have to do it ourselves
|
switch (subtitleAppearance.subtitleStyling) {
|
||||||
if (browser.ps4) {
|
case 'Native':
|
||||||
return true;
|
return false;
|
||||||
}
|
case 'Custom':
|
||||||
|
|
||||||
// Tizen 5 doesn't support displaying secondary subtitles
|
|
||||||
if (browser.tizenVersion >= 5 || browser.web0s) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (browser.edge) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (browser.iOS) {
|
|
||||||
const userAgent = navigator.userAgent.toLowerCase();
|
|
||||||
// works in the browser but not the native app
|
|
||||||
if ((userAgent.includes('os 9') || userAgent.includes('os 8')) && !userAgent.includes('safari')) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
default:
|
||||||
}
|
// after a system update, ps4 isn't showing anything when creating a track element dynamically
|
||||||
|
// going to have to do it ourselves
|
||||||
|
if (browser.ps4) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
// Tizen 5 doesn't support displaying secondary subtitles
|
||||||
|
if (browser.tizenVersion >= 5 || browser.web0s) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (browser.edge) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// font-size styling does not seem to work natively in firefox. Switching to custom subtitles element for firefox.
|
||||||
|
if (browser.firefox) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (browser.iOS) {
|
||||||
|
const userAgent = navigator.userAgent.toLowerCase();
|
||||||
|
// works in the browser but not the native app
|
||||||
|
if ((userAgent.includes('os 9') || userAgent.includes('os 8')) && !userAgent.includes('safari')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1458,7 +1471,9 @@ export class HtmlVideoPlayer {
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
renderTracksEvents(videoElement, track, item, targetTextTrackIndex = PRIMARY_TEXT_TRACK_INDEX) {
|
async renderTracksEvents(videoElement, track, item, targetTextTrackIndex = PRIMARY_TEXT_TRACK_INDEX) {
|
||||||
|
const { currentSettings: userSettings } = await import('../../scripts/settings/userSettings');
|
||||||
|
|
||||||
if (!itemHelper.isLocalItem(item) || track.IsExternal) {
|
if (!itemHelper.isLocalItem(item) || track.IsExternal) {
|
||||||
const format = (track.Codec || '').toLowerCase();
|
const format = (track.Codec || '').toLowerCase();
|
||||||
if (format === 'ssa' || format === 'ass') {
|
if (format === 'ssa' || format === 'ass') {
|
||||||
|
@ -1470,7 +1485,7 @@ export class HtmlVideoPlayer {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.requiresCustomSubtitlesElement()) {
|
if (this.requiresCustomSubtitlesElement(userSettings)) {
|
||||||
this.renderSubtitlesWithCustomElement(videoElement, track, item, targetTextTrackIndex);
|
this.renderSubtitlesWithCustomElement(videoElement, track, item, targetTextTrackIndex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1500,28 +1515,25 @@ export class HtmlVideoPlayer {
|
||||||
|
|
||||||
// download the track json
|
// download the track json
|
||||||
this.fetchSubtitles(track, item).then(function (data) {
|
this.fetchSubtitles(track, item).then(function (data) {
|
||||||
import('../../scripts/settings/userSettings').then((userSettings) => {
|
console.debug(`downloaded ${data.TrackEvents.length} track events`);
|
||||||
// show in ui
|
|
||||||
console.debug(`downloaded ${data.TrackEvents.length} track events`);
|
|
||||||
|
|
||||||
const subtitleAppearance = userSettings.getSubtitleAppearanceSettings();
|
const subtitleAppearance = userSettings.getSubtitleAppearanceSettings();
|
||||||
const cueLine = parseInt(subtitleAppearance.verticalPosition, 10);
|
const cueLine = parseInt(subtitleAppearance.verticalPosition, 10);
|
||||||
|
|
||||||
// add some cues to show the text
|
// add some cues to show the text
|
||||||
// in safari, the cues need to be added before setting the track mode to showing
|
// in safari, the cues need to be added before setting the track mode to showing
|
||||||
for (const trackEvent of data.TrackEvents) {
|
for (const trackEvent of data.TrackEvents) {
|
||||||
const TrackCue = window.VTTCue || window.TextTrackCue;
|
const TrackCue = window.VTTCue || window.TextTrackCue;
|
||||||
const cue = new TrackCue(trackEvent.StartPositionTicks / 10000000, trackEvent.EndPositionTicks / 10000000, normalizeTrackEventText(trackEvent.Text, false));
|
const cue = new TrackCue(trackEvent.StartPositionTicks / 10000000, trackEvent.EndPositionTicks / 10000000, normalizeTrackEventText(trackEvent.Text, false));
|
||||||
|
|
||||||
if (cue.line === 'auto') {
|
if (cue.line === 'auto') {
|
||||||
cue.line = cueLine;
|
cue.line = cueLine;
|
||||||
}
|
|
||||||
|
|
||||||
trackElement.addCue(cue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trackElement.mode = 'showing';
|
trackElement.addCue(cue);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
trackElement.mode = 'showing';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,7 @@
|
||||||
"Authorize": "Authorize",
|
"Authorize": "Authorize",
|
||||||
"AuthProviderHelp": "Select an authentication provider to be used to authenticate this user's password.",
|
"AuthProviderHelp": "Select an authentication provider to be used to authenticate this user's password.",
|
||||||
"Auto": "Auto",
|
"Auto": "Auto",
|
||||||
|
"AutoSubtitleStylingHelp": "This mode will automatically switch between the native and custom subtitle styling mechanisms based on your device type.",
|
||||||
"Backdrop": "Backdrop",
|
"Backdrop": "Backdrop",
|
||||||
"Backdrops": "Backdrops",
|
"Backdrops": "Backdrops",
|
||||||
"BackdropScreensaver": "Backdrop Screensaver",
|
"BackdropScreensaver": "Backdrop Screensaver",
|
||||||
|
@ -191,6 +192,8 @@
|
||||||
"Creator": "Creator",
|
"Creator": "Creator",
|
||||||
"CriticRating": "Critics rating",
|
"CriticRating": "Critics rating",
|
||||||
"Cursive": "Cursive",
|
"Cursive": "Cursive",
|
||||||
|
"Custom": "Custom",
|
||||||
|
"CustomSubtitleStylingHelp": "Subtitle styling will work on most devices, but comes with an additional performance overhead.",
|
||||||
"DailyAt": "Daily at {0}",
|
"DailyAt": "Daily at {0}",
|
||||||
"Data": "Data",
|
"Data": "Data",
|
||||||
"DateAdded": "Date added",
|
"DateAdded": "Date added",
|
||||||
|
@ -907,6 +910,7 @@
|
||||||
"LabelStreamType": "Stream type",
|
"LabelStreamType": "Stream type",
|
||||||
"LabelSubtitleDownloaders": "Subtitle downloaders",
|
"LabelSubtitleDownloaders": "Subtitle downloaders",
|
||||||
"LabelSubtitlePlaybackMode": "Subtitle mode",
|
"LabelSubtitlePlaybackMode": "Subtitle mode",
|
||||||
|
"LabelSubtitleStyling": "Subtitle styling",
|
||||||
"LabelSubtitleVerticalPosition": "Vertical position",
|
"LabelSubtitleVerticalPosition": "Vertical position",
|
||||||
"LabelSyncPlayAccess": "SyncPlay access",
|
"LabelSyncPlayAccess": "SyncPlay access",
|
||||||
"LabelSyncPlayAccessCreateAndJoinGroups": "Allow user to create and join groups",
|
"LabelSyncPlayAccessCreateAndJoinGroups": "Allow user to create and join groups",
|
||||||
|
@ -1190,6 +1194,8 @@
|
||||||
"Mute": "Mute",
|
"Mute": "Mute",
|
||||||
"MySubtitles": "My Subtitles",
|
"MySubtitles": "My Subtitles",
|
||||||
"Name": "Name",
|
"Name": "Name",
|
||||||
|
"Native": "Native",
|
||||||
|
"NativeSubtitleStylingHelp": "Subtitle styling will not work on some devices. However, it does not come with any performance overhead.",
|
||||||
"Never": "Never",
|
"Never": "Never",
|
||||||
"New": "New",
|
"New": "New",
|
||||||
"NewCollection": "New Collection",
|
"NewCollection": "New Collection",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue