source: Klonkt/src/views/pages/home.ejs@ bfa6fa1

main
Last change on this file since bfa6fa1 was bfa6fa1, checked in by Robin <roboburr@…>, 6 weeks ago

Account-verhuizingen slice 3: het wegwijsbord (movedTo + homepage-link)

Het sluitstuk van shaer-0j2's federatiekant. De oude Klonkt blijft
staan en ZEGT waar hij heen ging, op twee plekken.

Voor servers: het actor-document draagt movedTo zodra moved_to gezet is
(FEP-7628: een verhuisd account moet dat publiceren en geldt als
inactief). Dat is precies waarom de oude actor online blijft: wie de
Move-activity miste (server offline, latere bezoeker) leert de
verhuizing alsnog door ons op te halen. Een kolomwaarde die geen URL is
haalt de draad nooit.

Voor mensen: de homepage opent met een groot wegwijsbord boven de feed,
met de handle van het nieuwe adres als grote link. Boven de posts met
opzet: niemand hoort een dode tijdlijn door te scrollen om te ontdekken
dat we weg zijn.

En de verhuizing zelf vertelt het nu twee keer: naast de Move gaat er
een Update van de actor naar elke volger-inbox, gebouwd uit de VERSE
rij, zodat het bord ook staat als de Move onderweg verdwijnt (FEP-7628
SHOULD).

Changed files:
src/services/ActivityPubService.js

  • buildActor: movedTo bij een geldige moved_to
  • moveAccount: Update(actor) naast de Move, per inbox

src/routes/posts.js

  • home: movedTo + leesbaar label (actorDisplay) naar de view

src/views/pages/home.ejs

  • wegwijsbord boven de feed, typeof-guard voor deploy-races

src/assets/css/style.css

  • .moved-banner: accentrand, grote link, tekst breekt netjes af

src/services/i18n.js

  • phome.moved_lead/_hint in nl/en/de

test/move-actor.test.js

  • movedTo aan/uit/rommel; Update draagt het bord naast de Move
  • slice-2-test telt nu Moves apart (Update rijdt mee)

remarks: banner visueel gecontroleerd (mobiel en desktop) door het echte
templateblok met de echte CSS te renderen; suite 372 groen.

-robo
Co-Authored-By: Claude Opus 4.8 <noreply@…>

  • Property mode set to 100644
File size: 3.0 KB
Line 
1<%
2// Homepage — feed of posts.
3//
4// Renders BOTH a timeline view (.post-list, default) AND a grid view
5// (.feed-grid, square Instagram-style tiles). CSS toggles between the
6// two based on body[data-feed-view="timeline"|"grid"]. This mirrors the
7// v9 pattern in lib/template-content.php so the same view-switcher works.
8//
9// Pinned posts sort first inside the timeline list; they are not given a
10// separate "Pinned" header (v9 just lets order speak for itself + a ★ chip).
11
12const allPosts = [...pinnedPosts, ...posts];
13const _base = (typeof siteUrlBase !== 'undefined' && siteUrlBase) ? siteUrlBase : '';
14%>
15
16<%# View switcher used to be rendered here; moved to shell.ejs (above
17 #pcms-main) so it survives HTMX swaps and is visible on every
18 non-admin page. %>
19
20<%# FEP-7628 slice 3: this account moved. The signpost comes FIRST, before
21 any post: a visitor should not scroll a dead feed to find out we left.
22 typeof-guard because an old route may render this template for one
23 request right after a deploy (view cache fills on first hit). %>
24<% if (typeof movedTo !== 'undefined' && movedTo) { %>
25 <div class="container">
26 <aside class="moved-banner">
27 <p class="moved-banner-lead"><%= t('phome.moved_lead') %></p>
28 <a class="moved-banner-link" href="<%= movedTo %>" rel="me noopener"><%= movedToLabel || movedTo %></a>
29 <p class="moved-banner-hint"><%= t('phome.moved_hint') %></p>
30 </aside>
31 </div>
32<% } %>
33
34<!-- ========== TIMELINE ========== -->
35<div class="container feed-timeline">
36
37 <% if (allPosts.length === 0) { %>
38 <div class="empty">
39 <h1><%= t('phome.empty_title') %></h1>
40 <p><%= t('phome.empty_sub') %></p>
41 <% if (user && canMutate && permissions.canCreatePost(user, site)) { %>
42 <p style="margin-top:2rem">
43 <a class="btn" href="<%= _base %>/posts/new"
44 hx-get="<%= _base %>/posts/new?partial=1" hx-target="#pcms-main" hx-swap="innerHTML"
45 hx-push-url="<%= _base %>/posts/new" hx-indicator="#pcms-loading">
46 <%= t('phome.write_first') %> →
47 </a>
48 </p>
49 <% } %>
50 </div>
51 <% } else { %>
52 <ul class="post-list feed-timeline-list" id="post-list">
53 <% allPosts.forEach(function(post) { %>
54 <%- include('../partials/post-card', { post: post }) %>
55 <% }); %>
56 </ul>
57 <% } %>
58
59</div>
60
61<!-- ========== GRID (only visible when body[data-feed-view="grid"]) ========== -->
62<% if (allPosts.length > 0) { %>
63<section class="feed-grid container" aria-label="<%= t('phome.grid_view') %>">
64 <div class="grid-tiles" id="grid-tiles">
65 <% allPosts.forEach(function(post) { %>
66 <%- include('../partials/post-tile', { post: post }) %>
67 <% }); %>
68 </div>
69</section>
70<% } %>
71<% if (typeof hasMore !== 'undefined' && allPosts.length > 0) { %>
72<div class="container feed-more-wrap">
73 <%- include('../partials/load-more', { hasMore: hasMore, nextOffset: nextOffset, moreBase: moreBase, moreTarget: '#post-list', morePath: '/' }) %>
74</div>
75<% } %>
Note: See TracBrowser for help on using the repository browser.