feat: Render notes with replies in a thread view

This commit is contained in:
Jesse Wierzbinski 2024-12-29 14:51:21 +01:00
parent 977defc169
commit 0a977468d0
No known key found for this signature in database
4 changed files with 35 additions and 8 deletions

View file

@ -1,14 +1,17 @@
<template> <template>
<Card as="article" class="rounded-none border-0 duration-200 shadow- max-w-full"> <Card as="article" class="rounded-none border-0 duration-200 shadow- max-w-full relative">
<CardHeader class="pb-4" as="header"> <CardHeader class="pb-4" as="header">
<ReblogHeader v-if="note.reblog" :avatar="note.account.avatar" :display-name="note.account.display_name" <ReblogHeader v-if="note.reblog" :avatar="note.account.avatar" :display-name="note.account.display_name"
:url="reblogAccountUrl" :emojis="note.account.emojis" /> :url="reblogAccountUrl" :emojis="note.account.emojis" />
<Header :author="noteToUse.account" :author-url="accountUrl" <Header :author="noteToUse.account" :author-url="accountUrl"
:corner-avatar="note.reblog ? note.account.avatar : undefined" :note-url="url" :corner-avatar="note.reblog ? note.account.avatar : undefined" :note-url="url"
:visibility="noteToUse.visibility" :created-at="new Date(noteToUse.created_at)" :visibility="noteToUse.visibility" :created-at="new Date(noteToUse.created_at)"
:small-layout="smallLayout" /> :small-layout="smallLayout" class="z-[1]" />
<div v-if="topAvatarBar" :class="cn('shrink-0 bg-border w-0.5 absolute top-0 h-7 left-[3.25rem]')"></div>
<div v-if="bottomAvatarBar" :class="cn('shrink-0 bg-border w-0.5 absolute bottom-0 h-[calc(100%-1.5rem)] left-[3.25rem]')"></div>
</CardHeader> </CardHeader>
<CardContent> <!-- Simply offset by the size of avatar + 0.75rem (the gap) -->
<CardContent :class="contentUnderUsername && (smallLayout ? 'ml-11' : 'ml-[4.25rem]')">
<Content :content="noteToUse.content" :quote="note.quote ?? undefined" <Content :content="noteToUse.content" :quote="note.quote ?? undefined"
:attachments="noteToUse.media_attachments" :plain-content="noteToUse.plain_content ?? undefined" :attachments="noteToUse.media_attachments" :plain-content="noteToUse.plain_content ?? undefined"
:emojis="noteToUse.emojis" :sensitive="noteToUse.sensitive" :content-warning="noteToUse.spoiler_text" /> :emojis="noteToUse.emojis" :sensitive="noteToUse.sensitive" :content-warning="noteToUse.spoiler_text" />
@ -26,6 +29,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { cn } from "@/lib/utils";
import type { Status } from "@versia/client/types"; import type { Status } from "@versia/client/types";
import { Card, CardFooter, CardHeader } from "../ui/card"; import { Card, CardFooter, CardHeader } from "../ui/card";
import Actions from "./actions.vue"; import Actions from "./actions.vue";
@ -37,6 +41,9 @@ const { note } = defineProps<{
note: Status; note: Status;
hideActions?: boolean; hideActions?: boolean;
smallLayout?: boolean; smallLayout?: boolean;
contentUnderUsername?: boolean;
topAvatarBar?: boolean;
bottomAvatarBar?: boolean;
}>(); }>();
// Notes can be reblogs, in which case the actual thing to render is inside the reblog property // Notes can be reblogs, in which case the actual thing to render is inside the reblog property

View file

@ -0,0 +1,17 @@
<template>
<div>
<Note v-if="parent" :note="parent" :hide-actions="true" :content-under-username="true" :bottom-avatar-bar="true" />
<Note :note="note" :top-avatar-bar="!!parent" />
</div>
</template>
<script lang="ts" setup>
import type { Status } from "@versia/client/types";
import Note from "./note.vue";
const { note } = defineProps<{
note: Status;
}>();
const parent = useNote(client, note.in_reply_to_id);
</script>

View file

@ -5,7 +5,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { Notification, Status } from "@versia/client/types"; import type { Notification, Status } from "@versia/client/types";
import Note from "../notes/note.vue"; import Thread from "../notes/thread.vue";
import NotificationItem from "../notifications/notification.vue"; import NotificationItem from "../notifications/notification.vue";
const props = defineProps<{ const props = defineProps<{
@ -15,7 +15,7 @@ const props = defineProps<{
const itemComponent = computed(() => { const itemComponent = computed(() => {
if (props.type === "status") { if (props.type === "status") {
return Note; return Thread;
} }
if (props.type === "notification") { if (props.type === "notification") {
return NotificationItem; return NotificationItem;

View file

@ -1,7 +1,10 @@
<template> <template>
<div v-if="loaded" class="mx-auto max-w-2xl w-full pb-72 *:rounded space-y-4 *:border"> <div v-if="loaded" class="mx-auto max-w-2xl w-full pb-72 *:rounded space-y-4 *:border">
<Note v-for="note of context?.ancestors" :note="note" /> <div>
<Note v-if="note" :note="note" /> <Note v-for="note, index of context?.ancestors" :note="note" :hide-actions="true"
:top-avatar-bar="index !== 0" :bottom-avatar-bar="true" :content-under-username="true" />
<Note v-if="note" :note="note" :top-avatar-bar="true" />
</div>
<Note v-for="note of context?.descendants" :note="note" /> <Note v-for="note of context?.descendants" :note="note" />
</div> </div>