Skip to content
This repository has been archived by the owner on Jan 2, 2025. It is now read-only.

Commit

Permalink
implementing pagination in the frontend WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
horacioh committed Mar 29, 2024
1 parent 5f71c05 commit b98be1a
Show file tree
Hide file tree
Showing 12 changed files with 145 additions and 112 deletions.
30 changes: 25 additions & 5 deletions frontend/packages/app/models/accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {queryKeys} from '@mintter/app/models/query-keys'
import {Account, GRPCClient, Profile} from '@mintter/shared'
import {
UseMutationOptions,
useInfiniteQuery,
useMutation,
useQueries,
useQuery,
Expand Down Expand Up @@ -41,13 +42,19 @@ function getAccountQuery(grpcClient: GRPCClient, accountId?: string) {
export function useAllAccounts(filterSites?: boolean) {
// let isDaemonReady = useDaemonReady()
const grpcClient = useGRPCClient()
const contacts = useQuery<{accounts: Array<Account>}, ConnectError>({
// enabled: !!isDaemonReady,
const accountsQuery = useInfiniteQuery<
{accounts: Array<Account>},
ConnectError
>({
queryKey: [queryKeys.GET_ALL_ACCOUNTS, filterSites],
queryFn: async () => {
const listed = await grpcClient.accounts.listAccounts({})
queryFn: async (context) => {
const listed = await grpcClient.accounts.listAccounts({
pageToken: context.pageParam,
pageSize: 20,
})
if (filterSites) {
return {
...listed,
accounts: listed.accounts.filter(
(account) =>
account.profile?.bio !== 'Hypermedia Site. Powered by Mintter.',
Expand All @@ -59,8 +66,21 @@ export function useAllAccounts(filterSites?: boolean) {
onError: (err) => {
appError(`useAllAccounts Error ${err.code}: ${err.message}`, err.metadata)
},
getNextPageParam: (lastPage) => {
return lastPage.nextPageToken || undefined
},
})
return contacts

const allAccounts =
accountsQuery.data?.pages.flatMap((page) => page.accounts) ?? []
console.log(`== ~ useAllAccounts ~ accountsQuery:`, accountsQuery)
return {
...accountsQuery,
data: {
...accountsQuery.data,
accounts: allAccounts,
},
}
}

export function useSetTrusted(
Expand Down
14 changes: 1 addition & 13 deletions frontend/packages/app/models/contacts.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,13 @@
import {queryKeys} from '@mintter/app/models/query-keys'
import {Device} from '@mintter/shared'
import {UseMutationOptions, useMutation, useQuery} from '@tanstack/react-query'
import {UseMutationOptions, useMutation} from '@tanstack/react-query'
import {decompressFromEncodedURIComponent} from 'lz-string'
import {useGRPCClient, useQueryInvalidator} from '../app-context'
import appError from '../errors'
import {useAccount} from './accounts'
import {useConnectedPeers} from './networking'
import {fullInvalidate} from './query-keys'

export function useContactsList() {
const grpcClient = useGRPCClient()
const contacts = useQuery({
queryKey: [queryKeys.GET_ALL_ACCOUNTS],
queryFn: async () => {
return await grpcClient.accounts.listAccounts({})
},
refetchInterval: 20_000,
})
return contacts
}

export function useConnectionSummary() {
const peerInfo = useConnectedPeers({
refetchInterval: 15_000,
Expand Down
65 changes: 54 additions & 11 deletions frontend/packages/app/models/documents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ import {
import {UpdateDraftResponse} from '@mintter/shared/src/client/.generated/documents/v1alpha/documents_pb'
import {
FetchQueryOptions,
UseInfiniteQueryOptions,
UseMutationOptions,
UseQueryOptions,
useInfiniteQuery,
useMutation,
useQueries,
useQuery,
Expand All @@ -61,38 +63,58 @@ import {useGroupContent, useGroups} from './groups'
import {queryKeys} from './query-keys'

export function usePublicationList(
opts?: UseQueryOptions<ListPublicationsResponse> & {trustedOnly: boolean},
opts?: UseInfiniteQueryOptions<ListPublicationsResponse> & {
trustedOnly: boolean
},
) {
const {trustedOnly, ...queryOpts} = opts || {}
const grpcClient = useGRPCClient()
return useQuery({
const pubListQuery = useInfiniteQuery({
...queryOpts,
queryKey: [
queryKeys.GET_PUBLICATION_LIST,
trustedOnly ? 'trusted' : 'global',
],
refetchOnMount: true,
queryFn: async () => {
queryFn: async (context) => {
const result = await grpcClient.publications.listPublications({
trustedOnly: trustedOnly,
pageSize: 50,
pageToken: context.pageParam,
})
let publications =
result.publications.sort((a, b) =>
sortDocuments(a.document?.updateTime, b.document?.updateTime),
) || []
publications = publications.filter((pub) => {
return pub.document?.title !== '(HIDDEN) Group Navigation'
})
// publications = publications.filter((pub) => {
// return pub.document?.title !== '(HIDDEN) Group Navigation'
// })
return {
...result,
publications,
}
},
getNextPageParam: (lastPage) => {
return lastPage.nextPageToken
},
})

const allPublications =
pubListQuery.data?.pages.flatMap((page) => page.publications) || []
console.log(`== ~ allPublications:`, allPublications)
return {
...pubListQuery,
data: {
...pubListQuery.data,
publications: allPublications,
},
}
}

export function usePublicationFullList(
opts?: UseQueryOptions<ListPublicationsResponse> & {trustedOnly: boolean},
opts?: UseInfiniteQueryOptions<ListPublicationsResponse> & {
trustedOnly: boolean
},
) {
const pubList = usePublicationList(opts)
const accounts = useAllAccounts()
Expand All @@ -114,14 +136,15 @@ export function usePublicationFullList(

export function useDraftList() {
const grpcClient = useGRPCClient()
return useQuery({
const draftListQuery = useInfiniteQuery({
queryKey: [queryKeys.GET_DRAFT_LIST],
refetchOnMount: true,
queryFn: async () => {
queryFn: async (context) => {
const result = await grpcClient.drafts.listDrafts({
pageSize: undefined,
pageToken: undefined,
pageToken: context.pageParam,
})

console.log(`== ~ queryFn: ~ result:`, result)
const documents =
result.documents.sort((a, b) =>
sortDocuments(a.updateTime, b.updateTime),
Expand All @@ -131,7 +154,27 @@ export function useDraftList() {
documents,
}
},
getNextPageParam: (lastPage) => {
return lastPage.nextPageToken || undefined
},
})

const allDrafts =
draftListQuery.data?.pages.flatMap((page) => page.documents) || []

console.log(
`== ~ useDraftList ~ draftListQuery:`,
draftListQuery.data,
allDrafts,
)

return {
...draftListQuery,
data: {
...draftListQuery.data,
documents: allDrafts,
},
}
}

export function useDeleteDraft(
Expand Down
20 changes: 15 additions & 5 deletions frontend/packages/app/models/groups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ import {
} from '@mintter/shared'
import {ListDocumentGroupsResponse_Item} from '@mintter/shared/src/client/.generated/groups/v1alpha/groups_pb'
import {
UseInfiniteQueryOptions,
UseMutationOptions,
UseQueryOptions,
useInfiniteQuery,
useMutation,
useQueries,
useQuery,
Expand All @@ -35,23 +37,31 @@ import {
} from '@mintter/shared'
import {queryKeys} from './query-keys'

export function useAllGroups(opts?: UseQueryOptions<ListGroupsResponse>) {
export function useAllGroups(
opts?: UseInfiniteQueryOptions<ListGroupsResponse>,
) {
const grpcClient = useGRPCClient()
const groupsQuery = useQuery({
const groupsQuery = useInfiniteQuery({
...opts,
queryKey: [queryKeys.GET_GROUPS],
queryFn: async () => {
return await grpcClient.groups.listGroups({})
queryFn: async (context) => {
return await grpcClient.groups.listGroups({
pageSize: 50,
pageToken: context.pageParam,
})
},
getNextPageParam: (lastPage) => lastPage?.nextPageToken ?? undefined,
})

const allGroups = groupsQuery.data?.pages.flatMap((page) => page.groups) || []

return useMemo(() => {
return {
...groupsQuery,
data: {
...groupsQuery.data,
groups:
groupsQuery.data?.groups?.sort((a, b) =>
allGroups?.sort((a, b) =>
sortDocuments(a.updateTime, b.updateTime),
) || [],
},
Expand Down
6 changes: 6 additions & 0 deletions frontend/packages/app/pages/contacts-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ function ErrorPage({}: {error: any}) {

export default function ContactsPage() {
const contacts = useAllAccounts(true)

console.log(`== ~ ContactsPage ~ contacts:`, contacts)
const myAccount = useMyAccount()
const allAccounts = contacts.data?.accounts || []
const trustedAccounts = allAccounts.filter(
Expand Down Expand Up @@ -147,6 +149,7 @@ export default function ContactsPage() {
<MainWrapperNoScroll>
<List
items={[...trustedAccounts, ...untrustedAccounts]}
fixedItemHeight={52}
renderItem={({item}) => {
return (
<ContactItem
Expand All @@ -158,6 +161,9 @@ export default function ContactsPage() {
/>
)
}}
onEndReached={() => {
contacts.fetchNextPage()
}}
/>
</MainWrapperNoScroll>
{copyDialogContent}
Expand Down
19 changes: 9 additions & 10 deletions frontend/packages/app/pages/feed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ import {
import {
Button,
ButtonText,
FeedList,
FeedListHandle,
Globe,
List,
PageContainer,
RadioButtons,
SizableText,
Spinner,
TextProps,
Theme,
UIAvatar,
View,
Expand All @@ -33,7 +33,7 @@ import {
toast,
} from '@mintter/ui'
import {ArrowRight, ChevronUp, Verified} from '@tamagui/lucide-icons'
import React, {PropsWithChildren, ReactNode, useRef} from 'react'
import React, {PropsWithChildren, ReactNode} from 'react'
import Footer from '../components/footer'
import {MainWrapperNoScroll} from '../components/main-wrapper'
import {useAccount} from '../models/accounts'
Expand Down Expand Up @@ -162,13 +162,15 @@ type CommentFeedItemProps = {
function EntityLink({
id,
children,
}: {
...props
}: TextProps & {
id: UnpackedHypermediaId
children: ReactNode
}) {
const navigate = useNavigate('push')
return (
<ButtonText
style={{whiteSpace: 'break-spaces'}}
fontWeight={'bold'}
onPress={(e) => {
e.stopPropagation()
Expand All @@ -181,6 +183,7 @@ function EntityLink({
}}
numberOfLines={1}
textOverflow="ellipsis" // not working. long titles don't look great
{...props}
>
{children}
</ButtonText>
Expand Down Expand Up @@ -762,12 +765,10 @@ const Feed = React.memo(function Feed({tab}: {tab: 'trusted' | 'all'}) {
const feed = useFeedWithLatest(tab === 'trusted')
const route = useNavRoute()
const replace = useNavigate('replace')
const scrollRef = useRef<FeedListHandle>(null)
if (route.key !== 'feed') throw new Error('invalid route')
return (
<YStack f={1} gap="$3">
<FeedList
ref={scrollRef}
<List
header={
<PageContainer marginVertical="$6">
<XStack f={1} ai="center" gap="$3">
Expand Down Expand Up @@ -837,11 +838,9 @@ export const ResourceFeed = React.memo(function ResourceFeed({
id: string
}) {
const feed = useResourceFeed(id)
const scrollRef = useRef<FeedListHandle>(null)
return (
<YStack f={1} gap="$3">
<FeedList
ref={scrollRef}
<List
header={<View height="$2" />}
footer={
feed.data?.pages?.length && (
Expand Down
1 change: 1 addition & 0 deletions frontend/packages/app/pages/groups.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ export default function GroupsPage() {
</Container>
) : groups.length > 0 ? (
<List
fixedItemHeight={52}
items={groups}
renderItem={({item}) => {
if (!item.group) return null
Expand Down
Loading

0 comments on commit b98be1a

Please sign in to comment.