Enhance comment seeding and search functionality
- Updated the `seedComments` function to return an array of published comment event IDs for tracking. - Introduced `seedCommentReactions` to seed upvotes and downvotes on comments, improving interaction visibility. - Enhanced the `App.vue` and `MobileNav.vue` components to support a mobile search overlay, allowing users to search films seamlessly. - Added a new `MobileSearch` component for better search experience on mobile devices. - Implemented a search feature in `AppHeader.vue` with dropdown results for improved content discovery. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -31,14 +31,41 @@ export interface CommentNode {
|
||||
replies: CommentNode[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the net vote score (positive - negative) for a comment event
|
||||
* from a reactions map.
|
||||
*/
|
||||
function getNetVotes(eventId: string, reactionsMap: Map<string, NostrEvent[]>): number {
|
||||
const reactions = reactionsMap.get(eventId) || []
|
||||
// Deduplicate: one vote per pubkey, keep latest
|
||||
const byPubkey = new Map<string, NostrEvent>()
|
||||
for (const r of reactions) {
|
||||
const existing = byPubkey.get(r.pubkey)
|
||||
if (!existing || r.created_at > existing.created_at) {
|
||||
byPubkey.set(r.pubkey, r)
|
||||
}
|
||||
}
|
||||
let net = 0
|
||||
for (const r of byPubkey.values()) {
|
||||
if (r.content === '+') net++
|
||||
else if (r.content === '-') net--
|
||||
}
|
||||
return net
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a threaded comment tree from flat event arrays.
|
||||
* Top-level comments have #i = externalId.
|
||||
* Replies reference parent via #e tag.
|
||||
*
|
||||
* Top-level comments are sorted by net votes (most upvoted first),
|
||||
* with created_at descending as tiebreaker.
|
||||
* Replies are sorted chronologically (oldest first).
|
||||
*/
|
||||
function buildCommentTree(
|
||||
topLevel: NostrEvent[],
|
||||
allInThread: NostrEvent[],
|
||||
reactionsMap: Map<string, NostrEvent[]>,
|
||||
): CommentNode[] {
|
||||
// Group replies by parent event ID
|
||||
const childrenMap = new Map<string, NostrEvent[]>()
|
||||
@@ -66,8 +93,13 @@ function buildCommentTree(
|
||||
}
|
||||
}
|
||||
|
||||
// Sort top-level by net votes descending, then newest first as tiebreaker
|
||||
return [...topLevel]
|
||||
.sort((a, b) => b.created_at - a.created_at)
|
||||
.sort((a, b) => {
|
||||
const voteDiff = getNetVotes(b.id, reactionsMap) - getNetVotes(a.id, reactionsMap)
|
||||
if (voteDiff !== 0) return voteDiff
|
||||
return b.created_at - a.created_at
|
||||
})
|
||||
.map(buildNode)
|
||||
}
|
||||
|
||||
@@ -171,7 +203,7 @@ export function useNostr(contentId?: string) {
|
||||
}
|
||||
|
||||
allComments.value = allEvents
|
||||
commentTree.value = buildCommentTree(topLevelEvents, allEvents)
|
||||
commentTree.value = buildCommentTree(topLevelEvents, allEvents, commentReactions.value)
|
||||
|
||||
// Fetch profiles for all comment authors
|
||||
const pubkeys = [...new Set(allEvents.map((e) => e.pubkey))]
|
||||
@@ -218,6 +250,7 @@ export function useNostr(contentId?: string) {
|
||||
|
||||
/**
|
||||
* Refresh reactions for a single comment event from the store.
|
||||
* Also re-sorts the comment tree so most-voted comments float to top.
|
||||
*/
|
||||
function refreshSingleCommentReactions(eventId: string) {
|
||||
const events = eventStore.getByFilters([
|
||||
@@ -227,6 +260,25 @@ export function useNostr(contentId?: string) {
|
||||
const newMap = new Map(commentReactions.value)
|
||||
newMap.set(eventId, [...events])
|
||||
commentReactions.value = newMap
|
||||
|
||||
// Re-sort the comment tree with updated vote counts
|
||||
if (currentExternalId) {
|
||||
const topLevel = eventStore.getByFilters([
|
||||
{ kinds: [COMMENT_KIND], '#i': [currentExternalId] },
|
||||
])
|
||||
const allInThread = eventStore.getByFilters([
|
||||
{ kinds: [COMMENT_KIND], '#I': [currentExternalId] },
|
||||
])
|
||||
if (topLevel && allInThread) {
|
||||
const topLevelEvents = [...topLevel]
|
||||
const allEvents = [...allInThread]
|
||||
const allIds = new Set(allEvents.map((e) => e.id))
|
||||
for (const e of topLevelEvents) {
|
||||
if (!allIds.has(e.id)) allEvents.push(e)
|
||||
}
|
||||
commentTree.value = buildCommentTree(topLevelEvents, allEvents, newMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user