From de9ed04ca8cce1049c46056c85c912bfaa77a1d2 Mon Sep 17 00:00:00 2001 From: codytseng Date: Mon, 15 Sep 2025 21:20:46 +0800 Subject: [PATCH] feat: add refresh button for non-touch devices --- src/components/KindFilter/index.tsx | 5 +- src/components/NormalFeed/index.tsx | 10 ++- src/components/NoteList/index.tsx | 84 ++++++++++++++--------- src/components/NotificationList/index.tsx | 73 +++++++++++++------- src/components/Profile/ProfileFeed.tsx | 8 ++- src/components/RefreshButton/index.tsx | 24 +++++++ 6 files changed, 140 insertions(+), 64 deletions(-) create mode 100644 src/components/RefreshButton/index.tsx diff --git a/src/components/KindFilter/index.tsx b/src/components/KindFilter/index.tsx index d2c5ea8a..53c2b147 100644 --- a/src/components/KindFilter/index.tsx +++ b/src/components/KindFilter/index.tsx @@ -74,7 +74,10 @@ export default function KindFilter({ + + )} + + ) + return (
{filteredNewEvents.length > 0 && ( )}
- { - setRefreshCount((count) => count + 1) - await new Promise((resolve) => setTimeout(resolve, 1000)) - }} - pullingContent="" - > -
- {filteredEvents.map((event) => ( - - ))} - {hasMore || loading ? ( -
- -
- ) : events.length ? ( -
- {t('no more notes')} -
- ) : ( -
- -
- )} -
-
+ {supportTouch ? ( + { + refresh() + await new Promise((resolve) => setTimeout(resolve, 1000)) + }} + pullingContent="" + > + {list} + + ) : ( + list + )}
) @@ -299,4 +314,5 @@ export default NoteList export type TNoteListRef = { scrollToTop: (behavior?: ScrollBehavior) => void + refresh: () => void } diff --git a/src/components/NotificationList/index.tsx b/src/components/NotificationList/index.tsx index 216a8840..c98da65e 100644 --- a/src/components/NotificationList/index.tsx +++ b/src/components/NotificationList/index.tsx @@ -23,6 +23,8 @@ import PullToRefresh from 'react-simple-pull-to-refresh' 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 @@ -43,6 +45,8 @@ const NotificationList = forwardRef((_, ref) => { const [visibleNotifications, setVisibleNotifications] = useState([]) const [showCount, setShowCount] = useState(SHOW_COUNT) const [until, setUntil] = useState(dayjs().unix()) + const supportTouch = useMemo(() => isTouchDevice(), []) + const topRef = useRef(null) const bottomRef = useRef(null) const filterKinds = useMemo(() => { switch (notificationType) { @@ -235,6 +239,34 @@ const NotificationList = forwardRef((_, ref) => { } }, [pubkey, timelineKey, until, loading, showCount, notifications]) + const refresh = () => { + topRef.current?.scrollIntoView({ behavior: 'instant', block: 'start' }) + setTimeout(() => { + setRefreshCount((count) => count + 1) + }, 500) + } + + const list = ( +
+ {visibleNotifications.map((notification) => ( + lastReadTime} + /> + ))} +
+ {until || loading ? ( +
+ +
+ ) : ( + t('no more notifications') + )} +
+
+ ) + return (
{ setShowCount(SHOW_COUNT) setNotificationType(type as TNotificationType) }} + options={!supportTouch ? refresh()} /> : null} /> - { - setRefreshCount((count) => count + 1) - await new Promise((resolve) => setTimeout(resolve, 1000)) - }} - pullingContent="" - > -
- {visibleNotifications.map((notification) => ( - lastReadTime} - /> - ))} -
- {until || loading ? ( -
- -
- ) : ( - t('no more notifications') - )} -
-
-
+
+ {supportTouch ? ( + { + refresh() + await new Promise((resolve) => setTimeout(resolve, 1000)) + }} + pullingContent="" + > + {list} + + ) : ( + list + )}
) }) diff --git a/src/components/Profile/ProfileFeed.tsx b/src/components/Profile/ProfileFeed.tsx index 0162493a..dd5e5e22 100644 --- a/src/components/Profile/ProfileFeed.tsx +++ b/src/components/Profile/ProfileFeed.tsx @@ -2,12 +2,14 @@ import KindFilter from '@/components/KindFilter' import NoteList, { TNoteListRef } from '@/components/NoteList' import Tabs from '@/components/Tabs' import { BIG_RELAY_URLS } from '@/constants' +import { isTouchDevice } from '@/lib/utils' import { useKindFilter } from '@/providers/KindFilterProvider' import { useNostr } from '@/providers/NostrProvider' import client from '@/services/client.service' import storage from '@/services/local-storage.service' import { TFeedSubRequest, TNoteListMode } from '@/types' import { useEffect, useMemo, useRef, useState } from 'react' +import { RefreshButton } from '../RefreshButton' export default function ProfileFeed({ pubkey, @@ -34,6 +36,7 @@ export default function ProfileFeed({ return _tabs }, [myPubkey, pubkey]) + const supportTouch = useMemo(() => isTouchDevice(), []) useEffect(() => { const init = async () => { @@ -100,7 +103,10 @@ export default function ProfileFeed({ }} threshold={Math.max(800, topSpace)} options={ - + <> + {!supportTouch && noteListRef.current?.refresh()} />} + + } /> void }) { + const [refreshing, setRefreshing] = useState(false) + + return ( + + ) +}