diff --git a/src/lib/client/api.js b/src/lib/client/api.js index 11d3238..c3accbb 100644 --- a/src/lib/client/api.js +++ b/src/lib/client/api.js @@ -91,8 +91,27 @@ export async function verifyCredentials() { return data; } +export async function getNotifications(since_id, limit, types) { + if (!get(client).user) return false; + + let url = `https://${get(client).instance.host}/api/v1/notifications`; + + let params = new URLSearchParams(); + if (since_id) params.append("since_id", since_id); + if (limit) params.append("limit", limit); + if (types) params.append("types", types.join(',')); + const params_string = params.toString(); + if (params_string) url += '?' + params_string; + + const data = await fetch(url, { + method: 'GET', + headers: { "Authorization": "Bearer " + get(client).app.token } + }).then(res => res.json()); + + return data; +} + export async function getTimeline(last_post_id) { - if (!get(client).instance || !get(client).app) return false; let url = `https://${get(client).instance.host}/api/v1/timelines/home`; if (last_post_id) url += "?max_id=" + last_post_id; const data = await fetch(url, { @@ -200,6 +219,7 @@ export async function parsePost(data, ancestor_count) { let post = new Post(); post.text = data.content; + post.html = data.content; post.reply = null; if ((data.in_reply_to_id || data.reply) && @@ -259,7 +279,7 @@ export async function parseUser(data) { user = new User(); user.id = data.id; - user.nickname = data.display_name; + user.nickname = data.display_name.trim(); user.username = data.username; user.avatar_url = data.avatar; user.url = data.url; diff --git a/src/lib/client/client.js b/src/lib/client/client.js index 44e7b53..3ac4269 100644 --- a/src/lib/client/client.js +++ b/src/lib/client/client.js @@ -1,6 +1,8 @@ import { Instance, server_types } from './instance.js'; import * as api from './api.js'; import { get, writable } from 'svelte/store'; +import { last_read_notif_id } from '$lib/notifications.js'; +import { user } from '$lib/stores/user.js'; export const client = writable(false); @@ -93,6 +95,10 @@ export class Client { return user; } + async getNotifications(since_id, limit, types) { + return await api.getNotifications(since_id, limit, types); + } + async getTimeline(last_post_id) { return await api.getTimeline(last_post_id); } @@ -173,6 +179,7 @@ export class Client { host: this.instance.host, version: this.instance.version, }, + last_read_notif_id: get(last_read_notif_id), app: this.app, })); } @@ -187,6 +194,7 @@ export class Client { return false; } this.instance = new Instance(saved.instance.host, saved.instance.version); + last_read_notif_id.set(saved.last_read_notif_id || 0); this.app = saved.app; client.set(this); return true; diff --git a/src/lib/notifications.js b/src/lib/notifications.js new file mode 100644 index 0000000..5d16795 --- /dev/null +++ b/src/lib/notifications.js @@ -0,0 +1,40 @@ +import { client } from '$lib/client/client.js'; +import * as api from '$lib/client/api.js'; +import { get, writable } from 'svelte/store'; + +export let notifications = writable([]); +export let unread_notif_count = writable(0); +export let last_read_notif_id = writable(0); + +let loading; +export async function getNotifications() { + if (loading) return; // no spamming!! + loading = true; + + api.getNotifications().then(async data => { + if (!data || data.length <= 0) return; + notifications.set([]); + for (let i in data) { + let notif = data[i]; + notif.accounts = [ await api.parseUser(notif.account) ]; + if (get(notifications).length > 0) { + let prev = get(notifications)[get(notifications).length - 1]; + if (notif.type === prev.type) { + if (prev.status && notif.status && prev.status.id === notif.status.id) { + notifications.update(notifications => { + notifications[notifications.length - 1].accounts.push(notif.accounts[0]); + return notifications; + }); + continue; + } + } + } + notif.status = await api.parsePost(notif.status, 0, false); + notifications.update(notifications => [...notifications, notif]); + } + last_read_notif_id.set(data[0].id); + unread_notif_count.set(0); + get(client).save(); + loading = false; + }); +} diff --git a/src/lib/stores/user.js b/src/lib/stores/user.js new file mode 100644 index 0000000..6648031 --- /dev/null +++ b/src/lib/stores/user.js @@ -0,0 +1,4 @@ +import { writable } from 'svelte/store'; + +export let user = writable(0); +export let logged_in = writable(false); diff --git a/src/lib/timeline.js b/src/lib/timeline.js index a9fcdbf..0ef7b8f 100644 --- a/src/lib/timeline.js +++ b/src/lib/timeline.js @@ -2,7 +2,7 @@ import { client } from '$lib/client/client.js'; import { get, writable } from 'svelte/store'; import { parsePost } from '$lib/client/api.js'; -export let posts = writable([]); +export let timeline = writable([]); let loading = false; @@ -11,8 +11,8 @@ export async function getTimeline(clean) { loading = true; let timeline_data; - if (clean || get(posts).length === 0) timeline_data = await get(client).getTimeline() - else timeline_data = await get(client).getTimeline(get(posts)[get(posts).length - 1].id); + if (clean || get(timeline).length === 0) timeline_data = await get(client).getTimeline() + else timeline_data = await get(client).getTimeline(get(timeline)[get(timeline).length - 1].id); if (!timeline_data) { console.error(`Failed to retrieve timeline.`); @@ -20,7 +20,7 @@ export async function getTimeline(clean) { return; } - if (clean) posts.set([]); + if (clean) timeline.set([]); for (let i in timeline_data) { const post_data = timeline_data[i]; @@ -36,7 +36,7 @@ export async function getTimeline(clean) { } continue; } - posts.update(current => [...current, post]); + timeline.update(current => [...current, post]); } loading = false; } diff --git a/src/lib/ui/Button.svelte b/src/lib/ui/Button.svelte index 4a7d95e..ea68fc4 100644 --- a/src/lib/ui/Button.svelte +++ b/src/lib/ui/Button.svelte @@ -1,6 +1,8 @@ + + +

+ Post by {@html post.user.rich_name} +

{/await} -
{#await post} -
+
loading post...
{:then post} @@ -78,11 +89,19 @@