mirror of
https://github.com/narrrl/pl8list-rewind.git
synced 2026-11-03 16:41:26 +01:00
Remove the wheel-up rewind
Holding the drop and the w key no longer spin it back and restart the tune; the help and the first-start hint no longer mention it.
This commit is contained in:
1 parent
aa0e28d326
commit
92ac36bc67
4 files changed
+2
-70
No files matched your search
@@ -241,7 +241,6 @@
|
|||||||
<dt>double-tap</dt><dd>like</dd>
|
<dt>double-tap</dt><dd>like</dd>
|
||||||
<dt>swipe up / down</dt><dd>next / previous</dd>
|
<dt>swipe up / down</dt><dd>next / previous</dd>
|
||||||
<dt>drag waveform</dt><dd>seek</dd>
|
<dt>drag waveform</dt><dd>seek</dd>
|
||||||
<dt>hold the drop</dt><dd>wheel up: rewind the tune</dd>
|
|
||||||
</dl>
|
</dl>
|
||||||
<dl class="pointer-only">
|
<dl class="pointer-only">
|
||||||
<dt>click · space</dt><dd>play / pause</dd>
|
<dt>click · space</dt><dd>play / pause</dd>
|
||||||
@@ -256,7 +255,6 @@
|
|||||||
<dt>z</dt><dd>zen: just the drop</dd>
|
<dt>z</dt><dd>zen: just the drop</dd>
|
||||||
<dt>c</dt><dd>filters and settings</dd>
|
<dt>c</dt><dd>filters and settings</dd>
|
||||||
<dt>h</dt><dd>history</dd>
|
<dt>h</dt><dd>history</dd>
|
||||||
<dt>w · hold drop</dt><dd>wheel up: rewind the tune</dd>
|
|
||||||
<dt>0–9 · , .</dt><dd>jump to 0–90 % · seek 5 s</dd>
|
<dt>0–9 · , .</dt><dd>jump to 0–90 % · seek 5 s</dd>
|
||||||
<dt>m · + −</dt><dd>mute · volume</dd>
|
<dt>m · + −</dt><dd>mute · volume</dd>
|
||||||
<dt>?</dt><dd>this help</dd>
|
<dt>?</dt><dd>this help</dd>
|
||||||
|
|||||||
+2
-35
@@ -16,7 +16,6 @@ const PREFETCH_AHEAD = 4; // fetch more when this close to the end
|
|||||||
const SKIP_SECONDS = 8; // leaving earlier than this counts as a skip
|
const SKIP_SECONDS = 8; // leaving earlier than this counts as a skip
|
||||||
const COMPLETE_RATIO = 0.85;
|
const COMPLETE_RATIO = 0.85;
|
||||||
const DOUBLE_TAP_MS = 300;
|
const DOUBLE_TAP_MS = 300;
|
||||||
const LONG_PRESS_MS = 550; // holding the drop this long rewinds the tune
|
|
||||||
const PRELOAD_AFTER_MS = 2500; // start buffering the next track once this one has played a bit
|
const PRELOAD_AFTER_MS = 2500; // start buffering the next track once this one has played a bit
|
||||||
const KEEP_BUILT = 3; // cards further than this from the current one drop their elements
|
const KEEP_BUILT = 3; // cards further than this from the current one drop their elements
|
||||||
const HISTORY_AFTER = 1; // s heard before a track goes into the history
|
const HISTORY_AFTER = 1; // s heard before a track goes into the history
|
||||||
@@ -322,14 +321,6 @@ async function share(card: Card): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The rewind: spin the drop back, slow the tune down, and run it again.
|
|
||||||
function wheelUp(): void {
|
|
||||||
if (!current()) return;
|
|
||||||
visual.wheelUp();
|
|
||||||
player.wheelUp();
|
|
||||||
toast("wheel up!");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Player events -----------------------------------------------------------
|
// Player events -----------------------------------------------------------
|
||||||
|
|
||||||
player.on("timeupdate", () => {
|
player.on("timeupdate", () => {
|
||||||
@@ -430,38 +421,15 @@ if ("mediaSession" in navigator) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tap to play/pause, double-tap to like, hold to rewind ---------------------
|
// Tap to play/pause, double-tap to like -------------------------------------
|
||||||
|
|
||||||
let lastTap: { at: number; card: Card | null; toggled: boolean } = { at: 0, card: null, toggled: false };
|
let lastTap: { at: number; card: Card | null; toggled: boolean } = { at: 0, card: null, toggled: false };
|
||||||
let press: { timer: number; x: number; y: number } | null = null;
|
|
||||||
let pressFired = false;
|
|
||||||
|
|
||||||
feedEl.addEventListener("pointerdown", (e) => {
|
|
||||||
if (!started || !(e.target as Element).closest(".card.current .art")) return;
|
|
||||||
pressFired = false;
|
|
||||||
press = {
|
|
||||||
x: e.clientX,
|
|
||||||
y: e.clientY,
|
|
||||||
timer: window.setTimeout(() => {
|
|
||||||
press = null;
|
|
||||||
pressFired = true;
|
|
||||||
wheelUp();
|
|
||||||
}, LONG_PRESS_MS),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
const cancelPress = (e: PointerEvent) => {
|
|
||||||
if (press && (e.type !== "pointermove" || Math.hypot(e.clientX - press.x, e.clientY - press.y) > 10)) {
|
|
||||||
clearTimeout(press.timer);
|
|
||||||
press = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
for (const ev of ["pointermove", "pointerup", "pointercancel"]) feedEl.addEventListener(ev, (e) => cancelPress(e as PointerEvent));
|
|
||||||
// A long press opens the context menu on some phones.
|
// A long press opens the context menu on some phones.
|
||||||
feedEl.addEventListener("contextmenu", (e) => { if ((e.target as Element).closest(".art")) e.preventDefault(); });
|
feedEl.addEventListener("contextmenu", (e) => { if ((e.target as Element).closest(".art")) e.preventDefault(); });
|
||||||
|
|
||||||
feedEl.addEventListener("click", (e) => {
|
feedEl.addEventListener("click", (e) => {
|
||||||
if (pager.suppressClick) return;
|
if (pager.suppressClick) return;
|
||||||
if (pressFired) { pressFired = false; return; }
|
|
||||||
const target = e.target as Element;
|
const target = e.target as Element;
|
||||||
if (target.closest("button, a, input, .wave-wrap")) return;
|
if (target.closest("button, a, input, .wave-wrap")) return;
|
||||||
const el = target.closest(".card");
|
const el = target.closest(".card");
|
||||||
@@ -554,7 +522,7 @@ function start(): void {
|
|||||||
showUpNext();
|
showUpNext();
|
||||||
if (!localStorage.getItem(HINT_KEY)) {
|
if (!localStorage.getItem(HINT_KEY)) {
|
||||||
localStorage.setItem(HINT_KEY, "1");
|
localStorage.setItem(HINT_KEY, "1");
|
||||||
toast(isTouch ? "tap to pause · double-tap to like · hold the drop to rewind"
|
toast(isTouch ? "tap to pause · double-tap to like · swipe up for next"
|
||||||
: "click to pause · double-click to like · ? for shortcuts", 5000);
|
: "click to pause · double-click to like · ? for shortcuts", 5000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -990,7 +958,6 @@ document.addEventListener("keydown", (e) => {
|
|||||||
else if (k === "r" && card) actions.radio(card);
|
else if (k === "r" && card) actions.radio(card);
|
||||||
else if (k === "x" && card) dislike(card);
|
else if (k === "x" && card) dislike(card);
|
||||||
else if (k === "s" && card) share(card);
|
else if (k === "s" && card) share(card);
|
||||||
else if (k === "w") wheelUp();
|
|
||||||
else if (k === "h") sheets.history.open();
|
else if (k === "h") sheets.history.open();
|
||||||
else if (k === "c") sheets.filters.open();
|
else if (k === "c") sheets.filters.open();
|
||||||
else if (k === "v") { setVisuals(visual.visuals === "liquid" ? "simple" : "liquid"); toast(`${visual.visuals} visuals`); }
|
else if (k === "v") { setVisuals(visual.visuals === "liquid" ? "simple" : "liquid"); toast(`${visual.visuals} visuals`); }
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ const CROSSFADE_KEY = "pl8inf.crossfade";
|
|||||||
const BASS_KEY = "pl8inf.bass";
|
const BASS_KEY = "pl8inf.bass";
|
||||||
const BASS_DB = 6; // gain of the bass boost's low shelf …
|
const BASS_DB = 6; // gain of the bass boost's low shelf …
|
||||||
const BASS_HZ = 120; // … below this
|
const BASS_HZ = 120; // … below this
|
||||||
const TAPE_STOP = 0.45; // s the rewind's tape stop takes
|
|
||||||
|
|
||||||
type Hls = HlsType;
|
type Hls = HlsType;
|
||||||
type HlsClass = typeof HlsType;
|
type HlsClass = typeof HlsType;
|
||||||
@@ -301,32 +300,6 @@ export class Player {
|
|||||||
this.audio.pause();
|
this.audio.pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The soundsystem rewind: the record is pulled back, the music slows down and
|
|
||||||
/// drops in pitch, and the tune starts again from the top.
|
|
||||||
async wheelUp(): Promise<void> {
|
|
||||||
const a = this.audio;
|
|
||||||
if (a.paused) {
|
|
||||||
this.seek(0);
|
|
||||||
this.resume();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const pitch = a.preservesPitch;
|
|
||||||
a.preservesPitch = false;
|
|
||||||
const t0 = performance.now();
|
|
||||||
await new Promise<void>((done) => {
|
|
||||||
const step = () => {
|
|
||||||
const k = Math.min(1, (performance.now() - t0) / 1000 / TAPE_STOP);
|
|
||||||
a.playbackRate = Math.max(0.1, 1 - 0.9 * k * k);
|
|
||||||
if (k < 1) requestAnimationFrame(step);
|
|
||||||
else done();
|
|
||||||
};
|
|
||||||
requestAnimationFrame(step);
|
|
||||||
});
|
|
||||||
a.playbackRate = 1;
|
|
||||||
a.preservesPitch = pitch;
|
|
||||||
this.seek(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
seek(seconds: number): void {
|
seek(seconds: number): void {
|
||||||
const a = this.audio;
|
const a = this.audio;
|
||||||
a.currentTime = Math.max(0, Math.min(a.duration || 0, seconds));
|
a.currentTime = Math.max(0, Math.min(a.duration || 0, seconds));
|
||||||
|
|||||||
@@ -143,12 +143,6 @@ export class Visualizer {
|
|||||||
return this.blob?.lost ? null : this.blob;
|
return this.blob?.lost ? null : this.blob;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Spin the drop backwards, hard: the rewind.
|
|
||||||
wheelUp(): void {
|
|
||||||
this.blob?.spin.fling([0, -26, 0]);
|
|
||||||
this.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A play/pause from a tap was taken back by the second tap of a double-tap.
|
/// A play/pause from a tap was taken back by the second tap of a double-tap.
|
||||||
cancelFlash(): void {
|
cancelFlash(): void {
|
||||||
this.blob?.settleIcon();
|
this.blob?.settleIcon();
|
||||||
|
|||||||
Reference in new issue
Block a user