feat: Create new user profile view, refine components, add dropdown to notes

This commit is contained in:
Jesse Wierzbinski 2024-04-24 20:56:01 -10:00
parent a0d0737683
commit a17df9fff8
No known key found for this signature in database
21 changed files with 470 additions and 133 deletions

View file

@ -0,0 +1,92 @@
import type { Mastodon } from "megalodon";
import type { Status } from "~/types/mastodon/status";
export const useAccountTimeline = (
client: Mastodon | null,
id: string | null,
options: MaybeRef<
Partial<{
limit?: number | undefined;
max_id?: string | undefined;
since_id?: string | undefined;
min_id?: string | undefined;
pinned?: boolean | undefined;
exclude_replies?: boolean | undefined;
exclude_reblogs?: boolean | undefined;
only_media: boolean;
}>
>,
): {
timeline: Ref<Status[]>;
loadNext: () => Promise<void>;
loadPrev: () => Promise<void>;
} => {
if (!client || !id) {
return {
timeline: ref([]),
loadNext: async () => {},
loadPrev: async () => {},
};
}
const fetchedNotes = ref<Status[]>([]);
const fetchedNoteIds = new Set<string>();
let nextMaxId: string | undefined = undefined;
let prevMinId: string | undefined = undefined;
const loadNext = async () => {
const response = await client.getAccountStatuses(id, {
only_media: false,
...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.getAccountStatuses(id, {
only_media: false,
...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 };
};

View file

@ -1,7 +1,7 @@
import { renderToString } from "vue/server-renderer";
import type { Account } from "~/types/mastodon/account";
import type { Emoji } from "~/types/mastodon/emoji";
import MentionComponent from "../components/social-elements/notes/mention.vue";
import { renderToString } from "vue/server-renderer";
/**
* Takes in an HTML string, parses emojis and returns a reactive object with the parsed content.
@ -55,5 +55,24 @@ export const useParsedContent = async (
link.outerHTML = await renderToString(renderedMention);
}
// Highlight code blocks
const codeBlocks = contentHtml.querySelectorAll("pre code");
for (const codeBlock of codeBlocks) {
const code = codeBlock.textContent;
if (!code) {
continue;
}
const newCode = (await getShikiHighlighter()).highlight(code, {
lang: codeBlock.getAttribute("class")?.replace("language-", ""),
});
// Replace parent pre tag with highlighted code
const parent = codeBlock.parentElement;
if (!parent) {
continue;
}
parent.outerHTML = newCode;
}
return ref(contentHtml.innerHTML);
};