feat: local and federated timelines

This commit is contained in:
mae taylor 2025-07-15 15:08:37 +01:00
parent 7db5ec7fae
commit c51a0b1e5d
Signed by: mae
GPG key ID: 3C80D76BA7A3B9BD
3 changed files with 64 additions and 11 deletions

View file

@ -243,11 +243,13 @@ export async function rejectFollowRequest(host, token, account_id) {
* @param {string} timeline - The name of the timeline to pull (default "home"). * @param {string} timeline - The name of the timeline to pull (default "home").
* @param {string} max_id - If provided, only shows posts after this ID. * @param {string} max_id - If provided, only shows posts after this ID.
*/ */
export async function getTimeline(host, token, timeline, max_id) { export async function getTimeline(host, token, timeline, max_id, local_only, remote_only) {
let url = `https://${host}/api/v1/timelines/${timeline || "home"}`; let url = `https://${host}/api/v1/timelines/${timeline || "home"}`;
let params = new URLSearchParams(); let params = new URLSearchParams();
if (max_id) params.append("max_id", max_id); if (max_id) params.append("max_id", max_id);
if (remote_only) params.append("remote", remote_only);
if (local_only) params.append("local", local_only);
const params_string = params.toString(); const params_string = params.toString();
if (params_string) url += '?' + params_string; if (params_string) url += '?' + params_string;

View file

@ -11,7 +11,7 @@ const lang = Lang();
let loading = false; let loading = false;
export async function getTimeline(clean) { 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;
@ -22,9 +22,11 @@ export async function getTimeline(clean) {
const timeline_data = await api.getTimeline( const timeline_data = await api.getTimeline(
get(server).host, get(server).host,
get(app).token, get(app).token,
"home", timelineType,
last_post last_post,
); localOnly,
remoteOnly
);
if (!timeline_data) { if (!timeline_data) {
console.error(lang.string('logs.timeline_fetch_failed')); console.error(lang.string('logs.timeline_fetch_failed'));

View file

@ -2,6 +2,7 @@
import { page } from '$app/stores'; import { page } from '$app/stores';
import { account } from '$lib/stores/account.js'; import { account } from '$lib/stores/account.js';
import { timeline, getTimeline } from '$lib/timeline.js'; import { timeline, getTimeline } from '$lib/timeline.js';
import { app_name } from '$lib/config.js';
import Lang from '$lib/lang'; import Lang from '$lib/lang';
import LoginForm from '$lib/ui/LoginForm.svelte'; import LoginForm from '$lib/ui/LoginForm.svelte';
@ -11,23 +12,71 @@
const lang = Lang(); const lang = Lang();
// TODO: refactor to enum when moving to TS
let timelineType = localStorage.getItem(app_name + '_selected_timeline') || "home";
$: {
// awful hack to update timeline fresh
// when timelineType is updated
//
// TODO: migrate to $effect when migrating to svelte 5
timelineType = timelineType
// set in localStorage
localStorage.setItem(app_name + '_selected_timeline', timelineType);
// erase the timeline here so the ui reacts instantly
// mae: i could write an awesome undertale reference here
timeline.set([]);
getCurrentTimeline()
}
function getCurrentTimeline(clean = false) {
switch(timelineType) {
case "home":
getTimeline("home", clean);
break;
case "local":
getTimeline("public", clean, true)
break;
case "federated":
getTimeline("public", clean, false, true)
break;
}
}
account.subscribe(account => { account.subscribe(account => {
if (account) getTimeline(); if (account) getCurrentTimeline();
}); });
document.addEventListener('scroll', () => { document.addEventListener('scroll', () => {
if ($account && $page.url.pathname !== "/") return; if ($account && $page.url.pathname !== "/") return;
if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 2048) { if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 2048) {
getTimeline(); getCurrentTimeline();
} }
}); });
</script> </script>
{#if $account} {#if $account}
<PageHeader title={lang.string('timeline.home')}> <PageHeader title={lang.string(`timeline.${timelineType}`)}>
<Button centered active>{lang.string('timeline.home')}</Button> <Button centered
<Button centered disabled>{lang.string('timeline.local')}</Button> active={(timelineType == "home")}
<Button centered disabled>{lang.string('timeline.federated')}</Button> on:click={() => timelineType = "home"}>
{lang.string('timeline.home')}
</Button>
<Button centered
active={(timelineType == "local")}
on:click={() => timelineType = "local"}>
{lang.string('timeline.local')}
</Button>
<Button centered
active={(timelineType == "federated")}
on:click={() => timelineType = "federated"}>
{lang.string('timeline.federated')}
</Button>
</PageHeader> </PageHeader>
<div id="feed" role="feed"> <div id="feed" role="feed">