mirror of
https://git.sr.ht/~cadence/bibliogram
synced 2024-11-22 16:17:29 +00:00
Infinite scroll
This commit is contained in:
parent
a3b4e2e64e
commit
b5f163891c
@ -9,13 +9,13 @@ See also: [Invidious, a front-end for YouTube.](https://github.com/omarroth/invi
|
|||||||
## Features
|
## Features
|
||||||
|
|
||||||
- [x] View profile and timeline
|
- [x] View profile and timeline
|
||||||
|
- [x] Infinite scroll
|
||||||
- [x] User memory cache
|
- [x] User memory cache
|
||||||
- [ ] Image disk cache
|
- [ ] Image disk cache
|
||||||
- [ ] View post
|
- [ ] View post
|
||||||
- [ ] Homepage
|
- [ ] Homepage
|
||||||
- [ ] Optimised for mobile
|
- [ ] Optimised for mobile
|
||||||
- [ ] Favicon
|
- [ ] Favicon
|
||||||
- [ ] Infinite scroll
|
|
||||||
- [ ] Settings (e.g. data saving)
|
- [ ] Settings (e.g. data saving)
|
||||||
- [ ] Galleries
|
- [ ] Galleries
|
||||||
- [ ] List view
|
- [ ] List view
|
||||||
|
@ -10,5 +10,20 @@ module.exports = [
|
|||||||
await user.timeline.fetchUpToPage(page - 1)
|
await user.timeline.fetchUpToPage(page - 1)
|
||||||
}
|
}
|
||||||
return render(200, "pug/user.pug", {url, user})
|
return render(200, "pug/user.pug", {url, user})
|
||||||
|
}},
|
||||||
|
{route: "/fragment/user/([\\w.]+)/(\\d+)", methods: ["GET"], code: async ({url, fill}) => {
|
||||||
|
const user = await fetchUser(fill[0])
|
||||||
|
const pageNumber = +fill[1]
|
||||||
|
const pageIndex = pageNumber - 1
|
||||||
|
await user.timeline.fetchUpToPage(pageIndex)
|
||||||
|
if (user.timeline.pages[pageIndex]) {
|
||||||
|
return render(200, "pug/fragments/timeline_page.pug", {page: user.timeline.pages[pageIndex], pageIndex, user, url})
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
statusCode: 400,
|
||||||
|
contentType: "text/html",
|
||||||
|
content: "That page does not exist"
|
||||||
|
}
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
]
|
]
|
||||||
|
56
src/site/html/static/js/pagination.js
Normal file
56
src/site/html/static/js/pagination.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import {ElemJS, q} from "./elemjs/elemjs.js"
|
||||||
|
|
||||||
|
class FreezeWidth extends ElemJS {
|
||||||
|
freeze(text) {
|
||||||
|
this.element.style.width = window.getComputedStyle(this.element).width
|
||||||
|
this.oldText = this.element.textContent
|
||||||
|
this.text(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
unfreeze() {
|
||||||
|
this.element.style.width = ""
|
||||||
|
this.text(this.oldText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NextPage extends FreezeWidth {
|
||||||
|
constructor(container) {
|
||||||
|
super(container)
|
||||||
|
this.clicked = false
|
||||||
|
this.nextPageNumber = +this.element.getAttribute("data-page")
|
||||||
|
this.attribute("href", "javascript:void(0)")
|
||||||
|
this.event("click", event => this.onClick(event))
|
||||||
|
|
||||||
|
this.observer = new IntersectionObserver(entries => this.onIntersect(entries), {rootMargin: "-20px", threshold: 1})
|
||||||
|
this.observer.observe(this.element)
|
||||||
|
}
|
||||||
|
|
||||||
|
onClick(event) {
|
||||||
|
if (event) event.preventDefault()
|
||||||
|
if (this.clicked) return
|
||||||
|
this.clicked = true
|
||||||
|
this.freeze("Loading...")
|
||||||
|
|
||||||
|
fetch(`/fragment/user/${this.element.getAttribute("data-username")}/${this.nextPageNumber}`).then(res => res.text()).then(text => {
|
||||||
|
q("#next-page-container").remove()
|
||||||
|
this.observer.disconnect()
|
||||||
|
|
||||||
|
q("#timeline").insertAdjacentHTML("beforeend", text)
|
||||||
|
addNextPageControl()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {IntersectionObserverEntry[]} entries
|
||||||
|
*/
|
||||||
|
onIntersect(entries) {
|
||||||
|
if (entries.some(entry => entry.isIntersecting && entry.intersectionRatio == 1)) this.onClick()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addNextPageControl() {
|
||||||
|
const nextPage = q("#next-page")
|
||||||
|
if (nextPage) new NextPage(nextPage)
|
||||||
|
}
|
||||||
|
|
||||||
|
addNextPageControl()
|
6
src/site/pug/fragments/timeline_page.pug
Normal file
6
src/site/pug/fragments/timeline_page.pug
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
include ../includes/timeline_page.pug
|
||||||
|
include ../includes/next_page_button.pug
|
||||||
|
|
||||||
|
+timeline_page(page, pageIndex)
|
||||||
|
|
||||||
|
+next_page_button(user, url)
|
10
src/site/pug/includes/next_page_button.pug
Normal file
10
src/site/pug/includes/next_page_button.pug
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
mixin next_page_button(user, url)
|
||||||
|
if user.timeline.hasNextPage()
|
||||||
|
div.next-page-container#next-page-container
|
||||||
|
-
|
||||||
|
const nu = new URL(url)
|
||||||
|
nu.searchParams.set("page", user.timeline.pages.length+1)
|
||||||
|
a(href=`${nu.search}#page-${user.timeline.pages.length+1}` data-page=(user.timeline.pages.length+1) data-username=(user.data.username))#next-page.next-page Next page
|
||||||
|
else
|
||||||
|
div.page-number.no-more-pages
|
||||||
|
span.number No more posts.
|
@ -1,4 +1,5 @@
|
|||||||
include includes/timeline_page.pug
|
include includes/timeline_page.pug
|
||||||
|
include includes/next_page_button.pug
|
||||||
|
|
||||||
- const numberFormat = new Intl.NumberFormat().format
|
- const numberFormat = new Intl.NumberFormat().format
|
||||||
|
|
||||||
@ -10,6 +11,7 @@ html
|
|||||||
title
|
title
|
||||||
= `${user.data.full_name} (@${user.data.username}) | Bibliogram`
|
= `${user.data.full_name} (@${user.data.username}) | Bibliogram`
|
||||||
link(rel="stylesheet" type="text/css" href="/static/css/main.css")
|
link(rel="stylesheet" type="text/css" href="/static/css/main.css")
|
||||||
|
script(src="/static/js/pagination.js" type="module")
|
||||||
body
|
body
|
||||||
.main-divider
|
.main-divider
|
||||||
header.profile-overview
|
header.profile-overview
|
||||||
@ -34,16 +36,8 @@ html
|
|||||||
|
|
|
|
||||||
| followed by
|
| followed by
|
||||||
|
|
||||||
main.timeline
|
main#timeline.timeline
|
||||||
each page, pageIndex in user.timeline.pages
|
each page, pageIndex in user.timeline.pages
|
||||||
+timeline_page(page, pageIndex)
|
+timeline_page(page, pageIndex)
|
||||||
|
|
||||||
if user.timeline.hasNextPage()
|
+next_page_button(user, url)
|
||||||
div.next-page-container
|
|
||||||
-
|
|
||||||
const nu = new URL(url)
|
|
||||||
nu.searchParams.set("page", user.timeline.pages.length+1)
|
|
||||||
a(href=`${nu.search}#page-${user.timeline.pages.length+1}` data-cursor=user.timeline.page_info.end_cursor)#next-page.next-page Next page
|
|
||||||
else
|
|
||||||
div.page-number.no-more-pages
|
|
||||||
span.number No more posts.
|
|
||||||
|
@ -114,6 +114,7 @@ body
|
|||||||
.next-page
|
.next-page
|
||||||
@include link-button
|
@include link-button
|
||||||
font-size: 18px
|
font-size: 18px
|
||||||
|
text-align: center
|
||||||
|
|
||||||
.timeline-inner
|
.timeline-inner
|
||||||
display: flex
|
display: flex
|
||||||
|
Loading…
Reference in New Issue
Block a user