refactor: use Link HTTP header for pagination
This commit is contained in:
		
							parent
							
								
									99def58c8b
								
							
						
					
					
						commit
						3b8ca902f1
					
				
					 2 changed files with 74 additions and 32 deletions
				
			
		|  | @ -2,6 +2,31 @@ const errors = { | |||
|     AUTHENTICATION_FAILED: "AUTHENTICATION_FAILED", | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * Parses a HTTP Link header | ||||
|  * @param {string} header - the HTTP Link header string | ||||
|  */ | ||||
| function _parseLinkHeader(header) { | ||||
|     // remove whitespace and split
 | ||||
|     let links = header.replace(/\ /g, "").split(","); | ||||
| 
 | ||||
|     return links.map(l => { | ||||
|         let parts = l.split(";"); | ||||
| 
 | ||||
|         // assuming 0th is URL, removing <>
 | ||||
|         let url = new URL(parts[0].slice(1, -1)); | ||||
| 
 | ||||
|         // get rel inbetween double-quotes
 | ||||
|         let rel = parts[1].match(/"(.*?)"/g)[0].slice(1, -1); | ||||
| 
 | ||||
|         return { | ||||
|             url, rel | ||||
|         } | ||||
|     }) | ||||
| } | ||||
| 
 | ||||
| _parseLinkHeader(`<https://wetdry.world/api/v1/timelines/home?max_id=114857293229157171>; rel="next", <https://wetdry.world/api/v1/timelines/home?min_id=114857736990577458>; rel="prev"`) | ||||
| 
 | ||||
| /** | ||||
|  * GET /api/v1/instance | ||||
|  * @param {string} host - The domain of the target server. | ||||
|  | @ -258,9 +283,43 @@ export async function getTimeline(host, token, timeline, max_id, local_only, rem | |||
|     const data = await fetch(url, { | ||||
|         method: 'GET', | ||||
|         headers: { "Authorization": token ? `Bearer ${token}` : null } | ||||
|     }).then(res => res.json()); | ||||
|     }) | ||||
| 
 | ||||
|     return data; | ||||
|     let links = _parseLinkHeader(data.headers.get("Link")); | ||||
| 
 | ||||
|     return { | ||||
|         data: await data.json(), | ||||
|         prev: links.find(f=>f.rel=="prev"), | ||||
|         next: links.find(f=>f.rel=="next") | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * GET /api/v1/favourites | ||||
|  * @param {string} host - The domain of the target server. | ||||
|  * @param {string} token - The application token. | ||||
|  * @param {string} max_id - If provided, only shows posts after this ID. | ||||
|  */ | ||||
| export async function getFavourites(host, token, max_id) { | ||||
|     let url = `https://${host}/api/v1/favourites`; | ||||
| 
 | ||||
|     let params = new URLSearchParams(); | ||||
|     if (max_id) params.append("max_id", max_id); | ||||
|     const params_string = params.toString(); | ||||
|     if (params_string) url += '?' + params_string; | ||||
|      | ||||
|     const data = await fetch(url, { | ||||
|         method: 'GET', | ||||
|         headers: { "Authorization": token ? `Bearer ${token}` : null } | ||||
|     }) | ||||
| 
 | ||||
|     let links = _parseLinkHeader(data.headers.get("Link")); | ||||
| 
 | ||||
|     return { | ||||
|         data: await data.json(), | ||||
|         prev: links.find(f=>f.rel=="prev"), | ||||
|         next: links.find(f=>f.rel=="next") | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  | @ -560,25 +619,3 @@ export async function getUserPinnedPosts(host, token, user_id) { | |||
| 
 | ||||
|     return data; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * GET /api/v1/favourites | ||||
|  * @param {string} host - The domain of the target server. | ||||
|  * @param {string} token - The application token. | ||||
|  * @param {string} max_id - If provided, only shows posts after this ID. | ||||
|  */ | ||||
| export async function getFavourites(host, token, timeline, max_id) { | ||||
|     let url = `https://${host}/api/v1/favourites`; | ||||
| 
 | ||||
|     let params = new URLSearchParams(); | ||||
|     if (max_id) params.append("max_id", max_id); | ||||
|     const params_string = params.toString(); | ||||
|     if (params_string) url += '?' + params_string; | ||||
|      | ||||
|     const data = await fetch(url, { | ||||
|         method: 'GET', | ||||
|         headers: { "Authorization": token ? `Bearer ${token}` : null } | ||||
|     }).then(res => res.json()); | ||||
| 
 | ||||
|     return data; | ||||
| } | ||||
|  |  | |||
|  | @ -10,14 +10,14 @@ export const timeline = writable([]); | |||
| const lang = Lang(); | ||||
| 
 | ||||
| let loading = false; | ||||
| let last_post = false; | ||||
| 
 | ||||
| export async function getTimeline(timelineType = "home", clean, localOnly = false, remoteOnly = false) { | ||||
|     if (loading) return; // no spamming!!
 | ||||
|     loading = true; | ||||
| 
 | ||||
|     let last_post = false; | ||||
|     if (!clean && get(timeline).length > 0) | ||||
|         last_post = get(timeline)[get(timeline).length - 1].id; | ||||
|     // if (!clean && get(timeline).length > 0)
 | ||||
|     //     last_post = get(timeline)[get(timeline).length - 1].id;
 | ||||
| 
 | ||||
|     let timeline_data; | ||||
|     switch(timelineType) { | ||||
|  | @ -25,7 +25,7 @@ export async function getTimeline(timelineType = "home", clean, localOnly = fals | |||
|             timeline_data = await api.getFavourites( | ||||
|                 get(server).host, | ||||
|                 get(app).token, | ||||
|                 last_post, | ||||
|                 last_post | ||||
|             ) | ||||
|             break; | ||||
|              | ||||
|  | @ -47,10 +47,15 @@ export async function getTimeline(timelineType = "home", clean, localOnly = fals | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (clean) timeline.set([]); | ||||
|     if (clean) { | ||||
|         timeline.set([]); | ||||
|         last_post = false; | ||||
|     } else { | ||||
|         last_post = timeline_data.next.url.searchParams.get("max_id") | ||||
|     }  | ||||
| 
 | ||||
|     for (let i in timeline_data) { | ||||
|         const post_data = timeline_data[i]; | ||||
|     for (let i in timeline_data.data) { | ||||
|         const post_data = timeline_data.data[i]; | ||||
|         const post = await parsePost(post_data, 1); | ||||
|         if (!post) { | ||||
|             if (post === null || post === undefined) { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue