Radioplayer-with-Presets/main.js
2025-12-18 19:05:05 +01:00

251 lines
No EOL
8.9 KiB
JavaScript

// Public Domain - Hauptlogik des Radioplayers (Schaltzentrale)
document.addEventListener('DOMContentLoaded', function () {
// --- UI ELEMENTE ---
const presetContainer = document.getElementById('preset-container');
const stopButton = document.querySelector('.stop-button');
const currentStationName = document.getElementById('current-station-name');
const presetModal = document.getElementById('preset-modal');
const tableBody = document.querySelector('#sortable-tbody');
let currentSound = null;
// --- INITIALISIERUNG ---
if (window.UI) window.UI.initializeFooter();
initializeEventListeners();
// Manager verknüpfen
if (window.SleepTimer) {
window.SleepTimer.init(() => stopPlayback());
}
if (window.PresetManager) {
window.PresetManager.load((loadedPresets) => {
displayPresets(loadedPresets);
initSortable();
});
}
// --- EVENT LISTENER ---
function initializeEventListeners() {
// Stop Button
if (stopButton) {
stopButton.onclick = stopPlayback;
}
// Preset Modal öffnen
const editBtn = document.getElementById('edit-presets-button');
if (editBtn) {
editBtn.onclick = openPresetModal;
}
// Sleep Timer Modal öffnen
const sleepBtn = document.getElementById('open-sleep-timer-modal');
if (sleepBtn) {
sleepBtn.onclick = openSleepModal;
}
// Sleep Timer Modal schließen (X-Button)
const closeSleepBtn = document.getElementById('close-sleep-timer-modal');
if (closeSleepBtn) {
closeSleepBtn.onclick = () => {
const sm = document.getElementById('sleep-timer-modal');
sm.classList.add('hidden');
sm.style.display = 'none';
};
}
// Sleep Timer wirklich ausschalten
const offSleepBtn = document.getElementById('off-sleep-timer-modal');
if (offSleepBtn) {
offSleepBtn.onclick = () => {
if (window.SleepTimer) {
window.SleepTimer.clear(); // Stoppt den Timeout und resettet die UI
}
const sm = document.getElementById('sleep-timer-modal');
if (sm) {
sm.classList.add('hidden');
sm.style.display = 'none';
}
};
}
// Zeit-Optionen im Sleep Timer
document.querySelectorAll('.time-option').forEach(btn => {
btn.onclick = () => {
const minutes = parseInt(btn.getAttribute('data-time')) / 60000;
window.SleepTimer.start(minutes);
const sm = document.getElementById('sleep-timer-modal');
sm.classList.add('hidden');
sm.style.display = 'none';
};
});
}
// --- PLAYER LOGIK ---
function playStream(url, item) {
stopPlayback();
if (window.MetaHandler) window.MetaHandler.stop();
currentSound = new Howl({
src: [url],
html5: true,
volume: 0.5,
// In der playStream Funktion innerhalb von onplay:
onplay: () => {
stopButton.classList.remove('hidden');
const stationName = item.querySelector('h3').textContent;
if (window.UI) window.UI.updateDocumentTitle(stationName);
// Wir setzen das Icon für den Sender
currentStationName.innerHTML = `<i class="fa-solid fa-tower-broadcast"></i> ${stationName}`;
if (window.MetaHandler) window.MetaHandler.start(url);
},
onstop: () => {
stopButton.classList.add('hidden');
currentStationName.textContent = 'Wähle einen Sender aus';
if (window.UI) window.UI.updateDocumentTitle('');
if (window.MetaHandler) window.MetaHandler.stop();
}
});
currentSound.play();
}
function stopPlayback() {
if (currentSound) {
currentSound.stop();
currentSound = null;
}
}
// --- PRESET UI ---
function displayPresets(presets) {
presetContainer.innerHTML = '';
presets.forEach(preset => {
const presetItem = document.createElement('div');
presetItem.classList.add('preset-item');
presetItem.innerHTML = `<h3>${preset.name}</h3>`;
presetItem.onclick = () => playStream(preset.url, presetItem);
presetContainer.appendChild(presetItem);
});
}
function renderPresetsTable() {
if (!tableBody) return;
tableBody.innerHTML = '';
window.PresetManager.presets.forEach((preset, index) => {
const row = document.createElement('tr');
row.setAttribute('data-index', index);
row.innerHTML = `
<td class="drag-handle">☰</td>
<td><input type="text" value="${preset.name}" onchange="changeName(${index}, this.value)"></td>
<td><input type="text" value="${preset.url}" onchange="changeURL(${index}, this.value)"></td>
<td><button class="delete-btn" onclick="deletePreset(${index})"><i class="fas fa-trash-alt"></i></button></td>
`;
tableBody.appendChild(row);
});
}
// --- MODAL WRAPPER ---
function openPresetModal() {
if (!presetModal) return;
presetModal.classList.remove('hidden');
presetModal.style.display = 'block';
renderPresetsTable();
if (window.PresetManager) window.PresetManager.generateExportCode();
}
function openSleepModal() {
const sm = document.getElementById('sleep-timer-modal');
if (sm) {
sm.classList.remove('hidden');
sm.style.display = 'block';
if (window.SleepTimer) window.SleepTimer.updateButtonUI();
}
}
// --- GLOBALE HELFER (für HTML onclicks & Manager) ---
window.closeModal = () => {
if (presetModal) {
presetModal.classList.add('hidden');
presetModal.style.display = 'none';
}
};
window.addPreset = () => {
window.PresetManager.presets.push({ name: 'Neuer Sender', url: '' });
renderPresetsTable();
};
window.deletePreset = (index) => {
window.UI.showConfirm("Löschen", "Sender wirklich entfernen?", (conf) => {
if (conf) {
window.PresetManager.presets.splice(index, 1);
renderPresetsTable();
window.PresetManager.generateExportCode();
}
});
};
window.saveAndClose = () => {
window.PresetManager.save();
location.reload();
};
window.changeName = (i, v) => {
window.PresetManager.presets[i].name = v;
window.PresetManager.generateExportCode();
};
window.changeURL = (i, v) => {
window.PresetManager.presets[i].url = v;
window.PresetManager.generateExportCode();
};
window.exportPreset = () => window.PresetManager.exportToFile();
window.importPreset = () => {
window.UI.showConfirm("Vorsicht", "Alle Sender werden überschrieben!", (conf) => {
if (conf) {
const input = document.createElement('input');
input.type = 'file';
input.accept = 'application/json';
input.onchange = e => {
const reader = new FileReader();
reader.onload = ev => {
try {
window.PresetManager.presets = JSON.parse(ev.target.result);
window.PresetManager.save();
location.reload();
} catch (err) { window.UI.showAlert("Fehler", "Ungültige Datei."); }
};
reader.readAsText(e.target.files[0]);
};
input.click();
}
});
};
window.importFromString = () => {
const field = document.getElementById('import-string-field');
const code = field ? field.value.trim() : "";
if (!code) return window.UI.showAlert("Fehler", "Bitte Code einfügen.");
window.UI.showConfirm("Vorsicht", "Alle Sender werden überschrieben!", (conf) => {
if (conf) window.PresetManager.importFromString(code);
});
};
function initSortable() {
if (!tableBody) return;
new Sortable(tableBody, {
handle: '.drag-handle',
animation: 150,
onEnd: () => {
const newOrder = Array.from(tableBody.children).map(row => parseInt(row.getAttribute('data-index')));
window.PresetManager.presets = newOrder.map(index => window.PresetManager.presets[index]);
window.PresetManager.generateExportCode();
}
});
}
});