From 7ec4835c61bc4f50c08610980d636faae0e157f5 Mon Sep 17 00:00:00 2001 From: codytseng Date: Mon, 1 Dec 2025 00:05:09 +0800 Subject: [PATCH] feat: pinned users event --- src/App.tsx | 23 +-- src/components/UserAggregationList/index.tsx | 70 ++++---- src/constants.ts | 3 +- src/providers/MuteListProvider.tsx | 27 +-- src/providers/NostrProvider/index.tsx | 40 ++++- src/providers/PinnedUsersProvider.tsx | 171 +++++++++++++++++++ src/services/client.service.ts | 4 + src/services/indexed-db.service.ts | 37 ++-- src/services/local-storage.service.ts | 19 +-- src/services/user-aggregation.service.ts | 45 ----- 10 files changed, 303 insertions(+), 136 deletions(-) create mode 100644 src/providers/PinnedUsersProvider.tsx diff --git a/src/App.tsx b/src/App.tsx index f9be778..8c98026 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -14,6 +14,7 @@ import { MediaUploadServiceProvider } from '@/providers/MediaUploadServiceProvid import { MuteListProvider } from '@/providers/MuteListProvider' import { NostrProvider } from '@/providers/NostrProvider' import { PinListProvider } from '@/providers/PinListProvider' +import { PinnedUsersProvider } from '@/providers/PinnedUsersProvider' import { ReplyProvider } from '@/providers/ReplyProvider' import { ScreenSizeProvider } from '@/providers/ScreenSizeProvider' import { ThemeProvider } from '@/providers/ThemeProvider' @@ -40,16 +41,18 @@ export default function App(): JSX.Element { - - - - - - - - - - + + + + + + + + + + + + diff --git a/src/components/UserAggregationList/index.tsx b/src/components/UserAggregationList/index.tsx index 5cb74fd..4c7256d 100644 --- a/src/components/UserAggregationList/index.tsx +++ b/src/components/UserAggregationList/index.tsx @@ -11,6 +11,7 @@ import { useContentPolicy } from '@/providers/ContentPolicyProvider' import { useDeletedEvent } from '@/providers/DeletedEventProvider' import { useMuteList } from '@/providers/MuteListProvider' import { useNostr } from '@/providers/NostrProvider' +import { usePinnedUsers } from '@/providers/PinnedUsersProvider' import { useUserTrust } from '@/providers/UserTrustProvider' import client from '@/services/client.service' import userAggregationService, { TUserAggregation } from '@/services/user-aggregation.service' @@ -53,6 +54,7 @@ const UserAggregationList = forwardRef< const { push } = useSecondaryPage() const { hideUntrustedNotes, isUserTrusted } = useUserTrust() const { mutePubkeySet } = useMuteList() + const { pinnedPubkeySet } = usePinnedUsers() const { hideContentMentioningMutedUsers } = useContentPolicy() const { isEventDeleted } = useDeletedEvent() const [since, setSince] = useState(() => dayjs().subtract(1, 'day').unix()) @@ -64,9 +66,6 @@ const UserAggregationList = forwardRef< const [showCount, setShowCount] = useState(SHOW_COUNT) const [hasMore, setHasMore] = useState(true) const supportTouch = useMemo(() => isTouchDevice(), []) - const [pinnedPubkeys, setPinnedPubkeys] = useState>( - new Set(userAggregationService.getPinnedPubkeys()) - ) const feedId = useMemo(() => { return userAggregationService.getFeedId(subRequests, showKinds) }, [JSON.stringify(subRequests), JSON.stringify(showKinds)]) @@ -97,7 +96,6 @@ const UserAggregationList = forwardRef< useEffect(() => { if (!subRequests.length) return - setPinnedPubkeys(new Set(userAggregationService.getPinnedPubkeys())) setSince(dayjs().subtract(1, 'day').unix()) setHasMore(true) @@ -223,28 +221,24 @@ const UserAggregationList = forwardRef< const aggregations = useMemo(() => { const aggs = userAggregationService.aggregateByUser(filteredEvents) userAggregationService.saveAggregations(feedId, aggs) + return aggs + }, [feedId, filteredEvents]) - const pinned: TUserAggregation[] = [] - const unpinned: TUserAggregation[] = [] + const pinnedAggregations = useMemo(() => { + return aggregations.filter((agg) => pinnedPubkeySet.has(agg.pubkey)) + }, [aggregations, pinnedPubkeySet]) - aggs.forEach((agg) => { - if (pinnedPubkeys.has(agg.pubkey)) { - pinned.push(agg) - } else { - unpinned.push(agg) - } - }) + const normalAggregations = useMemo(() => { + return aggregations.filter((agg) => !pinnedPubkeySet.has(agg.pubkey)) + }, [aggregations, pinnedPubkeySet]) - return [...pinned, ...unpinned] - }, [feedId, filteredEvents, pinnedPubkeys]) - - const displayedAggregations = useMemo(() => { - return aggregations.slice(0, showCount) - }, [aggregations, showCount]) + const displayedNormalAggregations = useMemo(() => { + return normalAggregations.slice(0, showCount) + }, [normalAggregations, showCount]) const hasMoreToDisplay = useMemo(() => { - return aggregations.length > displayedAggregations.length - }, [aggregations, displayedAggregations]) + return normalAggregations.length > displayedNormalAggregations.length + }, [normalAggregations, displayedNormalAggregations]) useEffect(() => { const options = { @@ -294,7 +288,7 @@ const UserAggregationList = forwardRef< const list = (
- {displayedAggregations.map((agg) => ( + {pinnedAggregations.map((agg) => ( handleViewUser(agg)} /> ))} + + {normalAggregations.map((agg) => ( + handleViewUser(agg)} + /> + ))} + {loading || hasMoreToDisplay ? (
- ) : displayedAggregations.length === 0 ? ( + ) : aggregations.length === 0 ? (