feat: draggable progress bar (seek) and settings sliders
This commit is contained in:
@@ -212,6 +212,8 @@ function renderMediaCard(info) {
|
||||
// Cover tap opens the media app's playback UI
|
||||
const coverEl = el.querySelector('.cover');
|
||||
if (coverEl) coverEl.onclick = () => bridge.call('openMediaApp', currentMediaIndex);
|
||||
// 进度条拖动 seek
|
||||
setupMediaSeek(el);
|
||||
// 进度状态 + 全局 ticker
|
||||
updateMediaProgressState(info);
|
||||
startMediaTicker();
|
||||
@@ -268,6 +270,43 @@ function fmtDuration(ms) {
|
||||
return m + ':' + String(s % 60).padStart(2, '0');
|
||||
}
|
||||
|
||||
// 进度条拖动 seek:拖动预览进度,松手后 seek 到目标位置
|
||||
// Progress-bar drag seek: preview while dragging, seek on release
|
||||
function setupMediaSeek(el) {
|
||||
const prog = el.querySelector('.prog');
|
||||
if (!prog) return;
|
||||
let dragging = false;
|
||||
const ratioAt = (clientX) => {
|
||||
const rect = prog.getBoundingClientRect();
|
||||
return Math.min(1, Math.max(0, (clientX - rect.left) / rect.width));
|
||||
};
|
||||
const preview = (clientX) => {
|
||||
const bar = el.querySelector('.bar');
|
||||
if (bar) bar.style.width = (ratioAt(clientX) * 100) + '%';
|
||||
};
|
||||
prog.addEventListener('touchstart', (e) => {
|
||||
dragging = true;
|
||||
preview(e.touches[0].clientX);
|
||||
}, { passive: true });
|
||||
prog.addEventListener('touchmove', (e) => {
|
||||
if (dragging) preview(e.touches[0].clientX);
|
||||
}, { passive: true });
|
||||
prog.addEventListener('touchend', (e) => {
|
||||
if (!dragging) return;
|
||||
dragging = false;
|
||||
const ratio = ratioAt(e.changedTouches[0].clientX);
|
||||
const duration = mediaProgressState ? mediaProgressState.duration : 0;
|
||||
if (duration > 0) {
|
||||
const pos = Math.floor(ratio * duration);
|
||||
bridge.call('mediaSeekTo', currentMediaIndex, pos);
|
||||
if (mediaProgressState) {
|
||||
mediaProgressState.position = pos;
|
||||
mediaProgressState.updatedAt = Date.now();
|
||||
}
|
||||
}
|
||||
}, { passive: true });
|
||||
}
|
||||
|
||||
// 布局方向:默认上下(封面在上、信息在下),横条(宽>高)时左右
|
||||
// Layout direction: vertical (cover on top, info below) by default; horizontal
|
||||
// (cover left, info right) when the card is wider than tall
|
||||
|
||||
@@ -116,12 +116,10 @@ function setupMask(page) {
|
||||
window.mask.setEnabled(!window.mask.enabled());
|
||||
refresh();
|
||||
};
|
||||
slider.onclick = (e) => {
|
||||
const rect = slider.getBoundingClientRect();
|
||||
const a = Math.min(1, Math.max(0, (e.clientX - rect.left) / rect.width));
|
||||
makeSliderDraggable(slider, (a) => {
|
||||
window.mask.setAlpha(Math.round(a * 100) / 100);
|
||||
refresh();
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// 通知使用权授权项:异步查状态,未授权点击跳转系统授权页
|
||||
@@ -155,12 +153,10 @@ function setupBrightness(page) {
|
||||
const pct = value / 255 * 100;
|
||||
sliderEl.style.setProperty('--fill', pct + '%');
|
||||
sliderEl.querySelector('i').style.left = pct + '%';
|
||||
sliderEl.onclick = (e) => {
|
||||
e.stopPropagation();
|
||||
const rect = sliderEl.getBoundingClientRect();
|
||||
const v = Math.round(Math.min(255, Math.max(0, (e.clientX - rect.left) / rect.width)) * 255);
|
||||
makeSliderDraggable(sliderEl, (ratio) => {
|
||||
const v = Math.round(ratio * 255);
|
||||
bridge.call('setSystemBrightness', v).then(() => renderSlider(v)).catch(() => {});
|
||||
};
|
||||
});
|
||||
item.appendChild(sliderEl);
|
||||
};
|
||||
|
||||
@@ -237,3 +233,22 @@ function setupCheckUpdate(page) {
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// 通用滑块拖动:touch 拖动实时回调(保留 click 兼容桌面调试)
|
||||
// Generic draggable slider: touch-drag with live callback (click kept for desktop)
|
||||
function makeSliderDraggable(slider, onRatio) {
|
||||
let dragging = false;
|
||||
const ratioAt = (clientX) => {
|
||||
const rect = slider.getBoundingClientRect();
|
||||
return Math.min(1, Math.max(0, (clientX - rect.left) / rect.width));
|
||||
};
|
||||
slider.addEventListener('touchstart', (e) => {
|
||||
dragging = true;
|
||||
onRatio(ratioAt(e.touches[0].clientX));
|
||||
}, { passive: true });
|
||||
slider.addEventListener('touchmove', (e) => {
|
||||
if (dragging) onRatio(ratioAt(e.touches[0].clientX));
|
||||
}, { passive: true });
|
||||
slider.addEventListener('touchend', () => { dragging = false; }, { passive: true });
|
||||
slider.addEventListener('click', (e) => onRatio(ratioAt(e.clientX)));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user