Make the timeline the default view, paginated and configurable
The day-grouped timeline is now the site root (/, /page/N/); the flat square grid moves to /grid/ (/grid/page/N/). Both are linked from the profile header, separated by a divider. Timeline pages pack whole day-groups until they reach the page size, never splitting a day across a page boundary, so appended pages never repeat a date heading — the infinite-scroll handler relies on this. Page size is configurable via -page-size (default 60), threaded through the Generator and exposed as services.photogallery.pageSize in the NixOS module.
This commit is contained in:
@@ -20,7 +20,7 @@
|
||||
<p class="handle">{{.Handle}}</p>
|
||||
<p class="pcount"><strong>{{.Total}}</strong> posts</p>
|
||||
<p class="pbio">{{.Bio}}{{if .BioAlt}}<br><span class="ml">{{.BioAlt}}</span>{{end}}</p>
|
||||
<a href="/timeline/" class="rss-a">Timeline</a>
|
||||
<a href="/" class="rss-a">Timeline</a>
|
||||
<a href="/feed.xml" class="rss-a">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor" aria-hidden="true">
|
||||
<circle cx="2.5" cy="11.5" r="1.5"/>
|
||||
+59
-2
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Timeline · Photo Gallery</title>
|
||||
<title>Photo Gallery</title>
|
||||
<link rel="stylesheet" href="{{.FontsURL}}">
|
||||
<link rel="stylesheet" href="/static/style.css">
|
||||
<style>:root { --serif: '{{.SerifFamily}}', Georgia, serif; --mj: '{{.MlFamily}}', sans-serif; }</style>
|
||||
@@ -19,7 +19,16 @@
|
||||
<h1>{{.Author}}</h1>
|
||||
<p class="handle">{{.Handle}}</p>
|
||||
<p class="pcount"><strong>{{.Total}}</strong> posts</p>
|
||||
<a href="/" class="rss-a">← Grid</a>
|
||||
<p class="pbio">{{.Bio}}{{if .BioAlt}}<br><span class="ml">{{.BioAlt}}</span>{{end}}</p>
|
||||
<a href="/grid/" class="rss-a">Grid</a>
|
||||
<a href="/feed.xml" class="rss-a">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor" aria-hidden="true">
|
||||
<circle cx="2.5" cy="11.5" r="1.5"/>
|
||||
<path d="M1.5 7.5A5 5 0 0 1 6.5 12.5H8A6.5 6.5 0 0 0 1.5 6V7.5z"/>
|
||||
<path d="M1.5 4A8.5 8.5 0 0 1 10 12.5h1.5A10 10 0 0 0 1.5 2.5V4z"/>
|
||||
</svg>
|
||||
RSS feed
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
@@ -38,11 +47,59 @@
|
||||
</div>
|
||||
</section>
|
||||
{{end}}
|
||||
|
||||
{{if or .PrevURL .NextURL}}
|
||||
<nav class="pager">
|
||||
{{if .PrevURL}}<a class="pager-newer" href="{{.PrevURL}}">← Newer</a>{{end}}
|
||||
{{if .NextURL}}<a class="pager-older" href="{{.NextURL}}" data-load-more>Older →</a>{{end}}
|
||||
</nav>
|
||||
{{end}}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="site-footer">
|
||||
© 2000–{{.Year}} {{.Author}}. All rights reserved.
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
const btn = document.querySelector('[data-load-more]');
|
||||
if (!btn) return;
|
||||
const nav = btn.closest('.pager');
|
||||
const wrap = nav.parentNode;
|
||||
let loading = false;
|
||||
|
||||
async function loadMore(url) {
|
||||
if (loading) return;
|
||||
loading = true;
|
||||
try {
|
||||
const res = await fetch(url);
|
||||
if (!res.ok) return;
|
||||
const html = await res.text();
|
||||
const doc = new DOMParser().parseFromString(html, 'text/html');
|
||||
// Days never split across pages, so appended sections never duplicate
|
||||
// a heading already on the page.
|
||||
doc.querySelectorAll('.tl-day').forEach(s => wrap.insertBefore(s, nav));
|
||||
const nextBtn = doc.querySelector('[data-load-more]');
|
||||
if (nextBtn) btn.href = nextBtn.getAttribute('href');
|
||||
else btn.remove();
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
btn.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
loadMore(btn.href);
|
||||
});
|
||||
|
||||
const io = new IntersectionObserver((entries) => {
|
||||
if (entries[0].isIntersecting && document.body.contains(btn)) {
|
||||
loadMore(btn.href);
|
||||
}
|
||||
}, { rootMargin: '400px' });
|
||||
io.observe(btn);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user