1
0
mirror of https://github.com/tooot-app/app synced 2025-04-17 03:37:21 +02:00
This commit is contained in:
xmflsct 2022-12-15 01:41:34 +01:00
parent c4316804fc
commit a4cd24f313
9 changed files with 141 additions and 31 deletions

View File

@ -47,9 +47,27 @@ const apiGeneral = async <T = unknown>({
...(body && { data: body })
})
.then(response => {
return Promise.resolve({
body: response.data
})
let links: {
prev?: { id: string; isOffset: boolean }
next?: { id: string; isOffset: boolean }
} = {}
if (response.headers?.link) {
const linksParsed = response.headers.link.matchAll(
new RegExp('[?&](.*?_id|offset)=(.*?)>; *rel="(.*?)"', 'gi')
)
for (const link of linksParsed) {
switch (link[3]) {
case 'prev':
links.prev = { id: link[2], isOffset: link[1].includes('offset') }
break
case 'next':
links.next = { id: link[2], isOffset: link[1].includes('offset') }
break
}
}
}
return Promise.resolve({ body: response.data, links })
})
.catch(handleError())
}

View File

@ -37,7 +37,7 @@ const TimelineFeedback = () => {
onPress={() =>
navigation.push('Tab-Shared-Users', {
reference: 'statuses',
id: status.id,
status,
type: 'reblogged_by',
count: status.reblogs_count
})
@ -59,7 +59,7 @@ const TimelineFeedback = () => {
onPress={() =>
navigation.push('Tab-Shared-Users', {
reference: 'statuses',
id: status.id,
status,
type: 'favourited_by',
count: status.favourites_count
})

View File

@ -395,7 +395,8 @@
"statuses": {
"reblogged_by": "{{count}} boosted",
"favourited_by": "{{count}} favourited"
}
},
"resultIncomplete": "Results from a remote instance is incomplete"
}
}
}

View File

