Create post content component

This commit is contained in:
silverpill 2022-10-02 15:47:00 +00:00
parent 816c133479
commit b4c2ab260e
2 changed files with 120 additions and 98 deletions

View file

@ -57,7 +57,7 @@
@{{ mention.username }}
</a>
</div>
<div class="post-content" ref="postContentRef" v-html="getContent()"></div>
<post-content :post="post"></post-content>
<div class="post-attachment" v-if="post.media_attachments.length > 0">
<template v-for="attachment in post.media_attachments" :key="attachment.id">
<img v-if="attachment.type === 'image'" :src="attachment.url">
@ -77,7 +77,7 @@
@{{ getActorAddress(post.quote.account) }}
</span>
</div>
<div class="quote-content" v-html="post.quote.content"></div>
<post-content :post="post.quote"></post-content>
</a>
<div class="post-footer">
<router-link
@ -223,7 +223,6 @@
<script setup lang="ts">
/* eslint-disable vue/no-mutating-props */
import { onMounted } from "vue"
import { $, $computed, $ref } from "vue/macros"
import { useRouter } from "vue-router"
@ -247,6 +246,7 @@ import {
import { ProfileWrapper } from "@/api/users"
import Avatar from "@/components/Avatar.vue"
import CryptoAddress from "@/components/CryptoAddress.vue"
import PostContent from "@/components/PostContent.vue"
import PostEditor from "@/components/PostEditor.vue"
import VisibilityIcon from "@/components/VisibilityIcon.vue"
import { useInstanceInfo } from "@/store/instance"
@ -254,7 +254,6 @@ import { useCurrentUser } from "@/store/user"
import { CRYPTOCURRENCIES } from "@/utils/cryptocurrencies"
import { getWallet } from "@/utils/ethereum"
import { humanizeDate } from "@/utils/dates"
import { addGreentext } from "@/utils/greentext"
interface PaymentOption {
code: string;
@ -281,8 +280,6 @@ const emit = defineEmits<{
(event: "post-deleted"): void,
}>()
const postContentRef = $ref<HTMLElement | null>(null)
let commentFormVisible = $ref(false)
let menuVisible = $ref(false)
let selectedPaymentAddress = $ref<string | null>(null)
@ -291,55 +288,6 @@ let isWaitingForToken = $ref(false)
const blockchain = $computed(() => instance?.blockchains[0])
const author = $computed(() => new ProfileWrapper(props.post.account))
onMounted(() => {
if (currentUser !== null) {
configureInlineLinks()
}
})
function configureInlineLinks() {
if (postContentRef === null) {
return
}
const mentions = postContentRef.getElementsByClassName("mention")
for (const mentionElement of Array.from(mentions)) {
const mention = props.post.mentions
.find((mention) => mentionElement.getAttribute("href") === mention.url)
if (mention) {
mentionElement.addEventListener("click", (event: Event) => {
event.preventDefault()
router.push({ name: "profile", params: { profileId: mention.id } })
})
}
}
const hashtags = postContentRef.getElementsByClassName("hashtag")
for (const hashtagElement of Array.from(hashtags)) {
const hashtag = props.post.tags
.find((tag) => {
const innerText = (hashtagElement as HTMLElement).innerText
return innerText.toLowerCase() === `#${tag.name}`
})
if (hashtag) {
hashtagElement.addEventListener("click", (event: Event) => {
event.preventDefault()
router.push({ name: "tag", params: { tagName: hashtag.name } })
})
}
}
const quote = props.post.quote
if (quote) {
const links = postContentRef.querySelectorAll("a")
for (const linkElement of Array.from(links)) {
if (quote.uri === linkElement.getAttribute("href")) {
linkElement.addEventListener("click", (event: Event) => {
event.preventDefault()
router.push({ name: "post", params: { postId: quote.id } })
})
}
}
}
}
function openProfile(event: Event, profileId: string) {
if (currentUser === null) {
// Viewing as guest; do not override click handler
@ -370,11 +318,6 @@ function getVisibilityDisplay(): string {
return VISIBILITY_MAP[props.post.visibility]
}
function getContent(): string {
const content = addGreentext(props.post.content)
return content
}
function getReplyMentions(): Mention[] {
if (props.post.in_reply_to_id === null) {
return []
@ -664,40 +607,6 @@ async function onMintToken() {
}
}
.post-content {
color: $text-color;
line-height: 1.5;
padding: $block-inner-padding;
word-wrap: break-word;
:deep(a) {
@include block-link;
}
:deep(pre),
:deep(code) {
overflow-x: scroll;
}
:deep(ul),
:deep(ol) {
list-style-position: inside;
}
:deep(.greentext) {
color: $greentext-color;
}
:deep(blockquote) {
color: $greentext-color;
&::before {
content: ">";
float: left;
}
}
}
.post-quote {
border: 1px solid $separator-color;
border-radius: $block-border-radius;
@ -730,10 +639,6 @@ async function onMintToken() {
}
}
.quote-content {
padding: $block-inner-padding;
}
.post-attachment {
padding: 0 $block-inner-padding $block-inner-padding;
word-wrap: break-word;

View file

@ -0,0 +1,117 @@
<template>
<div class="post-content" ref="postContentRef" v-html="getContent()"></div>
</template>
<script setup lang="ts">
import { onMounted } from "vue"
import { $, $ref } from "vue/macros"
import { useRouter } from "vue-router"
import { Post } from "@/api/posts"
import { useCurrentUser } from "@/store/user"
import { addGreentext } from "@/utils/greentext"
const router = useRouter()
const { currentUser } = $(useCurrentUser())
/* eslint-disable-next-line no-undef */
const props = defineProps<{
post: Post,
}>()
const postContentRef = $ref<HTMLElement | null>(null)
onMounted(() => {
if (currentUser !== null) {
configureInlineLinks()
}
})
function configureInlineLinks() {
if (postContentRef === null) {
return
}
const mentions = postContentRef.getElementsByClassName("mention")
for (const mentionElement of Array.from(mentions)) {
const mention = props.post.mentions
.find((mention) => mentionElement.getAttribute("href") === mention.url)
if (mention) {
mentionElement.addEventListener("click", (event: Event) => {
event.preventDefault()
router.push({ name: "profile", params: { profileId: mention.id } })
})
}
}
const hashtags = postContentRef.getElementsByClassName("hashtag")
for (const hashtagElement of Array.from(hashtags)) {
const hashtag = props.post.tags
.find((tag) => {
const innerText = (hashtagElement as HTMLElement).innerText
return innerText.toLowerCase() === `#${tag.name}`
})
if (hashtag) {
hashtagElement.addEventListener("click", (event: Event) => {
event.preventDefault()
router.push({ name: "tag", params: { tagName: hashtag.name } })
})
}
}
const quote = props.post.quote
if (quote) {
const links = postContentRef.querySelectorAll("a")
for (const linkElement of Array.from(links)) {
if (quote.uri === linkElement.getAttribute("href")) {
linkElement.addEventListener("click", (event: Event) => {
event.preventDefault()
router.push({ name: "post", params: { postId: quote.id } })
})
}
}
}
}
function getContent(): string {
const content = addGreentext(props.post.content)
return content
}
</script>
<style scoped lang="scss">
@import "../styles/layout";
@import "../styles/theme";
@import "../styles/mixins";
.post-content {
color: $text-color;
line-height: 1.5;
padding: $block-inner-padding;
word-wrap: break-word;
:deep(a) {
@include block-link;
}
:deep(pre),
:deep(code) {
overflow-x: scroll;
}
:deep(ul),
:deep(ol) {
list-style-position: inside;
}
:deep(.greentext) {
color: $greentext-color;
}
:deep(blockquote) {
color: $greentext-color;
&::before {
content: ">";
float: left;
}
}
}
</style>