mirror of
https://github.com/tooot-app/app
synced 2025-04-17 03:37:21 +02:00
Fixed #457
This commit is contained in:
parent
c4316804fc
commit
a4cd24f313
@ -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())
|
||||
}
|
||||
|
@ -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
|
||||
})
|
||||
|
@ -395,7 +395,8 @@
|
||||
"statuses": {
|
||||
"reblogged_by": "{{count}} boosted",
|
||||
"favourited_by": "{{count}} favourited"
|
||||
}
|
||||
},
|
||||
"resultIncomplete": "Results from a remote instance is incomplete"
|
||||
}
|
||||
}
|
||||
}
|
@ -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({
|
||||
|
@ -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}
|
||||
|
@ -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
|
||||
})
|
||||
|
@ -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
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
>
|
||||
}) => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user