Commit Graph

153 Commits

Author SHA1 Message Date
svemagie
d0cb9a76aa Merge upstream rmdes:main — v2.11.0, v2.12.0, v2.12.1 into svemagie/main (v2.12.2)
Integrates upstream features (visibility/CW compose controls, @mention
support, federation management page, layout fix) while preserving
svemagie DM support. Visibility and syndication controls are hidden
for direct messages.
2026-03-15 19:25:54 +01:00
Ricardo
6707450079 fix: federation-mgmt extends ap-reader.njk layout for proper CSS loading (v2.12.1)
Confab-Link: http://localhost:8080/sessions/c2335791-4b8c-44a6-b1b7-8d0fa8d7f647
2026-03-15 17:27:27 +01:00
Ricardo
19aa83ab8d feat: federation management page with collection stats, post actions, object lookup (v2.12.0)
Confab-Link: http://localhost:8080/sessions/c2335791-4b8c-44a6-b1b7-8d0fa8d7f647
2026-03-15 16:32:14 +01:00
Ricardo
6238e7d4e5 feat: visibility/CW compose controls, @mention support (v2.11.0)
Add visibility and content warning controls to the reply compose form.
Add @user@domain mention parsing, WebFinger resolution, Mention tags,
inbox delivery, and content linkification for outbound posts.

Confab-Link: http://localhost:8080/sessions/cc343b15-8d10-43cd-a48f-ca912eb79b83
2026-03-14 21:28:24 +01:00
Sven Giersig
eefa46f0c1 Merge upstream rmdes:main — v2.10.0 (Delete, visibility, CW, polls, Flag) into svemagie/main (v2.10.1)
Upstream v2.10.0 adds: outbound Delete, visibility addressing (unlisted/
followers-only), Content Warning (sensitive flag + summary), inbound poll
rendering, Flag/report handler, DM support files.

Conflict resolution — all four conflicts were additive (no code removed):

  lib/controllers/reader.js: union of validTabs — fork added "mention",
    upstream added "dm" and "report"; result keeps all five additions.

  lib/storage/notifications.js: union of count keys — fork added mention:0,
    upstream added dm:0 and report:0; result keeps the fork's mention split
    logic alongside the new upstream keys.

  views/partials/ap-notification-card.njk: fork kept isDirect 🔒 badge for
    direct mentions; upstream added ✉ for dm and ⚑ for report; result keeps
    the isDirect branch and appends the two new type badges.

  package.json: upstream bumped to 2.10.0; we bump to 2.10.1 to reflect our
    own Alpine.js and publication-aware docloader bug fixes on top.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 13:00:58 +01:00
Sven Giersig
b8e0beb5a3 fix: load Alpine.js in reader layout and allow private addresses for own host in author resolution (v2.9.2)
- views/layouts/ap-reader.njk: Replace incorrect comment "Alpine.js
  loaded by default.njk" with an actual Alpine.js CDN script tag.
  Without this, all Alpine directives on the remote-profile page
  (x-data, @click, x-text, :class) were dead — Follow/Mute/Block
  buttons showed no label and clicks did nothing.

- lib/resolve-author.js: Add createPublicationAwareDocumentLoader()
  which wraps the authenticated Fedify document loader to opt in to
  allowPrivateAddress for requests to the publication's own hostname.
  Fedify blocks private IP ranges by default; self-hosted instances
  (localhost / private IPs) were failing author resolution for their
  own posts with a private-address error. All three lookupObject calls
  in resolveAuthor() now use the wrapped loader.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 12:57:30 +01:00
Ricardo
1dc42ad5e5 feat: outbound Delete, visibility addressing, CW/sensitive, polls, Flag reports (v2.10.0)
- Outbound Delete: broadcastDelete() + POST /admin/federation/delete route
- Visibility: unlisted + followers-only addressing via defaultVisibility config
- Content Warning: outbound sensitive flag + summary as CW text
- Polls: inbound Question/poll parsing with progress bar rendering
- Flag: inbound report handler with ap_reports collection + Reports tab
- Includes DM support files from v2.9.x (messages controller, storage, templates)
- Includes coverage audit and high-impact gaps implementation plan

