Revert "feat: support displaying highlights in replies"
This reverts commit d2c5c923a3.
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
import { useFetchEvent, useTranslatedEvent } from '@/hooks'
|
import { useFetchEvent, useTranslatedEvent } from '@/hooks'
|
||||||
import { createFakeEvent } from '@/lib/event'
|
import { createFakeEvent } from '@/lib/event'
|
||||||
import { getHighlightSourceTag } from '@/lib/event-metadata'
|
|
||||||
import { toNote } from '@/lib/link'
|
import { toNote } from '@/lib/link'
|
||||||
import { isValidPubkey } from '@/lib/pubkey'
|
import { isValidPubkey } from '@/lib/pubkey'
|
||||||
import { generateBech32IdFromATag, generateBech32IdFromETag } from '@/lib/tag'
|
import { generateBech32IdFromATag, generateBech32IdFromETag } from '@/lib/tag'
|
||||||
@@ -38,7 +37,36 @@ export default function Highlight({ event, className }: { event: Event; classNam
|
|||||||
function HighlightSource({ event }: { event: Event }) {
|
function HighlightSource({ event }: { event: Event }) {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { push } = useSecondaryPage()
|
const { push } = useSecondaryPage()
|
||||||
const sourceTag = useMemo(() => getHighlightSourceTag(event), [event])
|
const sourceTag = useMemo(() => {
|
||||||
|
let sourceTag: string[] | undefined
|
||||||
|
for (const tag of event.tags) {
|
||||||
|
// Highest priority: 'source' tag
|
||||||
|
if (tag[2] === 'source') {
|
||||||
|
sourceTag = tag
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// Give 'e' tags highest priority
|
||||||
|
if (tag[0] === 'e') {
|
||||||
|
sourceTag = tag
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Give 'a' tags second priority over 'e' tags
|
||||||
|
if (tag[0] === 'a' && (!sourceTag || sourceTag[0] !== 'e')) {
|
||||||
|
sourceTag = tag
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Give 'r' tags lowest priority
|
||||||
|
if (tag[0] === 'r' && (!sourceTag || sourceTag[0] === 'r')) {
|
||||||
|
sourceTag = tag
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sourceTag
|
||||||
|
}, [event])
|
||||||
const { event: referenceEvent } = useFetchEvent(
|
const { event: referenceEvent } = useFetchEvent(
|
||||||
sourceTag
|
sourceTag
|
||||||
? sourceTag[0] === 'e'
|
? sourceTag[0] === 'e'
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
import { useTranslatedEvent } from '@/hooks'
|
|
||||||
import { createFakeEvent } from '@/lib/event'
|
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
import { Event } from 'nostr-tools'
|
|
||||||
import { useMemo } from 'react'
|
|
||||||
import Content from '../Content'
|
|
||||||
|
|
||||||
export default function Highlight({ event, className }: { event: Event; className?: string }) {
|
|
||||||
const translatedEvent = useTranslatedEvent(event.id)
|
|
||||||
const comment = useMemo(
|
|
||||||
() => (translatedEvent?.tags ?? event.tags).find((tag) => tag[0] === 'comment')?.[1],
|
|
||||||
[event, translatedEvent]
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={cn('text-wrap break-words whitespace-pre-wrap space-y-4', className)}>
|
|
||||||
{comment && <Content event={createFakeEvent({ content: comment })} />}
|
|
||||||
<div className="flex gap-4">
|
|
||||||
<div className="w-1 flex-shrink-0 my-1 bg-primary/60 rounded-md" />
|
|
||||||
<div className="italic whitespace-pre-line">
|
|
||||||
{translatedEvent?.content ?? event.content}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -6,7 +6,7 @@ import { toNote } from '@/lib/link'
|
|||||||
import { useContentPolicy } from '@/providers/ContentPolicyProvider'
|
import { useContentPolicy } from '@/providers/ContentPolicyProvider'
|
||||||
import { useMuteList } from '@/providers/MuteListProvider'
|
import { useMuteList } from '@/providers/MuteListProvider'
|
||||||
import { useScreenSize } from '@/providers/ScreenSizeProvider'
|
import { useScreenSize } from '@/providers/ScreenSizeProvider'
|
||||||
import { Event, kinds } from 'nostr-tools'
|
import { Event } from 'nostr-tools'
|
||||||
import { useMemo, useState } from 'react'
|
import { useMemo, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import ClientTag from '../ClientTag'
|
import ClientTag from '../ClientTag'
|
||||||
@@ -15,12 +15,11 @@ import Content from '../Content'
|
|||||||
import { FormattedTimestamp } from '../FormattedTimestamp'
|
import { FormattedTimestamp } from '../FormattedTimestamp'
|
||||||
import Nip05 from '../Nip05'
|
import Nip05 from '../Nip05'
|
||||||
import NoteOptions from '../NoteOptions'
|
import NoteOptions from '../NoteOptions'
|
||||||
import ParentNotePreview from '../ParentNotePreview'
|
|
||||||
import StuffStats from '../StuffStats'
|
import StuffStats from '../StuffStats'
|
||||||
|
import ParentNotePreview from '../ParentNotePreview'
|
||||||
import TranslateButton from '../TranslateButton'
|
import TranslateButton from '../TranslateButton'
|
||||||
import UserAvatar from '../UserAvatar'
|
import UserAvatar from '../UserAvatar'
|
||||||
import Username from '../Username'
|
import Username from '../Username'
|
||||||
import Highlight from './Highlight'
|
|
||||||
|
|
||||||
export default function ReplyNote({
|
export default function ReplyNote({
|
||||||
event,
|
event,
|
||||||
@@ -52,13 +51,6 @@ export default function ReplyNote({
|
|||||||
return true
|
return true
|
||||||
}, [showMuted, mutePubkeySet, event, hideContentMentioningMutedUsers])
|
}, [showMuted, mutePubkeySet, event, hideContentMentioningMutedUsers])
|
||||||
|
|
||||||
let content: React.ReactNode
|
|
||||||
if (event.kind === kinds.Highlights) {
|
|
||||||
content = <Highlight className="mt-2" event={event} />
|
|
||||||
} else {
|
|
||||||
content = <Content className="mt-2" event={event} />
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`pb-3 border-b transition-colors duration-500 clickable ${highlight ? 'bg-primary/50' : ''}`}
|
className={`pb-3 border-b transition-colors duration-500 clickable ${highlight ? 'bg-primary/50' : ''}`}
|
||||||
@@ -103,7 +95,7 @@ export default function ReplyNote({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{show ? (
|
{show ? (
|
||||||
content
|
<Content className="mt-2" event={event} />
|
||||||
) : (
|
) : (
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { BIG_RELAY_URLS, ExtendedKind } from '@/constants'
|
import { BIG_RELAY_URLS, ExtendedKind } from '@/constants'
|
||||||
import { useStuff } from '@/hooks/useStuff'
|
|
||||||
import {
|
import {
|
||||||
getEventKey,
|
getEventKey,
|
||||||
getKeyFromTag,
|
getKeyFromTag,
|
||||||
@@ -24,6 +23,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { LoadingBar } from '../LoadingBar'
|
import { LoadingBar } from '../LoadingBar'
|
||||||
import ReplyNote, { ReplyNoteSkeleton } from '../ReplyNote'
|
import ReplyNote, { ReplyNoteSkeleton } from '../ReplyNote'
|
||||||
|
import { useStuff } from '@/hooks/useStuff'
|
||||||
|
|
||||||
type TRootInfo =
|
type TRootInfo =
|
||||||
| { type: 'E'; id: string; pubkey: string }
|
| { type: 'E'; id: string; pubkey: string }
|
||||||
@@ -144,7 +144,7 @@ export default function ReplyNoteList({
|
|||||||
if (rootInfo.type === 'E') {
|
if (rootInfo.type === 'E') {
|
||||||
filters.push({
|
filters.push({
|
||||||
'#e': [rootInfo.id],
|
'#e': [rootInfo.id],
|
||||||
kinds: [kinds.ShortTextNote, kinds.Highlights],
|
kinds: [kinds.ShortTextNote],
|
||||||
limit: LIMIT
|
limit: LIMIT
|
||||||
})
|
})
|
||||||
if (event?.kind !== kinds.ShortTextNote) {
|
if (event?.kind !== kinds.ShortTextNote) {
|
||||||
@@ -158,7 +158,7 @@ export default function ReplyNoteList({
|
|||||||
filters.push(
|
filters.push(
|
||||||
{
|
{
|
||||||
'#a': [rootInfo.id],
|
'#a': [rootInfo.id],
|
||||||
kinds: [kinds.ShortTextNote, kinds.Highlights],
|
kinds: [kinds.ShortTextNote],
|
||||||
limit: LIMIT
|
limit: LIMIT
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -171,18 +171,11 @@ export default function ReplyNoteList({
|
|||||||
relayUrls.push(rootInfo.relay)
|
relayUrls.push(rootInfo.relay)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
filters.push(
|
filters.push({
|
||||||
{
|
'#I': [rootInfo.id],
|
||||||
'#I': [rootInfo.id],
|
kinds: [ExtendedKind.COMMENT, ExtendedKind.VOICE_COMMENT],
|
||||||
kinds: [ExtendedKind.COMMENT, ExtendedKind.VOICE_COMMENT],
|
limit: LIMIT
|
||||||
limit: LIMIT
|
})
|
||||||
},
|
|
||||||
{
|
|
||||||
'#r': [rootInfo.id],
|
|
||||||
kinds: [kinds.Highlights],
|
|
||||||
limit: LIMIT
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
const { closer, timelineKey } = await client.subscribeTimeline(
|
const { closer, timelineKey } = await client.subscribeTimeline(
|
||||||
filters.map((filter) => ({
|
filters.map((filter) => ({
|
||||||
@@ -192,9 +185,7 @@ export default function ReplyNoteList({
|
|||||||
{
|
{
|
||||||
onEvents: (evts, eosed) => {
|
onEvents: (evts, eosed) => {
|
||||||
if (evts.length > 0) {
|
if (evts.length > 0) {
|
||||||
addReplies(
|
addReplies(evts.filter((evt) => isReplyNoteEvent(evt)))
|
||||||
evts.filter((evt) => isReplyNoteEvent(evt) || evt.kind === kinds.Highlights)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
if (eosed) {
|
if (eosed) {
|
||||||
setUntil(evts.length >= LIMIT ? evts[evts.length - 1].created_at - 1 : undefined)
|
setUntil(evts.length >= LIMIT ? evts[evts.length - 1].created_at - 1 : undefined)
|
||||||
@@ -202,7 +193,7 @@ export default function ReplyNoteList({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onNew: (evt) => {
|
onNew: (evt) => {
|
||||||
if (!isReplyNoteEvent(evt) || evt.kind === kinds.Highlights) return
|
if (!isReplyNoteEvent(evt)) return
|
||||||
addReplies([evt])
|
addReplies([evt])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -258,9 +249,7 @@ export default function ReplyNoteList({
|
|||||||
|
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
const events = await client.loadMoreTimeline(timelineKey, until, LIMIT)
|
const events = await client.loadMoreTimeline(timelineKey, until, LIMIT)
|
||||||
const olderEvents = events.filter(
|
const olderEvents = events.filter((evt) => isReplyNoteEvent(evt))
|
||||||
(evt) => isReplyNoteEvent(evt) || evt.kind === kinds.Highlights
|
|
||||||
)
|
|
||||||
if (olderEvents.length > 0) {
|
if (olderEvents.length > 0) {
|
||||||
addReplies(olderEvents)
|
addReplies(olderEvents)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -403,34 +403,3 @@ export function getPinnedEventHexIdSetFromPinListEvent(event?: Event | null): Se
|
|||||||
.slice(0, MAX_PINNED_NOTES) ?? []
|
.slice(0, MAX_PINNED_NOTES) ?? []
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getHighlightSourceTag(event: Event) {
|
|
||||||
let sourceTag: string[] | undefined
|
|
||||||
for (const tag of event.tags) {
|
|
||||||
// Highest priority: 'source' tag
|
|
||||||
if (tag[2] === 'source') {
|
|
||||||
sourceTag = tag
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// Give 'e' tags highest priority
|
|
||||||
if (tag[0] === 'e') {
|
|
||||||
sourceTag = tag
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Give 'a' tags second priority over 'e' tags
|
|
||||||
if (tag[0] === 'a' && (!sourceTag || sourceTag[0] !== 'e')) {
|
|
||||||
sourceTag = tag
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Give 'r' tags lowest priority
|
|
||||||
if (tag[0] === 'r' && (!sourceTag || sourceTag[0] === 'r')) {
|
|
||||||
sourceTag = tag
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sourceTag
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { getEventKey, getKeyFromTag, getParentTag } from '@/lib/event'
|
import { getEventKey, getKeyFromTag, getParentTag } from '@/lib/event'
|
||||||
import { getHighlightSourceTag } from '@/lib/event-metadata'
|
import { Event } from 'nostr-tools'
|
||||||
import { Event, kinds } from 'nostr-tools'
|
|
||||||
import { createContext, useCallback, useContext, useState } from 'react'
|
import { createContext, useCallback, useContext, useState } from 'react'
|
||||||
|
|
||||||
type TReplyContext = {
|
type TReplyContext = {
|
||||||
@@ -31,25 +30,12 @@ export function ReplyProvider({ children }: { children: React.ReactNode }) {
|
|||||||
if (newReplyKeySet.has(key)) return
|
if (newReplyKeySet.has(key)) return
|
||||||
newReplyKeySet.add(key)
|
newReplyKeySet.add(key)
|
||||||
|
|
||||||
let parentKey: string | undefined
|
const parentTag = getParentTag(reply)
|
||||||
if (reply.kind === kinds.Highlights) {
|
if (parentTag) {
|
||||||
console.log('reply', reply)
|
const parentKey = getKeyFromTag(parentTag.tag)
|
||||||
const sourceTag = getHighlightSourceTag(reply)
|
if (parentKey) {
|
||||||
if (!sourceTag) return
|
newReplyEventMap.set(parentKey, [...(newReplyEventMap.get(parentKey) || []), reply])
|
||||||
|
|
||||||
parentKey = getKeyFromTag(sourceTag)
|
|
||||||
} else {
|
|
||||||
const parentTag = getParentTag(reply)
|
|
||||||
if (!parentTag) return
|
|
||||||
|
|
||||||
parentKey = getKeyFromTag(parentTag.tag)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parentKey) {
|
|
||||||
if (reply.kind === kinds.Highlights) {
|
|
||||||
console.log('parentKey', parentKey)
|
|
||||||
}
|
}
|
||||||
newReplyEventMap.set(parentKey, [...(newReplyEventMap.get(parentKey) || []), reply])
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if (newReplyEventMap.size === 0) return
|
if (newReplyEventMap.size === 0) return
|
||||||
|
|||||||
Reference in New Issue
Block a user