From 445f3d04416c9895035f0142f71d2613949c2fa8 Mon Sep 17 00:00:00 2001
From: AkiraFukushima
Date: Sat, 9 Mar 2024 01:04:39 +0900
Subject: [PATCH] Handle nextId in link header when favourites and bookmarks
---
package.json | 1 +
renderer/components/timelines/Timeline.tsx | 27 +++++++++++++++++++---
yarn.lock | 17 ++++++++++++++
3 files changed, 42 insertions(+), 3 deletions(-)
diff --git a/package.json b/package.json
index 40495ce9..c1a0fb29 100644
--- a/package.json
+++ b/package.json
@@ -28,6 +28,7 @@
"electron-store": "^8.1.0",
"emoji-mart": "^5.5.2",
"megalodon": "9.2.2",
+ "parse-link-header": "^2.0.0",
"react-blurhash": "^0.3.0",
"react-hotkeys-hook": "^4.4.1",
"react-icons": "^5.0.0",
diff --git a/renderer/components/timelines/Timeline.tsx b/renderer/components/timelines/Timeline.tsx
index 5f15170e..da964e74 100644
--- a/renderer/components/timelines/Timeline.tsx
+++ b/renderer/components/timelines/Timeline.tsx
@@ -9,6 +9,7 @@ import { useRouter } from 'next/router'
import Compose from '../compose/Compose'
import { useHotkeys } from 'react-hotkeys-hook'
import { Input, Spinner } from '@material-tailwind/react'
+import parse from 'parse-link-header'
const TIMELINE_STATUSES_COUNT = 30
const TIMELINE_MAX_STATUSES = 2147483647
@@ -27,6 +28,7 @@ export default function Timeline(props: Props) {
const [composeHeight, setComposeHeight] = useState(120)
const [list, setList] = useState(null)
const [filters, setFilters] = useState>([])
+ const [nextMaxId, setNextMaxId] = useState(null)
const router = useRouter()
const { formatMessage } = useIntl()
@@ -147,11 +149,18 @@ export default function Timeline(props: Props) {
}
case 'favourites': {
const res = await client.getFavourites(options)
- // TODO: handle next_id in link header to get more posts
+ const link = parse(res.headers.link)
+ if (link !== null && link.next) {
+ setNextMaxId(link.next.max_id)
+ }
return res.data
}
case 'bookmarks': {
const res = await client.getBookmarks(options)
+ const link = parse(res.headers.link)
+ if (link !== null && link.next) {
+ setNextMaxId(link.next.max_id)
+ }
return res.data
}
default: {
@@ -190,11 +199,23 @@ export default function Timeline(props: Props) {
const loadMore = useCallback(async () => {
console.debug('appending')
- const maxId = statuses[statuses.length - 1].id
+ let maxId = null
+ switch (props.timeline) {
+ case 'favourites':
+ case 'bookmarks':
+ if (!nextMaxId) {
+ return
+ }
+ maxId = nextMaxId
+ break
+ default:
+ maxId = statuses[statuses.length - 1].id
+ break
+ }
const append = await loadTimeline(props.timeline, props.client, maxId)
setStatuses(last => [...last, ...append])
- }, [props.client, statuses, setStatuses])
+ }, [props.client, statuses, setStatuses, nextMaxId])
const prependUnreads = useCallback(() => {
console.debug('prepending')
diff --git a/yarn.lock b/yarn.lock
index ddbfae0d..b3c71878 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2706,6 +2706,7 @@ __metadata:
megalodon: 9.2.2
next: ^12.3.4
nextron: ^8.12.0
+ parse-link-header: ^2.0.0
postcss: ^8.4.31
react: ^18.2.0
react-blurhash: ^0.3.0
@@ -7156,6 +7157,15 @@ __metadata:
languageName: node
linkType: hard
+"parse-link-header@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "parse-link-header@npm:2.0.0"
+ dependencies:
+ xtend: ~4.0.1
+ checksum: 0e96c6af9910e8f92084b49b8dc6a10dd58db470847d1499f562576180c1ac5e49d18007697f0d538e5f3efdc8ce1d8777641f3ae225302b74af0dd0578b628e
+ languageName: node
+ linkType: hard
+
"parse-srcset@npm:^1.0.2":
version: 1.0.2
resolution: "parse-srcset@npm:1.0.2"
@@ -9216,6 +9226,13 @@ __metadata:
languageName: node
linkType: hard
+"xtend@npm:~4.0.1":
+ version: 4.0.2
+ resolution: "xtend@npm:4.0.2"
+ checksum: ac5dfa738b21f6e7f0dd6e65e1b3155036d68104e67e5d5d1bde74892e327d7e5636a076f625599dc394330a731861e87343ff184b0047fef1360a7ec0a5a36a
+ languageName: node
+ linkType: hard
+
"y18n@npm:^5.0.5":
version: 5.0.8
resolution: "y18n@npm:5.0.8"