mirror of
				https://github.com/tooot-app/app
				synced 2025-06-05 22:19:13 +02:00 
			
		
		
		
	| @@ -4,39 +4,47 @@ 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 } from 'react' | ||||
| import React, { PropsWithChildren } from 'react' | ||||
| import { Pressable, View } from 'react-native' | ||||
| import GracefullyImage from './GracefullyImage' | ||||
| import CustomText from './Text' | ||||
|  | ||||
| export interface Props { | ||||
|   account: Mastodon.Account | ||||
|   onPress?: () => void | ||||
|   Component?: typeof View | typeof Pressable | ||||
|   props?: {} | ||||
| } | ||||
|  | ||||
| const ComponentAccount: React.FC<Props> = ({ account, onPress: customOnPress }) => { | ||||
| const ComponentAccount: React.FC<PropsWithChildren & Props> = ({ | ||||
|   account, | ||||
|   Component, | ||||
|   props, | ||||
|   children | ||||
| }) => { | ||||
|   const { colors } = useTheme() | ||||
|   const navigation = useNavigation<StackNavigationProp<TabLocalStackParamList>>() | ||||
|  | ||||
|   const onPress = useCallback(() => navigation.push('Tab-Shared-Account', { account }), []) | ||||
|   if (!props) { | ||||
|     props = { onPress: () => navigation.push('Tab-Shared-Account', { account }) } | ||||
|   } | ||||
|  | ||||
|   return ( | ||||
|     <Pressable | ||||
|       accessibilityRole='button' | ||||
|       style={{ | ||||
|   return React.createElement( | ||||
|     Component || Pressable, | ||||
|     { | ||||
|       ...props, | ||||
|       style: { | ||||
|         flex: 1, | ||||
|         paddingHorizontal: StyleConstants.Spacing.Global.PagePadding, | ||||
|         paddingVertical: StyleConstants.Spacing.M, | ||||
|         flexDirection: 'row', | ||||
|         alignSelf: 'flex-start', | ||||
|         justifyContent: 'space-between', | ||||
|         alignItems: 'center' | ||||
|       }} | ||||
|       onPress={customOnPress || onPress} | ||||
|     > | ||||
|       } | ||||
|     }, | ||||
|     <View style={{ flex: 1, flexDirection: 'row', alignItems: 'center' }}> | ||||
|       <GracefullyImage | ||||
|         uri={{ original: account.avatar, static: account.avatar_static }} | ||||
|         style={{ | ||||
|           alignSelf: 'flex-start', | ||||
|           width: StyleConstants.Avatar.S, | ||||
|           height: StyleConstants.Avatar.S, | ||||
|           borderRadius: 6, | ||||
| @@ -62,7 +70,8 @@ const ComponentAccount: React.FC<Props> = ({ account, onPress: customOnPress }) | ||||
|           @{account.acct} | ||||
|         </CustomText> | ||||
|       </View> | ||||
|     </Pressable> | ||||
|     </View>, | ||||
|     children | ||||
|   ) | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -57,7 +57,7 @@ const TimelineEmpty = React.memo( | ||||
|                 style={{ | ||||
|                   marginTop: StyleConstants.Spacing.S, | ||||
|                   marginBottom: StyleConstants.Spacing.L, | ||||
|                   color: colors.primaryDefault | ||||
|                   color: colors.secondary | ||||
|                 }} | ||||
|               > | ||||
|                 {t('empty.success.message')} | ||||
|   | ||||
| @@ -46,17 +46,20 @@ | ||||
|       "language": { | ||||
|         "name": "Language" | ||||
|       }, | ||||
|       "lists": { | ||||
|         "name": "Lists" | ||||
|       "list": { | ||||
|         "name": "List: {{list}}" | ||||
|       }, | ||||
|       "listAccounts": { | ||||
|         "name": "Users in list: {{list}}" | ||||
|       }, | ||||
|       "listAdd": { | ||||
|         "name": "Add a List" | ||||
|       }, | ||||
|       "listEdit": { | ||||
|         "name": "Edit List" | ||||
|         "name": "Edit List Details" | ||||
|       }, | ||||
|       "list": { | ||||
|         "name": "List: {{list}}" | ||||
|       "lists": { | ||||
|         "name": "Lists" | ||||
|       }, | ||||
|       "push": { | ||||
|         "name": "Push Notification" | ||||
| @@ -93,7 +96,13 @@ | ||||
|         "XXL": "XXL" | ||||
|       } | ||||
|     }, | ||||
|     "listAccounts": { | ||||
|       "heading": "Manage users", | ||||
|       "error": "Delete user from list", | ||||
|       "empty": "No user added in this list" | ||||
|     }, | ||||
|     "listEdit": { | ||||
|       "heading": "Edit list details", | ||||
|       "title": "Title", | ||||
|       "repliesPolicy": { | ||||
|         "heading": "Show replies to:", | ||||
|   | ||||
| @@ -44,7 +44,7 @@ const ComposeRootSuggestion: React.FC<Props> = ({ item }) => { | ||||
|   } | ||||
|  | ||||
|   return item.acct ? ( | ||||
|     <ComponentAccount account={item} onPress={onPress} /> | ||||
|     <ComponentAccount account={item} props={{ onPress }} /> | ||||
|   ) : ( | ||||
|     <ComponentHashtag hashtag={item} onPress={onPress} origin='suggestion' /> | ||||
|   ) | ||||
|   | ||||
| @@ -8,8 +8,9 @@ import TabMeBookmarks from './Me/Bookmarks' | ||||
| import TabMeConversations from './Me/Cconversations' | ||||
| import TabMeFavourites from './Me/Favourites' | ||||
| import TabMeList from './Me/List' | ||||
| import TabMeListEdit from './Me/ListEdit' | ||||
| import TabMeLists from './Me/Lists' | ||||
| import TabMeListAccounts from './Me/List/Accounts' | ||||
| import TabMeListEdit from './Me/List/Edit' | ||||
| import TabMeListList from './Me/List/List' | ||||
| import TabMeProfile from './Me/Profile' | ||||
| import TabMePush from './Me/Push' | ||||
| import TabMeRoot from './Me/Root' | ||||
| @@ -86,21 +87,28 @@ const TabMe = React.memo( | ||||
|             headerLeft: () => <HeaderLeft onPress={() => navigation.pop(1)} /> | ||||
|           })} | ||||
|         /> | ||||
|         <Stack.Screen | ||||
|           name='Tab-Me-List-Accounts' | ||||
|           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)} /> | ||||
|           })} | ||||
|         /> | ||||
|         <Stack.Screen | ||||
|           name='Tab-Me-List-Edit' | ||||
|           component={TabMeListEdit} | ||||
|           options={{ | ||||
|             gestureEnabled: false, | ||||
|             presentation: 'modal', | ||||
|             title: t('me.stacks.listsAdd.name'), | ||||
|             ...(Platform.OS === 'android' && { | ||||
|               headerCenter: () => <HeaderCenter content={t('me.stacks.listsAdd.name')} /> | ||||
|             }) | ||||
|             presentation: 'modal' | ||||
|           }} | ||||
|         /> | ||||
|         <Stack.Screen | ||||
|           name='Tab-Me-Lists' | ||||
|           component={TabMeLists} | ||||
|           name='Tab-Me-List-List' | ||||
|           component={TabMeListList} | ||||
|           options={({ navigation }: any) => ({ | ||||
|             title: t('me.stacks.lists.name'), | ||||
|             ...(Platform.OS === 'android' && { | ||||
|   | ||||
							
								
								
									
										99
									
								
								src/screens/Tabs/Me/List/Accounts.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								src/screens/Tabs/Me/List/Accounts.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | ||||
| import ComponentAccount from '@components/Account' | ||||
| import Button from '@components/Button' | ||||
| import haptics from '@components/haptics' | ||||
| import { displayMessage } from '@components/Message' | ||||
| import CustomText from '@components/Text' | ||||
| import { TabMeStackScreenProps } from '@utils/navigation/navigators' | ||||
| import { | ||||
|   QueryKeyListAccounts, | ||||
|   useListAccountsMutation, | ||||
|   useListAccountsQuery | ||||
| } from '@utils/queryHooks/lists' | ||||
| import { StyleConstants } from '@utils/styles/constants' | ||||
| import { useTheme } from '@utils/styles/ThemeManager' | ||||
| import React from 'react' | ||||
| import { useTranslation } from 'react-i18next' | ||||
| import { FlatList, View } from 'react-native' | ||||
|  | ||||
| const TabMeListAccounts: React.FC<TabMeStackScreenProps<'Tab-Me-List-Accounts'>> = ({ | ||||
|   route: { params } | ||||
| }) => { | ||||
|   const { colors, theme } = useTheme() | ||||
|   const { t } = useTranslation('screenTabs') | ||||
|  | ||||
|   const queryKey: QueryKeyListAccounts = ['ListAccounts', { id: params.id }] | ||||
|   const { data, refetch, fetchNextPage, hasNextPage } = useListAccountsQuery({ | ||||
|     ...queryKey[1], | ||||
|     options: { | ||||
|       getNextPageParam: lastPage => | ||||
|         lastPage?.links?.next && { | ||||
|           max_id: lastPage.links.next | ||||
|         } | ||||
|     } | ||||
|   }) | ||||
|  | ||||
|   const flattenData = data?.pages ? data.pages?.flatMap(page => [...page.body]) : [] | ||||
|  | ||||
|   const mutation = useListAccountsMutation({ | ||||
|     onSuccess: () => { | ||||
|       haptics('Light') | ||||
|       refetch() | ||||
|     }, | ||||
|     onError: () => { | ||||
|       displayMessage({ | ||||
|         theme, | ||||
|         type: 'error', | ||||
|         message: t('common:message.error.message', { | ||||
|           function: t('me.listAccounts.error') | ||||
|         }) | ||||
|       }) | ||||
|     } | ||||
|   }) | ||||
|  | ||||
|   return ( | ||||
|     <FlatList | ||||
|       data={flattenData} | ||||
|       renderItem={({ item, index }) => ( | ||||
|         <ComponentAccount | ||||
|           key={index} | ||||
|           account={item} | ||||
|           Component={View} | ||||
|           children={ | ||||
|             <Button | ||||
|               type='icon' | ||||
|               content='X' | ||||
|               round | ||||
|               onPress={() => | ||||
|                 mutation.mutate({ type: 'delete', payload: { id: params.id, accounts: [item.id] } }) | ||||
|               } | ||||
|             /> | ||||
|           } | ||||
|         /> | ||||
|       )} | ||||
|       ListEmptyComponent={ | ||||
|         <View | ||||
|           style={{ | ||||
|             flex: 1, | ||||
|             minHeight: '100%', | ||||
|             justifyContent: 'center', | ||||
|             alignItems: 'center' | ||||
|           }} | ||||
|         > | ||||
|           <CustomText | ||||
|             fontStyle='M' | ||||
|             style={{ | ||||
|               marginTop: StyleConstants.Spacing.S, | ||||
|               marginBottom: StyleConstants.Spacing.L, | ||||
|               color: colors.secondary | ||||
|             }} | ||||
|           > | ||||
|             {t('me.listAccounts.empty')} | ||||
|           </CustomText> | ||||
|         </View> | ||||
|       } | ||||
|       onEndReached={() => hasNextPage && fetchNextPage()} | ||||
|     /> | ||||
|   ) | ||||
| } | ||||
|  | ||||
| export default TabMeListAccounts | ||||
| @@ -1,6 +1,6 @@ | ||||
| import { EmojisState } from '@components/Emojis/helpers/EmojisContext' | ||||
| import haptics from '@components/haptics' | ||||
| import { HeaderLeft, HeaderRight } from '@components/Header' | ||||
| import { HeaderCenter, HeaderLeft, HeaderRight } from '@components/Header' | ||||
| import ComponentInput from '@components/Input' | ||||
| import { displayMessage, Message } from '@components/Message' | ||||
| import Selections from '@components/Selections' | ||||
| @@ -12,7 +12,7 @@ import { StyleConstants } from '@utils/styles/constants' | ||||
| import { useTheme } from '@utils/styles/ThemeManager' | ||||
| import React, { useEffect, useRef, useState } from 'react' | ||||
| import { useTranslation } from 'react-i18next' | ||||
| import { Alert, ScrollView, TextInput } from 'react-native' | ||||
| import { Alert, Platform, ScrollView, TextInput } from 'react-native' | ||||
| import { useQueryClient } from 'react-query' | ||||
| 
 | ||||
| const TabMeListEdit: React.FC<TabMeStackScreenProps<'Tab-Me-List-Edit'>> = ({ | ||||
| @@ -83,6 +83,16 @@ const TabMeListEdit: React.FC<TabMeStackScreenProps<'Tab-Me-List-Edit'>> = ({ | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     navigation.setOptions({ | ||||
|       title: params.type === 'add' ? t('me.stacks.listAdd.name') : t('me.stacks.listEdit.name'), | ||||
|       ...(Platform.OS === 'android' && { | ||||
|         headerCenter: () => ( | ||||
|           <HeaderCenter | ||||
|             content={ | ||||
|               params.type === 'add' ? t('me.stacks.listAdd.name') : t('me.stacks.listEdit.name') | ||||
|             } | ||||
|           /> | ||||
|         ) | ||||
|       }), | ||||
|       headerLeft: () => ( | ||||
|         <HeaderLeft | ||||
|           content='X' | ||||
| @@ -5,7 +5,7 @@ import { useListsQuery } from '@utils/queryHooks/lists' | ||||
| import React, { useEffect } from 'react' | ||||
| import { useTranslation } from 'react-i18next' | ||||
| 
 | ||||
| const TabMeLists: React.FC<TabMeStackScreenProps<'Tab-Me-Lists'>> = ({ navigation }) => { | ||||
| const TabMeListList: React.FC<TabMeStackScreenProps<'Tab-Me-List-List'>> = ({ navigation }) => { | ||||
|   const { data } = useListsQuery({}) | ||||
|   const { t } = useTranslation('screenTabs') | ||||
| 
 | ||||
| @@ -23,17 +23,17 @@ const TabMeLists: React.FC<TabMeStackScreenProps<'Tab-Me-Lists'>> = ({ navigatio | ||||
| 
 | ||||
|   return ( | ||||
|     <MenuContainer> | ||||
|       {data?.map((d: Mastodon.List, i: number) => ( | ||||
|       {data?.map((params, index) => ( | ||||
|         <MenuRow | ||||
|           key={i} | ||||
|           key={index} | ||||
|           iconFront='List' | ||||
|           iconBack='ChevronRight' | ||||
|           title={d.title} | ||||
|           onPress={() => navigation.navigate('Tab-Me-List', d)} | ||||
|           title={params.title} | ||||
|           onPress={() => navigation.navigate('Tab-Me-List', params)} | ||||
|         /> | ||||
|       ))} | ||||
|     </MenuContainer> | ||||
|   ) | ||||
| } | ||||
| 
 | ||||
| export default TabMeLists | ||||
| export default TabMeListList | ||||
| @@ -9,9 +9,9 @@ import { StyleConstants } from '@utils/styles/constants' | ||||
| import { useTheme } from '@utils/styles/ThemeManager' | ||||
| import React, { useEffect } from 'react' | ||||
| import { useTranslation } from 'react-i18next' | ||||
| import { Alert } from 'react-native' | ||||
| import { useQueryClient } from 'react-query' | ||||
| import * as DropdownMenu from 'zeego/dropdown-menu' | ||||
| import { menuListAccounts, menuListDelete, menuListEdit } from './menus' | ||||
| 
 | ||||
| const TabMeList: React.FC<TabMeStackScreenProps<'Tab-Me-List'>> = ({ | ||||
|   navigation, | ||||
| @@ -40,6 +40,10 @@ const TabMeList: React.FC<TabMeStackScreenProps<'Tab-Me-List'>> = ({ | ||||
|   }) | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     const listAccounts = menuListAccounts({ params }) | ||||
|     const listEdit = menuListEdit({ params, key }) | ||||
|     const listDelete = menuListDelete({ params, mutation }) | ||||
| 
 | ||||
|     navigation.setOptions({ | ||||
|       headerRight: () => ( | ||||
|         <DropdownMenu.Root> | ||||
| @@ -52,41 +56,24 @@ const TabMeList: React.FC<TabMeStackScreenProps<'Tab-Me-List'>> = ({ | ||||
|           </DropdownMenu.Trigger> | ||||
| 
 | ||||
|           <DropdownMenu.Content> | ||||
|             <DropdownMenu.Item | ||||
|               key='list-edit' | ||||
|               onSelect={() => | ||||
|                 navigation.navigate('Tab-Me-List-Edit', { | ||||
|                   type: 'edit', | ||||
|                   payload: params, | ||||
|                   key | ||||
|                 }) | ||||
|               } | ||||
|             > | ||||
|               <DropdownMenu.ItemTitle children={t('me.stacks.listEdit.name')} /> | ||||
|               <DropdownMenu.ItemIcon iosIconName='square.and.pencil' /> | ||||
|             </DropdownMenu.Item> | ||||
|             <DropdownMenu.Group> | ||||
|               <DropdownMenu.Item key={listAccounts.key} onSelect={listAccounts.onSelect}> | ||||
|                 <DropdownMenu.ItemTitle children={listAccounts.title} /> | ||||
|                 <DropdownMenu.ItemIcon iosIconName={listAccounts.icon} /> | ||||
|               </DropdownMenu.Item> | ||||
|             </DropdownMenu.Group> | ||||
| 
 | ||||
|             <DropdownMenu.Item | ||||
|               key='list-delete' | ||||
|               destructive | ||||
|               onSelect={() => | ||||
|                 Alert.alert( | ||||
|                   t('me.listDelete.confirm.title', { list: params.title.slice(0, 6) }), | ||||
|                   t('me.listDelete.confirm.message'), | ||||
|                   [ | ||||
|                     { | ||||
|                       text: t('common:buttons.delete'), | ||||
|                       style: 'destructive', | ||||
|                       onPress: () => mutation.mutate({ type: 'delete', payload: params }) | ||||
|                     }, | ||||
|                     { text: t('common:buttons.cancel') } | ||||
|                   ] | ||||
|                 ) | ||||
|               } | ||||
|             > | ||||
|               <DropdownMenu.ItemTitle children={t('me.listDelete.heading')} /> | ||||
|               <DropdownMenu.ItemIcon iosIconName='trash' /> | ||||
|             </DropdownMenu.Item> | ||||
|             <DropdownMenu.Group> | ||||
|               <DropdownMenu.Item key={listEdit.key} onSelect={listEdit.onSelect}> | ||||
|                 <DropdownMenu.ItemTitle children={listEdit.title} /> | ||||
|                 <DropdownMenu.ItemIcon iosIconName={listEdit.icon} /> | ||||
|               </DropdownMenu.Item> | ||||
| 
 | ||||
|               <DropdownMenu.Item key={listDelete.key} destructive onSelect={listDelete.onSelect}> | ||||
|                 <DropdownMenu.ItemTitle children={listDelete.title} /> | ||||
|                 <DropdownMenu.ItemIcon iosIconName={listDelete.icon} /> | ||||
|               </DropdownMenu.Item> | ||||
|             </DropdownMenu.Group> | ||||
|           </DropdownMenu.Content> | ||||
|         </DropdownMenu.Root> | ||||
|       ) | ||||
							
								
								
									
										48
									
								
								src/screens/Tabs/Me/List/menus.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/screens/Tabs/Me/List/menus.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| import navigationRef from '@helpers/navigationRef' | ||||
| import i18next from 'i18next' | ||||
| import { Alert } from 'react-native' | ||||
| import { UseMutationResult } from 'react-query' | ||||
|  | ||||
| export const menuListAccounts = ({ params }: { params: Mastodon.List }) => ({ | ||||
|   key: 'list-accounts', | ||||
|   onSelect: () => navigationRef.navigate<any>('Tab-Me-List-Accounts', params), | ||||
|   title: i18next.t('screenTabs:me.listAccounts.heading'), | ||||
|   icon: 'person.crop.circle.fill.badge.checkmark' | ||||
| }) | ||||
|  | ||||
| export const menuListEdit = ({ params, key }: { params: Mastodon.List; key: string }) => ({ | ||||
|   key: 'list-edit', | ||||
|   onSelect: () => | ||||
|     navigationRef.navigate<any>('Tab-Me-List-Edit', { | ||||
|       type: 'edit', | ||||
|       payload: params, | ||||
|       key | ||||
|     }), | ||||
|   title: i18next.t('screenTabs:me.listEdit.heading'), | ||||
|   icon: 'square.and.pencil' | ||||
| }) | ||||
|  | ||||
| export const menuListDelete = ({ | ||||
|   params, | ||||
|   mutation | ||||
| }: { | ||||
|   params: Mastodon.List | ||||
|   mutation: UseMutationResult<any, any, unknown, unknown> | ||||
| }) => ({ | ||||
|   key: 'list-delete', | ||||
|   onSelect: () => | ||||
|     Alert.alert( | ||||
|       i18next.t('screenTabs:me.listDelete.confirm.title', { list: params.title.slice(0, 6) }), | ||||
|       i18next.t('screenTabs:me.listDelete.confirm.message'), | ||||
|       [ | ||||
|         { | ||||
|           text: i18next.t('common:buttons.delete'), | ||||
|           style: 'destructive', | ||||
|           onPress: () => mutation.mutate({ type: 'delete', payload: params }) | ||||
|         }, | ||||
|         { text: i18next.t('common:buttons.cancel') } | ||||
|       ] | ||||
|     ), | ||||
|   title: i18next.t('screenTabs:me.listDelete.heading'), | ||||
|   icon: 'trash' | ||||
| }) | ||||
| @@ -85,7 +85,7 @@ const Collections: React.FC = () => { | ||||
|           iconFront='List' | ||||
|           iconBack='ChevronRight' | ||||
|           title={t('me.stacks.lists.name')} | ||||
|           onPress={() => navigation.navigate('Tab-Me-Lists')} | ||||
|           onPress={() => navigation.navigate('Tab-Me-List-List')} | ||||
|         /> | ||||
|       ) : null} | ||||
|       {mePage.announcements.shown ? ( | ||||
|   | ||||
| @@ -139,6 +139,7 @@ export type TabMeStackParamList = { | ||||
|   'Tab-Me-Conversations': undefined | ||||
|   'Tab-Me-Favourites': undefined | ||||
|   'Tab-Me-List': Mastodon.List | ||||
|   'Tab-Me-List-Accounts': Omit<Mastodon.List, 'replies_policy'> | ||||
|   'Tab-Me-List-Edit': | ||||
|     | { | ||||
|         type: 'add' | ||||
| @@ -148,7 +149,7 @@ export type TabMeStackParamList = { | ||||
|         payload: Mastodon.List | ||||
|         key: string // To update title after successful mutation | ||||
|       } | ||||
|   'Tab-Me-Lists': undefined | ||||
|   'Tab-Me-List-List': undefined | ||||
|   'Tab-Me-Profile': undefined | ||||
|   'Tab-Me-Push': undefined | ||||
|   'Tab-Me-Settings': undefined | ||||
|   | ||||
| @@ -1,6 +1,14 @@ | ||||
| import apiInstance from '@api/instance' | ||||
| import apiInstance, { InstanceResponse } from '@api/instance' | ||||
| import { AxiosError } from 'axios' | ||||
| import { useMutation, UseMutationOptions, useQuery, UseQueryOptions } from 'react-query' | ||||
| import { | ||||
|   QueryFunctionContext, | ||||
|   useInfiniteQuery, | ||||
|   UseInfiniteQueryOptions, | ||||
|   useMutation, | ||||
|   UseMutationOptions, | ||||
|   useQuery, | ||||
|   UseQueryOptions | ||||
| } from 'react-query' | ||||
|  | ||||
| export type QueryKeyLists = ['Lists'] | ||||
|  | ||||
| @@ -53,10 +61,10 @@ const mutationFunction = async (params: MutationVarsLists) => { | ||||
|         body | ||||
|       }).then(res => res.body) | ||||
|     case 'delete': | ||||
|       return apiInstance({ | ||||
|       return apiInstance<{}>({ | ||||
|         method: 'delete', | ||||
|         url: `lists/${params.payload.id}` | ||||
|       }) | ||||
|       }).then(res => res.body) | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -66,4 +74,54 @@ const useListsMutation = ( | ||||
|   return useMutation(mutationFunction, options) | ||||
| } | ||||
|  | ||||
| export { useListsQuery, useListsMutation } | ||||
| /* ----- */ | ||||
|  | ||||
| export type QueryKeyListAccounts = ['ListAccounts', { id: Mastodon.List['id'] }] | ||||
|  | ||||
| const accountsQueryFunction = async ({ | ||||
|   queryKey, | ||||
|   pageParam | ||||
| }: QueryFunctionContext<QueryKeyListAccounts>) => { | ||||
|   const { id } = queryKey[1] | ||||
|  | ||||
|   return await apiInstance<Mastodon.Account[]>({ | ||||
|     method: 'get', | ||||
|     url: `lists/${id}/accounts`, | ||||
|     params: { ...pageParam, limit: 40 } | ||||
|   }) | ||||
| } | ||||
|  | ||||
| const useListAccountsQuery = ({ | ||||
|   options, | ||||
|   ...queryKeyParams | ||||
| }: QueryKeyListAccounts[1] & { | ||||
|   options?: UseInfiniteQueryOptions<InstanceResponse<Mastodon.Account[]>, AxiosError> | ||||
| }) => { | ||||
|   const queryKey: QueryKeyListAccounts = ['ListAccounts', queryKeyParams] | ||||
|   return useInfiniteQuery(queryKey, accountsQueryFunction, options) | ||||
| } | ||||
|  | ||||
| type AccountsMutationVarsLists = { | ||||
|   type: 'add' | 'delete' | ||||
|   payload: Pick<Mastodon.List, 'id'> & { accounts: Mastodon.Account['id'][] } | ||||
| } | ||||
|  | ||||
| const accountsMutationFunction = async (params: AccountsMutationVarsLists) => { | ||||
|   const body = new FormData() | ||||
|   for (const account of params.payload.accounts) { | ||||
|     body.append('account_ids[]', account) | ||||
|   } | ||||
|   return apiInstance<{}>({ | ||||
|     method: params.type === 'add' ? 'post' : 'delete', | ||||
|     url: `lists/${params.payload.id}/accounts`, | ||||
|     body | ||||
|   }).then(res => res.body) | ||||
| } | ||||
|  | ||||
| const useListAccountsMutation = ( | ||||
|   options: UseMutationOptions<Mastodon.List, AxiosError, AccountsMutationVarsLists> | ||||
| ) => { | ||||
|   return useMutation(accountsMutationFunction, options) | ||||
| } | ||||
|  | ||||
| export { useListsQuery, useListsMutation, useListAccountsQuery, useListAccountsMutation } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user