fix: circular import causing navigate undefined; unified importer input

- Remove top-level ui.js import from soundcloud.js (broke views.js→soundcloud.js→ui.js→views.js cycle)
- Use window.executeSpotifyDownload() instead to avoid the circular dep
- Merge Spotify + SoundCloud into one unified URL input that auto-detects
  the service and colors the badge/button accordingly
- resolveImporterLink() routes to the correct handler based on URL

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Sonnet 4.6 committed 2026-05-23 20:39:21 +02:00
1 parent ee65183555
commit 0e8eb311af
4 files changed
+84 -57

No files matched your search

+3 -1
View File
@@ -18,7 +18,8 @@ import {
loadAlbums, loadStarred, loadRandom, filterStarred, filterPlaylist,
plReorderEnter, plReorderSave, plReorderCancel, toggleAllGenres,
} from './views.js';
import { loadSpotifyImporter, resolveSpotifyLink, clearSpotifyPreview, spotifyDlAll } from './spotify.js';
import { loadSpotifyImporter, resolveSpotifyLink, clearSpotifyPreview, spotifyDlAll,
onImporterInput, resolveImporterLink } from './spotify.js';
import { loadSoundCloudImporter, resolveSoundCloudLink, clearSoundCloudPreview, scDlAll } from './soundcloud.js';
import {
absInitFromStorage, absOpenSettings, absConnectSettings, absSetLibrary, absDisconnect, absVerifyApiKey,
@@ -308,6 +309,7 @@ Object.assign(window, {
loadAlbums, loadStarred, loadRandom, filterStarred, filterPlaylist,
plReorderEnter, plReorderSave, plReorderCancel, toggleAllGenres,
loadSpotifyImporter, resolveSpotifyLink, clearSpotifyPreview, spotifyDlAll,
onImporterInput, resolveImporterLink,
loadSoundCloudImporter, resolveSoundCloudLink, clearSoundCloudPreview, scDlAll, scDlSingle, scDlTrack,
executeSpotifyDownload,
openPlModal, closePlModal, addSongsToPlaylist, createAndAddPlaylist, createPlaylistPrompt,
+7 -16
View File
@@ -1,34 +1,25 @@
import { S } from './state.js';
import { esc, toast } from './utils.js';
// Circular imports — safe (only used inside function bodies)
import { executeSpotifyDownload } from './ui.js';
export function loadSoundCloudImporter() {
const input = document.getElementById('sc-link-input');
if (!input?.value) _showHint();
// Hint is managed by the unified importer input in spotify.js
}
export function clearSoundCloudPreview() {
if (!document.getElementById('sc-link-input')?.value) _showHint();
}
function _showHint() {
document.getElementById('sc-importer-hint').style.display = '';
document.getElementById('sc-preview').style.display = 'none';
// no-op — handled by onImporterInput
}
export async function resolveSoundCloudLink() {
const url = document.getElementById('sc-link-input')?.value.trim();
const url = document.getElementById('sc-link-input')?.value.trim()
|| document.getElementById('importer-link-input')?.value.trim();
if (!url) return;
if (!url.includes('soundcloud.com')) { toast('⚠ Kein SoundCloud-Link'); return; }
if (!S.cfg.backendUrl) { toast('⚠ Backend URL in Einstellungen konfigurieren'); return; }
const hint = document.getElementById('sc-importer-hint');
const preview = document.getElementById('sc-preview');
const inner = document.getElementById('sc-preview-inner');
const section = document.getElementById('sc-tracks-section');
hint.style.display = 'none';
preview.style.display = '';
section.style.display = 'none';
inner.innerHTML = '<div class="spinner"></div>';
@@ -59,7 +50,7 @@ export async function resolveSoundCloudLink() {
export function scDlAll() {
const data = window._scResolved;
if (!data) return;
executeSpotifyDownload({
window.executeSpotifyDownload({
type: 'playlist',
title: data.name,
artist: data.artist,
@@ -72,7 +63,7 @@ export function scDlSingle() {
const data = window._scResolved;
if (!data?.tracks?.[0]) return;
const t = data.tracks[0];
executeSpotifyDownload({
window.executeSpotifyDownload({
type: 'track',
title: t.trackName,
artist: t.artistName,
@@ -85,7 +76,7 @@ export function scDlTrack(idx) {
const data = window._scResolved;
const t = data?.tracks?.[idx];
if (!t) return;
executeSpotifyDownload({
window.executeSpotifyDownload({
type: 'track',
title: t.trackName,
artist: t.artistName,
+56 -12
View File
@@ -5,27 +5,71 @@ import { itunesSearch } from './api.js';
import { makeGlobalTrackItem } from './components.js';
import { openDlModal } from './ui.js';
// ─── UNIFIED IMPORTER INPUT ───
export function onImporterInput(val) {
const badge = document.getElementById('importer-badge');
const btn = document.getElementById('importer-btn');
if (!badge || !btn) return;
if (val.includes('spotify.com')) {
badge.textContent = 'Spotify';
badge.style.background = 'rgba(29,185,84,.15)';
badge.style.color = '#1DB954';
btn.style.background = '#1DB954';
btn.style.color = '#000';
btn.style.borderColor = 'transparent';
} else if (val.includes('soundcloud.com')) {
badge.textContent = 'SoundCloud';
badge.style.background = 'rgba(255,85,0,.15)';
badge.style.color = '#ff5500';
btn.style.background = '#ff5500';
btn.style.color = '#fff';
btn.style.borderColor = 'transparent';
} else {
badge.textContent = 'URL';
badge.style.background = '';
badge.style.color = '';
btn.style.background = '';
btn.style.color = '';
btn.style.borderColor = '';
}
// Hide results when input is cleared
if (!val) {
document.getElementById('spotify-preview').style.display = 'none';
document.getElementById('sc-preview').style.display = 'none';
document.getElementById('importer-hint').style.display = '';
}
}
export async function resolveImporterLink() {
const url = document.getElementById('importer-link-input')?.value.trim();
if (!url) return;
// Mirror to the hidden inputs so existing resolve functions pick it up
document.getElementById('spotify-link-input').value = url;
document.getElementById('sc-link-input').value = url;
document.getElementById('importer-hint').style.display = 'none';
if (url.includes('soundcloud.com')) {
window.resolveSoundCloudLink();
} else {
resolveSpotifyLink();
}
}
// ─── SPOTIFY IMPORTER PAGE ───
export function loadSpotifyImporter() {
if (!document.getElementById('spotify-link-input')?.value) {
const hint = document.getElementById('spotify-importer-hint');
const preview = document.getElementById('spotify-preview');
if (hint) hint.style.display = '';
if (preview) preview.style.display = 'none';
const input = document.getElementById('importer-link-input');
if (!input?.value) {
document.getElementById('importer-hint').style.display = '';
document.getElementById('spotify-preview').style.display = 'none';
}
}
export function clearSpotifyPreview() {
if (!document.getElementById('spotify-link-input')?.value) {
const hint = document.getElementById('spotify-importer-hint');
const preview = document.getElementById('spotify-preview');
if (hint) hint.style.display = '';
if (preview) preview.style.display = 'none';
}
// no-op — handled by onImporterInput
}
export async function resolveSpotifyLink() {
const url = document.getElementById('spotify-link-input')?.value.trim();
const url = document.getElementById('spotify-link-input')?.value.trim()
|| document.getElementById('importer-link-input')?.value.trim();
if (!url) return;
if (!S.cfg.backendUrl) { toast('⚠ Backend URL in Einstellungen konfigurieren'); return; }