- Timestamp:
- 08/20/2026 02:27:56 AM (3 weeks ago)
- Branches:
- main
- Children:
- 88838bc
- Parents:
- d8f8f07
- Location:
- src
- Files:
-
- 3 added
- 5 edited
-
assets/css/style.css (modified) (2 diffs)
-
assets/js/mod/read.js (modified) (2 diffs)
-
assets/js/vendor/lenis-LICENSE.txt (added)
-
assets/js/vendor/lenis-snap.mjs (added)
-
assets/js/vendor/lenis.mjs (added)
-
services/i18n.js (modified) (3 diffs)
-
views/partials/read-article.ejs (modified) (1 diff)
-
views/shell.ejs (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/assets/css/style.css
rd8f8f07 ra505f31 2587 2587 .feed-reader .read-head { padding-bottom: .5rem; } 2588 2588 .feed-reader .read-title { font-size: clamp(1.6rem, 4vw, 2.4rem); line-height: 1.15; margin: 0 0 .3rem; } 2589 /* Het pin-icoon voor de titel: meeschalend met de kop, maar duidelijk kleiner -- 2590 het is een markering en geen deel van de titel. */ 2591 .feed-reader .read-pin { 2592 display: inline-block; 2593 vertical-align: baseline; 2594 width: .62em; height: .62em; 2595 margin-right: .35em; 2596 color: var(--ink-muted); 2597 } 2598 .feed-reader .read-pin svg { width: 100%; height: 100%; display: block; } 2589 2599 /* De titel is een link, maar mag er niet als een link uitzien: dit is een 2590 2600 leesscherm, geen index. */ … … 2635 2645 @media (min-width: 768px) { 2636 2646 .read-top { bottom: 1.5rem; right: 1.5rem; } 2647 } 2648 /* Staat de mini-speler onderin, dan wijkt de knop daarvoor -- anders komt hij er 2649 bovenop te liggen (Robins schermafbeelding, 20-8). body.has-audio-player wordt 2650 door audio-player.js gezet zodra de speler zichtbaar is, en weer weggehaald 2651 als hij verdwijnt, dus dit volgt vanzelf. 2652 Op mobiel staat de speler BOVEN de tabbalk gestapeld, dus daar komt zijn 2653 hoogte bovenop de ruimte die er al gereserveerd was. */ 2654 body.has-audio-player .read-top { bottom: calc(env(safe-area-inset-bottom, 0) + 4.75rem + 4.25rem); } 2655 @media (min-width: 768px) { 2656 body.has-audio-player .read-top { bottom: calc(1.5rem + 4.25rem); } 2637 2657 } 2638 2658 @media (prefers-reduced-motion: reduce) { -
src/assets/js/mod/read.js
rd8f8f07 ra505f31 117 117 let rustTimer = null; 118 118 119 /** 120 * LENIS, en alleen op desktop. 121 * 122 * Op touch doet Lenis van zichzelf niets (syncTouch staat standaard uit) en is 123 * het systeem-scrollen al soepel -- daar blijft de native CSS-snap staan die 124 * hierboven beschreven is. Robins keuze (20-8): "enkel voor desktop, dat is 125 * prima, logisch dat het niet op mobiel kan". 126 * 127 * WAAROM LENIS HIER STAAT, en dat is niet het vloeiende scrollen: de DUUR van 128 * een snap is met native scroll-snap niet in te stellen -- die zit in de browser. 129 * Lenis' snap-pakket wel: duration, easing, distanceThreshold en debounce zijn 130 * allemaal van ons. Dat was de aanleiding. 131 * 132 * Het vloeiende scrollen (smoothWheel) kwam er daarna bij, en dat is de kant die 133 * OPPASSEN vraagt. Een Mac-trackpad heeft zijn EIGEN momentum, en Lenis' 134 * demping komt daar bovenop -- dubbel gedempt voelt drijverig. Vandaar lerp 0.2 135 * in plaats van de standaard 0.1. Robin vond dat op 20-8 nog steeds te zweverig, 136 * dus dat getal is nog niet uit; zie de opmerking bij de instellingen. 137 * 138 * De stand met `smoothWheel: false` werkte ook, en dan doet Lenis alleen de 139 * snap. Dat is de terugvalpositie als het vloeiende scrollen niet bevalt. 140 * 141 * lenis/snap haakt alleen in op lenis.on('scroll') en roept lenis.scrollTo aan 142 * (nagekeken in de dist), dus die opzet werkt. 143 */ 144 const OP_DESKTOP = window.matchMedia('(hover: hover) and (pointer: fine)'); 145 const VENDOR_V = 1; // ophogen als de bestanden in /assets/js/vendor wijzigen 146 147 let lenis = null; 148 let snap = null; 149 150 async function startLenis() { 151 if (lenis || !OP_DESKTOP.matches) return; 152 const [L, S] = await Promise.all([ 153 import(`/assets/js/vendor/lenis.mjs?v=${VENDOR_V}`), 154 import(`/assets/js/vendor/lenis-snap.mjs?v=${VENDOR_V}`), 155 ]); 156 lenis = new L.default({ 157 // Lenis tekent de scrollbeweging zelf, maar STEVIG GEDEMPT (lerp 0.2 in 158 // plaats van de standaard 0.1). Reden: een muiswiel scrollt in schokken en 159 // heeft die demping nodig; een Mac-trackpad heeft zijn EIGEN momentum en 160 // krijgt er dan een tweede overheen -- dat is precies het drijverige gevoel 161 // waar Robin voor waarschuwde. Hoger betekent korter naijlen, dus dit is de 162 // middenweg: de schokjes weg, de nasleep kort. 163 // Staat het toch te zweven, dan is lerp omhoog (richting 1) of terug naar 164 // smoothWheel:false de knop -- die stand werkte ook, met alleen de snap. 165 smoothWheel: true, 166 lerp: 0.2, 167 syncTouch: false, // op touch blijft alles van het systeem 168 autoRaf: true, 169 }); 170 snap = new S.default(lenis, { 171 type: 'proximity', 172 distanceThreshold: '12%', // de vangzone, hier WEL instelbaar 173 debounce: 60, // niet de standaard 500: dat voelt als te laat 174 duration: 0.4, // in totaal onder de halve seconde 175 // Vlot weg, dan steeds langzamer aankomen (Robin, 20-8). easeOutQuart: op de 176 // helft van de tijd is 94% van de weg af, en de rest dempt zacht uit. 177 // Bewust NIET Lenis' standaard easeOutExpo -- die schiet weg en kruipt dan 178 // zo lang na dat het lijkt of hij niet afmaakt. 179 easing: (t) => 1 - Math.pow(1 - t, 4), 180 }); 181 // Het snappunt is de bovenkant van elk bericht. Het laatste doet niet mee: 182 // zijn bovenkant is niet te bereiken, er zit te weinig pagina onder. 183 const berichten = [...document.querySelectorAll('.feed-reader .read-post')]; 184 berichten.slice(0, -1).forEach((a) => snap.addElement(a, { align: 'start' })); 185 // Native snappen uit: twee mechanismen op dezelfde scroller vechten. 186 document.documentElement.style.scrollSnapType = 'none'; 187 } 188 189 function stopLenis() { 190 if (snap) { snap.destroy(); snap = null; } 191 if (lenis) { lenis.destroy(); lenis = null; } 192 document.documentElement.style.scrollSnapType = ''; 193 } 194 195 /** 196 * Omhoog niet snappen. Met Lenis is dat snap.stop()/start(); zonder Lenis (dus 197 * op touch) zetten we de CSS-eigenschap om, precies zoals hiervoor. 198 */ 119 199 function zetSnappen(aan) { 200 if (snap) { if (aan) snap.start(); else snap.stop(); return; } 120 201 const el = document.documentElement; 121 202 const wil = aan ? '' : 'none'; … … 197 278 window.addEventListener('touchmove', opRaakBeweeg, { passive: true }); 198 279 window.addEventListener('keydown', opToets); 280 281 // Alleen in de leesweergave, en alleen op desktop. Bij elke init() opnieuw 282 // beoordelen: van Grid naar Lezen schakelen hoort hem aan te zetten, en 283 // wegnavigeren hoort hem op te ruimen. 284 stopLenis(); 285 if (document.body.dataset.feedView === 'reader') startLenis(); 199 286 } 200 287 -
src/services/i18n.js
rd8f8f07 ra505f31 33 33 'switch.solo': 'Solo', 34 34 'switch.circle': 'Cirkels', 35 'switch.grid': 'Grid', 'switch.reader': 'Lezen', 'switch.timeline': 'Tijdlijn', 'read.to_top': 'Terug naar boven', 35 'switch.grid': 'Grid', 'switch.reader': 'Lezen', 'switch.timeline': 'Tijdlijn', 'read.to_top': 'Terug naar boven', 'read.pinned': 'Vastgepind', 36 36 'asite.feed_alt': 'Tweede weergave', 'asite.feed_alt_reader': 'Lezen', 'asite.feed_alt_timeline': 'Tijdlijn', 'asite.feed_alt_auto': 'Lezen op mobiel, Tijdlijn op desktop', 37 37 'switch.reader_solo_only': 'Lezen kan alleen in Solo — in de cirkel staan berichten van anderen', … … 1049 1049 'switch.solo': 'Solo', 1050 1050 'switch.circle': 'Circles', 1051 'switch.grid': 'Grid', 'switch.reader': 'Reader', 'switch.timeline': 'Timeline', 'read.to_top': 'Back to top', 1051 'switch.grid': 'Grid', 'switch.reader': 'Reader', 'switch.timeline': 'Timeline', 'read.to_top': 'Back to top', 'read.pinned': 'Pinned', 1052 1052 'asite.feed_alt': 'Second view', 'asite.feed_alt_reader': 'Reader', 'asite.feed_alt_timeline': 'Timeline', 'asite.feed_alt_auto': 'Reader on mobile, Timeline on desktop', 1053 1053 'switch.reader_solo_only': 'Reader is Solo only — a circle shows other people\u2019s posts', … … 2056 2056 'switch.solo': 'Solo', 2057 2057 'switch.circle': 'Zirkel', 2058 'switch.grid': 'Raster', 'switch.reader': 'Lesen', 'switch.timeline': 'Zeitleiste', 'read.to_top': 'Nach oben', 2058 'switch.grid': 'Raster', 'switch.reader': 'Lesen', 'switch.timeline': 'Zeitleiste', 'read.to_top': 'Nach oben', 'read.pinned': 'Angeheftet', 2059 2059 'asite.feed_alt': 'Zweite Ansicht', 'asite.feed_alt_reader': 'Lesen', 'asite.feed_alt_timeline': 'Zeitleiste', 'asite.feed_alt_auto': 'Lesen mobil, Zeitleiste am Desktop', 2060 2060 'switch.reader_solo_only': 'Lesen gibt es nur in Solo — im Zirkel stehen Beitr\u00e4ge anderer', -
src/views/partials/read-article.ejs
rd8f8f07 ra505f31 68 68 69 69 <header class="read-head"> 70 <h1 class="read-title"><a href="<%= _b %>/<%= post.slug %>"><%= post.title || '' %></a></h1> 70 <%# Vastgepind hoort zichtbaar te zijn in de titel: in de leesstroom staat een 71 gepind bericht bovenaan zonder dat je ziet WAAROM het daar staat. Zelfde 72 icoon als in de tijdlijn (post-card.ejs), zodat het hetzelfde ding is. %> 73 <h1 class="read-title"> 74 <% if (post.pinned > 0) { %><span class="read-pin" title="<%= t('read.pinned') %>" aria-label="<%= t('read.pinned') %>"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.1" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="12" y1="17" x2="12" y2="22"/><path d="M5 17h14v-1.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V6h1a2 2 0 0 0 0-4H8a2 2 0 0 0 0 4h1v4.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24z"/></svg></span><% } %><a href="<%= _b %>/<%= post.slug %>"><%= post.title || '' %></a> 75 </h1> 71 76 <% if (post.published_at) { %><p class="read-when"><%= formatDateTime(post.published_at) %></p><% } %> 72 77 </header> -
src/views/shell.ejs
rd8f8f07 ra505f31 222 222 223 223 <!-- v9 stylesheet (full palette system) --> 224 <link rel="stylesheet" href="/assets/css/style.css?v=8 1">224 <link rel="stylesheet" href="/assets/css/style.css?v=82"> 225 225 <script> 226 226 /* iOS safe-area, built by hand. env(safe-area-inset-top) resolves to 0 on this iOS in … … 505 505 // Eén nummer voor de hele map. Te vaak bumpen kost één download; te weinig 506 506 // bumpen kost een bugfix die nooit aankomt. 507 var MOD_V = 1 6;507 var MOD_V = 19; 508 508 509 509 // name -> 1 (aan het laden) of de module-namespace (geladen). Een module
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)