refactor: simplify reactions group usage

This commit is contained in:
Tim
2025-10-15 17:47:45 +08:00
parent a8667ce5e9
commit e9e996f291
4 changed files with 257 additions and 93 deletions

View File

@@ -53,14 +53,29 @@
@click="handleContentClick"
></div>
<div class="article-footer-container">
<ReactionsGroup v-model="comment.reactions" content-type="comment" :content-id="comment.id">
<div class="make-reaction-item comment-reaction" @click="toggleEditor">
<ReactionsGroup
ref="commentReactionsGroupRef"
v-model="comment.reactions"
content-type="comment"
:content-id="comment.id"
/>
<div class="comment-reaction-actions">
<div
class="reaction-action like-action"
:class="{ selected: commentLikedByMe }"
@click="toggleCommentLike"
>
<like v-if="!commentLikedByMe" />
<like v-else theme="filled" />
<span v-if="commentLikeCount" class="reaction-count">{{ commentLikeCount }}</span>
</div>
<div class="reaction-action comment-reaction" @click="toggleEditor">
<comment-icon />
</div>
<div class="make-reaction-item copy-link" @click="copyCommentLink">
<div class="reaction-action copy-link" @click="copyCommentLink">
<link-icon />
</div>
</ReactionsGroup>
</div>
</div>
<div class="comment-editor-wrapper" ref="editorWrapper">
<CommentEditor
@@ -156,6 +171,18 @@ const lightboxVisible = ref(false)
const lightboxIndex = ref(0)
const lightboxImgs = ref([])
const loggedIn = computed(() => authState.loggedIn)
const commentReactionsGroupRef = ref(null)
const commentLikeCount = computed(
() => (props.comment.reactions || []).filter((reaction) => reaction.type === 'LIKE').length,
)
const commentLikedByMe = computed(() =>
(props.comment.reactions || []).some(
(reaction) => reaction.type === 'LIKE' && reaction.user === authState.username,
),
)
const toggleCommentLike = () => {
commentReactionsGroupRef.value?.toggleReaction('LIKE')
}
const countReplies = (list) => list.reduce((sum, r) => sum + 1 + countReplies(r.reply || []), 0)
const replyCount = computed(() => countReplies(props.comment.reply || []))
const isCommentFromPostAuthor = computed(() => {
@@ -365,6 +392,56 @@ const handleContentClick = (e) => {
</script>
<style scoped>
.article-footer-container {
display: flex;
flex-direction: row;
align-items: center;
gap: 10px;
flex-wrap: wrap;
margin-top: 6px;
}
.comment-reaction-actions {
display: flex;
flex-direction: row;
align-items: center;
gap: 10px;
}
.reaction-action {
cursor: pointer;
padding: 4px 10px;
border-radius: 10px;
display: flex;
flex-direction: row;
align-items: center;
gap: 5px;
opacity: 0.6;
font-size: 18px;
transition:
background-color 0.2s ease,
opacity 0.2s ease;
}
.reaction-action:hover {
opacity: 1;
background-color: var(--normal-light-background-color);
}
.reaction-action.like-action {
color: #ff0000;
}
.reaction-action.selected {
opacity: 1;
background-color: var(--normal-light-background-color);
}
.reaction-count {
font-size: 14px;
font-weight: bold;
}
.reply-toggle {
cursor: pointer;
color: var(--primary-color);
@@ -378,10 +455,6 @@ const handleContentClick = (e) => {
color: var(--primary-color);
}
.comment-reaction:hover {
background-color: lightgray;
}
.comment-highlight {
animation: highlight 2s;
}

View File

@@ -35,18 +35,6 @@
</template>
</div>
</div>
<div class="make-reaction-container">
<div
v-if="props.contentType !== 'message'"
class="make-reaction-item like-reaction"
@click="toggleReaction('LIKE')"
>
<like v-if="!userReacted('LIKE')" />
<like v-else theme="filled" />
<span class="reactions-count" v-if="likeCount">{{ likeCount }}</span>
</div>
<slot></slot>
</div>
<div
v-if="panelVisible"
class="reactions-panel"
@@ -102,8 +90,6 @@ const counts = computed(() => {
})
const totalCount = computed(() => Object.values(counts.value).reduce((a, b) => a + b, 0))
const likeCount = computed(() => counts.value['LIKE'] || 0)
const userReacted = (type) =>
reactions.value.some((r) => r.type === type && r.user === authState.username)
@@ -152,7 +138,7 @@ const displayedReactions = computed(() => {
.map((type) => ({ type }))
})
const panelTypes = computed(() => sortedReactionTypes.value.filter((t) => t !== 'LIKE'))
const panelTypes = computed(() => sortedReactionTypes.value)
const panelVisible = ref(false)
let hideTimer = null
@@ -246,6 +232,10 @@ const toggleReaction = async (type) => {
onMounted(async () => {
await initialize()
})
defineExpose({
toggleReaction,
})
</script>
<style>
@@ -253,11 +243,7 @@ onMounted(async () => {
position: relative;
display: flex;
flex-direction: row;
gap: 10px;
align-items: center;
width: 100%;
justify-content: space-between;
flex-wrap: wrap;
}
.reactions-viewer {
@@ -295,32 +281,6 @@ onMounted(async () => {
padding-left: 5px;
}
.make-reaction-container {
display: flex;
flex-direction: row;
gap: 10px;
}
.make-reaction-item {
cursor: pointer;
padding: 4px;
opacity: 0.5;
border-radius: 8px;
font-size: 20px;
}
.like-reaction {
color: #ff0000;
display: flex;
flex-direction: row;
align-items: center;
gap: 5px;
}
.make-reaction-item:hover {
background-color: #ffe2e2;
}
.reactions-count {
font-size: 16px;
font-weight: bold;