neue Section: Aktuelle Posts in #Fedikirche

This commit is contained in:
Alexander Müller 2024-12-28 15:17:57 +01:00
parent 9f79d15a91
commit 8ef7b1ba5e
5 changed files with 365 additions and 2 deletions

View file

@ -42,6 +42,15 @@
</div>
</section>
<section id="aktuell">
<div class="container">
<h2>Aktuelle Posts mit #FediKirche ✏️</h2>
</div>
<div class="posts full-width" id="postswall-container">
<!-- Posts will be loaded dynamically here -->
</div>
</section>
<section id="empfehlungen">
<div class="container">
<h2>Unsere StarterPacks für dich 🚀</h2>

141
src/components/postwall.js Normal file
View file

@ -0,0 +1,141 @@
export async function loadPostwall() {
const container = document.getElementById('postswall-container');
// Mastodon API-URL für Hashtag-Suche
const apiUrl = 'https://libori.social/api/v1/timelines/tag/fedikirche?limit=20';
// Posts laden
async function fetchPosts() {
try {
const response = await fetch(apiUrl);
if (!response.ok) {
throw new Error('Fehler beim Laden der Posts');
}
const posts = await response.json();
renderPosts(posts);
// Button hinzufügen
addReadMoreButton();
} catch (error) {
console.error('Fehler:', error);
container.innerHTML = '<p>Fehler beim Laden der Posts.</p>';
}
}
// Posts rendern
function renderPosts(posts) {
container.innerHTML = ''; // Vorherige Inhalte leeren
posts.forEach(post => {
const postElement = document.createElement('a');
postElement.classList.add('post');
postElement.href = post.url; // Link zum Originalpost
postElement.target = '_blank'; // Link in neuem Tab öffnen
postElement.rel = 'noopener noreferrer'; // Sicherheit für externe Links
postElement.setAttribute('aria-label', 'Zum Originalpost auf Mastodon'); // Accessibility
// Zeitstempel berechnen
const postDate = new Date(post.created_at); // Datum des Posts
const timeAgo = getTimeAgo(postDate); // Funktion zur Berechnung der Zeitspanne
let content = post.content || 'Kein Inhalt verfügbar.';
const author = post.account.display_name || post.account.username;
const username = `@${post.account.acct}`; // Adresse hinzufügen (@nutzer@instanz)
const avatar = post.account.avatar || 'src/assets/default-avatar.png'; // Fallback-Bild
// Alle anderen Links deaktivieren
const tempContainer = document.createElement('div');
tempContainer.innerHTML = content;
// Links deaktivieren
const links = tempContainer.querySelectorAll('a');
links.forEach(link => {
link.removeAttribute('href'); // Entfernt den Link
link.style.pointerEvents = 'none'; // Deaktiviert Klickbarkeit
link.style.color = 'blue'; // Behält Linkfarbe bei
link.style.textDecoration = 'underline'; // Behält Unterstreichung bei
});
// Bilder bearbeiten
const images = tempContainer.querySelectorAll('img');
images.forEach(img => {
img.style.maxHeight = '200px'; // Maximale Höhe festlegen
img.style.width = 'auto'; // Automatische Breite für Proportionen
img.style.display = 'block'; // Sicherstellen, dass Bilder Blöcke sind
img.style.margin = '10px 0'; // Abstand zu Text einfügen
});
content = tempContainer.innerHTML;
// Medien-Anhänge (Bilder, Videos, etc.) hinzufügen
const mediaAttachments = post.media_attachments || [];
let mediaHTML = '';
mediaAttachments.forEach(media => {
if (media.type === 'image') {
mediaHTML += `
<img src="${media.url}" alt="Medienanhang" style="max-height: 200px; width: auto; display: block; margin: 10px 0;">
`;
}
});
// Post zusammenbauen
postElement.innerHTML = `
<div class="post-header">
<img src="${avatar}" alt="${author}" class="avatar">
<div class="post-author">
<strong>${author}</strong><br>
<span class="post-username">${username}</span>
</div>
<span class="post-timestamp">${timeAgo}</span>
</div>
<div class="post-content">${content}</div>
<div class="post-media">${mediaHTML}</div>
<div class="post-footer"></div>
`;
container.appendChild(postElement);
});
}
// Lade die Posts
fetchPosts();
}
function getTimeAgo(date) {
const now = new Date();
const secondsAgo = Math.floor((now - date) / 1000);
if (secondsAgo < 60) {
// Weniger als 60 Sekunden
return `${secondsAgo} Sek.`;
} else if (secondsAgo < 3600) {
// Weniger als 60 Minuten
const minutes = Math.floor(secondsAgo / 60);
return `${minutes} Min.`;
} else if (secondsAgo < 86400) {
// Weniger als 24 Stunden
const hours = Math.floor(secondsAgo / 3600);
return `${hours} Std.`;
} else {
// Mehr als 24 Stunden (Tage zählen)
const days = Math.floor(secondsAgo / 86400);
return `${days} T.`;
}
}
// Funktion zum Erstellen des "Lese weiter"-Buttons
function addReadMoreButton() {
const container = document.getElementById('postswall-container');
// Button erstellen
const readMoreButton = document.createElement('a');
readMoreButton.href = 'https://libori.social/tags/fedikirche'; // Link zur Mastodon-Instanz mit Hashtag
readMoreButton.target = '_blank'; // Öffnet in neuem Tab
readMoreButton.rel = 'noopener noreferrer';
readMoreButton.classList.add('read-more-button'); // Klasse für CSS-Styling
readMoreButton.innerText = 'weiterlesen';
// Button zum Container hinzufügen
container.appendChild(readMoreButton);
}

