mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Add subtitle position
This commit is contained in:
parent
9e92bfaae7
commit
597b4258d9
10 changed files with 219 additions and 33 deletions
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -38,6 +38,45 @@
|
|||
${HeaderSubtitleAppearance}
|
||||
</h2>
|
||||
|
||||
<style>
|
||||
.subtitleappearance-fullpreview {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1000;
|
||||
pointer-events: none;
|
||||
transition: 0.2s
|
||||
}
|
||||
|
||||
.subtitleappearance-fullpreview-hide {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.subtitleappearance-fullpreview-window {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
font-size: 170%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.subtitleappearance-fullpreview-text {
|
||||
display: inline-block;
|
||||
max-width: 70%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="subtitleappearance-fullpreview subtitleappearance-fullpreview-hide">
|
||||
<div class="subtitleappearance-fullpreview-window">
|
||||
<div class="subtitleappearance-fullpreview-text">
|
||||
${HeaderSubtitleAppearance}
|
||||
<br>
|
||||
${TheseSettingsAffectSubtitlesOnThisDevice}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin: 2em 0 2em;">
|
||||
<div class="subtitleappearance-preview flex align-items-center justify-content-center" style="margin:2em 0;padding:1.6em;color:black;background:linear-gradient(140deg,#aa5cc3,#00a4dc);">
|
||||
<div class="subtitleappearance-preview-window flex align-items-center justify-content-center" style="width: 90%; padding: .25em;">
|
||||
|
@ -89,6 +128,20 @@
|
|||
<option value="">${DropShadow}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="sliderContainer-settings">
|
||||
<div class="sliderContainer">
|
||||
<input is="emby-slider" id="sliderVerticalPosition" label="${LabelSubtitleVerticalPosition}" type="range" min="-16" max="16" />
|
||||
</div>
|
||||
<div class="fieldDescription">${SubtitleVerticalPositionHelp}</div>
|
||||
</div>
|
||||
|
||||
<div class="checkboxContainer">
|
||||
<label>
|
||||
<input is="emby-checkbox" type="checkbox" class="chkPreview" />
|
||||
<span>${Preview}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button is="emby-button" type="submit" class="raised button-submit block btnSave hide">
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue