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",
|
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
|
* GET /api/v1/instance
|
||||||
* @param {string} host - The domain of the target server.
|
* @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, {
|
const data = await fetch(url, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: { "Authorization": token ? `Bearer ${token}` : null }
|
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")
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -559,26 +618,4 @@ export async function getUserPinnedPosts(host, token, user_id) {
|
||||||
}).then(res => res.json());
|
}).then(res => res.json());
|
||||||
|
|
||||||
return data;
|
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();
|
const lang = Lang();
|
||||||
|
|
||||||
let loading = false;
|
let loading = false;
|
||||||
|
let last_post = false;
|
||||||
|
|
||||||
export async function getTimeline(timelineType = "home", clean, localOnly = false, remoteOnly = false) {
|
export async function getTimeline(timelineType = "home", clean, localOnly = false, remoteOnly = false) {
|
||||||
if (loading) return; // no spamming!!
|
if (loading) return; // no spamming!!
|
||||||
loading = true;
|
loading = true;
|
||||||
|
|
||||||
let last_post = false;
|
// if (!clean && get(timeline).length > 0)
|
||||||
if (!clean && get(timeline).length > 0)
|
// last_post = get(timeline)[get(timeline).length - 1].id;
|
||||||
last_post = get(timeline)[get(timeline).length - 1].id;
|
|
||||||
|
|
||||||
let timeline_data;
|
let timeline_data;
|
||||||
switch(timelineType) {
|
switch(timelineType) {
|
||||||
|
@ -25,7 +25,7 @@ export async function getTimeline(timelineType = "home", clean, localOnly = fals
|
||||||
timeline_data = await api.getFavourites(
|
timeline_data = await api.getFavourites(
|
||||||
get(server).host,
|
get(server).host,
|
||||||
get(app).token,
|
get(app).token,
|
||||||
last_post,
|
last_post
|
||||||
)
|
)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -47,10 +47,15 @@ export async function getTimeline(timelineType = "home", clean, localOnly = fals
|
||||||
return;
|
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) {
|
for (let i in timeline_data.data) {
|
||||||
const post_data = timeline_data[i];
|
const post_data = timeline_data.data[i];
|
||||||
const post = await parsePost(post_data, 1);
|
const post = await parsePost(post_data, 1);
|
||||||
if (!post) {
|
if (!post) {
|
||||||
if (post === null || post === undefined) {
|
if (post === null || post === undefined) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue