mirror of
https://github.com/tooot-app/app
synced 2025-04-25 15:38:42 +02:00
Fixed #536
This commit is contained in:
parent
357c4039cb
commit
bdbacf579e
@ -3,8 +3,8 @@ import { StackNavigationProp } from '@react-navigation/stack'
|
||||
import { TabLocalStackParamList } from '@utils/navigation/navigators'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import React, { useCallback, useState } from 'react'
|
||||
import { Dimensions, Pressable } from 'react-native'
|
||||
import React, { PropsWithChildren, useCallback, useState } from 'react'
|
||||
import { Dimensions, Pressable, View } from 'react-native'
|
||||
import Sparkline from './Sparkline'
|
||||
import CustomText from './Text'
|
||||
|
||||
@ -13,7 +13,11 @@ export interface Props {
|
||||
onPress?: () => void
|
||||
}
|
||||
|
||||
const ComponentHashtag: React.FC<Props> = ({ hashtag, onPress: customOnPress }) => {
|
||||
const ComponentHashtag: React.FC<PropsWithChildren & Props> = ({
|
||||
hashtag,
|
||||
onPress: customOnPress,
|
||||
children
|
||||
}) => {
|
||||
const { colors } = useTheme()
|
||||
const navigation = useNavigation<StackNavigationProp<TabLocalStackParamList>>()
|
||||
|
||||
@ -31,15 +35,11 @@ const ComponentHashtag: React.FC<Props> = ({ hashtag, onPress: customOnPress })
|
||||
style={{
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
padding
|
||||
}}
|
||||
onPress={customOnPress || onPress}
|
||||
onLayout={({
|
||||
nativeEvent: {
|
||||
layout: { height }
|
||||
}
|
||||
}) => setHeight(height - padding * 2 - 1)}
|
||||
>
|
||||
<CustomText
|
||||
fontStyle='M'
|
||||
@ -52,11 +52,22 @@ const ComponentHashtag: React.FC<Props> = ({ hashtag, onPress: customOnPress })
|
||||
>
|
||||
#{hashtag.name}
|
||||
</CustomText>
|
||||
<Sparkline
|
||||
data={hashtag.history.map(h => parseInt(h.uses)).reverse()}
|
||||
width={width}
|
||||
height={height}
|
||||
/>
|
||||
<View
|
||||
style={{ flexDirection: 'row', alignItems: 'center' }}
|
||||
onLayout={({
|
||||
nativeEvent: {
|
||||
layout: { height }
|
||||
}
|
||||
}) => setHeight(height)}
|
||||
>
|
||||
<Sparkline
|
||||
data={hashtag.history.map(h => parseInt(h.uses)).reverse()}
|
||||
width={width}
|
||||
height={height}
|
||||
margin={children ? StyleConstants.Spacing.S : undefined}
|
||||
/>
|
||||
{children}
|
||||
</View>
|
||||
</Pressable>
|
||||
)
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import { maxBy, minBy } from 'lodash'
|
||||
import React from 'react'
|
||||
import { Platform } from 'react-native'
|
||||
import Svg, { G, Path } from 'react-native-svg'
|
||||
|
||||
export interface Props {
|
||||
@ -69,7 +68,7 @@ const Sparkline: React.FC<Props> = ({ data, width, height, margin = 0 }) => {
|
||||
const fillPoints = linePoints.concat(closePolyPoints)
|
||||
|
||||
return (
|
||||
<Svg height={Platform.OS !== 'android' ? 'auto' : 24} width={width}>
|
||||
<Svg height={height} width={width} style={{ marginRight: margin }}>
|
||||
<G>
|
||||
<Path d={'M' + fillPoints.join(' ')} fill={colors.blue} fillOpacity={0.1} />
|
||||
<Path
|
||||
|
@ -5,6 +5,7 @@
|
||||
"cancel": "Cancel",
|
||||
"discard": "Discard",
|
||||
"continue": "Continue",
|
||||
"create": "Create",
|
||||
"delete": "Delete",
|
||||
"done": "Done"
|
||||
},
|
||||
|
@ -40,6 +40,9 @@
|
||||
"favourites": {
|
||||
"name": "Favourites"
|
||||
},
|
||||
"followedTags": {
|
||||
"name": "Followed hashtags"
|
||||
},
|
||||
"fontSize": {
|
||||
"name": "Toot Font Size"
|
||||
},
|
||||
@ -53,7 +56,7 @@
|
||||
"name": "Users in list: {{list}}"
|
||||
},
|
||||
"listAdd": {
|
||||
"name": "Add a List"
|
||||
"name": "Create a List"
|
||||
},
|
||||
"listEdit": {
|
||||
"name": "Edit List Details"
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { HeaderCenter, HeaderLeft } from '@components/Header'
|
||||
import { HeaderLeft } from '@components/Header'
|
||||
import { createNativeStackNavigator } from '@react-navigation/native-stack'
|
||||
import { TabMeStackParamList } from '@utils/navigation/navigators'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Platform } from 'react-native'
|
||||
import TabMeBookmarks from './Me/Bookmarks'
|
||||
import TabMeConversations from './Me/Cconversations'
|
||||
import TabMeFavourites from './Me/Favourites'
|
||||
import TabMeFollowedTags from './Me/FollowedTags'
|
||||
import TabMeList from './Me/List'
|
||||
import TabMeListAccounts from './Me/List/Accounts'
|
||||
import TabMeListEdit from './Me/List/Edit'
|
||||
@ -42,9 +42,6 @@ const TabMe = React.memo(
|
||||
component={TabMeBookmarks}
|
||||
options={({ navigation }: any) => ({
|
||||
title: t('me.stacks.bookmarks.name'),
|
||||
...(Platform.OS === 'android' && {
|
||||
headerCenter: () => <HeaderCenter content={t('me.stacks.bookmarks.name')} />
|
||||
}),
|
||||
headerLeft: () => <HeaderLeft onPress={() => navigation.pop(1)} />
|
||||
})}
|
||||
/>
|
||||
@ -53,9 +50,6 @@ const TabMe = React.memo(
|
||||
component={TabMeConversations}
|
||||
options={({ navigation }: any) => ({
|
||||
title: t('me.stacks.conversations.name'),
|
||||
...(Platform.OS === 'android' && {
|
||||
headerCenter: () => <HeaderCenter content={t('me.stacks.conversations.name')} />
|
||||
}),
|
||||
headerLeft: () => <HeaderLeft onPress={() => navigation.pop(1)} />
|
||||
})}
|
||||
/>
|
||||
@ -64,9 +58,14 @@ const TabMe = React.memo(
|
||||
component={TabMeFavourites}
|
||||
options={({ navigation }: any) => ({
|
||||
title: t('me.stacks.favourites.name'),
|
||||
...(Platform.OS === 'android' && {
|
||||
headerCenter: () => <HeaderCenter content={t('me.stacks.favourites.name')} />
|
||||
}),
|
||||
headerLeft: () => <HeaderLeft onPress={() => navigation.pop(1)} />
|
||||
})}
|
||||
/>
|
||||
<Stack.Screen
|
||||
name='Tab-Me-FollowedTags'
|
||||
component={TabMeFollowedTags}
|
||||
options={({ navigation }: any) => ({
|
||||
title: t('me.stacks.followedTags.name'),
|
||||
headerLeft: () => <HeaderLeft onPress={() => navigation.pop(1)} />
|
||||
})}
|
||||
/>
|
||||
@ -75,15 +74,6 @@ const TabMe = React.memo(
|
||||
component={TabMeList}
|
||||
options={({ route, navigation }: any) => ({
|
||||
title: t('me.stacks.list.name', { list: route.params.title }),
|
||||
...(Platform.OS === 'android' && {
|
||||
headerCenter: () => (
|
||||
<HeaderCenter
|
||||
content={t('me.stacks.list.name', {
|
||||
list: route.params.title
|
||||
})}
|
||||
/>
|
||||
)
|
||||
}),
|
||||
headerLeft: () => <HeaderLeft onPress={() => navigation.pop(1)} />
|
||||
})}
|
||||
/>
|
||||
@ -92,9 +82,6 @@ const TabMe = React.memo(
|
||||
component={TabMeListAccounts}
|
||||
options={({ navigation, route: { params } }) => ({
|
||||
title: t('me.stacks.listAccounts.name', { list: params.title }),
|
||||
...(Platform.OS === 'android' && {
|
||||
headerCenter: () => <HeaderCenter content={t('me.stacks.listsAdd.name')} />
|
||||
}),
|
||||
headerLeft: () => <HeaderLeft onPress={() => navigation.pop(1)} />
|
||||
})}
|
||||
/>
|
||||
@ -111,9 +98,6 @@ const TabMe = React.memo(
|
||||
component={TabMeListList}
|
||||
options={({ navigation }: any) => ({
|
||||
title: t('me.stacks.lists.name'),
|
||||
...(Platform.OS === 'android' && {
|
||||
headerCenter: () => <HeaderCenter content={t('me.stacks.lists.name')} />
|
||||
}),
|
||||
headerLeft: () => <HeaderLeft onPress={() => navigation.pop(1)} />
|
||||
})}
|
||||
/>
|
||||
@ -130,9 +114,6 @@ const TabMe = React.memo(
|
||||
component={TabMePush}
|
||||
options={({ navigation }) => ({
|
||||
title: t('me.stacks.push.name'),
|
||||
...(Platform.OS === 'android' && {
|
||||
headerCenter: () => <HeaderCenter content={t('me.stacks.push.name')} />
|
||||
}),
|
||||
headerLeft: () => <HeaderLeft onPress={() => navigation.goBack()} />
|
||||
})}
|
||||
/>
|
||||
@ -149,9 +130,6 @@ const TabMe = React.memo(
|
||||
component={TabMeSettingsFontsize}
|
||||
options={({ navigation }: any) => ({
|
||||
title: t('me.stacks.fontSize.name'),
|
||||
...(Platform.OS === 'android' && {
|
||||
headerCenter: () => <HeaderCenter content={t('me.stacks.fontSize.name')} />
|
||||
}),
|
||||
headerLeft: () => <HeaderLeft onPress={() => navigation.pop(1)} />
|
||||
})}
|
||||
/>
|
||||
@ -160,9 +138,6 @@ const TabMe = React.memo(
|
||||
component={TabMeSettingsLanguage}
|
||||
options={({ navigation }: any) => ({
|
||||
title: t('me.stacks.language.name'),
|
||||
...(Platform.OS === 'android' && {
|
||||
headerCenter: () => <HeaderCenter content={t('me.stacks.language.name')} />
|
||||
}),
|
||||
headerLeft: () => <HeaderLeft onPress={() => navigation.pop(1)} />
|
||||
})}
|
||||
/>
|
||||
@ -173,9 +148,6 @@ const TabMe = React.memo(
|
||||
presentation: 'modal',
|
||||
headerShown: true,
|
||||
title: t('me.stacks.switch.name'),
|
||||
...(Platform.OS === 'android' && {
|
||||
headerCenter: () => <HeaderCenter content={t('me.stacks.switch.name')} />
|
||||
}),
|
||||
headerLeft: () => (
|
||||
<HeaderLeft content='ChevronDown' onPress={() => navigation.goBack()} />
|
||||
)
|
||||
|
71
src/screens/Tabs/Me/FollowedTags.tsx
Normal file
71
src/screens/Tabs/Me/FollowedTags.tsx
Normal file
@ -0,0 +1,71 @@
|
||||
import Button from '@components/Button'
|
||||
import haptics from '@components/haptics'
|
||||
import ComponentHashtag from '@components/Hashtag'
|
||||
import { displayMessage } from '@components/Message'
|
||||
import ComponentSeparator from '@components/Separator'
|
||||
import { TabMeStackScreenProps } from '@utils/navigation/navigators'
|
||||
import { useFollowedTagsQuery, useTagsMutation } from '@utils/queryHooks/tags'
|
||||
import React, { useEffect } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { FlatList } from 'react-native-gesture-handler'
|
||||
|
||||
const TabMeFollowedTags: React.FC<TabMeStackScreenProps<'Tab-Me-FollowedTags'>> = ({
|
||||
navigation
|
||||
}) => {
|
||||
const { t } = useTranslation('screenTabs')
|
||||
|
||||
const { data, fetchNextPage, refetch } = useFollowedTagsQuery()
|
||||
const flattenData = data?.pages ? data.pages.flatMap(page => [...page.body]) : []
|
||||
useEffect(() => {
|
||||
if (flattenData.length === 0) {
|
||||
navigation.goBack()
|
||||
}
|
||||
}, [flattenData.length])
|
||||
|
||||
const mutation = useTagsMutation({
|
||||
onSuccess: () => {
|
||||
haptics('Light')
|
||||
refetch()
|
||||
},
|
||||
onError: (err: any, { to }) => {
|
||||
displayMessage({
|
||||
type: 'error',
|
||||
message: t('common:message.error.message', {
|
||||
function: to ? t('shared.hashtag.follow') : t('shared.hashtag.unfollow')
|
||||
}),
|
||||
...(err.status &&
|
||||
typeof err.status === 'number' &&
|
||||
err.data &&
|
||||
err.data.error &&
|
||||
typeof err.data.error === 'string' && {
|
||||
description: err.data.error
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<FlatList
|
||||
style={{ flex: 1 }}
|
||||
data={flattenData}
|
||||
renderItem={({ item }) => (
|
||||
<ComponentHashtag
|
||||
hashtag={item}
|
||||
onPress={() => {}}
|
||||
children={
|
||||
<Button
|
||||
type='text'
|
||||
content={t('shared.hashtag.unfollow')}
|
||||
onPress={() => mutation.mutate({ tag: item.name, to: !item.following })}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
onEndReached={() => fetchNextPage()}
|
||||
onEndReachedThreshold={0.5}
|
||||
ItemSeparatorComponent={ComponentSeparator}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default TabMeFollowedTags
|
@ -7,14 +7,14 @@ import { useTranslation } from 'react-i18next'
|
||||
|
||||
const TabMeListList: React.FC<TabMeStackScreenProps<'Tab-Me-List-List'>> = ({ navigation }) => {
|
||||
const { data } = useListsQuery({})
|
||||
const { t } = useTranslation('screenTabs')
|
||||
const { t } = useTranslation()
|
||||
|
||||
useEffect(() => {
|
||||
navigation.setOptions({
|
||||
headerRight: () => (
|
||||
<HeaderRight
|
||||
accessibilityLabel={t('me.stacks.listAdd.name')}
|
||||
content='Plus'
|
||||
type='text'
|
||||
content={t('common:buttons.create')}
|
||||
onPress={() => navigation.navigate('Tab-Me-List-Edit', { type: 'add' })}
|
||||
/>
|
||||
)
|
||||
|
@ -3,6 +3,7 @@ import { useNavigation } from '@react-navigation/native'
|
||||
import { useAppDispatch } from '@root/store'
|
||||
import { useAnnouncementQuery } from '@utils/queryHooks/announcement'
|
||||
import { useListsQuery } from '@utils/queryHooks/lists'
|
||||
import { useFollowedTagsQuery } from '@utils/queryHooks/tags'
|
||||
import { getInstanceMePage, updateInstanceMePage } from '@utils/slices/instancesSlice'
|
||||
import { getInstancePush } from '@utils/slices/instancesSlice'
|
||||
import React, { useEffect } from 'react'
|
||||
@ -16,39 +17,40 @@ const Collections: React.FC = () => {
|
||||
const dispatch = useAppDispatch()
|
||||
const mePage = useSelector(getInstanceMePage)
|
||||
|
||||
const listsQuery = useListsQuery({
|
||||
useFollowedTagsQuery({
|
||||
options: {
|
||||
notifyOnChangeProps: ['data']
|
||||
onSuccess: data =>
|
||||
dispatch(
|
||||
updateInstanceMePage({
|
||||
followedTags: { shown: !!data?.pages?.[0].body?.length }
|
||||
})
|
||||
)
|
||||
}
|
||||
})
|
||||
useEffect(() => {
|
||||
if (listsQuery.isSuccess) {
|
||||
dispatch(
|
||||
updateInstanceMePage({
|
||||
lists: { shown: listsQuery.data?.length ? true : false }
|
||||
})
|
||||
)
|
||||
useListsQuery({
|
||||
options: {
|
||||
onSuccess: data =>
|
||||
dispatch(
|
||||
updateInstanceMePage({
|
||||
lists: { shown: !!data?.length }
|
||||
})
|
||||
)
|
||||
}
|
||||
}, [listsQuery.isSuccess, listsQuery.data?.length])
|
||||
|
||||
const announcementsQuery = useAnnouncementQuery({
|
||||
})
|
||||
useAnnouncementQuery({
|
||||
showAll: true,
|
||||
options: {
|
||||
notifyOnChangeProps: ['data']
|
||||
onSuccess: data =>
|
||||
dispatch(
|
||||
updateInstanceMePage({
|
||||
announcements: {
|
||||
shown: !!data?.length ? true : false,
|
||||
unread: data?.filter(announcement => !announcement.read).length
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
})
|
||||
useEffect(() => {
|
||||
if (announcementsQuery.data) {
|
||||
dispatch(
|
||||
updateInstanceMePage({
|
||||
announcements: {
|
||||
shown: announcementsQuery.data.length ? true : false,
|
||||
unread: announcementsQuery.data.filter(announcement => !announcement.read).length
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
}, [announcementsQuery.data])
|
||||
|
||||
const instancePush = useSelector(getInstancePush, (prev, next) => prev?.global === next?.global)
|
||||
|
||||
@ -80,6 +82,14 @@ const Collections: React.FC = () => {
|
||||
onPress={() => navigation.navigate('Tab-Me-List-List')}
|
||||
/>
|
||||
) : null}
|
||||
{mePage.followedTags.shown ? (
|
||||
<MenuRow
|
||||
iconFront='Hash'
|
||||
iconBack='ChevronRight'
|
||||
title={t('me.stacks.followedTags.name')}
|
||||
onPress={() => navigation.navigate('Tab-Me-FollowedTags')}
|
||||
/>
|
||||
) : null}
|
||||
{mePage.announcements.shown ? (
|
||||
<MenuRow
|
||||
iconFront='Clipboard'
|
||||
|
@ -3,11 +3,11 @@ import { HeaderLeft, HeaderRight } from '@components/Header'
|
||||
import { displayMessage } from '@components/Message'
|
||||
import Timeline from '@components/Timeline'
|
||||
import TimelineDefault from '@components/Timeline/Default'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import { TabSharedStackScreenProps } from '@utils/navigation/navigators'
|
||||
import { useTagsMutation, useTagsQuery } from '@utils/queryHooks/tags'
|
||||
import { QueryKeyFollowedTags, useTagsMutation, useTagsQuery } from '@utils/queryHooks/tags'
|
||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||
import { checkInstanceFeature } from '@utils/slices/instancesSlice'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import React, { useEffect } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useSelector } from 'react-redux'
|
||||
@ -27,7 +27,6 @@ const TabSharedHashtag: React.FC<TabSharedStackScreenProps<'Tab-Shared-Hashtag'>
|
||||
|
||||
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Hashtag', hashtag }]
|
||||
|
||||
const { theme } = useTheme()
|
||||
const { t } = useTranslation('screenTabs')
|
||||
|
||||
const canFollowTags = useSelector(checkInstanceFeature('follow_tags'))
|
||||
@ -35,14 +34,16 @@ const TabSharedHashtag: React.FC<TabSharedStackScreenProps<'Tab-Shared-Hashtag'>
|
||||
tag: hashtag,
|
||||
options: { enabled: canFollowTags }
|
||||
})
|
||||
const queryClient = useQueryClient()
|
||||
const mutation = useTagsMutation({
|
||||
onSuccess: () => {
|
||||
haptics('Success')
|
||||
refetch()
|
||||
const queryKeyFollowedTags: QueryKeyFollowedTags = ['FollowedTags']
|
||||
queryClient.invalidateQueries({ queryKey: queryKeyFollowedTags })
|
||||
},
|
||||
onError: (err: any, { to }) => {
|
||||
displayMessage({
|
||||
theme,
|
||||
type: 'error',
|
||||
message: t('common:message.error.message', {
|
||||
function: to ? t('shared.hashtag.follow') : t('shared.hashtag.unfollow')
|
||||
@ -68,7 +69,7 @@ const TabSharedHashtag: React.FC<TabSharedStackScreenProps<'Tab-Shared-Hashtag'>
|
||||
content={data?.following ? t('shared.hashtag.unfollow') : t('shared.hashtag.follow')}
|
||||
onPress={() =>
|
||||
typeof data?.following === 'boolean' &&
|
||||
mutation.mutate({ tag: hashtag, type: 'follow', to: !data.following })
|
||||
mutation.mutate({ tag: hashtag, to: !data.following })
|
||||
}
|
||||
/>
|
||||
)
|
||||
|
@ -135,6 +135,7 @@ const instancesMigration = {
|
||||
instances: state.instances.map(instance => {
|
||||
return {
|
||||
...instance,
|
||||
mePage: { ...instance.mePage, followedTags: { shown: false } },
|
||||
push: {
|
||||
...instance.push,
|
||||
global: instance.push.global.value,
|
||||
|
@ -47,6 +47,7 @@ export type InstanceV11 = {
|
||||
}
|
||||
}
|
||||
mePage: {
|
||||
followedTags: { shown: boolean }
|
||||
lists: { shown: boolean }
|
||||
announcements: { shown: boolean; unread: number }
|
||||
}
|
||||
|
@ -143,6 +143,7 @@ export type TabMeStackParamList = {
|
||||
'Tab-Me-Bookmarks': undefined
|
||||
'Tab-Me-Conversations': undefined
|
||||
'Tab-Me-Favourites': undefined
|
||||
'Tab-Me-FollowedTags': undefined
|
||||
'Tab-Me-List': Mastodon.List
|
||||
'Tab-Me-List-Accounts': Omit<Mastodon.List, 'replies_policy'>
|
||||
'Tab-Me-List-Edit':
|
||||
|
@ -1,32 +1,40 @@
|
||||
import apiInstance from '@api/instance'
|
||||
import apiInstance, { InstanceResponse } from '@api/instance'
|
||||
import { AxiosError } from 'axios'
|
||||
import {
|
||||
QueryFunctionContext,
|
||||
useInfiniteQuery,
|
||||
UseInfiniteQueryOptions,
|
||||
useMutation,
|
||||
UseMutationOptions,
|
||||
useQuery,
|
||||
UseQueryOptions
|
||||
} from '@tanstack/react-query'
|
||||
import { infinitePageParams } from './utils'
|
||||
|
||||
type QueryKeyFollowedTags = ['FollowedTags']
|
||||
const useFollowedTagsQuery = ({
|
||||
options
|
||||
}: {
|
||||
options?: UseQueryOptions<Mastodon.Tag, AxiosError>
|
||||
}) => {
|
||||
export type QueryKeyFollowedTags = ['FollowedTags']
|
||||
const useFollowedTagsQuery = (
|
||||
params: {
|
||||
options?: Omit<
|
||||
UseInfiniteQueryOptions<InstanceResponse<Mastodon.Tag[]>, AxiosError>,
|
||||
'getPreviousPageParam' | 'getNextPageParam'
|
||||
>
|
||||
} | void
|
||||
) => {
|
||||
const queryKey: QueryKeyFollowedTags = ['FollowedTags']
|
||||
return useQuery(
|
||||
return useInfiniteQuery(
|
||||
queryKey,
|
||||
async ({ pageParam }: QueryFunctionContext<QueryKeyFollowedTags>) => {
|
||||
const params: { [key: string]: string } = { ...pageParam }
|
||||
const res = await apiInstance<Mastodon.Tag>({ method: 'get', url: `followed_tags`, params })
|
||||
return res.body
|
||||
return await apiInstance<Mastodon.Tag[]>({ method: 'get', url: `followed_tags`, params })
|
||||
},
|
||||
options
|
||||
{
|
||||
...params?.options,
|
||||
...infinitePageParams
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
type QueryKeyTags = ['Tags', { tag: string }]
|
||||
export type QueryKeyTags = ['Tags', { tag: string }]
|
||||
const queryFunction = async ({ queryKey }: QueryFunctionContext<QueryKeyTags>) => {
|
||||
const { tag } = queryKey[1]
|
||||
|
||||
@ -43,15 +51,12 @@ const useTagsQuery = ({
|
||||
return useQuery(queryKey, queryFunction, options)
|
||||
}
|
||||
|
||||
type MutationVarsAnnouncement = { tag: string; type: 'follow'; to: boolean }
|
||||
const mutationFunction = async ({ tag, type, to }: MutationVarsAnnouncement) => {
|
||||
switch (type) {
|
||||
case 'follow':
|
||||
return apiInstance<{}>({
|
||||
method: 'post',
|
||||
url: `tags/${tag}/${to ? 'follow' : 'unfollow'}`
|
||||
})
|
||||
}
|
||||
type MutationVarsAnnouncement = { tag: string; to: boolean }
|
||||
const mutationFunction = async ({ tag, to }: MutationVarsAnnouncement) => {
|
||||
return apiInstance<{}>({
|
||||
method: 'post',
|
||||
url: `tags/${tag}/${to ? 'follow' : 'unfollow'}`
|
||||
})
|
||||
}
|
||||
const useTagsMutation = (options: UseMutationOptions<{}, AxiosError, MutationVarsAnnouncement>) => {
|
||||
return useMutation(mutationFunction, options)
|
||||
|
8
src/utils/queryHooks/utils.ts
Normal file
8
src/utils/queryHooks/utils.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { InstanceResponse } from '@api/instance'
|
||||
|
||||
export const infinitePageParams = {
|
||||
getPreviousPageParam: (firstPage: InstanceResponse<any>) =>
|
||||
firstPage.links?.prev && { since_id: firstPage.links.next },
|
||||
getNextPageParam: (lastPage: InstanceResponse<any>) =>
|
||||
lastPage.links?.next && { max_id: lastPage.links.next }
|
||||
}
|
@ -107,6 +107,7 @@ const addInstance = createAsyncThunk(
|
||||
},
|
||||
timelinesLookback: {},
|
||||
mePage: {
|
||||
followedTags: { shown: false },
|
||||
lists: { shown: false },
|
||||
announcements: { shown: false, unread: 0 }
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user