Implement centralized collapse state management in NostrFeed component

- Introduced a centralized mechanism for managing the collapse state of posts, allowing for automatic collapsing of posts with more than 2 direct replies.
- Enhanced the ThreadedPost component to utilize the centralized collapse state, improving the visibility and interaction of nested replies.
- Added cascading collapse functionality to ensure that all descendant posts are collapsed when a parent post is collapsed.

These changes contribute to a more organized and user-friendly experience within the NostrFeed module.
This commit is contained in:
padreug 2025-09-20 15:40:43 +02:00
parent 1e1cd69aaf
commit 872954d5ce
2 changed files with 86 additions and 8 deletions

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref, computed } from 'vue'
import { computed } from 'vue'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { formatDistanceToNow } from 'date-fns'
@ -12,22 +12,30 @@ interface Props {
getDisplayName: (pubkey: string) => string
getEventReactions: (eventId: string) => { likes: number; userHasLiked: boolean }
depth?: number
parentCollapsed?: boolean
collapsedPosts?: Set<string>
}
interface Emits {
(e: 'reply-to-note', note: { id: string; content: string; pubkey: string }): void
(e: 'toggle-like', note: FeedPost): void
(e: 'toggle-collapse', postId: string): void
}
const props = withDefaults(defineProps<Props>(), {
adminPubkeys: () => [],
depth: 0
depth: 0,
parentCollapsed: false,
collapsedPosts: () => new Set<string>()
})
const emit = defineEmits<Emits>()
// Collapse state for this post's replies - auto-collapse if more than 2 direct replies
const isCollapsed = ref((props.post.replies?.length || 0) > 2)
// Check if this post is collapsed based on centralized state
const isCollapsed = computed(() => props.collapsedPosts?.has(props.post.id) || false)
// Check if this post should be visible (not hidden by parent collapse)
const isVisible = computed(() => !props.parentCollapsed)
// Check if this is an admin post
const isAdminPost = computed(() => props.adminPubkeys.includes(props.post.pubkey))
@ -47,9 +55,9 @@ const replyCount = computed(() => {
return countReplies(props.post)
})
// Toggle collapse state
// Toggle collapse state - emit to parent for centralized management
function toggleCollapse() {
isCollapsed.value = !isCollapsed.value
emit('toggle-collapse', props.post.id)
}
// Handle reply action
@ -101,7 +109,7 @@ function getRideshareType(post: FeedPost): string {
</script>
<template>
<div class="relative">
<div v-if="isVisible" class="relative">
<!-- Vertical line connecting to parent (for nested replies) -->
<div
v-if="depth > 0"
@ -241,8 +249,11 @@ function getRideshareType(post: FeedPost): string {
:get-display-name="getDisplayName"
:get-event-reactions="getEventReactions"
:depth="depth + 1"
:parent-collapsed="isCollapsed"
:collapsed-posts="collapsedPosts"
@reply-to-note="$emit('reply-to-note', $event)"
@toggle-like="$emit('toggle-like', $event)"
@toggle-collapse="$emit('toggle-collapse', $event)"
/>
<!-- Show "Load more replies" button when collapsed and there are more than 2 replies -->