mirror of
				https://github.com/tooot-app/app
				synced 2025-06-05 22:19:13 +02:00 
			
		
		
		
	Ready for push feature
This commit is contained in:
		| @@ -8,7 +8,7 @@ ensure_env_vars( | ||||
| VERSIONS = read_json( json_path: "./package.json" )[:versions] | ||||
| ENVIRONMENT = ENV["TOOOT_ENVIRONMENT"] | ||||
| VERSION = "#{VERSIONS[:major]}.#{VERSIONS[:minor]}" | ||||
| RELEASE_CHANNEL = "#{VERSIONS[:major]}-#{ENVIRONMENT}" | ||||
| RELEASE_CHANNEL = "#{VERSIONS[:major]}-#{VERSIONS[:minor]}-#{ENVIRONMENT}" | ||||
| BUILD_NUMBER = ENV["GITHUB_RUN_NUMBER"] | ||||
| GITHUB_REPO = "tooot-app/app" | ||||
| case ENVIRONMENT | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| { | ||||
|   "name": "tooot", | ||||
|   "versions": { | ||||
|     "native": "210201", | ||||
|     "native": "210304", | ||||
|     "major": 0, | ||||
|     "minor": 5, | ||||
|     "minor": 6, | ||||
|     "patch": 0, | ||||
|     "expo": "40.0.0" | ||||
|   }, | ||||
|   | ||||
| @@ -8,10 +8,12 @@ import ScreenAnnouncements from '@screens/Announcements' | ||||
| import ScreenCompose from '@screens/Compose' | ||||
| import ScreenImagesViewer from '@screens/ImagesViewer' | ||||
| import ScreenTabs from '@screens/Tabs' | ||||
| import pushUseConnect from '@utils/push/useConnect' | ||||
| import pushUseReceive from '@utils/push/useReceive' | ||||
| import pushUseRespond from '@utils/push/useRespond' | ||||
| import { updatePreviousTab } from '@utils/slices/contextsSlice' | ||||
| import { connectInstancesPush } from '@utils/slices/instances/connectPush' | ||||
| import { updateAccountPreferences } from '@utils/slices/instances/updateAccountPreferences' | ||||
| import { getInstanceActive } from '@utils/slices/instancesSlice' | ||||
| import { getInstanceActive, getInstances } from '@utils/slices/instancesSlice' | ||||
| import { useTheme } from '@utils/styles/ThemeManager' | ||||
| import { themes } from '@utils/styles/themes' | ||||
| import * as Analytics from 'expo-firebase-analytics' | ||||
| @@ -20,6 +22,7 @@ import React, { createRef, useCallback, useEffect, useRef } from 'react' | ||||
| import { useTranslation } from 'react-i18next' | ||||
| import { Alert, Platform, StatusBar } from 'react-native' | ||||
| import { createNativeStackNavigator } from 'react-native-screens/native-stack' | ||||
| import { useQueryClient } from 'react-query' | ||||
| import { useDispatch, useSelector } from 'react-redux' | ||||
| import * as Sentry from 'sentry-expo' | ||||
|  | ||||
| @@ -56,10 +59,15 @@ const Screens: React.FC<Props> = ({ localCorrupt }) => { | ||||
|   //   } | ||||
|   // }, [isConnected, firstRender]) | ||||
|  | ||||
|   // Update Expo Token to server | ||||
|   useEffect(() => { | ||||
|     dispatch(connectInstancesPush({ mode, t })) | ||||
|   }, []) | ||||
|   // Push hooks | ||||
|   const instances = useSelector( | ||||
|     getInstances, | ||||
|     (prev, next) => prev.length === next.length | ||||
|   ) | ||||
|   const queryClient = useQueryClient() | ||||
|   pushUseConnect({ navigationRef, mode, t, instances, dispatch }) | ||||
|   pushUseReceive({ navigationRef, queryClient, instances }) | ||||
|   pushUseRespond({ navigationRef, queryClient, instances, dispatch }) | ||||
|  | ||||
|   // Prevent screenshot alert | ||||
|   useEffect(() => { | ||||
|   | ||||
| @@ -56,8 +56,7 @@ const displayMessage = ({ | ||||
|     onPress, | ||||
|     ...(mode && | ||||
|       type && { | ||||
|         renderFlashMessageIcon: props => { | ||||
|           console.log(props) | ||||
|         renderFlashMessageIcon: () => { | ||||
|           return ( | ||||
|             <Icon | ||||
|               name={iconMapping[type]} | ||||
| @@ -92,7 +91,7 @@ const Message = React.memo( | ||||
|           ...StyleConstants.FontStyle.M, | ||||
|           fontWeight: StyleConstants.Font.Weight.Bold | ||||
|         }} | ||||
|         textStyle={{ color: theme.primary, ...StyleConstants.FontStyle.M }} | ||||
|         textStyle={{ color: theme.primary, ...StyleConstants.FontStyle.S }} | ||||
|         // @ts-ignore | ||||
|         textProps={{ numberOfLines: 2 }} | ||||
|       /> | ||||
|   | ||||
| @@ -209,7 +209,6 @@ const TimelineActions: React.FC<Props> = ({ | ||||
|               : iconColorAction(status.reblogged) | ||||
|           } | ||||
|           size={StyleConstants.Font.Size.L} | ||||
|           strokeWidth={status.reblogged ? 3 : undefined} | ||||
|         /> | ||||
|         {status.reblogs_count > 0 && ( | ||||
|           <Text | ||||
| @@ -233,7 +232,6 @@ const TimelineActions: React.FC<Props> = ({ | ||||
|           name='Heart' | ||||
|           color={iconColorAction(status.favourited)} | ||||
|           size={StyleConstants.Font.Size.L} | ||||
|           strokeWidth={status.favourited ? 3 : undefined} | ||||
|         /> | ||||
|         {status.favourites_count > 0 && ( | ||||
|           <Text | ||||
| @@ -257,7 +255,6 @@ const TimelineActions: React.FC<Props> = ({ | ||||
|         name='Bookmark' | ||||
|         color={iconColorAction(status.bookmarked)} | ||||
|         size={StyleConstants.Font.Size.L} | ||||
|         strokeWidth={status.bookmarked ? 3 : undefined} | ||||
|       /> | ||||
|     ), | ||||
|     [status.bookmarked] | ||||
|   | ||||
| @@ -1,6 +1,10 @@ | ||||
| export default { | ||||
|   heading: 'Push Notification', | ||||
|   content: { | ||||
|     enable: { | ||||
|       direct: 'Enable push notification', | ||||
|       settings: 'Enable in settings' | ||||
|     }, | ||||
|     global: { | ||||
|       heading: 'Enable push notification', | ||||
|       description: "Messages are routed through tooot's server" | ||||
| @@ -10,6 +14,9 @@ export default { | ||||
|       description: | ||||
|         "Messages routed through tooot's server are encrypted, but you can choose to decode the message on the server. Our server source code is open source, and no log policy." | ||||
|     }, | ||||
|     default: { | ||||
|       heading: 'Default' // Android notification channel name only | ||||
|     }, | ||||
|     follow: { | ||||
|       heading: 'New follower' | ||||
|     }, | ||||
| @@ -26,5 +33,9 @@ export default { | ||||
|       heading: 'Poll updates' | ||||
|     }, | ||||
|     howitworks: 'Learn how routing works' | ||||
|   }, | ||||
|   error: { | ||||
|     message: 'Push service error', | ||||
|     description: 'Please re-enable push notification in settings' | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -35,7 +35,7 @@ export default { | ||||
|     howitworks: '了解通知消息转发如何工作' | ||||
|   }, | ||||
|   error: { | ||||
|     message: '推送服务器错误', | ||||
|     message: '推送服务错误', | ||||
|     description: '请在设置中重新尝试启用推送通知' | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -7,19 +7,19 @@ import { | ||||
| import { NavigatorScreenParams } from '@react-navigation/native' | ||||
| import { StackScreenProps } from '@react-navigation/stack' | ||||
| import { getPreviousTab } from '@utils/slices/contextsSlice' | ||||
| import { getInstanceActive, getInstances } from '@utils/slices/instancesSlice' | ||||
| import { | ||||
|   getInstanceAccount, | ||||
|   getInstanceActive | ||||
| } from '@utils/slices/instancesSlice' | ||||
| import { useTheme } from '@utils/styles/ThemeManager' | ||||
| import React, { useCallback, useMemo } from 'react' | ||||
| import { Platform } from 'react-native' | ||||
| import FastImage from 'react-native-fast-image' | ||||
| import { useQueryClient } from 'react-query' | ||||
| import { useDispatch, useSelector } from 'react-redux' | ||||
| import { useSelector } from 'react-redux' | ||||
| import TabLocal from './Tabs/Local' | ||||
| import TabMe from './Tabs/Me' | ||||
| import TabNotifications from './Tabs/Notifications' | ||||
| import TabPublic from './Tabs/Public' | ||||
| import pushReceive from './Tabs/utils/pushReceive' | ||||
| import pushRespond from './Tabs/utils/pushRespond' | ||||
|  | ||||
| export type ScreenTabsParamList = { | ||||
|   'Tab-Local': NavigatorScreenParams<Nav.TabLocalStackParamList> | ||||
| @@ -40,18 +40,12 @@ const ScreenTabs = React.memo( | ||||
|   ({ navigation }: ScreenTabsProp) => { | ||||
|     const { mode, theme } = useTheme() | ||||
|  | ||||
|     const queryClient = useQueryClient() | ||||
|  | ||||
|     const dispatch = useDispatch() | ||||
|     const instanceActive = useSelector(getInstanceActive) | ||||
|     const instances = useSelector( | ||||
|       getInstances, | ||||
|       (prev, next) => prev.length === next.length | ||||
|     const instanceAccount = useSelector( | ||||
|       getInstanceAccount, | ||||
|       (prev, next) => prev?.avatarStatic === next?.avatarStatic | ||||
|     ) | ||||
|  | ||||
|     pushReceive({ navigation, queryClient, instances }) | ||||
|     pushRespond({ navigation, queryClient, instances, dispatch }) | ||||
|  | ||||
|     const screenOptions = useCallback( | ||||
|       ({ route }): BottomTabNavigationOptions => ({ | ||||
|         tabBarVisible: instanceActive !== -1, | ||||
| @@ -77,7 +71,7 @@ const ScreenTabs = React.memo( | ||||
|               return instanceActive !== -1 ? ( | ||||
|                 <FastImage | ||||
|                   source={{ | ||||
|                     uri: instances[instanceActive].account.avatarStatic | ||||
|                     uri: instanceAccount?.avatarStatic | ||||
|                   }} | ||||
|                   style={{ | ||||
|                     width: size, | ||||
| @@ -99,7 +93,7 @@ const ScreenTabs = React.memo( | ||||
|           } | ||||
|         } | ||||
|       }), | ||||
|       [instances, instanceActive] | ||||
|       [instanceAccount, instanceActive] | ||||
|     ) | ||||
|     const tabBarOptions = useMemo( | ||||
|       () => ({ | ||||
|   | ||||
| @@ -1,31 +0,0 @@ | ||||
| import apiInstance from '@api/instance' | ||||
| import { StackNavigationProp } from '@react-navigation/stack' | ||||
|  | ||||
| const pushNavigate = ( | ||||
|   navigation: StackNavigationProp<Nav.RootStackParamList, 'Screen-Tabs'>, | ||||
|   id?: Mastodon.Notification['id'] | ||||
| ) => { | ||||
|   // @ts-ignore | ||||
|   navigation.navigate('Tab-Notifications', { | ||||
|     screen: 'Tab-Notifications-Root' | ||||
|   }) | ||||
|  | ||||
|   if (!id) { | ||||
|     return | ||||
|   } | ||||
|  | ||||
|   apiInstance<Mastodon.Notification>({ | ||||
|     method: 'get', | ||||
|     url: `notifications/${id}` | ||||
|   }).then(({ body }) => { | ||||
|     if (body.status) { | ||||
|       // @ts-ignore | ||||
|       navigation.navigate('Tab-Notifications', { | ||||
|         screen: 'Tab-Shared-Toot', | ||||
|         params: { toot: body.status } | ||||
|       }) | ||||
|     } | ||||
|   }) | ||||
| } | ||||
|  | ||||
| export default pushNavigate | ||||
							
								
								
									
										35
									
								
								src/store.ts
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								src/store.ts
									
									
									
									
									
								
							| @@ -5,10 +5,11 @@ import { | ||||
|   configureStore, | ||||
|   getDefaultMiddleware | ||||
| } from '@reduxjs/toolkit' | ||||
| import { InstancesV3 } from '@utils/migrations/instances/v3' | ||||
| import contextsSlice from '@utils/slices/contextsSlice' | ||||
| import instancesSlice from '@utils/slices/instancesSlice' | ||||
| import settingsSlice from '@utils/slices/settingsSlice' | ||||
| import { persistReducer, persistStore } from 'redux-persist' | ||||
| import { createMigrate, persistReducer, persistStore } from 'redux-persist' | ||||
|  | ||||
| const secureStorage = createSecureStore() | ||||
|  | ||||
| @@ -20,10 +21,40 @@ const contextsPersistConfig = { | ||||
|   storage: AsyncStorage | ||||
| } | ||||
|  | ||||
| const instancesMigration = { | ||||
|   4: (state: InstancesV3) => { | ||||
|     return { | ||||
|       instances: state.local.instances.map((instance, index) => { | ||||
|         // @ts-ignore | ||||
|         delete instance.notification | ||||
|         return { | ||||
|           ...instance, | ||||
|           active: state.local.activeIndex === index, | ||||
|           push: { | ||||
|             global: { loading: false, value: false }, | ||||
|             decode: { loading: false, value: false }, | ||||
|             alerts: { | ||||
|               follow: { loading: false, value: true }, | ||||
|               favourite: { loading: false, value: true }, | ||||
|               reblog: { loading: false, value: true }, | ||||
|               mention: { loading: false, value: true }, | ||||
|               poll: { loading: false, value: true } | ||||
|             }, | ||||
|             keys: undefined | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| const instancesPersistConfig = { | ||||
|   key: 'instances', | ||||
|   prefix, | ||||
|   storage: secureStorage | ||||
|   storage: secureStorage, | ||||
|   version: 4, | ||||
|   // @ts-ignore | ||||
|   migrate: createMigrate(instancesMigration) | ||||
| } | ||||
|  | ||||
| const settingsPersistConfig = { | ||||
|   | ||||
							
								
								
									
										33
									
								
								src/utils/migrations/instances/v3.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/utils/migrations/instances/v3.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| type InstanceLocal = { | ||||
|   appData: { | ||||
|     clientId: string | ||||
|     clientSecret: string | ||||
|   } | ||||
|   url: string | ||||
|   token: string | ||||
|   uri: Mastodon.Instance['uri'] | ||||
|   urls: Mastodon.Instance['urls'] | ||||
|   max_toot_chars: number | ||||
|   account: { | ||||
|     id: Mastodon.Account['id'] | ||||
|     acct: Mastodon.Account['acct'] | ||||
|     avatarStatic: Mastodon.Account['avatar_static'] | ||||
|     preferences: Mastodon.Preferences | ||||
|   } | ||||
|   notification: { | ||||
|     readTime?: Mastodon.Notification['created_at'] | ||||
|     latestTime?: Mastodon.Notification['created_at'] | ||||
|   } | ||||
|   drafts: any[] | ||||
| } | ||||
|  | ||||
| export type InstancesV3 = { | ||||
|   local: { | ||||
|     activeIndex: number | null | ||||
|     instances: InstanceLocal[] | ||||
|   } | ||||
|  | ||||
|   remote: { | ||||
|     url: string | ||||
|   } | ||||
| } | ||||
							
								
								
									
										91
									
								
								src/utils/push/useConnect.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								src/utils/push/useConnect.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | ||||
| import apiGeneral from '@api/general' | ||||
| import { displayMessage } from '@components/Message' | ||||
| import { NavigationContainerRef } from '@react-navigation/native' | ||||
| import { Dispatch } from '@reduxjs/toolkit' | ||||
| import { | ||||
|   disableAllPushes, | ||||
|   Instance, | ||||
|   PUSH_SERVER | ||||
| } from '@utils/slices/instancesSlice' | ||||
| import * as Notifications from 'expo-notifications' | ||||
| import { useEffect } from 'react' | ||||
| import { TFunction } from 'react-i18next' | ||||
|  | ||||
| export interface Params { | ||||
|   navigationRef: React.RefObject<NavigationContainerRef> | ||||
|   mode: 'light' | 'dark' | ||||
|   t: TFunction<'common'> | ||||
|   instances: Instance[] | ||||
|   dispatch: Dispatch<any> | ||||
| } | ||||
|  | ||||
| const pushUseConnect = ({ | ||||
|   navigationRef, | ||||
|   mode, | ||||
|   t, | ||||
|   instances, | ||||
|   dispatch | ||||
| }: Params) => { | ||||
|   return useEffect(() => { | ||||
|     const connect = async () => { | ||||
|       const expoToken = ( | ||||
|         await Notifications.getExpoPushTokenAsync({ | ||||
|           experienceId: '@xmflsct/tooot' | ||||
|         }) | ||||
|       ).data | ||||
|  | ||||
|       apiGeneral({ | ||||
|         method: 'post', | ||||
|         domain: PUSH_SERVER, | ||||
|         url: 'v1/connect', | ||||
|         body: { | ||||
|           expoToken | ||||
|         } | ||||
|       }).catch(() => { | ||||
|         displayMessage({ | ||||
|           mode, | ||||
|           type: 'error', | ||||
|           duration: 'long', | ||||
|           message: t('meSettingsPush:error.message'), | ||||
|           description: t('meSettingsPush:error.description'), | ||||
|           onPress: () => { | ||||
|             navigationRef.current?.navigate('Screen-Tabs', { | ||||
|               screen: 'Tab-Me', | ||||
|               params: { | ||||
|                 screen: 'Tab-Me-Root' | ||||
|               } | ||||
|             }) | ||||
|             navigationRef.current?.navigate('Screen-Tabs', { | ||||
|               screen: 'Tab-Me', | ||||
|               params: { | ||||
|                 screen: 'Tab-Me-Settings' | ||||
|               } | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|  | ||||
|         dispatch(disableAllPushes()) | ||||
|  | ||||
|         instances.forEach(instance => { | ||||
|           if (instance.push.global.value) { | ||||
|             apiGeneral<{}>({ | ||||
|               method: 'delete', | ||||
|               domain: instance.url, | ||||
|               url: 'api/v1/push/subscription', | ||||
|               headers: { | ||||
|                 Authorization: `Bearer ${instance.token}` | ||||
|               } | ||||
|             }).catch(() => console.log('error!!!')) | ||||
|           } | ||||
|         }) | ||||
|       }) | ||||
|     } | ||||
|  | ||||
|     const pushEnabled = instances.filter(instance => instance.push.global.value) | ||||
|     if (pushEnabled.length) { | ||||
|       connect() | ||||
|     } | ||||
|   }, [instances]) | ||||
| } | ||||
|  | ||||
| export default pushUseConnect | ||||
							
								
								
									
										35
									
								
								src/utils/push/useNavigate.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/utils/push/useNavigate.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| import apiInstance from '@api/instance' | ||||
| import { NavigationContainerRef } from '@react-navigation/native' | ||||
|  | ||||
| const pushUseNavigate = ( | ||||
|   navigationRef: React.RefObject<NavigationContainerRef>, | ||||
|   id?: Mastodon.Notification['id'] | ||||
| ) => { | ||||
|   navigationRef.current?.navigate('Screen-Tabs', { | ||||
|     screen: 'Tab-Notifications', | ||||
|     params: { | ||||
|       screen: 'Tab-Notifications-Root' | ||||
|     } | ||||
|   }) | ||||
|  | ||||
|   if (!id) { | ||||
|     return | ||||
|   } | ||||
|  | ||||
|   apiInstance<Mastodon.Notification>({ | ||||
|     method: 'get', | ||||
|     url: `notifications/${id}` | ||||
|   }).then(({ body }) => { | ||||
|     if (body.status) { | ||||
|       navigationRef.current?.navigate('Screen-Tabs', { | ||||
|         screen: 'Tab-Notifications', | ||||
|         params: { | ||||
|           screen: 'Tab-Shared-Toot', | ||||
|           params: { toot: body.status } | ||||
|         } | ||||
|       }) | ||||
|     } | ||||
|   }) | ||||
| } | ||||
|  | ||||
| export default pushUseNavigate | ||||
| @@ -1,5 +1,5 @@ | ||||
| import { displayMessage } from '@components/Message' | ||||
| import { StackNavigationProp } from '@react-navigation/stack' | ||||
| import { NavigationContainerRef } from '@react-navigation/native' | ||||
| import { QueryKeyTimeline } from '@utils/queryHooks/timeline' | ||||
| import { Instance, updateInstanceActive } from '@utils/slices/instancesSlice' | ||||
| import * as Notifications from 'expo-notifications' | ||||
| @@ -7,15 +7,15 @@ import { findIndex } from 'lodash' | ||||
| import { useEffect } from 'react' | ||||
| import { QueryClient } from 'react-query' | ||||
| import { useDispatch } from 'react-redux' | ||||
| import pushNavigate from './pushNavigate' | ||||
| import pushUseNavigate from './useNavigate' | ||||
| 
 | ||||
| export interface Params { | ||||
|   navigation: StackNavigationProp<Nav.RootStackParamList, 'Screen-Tabs'> | ||||
|   navigationRef: React.RefObject<NavigationContainerRef> | ||||
|   queryClient: QueryClient | ||||
|   instances: Instance[] | ||||
| } | ||||
| 
 | ||||
| const pushReceive = ({ navigation, queryClient, instances }: Params) => { | ||||
| const pushUseReceive = ({ navigationRef, queryClient, instances }: Params) => { | ||||
|   const dispatch = useDispatch() | ||||
| 
 | ||||
|   return useEffect(() => { | ||||
| @@ -46,7 +46,7 @@ const pushReceive = ({ navigation, queryClient, instances }: Params) => { | ||||
|             if (notificationIndex !== -1) { | ||||
|               dispatch(updateInstanceActive(instances[notificationIndex])) | ||||
|             } | ||||
|             pushNavigate(navigation, payloadData.notification_id) | ||||
|             pushUseNavigate(navigationRef, payloadData.notification_id) | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
| @@ -55,4 +55,4 @@ const pushReceive = ({ navigation, queryClient, instances }: Params) => { | ||||
|   }, [instances]) | ||||
| } | ||||
| 
 | ||||
| export default pushReceive | ||||
| export default pushUseReceive | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { StackNavigationProp } from '@react-navigation/stack' | ||||
| import { NavigationContainerRef } from '@react-navigation/native' | ||||
| import { Dispatch } from '@reduxjs/toolkit' | ||||
| import { QueryKeyTimeline } from '@utils/queryHooks/timeline' | ||||
| import { Instance, updateInstanceActive } from '@utils/slices/instancesSlice' | ||||
| @@ -6,17 +6,17 @@ import * as Notifications from 'expo-notifications' | ||||
| import { findIndex } from 'lodash' | ||||
| import { useEffect } from 'react' | ||||
| import { QueryClient } from 'react-query' | ||||
| import pushNavigate from './pushNavigate' | ||||
| import pushUseNavigate from './useNavigate' | ||||
| 
 | ||||
| export interface Params { | ||||
|   navigation: StackNavigationProp<Nav.RootStackParamList, 'Screen-Tabs'> | ||||
|   navigationRef: React.RefObject<NavigationContainerRef> | ||||
|   queryClient: QueryClient | ||||
|   instances: Instance[] | ||||
|   dispatch: Dispatch<any> | ||||
| } | ||||
| 
 | ||||
| const pushRespond = ({ | ||||
|   navigation, | ||||
| const pushUseRespond = ({ | ||||
|   navigationRef, | ||||
|   queryClient, | ||||
|   instances, | ||||
|   dispatch | ||||
| @@ -44,11 +44,11 @@ const pushRespond = ({ | ||||
|         if (notificationIndex !== -1) { | ||||
|           dispatch(updateInstanceActive(instances[notificationIndex])) | ||||
|         } | ||||
|         pushNavigate(navigation, payloadData.notification_id) | ||||
|         pushUseNavigate(navigationRef, payloadData.notification_id) | ||||
|       } | ||||
|     ) | ||||
|     return () => subscription.remove() | ||||
|   }, [instances]) | ||||
| } | ||||
| 
 | ||||
| export default pushRespond | ||||
| export default pushUseRespond | ||||
| @@ -1,38 +0,0 @@ | ||||
| import apiGeneral from '@api/general' | ||||
| import { createAsyncThunk } from '@reduxjs/toolkit' | ||||
| import { RootState } from '@root/store' | ||||
| import * as Notifications from 'expo-notifications' | ||||
| import { TFunction } from 'react-i18next' | ||||
| import { PUSH_SERVER } from '../instancesSlice' | ||||
|  | ||||
| export const connectInstancesPush = createAsyncThunk( | ||||
|   'instances/connectPush', | ||||
|   async ( | ||||
|     { mode, t }: { mode: 'light' | 'dark'; t: TFunction<'common'> }, | ||||
|     { getState } | ||||
|   ): Promise<any> => { | ||||
|     const state = getState() as RootState | ||||
|     const pushEnabled = state.instances.instances.filter( | ||||
|       instance => instance.push.global.value | ||||
|     ) | ||||
|  | ||||
|     if (pushEnabled.length) { | ||||
|       const expoToken = ( | ||||
|         await Notifications.getExpoPushTokenAsync({ | ||||
|           experienceId: '@xmflsct/tooot' | ||||
|         }) | ||||
|       ).data | ||||
|  | ||||
|       return apiGeneral({ | ||||
|         method: 'post', | ||||
|         domain: PUSH_SERVER, | ||||
|         url: 'v1/connect', | ||||
|         body: { | ||||
|           expoToken | ||||
|         } | ||||
|       }) | ||||
|     } else { | ||||
|       return Promise.resolve() | ||||
|     } | ||||
|   } | ||||
| ) | ||||
| @@ -1,11 +1,9 @@ | ||||
| import analytics from '@components/analytics' | ||||
| import { displayMessage } from '@components/Message' | ||||
| import { createSlice, PayloadAction } from '@reduxjs/toolkit' | ||||
| import { RootState } from '@root/store' | ||||
| import { ComposeStateDraft } from '@screens/Compose/utils/types' | ||||
| import { findIndex } from 'lodash' | ||||
| import addInstance from './instances/add' | ||||
| import { connectInstancesPush } from './instances/connectPush' | ||||
| import removeInstance from './instances/remove' | ||||
| import { updateAccountPreferences } from './instances/updateAccountPreferences' | ||||
| import { updateInstancePush } from './instances/updatePush' | ||||
| @@ -150,6 +148,13 @@ const instancesSlice = createSlice({ | ||||
|       instances[activeIndex].drafts = instances[activeIndex].drafts?.filter( | ||||
|         draft => draft.timestamp !== action.payload | ||||
|       ) | ||||
|     }, | ||||
|     disableAllPushes: ({ instances }) => { | ||||
|       instances = instances.map(instance => { | ||||
|         let newInstance = instance | ||||
|         newInstance.push.global.value = false | ||||
|         return newInstance | ||||
|       }) | ||||
|     } | ||||
|   }, | ||||
|   extraReducers: builder => { | ||||
| @@ -266,22 +271,6 @@ const instancesSlice = createSlice({ | ||||
|           action.meta.arg.changed | ||||
|         ].loading = true | ||||
|       }) | ||||
|  | ||||
|       // If Expo token does not exist on the server, disable all existing ones | ||||
|       .addCase(connectInstancesPush.rejected, (state, action) => { | ||||
|         state.instances = state.instances.map(instance => { | ||||
|           let newInstance = instance | ||||
|           newInstance.push.global.value = false | ||||
|           displayMessage({ | ||||
|             mode: action.meta.arg.mode, | ||||
|             type: 'error', | ||||
|             autoHide: false, | ||||
|             message: action.meta.arg.t('meSettingsPush:error.message'), | ||||
|             description: action.meta.arg.t('meSettingsPush:error.description') | ||||
|           }) | ||||
|           return newInstance | ||||
|         }) | ||||
|       }) | ||||
|   } | ||||
| }) | ||||
|  | ||||
| @@ -337,7 +326,8 @@ export const { | ||||
|   updateInstanceActive, | ||||
|   updateInstanceAccount, | ||||
|   updateInstanceDraft, | ||||
|   removeInstanceDraft | ||||
|   removeInstanceDraft, | ||||
|   disableAllPushes | ||||
| } = instancesSlice.actions | ||||
|  | ||||
| export default instancesSlice.reducer | ||||
|   | ||||
		Reference in New Issue
	
	Block a user