android: tap-to-sync, the per-track auto-sync switch, the vocal-reduced copy
The editor the desktop drives with a mouse is better under a thumb: the song plays, the line to time sits large in the middle of the screen with the one behind and the one ahead faint around it, and a tap anywhere stamps it. One layer the back gesture peels, and a set left mid-tap is offered back by the row that opened it; Save writes the track's own document, lines never tapped left out of it and the button saying how many are kept. The lyrics sheet also gains the per-track auto-sync switch and the desktop's reduced-vocals copy — the same title, artist and duration, so the words keep following it, and one row puts the original back.
This commit is contained in:
1 parent
e693dfb868
commit
24c6857847
9 files changed
+434
-11
No files matched your search
@@ -16,7 +16,7 @@
|
||||
import { DOORS, start as startImport } from "./importer.svelte.js";
|
||||
import { slsk, refreshRooms, disconnect, openThread, addBuddy, removeBuddy, leaveRoom } from "./slsk.svelte.js";
|
||||
import { lib, albumById, albumsBy, tracksOf, loadLibrary, refreshPlaylists, refreshRecents } from "./lib.svelte.js";
|
||||
import { lyr, nudge, searchCandidates, closeCandidates, chooseCandidate, forgetLyrics, pasteLyrics } from "./lyrics.svelte.js";
|
||||
import { lyr, nudge, searchCandidates, closeCandidates, chooseCandidate, forgetLyrics, pasteLyrics, setAutoSync, openTapSync, tapProgress, reduceVocals, backToOriginal } from "./lyrics.svelte.js";
|
||||
import { art, wantArt } from "./art.svelte.js";
|
||||
import { metaOf, display, realName, setMeta, clearMeta } from "./contacts.svelte.js";
|
||||
import { downloadsAllowed } from "./network.svelte.js";
|
||||
@@ -69,6 +69,11 @@
|
||||
}
|
||||
return null;
|
||||
});
|
||||
/* the lyrics sheet: a tap-sync set left mid-tap for the playing track,
|
||||
and whether a vocal-reduced copy is what is playing */
|
||||
const tapLeft = $derived(kind === "lyrics" ? tapProgress() : null);
|
||||
const canReduce = $derived(!!player.track?.path && !player.track?.stream);
|
||||
const onReduced = $derived(!!lyr.reduced && player.track?.path === lyr.reduced.to);
|
||||
const onThisAlbum = $derived((id) => top().n === "album" && top().c.id === id);
|
||||
const after = $derived(Math.max(0, player.queue.length - player.qi - 1));
|
||||
|
||||
@@ -281,6 +286,14 @@
|
||||
</button>
|
||||
{/snippet}
|
||||
|
||||
{#snippet swrow(icon, t, m, on, fn)}
|
||||
<button class="row" onclick={fn}>
|
||||
<span class="lead"><Icon name={icon} size={20} /></span>
|
||||
<span class="b"><span class="t">{t}</span>{#if m}<span class="m">{m}</span>{/if}</span>
|
||||
<span class="sw" class:on><span></span></span>
|
||||
</button>
|
||||
{/snippet}
|
||||
|
||||
<div class="halfsheet" class:up={!!nav.half}>
|
||||
<div class="grab"></div>
|
||||
<div class="hs-body">
|
||||
@@ -621,10 +634,17 @@
|
||||
{#if lyr.lines.length}
|
||||
{@render row("skip-back", "Lyrics earlier", "half a second, kept for this track", () => nudge(-500))}
|
||||
{@render row("skip-forward", "Lyrics later", "half a second", () => nudge(500))}
|
||||
{@render swrow("history", "Auto-sync this track", lyr.autoOffset ? `correcting by ${lyr.autoOffset > 0 ? "+" : ""}${(lyr.autoOffset / 1000).toFixed(1)} s` : "let the app correct this track's timing", !lyr.autoSyncOff, () => { void setAutoSync(lyr.autoSyncOff); })}
|
||||
<div class="sheet-hair"></div>
|
||||
{/if}
|
||||
{@render row("search", "Wrong lyrics? Search again", "LRCLIB, by this track's name", () => { void searchCandidates(); })}
|
||||
{@render row("file-text", "Paste lyrics…", "plain text, or LRC with [mm:ss] timestamps", () => openHalf("prompt", { title: "Paste lyrics", placeholder: "[00:12.50] The first line…", ok: "Save", multiline: true, onsubmit: (v) => { void pasteLyrics(v); } }))}
|
||||
{#if lyr.lines.length || lyr.plain}
|
||||
{@render row("clock", lyr.lines.length ? "Re-time by hand" : "Sync these lyrics", tapLeft ? `${tapLeft.done} of ${tapLeft.total} lines timed — keep going` : "play the song and tap as each line begins", act(openTapSync))}
|
||||
{/if}
|
||||
{#if canReduce}
|
||||
{@render row("music", onReduced ? "Back to the original" : "Play with reduced vocals", onReduced ? "the recording as it is" : lyr.reducing ? "making the copy now — a moment" : "a rough centre cancel, made on this phone", act(() => { void (onReduced ? backToOriginal() : reduceVocals()); }))}
|
||||
{/if}
|
||||
{@render row("refresh", "Forget and look again", "", act(() => { void forgetLyrics(); }))}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
Reference in new issue
Block a user