2024-12-08 08:58:41 +01:00
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
2024-12-08 22:48:40 +01:00
|
|
|
|
const shuffleContainers = document.querySelectorAll('.shuffle-container');
|
|
|
|
|
const seed = Date.now();
|
2024-12-08 08:58:41 +01:00
|
|
|
|
|
2024-12-08 22:48:40 +01:00
|
|
|
|
shuffleContainers.forEach(container => {
|
|
|
|
|
seededShuffleChildren(container, seed);
|
|
|
|
|
});
|
2024-12-08 08:58:41 +01:00
|
|
|
|
|
2024-12-08 22:48:40 +01:00
|
|
|
|
const starterkits = document.querySelectorAll('.starterkit');
|
|
|
|
|
|
|
|
|
|
starterkits.forEach(kit => {
|
|
|
|
|
const authorAccount = kit.querySelector('.autor .account');
|
|
|
|
|
if (authorAccount) {
|
|
|
|
|
try {
|
|
|
|
|
const url = new URL(authorAccount.getAttribute('href'));
|
|
|
|
|
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://${config.homeInstance}/api/v1/accounts/lookup?acct=${handle}@${instance}`;
|
|
|
|
|
|
|
|
|
|
fetch(lookupUrl)
|
|
|
|
|
.then(response => response.json())
|
|
|
|
|
.then(data => {
|
|
|
|
|
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 || '';
|
|
|
|
|
|
|
|
|
|
authorAccount.prepend(avatarImage);
|
|
|
|
|
|
|
|
|
|
// Ergänze die Klasse basierend auf der Instanz
|
|
|
|
|
const serverClass = getServerClass(instance);
|
|
|
|
|
if (serverClass) {
|
|
|
|
|
authorAccount.classList.add(serverClass);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(error => {
|
|
|
|
|
console.error('Fehler beim Abrufen des Autoren-Profils:', error);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
console.error('Ungültiger Benutzer-Handle in URL:', url.href);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Fehler bei der Verarbeitung der URL:', error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const accounts = kit.querySelectorAll('.account');
|
|
|
|
|
accounts.forEach(account => {
|
|
|
|
|
const parent = account.closest('.autor');
|
|
|
|
|
if (!parent) {
|
|
|
|
|
account.style.display = 'none';
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Zeige die Anzahl der Accounts auf der StarterKit-Kachel
|
|
|
|
|
const accountCount = kit.querySelectorAll('.account:not(.autor .account)').length;
|
|
|
|
|
const accountCountElement = document.createElement('div');
|
|
|
|
|
accountCountElement.classList.add('account-count');
|
|
|
|
|
accountCountElement.textContent = `${accountCount} Profile`;
|
|
|
|
|
kit.appendChild(accountCountElement);
|
|
|
|
|
|
|
|
|
|
// Füge Event-Listener für StarterKit-Kacheln hinzu
|
|
|
|
|
kit.addEventListener('click', function() {
|
|
|
|
|
const title = kit.querySelector('h3').textContent;
|
|
|
|
|
const accountsForPopup = Array.from(kit.querySelectorAll('.account')).filter(account => !account.closest('.autor'));
|
|
|
|
|
const popup = createRecommendationPopup(accountsForPopup, title);
|
|
|
|
|
document.body.appendChild(popup);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
2024-12-08 08:58:41 +01:00
|
|
|
|
|
2024-12-08 22:48:40 +01:00
|
|
|
|
/**
|
|
|
|
|
* Funktion zum Erstellen eines Pop-ups.
|
|
|
|
|
* @param {NodeList} accounts - Die Liste der Accounts für das Pop-up.
|
|
|
|
|
* @param {string} title - Der Titel des StarterKits.
|
|
|
|
|
* @returns {HTMLElement} - Das erzeugte Pop-up-Element.
|
|
|
|
|
*/
|
|
|
|
|
function createRecommendationPopup(accounts, title) {
|
|
|
|
|
// Overlay erstellen
|
|
|
|
|
const overlay = document.createElement('div');
|
|
|
|
|
overlay.classList.add('recommendation-popup');
|
2024-12-08 08:58:41 +01:00
|
|
|
|
|
2024-12-08 22:48:40 +01:00
|
|
|
|
// Pop-up-Inhalt
|
|
|
|
|
const content = document.createElement('div');
|
|
|
|
|
content.classList.add('recommendation-popup-content');
|
2024-12-08 08:58:41 +01:00
|
|
|
|
|
2024-12-08 22:48:40 +01:00
|
|
|
|
// Header des Pop-ups
|
|
|
|
|
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()); // Schließen-Funktion
|
|
|
|
|
|
|
|
|
|
header.appendChild(titleElement);
|
|
|
|
|
header.appendChild(closeButton);
|
|
|
|
|
|
|
|
|
|
// Body des Pop-ups
|
|
|
|
|
const body = document.createElement('div');
|
|
|
|
|
body.classList.add('recommendation-popup-body');
|
|
|
|
|
|
|
|
|
|
accounts.forEach(account => {
|
2024-12-08 08:58:41 +01:00
|
|
|
|
try {
|
|
|
|
|
const url = new URL(account.getAttribute('href'));
|
|
|
|
|
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://${config.homeInstance}/api/v1/accounts/lookup?acct=${handle}@${instance}`;
|
|
|
|
|
|
|
|
|
|
fetch(lookupUrl)
|
|
|
|
|
.then(response => response.json())
|
|
|
|
|
.then(data => {
|
2024-12-08 22:48:40 +01:00
|
|
|
|
const card = createAccountCard(data, account.href, instance);
|
|
|
|
|
body.appendChild(card);
|
2024-12-08 08:58:41 +01:00
|
|
|
|
})
|
|
|
|
|
.catch(error => {
|
|
|
|
|
console.error('Fehler beim Abrufen des Profils:', error);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
console.error('Ungültiger Benutzer-Handle in URL:', url.href);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Fehler bei der Verarbeitung der URL:', error);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2024-12-08 22:48:40 +01:00
|
|
|
|
// Pop-up zusammenfügen
|
|
|
|
|
content.appendChild(header);
|
|
|
|
|
content.appendChild(body);
|
|
|
|
|
overlay.appendChild(content);
|
2024-12-08 08:58:41 +01:00
|
|
|
|
|
2024-12-08 22:48:40 +01:00
|
|
|
|
// Event-Listener für Overlay (schließt Pop-up bei Klick auf Hintergrund)
|
|
|
|
|
overlay.addEventListener('click', function(event) {
|
|
|
|
|
if (event.target === overlay) {
|
2024-12-08 08:58:41 +01:00
|
|
|
|
overlay.remove();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2024-12-08 22:48:40 +01:00
|
|
|
|
return overlay;
|
|
|
|
|
}
|
2024-12-08 08:58:41 +01:00
|
|
|
|
|
2024-12-08 22:48:40 +01:00
|
|
|
|
/**
|
|
|
|
|
* Funktion zum Erstellen einer Account-Kachel.
|
|
|
|
|
* @param {Object} data - Die Account-Daten von der API.
|
|
|
|
|
* @param {string} href - Die URL des Accounts.
|
|
|
|
|
* @param {string} instance - Der Instanz-Name.
|
|
|
|
|
* @returns {HTMLElement} - Die erzeugte 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);
|
2024-12-08 08:58:41 +01:00
|
|
|
|
}
|
|
|
|
|
|
2024-12-08 22:48:40 +01:00
|
|
|
|
handleElement.textContent = `@${data.username}`;
|
|
|
|
|
handleElement.appendChild(serverHandleElement);
|
|
|
|
|
|
|
|
|
|
infoContainer.appendChild(displayNameElement);
|
|
|
|
|
infoContainer.appendChild(handleElement);
|
2024-12-08 08:58:41 +01:00
|
|
|
|
|
2024-12-08 22:48:40 +01:00
|
|
|
|
card.appendChild(avatarImage);
|
|
|
|
|
card.appendChild(infoContainer);
|
|
|
|
|
link.appendChild(card);
|
2024-12-08 08:58:41 +01:00
|
|
|
|
|
2024-12-08 22:48:40 +01:00
|
|
|
|
return link;
|
2024-12-08 08:58:41 +01:00
|
|
|
|
}
|
|
|
|
|
|
2024-12-08 22:48:40 +01:00
|
|
|
|
/**
|
|
|
|
|
* Funktion, um die Kinder eines Containers deterministisch neu anzuordnen.
|
|
|
|
|
* @param {HTMLElement} container - Der Container, dessen Kinder durchmischt werden sollen.
|
|
|
|
|
* @param {number} seed - Der Seed für das deterministische Shuffle.
|
|
|
|
|
*/
|
|
|
|
|
function seededShuffleChildren(container, seed) {
|
|
|
|
|
const children = Array.from(container.children);
|
|
|
|
|
const shuffled = seededShuffle(children, seed);
|
|
|
|
|
shuffled.forEach(child => container.appendChild(child));
|
2024-12-08 08:58:41 +01:00
|
|
|
|
}
|
|
|
|
|
|
2024-12-08 22:48:40 +01:00
|
|
|
|
/**
|
|
|
|
|
* Funktion für einen deterministischen Shuffle-Algorithmus.
|
|
|
|
|
* @param {Array} array - Das Array, das gemischt werden soll.
|
|
|
|
|
* @param {number} seed - Der Seed für das deterministische Shuffle.
|
|
|
|
|
* @returns {Array} - Das gemischte Array.
|
|
|
|
|
*/
|
2024-12-08 08:58:41 +01:00
|
|
|
|
function seededShuffle(array, seed) {
|
|
|
|
|
for (let i = array.length - 1; i > 0; i--) {
|
2024-12-08 22:48:40 +01:00
|
|
|
|
const j = Math.floor(seededRandom(seed++) * (i + 1));
|
2024-12-08 08:58:41 +01:00
|
|
|
|
[array[i], array[j]] = [array[j], array[i]];
|
|
|
|
|
}
|
|
|
|
|
return array;
|
|
|
|
|
}
|
2024-12-08 22:48:40 +01:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Funktion für einen deterministischen Zufallswert.
|
|
|
|
|
* @param {number} seed - Der Seed für den Zufallswert.
|
|
|
|
|
* @returns {number} - Der generierte Zufallswert.
|
|
|
|
|
*/
|
|
|
|
|
function seededRandom(seed) {
|
|
|
|
|
const x = Math.sin(seed++) * 10000;
|
|
|
|
|
return x - Math.floor(x);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Funktion zur Zuordnung von Instanzen zu CSS-Klassen.
|
|
|
|
|
* @param {string} instance - Der Name der Instanz.
|
|
|
|
|
* @returns {string|null} - Die zugehörige CSS-Klasse oder null, wenn keine Übereinstimmung vorliegt.
|
|
|
|
|
*/
|
|
|
|
|
function getServerClass(instance) {
|
|
|
|
|
const serverClasses = {
|
|
|
|
|
'libori.social': 'liboriSocial',
|
|
|
|
|
'reliverse.social': 'reliverseSocial',
|
|
|
|
|
'kirche.social': 'kircheSocial',
|
|
|
|
|
'katholisch.social': 'katholischSocial'
|
|
|
|
|
};
|
|
|
|
|
return serverClasses[instance] || null;
|
|
|
|
|
}
|