2023-02-07 19:31:46 +03:00
|
|
|
import { useEffect, useRef } from 'preact/hooks';
|
2023-02-03 16:08:08 +03:00
|
|
|
import { useSnapshot } from 'valtio';
|
|
|
|
|
|
|
|
import Timeline from '../components/timeline';
|
2023-02-05 19:17:19 +03:00
|
|
|
import { api } from '../utils/api';
|
2023-02-05 20:10:49 +03:00
|
|
|
import states from '../utils/states';
|
2023-02-07 19:31:46 +03:00
|
|
|
import { getStatus, saveStatus } from '../utils/states';
|
2023-02-03 16:08:08 +03:00
|
|
|
import useTitle from '../utils/useTitle';
|
|
|
|
|
|
|
|
const LIMIT = 20;
|
|
|
|
|
|
|
|
function Following() {
|
|
|
|
useTitle('Following', '/l/f');
|
2023-02-06 18:50:00 +03:00
|
|
|
const { masto, instance } = api();
|
2023-02-03 16:08:08 +03:00
|
|
|
const snapStates = useSnapshot(states);
|
|
|
|
const homeIterator = useRef();
|
2023-02-07 19:31:46 +03:00
|
|
|
const latestItem = useRef();
|
|
|
|
|
2023-02-03 16:08:08 +03:00
|
|
|
async function fetchHome(firstLoad) {
|
|
|
|
if (firstLoad || !homeIterator.current) {
|
|
|
|
homeIterator.current = masto.v1.timelines.listHome({ limit: LIMIT });
|
|
|
|
}
|
2023-02-06 18:50:00 +03:00
|
|
|
const results = await homeIterator.current.next();
|
|
|
|
const { value } = results;
|
|
|
|
if (value?.length) {
|
2023-02-07 19:31:46 +03:00
|
|
|
if (firstLoad) {
|
|
|
|
latestItem.current = value[0].id;
|
|
|
|
}
|
|
|
|
|
2023-02-06 18:50:00 +03:00
|
|
|
value.forEach((item) => {
|
|
|
|
saveStatus(item, instance);
|
|
|
|
});
|
|
|
|
|
|
|
|
// ENFORCE sort by datetime (Latest first)
|
|
|
|
value.sort((a, b) => {
|
|
|
|
const aDate = new Date(a.createdAt);
|
|
|
|
const bDate = new Date(b.createdAt);
|
|
|
|
return bDate - aDate;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return results;
|
2023-02-03 16:08:08 +03:00
|
|
|
}
|
|
|
|
|
2023-02-07 19:31:46 +03:00
|
|
|
async function checkForUpdates() {
|
|
|
|
try {
|
|
|
|
const results = await masto.v1.timelines
|
|
|
|
.listHome({
|
|
|
|
limit: 5,
|
|
|
|
since_id: latestItem.current,
|
|
|
|
})
|
|
|
|
.next();
|
|
|
|
const { value } = results;
|
|
|
|
console.log('checkForUpdates', value);
|
|
|
|
if (value?.some((item) => !item.reblog)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
} catch (e) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const ws = useRef();
|
|
|
|
async function streamUser() {
|
|
|
|
if (
|
|
|
|
ws.current &&
|
|
|
|
(ws.current.readyState === WebSocket.CONNECTING ||
|
|
|
|
ws.current.readyState === WebSocket.OPEN)
|
|
|
|
) {
|
|
|
|
console.log('🎏 Streaming user already open');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const stream = await masto.v1.stream.streamUser();
|
|
|
|
ws.current = stream.ws;
|
|
|
|
console.log('🎏 Streaming user');
|
|
|
|
|
|
|
|
stream.on('status.update', (status) => {
|
|
|
|
console.log(`🔄 Status ${status.id} updated`);
|
|
|
|
saveStatus(status, instance);
|
|
|
|
});
|
|
|
|
|
|
|
|
stream.on('delete', (statusID) => {
|
|
|
|
console.log(`❌ Status ${statusID} deleted`);
|
|
|
|
// delete states.statuses[statusID];
|
|
|
|
const s = getStatus(statusID, instance);
|
|
|
|
if (s) s._deleted = true;
|
|
|
|
});
|
|
|
|
|
|
|
|
return stream;
|
|
|
|
}
|
|
|
|
useEffect(() => {
|
|
|
|
streamUser();
|
|
|
|
return () => {
|
|
|
|
if (ws.current) {
|
|
|
|
console.log('🎏 Closing streaming user');
|
|
|
|
ws.current.close();
|
|
|
|
ws.current = null;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}, []);
|
|
|
|
|
2023-02-03 16:08:08 +03:00
|
|
|
return (
|
|
|
|
<Timeline
|
|
|
|
title="Following"
|
|
|
|
id="following"
|
|
|
|
emptyText="Nothing to see here."
|
|
|
|
errorText="Unable to load posts."
|
|
|
|
fetchItems={fetchHome}
|
2023-02-07 19:31:46 +03:00
|
|
|
checkForUpdates={checkForUpdates}
|
2023-02-06 18:50:00 +03:00
|
|
|
useItemID
|
2023-02-03 16:08:08 +03:00
|
|
|
boostsCarousel={snapStates.settings.boostsCarousel}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export default Following;
|