feat: show avatar for mentioned users

This commit is contained in:
kolaente 2025-11-10 11:25:47 +01:00
parent 0d83a568ce
commit 435d029f33
No known key found for this signature in database
GPG Key ID: F40E70337AB24C9B
2 changed files with 63 additions and 16 deletions

View File

@ -146,7 +146,7 @@ import EditorToolbar from './EditorToolbar.vue'
import StarterKit from '@tiptap/starter-kit'
import {Extension, mergeAttributes} from '@tiptap/core'
import {EditorContent, type Extensions, useEditor} from '@tiptap/vue-3'
import {EditorContent, type Extensions, useEditor, VueNodeViewRenderer} from '@tiptap/vue-3'
import {Plugin, PluginKey} from '@tiptap/pm/state'
import {marked} from 'marked'
import {BubbleMenu} from '@tiptap/vue-3/menus'
@ -168,6 +168,7 @@ import {Node} from '@tiptap/pm/model'
import Commands from './commands'
import suggestionSetup from './suggestion'
import mentionSuggestionSetup from './mention/mentionSuggestion'
import MentionUser from './mention/MentionUser.vue'
import {common, createLowlight} from 'lowlight'
@ -494,6 +495,23 @@ if (props.enableMentions && props.mentionProjectId > 0) {
class: 'mention',
},
suggestion: mentionSuggestionSetup(props.mentionProjectId),
}).extend({
parseHTML() {
return [
{
tag: 'mention-user',
},
]
},
renderHTML({ HTMLAttributes }) {
return ['mention-user', mergeAttributes(HTMLAttributes)]
},
addNodeView() {
return VueNodeViewRenderer(MentionUser)
},
}),
)
}
@ -822,21 +840,6 @@ watch(
border-radius: $radius;
}
// Mention styles
.mention {
background-color: var(--grey-200);
color: var(--grey-800);
border-radius: 0.25rem;
padding: 0.125rem 0.375rem;
font-weight: 400;
text-decoration: none;
cursor: default;
&:hover {
background-color: var(--grey-300);
}
}
pre {
background: var(--grey-200);
color: var(--grey-700);

View File

@ -0,0 +1,44 @@
<template>
<NodeViewWrapper class="mention-user">
<img :src="avatarUrl">
<span class="mention__label">
{{ node.attrs.label ?? node.attrs.id }}
</span>
</NodeViewWrapper>
</template>
<script lang="ts" setup>
import { fetchAvatarBlobUrl } from '@/models/user'
import { nodeViewProps, NodeViewWrapper } from '@tiptap/vue-3'
import { watch, ref } from 'vue'
const props = defineProps(nodeViewProps)
const avatarUrl = ref('')
watch(
() => props.node.attrs.id,
async () => {
avatarUrl.value = await fetchAvatarBlobUrl({username: props.node.attrs.id}, 32)
},
{immediate: true},
)
</script>
<style lang="scss">
.tiptap .mention-user {
display: inline-flex;
align-items: center;
position: relative;
inset-block-end: 0;
padding-inline-start: 1.75rem;
> img {
border-radius: 100%;
inline-size: 1.5rem;
block-size: 1.5rem;
position: absolute;
inset-inline-start: 0;
}
}
</style>