feat(web+android): Lyrics-Mitlaufen umschaltbar, echtes Mischen, Wiederholung am Queue-Ende
Lyrics: Schalter "Mitlaufen" im Lyrics-Reiter, Vorgabe AUS. Hervorgehoben wird die laufende Zeile immer, gescrollt nur bei eingeschaltetem Mitlaufen. Nur bei synchronen Texten sichtbar. Android speichert den Schluessel einzeln, damit das Speichern im Einstellungsbildschirm ihn nicht auf die Vorgabe zuruecksetzt. Mischen (Web): sort(() => Math.random() - 0.5) ist keine Mischung. Gemessen blieb der erste Titel drei- bis fuenfmal zu oft vorn (18,8 % statt 10 % bei n=10, 0,23 % statt 0,05 % bei n=2000). Ersetzt durch Fisher-Yates in queueMath.mischeListe. Queue-Ende (Web): ein beendetes <audio> meldet sich als pausiert, die Wiederaufnahme nach unfreiwilligem Hintergrund-Stop rief play() und spielte den letzten Titel erneut. Jetzt Abbruch bei audio.ended. Shuffle (Android): das Mischen macht jetzt der Player (playSongs(liste, -1)), damit die ungemischte Liste erhalten bleibt — vorher leuchtete das Symbol nicht und "Shuffle aus" konnte die Albumreihenfolge nicht wiederherstellen. Radio-Modus (beide): der laufende Titel ist aus der letzten Rueckfallebene ausgenommen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ae357b0eb9
commit
b6e98463ee
21 files changed
+227
-29
No files matched your search
@@ -6,7 +6,7 @@ import { loadRecommendations } from '../views/views.js';
|
||||
import { updateLyricsHighlight, onNpSongChange, syncNowPlaying, renderNpQueue } from './nowplaying.js';
|
||||
import { logPlay } from './scrobbleLog.js';
|
||||
import { macheQueueBearbeitbar, QUEUE_WERKZEUGE } from './queueEdit.js';
|
||||
import { queueNachEntfernen, queueNachVerschieben } from './queueMath.js';
|
||||
import { queueNachEntfernen, queueNachVerschieben, mischeListe } from './queueMath.js';
|
||||
|
||||
// ─── NATIVE BRIDGE DETECTION ───────────────────────────────────────────────
|
||||
// True when running inside the NovaSonic Android wrapper (NSBridge injected before loadUrl).
|
||||
@@ -366,7 +366,7 @@ export function playQueue(songs, startIdx, opts = {}) {
|
||||
// opts.noShuffle = true skips shuffle (e.g. clicking a specific song on the artist page).
|
||||
if (S.shuffle && songs.length > 1 && !opts.noShuffle) {
|
||||
S._origQueue = songs.map(s => ({...s}));
|
||||
S.queue = [...songs].sort(() => Math.random() - 0.5).map(s => ({...s}));
|
||||
S.queue = mischeListe(songs).map(s => ({...s}));
|
||||
S.qIdx = 0;
|
||||
} else {
|
||||
S.queue = songs.map(s => ({...s}));
|
||||
@@ -793,7 +793,7 @@ export function toggleShuffle() {
|
||||
if (S.shuffle) {
|
||||
const cur = S.queue[S.qIdx];
|
||||
S._origQueue = [...S.queue];
|
||||
const rest = S.queue.filter((_, i) => i !== S.qIdx).sort(() => Math.random() - 0.5);
|
||||
const rest = mischeListe(S.queue.filter((_, i) => i !== S.qIdx));
|
||||
S.queue = [cur, ...rest];
|
||||
S.qIdx = 0;
|
||||
} else if (S._origQueue) {
|
||||
@@ -871,8 +871,12 @@ export async function fillRadioQueue() {
|
||||
if (gen !== _queueGen) return;
|
||||
const rr = await api('getRandomSongs', '&size=20');
|
||||
const randomFresh = (rr.randomSongs?.song || []).filter(s => !recentIds.has(s.id));
|
||||
// If random is also exhausted, allow repeats to keep music playing
|
||||
newSongs = randomFresh.length > 0 ? randomFresh : newSongs.slice(0, 5);
|
||||
// Ist auch der Zufall erschoepft, sind Wiederholungen erlaubt, damit Musik laeuft — aber
|
||||
// NIE der gerade laufende Titel: der landete sonst direkt hinter sich selbst und spielte
|
||||
// zweimal in Folge.
|
||||
newSongs = randomFresh.length > 0
|
||||
? randomFresh
|
||||
: newSongs.filter(s => s.id !== seed?.id).slice(0, 5);
|
||||
} else {
|
||||
newSongs = deduped;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user