From 9e8c7d788a79414c44f9761308c93f453c3b595b Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Mon, 25 Sep 2023 23:37:45 +0300 Subject: [PATCH 1/3] Fix slider rounding --- src/elements/emby-slider/emby-slider.js | 13 ++++++++++++- src/utils/number.ts | 13 +++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/elements/emby-slider/emby-slider.js b/src/elements/emby-slider/emby-slider.js index 5e44fb03c6..d08b87993f 100644 --- a/src/elements/emby-slider/emby-slider.js +++ b/src/elements/emby-slider/emby-slider.js @@ -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); @@ -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); } diff --git a/src/utils/number.ts b/src/utils/number.ts index 16797d7d51..553280c1fe 100644 --- a/src/utils/number.ts +++ b/src/utils/number.ts @@ -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; +} From 111958e2a5da5fdf2bcc500819de05ccc793ecc3 Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Thu, 24 Aug 2023 00:48:47 +0300 Subject: [PATCH 2/3] Pass slider value to bubble text generators --- src/elements/emby-slider/emby-slider.js | 26 ++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/elements/emby-slider/emby-slider.js b/src/elements/emby-slider/emby-slider.js index d08b87993f..cf804849d1 100644 --- a/src/elements/emby-slider/emby-slider.js +++ b/src/elements/emby-slider/emby-slider.js @@ -146,12 +146,12 @@ 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; } @@ -159,18 +159,20 @@ function updateBubble(range, value, bubble) { 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 = '

' + value + '

'; + html = '

' + html + '

'; } - bubble.innerHTML = value; + bubble.innerHTML = html; }); } @@ -306,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'); @@ -333,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'); From 6063ba6db57acb02bb6f88fd644681b6508e10cf Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Tue, 26 Sep 2023 00:04:31 +0300 Subject: [PATCH 3/3] Use slider to round and limit offset --- src/components/subtitlesync/subtitlesync.js | 51 +++++-------------- .../subtitlesync/subtitlesync.template.html | 2 +- 2 files changed, 15 insertions(+), 38 deletions(-) diff --git a/src/components/subtitlesync/subtitlesync.js b/src/components/subtitlesync/subtitlesync.js index ba8984486b..57ae63cb8c 100644 --- a/src/components/subtitlesync/subtitlesync.js +++ b/src/components/subtitlesync/subtitlesync.js @@ -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'; } @@ -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 '

' - + (newOffset > 0 ? '+' : '') + parseFloat(newOffset) + 's' + + (value > 0 ? '+' : '') + parseFloat(value) + 's' + '

'; }; @@ -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; diff --git a/src/components/subtitlesync/subtitlesync.template.html b/src/components/subtitlesync/subtitlesync.template.html index a055d24fcb..eb36d58260 100644 --- a/src/components/subtitlesync/subtitlesync.template.html +++ b/src/components/subtitlesync/subtitlesync.template.html @@ -3,7 +3,7 @@
0s
- +