diff --git a/src/components/NoteList/index.tsx b/src/components/NoteList/index.tsx index 9354dd4a..f0f041b7 100644 --- a/src/components/NoteList/index.tsx +++ b/src/components/NoteList/index.tsx @@ -20,9 +20,9 @@ import PullToRefresh from 'react-simple-pull-to-refresh' import NoteCard from '../NoteCard' import PictureNoteCard from '../PictureNoteCard' -const NORMAL_RELAY_LIMIT = 100 -const ALGO_RELAY_LIMIT = 500 -const PICTURE_NOTE_LIMIT = 30 +const LIMIT = 100 +const ALGO_LIMIT = 500 +const SHOW_COUNT = 20 export default function NoteList({ relayUrls, @@ -45,22 +45,17 @@ export default function NoteList({ const [timelineKey, setTimelineKey] = useState(undefined) const [events, setEvents] = useState([]) const [newEvents, setNewEvents] = useState([]) + const [showCount, setShowCount] = useState(SHOW_COUNT) const [hasMore, setHasMore] = useState(true) const [refreshing, setRefreshing] = useState(true) const [listMode, setListMode] = useState(() => storage.getNoteListMode()) const bottomRef = useRef(null) const isPictures = useMemo(() => listMode === 'pictures', [listMode]) const noteFilter = useMemo(() => { - if (isPictures) { - return { - kinds: [PICTURE_EVENT_KIND], - limit: PICTURE_NOTE_LIMIT, - ...filter - } - } return { - kinds: [kinds.ShortTextNote, kinds.Repost, PICTURE_EVENT_KIND], - limit: NORMAL_RELAY_LIMIT, + kinds: isPictures + ? [PICTURE_EVENT_KIND] + : [kinds.ShortTextNote, kinds.Repost, PICTURE_EVENT_KIND], ...filter } }, [JSON.stringify(filter), isPictures]) @@ -80,12 +75,11 @@ export default function NoteList({ const relayInfos = await relayInfoService.getRelayInfos(relayUrls) areAlgoRelays = relayInfos.every((relayInfo) => checkAlgoRelay(relayInfo)) } - const filter = areAlgoRelays ? { ...noteFilter, limit: ALGO_RELAY_LIMIT } : noteFilter let eventCount = 0 const { closer, timelineKey } = await client.subscribeTimeline( [...relayUrls], - filter, + { ...noteFilter, limit: areAlgoRelays ? ALGO_LIMIT : LIMIT }, { onEvents: (events, eosed) => { if (eventCount > events.length) return @@ -124,23 +118,25 @@ export default function NoteList({ }, [JSON.stringify(relayUrls), noteFilter, refreshCount]) const loadMore = useCallback(async () => { - if (!timelineKey || refreshing || !hasMore) return + if (showCount < events.length) { + setShowCount((prev) => prev + SHOW_COUNT) + return + } + if (!timelineKey || refreshing || !hasMore) return const newEvents = await client.loadMoreTimeline( timelineKey, events.length ? events[events.length - 1].created_at - 1 : dayjs().unix(), - noteFilter.limit + LIMIT ) if (newEvents.length === 0) { setHasMore(false) return } setEvents((oldEvents) => [...oldEvents, ...newEvents]) - }, [timelineKey, refreshing, hasMore, events, noteFilter]) + }, [timelineKey, refreshing, hasMore, events, noteFilter, showCount]) useEffect(() => { - if (refreshing) return - const options = { root: null, rootMargin: '10px', @@ -164,7 +160,7 @@ export default function NoteList({ observerInstance.unobserve(currentBottomRef) } } - }, [refreshing, loadMore]) + }, [loadMore]) const showNewEvents = () => { setEvents((oldEvents) => [...newEvents, ...oldEvents]) @@ -177,6 +173,7 @@ export default function NoteList({ listMode={listMode} setListMode={(listMode) => { setListMode(listMode) + setShowCount(SHOW_COUNT) topRef.current?.scrollIntoView({ behavior: 'instant', block: 'end' }) storage.setNoteListMode(listMode) }} @@ -190,27 +187,29 @@ export default function NoteList({ pullingContent="" >
- {newEvents.filter((event: Event) => { - return ( - (!filterMutedNotes || !mutePubkeys.includes(event.pubkey)) && - (listMode !== 'posts' || !isReplyNoteEvent(event)) - ) - }).length > 0 && ( -
- -
- )} + {events.length > 0 && + newEvents.filter((event: Event) => { + return ( + (!filterMutedNotes || !mutePubkeys.includes(event.pubkey)) && + (listMode !== 'posts' || !isReplyNoteEvent(event)) + ) + }).length > 0 && ( +
+ +
+ )} {isPictures ? ( ) : (
{events + .slice(0, showCount) .filter((event: Event) => listMode !== 'posts' || !isReplyNoteEvent(event)) .map((event) => ( { const { t } = useTranslation() @@ -34,6 +35,7 @@ const NotificationList = forwardRef((_, ref) => { const [timelineKey, setTimelineKey] = useState(undefined) const [refreshing, setRefreshing] = useState(true) const [notifications, setNotifications] = useState([]) + const [showCount, setShowCount] = useState(SHOW_COUNT) const [until, setUntil] = useState(dayjs().unix()) const bottomRef = useRef(null) useImperativeHandle( @@ -70,15 +72,23 @@ const NotificationList = forwardRef((_, ref) => { onEvents: (events, eosed) => { if (eventCount > events.length) return eventCount = events.length - setUntil(events.length >= LIMIT ? events[events.length - 1].created_at - 1 : undefined) setNotifications(events.filter((event) => event.pubkey !== pubkey)) if (eosed) { setRefreshing(false) + setUntil(events.length >= 0 ? events[events.length - 1].created_at - 1 : undefined) } }, onNew: (event) => { if (event.pubkey === pubkey) return - setNotifications((oldEvents) => [event, ...oldEvents]) + setNotifications((oldEvents) => { + const index = oldEvents.findIndex( + (oldEvent) => oldEvent.created_at < event.created_at + ) + if (index === -1) { + return [...oldEvents, event] + } + return [...oldEvents.slice(0, index), event, ...oldEvents.slice(index)] + }) } } ) @@ -93,26 +103,30 @@ const NotificationList = forwardRef((_, ref) => { }, [pubkey, refreshCount]) const loadMore = useCallback(async () => { + if (showCount < notifications.length) { + setShowCount((count) => count + SHOW_COUNT) + return + } + if (!pubkey || !timelineKey || !until || refreshing) return - const notifications = await client.loadMoreTimeline(timelineKey, until, LIMIT) - if (notifications.length === 0) { + + const newNotifications = await client.loadMoreTimeline(timelineKey, until, LIMIT) + if (newNotifications.length === 0) { setUntil(undefined) return } - if (notifications.length > 0) { + if (newNotifications.length > 0) { setNotifications((oldNotifications) => [ ...oldNotifications, - ...notifications.filter((event) => event.pubkey !== pubkey) + ...newNotifications.filter((event) => event.pubkey !== pubkey) ]) } - setUntil(notifications[notifications.length - 1].created_at - 1) - }, [pubkey, timelineKey, until, refreshing]) + setUntil(newNotifications[newNotifications.length - 1].created_at - 1) + }, [pubkey, timelineKey, until, refreshing, showCount, notifications]) useEffect(() => { - if (refreshing) return - const options = { root: null, rootMargin: '10px', @@ -136,7 +150,7 @@ const NotificationList = forwardRef((_, ref) => { observerInstance.unobserve(currentBottomRef) } } - }, [refreshing, loadMore]) + }, [loadMore]) return ( { pullingContent="" >
- {notifications.map((notification) => ( + {notifications.slice(0, showCount).map((notification) => ( ))}
diff --git a/src/services/client.service.ts b/src/services/client.service.ts index 2a8fb3d2..c9dbd1d8 100644 --- a/src/services/client.service.ts +++ b/src/services/client.service.ts @@ -320,7 +320,8 @@ class ClientService extends EventTarget { timeline.refs = newRefs.concat(timeline.refs) onEvents(newEvents.concat(cachedEvents), true) } - } + }, + eoseTimeout: 10000 // 10s }) } })