Merge branch 'codex/ui-fixes'
This commit is contained in:
@@ -1241,7 +1241,7 @@ async function adoptSharedPlaylistByCode(code, { fromName = '' } = {}) {
|
||||
Add “<strong>${escapeHtml(shared.name)}</strong>” (${count} video${count === 1 ? '' : 's'}) to your playlists?
|
||||
This playlist is added alongside your existing playlists and nothing is replaced.
|
||||
</p>`;
|
||||
showModal(fromName ? '🎵 Playlist sent to you' : '⬇ Add shared playlist', body, [
|
||||
showModal(fromName ? '🎵 Playlist sent to you' : 'Add shared playlist', body, [
|
||||
{ label: fromName ? 'No thanks' : 'Cancel', onClick: () => { closeModal(); resolve(false); } },
|
||||
{ label: 'Add playlist', primary: true, onClick: () => { closeModal(); resolve(true); } },
|
||||
]);
|
||||
@@ -1361,7 +1361,7 @@ async function adoptProfileFromUrl() {
|
||||
Loading it replaces the playlists, history and settings on this device,
|
||||
and future changes here sync to that profile.
|
||||
</p>`;
|
||||
showModal('⬇ Open shared profile', body, [
|
||||
showModal('Open shared profile', body, [
|
||||
{ label: 'Cancel', onClick: () => { closeModal(); resolve(false); } },
|
||||
{ label: 'Load profile', primary: true, onClick: () => { closeModal(); resolve(true); } },
|
||||
]);
|
||||
@@ -1567,7 +1567,7 @@ function loadProfileFlow() {
|
||||
changes here sync back to that profile.
|
||||
</p>
|
||||
<input id="profileNameInput" type="text" placeholder="profile name" autocomplete="off" />`;
|
||||
showModal('⬇ Load online profile', body, [
|
||||
showModal('Load online profile', body, [
|
||||
{ label: 'Cancel', onClick: closeModal },
|
||||
{ label: 'Load', primary: true, onClick: async () => {
|
||||
const name = ($('profileNameInput').value || '').trim();
|
||||
@@ -2209,7 +2209,7 @@ async function openVideoEditor(source) {
|
||||
{
|
||||
label: 'Save edited copy', primary: true, onClick: () => {
|
||||
if (!VideoEdit.hasEdits(cuts, duration)) {
|
||||
showErr('Add at least one cut, or use ⬇ Save for the full video.');
|
||||
showErr('Add at least one cut, or use Save for the full video.');
|
||||
return;
|
||||
}
|
||||
const keep = VideoEdit.invertCuts(cuts, duration);
|
||||
@@ -3559,7 +3559,7 @@ const Notes = (() => {
|
||||
<div class="notes-empty-actions">
|
||||
<button class="np-btn" type="button" data-act="web">🌐 Find lyrics online</button>
|
||||
<button class="np-btn" type="button" data-act="paste">✎ Add lyrics</button>
|
||||
${isUploadId(st.videoId) ? '' : '<button class="np-btn" type="button" data-act="captions">⤓ Import YouTube captions</button>'}
|
||||
${isUploadId(st.videoId) ? '' : `<button class="np-btn" type="button" data-act="captions">${MediaIcons.svg('download')} Import YouTube captions</button>`}
|
||||
</div>
|
||||
<div class="notes-empty-hint">Lyrics and chapters are shared with everyone who plays this song.</div>
|
||||
</div>`;
|
||||
@@ -3801,7 +3801,7 @@ const Notes = (() => {
|
||||
${note ? `<p class="lyr-editor-note">${escapeHtml(note)}</p>` : ''}
|
||||
<textarea class="lyr-editor-text" spellcheck="false" placeholder="Paste or type the lyrics…"></textarea>
|
||||
<div class="lyr-editor-tools">
|
||||
<button type="button" class="np-btn" data-act="captions">⤓ Import YouTube captions</button>
|
||||
<button type="button" class="np-btn" data-act="captions">${MediaIcons.svg('download')} Import YouTube captions</button>
|
||||
<button type="button" class="np-btn" data-act="break">↵ Line break (same time)</button>
|
||||
<button type="button" class="np-btn" data-act="stamp">⏱ Stamp current time on this line</button>
|
||||
</div>`;
|
||||
@@ -4181,7 +4181,7 @@ const Notes = (() => {
|
||||
const refresh = () => { ta.value = build(inc.checked); };
|
||||
inc.addEventListener('change', refresh);
|
||||
refresh();
|
||||
showModal('⤓ Export chapters', body, [
|
||||
showModal('Export chapters', body, [
|
||||
{ label: 'Download .txt', onClick: () => {
|
||||
const blob = new Blob([`${title}\nhttps://youtu.be/${st.videoId}\n\n${ta.value}\n`], { type: 'text/plain' });
|
||||
const a = document.createElement('a');
|
||||
@@ -6920,7 +6920,7 @@ function openImportYouTubeModal() {
|
||||
</p>
|
||||
`;
|
||||
|
||||
showModal('⬇ Import from YouTube', successBody, [
|
||||
showModal('Import from YouTube', successBody, [
|
||||
{ label: 'Cancel', onClick: closeModal },
|
||||
{
|
||||
label: 'Create playlist',
|
||||
@@ -6959,7 +6959,7 @@ function openImportYouTubeModal() {
|
||||
}
|
||||
}
|
||||
|
||||
showModal('⬇ Import from YouTube', body, [
|
||||
showModal('Import from YouTube', body, [
|
||||
{ label: 'Cancel', onClick: closeModal },
|
||||
{ label: 'Import', primary: true, onClick: handleImport },
|
||||
]);
|
||||
@@ -6991,7 +6991,7 @@ function openCardMenu(video) {
|
||||
const isCustom = !!video.custom;
|
||||
|
||||
const exportBtn = document.createElement('button');
|
||||
exportBtn.textContent = '🖼 Save to gallery';
|
||||
exportBtn.innerHTML = MediaIcons.svg('download') + ' Save to gallery';
|
||||
exportBtn.title = 'Put the video file in your gallery, Files app or Downloads folder';
|
||||
exportBtn.onclick = () => { closeModal(); exportToDevice(video); };
|
||||
body.appendChild(exportBtn);
|
||||
@@ -7005,7 +7005,7 @@ function openCardMenu(video) {
|
||||
saveBtn.className = 'danger';
|
||||
saveBtn.onclick = () => { closeModal(); deleteCustomVideo(video.id); };
|
||||
} else {
|
||||
saveBtn.textContent = isSaved ? '✓ Saved offline — remove' : '⬇ Save for offline';
|
||||
saveBtn.innerHTML = MediaIcons.svg(isSaved ? 'offline' : 'download') + (isSaved ? ' Saved offline — remove' : ' Save for offline');
|
||||
saveBtn.onclick = async () => {
|
||||
closeModal();
|
||||
if (cachedIds.has(video.id)) {
|
||||
@@ -7232,17 +7232,17 @@ function updatePlaylistOfflineButton(btn, pl) {
|
||||
let label;
|
||||
btn.classList.remove('done', 'busy');
|
||||
if (stats.total > 0 && stats.cached === stats.total) {
|
||||
if (iconOnly) { setListIcon(btn, 'offlineDone'); btn.classList.add('done'); } else btn.textContent = '✓ Available offline';
|
||||
if (iconOnly) { setListIcon(btn, 'offlineDone'); btn.classList.add('done'); } else btn.innerHTML = MediaIcons.svg('offline') + ' Available offline';
|
||||
btn.disabled = true;
|
||||
btn.classList.add('disabled');
|
||||
label = 'All videos in this playlist are available offline';
|
||||
} else if (isDownloading) {
|
||||
if (iconOnly) { btn.innerHTML = `<span class="lib-progress">${stats.cached}/${stats.total}</span>`; btn.classList.add('busy'); } else btn.textContent = `Saving ${stats.cached}/${stats.total}…`;
|
||||
if (iconOnly) { btn.innerHTML = MediaIcons.svg('progress') + `<span class="lib-progress">${stats.cached}/${stats.total}</span>`; btn.classList.add('busy'); } else btn.innerHTML = MediaIcons.svg('progress') + ` Saving ${stats.cached}/${stats.total}…`;
|
||||
btn.disabled = true;
|
||||
btn.classList.add('disabled');
|
||||
label = `${stats.cached} of ${stats.total} videos saved offline`;
|
||||
} else {
|
||||
if (iconOnly) setListIcon(btn, 'offline'); else btn.textContent = '⬇ Make available offline';
|
||||
if (iconOnly) setListIcon(btn, 'offline'); else btn.innerHTML = MediaIcons.svg('download') + ' Make available offline';
|
||||
btn.disabled = stats.total === 0;
|
||||
btn.classList.toggle('disabled', stats.total === 0);
|
||||
label = stats.total === 0 ? 'Playlist is empty' : 'Make available offline';
|
||||
@@ -7259,7 +7259,7 @@ async function makePlaylistOffline(pl) {
|
||||
const btn = $('plOfflineBtn');
|
||||
if (btn) {
|
||||
const stats = playlistOfflineStats(pl);
|
||||
btn.innerHTML = `<span class="lib-progress">${stats.cached}/${stats.total}</span>`;
|
||||
btn.innerHTML = MediaIcons.svg('progress') + `<span class="lib-progress">${stats.cached}/${stats.total}</span>`;
|
||||
btn.classList.add('busy');
|
||||
btn.disabled = true;
|
||||
btn.classList.add('disabled');
|
||||
|
||||
Reference in New Issue
Block a user