2023-01-14 14:42:04 +03:00
|
|
|
import { proxy, subscribe } from 'valtio';
|
|
|
|
|
|
|
|
import store from './store';
|
2022-12-10 12:14:48 +03:00
|
|
|
|
2023-01-09 14:11:34 +03:00
|
|
|
const states = proxy({
|
2022-12-10 12:14:48 +03:00
|
|
|
history: [],
|
2023-01-07 15:26:23 +03:00
|
|
|
statuses: {},
|
2023-01-10 14:59:02 +03:00
|
|
|
statusThreadNumber: {},
|
2022-12-10 12:14:48 +03:00
|
|
|
home: [],
|
2023-01-14 14:42:04 +03:00
|
|
|
specialHome: [],
|
2022-12-10 12:14:48 +03:00
|
|
|
homeNew: [],
|
|
|
|
homeLastFetchTime: null,
|
|
|
|
notifications: [],
|
|
|
|
notificationsNew: [],
|
|
|
|
notificationsLastFetchTime: null,
|
2023-01-07 15:26:23 +03:00
|
|
|
accounts: {},
|
2022-12-10 12:14:48 +03:00
|
|
|
reloadStatusPage: 0,
|
2023-01-07 15:26:23 +03:00
|
|
|
spoilers: {},
|
|
|
|
scrollPositions: {},
|
2022-12-10 12:14:48 +03:00
|
|
|
// Modals
|
|
|
|
showCompose: false,
|
|
|
|
showSettings: false,
|
|
|
|
showAccount: false,
|
2023-01-13 10:30:09 +03:00
|
|
|
showDrafts: false,
|
2023-01-04 14:03:11 +03:00
|
|
|
composeCharacterCount: 0,
|
2023-01-14 14:42:04 +03:00
|
|
|
settings: {
|
2023-01-16 15:32:30 +03:00
|
|
|
boostsCarousel: store.local.get('settings:boostsCarousel') === '1' ?? true,
|
2023-01-14 14:42:04 +03:00
|
|
|
},
|
2022-12-10 12:14:48 +03:00
|
|
|
});
|
2023-01-09 14:11:34 +03:00
|
|
|
export default states;
|
|
|
|
|
2023-01-14 14:42:04 +03:00
|
|
|
subscribe(states.settings, () => {
|
|
|
|
store.local.set(
|
|
|
|
'settings:boostsCarousel',
|
|
|
|
states.settings.boostsCarousel ? '1' : '0',
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2023-01-09 14:11:34 +03:00
|
|
|
export function saveStatus(status, opts) {
|
2023-01-10 14:59:02 +03:00
|
|
|
const { override, skipThreading } = Object.assign(
|
|
|
|
{ override: true, skipThreading: false },
|
|
|
|
opts,
|
|
|
|
);
|
2023-01-09 14:11:34 +03:00
|
|
|
if (!status) return;
|
|
|
|
if (!override && states.statuses[status.id]) return;
|
|
|
|
states.statuses[status.id] = status;
|
|
|
|
if (status.reblog) {
|
|
|
|
states.statuses[status.reblog.id] = status.reblog;
|
|
|
|
}
|
2023-01-10 14:59:02 +03:00
|
|
|
|
|
|
|
// THREAD TRAVERSER
|
|
|
|
if (!skipThreading) {
|
|
|
|
requestAnimationFrame(() => {
|
|
|
|
threadifyStatus(status);
|
2023-01-10 17:58:54 +03:00
|
|
|
if (status.reblog) {
|
|
|
|
threadifyStatus(status.reblog);
|
|
|
|
}
|
2023-01-10 14:59:02 +03:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-11 12:45:37 +03:00
|
|
|
export function threadifyStatus(status) {
|
2023-01-10 14:59:02 +03:00
|
|
|
// Return all statuses in the thread, via inReplyToId, if inReplyToAccountId === account.id
|
|
|
|
let fetchIndex = 0;
|
|
|
|
async function traverse(status, index = 0) {
|
|
|
|
const { inReplyToId, inReplyToAccountId } = status;
|
|
|
|
if (!inReplyToId || inReplyToAccountId !== status.account.id) {
|
|
|
|
return [status];
|
|
|
|
}
|
|
|
|
if (inReplyToId && inReplyToAccountId !== status.account.id) {
|
|
|
|
throw 'Not a thread';
|
|
|
|
// Possibly thread of replies by multiple people?
|
|
|
|
}
|
|
|
|
let prevStatus = states.statuses[inReplyToId];
|
|
|
|
if (!prevStatus) {
|
|
|
|
if (fetchIndex++ > 3) throw 'Too many fetches for thread'; // Some people revive old threads
|
|
|
|
await new Promise((r) => setTimeout(r, 500 * fetchIndex)); // Be nice to rate limits
|
|
|
|
prevStatus = await masto.v1.statuses.fetch(inReplyToId);
|
|
|
|
saveStatus(prevStatus, { skipThreading: true });
|
|
|
|
}
|
|
|
|
// Prepend so that first status in thread will be index 0
|
|
|
|
return [...(await traverse(prevStatus, ++index)), status];
|
|
|
|
}
|
|
|
|
return traverse(status)
|
|
|
|
.then((statuses) => {
|
|
|
|
if (statuses.length > 1) {
|
|
|
|
console.debug('THREAD', statuses);
|
|
|
|
statuses.forEach((status, index) => {
|
|
|
|
states.statusThreadNumber[status.id] = index + 1;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.catch((e) => {
|
|
|
|
console.error(e, status);
|
|
|
|
});
|
2023-01-09 14:11:34 +03:00
|
|
|
}
|