Confab-Link: http://localhost:8080/sessions/cc343b15-8d10-43cd-a48f-ca912eb79b83
2026-03-14 08:51:44 +01:00
svemagie
5806133dff Merge branch 'rmdes:main' into main 2026-03-13 18:51:10 +01:00
Ricardo
a266b6d9ba fix: render compose reply context with card content styling (v2.8.2)
The reply context on the compose page rendered raw Mastodon HTML in a
bare <blockquote>, causing hashtag links to display as block elements
(each on its own line with # separated from the tag name). Wrapping
the content in a <div class="ap-card__content"> applies the same
inline hashtag/mention/invisible-span CSS rules used in the timeline.

Confab-Link: http://localhost:8080/sessions/cc343b15-8d10-43cd-a48f-ca912eb79b83
2026-03-13 14:37:40 +01:00
Ricardo
bf386e0c41 chore: phase 2 convention alignment — onerror/onclick removal, CSS stacking avatar fallback (v2.8.1)
- Replace inline onerror handlers with CSS stacking + event delegation for avatar fallback
- Replace inline onclick with event delegation for profile link removal
- Replace hardcoded border values with design tokens in reader-links.css
- Add data-avatar-fallback pattern: fallback initials always visible, img layered on top

Confab-Link: http://localhost:8080/sessions/bb4a6ec4-b711-48cd-b3d7-942ec2a9851d
2026-03-13 12:32:14 +01:00
svemagie
0acd324070 fix: normalize aliasUrl to absolute URL before storing alsoKnownAs
Without https://, jsonld rejects the value as a relative object
reference during signature verification, breaking Mastodon migration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 08:24:41 +01:00
svemagie
a5223437b8 feat: add getDirectConversations to notifications storage
Groups ap_notifications with isDirect:true by peer actor and returns
them as conversation objects shaped for the DM reader tab template.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 08:12:54 +01:00
svemagie
39d45ec04e feat: integrate docloader loglevel, unlisted guards, alias-clear, likePost/boostPost
federation-setup.js:
- Suppress fedify docloader logs below fatal level to reduce noise from
  deleted remote actors (404/410)
- Add visibility:unlisted guard to outbox dispatcher, counter, and
  resolvePost object dispatcher

controllers/migrate.js:
- Allow clearing alsoKnownAs by detecting submitted empty aliasUrl field
  via hasOwnProperty check (previously only set when non-empty)

index.js:
- Add resolveAuthor import
- Skip federation for unlisted posts in syndicate()
- Add likePost(postUrl, collections) — sends AP Like activity to author
- Add boostPost(postUrl, collections) — sends AP Announce to followers
  and directly to the post author's inbox

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 08:08:23 +01:00
svemagie
445aab5632 fix: serve like/repost posts as Note for AP content negotiation
Returning a bare Like/Announce activity breaks Mastodon's
authorize_interaction flow because it expects a content object
(Note/Article). Serve as Note with emoji + linked URL instead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 07:49:50 +01:00
svemagie
8129b87382 feat: add Direct Messages tab to reader view 2026-03-13 07:36:18 +01:00
svemagie
364c41cba7 feat: add Direct Messages tab to reader view 2026-03-13 07:36:09 +01:00
svemagie
1b2554618e docs: document DM threading, getTags() fix, and outbound storage 2026-03-13 07:31:52 +01:00
svemagie
2fc85474a5 feat: add ap-dm-thread.njk chat-style conversation partial 2026-03-13 07:27:13 +01:00
svemagie
bf6262e2c6 feat: render DM conversations as threaded view on mention tab 2026-03-13 07:27:12 +01:00
svemagie
51a8abb0a2 feat: use getDirectConversations() for mention tab; pass conversations to template 2026-03-13 07:26:49 +01:00
svemagie
ba144da14c feat: store outbound DMs in ap_notifications for threading; redirect to ?tab=mention 2026-03-13 07:26:25 +01:00
svemagie
8d2dc3a05a fix: use ctx.lookupObject for DM recipient instead of resolveAuthor (actor URL, not post URL) 2026-03-13 07:12:19 +01:00
svemagie
4b4faea52f fix: use getTags() async iterator and instanceof checks for Mention/Hashtag 2026-03-13 06:59:27 +01:00
svemagie
e18d61d951 docs: update README for svemagie fork with DM support 2026-03-13 06:46:34 +01:00
svemagie
ea9a9856e9 feat: direct message (DM) receive and reply support
- Detect incoming DM visibility in inbox listener by checking absence of
  the public collection URL in object.toIds/ccIds; store isDirect and
  senderActorUrl on mention notifications
- Add native AP reply path in compose controller: when is-direct=true,
  build Create(Note) addressed only to the sender and deliver via
  ctx.sendActivity() instead of posting a public Micropub blog reply
- Add dedicated "Direct" tab to notifications view (separate from Replies)
  with its own count; update storage query so mention tab filters only
  mention type, reply tab filters only reply type
- Show lock badge (🔒) on direct mention notification cards and add
  ap-notification--direct CSS class
- Compose view: show DM notice banner, hide syndication targets, and
  change submit label when replying to a direct message

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 06:32:50 +01:00
Ricardo
1c2fb321bc feat: image rendering, link preview CSS, lightbox swipe, URL linkification (v2.8.0)
- Gallery photos: 220px → 280px height, 180px on mobile (≤480px)
- Link preview cards: full CSS for horizontal card layout (text left, image right)
- Lightbox: touch/swipe support for mobile (50px threshold)
- URL linkification: bare URLs in content auto-wrapped in <a> tags before AP delivery

Confab-Link: http://localhost:8080/sessions/c5b1471e-b046-44d9-b94f-ab5e68fae7cc
2026-03-06 10:42:39 +01:00
Ricardo
2083741535 fix: use human-readable URLs for reply-to links (v2.7.1)
Reply links were using the AP internal object ID (e.g.
/ap/users/{id}/statuses/{id}) which returns 404 on Mastodon for
browsers. Now uses the human-readable URL (/@username/{id}) for
replyTo params in item cards and notification cards.

- Store url field on reply/mention notifications (inbox-listeners)
- Prefer item.url over item.uid for compose replyTo links
- Falls back to uid for existing notifications without url field

Confab-Link: http://localhost:8080/sessions/d116ad5b-ef8a-424e-9ebe-76c06bef1df6
2026-03-05 08:24:08 +01:00
Ricardo
7611dba40f feat: remove quick reply, streamline blog reply (v2.7.0)
Remove the quick-reply code path entirely — all replies now go through
Micropub as blog posts. Quick replies created orphan URLs that served
raw JSON-LD to browsers and caused unreadable links in conversations.

- Delete quick-reply controller (note-object.js) and route
- Remove ap_notes collection registration
- Simplify compose form: no mode toggle, no character counter
- Remove quick-reply CSS and locale strings

Confab-Link: http://localhost:8080/sessions/d116ad5b-ef8a-424e-9ebe-76c06bef1df6
2026-03-04 17:33:02 +01:00
Ricardo
ec41fec366 fix: dark mode color comfort — use adaptive tokens, add dark overrides
Replace undefined --color-accent/--color-neutral-lighter with Indiekit tokens.
Swap --color-primary to --color-primary-on-background for all text/links.
Swap --color-red45 to --color-error in danger contexts (auto dark adapt).
Add @media (prefers-color-scheme: dark) block: softer action button colors
(red80, green90), pastel post-type borders, toned-down notification glow,
softened post detail highlight, light-tinted card shadows.

Confab-Link: http://localhost:8080/sessions/e9d666ac-3c90-4298-9e92-9ac9d142bc06
2026-03-03 20:51:14 +01:00
Ricardo
9332421890 feat: visual polish, focus-point cropping, blurhash placeholders (Release 8)
Card styling: softer 8px radius, subtle box-shadow elevation, hover enhancement.
Action buttons: borderless with color-coded hover states via color-mix().
Typography: tighter line-height (4/3), larger avatars (44px), gallery images (220px).
Focus-point cropping: convert Mastodon focus.x/y to CSS object-position.
Blurhash placeholders: decode DC component to background-color on images.

Confab-Link: http://localhost:8080/sessions/e9d666ac-3c90-4298-9e92-9ac9d142bc06
2026-03-03 19:26:38 +01:00
Ricardo
b9fc98f40c feat: content enhancements — URL shortening, hashtag collapse, bot badge, edit indicator (Release 7)
Shorten long URLs in post content (30 char display limit with tooltip).
Collapse hashtag-heavy paragraphs into expandable <details> toggle.
Show BOT badge for Service/Application actors. Show pencil icon for
edited posts with hover tooltip showing edit timestamp.

Confab-Link: http://localhost:8080/sessions/e9d666ac-3c90-4298-9e92-9ac9d142bc06
2026-03-03 16:40:01 +01:00
Ricardo
fca1738bd3 feat: skeleton loaders replace loading text (Release 6)
Animated card-shaped placeholders with shimmer effect shown during
content loading instead of plain "Loading..." text. Applied to reader,
tag timeline, and explore tabs (both first-load and load-more states).

Confab-Link: http://localhost:8080/sessions/e9d666ac-3c90-4298-9e92-9ac9d142bc06
2026-03-03 15:48:59 +01:00
Ricardo
2d2dcaec7d feat: interaction counts on timeline cards (Release 5)
Extract reply/boost/like counts from AP Collections (getReplies,
getLikes, getShares) and Mastodon API (replies_count, reblogs_count,
favourites_count). Display counts next to interaction buttons with
optimistic updates on like/boost actions.

Confab-Link: http://localhost:8080/sessions/e9d666ac-3c90-4298-9e92-9ac9d142bc06
2026-03-03 14:30:40 +01:00
Ricardo
c243b70629 feat: enriched media model with ALT badges (Release 3+4)
Change photo storage from bare URL strings to objects with url, alt,
width, height (AP) plus blurhash and focus (Mastodon API). Templates
handle both old string and new object format for backward compat.

Add ALT text badges on gallery images — click to expand the full
alt text in an overlay. Renders in both reader and explore views.

Also pass alt text through to lightbox and quote embed photos.

Bump version to 2.5.3.

Confab-Link: http://localhost:8080/sessions/e9d666ac-3c90-4298-9e92-9ac9d142bc06
2026-03-03 13:46:58 +01:00
Ricardo
e34d9c124d feat: relative timestamps in reader (Release 2)
Add Alpine.js directive x-relative-time that converts absolute dates
to human-friendly relative strings: just now, 5m, 3h, 2d, Mar 3.
Updates every 60s for posts less than 24h old. Server-rendered absolute
time stays as no-JS fallback and hover tooltip.

Applied to item cards, quote embeds, and notification cards.

Bump version to 2.5.2.

Confab-Link: http://localhost:8080/sessions/e9d666ac-3c90-4298-9e92-9ac9d142bc06
2026-03-03 13:34:01 +01:00
Ricardo
02d449d03c feat: render custom emoji in reader (Release 1)
Extract custom emoji from ActivityPub objects (Fedify Emoji tags) and
Mastodon API (status.emojis, account.emojis). Replace :shortcode:
patterns with <img> tags in the unified processing pipeline.

Emoji rendering applies to post content, author display names, boost
attribution, and quote embed authors. Uses the shared postProcessItems()
pipeline so both reader and explore views get emoji automatically.

Bump version to 2.5.1.

Confab-Link: http://localhost:8080/sessions/e9d666ac-3c90-4298-9e92-9ac9d142bc06
2026-03-03 13:13:28 +01:00
Ricardo
ab2363d123 docs: update CLAUDE.md and README.md for v2.5.0
Document unified item processing pipeline (gotcha #23), parameterized
infinite scroll component (gotcha #24), quote embeds (gotcha #25).
Update architecture tree with new modules and controllers. Expand
route table and admin UI pages with explore, tag timeline, post detail,
and API endpoints. Add reader features (explore, hashtags, quotes,
link previews, read tracking, infinite scroll) to README.

Confab-Link: http://localhost:8080/sessions/e9d666ac-3c90-4298-9e92-9ac9d142bc06
2026-03-03 13:03:48 +01:00
Ricardo
af2f899073 refactor: unify reader and explore processing pipeline (Release 0)
Extract shared item-processing.js module with postProcessItems(),
applyModerationFilters(), buildInteractionMap(), applyTabFilter(),
renderItemCards(), and loadModerationData(). All controllers (reader,
api-timeline, explore, hashtag-explore, tag-timeline) now flow through
the same pipeline.

Unify Alpine.js infinite scroll into single parameterized
apInfiniteScroll component configured via data attributes, replacing
the separate apExploreScroll component.

Also adds fetchAndStoreQuote() for quote enrichment and on-demand
quote fetching in post-detail controller.

Bump version to 2.5.0.

Confab-Link: http://localhost:8080/sessions/e9d666ac-3c90-4298-9e92-9ac9d142bc06
2026-03-03 12:48:40 +01:00
Ricardo
9fa3412875 fix: chain dropIndex before createIndex on ap_muted to prevent race condition
The non-async init() fired dropIndex and createIndex concurrently,
causing MongoDB to abort the index build (IndexBuildAborted error 276).
Chain createIndex via .then() so it runs after the drop completes.

Confab-Link: http://localhost:8080/sessions/e9d666ac-3c90-4298-9e92-9ac9d142bc06
2026-03-02 11:40:43 +01:00
Ricardo
76571b00ac chore: bump version to 2.4.0
Confab-Link: http://localhost:8080/sessions/e9d666ac-3c90-4298-9e92-9ac9d142bc06
2026-03-02 10:54:26 +01:00
Ricardo
508ac75363 feat: new posts banner, mark-as-read on scroll, unread filter
- Poll every 30s for new items, show sticky "N new posts — Load" banner
- IntersectionObserver marks cards as read at 50% visibility, batches to
  server every 5s
- Read cards fade to 70% opacity, full opacity on hover
- "Unread" toggle in tab bar filters to unread-only items
- New API: GET /api/timeline/count-new, POST /api/timeline/mark-read

Confab-Link: http://localhost:8080/sessions/e9d666ac-3c90-4298-9e92-9ac9d142bc06
2026-03-02 10:54:11 +01:00
Ricardo
68aadb6ff2 chore: bump version to 2.3.0
Confab-Link: http://localhost:8080/sessions/e9d666ac-3c90-4298-9e92-9ac9d142bc06
2026-03-02 10:33:20 +01:00
Ricardo
120f2ee00e feat: render quoted posts as embedded cards in reader
Extract quoteUrl from Fedify Note objects (supports Mastodon, Misskey,
Fedibird quote formats). Fetch quoted post data asynchronously on inbox
receive and on-demand in post detail view. Render as rich embed card
with author avatar, handle, content, and timestamp.

Confab-Link: http://localhost:8080/sessions/e9d666ac-3c90-4298-9e92-9ac9d142bc06
2026-03-02 10:33:11 +01:00
Ricardo
abf1b94bd6 feat: migrate Fedify KV store and plugin cache from MongoDB to Redis
Replace unbounded ap_kv MongoDB collection (169K docs, 49MB) with Redis:
- Fedify KV store uses @fedify/redis RedisKvStore (native TTL support)
- Plugin cache (fedidb, batch-refollow state, migration flags) uses new
  redis-cache.js utility with indiekit: key prefix
- All controllers updated to remove kvCollection parameter passing
- Addresses OOM kills caused by ap_kv growing ~14K entries/day
2026-03-01 16:26:17 +01:00
Ricardo
5c2fd09f8f fix: normalize category to array in my-profile controller
When a post has a single category, Indiekit stores it as a string
(e.g. "Fraude") rather than an array. Nunjucks iterates strings
character by character, producing hashtag pills like #F #r #a #u #d #e.
2026-02-28 18:21:32 +01:00
Ricardo
ecba2b5748 fix: pass CSRF token to API-rendered item cards
The explore and hashtag API controllers rendered ap-item-card.njk with
csrfToken: "" causing Like/Boost/Save buttons in tab panels to fail
with 403 Invalid CSRF token. Now generates a proper token from the
session via getToken().
2026-02-28 17:31:54 +01:00
Ricardo
35f1f13096 chore: bump version to 2.1.0 2026-02-28 16:51:06 +01:00
Ricardo
55baa7cef5 feat: replace explore deck layout with full-width tabbed design
Replace the cramped deck/column layout on the explore page with a
tabbed interface. Three tab types: Search (always first), Instance
(pinned with local/federated badge), and Hashtag (aggregated across
all pinned instances).

- New ap_explore_tabs collection replaces ap_decks (clean start)
- Tab CRUD API: add, remove, reorder with CSRF/SSRF validation
- Per-tab infinite scroll with IntersectionObserver + AbortController
- Hashtag tabs query up to 10 instances in parallel, merge by date,
  deduplicate by URL
- WAI-ARIA tabs pattern with arrow key navigation
- LRU cache (5 tabs) for tab content
- Extract shared explore-utils.js (validators + status mapping)
- Remove all old deck code (JS, CSS, controllers, locale strings)
2026-02-28 16:30:48 +01:00
Ricardo
f97e9a82f4 chore: remove dev plans from published repo
Plans moved to central /home/rick/code/indiekit-dev/docs/plans/
2026-02-27 17:18:30 +01:00
Ricardo
611bd3661c feat: add save-for-later button to activitypub reader
Adds a save button to the AP item card action bar that POSTs to
/readlater/save when the readlater plugin is installed. Uses Alpine.js
for optimistic UI update. Button only renders if
application.readlaterEndpoint is set.
2026-02-27 16:02:48 +01:00