@ -28,7 +28,7 @@ const AccountAttachments: React.FC<Props> = ({ account }) => {
const queryKeyParams: QueryKeyTimeline[1] = {
page: 'Account',
account: account.id,
exclude_reblogs: true,
exclude_reblogs: false,
only_media: true
}
const { data, refetch } = useTimelineQuery({

View File

@ -25,8 +25,8 @@ const AccountInformationAccount: React.FC<Props> = ({ account }) => {
options: { enabled: account !== undefined }
})
const localInstance = instanceAccount.acct.includes('@')
? instanceAccount.acct.includes(`@${instanceUri}`)
const localInstance = account?.acct.includes('@')
? account?.acct.includes(`@${instanceUri}`)
: true
if (account || (localInstance && instanceAccount)) {
@ -52,7 +52,7 @@ const AccountInformationAccount: React.FC<Props> = ({ account }) => {
}}
selectable
>
@{localInstance ? instanceAccount?.acct : account?.acct}
@{account?.acct}
{localInstance ? `@${instanceUri}` : null}
</CustomText>
{relationship?.followed_by ? t('shared.account.followed_by') : null}

View File

@ -53,7 +53,7 @@ const AccountInformationStats: React.FC<Props> = ({ account, myInfo }) => {
onPress={() =>
navigation.push('Tab-Shared-Users', {
reference: 'accounts',
id: account.id,
account,
type: 'following',
count: account.following_count
})
@ -77,7 +77,7 @@ const AccountInformationStats: React.FC<Props> = ({ account, myInfo }) => {
onPress={() =>
navigation.push('Tab-Shared-Users', {
reference: 'accounts',
id: account.id,
account,
type: 'followers',
count: account.followers_count
})

View File

@ -1,16 +1,22 @@
import ComponentAccount from '@components/Account'
import { HeaderLeft } from '@components/Header'
import Icon from '@components/Icon'
import ComponentSeparator from '@components/Separator'
import CustomText from '@components/Text'
import { TabSharedStackScreenProps } from '@utils/navigation/navigators'
import { QueryKeyUsers, useUsersQuery } from '@utils/queryHooks/users'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback, useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import { View } from 'react-native'
import { FlatList } from 'react-native-gesture-handler'
const TabSharedUsers: React.FC<TabSharedStackScreenProps<'Tab-Shared-Users'>> = ({
navigation,
route: { params }
}) => {
const { colors } = useTheme()
const { t } = useTranslation('screenTabs')
useEffect(() => {
navigation.setOptions({
@ -23,8 +29,9 @@ const TabSharedUsers: React.FC<TabSharedStackScreenProps<'Tab-Shared-Users'>> =
const { data, hasNextPage, fetchNextPage, isFetchingNextPage } = useUsersQuery({
...queryKey[1],
options: {
getPreviousPageParam: firstPage => firstPage.links?.prev && { min_id: firstPage.links.next },
getNextPageParam: lastPage => lastPage.links?.next && { max_id: lastPage.links.next }
getPreviousPageParam: firstPage =>
firstPage.links?.prev?.id && { min_id: firstPage.links.prev.id },
getNextPageParam: lastPage => lastPage.links?.next?.id && { max_id: lastPage.links.next.id }
}
})
const flattenData = data?.pages ? data.pages.flatMap(page => [...page.body]) : []
@ -49,6 +56,31 @@ const TabSharedUsers: React.FC<TabSharedStackScreenProps<'Tab-Shared-Users'>> =
minIndexForVisible: 0,
autoscrollToTopThreshold: 2
}}
ListHeaderComponent={
data?.pages[0]?.warnIncomplete === true ? (
<View
style={{
flexDirection: 'row',
alignItems: 'center',
marginHorizontal: StyleConstants.Spacing.Global.PagePadding,
padding: StyleConstants.Spacing.S,
borderColor: colors.border,
borderWidth: 1,
borderRadius: StyleConstants.Spacing.S
}}
>
<Icon
name='AlertCircle'
color={colors.secondary}
size={StyleConstants.Font.Size.M}
style={{ marginRight: StyleConstants.Spacing.S }}
/>
<CustomText fontStyle='S' style={{ flexShrink: 1, color: colors.secondary }}>
{t('shared.users.resultIncomplete')}
</CustomText>
</View>
) : null
}
/>
)
}

View File

@ -112,13 +112,13 @@ export type TabSharedStackParamList = {
'Tab-Shared-Users':
| {
reference: 'accounts'
id: Mastodon.Account['id']
account: Pick<Mastodon.Account, 'id' | 'username' | 'acct' | 'url'>
type: 'following' | 'followers'
count: number
}
| {
reference: 'statuses'
id: Mastodon.Status['id']
status: Pick<Mastodon.Status, 'id'>
type: 'reblogged_by' | 'favourited_by'
count: number
}

View File

@ -6,24 +6,83 @@ import {
useInfiniteQuery,
UseInfiniteQueryOptions
} from '@tanstack/react-query'
import apiGeneral from '@api/general'
export type QueryKeyUsers = [
'Users',
TabSharedStackParamList['Tab-Shared-Users']
]
export type QueryKeyUsers = ['Users', TabSharedStackParamList['Tab-Shared-Users']]
const queryFunction = ({
queryKey,
pageParam
}: QueryFunctionContext<QueryKeyUsers>) => {
const { reference, id, type } = queryKey[1]
const queryFunction = ({ queryKey, pageParam }: QueryFunctionContext<QueryKeyUsers>) => {
const page = queryKey[1]
let params: { [key: string]: string } = { ...pageParam }
return apiInstance<Mastodon.Account[]>({
method: 'get',
url: `${reference}/${id}/${type}`,
params
})
switch (page.reference) {
case 'statuses':
return apiInstance<Mastodon.Account[]>({
method: 'get',
url: `${page.reference}/${page.status.id}/${page.type}`,
params
}).then(res => ({ ...res, warnIncomplete: false }))
case 'accounts':
const localInstance = page.account.username === page.account.acct
if (localInstance) {
return apiInstance<Mastodon.Account[]>({
method: 'get',
url: `${page.reference}/${page.account.id}/${page.type}`,
params
}).then(res => ({ ...res, warnIncomplete: false }))
} else {
const domain = page.account.url.match(
/^(?:https?:\/\/)?(?:[^@\/\n]+@)?(?:www\.)?([^:\/\n]+)/i
)?.[1]
if (!domain) {
return apiInstance<Mastodon.Account[]>({
method: 'get',
url: `${page.reference}/${page.account.id}/${page.type}`,
params
}).then(res => ({ ...res, warnIncomplete: true }))
}
return apiGeneral<{ accounts: Mastodon.Account[] }>({
method: 'get',
domain,
url: 'api/v2/search',
params: {
q: `@${page.account.acct}`,
type: 'accounts',
limit: '1'
}
})
.then(res => {
if (res?.body?.accounts?.length === 1) {
return apiGeneral<Mastodon.Account[]>({
method: 'get',
domain,
url: `api/v1/${page.reference}/${res.body.accounts[0].id}/${page.type}`,
params
})
.catch(() => {
return apiInstance<Mastodon.Account[]>({
method: 'get',
url: `${page.reference}/${page.account.id}/${page.type}`,
params
}).then(res => ({ ...res, warnIncomplete: true }))
})
.then(res => ({ ...res, warnIncomplete: false }))
} else {
return apiInstance<Mastodon.Account[]>({
method: 'get',
url: `${page.reference}/${page.account.id}/${page.type}`,
params
}).then(res => ({ ...res, warnIncomplete: true }))
}
})
.catch(() => {
return apiInstance<Mastodon.Account[]>({
method: 'get',
url: `${page.reference}/${page.account.id}/${page.type}`,
params
}).then(res => ({ ...res, warnIncomplete: true }))
})
}
}
}
const useUsersQuery = ({
@ -31,7 +90,7 @@ const useUsersQuery = ({
...queryKeyParams
}: QueryKeyUsers[1] & {
options?: UseInfiniteQueryOptions<
InstanceResponse<Mastodon.Account[]>,
InstanceResponse<Mastodon.Account[]> & { warnIncomplete: boolean },
AxiosError
>
}) => {