From 224cad4d7f1d0bee49e2d619558740e585306ef3 Mon Sep 17 00:00:00 2001 From: Lim Chee Aun Date: Fri, 31 May 2024 17:11:40 +0800 Subject: [PATCH] Utilise the new batch fetch on Mastodon v4.3 --- src/data/features.json | 3 +- src/utils/timeline-utils.jsx | 94 ++++++++++++++++++++++++++++++++---- 2 files changed, 86 insertions(+), 11 deletions(-) diff --git a/src/data/features.json b/src/data/features.json index e0cbb876..0aba1ba3 100644 --- a/src/data/features.json +++ b/src/data/features.json @@ -1,5 +1,6 @@ { "@mastodon/edit-media-attributes": ">=4.1", "@mastodon/list-exclusive": ">=4.2", - "@mastodon/filtered-notifications": "~4.3 || >=4.3" + "@mastodon/filtered-notifications": "~4.3 || >=4.3", + "@mastodon/fetch-multiple-statuses": "~4.3 || >=4.3" } diff --git a/src/utils/timeline-utils.jsx b/src/utils/timeline-utils.jsx index d41be58e..20225f12 100644 --- a/src/utils/timeline-utils.jsx +++ b/src/utils/timeline-utils.jsx @@ -4,6 +4,7 @@ import pmem from './pmem'; import { fetchRelationships } from './relationships'; import states, { saveStatus, statusKey } from './states'; import store from './store'; +import supports from './supports'; export function groupBoosts(values) { let newValues = []; @@ -149,6 +150,7 @@ export function groupContext(items, instance) { const newItems = []; const appliedContextIndices = []; + const inReplyToIds = []; items.forEach((item) => { if (item.reblog) { newItems.push(item); @@ -176,17 +178,53 @@ export function groupContext(items, instance) { } } + // PREPARE FOR REPLY HINTS if (item.inReplyToId && item.inReplyToAccountId !== item.account.id) { const sKey = statusKey(item.id, instance); if (!states.statusReply[sKey]) { // If it's a reply and not a thread - queueMicrotask(async () => { + inReplyToIds.push({ + sKey, + inReplyToId: item.inReplyToId, + }); + // queueMicrotask(async () => { + // try { + // const { masto } = api({ instance }); + // // const replyToStatus = await masto.v1.statuses + // // .$select(item.inReplyToId) + // // .fetch(); + // const replyToStatus = await fetchStatus(item.inReplyToId, masto); + // saveStatus(replyToStatus, instance, { + // skipThreading: true, + // skipUnfurling: true, + // }); + // states.statusReply[sKey] = { + // id: replyToStatus.id, + // instance, + // }; + // } catch (e) { + // // Silently fail + // console.error(e); + // } + // }); + } + } + + newItems.push(item); + }); + + // FETCH AND SHOW REPLY HINTS + if (inReplyToIds?.length) { + queueMicrotask(() => { + const { masto } = api({ instance }); + console.log('REPLYHINT', inReplyToIds); + + // Fallback if batch fetch fails or returns nothing or not supported + async function fallbackFetch() { + for (let i = 0; i < inReplyToIds.length; i++) { + const { sKey, inReplyToId } = inReplyToIds[i]; try { - const { masto } = api({ instance }); - // const replyToStatus = await masto.v1.statuses - // .$select(item.inReplyToId) - // .fetch(); - const replyToStatus = await fetchStatus(item.inReplyToId, masto); + const replyToStatus = await fetchStatus(inReplyToId, masto); saveStatus(replyToStatus, instance, { skipThreading: true, skipUnfurling: true, @@ -195,16 +233,52 @@ export function groupContext(items, instance) { id: replyToStatus.id, instance, }; + // Pause 1s + await new Promise((resolve) => setTimeout(resolve, 1000)); } catch (e) { // Silently fail console.error(e); } - }); + } } - } - newItems.push(item); - }); + if (supports('@mastodon/fetch-multiple-statuses')) { + // This is batch fetching yooo, woot + // Limit 20, returns 422 if exceeded https://github.com/mastodon/mastodon/pull/27871 + const ids = inReplyToIds.map(({ inReplyToId }) => inReplyToId); + (async () => { + try { + const replyToStatuses = await masto.v1.statuses.list({ id: ids }); + if (replyToStatuses?.length) { + for (const replyToStatus of replyToStatuses) { + saveStatus(replyToStatus, instance, { + skipThreading: true, + skipUnfurling: true, + }); + const sKey = inReplyToIds.find( + ({ inReplyToId }) => inReplyToId === replyToStatus.id, + )?.sKey; + if (sKey) { + states.statusReply[sKey] = { + id: replyToStatus.id, + instance, + }; + } + } + } else { + fallbackFetch(); + } + } catch (e) { + // Silently fail + console.error(e); + fallbackFetch(); + } + })(); + } else { + fallbackFetch(); + } + }); + } return newItems; }