This commit is contained in:
2026-05-25 09:03:58 +02:00
parent 3a436304bd
commit 92cc474ca3
3 changed files with 83 additions and 15 deletions

View File

@@ -12919,6 +12919,12 @@ body.layout-modern .xd-score-wrapper {
min-width: 120px; min-width: 120px;
} }
/* Custom mobile-friendly slider that replaces the native range input */
.nav-xd-custom-slider {
flex: 1;
min-width: 120px;
}
.xd-slider::-webkit-slider-thumb { .xd-slider::-webkit-slider-thumb {
-webkit-appearance: none; -webkit-appearance: none;
appearance: none; appearance: none;

View File

@@ -4712,11 +4712,13 @@ window.cancelAnimFrame = (function () {
}); });
// ── xD Score filter ──────────────────────────────────────────────────── // ── xD Score filter ────────────────────────────────────────────────────
const navXdInput = document.getElementById('nav_min_xd_score'); const navXdInput = document.getElementById('nav_min_xd_score');
const navXdSaveBtn = document.getElementById('nav_xd_save_btn'); const navXdSaveBtn = document.getElementById('nav_xd_save_btn');
const navXdTier = document.getElementById('nav_xd_tier_label'); const navXdTier = document.getElementById('nav_xd_tier_label');
const navXdStatus = document.getElementById('nav_xd_status'); const navXdStatus = document.getElementById('nav_xd_status');
const navXdVal = document.getElementById('nav_xd_val'); const navXdVal = document.getElementById('nav_xd_val');
const navXdSliderContainer = document.getElementById('nav_xd_slider_container');
let navXdCustomFill = null; // set during custom slider init below
const XD_TIERS_NAV = [null, const XD_TIERS_NAV = [null,
{ cls: 'xd-tier-1', label: 'xD' }, { cls: 'xd-tier-1', label: 'xD' },
@@ -4739,14 +4741,12 @@ window.cancelAnimFrame = (function () {
score = +score; score = +score;
if (navXdVal) navXdVal.textContent = score; if (navXdVal) navXdVal.textContent = score;
const tier = getNavXdTier(score); const tier = getNavXdTier(score);
// Update slider track fill const color = XD_TIER_COLORS[tier];
if (navXdInput) { // Update custom slider fill colour
const pct = Math.round((score / +navXdInput.max) * 100); if (navXdCustomFill) navXdCustomFill.style.background = color;
const color = XD_TIER_COLORS[tier]; if (navXdVal) navXdVal.style.color = color;
navXdInput.style.setProperty('--xd-fill', color); // Keep hidden native input in sync (save button reads it)
navXdInput.style.setProperty('--xd-pct', pct + '%'); if (navXdInput) navXdInput.value = score;
if (navXdVal) navXdVal.style.color = color;
}
if (!navXdTier) return; if (!navXdTier) return;
if (!tier || score <= 0) { navXdTier.style.display = 'none'; return; } if (!tier || score <= 0) { navXdTier.style.display = 'none'; return; }
const t = XD_TIERS_NAV[tier]; const t = XD_TIERS_NAV[tier];
@@ -4757,7 +4757,68 @@ window.cancelAnimFrame = (function () {
if (navXdInput) { if (navXdInput) {
updateNavXdUI(+navXdInput.value); updateNavXdUI(+navXdInput.value);
navXdInput.addEventListener('input', () => updateNavXdUI(+navXdInput.value)); }
// Custom mobile-friendly slider for xD score
if (navXdInput && navXdSliderContainer) {
const xdMin = 0, xdMax = +navXdInput.max || 100;
const xdContainer = navXdSliderContainer;
xdContainer.style.cssText = 'position:relative;height:28px;flex:1;cursor:pointer;user-select:none;-webkit-user-select:none;touch-action:none;';
const xdTrack = document.createElement('div');
xdTrack.style.cssText = 'position:absolute;left:8px;right:8px;height:4px;background:#333;border-radius:2px;top:50%;transform:translateY(-50%);';
const xdFill = document.createElement('div');
xdFill.style.cssText = 'position:absolute;left:0;height:100%;background:#888;border-radius:2px;pointer-events:none;';
navXdCustomFill = xdFill;
const xdThumb = document.createElement('div');
xdThumb.style.cssText = 'position:absolute;width:18px;height:18px;background:#888;border-radius:50%;top:50%;transform:translate(-50%,-50%);box-shadow:0 0 6px rgba(0,0,0,.6);pointer-events:none;transition:transform .1s;';
const xdSetRatio = (r) => {
xdFill.style.width = (r * 100) + '%';
xdThumb.style.left = `calc(8px + ${r} * (100% - 16px))`;
};
xdSetRatio((+navXdInput.value - xdMin) / (xdMax - xdMin));
xdTrack.appendChild(xdFill);
xdContainer.appendChild(xdTrack);
xdContainer.appendChild(xdThumb);
const xdValueFromClientX = (clientX) => {
const rect = xdTrack.getBoundingClientRect();
const r = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));
xdSetRatio(r);
return Math.round(xdMin + r * (xdMax - xdMin));
};
xdContainer.addEventListener('pointerdown', (e) => {
e.preventDefault();
xdContainer.setPointerCapture(e.pointerId);
xdThumb.style.transform = 'translate(-50%,-50%) scale(1.25)';
updateNavXdUI(xdValueFromClientX(e.clientX));
// also tint thumb with current tier colour
xdThumb.style.background = XD_TIER_COLORS[getNavXdTier(+navXdInput.value)];
}, { passive: false });
xdContainer.addEventListener('pointermove', (e) => {
if (!xdContainer.hasPointerCapture(e.pointerId)) return;
const val = xdValueFromClientX(e.clientX);
xdThumb.style.background = XD_TIER_COLORS[getNavXdTier(val)];
updateNavXdUI(val);
});
const xdOnEnd = (e) => {
if (!xdContainer.hasPointerCapture(e.pointerId)) return;
xdContainer.releasePointerCapture(e.pointerId);
xdThumb.style.transform = 'translate(-50%,-50%) scale(1)';
};
xdContainer.addEventListener('pointerup', xdOnEnd);
xdContainer.addEventListener('pointercancel', xdOnEnd);
// Sync thumb colour on init
updateNavXdUI(+navXdInput.value);
xdThumb.style.background = XD_TIER_COLORS[getNavXdTier(+navXdInput.value)];
} }
if (navXdSaveBtn && navXdInput) { if (navXdSaveBtn && navXdInput) {

View File

@@ -35,7 +35,8 @@
<div class="nav-xd-filter"> <div class="nav-xd-filter">
<label class="nav-xd-label">{{ t('filter.min_xd_score') }}</label> <label class="nav-xd-label">{{ t('filter.min_xd_score') }}</label>
<div class="nav-xd-controls"> <div class="nav-xd-controls">
<input type="range" id="nav_min_xd_score" min="0" max="100" step="1" value="{{ session.min_xd_score || 0 }}" class="xd-slider"> <input type="range" id="nav_min_xd_score" min="0" max="100" step="1" value="{{ session.min_xd_score || 0 }}" class="xd-slider" style="display:none;" aria-hidden="true">
<div id="nav_xd_slider_container" class="nav-xd-custom-slider"></div>
<span id="nav_xd_val" class="xd-slider-val">{{ session.min_xd_score || 0 }}</span> <span id="nav_xd_val" class="xd-slider-val">{{ session.min_xd_score || 0 }}</span>
<span id="nav_xd_tier_label" class="xd-score-badge" style="display:none; font-size: 0.75em;"></span> <span id="nav_xd_tier_label" class="xd-score-badge" style="display:none; font-size: 0.75em;"></span>
</div> </div>