mirror of
https://codeberg.org/kirche-im-netz/Startodon-Hub.git
synced 2025-08-05 02:34:47 +02:00
282 lines
9.5 KiB
JavaScript
282 lines
9.5 KiB
JavaScript
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;
|
||
}
|
||
}
|