frontend/components/notes/content.vue

87 lines
3.5 KiB
Vue
Raw Normal View History

2024-11-30 02:19:32 +01:00
<template>
<Alert variant="warning" v-if="(sensitive || contentWarning) && showCw.value"
2024-12-07 15:16:45 +01:00
class="mb-4 py-2 px-4 grid grid-cols-[auto,1fr,auto] gap-2 items-center [&>svg~*]:pl-0 [&>svg+div]:translate-y-0 [&>svg]:static">
<AlertTitle class="sr-only">{{ m.livid_tangy_lionfish_clasp() }}</AlertTitle>
2024-12-07 15:16:45 +01:00
<div>
<TriangleAlert class="size-4" />
</div>
2024-12-07 15:16:45 +01:00
<AlertDescription>
{{ contentWarning || m.sour_seemly_bird_hike() }}
2024-12-07 15:16:45 +01:00
</AlertDescription>
<Button @click="blurred = !blurred" variant="outline" size="sm">{{ blurred ? m.bald_direct_turtle_win() : m.known_flaky_cockroach_dash() }}</Button>
2024-12-07 15:16:45 +01:00
</Alert>
<div ref="container" :class="cn('overflow-y-hidden relative duration-200', (blurred && showCw.value) && 'blur-md')" :style="{
2024-12-07 15:16:45 +01:00
maxHeight: collapsed ? '18rem' : `${container?.scrollHeight}px`,
}">
<div :class="[
'prose prose-sm block relative dark:prose-invert duration-200 !max-w-full break-words prose-a:no-underline hover:prose-a:underline',
2024-12-07 15:16:45 +01:00
$style.content,
]" v-html="content" v-render-emojis="emojis"></div>
<div v-if="isOverflowing && collapsed"
class="absolute inset-x-0 bottom-0 h-36 bg-gradient-to-t from-black/5 to-transparent rounded-b"></div>
<Button v-if="isOverflowing" @click="collapsed = !collapsed"
class="absolute bottom-2 right-1/2 translate-x-1/2">{{
2024-12-07 15:16:45 +01:00
collapsed
? `${m.lazy_honest_mammoth_bump()}${plainContent ? `${m.dark_spare_goldfish_charm({
count: formattedCharacterCount ?? '0',
})}` : "" }`
: m.that_misty_mule_arrive()
}}</Button>
2024-11-30 02:19:32 +01:00
</div>
2024-11-30 16:39:02 +01:00
<Attachments v-if="attachments.length > 0" :attachments="attachments" :class="(blurred && showCw.value) && 'blur-xl'" />
2024-11-30 19:15:23 +01:00
<div v-if="quote" class="mt-4 rounded border overflow-hidden">
2024-11-30 16:39:02 +01:00
<Note :note="quote" :hide-actions="true" :small-layout="true" />
</div>
2024-11-30 02:19:32 +01:00
</template>
<script lang="ts" setup>
2024-12-07 15:16:45 +01:00
import { cn } from "@/lib/utils";
import type { Attachment, Emoji, Status } from "@versia/client/types";
2024-12-07 15:16:45 +01:00
import { TriangleAlert } from "lucide-vue-next";
import { Button } from "~/components/ui/button";
import * as m from "~/paraglide/messages.js";
import { type BooleanSetting, SettingIds } from "~/settings";
2024-12-07 15:16:45 +01:00
import { Alert, AlertDescription, AlertTitle } from "../ui/alert";
import Attachments from "./attachments.vue";
2024-11-30 16:39:02 +01:00
import Note from "./note.vue";
2024-12-07 15:16:45 +01:00
const { content, plainContent, sensitive, contentWarning } = defineProps<{
plainContent?: string;
2024-11-30 02:19:32 +01:00
content: string;
2024-11-30 16:39:02 +01:00
quote?: NonNullable<Status["quote"]>;
emojis: Emoji[];
attachments: Attachment[];
2024-12-07 15:16:45 +01:00
sensitive: boolean;
contentWarning?: string;
2024-11-30 02:19:32 +01:00
}>();
const container = ref<HTMLDivElement | null>(null);
const collapsed = ref(true);
2024-12-07 15:16:45 +01:00
const blurred = ref(sensitive || !!contentWarning);
const showCw = useSetting(SettingIds.ShowContentWarning) as Ref<BooleanSetting>;
// max-h-72 is 18rem
const remToPx = (rem: number) =>
rem *
Number.parseFloat(
getComputedStyle(document.documentElement).fontSize || "16px",
);
const isOverflowing = computed(() => {
if (!container.value) {
return false;
}
return container.value.scrollHeight > remToPx(18);
});
const characterCount = plainContent?.length;
const formattedCharacterCount = characterCount
2024-12-07 23:05:26 +01:00
? new Intl.NumberFormat(getLanguageTag()).format(characterCount)
: undefined;
2024-11-30 02:19:32 +01:00
</script>
<style module>
@import url("~/styles/content.css");
2024-12-07 15:16:45 +01:00
</style>