View file

@ -1,6 +1,8 @@
import { createStarterKitElement, enhanceStarterKits } from './utils/starterkit-utils.js';
import { seededShuffleChildren } from './utils/shuffle-utils.js';
import { initializeCreateStarterKitPopup } from './utils/create-starterkit.js';
import { loadPostwall } from './components/postwall.js';
let userConsent = null;
export { userConsent };
@ -19,6 +21,9 @@ document.addEventListener('DOMContentLoaded', async function () {
initializeCreateStarterKitPopup();
// Lade die Postwall
loadPostwall();
const container = document.getElementById('starterkit-container');
const shuffleContainers = document.querySelectorAll('.shuffle-container');
const seed = Date.now();

View file

@ -4,6 +4,7 @@
@import "./starterkit.css";
@import "./recommendationPopup.css";
@import "./profile.css";
@import "./postwall.css";
@import "./media-query.css";
@import "./instances.css";
@import "./popup.css";

207
style/postwall.css Normal file
View file

@ -0,0 +1,207 @@
/* Allgemeine Einstellungen */
#aktuell {
background-color: #24242f;
padding: 0;
box-shadow: inset 0 0 15px rgba(0, 0, 0, 0.7);
}
#aktuell .container {
padding-bottom: 0;
}
.full-width {
width: 100vw;
overflow-x: hidden;
padding: 0;
}
/* Posts Container */
.posts {
display: flex;
gap: 20px;
overflow-x: auto;
scroll-behavior: smooth;
padding: 20px;
padding-bottom: 40px;
margin: 0 auto;
justify-content: flex-start;
scroll-snap-type: x mandatory;
scroll-padding: 40px;
}
/* Scrollbar */
.posts::-webkit-scrollbar {
height: 8px;
}
.posts::-webkit-scrollbar-thumb {
background-color: #888;
border-radius: 5px;
}
.posts::-webkit-scrollbar-thumb:hover {
background-color: #555;
}
.posts::-webkit-scrollbar-track {
background: #222;
}
/* Einzelner Post */
.post {
flex: 0 0 350px;
max-height: 300px;
background-color: var(--secondary-background-color);
border: 1px solid var(--secondary-background-color);
padding: 20px;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
scroll-snap-align: start;
transition: box-shadow 0.3s ease, background-color 0.3s ease;
text-align: left;
color: #fff;
position: relative;
overflow: hidden;
}
/* Header */
.post-header {
display: flex;
align-items: center;
gap: 10px;
position: relative;
}
.post-timestamp {
position: absolute;
top: 5px;
right: 5px;
font-size: 0.8rem;
color: #bbb;
font-weight: bold;
}
/* Autor-Informationen */
.post-author {
display: flex;
flex-direction: column;
}
.post-username {
font-size: 0.8em;
color: #bbb;
}
.avatar {
width: 40px;
height: 40px;
border-radius: 50%;
}
/* Inhalt */
.post-content {
overflow: hidden;
position: relative;
line-height: 1.4;
}
.post-content p {
margin: 15px 0;
font-size: 0.9rem;
}
/* Links innerhalb des Inhalts */
.post-content p a {
color: var(--link-color) !important;
text-decoration: none !important;
pointer-events: none; /* Links deaktivieren */
}
.post-content p a:hover {
text-decoration: underline !important;
color: #ddd !important;
}
/* Medien */
.post-media img {
max-width: 100%;
max-height: 150px;
object-fit: cover;
display: block;
margin: 10px 0;
border-radius: 5px;
transition: transform 0.3s ease-in-out;
}
.post-media img:hover {
transform: scale(1.1);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
}
/* Footer mit Verlauf und drei Punkten */
.post-footer {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 50px;
background: linear-gradient(to top, rgba(36, 36, 47, 1), rgba(36, 36, 47, 0));
text-align: center;
color: #bbb;
font-weight: bold;
font-size: 0.9rem;
padding-top: 15px;
pointer-events: none;
}
/* Hover-Effekt */
#aktuell .post:hover {
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.4);
border: 1px solid var(--primary-color-hover);
}
.read-more-button {
display: block;
text-align: center;
margin: 130px 130px 20px auto;
padding: 10px 20px;
background-color: var(--primary-color);
color: #fff;
font-size: 1rem;
font-weight: bold;
border-radius: 5px;
cursor: pointer;
text-decoration: none;
width: fit-content; /* Passt die Breite an den Text an */
height: fit-content;
transition: background-color 0.3s ease;
}
.read-more-button:hover {
background-color: var(--primary-color-hover);
transform: translateY(-2px);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
/* Responsives Verhalten */
@media (max-width: 800px) {
.post {
flex: 0 0 300px;
max-height: 350px;
}
.post-header .avatar {
width: 30px;
height: 30px;
}
.post-username {
font-size: 0.8em;
}
.post-media img {
max-height: 120px;
}
.post-footer {
height: 40px;
padding-top: 10px;
}
}