From 9e92bfaae78b3bd1f1dfdc9ba02ced18729bef95 Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Sun, 14 Jun 2020 23:37:48 +0300 Subject: [PATCH 01/32] Fix subtitle line spacing --- .../subtitleappearancehelper.js | 71 ++++++------------- src/plugins/htmlVideoPlayer/plugin.js | 2 +- src/plugins/htmlVideoPlayer/style.css | 6 ++ 3 files changed, 30 insertions(+), 49 deletions(-) diff --git a/src/components/subtitlesettings/subtitleappearancehelper.js b/src/components/subtitlesettings/subtitleappearancehelper.js index bec8156aca..503c81472f 100644 --- a/src/components/subtitlesettings/subtitleappearancehelper.js +++ b/src/components/subtitlesettings/subtitleappearancehelper.js @@ -1,55 +1,30 @@ define([], function () { 'use strict'; - function getTextStyles(settings, isCue) { + function getTextStyles(settings) { var list = []; - if (isCue) { - switch (settings.textSize || '') { - - case 'smaller': - list.push({ name: 'font-size', value: '.5em' }); - break; - case 'small': - list.push({ name: 'font-size', value: '.7em' }); - break; - case 'large': - list.push({ name: 'font-size', value: '1.3em' }); - break; - case 'larger': - list.push({ name: 'font-size', value: '1.72em' }); - break; - case 'extralarge': - list.push({ name: 'font-size', value: '2em' }); - break; - default: - case 'medium': - break; - } - } else { - switch (settings.textSize || '') { - - case 'smaller': - list.push({ name: 'font-size', value: '.8em' }); - break; - case 'small': - list.push({ name: 'font-size', value: 'inherit' }); - break; - case 'larger': - list.push({ name: 'font-size', value: '2em' }); - break; - case 'extralarge': - list.push({ name: 'font-size', value: '2.2em' }); - break; - case 'large': - list.push({ name: 'font-size', value: '1.72em' }); - break; - default: - case 'medium': - list.push({ name: 'font-size', value: '1.36em' }); - break; - } + switch (settings.textSize || '') { + case 'smaller': + list.push({ name: 'font-size', value: '.8em' }); + break; + case 'small': + list.push({ name: 'font-size', value: 'inherit' }); + break; + case 'larger': + list.push({ name: 'font-size', value: '2em' }); + break; + case 'extralarge': + list.push({ name: 'font-size', value: '2.2em' }); + break; + case 'large': + list.push({ name: 'font-size', value: '1.72em' }); + break; + default: + case 'medium': + list.push({ name: 'font-size', value: '1.36em' }); + break; } switch (settings.dropShadow || '') { @@ -122,10 +97,10 @@ define([], function () { return []; } - function getStyles(settings, isCue) { + function getStyles(settings) { return { - text: getTextStyles(settings, isCue), + text: getTextStyles(settings), window: getWindowStyles(settings) }; } diff --git a/src/plugins/htmlVideoPlayer/plugin.js b/src/plugins/htmlVideoPlayer/plugin.js index cc312bb956..9302612539 100644 --- a/src/plugins/htmlVideoPlayer/plugin.js +++ b/src/plugins/htmlVideoPlayer/plugin.js @@ -1178,7 +1178,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa document.getElementsByTagName('head')[0].appendChild(styleElem); } - styleElem.innerHTML = getCueCss(subtitleAppearanceHelper.getStyles(userSettings.getSubtitleAppearanceSettings(), true), '.htmlvideoplayer'); + styleElem.innerHTML = getCueCss(subtitleAppearanceHelper.getStyles(userSettings.getSubtitleAppearanceSettings()), '.htmlvideoplayer'); }); } diff --git a/src/plugins/htmlVideoPlayer/style.css b/src/plugins/htmlVideoPlayer/style.css index b83a7816f5..0f63e72d7e 100644 --- a/src/plugins/htmlVideoPlayer/style.css +++ b/src/plugins/htmlVideoPlayer/style.css @@ -33,6 +33,12 @@ video::-webkit-media-controls { text-shadow: 0.14em 0.14em 0.14em rgba(0, 0, 0, 1); -webkit-font-smoothing: antialiased; font-family: inherit; + line-height: normal; /* Restore value. See -webkit-media-text-track-container 'line-height' */ +} + +.htmlvideoplayer::-webkit-media-text-track-container { + font-size: 170% !important; /* Override element inline style */ + line-height: 50%; /* Child element cannot set line height smaller than its parent has. This allow smaller values for children */ } .htmlvideoplayer-moveupsubtitles::-webkit-media-text-track-display { From 597b4258d9eba3a663082632149511d4500264ce Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Tue, 7 Jul 2020 01:06:47 +0300 Subject: [PATCH 02/32] Add subtitle position --- .../subtitleappearancehelper.js | 39 ++++++++-- .../subtitlesettings/subtitlesettings.js | 71 ++++++++++++++++++- .../subtitlesettings.template.html | 53 ++++++++++++++ src/elements/emby-slider/emby-slider.css | 15 ++++ src/elements/emby-slider/emby-slider.js | 10 +++ src/plugins/htmlVideoPlayer/plugin.js | 39 +++++----- src/plugins/htmlVideoPlayer/style.css | 9 ++- src/scripts/settings/userSettings.js | 6 +- src/strings/en-us.json | 5 +- src/strings/ru.json | 5 +- 10 files changed, 219 insertions(+), 33 deletions(-) diff --git a/src/components/subtitlesettings/subtitleappearancehelper.js b/src/components/subtitlesettings/subtitleappearancehelper.js index 503c81472f..e611228d9a 100644 --- a/src/components/subtitlesettings/subtitleappearancehelper.js +++ b/src/components/subtitlesettings/subtitleappearancehelper.js @@ -1,7 +1,7 @@ define([], function () { 'use strict'; - function getTextStyles(settings) { + function getTextStyles(settings, preview) { var list = []; @@ -89,19 +89,44 @@ define([], function () { break; } + if (!preview) { + const pos = parseInt(settings.verticalPosition); + const lineHeight = 1.35; // FIXME: It is better to read this value from element + const line = Math.abs(pos * lineHeight); + if (pos < 0) { + list.push({ name: 'min-height', value: `${line}em` }); + list.push({ name: 'margin-top', value: '' }); + } else { + list.push({ name: 'min-height', value: '' }); + list.push({ name: 'margin-top', value: `${line}em` }); + } + } + return list; } - function getWindowStyles(settings) { + function getWindowStyles(settings, preview) { + const list = []; - return []; + if (!preview) { + const pos = parseInt(settings.verticalPosition); + if (pos < 0) { + list.push({ name: 'top', value: '' }); + list.push({ name: 'bottom', value: '0' }); + } else { + list.push({ name: 'top', value: '0' }); + list.push({ name: 'bottom', value: '' }); + } + } + + return list; } - function getStyles(settings) { + function getStyles(settings, preview) { return { - text: getTextStyles(settings), - window: getWindowStyles(settings) + text: getTextStyles(settings, preview), + window: getWindowStyles(settings, preview) }; } @@ -117,7 +142,7 @@ define([], function () { function applyStyles(elements, appearanceSettings) { - var styles = getStyles(appearanceSettings); + var styles = getStyles(appearanceSettings, !!elements.preview); if (elements.text) { applyStyleList(styles.text, elements.text); diff --git a/src/components/subtitlesettings/subtitlesettings.js b/src/components/subtitlesettings/subtitlesettings.js index d728360d05..819631184c 100644 --- a/src/components/subtitlesettings/subtitlesettings.js +++ b/src/components/subtitlesettings/subtitlesettings.js @@ -1,4 +1,4 @@ -define(['require', 'globalize', 'appSettings', 'apphost', 'focusManager', 'loading', 'connectionManager', 'subtitleAppearanceHelper', 'dom', 'events', 'listViewStyle', 'emby-select', 'emby-input', 'emby-checkbox', 'flexStyles'], function (require, globalize, appSettings, appHost, focusManager, loading, connectionManager, subtitleAppearanceHelper, dom, events) { +define(['require', 'globalize', 'appSettings', 'apphost', 'focusManager', 'loading', 'connectionManager', 'subtitleAppearanceHelper', 'dom', 'events', 'layoutManager', 'listViewStyle', 'emby-select', 'emby-input', 'emby-checkbox', 'emby-slider', 'flexStyles'], function (require, globalize, appSettings, appHost, focusManager, loading, connectionManager, subtitleAppearanceHelper, dom, events, layoutManager) { 'use strict'; function populateLanguages(select, languages) { @@ -21,6 +21,7 @@ define(['require', 'globalize', 'appSettings', 'apphost', 'focusManager', 'loadi appearanceSettings.font = context.querySelector('#selectFont').value; appearanceSettings.textBackground = context.querySelector('#inputTextBackground').value; appearanceSettings.textColor = context.querySelector('#inputTextColor').value; + appearanceSettings.verticalPosition = context.querySelector('#sliderVerticalPosition').value; return appearanceSettings; } @@ -47,6 +48,7 @@ define(['require', 'globalize', 'appSettings', 'apphost', 'focusManager', 'loadi context.querySelector('#inputTextBackground').value = appearanceSettings.textBackground || 'transparent'; context.querySelector('#inputTextColor').value = appearanceSettings.textColor || '#ffffff'; context.querySelector('#selectFont').value = appearanceSettings.font || ''; + context.querySelector('#sliderVerticalPosition').value = appearanceSettings.verticalPosition; context.querySelector('#selectSubtitleBurnIn').value = appSettings.get('subtitleburnin') || ''; @@ -134,10 +136,45 @@ define(['require', 'globalize', 'appSettings', 'apphost', 'focusManager', 'loadi var elements = { window: view.querySelector('.subtitleappearance-preview-window'), - text: view.querySelector('.subtitleappearance-preview-text') + text: view.querySelector('.subtitleappearance-preview-text'), + preview: true }; subtitleAppearanceHelper.applyStyles(elements, appearanceSettings); + + subtitleAppearanceHelper.applyStyles({ + window: view.querySelector('.subtitleappearance-fullpreview-window'), + text: view.querySelector('.subtitleappearance-fullpreview-text') + }, appearanceSettings); + } + + const subtitlePreviewDelay = 1000; + let subtitlePreviewTimer; + + function showSubtitlePreview(persistent) { + clearTimeout(subtitlePreviewTimer); + + this._fullPreview.classList.remove('subtitleappearance-fullpreview-hide'); + + if (persistent) { + this._refFullPreview++; + } + + if (this._refFullPreview === 0) { + subtitlePreviewTimer = setTimeout(hideSubtitlePreview.bind(this), subtitlePreviewDelay); + } + } + + function hideSubtitlePreview(persistent) { + clearTimeout(subtitlePreviewTimer); + + if (persistent) { + this._refFullPreview--; + } + + if (this._refFullPreview === 0) { + this._fullPreview.classList.add('subtitleappearance-fullpreview-hide'); + } } function embed(options, self) { @@ -162,6 +199,36 @@ define(['require', 'globalize', 'appSettings', 'apphost', 'focusManager', 'loadi if (appHost.supports('subtitleappearancesettings')) { options.element.querySelector('.subtitleAppearanceSection').classList.remove('hide'); + + self._fullPreview = options.element.querySelector('.subtitleappearance-fullpreview'); + self._refFullPreview = 0; + + const sliderVerticalPosition = options.element.querySelector('#sliderVerticalPosition'); + sliderVerticalPosition.addEventListener('input', onAppearanceFieldChange); + sliderVerticalPosition.addEventListener('input', () => showSubtitlePreview.call(self)); + + const eventPrefix = window.PointerEvent ? 'pointer' : 'mouse'; + sliderVerticalPosition.addEventListener(`${eventPrefix}enter`, () => showSubtitlePreview.call(self, true)); + sliderVerticalPosition.addEventListener(`${eventPrefix}leave`, () => hideSubtitlePreview.call(self, true)); + + if (layoutManager.tv) { + sliderVerticalPosition.addEventListener('focus', () => showSubtitlePreview.call(self, true)); + sliderVerticalPosition.addEventListener('blur', () => hideSubtitlePreview.call(self, true)); + + // Give CustomElements time to attach + setTimeout(() => { + sliderVerticalPosition.classList.add('focusable'); + sliderVerticalPosition.enableKeyboardDragging(); + }, 0); + } + + options.element.querySelector('.chkPreview').addEventListener('change', (e) => { + if (e.target.checked) { + showSubtitlePreview.call(self, true); + } else { + hideSubtitlePreview.call(self, true); + } + }); } self.loadData(); diff --git a/src/components/subtitlesettings/subtitlesettings.template.html b/src/components/subtitlesettings/subtitlesettings.template.html index 716296a257..2f49fa4c3e 100644 --- a/src/components/subtitlesettings/subtitlesettings.template.html +++ b/src/components/subtitlesettings/subtitlesettings.template.html @@ -38,6 +38,45 @@ ${HeaderSubtitleAppearance} + + +
+
+
+ ${HeaderSubtitleAppearance} +
+ ${TheseSettingsAffectSubtitlesOnThisDevice} +
+
+
+
@@ -89,6 +128,20 @@
+ +
+
+ +
+
${SubtitleVerticalPositionHelp}
+
+ +
+ +