document.addEventListener('DOMContentLoaded', function () { const container = document.getElementById('starterkit-container'); const shuffleContainers = document.querySelectorAll('.shuffle-container'); const seed = Date.now(); // Lade die Haupt-Konfigurationsdatei fetch('config.json') .then(response => response.json()) .then(config => { const starterkitFiles = config.starterkits; // Lade alle StarterKit-Dateien return Promise.all( starterkitFiles.map(file => fetch(file).then(res => res.json())) ); }) .then(starterkits => { // Verarbeite die geladenen StarterKits starterkits.forEach(kit => { const kitElement = createStarterKitElement(kit); container.appendChild(kitElement); }); // Shuffle-Logik anwenden shuffleContainers.forEach(container => { seededShuffleChildren(container, seed); }); // Zusätzliche Funktionalität für StarterKits hinzufügen enhanceStarterKits(); }) .catch(error => console.error('Fehler beim Laden der StarterKits:', error)); }); /** * Erstellt das HTML für ein StarterKit */ function createStarterKitElement(kit) { const kitElement = document.createElement('div'); kitElement.classList.add('starterkit'); const title = document.createElement('h3'); title.textContent = kit.name; const description = document.createElement('p'); description.textContent = kit.description; const authorContainer = document.createElement('div'); authorContainer.classList.add('autor'); const authorLink = document.createElement('a'); authorLink.classList.add('account'); authorLink.href = kit.author; authorLink.target = '_blank'; fetchProfile(kit.author, { updateElement: authorLink }); authorContainer.textContent = 'zusammengestellt von '; authorContainer.appendChild(authorLink); kitElement.appendChild(title); kitElement.appendChild(description); kitElement.appendChild(authorContainer); const accountCountElement = document.createElement('div'); accountCountElement.classList.add('account-count'); accountCountElement.textContent = `${kit.accounts.length} Profile`; kitElement.appendChild(accountCountElement); // Speichere die Accounts in einem Dataset für späteres Laden kitElement.dataset.accounts = JSON.stringify(kit.accounts); return kitElement; } /** * Zusätzliche Funktionen für StarterKits */ function enhanceStarterKits() { const starterkits = document.querySelectorAll('.starterkit'); starterkits.forEach(kit => { kit.addEventListener('click', function () { const title = kit.querySelector('h3').textContent; const accounts = JSON.parse(kit.dataset.accounts || '[]'); const popup = createRecommendationPopup(accounts, title); document.body.appendChild(popup); }); }); } /** * Erstellt ein Pop-up für die Account-Empfehlungen */ function createRecommendationPopup(accounts, title) { const overlay = document.createElement('div'); overlay.classList.add('recommendation-popup'); const content = document.createElement('div'); content.classList.add('recommendation-popup-content'); const header = document.createElement('div'); header.classList.add('recommendation-popup-header'); const titleElement = document.createElement('h3'); titleElement.textContent = title; const closeButton = document.createElement('button'); closeButton.classList.add('close-popup'); closeButton.textContent = '×'; closeButton.addEventListener('click', () => overlay.remove()); header.appendChild(titleElement); header.appendChild(closeButton); const body = document.createElement('div'); body.classList.add('recommendation-popup-body'); accounts.forEach(accountUrl => { fetchProfile(accountUrl, { createCard: true }) .then(card => body.appendChild(card)) .catch(error => console.error(`Fehler beim Laden des Accounts: ${accountUrl}`, error)); }); content.appendChild(header); content.appendChild(body); overlay.appendChild(content); overlay.addEventListener('click', function (event) { if (event.target === overlay) { overlay.remove(); } }); return overlay; } /** * Ruft Profilinformationen ab und aktualisiert ein DOM-Element oder erstellt eine Profil-Kachel. */ function fetchProfile(profileUrl, options = {}) { const { updateElement = null, createCard = false } = options; return new Promise((resolve, reject) => { try { const url = new URL(profileUrl); const pathParts = url.pathname.split('/'); if (pathParts.length > 1 && pathParts[1].startsWith('@')) { const handle = pathParts[1].substring(1); const instance = url.hostname; const lookupUrl = `https://${instance}/api/v1/accounts/lookup?acct=${handle}`; fetch(lookupUrl) .then(response => response.json()) .then(data => { if (updateElement) { // Aktualisiere das übergebene Element updateElement.textContent = data.display_name || data.username; const avatarImage = document.createElement('img'); avatarImage.classList.add('account-avatar'); avatarImage.alt = data.avatar ? `Profilbild von ${data.username}` : 'Profilbild nicht verfügbar'; avatarImage.src = data.avatar || ''; updateElement.prepend(avatarImage); const serverClass = getServerClass(instance); if (serverClass) { updateElement.classList.add(serverClass); } resolve(updateElement); } else if (createCard) { // Erstelle eine Profil-Kachel const card = createAccountCard(data, profileUrl, instance); resolve(card); } }) .catch(error => { console.error(`Fehler beim Abrufen des Profils für ${profileUrl}:`, error); reject(error); }); } } catch (error) { console.error('Ungültige URL:', profileUrl, error); reject(error); } }); } /** * Erstellt eine Account-Kachel */ function createAccountCard(data, href, instance) { const link = document.createElement('a'); link.classList.add('account-card-link'); link.href = href; link.target = '_blank'; const card = document.createElement('div'); card.classList.add('account-card'); const avatarImage = document.createElement('img'); avatarImage.classList.add('account-avatar'); avatarImage.alt = data.avatar ? `Profilbild von ${data.username}` : 'Profilbild nicht verfügbar'; avatarImage.src = data.avatar || ''; const infoContainer = document.createElement('div'); infoContainer.classList.add('account-info'); const displayNameElement = document.createElement('p'); displayNameElement.classList.add('display-name'); displayNameElement.textContent = data.display_name || data.username; const handleElement = document.createElement('p'); handleElement.classList.add('handle'); const serverHandleElement = document.createElement('span'); serverHandleElement.classList.add('server-handle'); serverHandleElement.textContent = `@${instance}`; // Ergänze die Klasse basierend auf der Instanz const serverClass = getServerClass(instance); if (serverClass) { serverHandleElement.classList.add(serverClass); } handleElement.textContent = `@${data.username}`; handleElement.appendChild(serverHandleElement); infoContainer.appendChild(displayNameElement); infoContainer.appendChild(handleElement); card.appendChild(avatarImage); card.appendChild(infoContainer); link.appendChild(card); return link; } /** * Deterministisch Kinder neu anordnen */ function seededShuffleChildren(container, seed) { const children = Array.from(container.children); const shuffled = seededShuffle(children, seed); shuffled.forEach(child => container.appendChild(child)); } function seededShuffle(array, seed) { for (let i = array.length - 1; i > 0; i--) { const j = Math.floor(seededRandom(seed++) * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } return array; } function seededRandom(seed) { const x = Math.sin(seed++) * 10000; return x - Math.floor(x); } function getServerClass(instance) { const serverClasses = { 'libori.social': 'liboriSocial', 'reliverse.social': 'reliverseSocial', 'kirche.social': 'kircheSocial', 'katholisch.social': 'katholischSocial' }; return serverClasses[instance] || null; } /** * Extrahiert den Handle (z. B. @benutzer@instanz) aus einer URL */ function extractHandleFromURL(url) { try { const parsedUrl = new URL(url); const pathParts = parsedUrl.pathname.split('/'); return pathParts.length > 1 ? pathParts[1] : url; } catch (error) { console.error('Ungültige URL:', url); return url; } }