Chapter picker: tap the chapter badge to jump to any chapter
The CH badge by the scrubber is now a button opening a list of every chapter (number, title, start time); the playing one is highlighted and scrolled into view, a tap seeks there (and resumes if paused). Works with shared chapters and YouTube's.
This commit is contained in:
@@ -3273,7 +3273,7 @@ function fitLyricLines(list, { maxShare = 0.17, maxPx = 160, minPx = 18, uniform
|
||||
const Notes = (() => {
|
||||
const LC = window.LyricsCore;
|
||||
const panel = $('notesPanel');
|
||||
const noop = { load() {}, tick() {}, addBookmark() {}, handleSyncKey() { return false; }, serviceRefresh() {}, chapterAt() { return null; }, jumpChapter() {} };
|
||||
const noop = { load() {}, tick() {}, addBookmark() {}, handleSyncKey() { return false; }, serviceRefresh() {}, chapterAt() { return null; }, jumpChapter() {}, openChapterPicker() {} };
|
||||
if (!panel || !LC) return noop;
|
||||
|
||||
const CACHE_KEY = 'ytpNotesCache';
|
||||
@@ -3892,6 +3892,42 @@ const Notes = (() => {
|
||||
await saveShared('chapters', { items: [...chapters().map((c) => ({ t: c.t, title: c.title })), v] }, baseRev);
|
||||
}
|
||||
|
||||
// Chapter picker: every chapter with its number and start time; the one
|
||||
// playing is marked and scrolled into view. Tapping a row jumps there.
|
||||
function openChapterPicker() {
|
||||
const cs = chapters().slice().sort((a, b) => a.t - b.t);
|
||||
if (!cs.length) { toast('No chapters for this video'); return; }
|
||||
const cur = (Player.master && Player.master.currentTime) || 0;
|
||||
let active = -1;
|
||||
cs.forEach((c, i) => { if (c.t <= cur + 0.5) active = i; });
|
||||
const body = document.createElement('div');
|
||||
body.className = 'ch-picker';
|
||||
if (autoChapters()) {
|
||||
const note = document.createElement('p');
|
||||
note.className = 'ch-picker-src';
|
||||
note.textContent = 'Chapters from YouTube';
|
||||
body.appendChild(note);
|
||||
}
|
||||
const list = document.createElement('div');
|
||||
list.className = 'ch-picker-list';
|
||||
list.setAttribute('role', 'listbox');
|
||||
cs.forEach((c, i) => {
|
||||
const b = document.createElement('button');
|
||||
b.type = 'button';
|
||||
b.className = 'ch-pick' + (i === active ? ' on' : '');
|
||||
b.setAttribute('role', 'option');
|
||||
b.setAttribute('aria-selected', String(i === active));
|
||||
b.innerHTML = `<span class="ch-pick-n">${String(i + 1).padStart(2, '0')}</span><span class="ch-pick-title"></span><span class="ch-pick-t">${LC.fmtClock(c.t)}</span>`;
|
||||
b.querySelector('.ch-pick-title').textContent = c.title || `Chapter ${i + 1}`;
|
||||
b.onclick = () => { Player.seek(c.t); if (Player.master && Player.master.paused) Player.toggle(); closeModal(); };
|
||||
list.appendChild(b);
|
||||
});
|
||||
body.appendChild(list);
|
||||
showModal(`Chapters · ${cs.length}`, body, [{ label: 'Close', onClick: closeModal }]);
|
||||
const on = list.querySelector('.ch-pick.on');
|
||||
if (on) requestAnimationFrame(() => { on.scrollIntoView({ block: 'center' }); on.focus({ preventScroll: true }); });
|
||||
}
|
||||
|
||||
// [ / ] — previous / next chapter. "Previous" restarts the current chapter
|
||||
// first when more than 3 s into it, like a CD player.
|
||||
function jumpChapter(dir) {
|
||||
@@ -4443,6 +4479,7 @@ const Notes = (() => {
|
||||
load, tick, addBookmark, addNote, handleSyncKey, serviceRefresh, refreshFlags: () => { sv.flagsKey = ''; renderServiceButtons(); setPanelFlagMode(sv.panelFlag && flagsEnabled()); paintFlags(); loadFlags(); },
|
||||
stageLyrics: { render: renderStage, set: setStageLyrics, on: stageOn },
|
||||
jumpChapter,
|
||||
openChapterPicker,
|
||||
chapterAt: (t) => { const c = chapters().slice().sort((a, b) => a.t - b.t); let k = -1; c.forEach((x, i) => { if (x.t <= t) k = i; }); return k < 0 ? null : { n: k + 1, of: c.length, title: c[k].title || '' }; },
|
||||
};
|
||||
})();
|
||||
@@ -11176,6 +11213,7 @@ document.querySelectorAll('.chip').forEach((c) => {
|
||||
// Mini now-playing bar
|
||||
$('miniPlayBtn').addEventListener('click', (e) => { e.stopPropagation(); Player.toggle(); });
|
||||
$('updateIconBtn').addEventListener('click', updateFromIcon);
|
||||
$('chBadge').addEventListener('click', (e) => { e.stopPropagation(); Notes.openChapterPicker(); });
|
||||
$('miniBar').addEventListener('click', () => {
|
||||
setHomeOverPlayer(false);
|
||||
hideMiniBar();
|
||||
|
||||
Reference in New Issue
Block a user