diff options
Diffstat (limited to 'packages/frontend-embed/src/components/EmNoteSub.vue')
| -rw-r--r-- | packages/frontend-embed/src/components/EmNoteSub.vue | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/packages/frontend-embed/src/components/EmNoteSub.vue b/packages/frontend-embed/src/components/EmNoteSub.vue new file mode 100644 index 0000000000..9fbd1eae35 --- /dev/null +++ b/packages/frontend-embed/src/components/EmNoteSub.vue @@ -0,0 +1,151 @@ +<!-- +SPDX-FileCopyrightText: syuilo and misskey-project +SPDX-License-Identifier: AGPL-3.0-only +--> + +<template> +<div :class="[$style.root, { [$style.children]: depth > 1 }]"> + <div :class="$style.main"> + <div v-if="note.channel" :class="$style.colorBar" :style="{ background: note.channel.color }"></div> + <EmAvatar :class="$style.avatar" :user="note.user" link preview/> + <div :class="$style.body"> + <EmNoteHeader :class="$style.header" :note="note" :mini="true"/> + <div> + <p v-if="note.cw != null" :class="$style.cw"> + <EmMfm v-if="note.cw != ''" style="margin-right: 8px;" :text="note.cw" :author="note.user" :nyaize="'respect'" :isBlock="true"/> + <button style="display: block; width: 100%;" class="_buttonGray _buttonRounded" @click="showContent = !showContent">{{ showContent ? i18n.ts._cw.hide : i18n.ts._cw.show }}</button> + </p> + <div v-show="note.cw == null || showContent"> + <EmSubNoteContent :class="$style.text" :note="note"/> + </div> + </div> + </div> + </div> + <template v-if="depth < 5"> + <EmNoteSub v-for="reply in replies" :key="reply.id" :note="reply" :class="$style.reply" :detail="true" :depth="depth + 1"/> + </template> + <div v-else :class="$style.more"> + <EmA class="_link" :to="notePage(note)">{{ i18n.ts.continueThread }} <i class="ti ti-chevron-double-right"></i></EmA> + </div> +</div> +</template> + +<script lang="ts" setup> +import { ref } from 'vue'; +import * as Misskey from 'misskey-js'; +import EmA from '@/components/EmA.vue'; +import EmAvatar from '@/components/EmAvatar.vue'; +import EmNoteHeader from '@/components/EmNoteHeader.vue'; +import EmSubNoteContent from '@/components/EmSubNoteContent.vue'; +import { notePage } from '@/utils.js'; +import { misskeyApi } from '@/misskey-api.js'; +import { i18n } from '@/i18n.js'; +import EmMfm from '@/components/EmMfm.js'; + +const props = withDefaults(defineProps<{ + note: Misskey.entities.Note; + detail?: boolean; + + // how many notes are in between this one and the note being viewed in detail + depth?: number; +}>(), { + depth: 1, +}); + +const showContent = ref(false); +const replies = ref<Misskey.entities.Note[]>([]); + +if (props.detail) { + misskeyApi('notes/children', { + noteId: props.note.id, + limit: 5, + }).then(res => { + replies.value = res; + }); +} +</script> + +<style lang="scss" module> +.root { + padding: 16px 32px; + font-size: 0.9em; + position: relative; + + &.children { + padding: 10px 0 0 16px; + font-size: 1em; + } +} + +.main { + display: flex; +} + +.colorBar { + position: absolute; + top: 8px; + left: 8px; + width: 5px; + height: calc(100% - 8px); + border-radius: 999px; + pointer-events: none; +} + +.avatar { + flex-shrink: 0; + display: block; + margin: 0 8px 0 0; + width: 38px; + height: 38px; + border-radius: 8px; +} + +.body { + flex: 1; + min-width: 0; +} + +.header { + margin-bottom: 2px; +} + +.cw { + cursor: default; + display: block; + margin: 0; + padding: 0; + overflow-wrap: break-word; +} + +.text { + margin: 0; + padding: 0; +} + +.reply, .more { + border-left: solid 0.5px var(--divider); + margin-top: 10px; +} + +.more { + padding: 10px 0 0 16px; +} + +@container (max-width: 450px) { + .root { + padding: 14px 16px; + + &.children { + padding: 10px 0 0 8px; + } + } +} + +.muted { + text-align: center; + padding: 8px !important; + border: 1px solid var(--divider); + margin: 8px 8px 0 8px; + border-radius: 8px; +} +</style> |