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:
KeelrLeek committed 2026-09-13 23:04:49 -05:00
1 parent e693dfb868
commit 24c6857847
9 files changed
+434 -11

No files matched your search

+62
View File
@@ -134,6 +134,11 @@ const PROBE = `(function () {
fmtBadges: document.querySelectorAll('.grid2 .release .ed-badge').length,
played: (document.querySelector('.hero-acts .stats .played') || {}).textContent || '',
lyrLines: document.querySelectorAll('.lyr .ln').length,
sync: !!document.querySelector('.syncroom'),
syCount: (document.querySelector('.sy-count') || {}).textContent || '',
syNow: (document.querySelector('.sy-now') || {}).textContent || '',
lyrAuto: (function () { var r = [].slice.call(document.querySelectorAll('.halfsheet .row')).find(function (x) { return /Auto-sync/.test(x.textContent); }); return r ? (r.querySelector('.sw.on') ? 'on' : 'off') : ''; })(),
trackPath: (function () { try { return __ss.player.track ? String(__ss.player.track.path || '') : ''; } catch (e) { return ''; } })(),
sheetTitle: (document.querySelector('.halfsheet .sheet-title') || {}).textContent || '',
recents: document.querySelectorAll('.recent-chips .chip').length,
dym: (document.querySelector('.dym') || {}).textContent || '',
@@ -215,6 +220,31 @@ const MOCK_STEPS = [
{ do: `__click('.halfsheet .row', 'Paste lyrics')`, wait: 600 },
{ do: `(function () { var i = document.querySelector('.halfsheet .prompt .field'); i.value = '[00:01.00] Pasted line one\\n[00:05.00] Pasted line two'; i.dispatchEvent(new Event('input', { bubbles: true })); })()`, wait: 300 },
{ do: `__click('.halfsheet .prompt-acts .btn-fill', 'Save')`, name: "lyrics-pasted", wait: 800 },
/* auto-sync: the app's own correction turned off for this track, then
back on — the re-read leaves the sheet up so the switch is seen */
{ do: `__click('.lyr-tools', null)`, wait: 600 },
{ do: `__click('.halfsheet .row', 'Auto-sync')`, name: "lyrics-autosync-off", wait: 800 },
{ do: `__click('.halfsheet .row', 'Auto-sync')`, name: "lyrics-autosync-on", wait: 800 },
/* off again, and left off: a save returns the document with that flag at
its default, and the switch must not take it */
{ do: `__click('.halfsheet .row', 'Auto-sync')`, wait: 800 },
/* the tap-to-sync room: taps become the timing, one undone, the room
peeled by the back gesture and the set offered back, then saved */
{ do: `__click('.halfsheet .row', 'Re-time by hand')`, name: "sync-room", wait: 800 },
{ do: `__click('.sy-pad', null)`, wait: 400 },
{ do: `__click('.sy-pad', null)`, name: "sync-tapped", wait: 500 },
{ do: `__click('.sy-undo', null)`, name: "sync-undone", wait: 500 },
{ do: `history.back()`, wait: 600 },
{ do: `__click('.lyr-tools', null)`, name: "sync-left", wait: 700 },
{ do: `__click('.halfsheet .row', 'lines timed')`, name: "sync-resumed", wait: 800 },
{ do: `__click('.sy-pad', null)`, wait: 400 },
{ do: `__click('.sy-pad', null)`, name: "sync-all", wait: 500 },
{ do: `__click('.sy-foot .btn-fill', 'Save')`, name: "sync-saved", wait: 900 },
/* the vocal-reduced copy, and back to the recording */
{ do: `__click('.lyr-tools', null)`, name: "sync-saved-sheet", wait: 600 },
{ do: `__click('.halfsheet .row', 'reduced vocals')`, name: "lyrics-reduced", wait: 1800 },
{ do: `__click('.lyr-tools', null)`, wait: 700 },
{ do: `__click('.halfsheet .row', 'Back to the original')`, name: "lyrics-original", wait: 1800 },
{ do: `document.querySelectorAll('.fbtn')[0].click()`, wait: 300 },
{ do: `history.back()`, name: "after-back", wait: 900 },
{ do: `document.querySelector('.rec-artist').click()`, name: "artist", wait: 900 },
@@ -517,6 +547,19 @@ const MOCK_EXPECT = {
"lyrics-candidates": (i) => /Choose the right lyrics/.test(i.halfText) && /Live/.test(i.halfText),
"lyrics-chosen": (i) => !i.half.includes("up") && i.lyrLines >= 3,
"lyrics-pasted": (i) => !i.half.includes("up") && i.lyrLines === 2,
"lyrics-autosync-off": (i) => i.half.includes("up") && i.lyrAuto === "off",
"lyrics-autosync-on": (i) => i.half.includes("up") && i.lyrAuto === "on",
"sync-room": (i) => i.sync && i.syCount === "0 / 3" && !!i.syNow,
"sync-tapped": (i) => i.sync && i.syCount === "2 / 3",
"sync-undone": (i) => i.sync && i.syCount === "1 / 3",
"sync-left": (i) => !i.sync && i.half.includes("up") && /1 of 3 lines timed/.test(i.halfText),
"sync-resumed": (i) => i.sync && i.syCount === "1 / 3",
"sync-all": (i) => i.sync && i.syCount === "3 / 3" && /every line/.test(i.syNow),
"sync-saved": (i) => !i.sync && i.lyrLines === 3 && !i.toast,
/* the save's own payload carries no auto-sync flag: the switch kept its */
"sync-saved-sheet": (i) => i.half.includes("up") && i.lyrAuto === "off",
"lyrics-reduced": (i) => /instrumental\.wav$/.test(i.trackPath) && !i.toast,
"lyrics-original": (i) => !!i.trackPath && !/instrumental\.wav$/.test(i.trackPath) && !i.toast,
viewer: (i) => i.viewer,
"viewer-closed": (i) => !i.viewer && i.sheet.includes("up"),
"album-playing": (i) => i.mini,
@@ -642,6 +685,17 @@ const PHONE_STEPS = [
{ do: `(function () { var b = document.querySelector('.lyr-tools'); if (b) b.click(); else __ss.openHalf('lyrics'); })()`, name: "lyrics-sheet", wait: 800 },
{ do: `(function () { var r = [].slice.call(document.querySelectorAll('.halfsheet .row')).find(function (x) { return /Lyrics later/.test(x.textContent); }); if (r) r.click(); })()`, name: "lyrics-nudged", wait: 700 },
{ do: `(function () { var r = [].slice.call(document.querySelectorAll('.halfsheet .row')).find(function (x) { return /Lyrics earlier/.test(x.textContent); }); if (r) r.click(); })()`, wait: 700 },
/* auto-sync off and straight back on — the cache entry ends as it began */
{ do: `(function () { var r = [].slice.call(document.querySelectorAll('.halfsheet .row')).find(function (x) { return /Auto-sync/.test(x.textContent); }); if (r) r.click(); })()`, name: "lyrics-autosync-off", wait: 1200 },
{ do: `(function () { var r = [].slice.call(document.querySelectorAll('.halfsheet .row')).find(function (x) { return /Auto-sync/.test(x.textContent); }); if (r) r.click(); })()`, name: "lyrics-autosync-on", wait: 1200 },
/* the tap room on the real clock: two taps, one undone, then discarded —
nothing is written to Kyle's own lyrics for this track */
{ do: `(function () { var r = [].slice.call(document.querySelectorAll('.halfsheet .row')).find(function (x) { return /Re-time by hand|Sync these lyrics/.test(x.textContent); }); if (r) r.click(); })()`, name: "sync-room", wait: 1000 },
{ do: `(function () { var p = document.querySelector('.sy-pad'); if (p) p.click(); })()`, wait: 700 },
{ do: `(function () { var p = document.querySelector('.sy-pad'); if (p) p.click(); })()`, name: "sync-tapped", wait: 700 },
{ do: `(function () { var u = document.querySelector('.sy-undo'); if (u) u.click(); })()`, name: "sync-undone", wait: 700 },
{ do: `(function () { var c = document.querySelector('.sy-close'); if (c) c.click(); })()`, wait: 500 },
{ do: `(function () { var c = document.querySelector('.sy-close'); if (c) c.click(); })()`, name: "sync-discarded", wait: 800 },
{ do: `document.querySelector('.scrim').click()`, wait: 500 },
{ do: `document.querySelectorAll('.fbtn')[0].click()`, wait: 400 },
{ do: `history.back()`, name: "after-back", wait: 1000 },
@@ -728,6 +782,14 @@ const PHONE_EXPECT = {
"album-playing": (i) => i.mini && !i.toast,
"lyrics-sheet": (i) => i.half.includes("up") && /Search again/.test(i.halfText),
"lyrics-nudged": (i) => i.half.includes("up") && !i.toast,
/* the walked album's track may genuinely have no words, so the room's
own rows are conditional — the discard is not */
"lyrics-autosync-off": (i) => !i.toast && (i.lyrAuto === "" || i.lyrAuto === "off"),
"lyrics-autosync-on": (i) => !i.toast && (i.lyrAuto === "" || i.lyrAuto === "on"),
"sync-room": (i) => !i.toast && (!i.sync || /^0 \/ [1-9]/.test(i.syCount)),
"sync-tapped": (i) => !i.toast && (!i.sync || /^2 \//.test(i.syCount)),
"sync-undone": (i) => !i.toast && (!i.sync || /^1 \//.test(i.syCount)),
"sync-discarded": (i) => !i.sync && !i.toast,
viewer: (i) => i.viewer,
"viewer-closed": (i) => !i.viewer && i.sheet.includes("up"),
"home-ambience": (i) => /^(Good |Still)/.test(i.title) && i.amb.includes("on:img"),