feat: 💨

This commit is contained in:
codytseng
2025-11-20 21:31:48 +08:00
parent ce72098175
commit 18ae2a5fd4
4 changed files with 17 additions and 12 deletions

View File

@@ -7,6 +7,7 @@ import { useContentPolicy } from '@/providers/ContentPolicyProvider'
import { useDeletedEvent } from '@/providers/DeletedEventProvider'
import { useMuteList } from '@/providers/MuteListProvider'
import { useNostr } from '@/providers/NostrProvider'
import { useReply } from '@/providers/ReplyProvider'
import { useUserTrust } from '@/providers/UserTrustProvider'
import client from '@/services/client.service'
import { TFeedSubRequest } from '@/types'
@@ -65,6 +66,7 @@ const NoteList = forwardRef(
const { mutePubkeySet } = useMuteList()
const { hideContentMentioningMutedUsers } = useContentPolicy()
const { isEventDeleted } = useDeletedEvent()
const { addReplies } = useReply()
const [events, setEvents] = useState<Event[]>([])
const [newEvents, setNewEvents] = useState<Event[]>([])
const [hasMore, setHasMore] = useState<boolean>(true)
@@ -253,6 +255,7 @@ const NoteList = forwardRef(
if (eosed) {
setLoading(false)
setHasMore(events.length > 0)
addReplies(events)
}
},
onNew: (event) => {
@@ -265,6 +268,7 @@ const NoteList = forwardRef(
[event, ...oldEvents].sort((a, b) => b.created_at - a.created_at)
)
}
addReplies([event])
},
onClose: (url, reason) => {
if (!showRelayCloseReason) return

View File

@@ -1,8 +1,10 @@
import { BIG_RELAY_URLS, ExtendedKind, NOTIFICATION_LIST_STYLE } from '@/constants'
import { compareEvents } from '@/lib/event'
import { isTouchDevice } from '@/lib/utils'
import { usePrimaryPage } from '@/PageManager'
import { useNostr } from '@/providers/NostrProvider'
import { useNotification } from '@/providers/NotificationProvider'
import { useReply } from '@/providers/ReplyProvider'
import { useUserPreferences } from '@/providers/UserPreferencesProvider'
import client from '@/services/client.service'
import stuffStatsService from '@/services/stuff-stats.service'
@@ -20,11 +22,10 @@ import {
} from 'react'
import { useTranslation } from 'react-i18next'
import PullToRefresh from 'react-simple-pull-to-refresh'
import { RefreshButton } from '../RefreshButton'
import Tabs from '../Tabs'
import { NotificationItem } from './NotificationItem'
import { NotificationSkeleton } from './NotificationItem/Notification'
import { isTouchDevice } from '@/lib/utils'
import { RefreshButton } from '../RefreshButton'
const LIMIT = 100
const SHOW_COUNT = 30
@@ -36,6 +37,7 @@ const NotificationList = forwardRef((_, ref) => {
const { pubkey } = useNostr()
const { getNotificationsSeenAt } = useNotification()
const { notificationListStyle } = useUserPreferences()
const { addReplies } = useReply()
const [notificationType, setNotificationType] = useState<TNotificationType>('all')
const [lastReadTime, setLastReadTime] = useState(0)
const [refreshCount, setRefreshCount] = useState(0)
@@ -139,11 +141,13 @@ const NotificationList = forwardRef((_, ref) => {
if (eosed) {
setLoading(false)
setUntil(events.length > 0 ? events[events.length - 1].created_at - 1 : undefined)
addReplies(events)
stuffStatsService.updateStuffStatsByEvents(events)
}
},
onNew: (event) => {
handleNewEvent(event)
addReplies([event])
}
}
)

View File

@@ -1,4 +1,5 @@
import { BIG_RELAY_URLS, ExtendedKind } from '@/constants'
import { useStuff } from '@/hooks/useStuff'
import {
getEventKey,
getKeyFromTag,
@@ -7,8 +8,7 @@ import {
getRootTag,
isMentioningMutedUsers,
isProtectedEvent,
isReplaceableEvent,
isReplyNoteEvent
isReplaceableEvent
} from '@/lib/event'
import { toNote } from '@/lib/link'
import { generateBech32IdFromATag, generateBech32IdFromETag } from '@/lib/tag'
@@ -23,7 +23,6 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { LoadingBar } from '../LoadingBar'
import ReplyNote, { ReplyNoteSkeleton } from '../ReplyNote'
import { useStuff } from '@/hooks/useStuff'
type TRootInfo =
| { type: 'E'; id: string; pubkey: string }
@@ -185,7 +184,7 @@ export default function ReplyNoteList({
{
onEvents: (evts, eosed) => {
if (evts.length > 0) {
addReplies(evts.filter((evt) => isReplyNoteEvent(evt)))
addReplies(evts)
}
if (eosed) {
setUntil(evts.length >= LIMIT ? evts[evts.length - 1].created_at - 1 : undefined)
@@ -193,7 +192,6 @@ export default function ReplyNoteList({
}
},
onNew: (evt) => {
if (!isReplyNoteEvent(evt)) return
addReplies([evt])
}
}
@@ -249,10 +247,7 @@ export default function ReplyNoteList({
setLoading(true)
const events = await client.loadMoreTimeline(timelineKey, until, LIMIT)
const olderEvents = events.filter((evt) => isReplyNoteEvent(evt))
if (olderEvents.length > 0) {
addReplies(olderEvents)
}
addReplies(events)
setUntil(events.length ? events[events.length - 1].created_at - 1 : undefined)
setLoading(false)
}, [loading, until, timelineKey])

View File

@@ -1,4 +1,4 @@
import { getEventKey, getKeyFromTag, getParentTag } from '@/lib/event'
import { getEventKey, getKeyFromTag, getParentTag, isReplyNoteEvent } from '@/lib/event'
import { Event } from 'nostr-tools'
import { createContext, useCallback, useContext, useState } from 'react'
@@ -26,6 +26,8 @@ export function ReplyProvider({ children }: { children: React.ReactNode }) {
const newReplyKeySet = new Set<string>()
const newReplyEventMap = new Map<string, Event[]>()
replies.forEach((reply) => {
if (!isReplyNoteEvent(reply)) return
const key = getEventKey(reply)
if (newReplyKeySet.has(key)) return
newReplyKeySet.add(key)