mirror of
https://github.com/svemagie/indiekit-endpoint-activitypub.git
synced 2026-04-02 15:44:58 +02:00
fix: use async iteration for Fedify 2.0 attachments/tags, add image lightbox
Fedify 2.0's getAttachments() and getTags() return async iterables, but the code used synchronous for...of which silently yielded zero results. Changed to for await...of so media URLs (photo/video/audio) and hashtags are now properly extracted from incoming posts. Also replaced the gallery's target=_blank links with an Alpine.js lightbox modal for full-size image viewing with prev/next navigation and keyboard support.
This commit is contained in:
@@ -457,7 +457,12 @@
|
||||
}
|
||||
|
||||
.ap-card__gallery-link {
|
||||
appearance: none;
|
||||
background: none;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@@ -522,6 +527,83 @@
|
||||
grid-template-rows: 1fr 1fr;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Photo Lightbox
|
||||
========================================================================== */
|
||||
|
||||
[x-cloak] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.ap-lightbox {
|
||||
align-items: center;
|
||||
background: rgba(0, 0, 0, 0.92);
|
||||
display: flex;
|
||||
inset: 0;
|
||||
justify-content: center;
|
||||
position: fixed;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.ap-lightbox__img {
|
||||
max-height: 90vh;
|
||||
max-width: 95vw;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.ap-lightbox__close {
|
||||
background: none;
|
||||
border: 0;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
font-size: 2rem;
|
||||
line-height: 1;
|
||||
padding: var(--space-s);
|
||||
position: absolute;
|
||||
right: var(--space-m);
|
||||
top: var(--space-m);
|
||||
}
|
||||
|
||||
.ap-lightbox__close:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.ap-lightbox__prev,
|
||||
.ap-lightbox__next {
|
||||
background: none;
|
||||
border: 0;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
font-size: 3rem;
|
||||
line-height: 1;
|
||||
padding: var(--space-m);
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.ap-lightbox__prev {
|
||||
left: var(--space-s);
|
||||
}
|
||||
|
||||
.ap-lightbox__next {
|
||||
right: var(--space-s);
|
||||
}
|
||||
|
||||
.ap-lightbox__prev:hover,
|
||||
.ap-lightbox__next:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.ap-lightbox__counter {
|
||||
bottom: var(--space-m);
|
||||
color: white;
|
||||
font-size: var(--font-size-s);
|
||||
left: 50%;
|
||||
position: absolute;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Video Embed
|
||||
========================================================================== */
|
||||
|
||||
@@ -185,7 +185,7 @@ export async function extractObjectData(object, options = {}) {
|
||||
try {
|
||||
if (typeof object.getTags === "function") {
|
||||
const tags = await object.getTags();
|
||||
for (const tag of tags) {
|
||||
for await (const tag of tags) {
|
||||
if (tag.name) {
|
||||
const tagName = tag.name.toString().replace(/^#/, "");
|
||||
if (tagName) category.push(tagName);
|
||||
@@ -204,7 +204,7 @@ export async function extractObjectData(object, options = {}) {
|
||||
try {
|
||||
if (typeof object.getAttachments === "function") {
|
||||
const attachments = await object.getAttachments();
|
||||
for (const att of attachments) {
|
||||
for await (const att of attachments) {
|
||||
const mediaUrl = att.url?.href || "";
|
||||
if (!mediaUrl) continue;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@rmdes/indiekit-endpoint-activitypub",
|
||||
"version": "2.0.16",
|
||||
"version": "2.0.17",
|
||||
"description": "ActivityPub federation endpoint for Indiekit via Fedify. Adds full fediverse support: actor, inbox, outbox, followers, following, syndication, and Mastodon migration.",
|
||||
"keywords": [
|
||||
"indiekit",
|
||||
|
||||
@@ -1,20 +1,36 @@
|
||||
{# Media attachments partial — included from ap-item-card.njk #}
|
||||
|
||||
{# Photo gallery #}
|
||||
{# Photo gallery with lightbox #}
|
||||
{% if item.photo and item.photo.length > 0 %}
|
||||
{% set displayCount = [item.photo.length, 4] | min %}
|
||||
{% set extraCount = item.photo.length - 4 %}
|
||||
<div class="ap-card__gallery ap-card__gallery--{{ displayCount }}">
|
||||
{% set totalPhotos = item.photo.length %}
|
||||
<div x-data="{ lightbox: false, idx: 0 }" class="ap-card__gallery ap-card__gallery--{{ displayCount }}">
|
||||
{% for photoUrl in item.photo %}
|
||||
{% if loop.index0 < 4 %}
|
||||
<a href="{{ photoUrl }}" target="_blank" rel="noopener" class="ap-card__gallery-link{% if loop.index0 == 3 and extraCount > 0 %} ap-card__gallery-link--more{% endif %}">
|
||||
<button type="button" @click="idx = {{ loop.index0 }}; lightbox = true" class="ap-card__gallery-link{% if loop.index0 == 3 and extraCount > 0 %} ap-card__gallery-link--more{% endif %}">
|
||||
<img src="{{ photoUrl }}" alt="" loading="lazy">
|
||||
{% if loop.index0 == 3 and extraCount > 0 %}
|
||||
<span class="ap-card__gallery-more">+{{ extraCount }}</span>
|
||||
{% endif %}
|
||||
</a>
|
||||
</button>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{# Lightbox modal — teleported to body to prevent overflow clipping #}
|
||||
<template x-teleport="body">
|
||||
<div x-show="lightbox" x-cloak @keydown.escape.window="lightbox = false" @click.self="lightbox = false" class="ap-lightbox" role="dialog" aria-modal="true">
|
||||
<button type="button" @click="lightbox = false" class="ap-lightbox__close" aria-label="Close">×</button>
|
||||
{% if totalPhotos > 1 %}
|
||||
<button type="button" @click="idx = (idx - 1 + {{ totalPhotos }}) % {{ totalPhotos }}" class="ap-lightbox__prev" aria-label="Previous image">‹</button>
|
||||
{% endif %}
|
||||
<img :src="[{% for p in item.photo %}'{{ p }}'{% if not loop.last %},{% endif %}{% endfor %}][idx]" class="ap-lightbox__img" alt="">
|
||||
{% if totalPhotos > 1 %}
|
||||
<button type="button" @click="idx = (idx + 1) % {{ totalPhotos }}" class="ap-lightbox__next" aria-label="Next image">›</button>
|
||||
<div class="ap-lightbox__counter" x-text="(idx + 1) + ' / ' + {{ totalPhotos }}"></div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user