diff --git a/bun.lockb b/bun.lockb index 04ac9f1..80d6bb3 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/components/buttons/base.vue b/components/buttons/base.vue index 693622f..a9f092e 100644 --- a/components/buttons/base.vue +++ b/components/buttons/base.vue @@ -1,6 +1,6 @@ + class="rounded-md duration-200 hover:shadow disabled:opacity-70 disabled:cursor-not-allowed px-3 py-2 text-sm font-semibold text-white shadow-sm"> diff --git a/components/sidebars/navigation.vue b/components/sidebars/navigation.vue new file mode 100644 index 0000000..3db4aa3 --- /dev/null +++ b/components/sidebars/navigation.vue @@ -0,0 +1,48 @@ + + + + + \ No newline at end of file diff --git a/composables/ExtendedDescription.ts b/composables/ExtendedDescription.ts new file mode 100644 index 0000000..34c0e4e --- /dev/null +++ b/composables/ExtendedDescription.ts @@ -0,0 +1,13 @@ +import type { Mastodon } from "megalodon"; + +export const useExtendedDescription = async (client: Mastodon | null) => { + if (!client) { + return null; + } + + return (await client.client.get("/api/v1/instance/extended_description")) + .data as { + updated_at: string; + content: string; + }; +}; diff --git a/composables/Instance.ts b/composables/Instance.ts index 87d9403..75cd4c0 100644 --- a/composables/Instance.ts +++ b/composables/Instance.ts @@ -1,9 +1,12 @@ import type { Mastodon } from "megalodon"; +import type { Instance } from "~/types/mastodon/instance"; export const useInstance = async (client: Mastodon | null) => { if (!client) { return null; } - return (await client.getInstance()).data; + return (await client.getInstance()).data as Instance & { + banner?: string; + }; }; diff --git a/composables/LocalTimeline.ts b/composables/LocalTimeline.ts new file mode 100644 index 0000000..a096e70 --- /dev/null +++ b/composables/LocalTimeline.ts @@ -0,0 +1,86 @@ +import type { Mastodon } from "megalodon"; +import type { Status } from "~/types/mastodon/status"; + +export const useLocalTimeline = ( + client: Mastodon | null, + options: MaybeRef< + Partial<{ + only_media: boolean; + max_id: string; + since_id: string; + min_id: string; + limit: number; + }> + >, +): { + timeline: Ref; + loadNext: () => Promise; + loadPrev: () => Promise; +} => { + if (!client) { + return { + timeline: ref([]), + loadNext: async () => {}, + loadPrev: async () => {}, + }; + } + + const fetchedNotes = ref([]); + const fetchedNoteIds = new Set(); + let nextMaxId: string | undefined = undefined; + let prevMinId: string | undefined = undefined; + + const loadNext = async () => { + const response = await client.getLocalTimeline({ + ...ref(options).value, + max_id: nextMaxId, + limit: useConfig().NOTES_PER_PAGE, + }); + + const newNotes = response.data.filter( + (note) => !fetchedNoteIds.has(note.id), + ); + if (newNotes.length > 0) { + fetchedNotes.value = [...fetchedNotes.value, ...newNotes]; + nextMaxId = newNotes[newNotes.length - 1].id; + for (const note of newNotes) { + fetchedNoteIds.add(note.id); + } + } else { + nextMaxId = undefined; + } + }; + + const loadPrev = async () => { + const response = await client.getLocalTimeline({ + ...ref(options).value, + min_id: prevMinId, + limit: useConfig().NOTES_PER_PAGE, + }); + + const newNotes = response.data.filter( + (note) => !fetchedNoteIds.has(note.id), + ); + if (newNotes.length > 0) { + fetchedNotes.value = [...newNotes, ...fetchedNotes.value]; + prevMinId = newNotes[0].id; + for (const note of newNotes) { + fetchedNoteIds.add(note.id); + } + } else { + prevMinId = undefined; + } + }; + + watch( + () => ref(options).value, + async ({ max_id, min_id }) => { + nextMaxId = max_id; + prevMinId = min_id; + await loadNext(); + }, + { immediate: true }, + ); + + return { timeline: fetchedNotes, loadNext, loadPrev }; +}; diff --git a/layouts/default.vue b/layouts/default.vue index b94471a..5d06042 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -1,5 +1,6 @@ + diff --git a/package.json b/package.json index c182562..78dec36 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,8 @@ "@fortawesome/fontawesome-common-types", "@fortawesome/free-regular-svg-icons", "@fortawesome/free-solid-svg-icons", - "json-editor-vue" + "esbuild", + "json-editor-vue", + "vue-demi" ] } diff --git a/pages/[username]/index.vue b/pages/[username]/index.vue index 85e2a33..12c9a7c 100644 --- a/pages/[username]/index.vue +++ b/pages/[username]/index.vue @@ -1,6 +1,6 @@ + class="flex mx-auto md:pl-20 max-w-7xl min-h-screen flex-col gap-x-6 md:flex-row justify-center items-start md:py-12 lg:pr-8 relative"> diff --git a/pages/index.vue b/pages/index.vue index bd78802..f52f61c 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -1,7 +1,9 @@ - + + - + + @@ -52,11 +54,51 @@ + \ No newline at end of file