Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify subtitle sync #4760

Merged
merged 3 commits into from
Sep 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 15 additions & 38 deletions src/components/subtitlesync/subtitlesync.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,8 @@ function init(instance) {
if (inputOffset) {
inputOffset = inputOffset[0];
inputOffset = parseFloat(inputOffset);
inputOffset = Math.min(30, Math.max(-30, inputOffset));

// replace current text by considered offset
this.textContent = inputOffset + 's';
// set new offset
playbackManager.setSubtitleOffset(inputOffset, player);
// synchronize with slider value
subtitleSyncSlider.updateOffset(
getSliderValueFromOffset(inputOffset));

subtitleSyncSlider.updateOffset(inputOffset);
} else {
this.textContent = (playbackManager.getPlayerSubtitleOffset(player) || 0) + 's';
}
Expand All @@ -79,23 +72,26 @@ function init(instance) {
}
};

function updateSubtitleOffset() {
const value = parseFloat(subtitleSyncSlider.value);
// set new offset
playbackManager.setSubtitleOffset(value, player);
// synchronize with textField value
subtitleSyncTextField.updateOffset(value);
}

subtitleSyncSlider.updateOffset = function (sliderValue) {
// default value is 0s = 0ms
this.value = sliderValue === undefined ? 0 : sliderValue;

updateSubtitleOffset();
};

subtitleSyncSlider.addEventListener('change', function () {
// set new offset
playbackManager.setSubtitleOffset(getOffsetFromSliderValue(this.value), player);
// synchronize with textField value
subtitleSyncTextField.updateOffset(
getOffsetFromSliderValue(this.value));
});
subtitleSyncSlider.addEventListener('change', () => updateSubtitleOffset());

subtitleSyncSlider.getBubbleHtml = function (value) {
const newOffset = getOffsetFromPercentage(value);
subtitleSyncSlider.getBubbleHtml = function (_, value) {
return '<h1 class="sliderBubbleText">'
+ (newOffset > 0 ? '+' : '') + parseFloat(newOffset) + 's'
+ (value > 0 ? '+' : '') + parseFloat(value) + 's'
+ '</h1>';
};

Expand All @@ -107,25 +103,6 @@ function init(instance) {
instance.element = parent;
}

function getOffsetFromPercentage(value) {
// convert percentage to fraction
let offset = (value - 50) / 50;
// multiply by offset min/max range value (-x to +x) :
offset *= 30;
return offset.toFixed(1);
}

function getOffsetFromSliderValue(value) {
// convert slider value to offset
const offset = value / 10;
return offset.toFixed(1);
}

function getSliderValueFromOffset(value) {
const sliderValue = value * 10;
return Math.min(300, Math.max(-300, sliderValue.toFixed(1)));
}

class SubtitleSync {
constructor(currentPlayer) {
player = currentPlayer;
Expand Down
2 changes: 1 addition & 1 deletion src/components/subtitlesync/subtitlesync.template.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<button type="button" is="paper-icon-button-light" class="subtitleSync-closeButton"><span class="material-icons close" aria-hidden="true"></span></button>
<div class="subtitleSyncTextField" contenteditable="true" spellcheck="false">0s</div>
<div class="sliderContainer subtitleSyncSliderContainer">
<input is="emby-slider" type="range" step="1" min="-300" max="300" value="0" class="subtitleSyncSlider" data-slider-keep-progress="true" />
<input is="emby-slider" type="range" step="0.1" min="-30" max="30" value="0" class="subtitleSyncSlider" data-slider-keep-progress="true" />
</div>
</div>
</div>
39 changes: 27 additions & 12 deletions src/elements/emby-slider/emby-slider.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import './emby-slider.scss';
import 'webcomponents.js/webcomponents-lite';
import '../emby-input/emby-input';
import globalize from '../../scripts/globalize';
import { decimalCount } from '../../utils/number';

const EmbySliderPrototype = Object.create(HTMLInputElement.prototype);

Expand Down Expand Up @@ -75,13 +76,23 @@ function mapClientToFraction(range, clientX) {
function mapFractionToValue(range, fraction) {
let value = (range.max - range.min) * fraction;

let decimals = null;

// Snap to step
if (range.step !== 'any') {
const step = normalizeSliderStep(range);
decimals = decimalCount(step);
value = Math.round(value / step) * step;
}

value += parseFloat(range.min);
const min = parseFloat(range.min);

value += min;

if (decimals != null) {
decimals = Math.max(decimals, decimalCount(min));
value = parseFloat(value.toFixed(decimals));
}

return Math.min(Math.max(value, range.min), range.max);
}
Expand Down Expand Up @@ -135,31 +146,33 @@ function updateValues(isValueSet) {
});
}

function updateBubble(range, value, bubble) {
function updateBubble(range, percent, value, bubble) {
requestAnimationFrame(function () {
const bubbleTrackRect = range.sliderBubbleTrack.getBoundingClientRect();
const bubbleRect = bubble.getBoundingClientRect();

let bubblePos = bubbleTrackRect.width * value / 100;
let bubblePos = bubbleTrackRect.width * percent / 100;
if (globalize.getIsElementRTL(range)) {
bubblePos = bubbleTrackRect.width - bubblePos;
}
bubblePos = Math.min(Math.max(bubblePos, bubbleRect.width / 2), bubbleTrackRect.width - bubbleRect.width / 2);

bubble.style.left = bubblePos + 'px';

let html;

if (range.getBubbleHtml) {
value = range.getBubbleHtml(value);
html = range.getBubbleHtml(percent, value);
} else {
if (range.getBubbleText) {
value = range.getBubbleText(value);
html = range.getBubbleText(percent, value);
} else {
value = mapFractionToValue(range, value / 100).toLocaleString();
html = value.toLocaleString();
}
value = '<h1 class="sliderBubbleText">' + value + '</h1>';
html = '<h1 class="sliderBubbleText">' + html + '</h1>';
}

bubble.innerHTML = value;
bubble.innerHTML = html;
});
}

Expand Down Expand Up @@ -295,8 +308,8 @@ EmbySliderPrototype.attachedCallback = function () {
updateValues.call(this);
}

const bubbleValue = mapValueToFraction(this, this.value) * 100;
updateBubble(this, bubbleValue, sliderBubble);
const percent = mapValueToFraction(this, this.value) * 100;
updateBubble(this, percent, parseFloat(this.value), sliderBubble);

if (hasHideBubbleClass) {
sliderBubble.classList.remove('hide');
Expand All @@ -322,9 +335,11 @@ EmbySliderPrototype.attachedCallback = function () {
/* eslint-disable-next-line compat/compat */
dom.addEventListener(this, (window.PointerEvent ? 'pointermove' : 'mousemove'), function (e) {
if (!this.dragging) {
const bubbleValue = mapClientToFraction(this, e.clientX) * 100;
const fraction = mapClientToFraction(this, e.clientX);
const percent = fraction * 100;
const value = mapFractionToValue(this, fraction);

updateBubble(this, bubbleValue, sliderBubble);
updateBubble(this, percent, value, sliderBubble);

if (hasHideBubbleClass) {
sliderBubble.classList.remove('hide');
Expand Down
13 changes: 13 additions & 0 deletions src/utils/number.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,16 @@ export function toPercent(value: number | null | undefined, locale: string): str

return `${Math.round(value * 100)}%`;
}

/**
* Gets decimal count of a Number.
* @param {number} value Number.
* @returns {number} Decimal count of a Number.
*/
export function decimalCount(value: number): number {
if (Number.isInteger(value)) return 0;

const arr = value.toString().split('.');

return arr[1].length;
}
Loading