mirror of
https://github.com/tooot-app/app
synced 2025-02-27 09:07:51 +01:00
Removed webhook notification
This commit is contained in:
parent
b20b75f22e
commit
32aaf08574
@ -83,7 +83,6 @@
|
|||||||
"react-query": "^3.12.0",
|
"react-query": "^3.12.0",
|
||||||
"react-redux": "^7.2.2",
|
"react-redux": "^7.2.2",
|
||||||
"react-timeago": "^5.2.0",
|
"react-timeago": "^5.2.0",
|
||||||
"reconnecting-websocket": "^4.4.0",
|
|
||||||
"redux-persist": "^6.0.0",
|
"redux-persist": "^6.0.0",
|
||||||
"rn-placeholder": "^3.0.3",
|
"rn-placeholder": "^3.0.3",
|
||||||
"sentry-expo": "^3.0.4",
|
"sentry-expo": "^3.0.4",
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
|
||||||
import {
|
|
||||||
getInstance,
|
|
||||||
updateInstanceNotification
|
|
||||||
} from '@utils/slices/instancesSlice'
|
|
||||||
import { useEffect, useRef } from 'react'
|
|
||||||
import { useQueryClient } from 'react-query'
|
|
||||||
import { useDispatch, useSelector } from 'react-redux'
|
|
||||||
import ReconnectingWebSocket from 'reconnecting-websocket'
|
|
||||||
|
|
||||||
const useWebsocket = ({
|
|
||||||
stream,
|
|
||||||
event
|
|
||||||
}: {
|
|
||||||
stream: Mastodon.WebSocketStream
|
|
||||||
event: 'update' | 'delete' | 'notification'
|
|
||||||
}) => {
|
|
||||||
const queryClient = useQueryClient()
|
|
||||||
const dispatch = useDispatch()
|
|
||||||
const localInstance = useSelector(
|
|
||||||
getInstance,
|
|
||||||
(prev, next) =>
|
|
||||||
prev?.urls.streaming_api === next?.urls.streaming_api &&
|
|
||||||
prev?.token === next?.token
|
|
||||||
)
|
|
||||||
|
|
||||||
const rws = useRef<ReconnectingWebSocket>()
|
|
||||||
useEffect(() => {
|
|
||||||
if (!localInstance) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rws.current = new ReconnectingWebSocket(
|
|
||||||
`${localInstance.urls.streaming_api}/api/v1/streaming?stream=${stream}&access_token=${localInstance.token}`
|
|
||||||
)
|
|
||||||
rws.current.addEventListener('message', ({ data }) => {
|
|
||||||
const message: Mastodon.WebSocket = JSON.parse(data)
|
|
||||||
if (message.event === event) {
|
|
||||||
switch (message.event) {
|
|
||||||
case 'notification':
|
|
||||||
const payload: Mastodon.Notification = JSON.parse(message.payload)
|
|
||||||
dispatch(
|
|
||||||
updateInstanceNotification({ latestTime: payload.created_at })
|
|
||||||
)
|
|
||||||
const queryKey: QueryKeyTimeline = [
|
|
||||||
'Timeline',
|
|
||||||
{ page: 'Notifications' }
|
|
||||||
]
|
|
||||||
queryClient.invalidateQueries(queryKey)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}, [localInstance?.urls.streaming_api, localInstance?.token])
|
|
||||||
}
|
|
||||||
|
|
||||||
export default useWebsocket
|
|
@ -7,6 +7,7 @@ import FlashMessage, { showMessage } from 'react-native-flash-message'
|
|||||||
import haptics from './haptics'
|
import haptics from './haptics'
|
||||||
|
|
||||||
const displayMessage = ({
|
const displayMessage = ({
|
||||||
|
duration = 'short',
|
||||||
autoHide = true,
|
autoHide = true,
|
||||||
message,
|
message,
|
||||||
description,
|
description,
|
||||||
@ -15,6 +16,7 @@ const displayMessage = ({
|
|||||||
type
|
type
|
||||||
}:
|
}:
|
||||||
| {
|
| {
|
||||||
|
duration?: 'short' | 'long'
|
||||||
autoHide?: boolean
|
autoHide?: boolean
|
||||||
message: string
|
message: string
|
||||||
description?: string
|
description?: string
|
||||||
@ -23,6 +25,7 @@ const displayMessage = ({
|
|||||||
type?: undefined
|
type?: undefined
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
|
duration?: 'short' | 'long'
|
||||||
autoHide?: boolean
|
autoHide?: boolean
|
||||||
message: string
|
message: string
|
||||||
description?: string
|
description?: string
|
||||||
@ -46,6 +49,7 @@ const displayMessage = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
showMessage({
|
showMessage({
|
||||||
|
duration: duration === 'short' ? 1500 : 3000,
|
||||||
autoHide,
|
autoHide,
|
||||||
message,
|
message,
|
||||||
description,
|
description,
|
||||||
@ -80,7 +84,7 @@ const Message = React.memo(
|
|||||||
backgroundColor: theme.background,
|
backgroundColor: theme.background,
|
||||||
shadowColor: theme.primary,
|
shadowColor: theme.primary,
|
||||||
shadowOffset: { width: 0, height: 0 },
|
shadowOffset: { width: 0, height: 0 },
|
||||||
shadowOpacity: mode === 'light' ? 0.16 : 0.32,
|
shadowOpacity: mode === 'light' ? 0.16 : 0.24,
|
||||||
shadowRadius: 4
|
shadowRadius: 4
|
||||||
}}
|
}}
|
||||||
titleStyle={{
|
titleStyle={{
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import ComponentSeparator from '@components/Separator'
|
import ComponentSeparator from '@components/Separator'
|
||||||
import { useScrollToTop } from '@react-navigation/native'
|
import { useScrollToTop } from '@react-navigation/native'
|
||||||
import { QueryKeyTimeline, useTimelineQuery } from '@utils/queryHooks/timeline'
|
import { QueryKeyTimeline, useTimelineQuery } from '@utils/queryHooks/timeline'
|
||||||
|
import { getInstanceActive } from '@utils/slices/instancesSlice'
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import React, { RefObject, useCallback, useRef } from 'react'
|
import React, { RefObject, useCallback, useRef } from 'react'
|
||||||
@ -15,6 +16,7 @@ import Animated, {
|
|||||||
useAnimatedScrollHandler,
|
useAnimatedScrollHandler,
|
||||||
useSharedValue
|
useSharedValue
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
|
import { useSelector } from 'react-redux'
|
||||||
import TimelineEmpty from './Timeline/Empty'
|
import TimelineEmpty from './Timeline/Empty'
|
||||||
import TimelineFooter from './Timeline/Footer'
|
import TimelineFooter from './Timeline/Footer'
|
||||||
import TimelineRefresh, {
|
import TimelineRefresh, {
|
||||||
@ -40,6 +42,9 @@ const Timeline: React.FC<Props> = ({
|
|||||||
disableInfinity = false,
|
disableInfinity = false,
|
||||||
customProps
|
customProps
|
||||||
}) => {
|
}) => {
|
||||||
|
// Switching account update timeline
|
||||||
|
useSelector(getInstanceActive)
|
||||||
|
|
||||||
const { theme } = useTheme()
|
const { theme } = useTheme()
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
@ -1,22 +1,20 @@
|
|||||||
import apiInstance from '@api/instance'
|
import apiInstance from '@api/instance'
|
||||||
import useWebsocket from '@api/websocket'
|
|
||||||
import haptics from '@components/haptics'
|
import haptics from '@components/haptics'
|
||||||
import Icon from '@components/Icon'
|
import Icon from '@components/Icon'
|
||||||
|
import { displayMessage } from '@components/Message'
|
||||||
import {
|
import {
|
||||||
BottomTabNavigationOptions,
|
BottomTabNavigationOptions,
|
||||||
createBottomTabNavigator
|
createBottomTabNavigator
|
||||||
} from '@react-navigation/bottom-tabs'
|
} from '@react-navigation/bottom-tabs'
|
||||||
import { NavigatorScreenParams } from '@react-navigation/native'
|
import { NavigatorScreenParams } from '@react-navigation/native'
|
||||||
import { StackScreenProps } from '@react-navigation/stack'
|
import { StackNavigationProp, StackScreenProps } from '@react-navigation/stack'
|
||||||
import { useTimelineQuery } from '@utils/queryHooks/timeline'
|
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||||
import { getPreviousTab } from '@utils/slices/contextsSlice'
|
import { getPreviousTab } from '@utils/slices/contextsSlice'
|
||||||
import {
|
import {
|
||||||
getInstanceAccount,
|
getInstanceAccount,
|
||||||
getInstanceActive,
|
getInstanceActive,
|
||||||
getInstanceNotification,
|
|
||||||
getInstances,
|
getInstances,
|
||||||
updateInstanceActive,
|
updateInstanceActive
|
||||||
updateInstanceNotification
|
|
||||||
} from '@utils/slices/instancesSlice'
|
} from '@utils/slices/instancesSlice'
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import * as Notifications from 'expo-notifications'
|
import * as Notifications from 'expo-notifications'
|
||||||
@ -24,6 +22,7 @@ import { findIndex } from 'lodash'
|
|||||||
import React, { useCallback, useEffect, useMemo } from 'react'
|
import React, { useCallback, useEffect, useMemo } from 'react'
|
||||||
import { Platform } from 'react-native'
|
import { Platform } from 'react-native'
|
||||||
import FastImage from 'react-native-fast-image'
|
import FastImage from 'react-native-fast-image'
|
||||||
|
import { useQueryClient } from 'react-query'
|
||||||
import { useDispatch, useSelector } from 'react-redux'
|
import { useDispatch, useSelector } from 'react-redux'
|
||||||
import TabLocal from './Tabs/Local'
|
import TabLocal from './Tabs/Local'
|
||||||
import TabMe from './Tabs/Me'
|
import TabMe from './Tabs/Me'
|
||||||
@ -44,7 +43,7 @@ export type ScreenTabsProp = StackScreenProps<
|
|||||||
>
|
>
|
||||||
|
|
||||||
const convertNotificationToToot = (
|
const convertNotificationToToot = (
|
||||||
navigation: any,
|
navigation: StackNavigationProp<Nav.RootStackParamList, 'Screen-Tabs'>,
|
||||||
id: Mastodon.Notification['id']
|
id: Mastodon.Notification['id']
|
||||||
) => {
|
) => {
|
||||||
apiInstance<Mastodon.Notification>({
|
apiInstance<Mastodon.Notification>({
|
||||||
@ -70,11 +69,48 @@ const Tab = createBottomTabNavigator<Nav.ScreenTabsStackParamList>()
|
|||||||
const ScreenTabs = React.memo(
|
const ScreenTabs = React.memo(
|
||||||
({ navigation }: ScreenTabsProp) => {
|
({ navigation }: ScreenTabsProp) => {
|
||||||
// Push notifications
|
// Push notifications
|
||||||
|
const queryClient = useQueryClient()
|
||||||
const instances = useSelector(
|
const instances = useSelector(
|
||||||
getInstances,
|
getInstances,
|
||||||
(prev, next) => prev.length === next.length
|
(prev, next) => prev.length === next.length
|
||||||
)
|
)
|
||||||
const lastNotificationResponse = Notifications.useLastNotificationResponse()
|
useEffect(() => {
|
||||||
|
const subscription = Notifications.addNotificationReceivedListener(
|
||||||
|
notification => {
|
||||||
|
const queryKey: QueryKeyTimeline = [
|
||||||
|
'Timeline',
|
||||||
|
{ page: 'Notifications' }
|
||||||
|
]
|
||||||
|
queryClient.invalidateQueries(queryKey)
|
||||||
|
const payloadData = notification.request.content.data as {
|
||||||
|
notification_id?: string
|
||||||
|
instanceUrl: string
|
||||||
|
accountId: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const notificationIndex = findIndex(
|
||||||
|
instances,
|
||||||
|
instance =>
|
||||||
|
instance.url === payloadData.instanceUrl &&
|
||||||
|
instance.account.id === payloadData.accountId
|
||||||
|
)
|
||||||
|
if (notificationIndex !== -1 && payloadData.notification_id) {
|
||||||
|
displayMessage({
|
||||||
|
duration: 'long',
|
||||||
|
message: notification.request.content.title!,
|
||||||
|
description: notification.request.content.body!,
|
||||||
|
onPress: () =>
|
||||||
|
convertNotificationToToot(
|
||||||
|
navigation,
|
||||||
|
// @ts-ignore Typescript is wrong
|
||||||
|
payloadData.notification_id
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return () => subscription.remove()
|
||||||
|
}, [instances])
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const subscription = Notifications.addNotificationResponseReceivedListener(
|
const subscription = Notifications.addNotificationResponseReceivedListener(
|
||||||
({ notification }) => {
|
({ notification }) => {
|
||||||
@ -93,46 +129,13 @@ const ScreenTabs = React.memo(
|
|||||||
if (notificationIndex !== -1) {
|
if (notificationIndex !== -1) {
|
||||||
dispatch(updateInstanceActive(instances[notificationIndex]))
|
dispatch(updateInstanceActive(instances[notificationIndex]))
|
||||||
}
|
}
|
||||||
if (payloadData?.notification_id) {
|
if (payloadData.notification_id) {
|
||||||
convertNotificationToToot(
|
convertNotificationToToot(navigation, payloadData.notification_id)
|
||||||
navigation,
|
|
||||||
notification.request.content.data.notification_id as string
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return () => subscription.remove()
|
return () => subscription.remove()
|
||||||
|
}, [instances])
|
||||||
// if (
|
|
||||||
// lastNotificationResponse &&
|
|
||||||
// lastNotificationResponse.actionIdentifier ===
|
|
||||||
// Notifications.DEFAULT_ACTION_IDENTIFIER
|
|
||||||
// ) {
|
|
||||||
// const payloadData = lastNotificationResponse.notification.request
|
|
||||||
// .content.data as {
|
|
||||||
// notification_id?: string
|
|
||||||
// instanceUrl: string
|
|
||||||
// accountId: string
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const notificationIndex = findIndex(
|
|
||||||
// instances,
|
|
||||||
// instance =>
|
|
||||||
// instance.url === payloadData.instanceUrl &&
|
|
||||||
// instance.account.id === payloadData.accountId
|
|
||||||
// )
|
|
||||||
// if (notificationIndex !== -1) {
|
|
||||||
// dispatch(updateInstanceActive(instances[notificationIndex]))
|
|
||||||
// }
|
|
||||||
// if (payloadData?.notification_id) {
|
|
||||||
// convertNotificationToToot(
|
|
||||||
// navigation,
|
|
||||||
// lastNotificationResponse.notification.request.content.data
|
|
||||||
// .notification_id as string
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}, [instances, lastNotificationResponse])
|
|
||||||
|
|
||||||
const { mode, theme } = useTheme()
|
const { mode, theme } = useTheme()
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
@ -210,33 +213,6 @@ const ScreenTabs = React.memo(
|
|||||||
)
|
)
|
||||||
const composeComponent = useCallback(() => null, [])
|
const composeComponent = useCallback(() => null, [])
|
||||||
|
|
||||||
// On launch check if there is any unread noficiations
|
|
||||||
useTimelineQuery({
|
|
||||||
page: 'Notifications',
|
|
||||||
options: {
|
|
||||||
enabled: instanceActive !== -1,
|
|
||||||
notifyOnChangeProps: [],
|
|
||||||
select: data => {
|
|
||||||
if (data.pages[0].body.length) {
|
|
||||||
dispatch(
|
|
||||||
updateInstanceNotification({
|
|
||||||
// @ts-ignore
|
|
||||||
latestTime: data.pages[0].body[0].created_at
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
useWebsocket({ stream: 'user', event: 'notification' })
|
|
||||||
const localNotification = useSelector(
|
|
||||||
getInstanceNotification,
|
|
||||||
(prev, next) =>
|
|
||||||
prev?.readTime === next?.readTime &&
|
|
||||||
prev?.latestTime === next?.latestTime
|
|
||||||
)
|
|
||||||
|
|
||||||
const previousTab = useSelector(getPreviousTab, () => true)
|
const previousTab = useSelector(getPreviousTab, () => true)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -252,23 +228,7 @@ const ScreenTabs = React.memo(
|
|||||||
component={composeComponent}
|
component={composeComponent}
|
||||||
listeners={composeListeners}
|
listeners={composeListeners}
|
||||||
/>
|
/>
|
||||||
<Tab.Screen
|
<Tab.Screen name='Tab-Notifications' component={TabNotifications} />
|
||||||
name='Tab-Notifications'
|
|
||||||
component={TabNotifications}
|
|
||||||
options={{
|
|
||||||
tabBarBadge: localNotification?.latestTime
|
|
||||||
? !localNotification.readTime ||
|
|
||||||
new Date(localNotification.readTime) <
|
|
||||||
new Date(localNotification.latestTime)
|
|
||||||
? ''
|
|
||||||
: undefined
|
|
||||||
: undefined,
|
|
||||||
tabBarBadgeStyle: {
|
|
||||||
transform: [{ scale: 0.5 }],
|
|
||||||
backgroundColor: theme.red
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Tab.Screen name='Tab-Me' component={TabMe} />
|
<Tab.Screen name='Tab-Me' component={TabMe} />
|
||||||
</Tab.Navigator>
|
</Tab.Navigator>
|
||||||
)
|
)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import Button from '@components/Button'
|
import Button from '@components/Button'
|
||||||
import haptics from '@root/components/haptics'
|
import haptics from '@root/components/haptics'
|
||||||
import removeInstance from '@utils/slices/instances/remove'
|
import removeInstance from '@utils/slices/instances/remove'
|
||||||
import { getInstanceActive } from '@utils/slices/instancesSlice'
|
import { getInstance, getInstanceActive } from '@utils/slices/instancesSlice'
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
@ -13,7 +13,7 @@ const Logout: React.FC = () => {
|
|||||||
const { t } = useTranslation('meRoot')
|
const { t } = useTranslation('meRoot')
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const instanceActive = useSelector(getInstanceActive)
|
const instance = useSelector(getInstance)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
@ -33,9 +33,11 @@ const Logout: React.FC = () => {
|
|||||||
text: t('content.logout.alert.buttons.logout'),
|
text: t('content.logout.alert.buttons.logout'),
|
||||||
style: 'destructive' as const,
|
style: 'destructive' as const,
|
||||||
onPress: () => {
|
onPress: () => {
|
||||||
haptics('Success')
|
if (instance) {
|
||||||
queryClient.clear()
|
haptics('Success')
|
||||||
dispatch(removeInstance(instanceActive))
|
queryClient.clear()
|
||||||
|
dispatch(removeInstance(instance))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -3,10 +3,9 @@ import Timeline from '@components/Timeline'
|
|||||||
import TimelineNotifications from '@components/Timeline/Notifications'
|
import TimelineNotifications from '@components/Timeline/Notifications'
|
||||||
import sharedScreens from '@screens/Tabs/Shared/sharedScreens'
|
import sharedScreens from '@screens/Tabs/Shared/sharedScreens'
|
||||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||||
import { updateInstanceNotification } from '@utils/slices/instancesSlice'
|
|
||||||
import React, { useCallback, useMemo } from 'react'
|
import React, { useCallback, useMemo } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { Platform, ViewToken } from 'react-native'
|
import { Platform } from 'react-native'
|
||||||
import { createNativeStackNavigator } from 'react-native-screens/native-stack'
|
import { createNativeStackNavigator } from 'react-native-screens/native-stack'
|
||||||
import { useDispatch } from 'react-redux'
|
import { useDispatch } from 'react-redux'
|
||||||
|
|
||||||
@ -39,39 +38,7 @@ const TabNotifications = React.memo(
|
|||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
const children = useCallback(
|
const children = useCallback(
|
||||||
({ navigation }) => (
|
() => <Timeline queryKey={queryKey} customProps={{ renderItem }} />,
|
||||||
<Timeline
|
|
||||||
queryKey={queryKey}
|
|
||||||
customProps={{
|
|
||||||
renderItem
|
|
||||||
// viewabilityConfigCallbackPairs: [
|
|
||||||
// {
|
|
||||||
// onViewableItemsChanged: ({
|
|
||||||
// viewableItems
|
|
||||||
// }: {
|
|
||||||
// viewableItems: ViewToken[]
|
|
||||||
// }) => {
|
|
||||||
// if (
|
|
||||||
// navigation.isFocused() &&
|
|
||||||
// viewableItems.length &&
|
|
||||||
// viewableItems[0].index === 0
|
|
||||||
// ) {
|
|
||||||
// dispatch(
|
|
||||||
// updateInstanceNotification({
|
|
||||||
// readTime: viewableItems[0].item.created_at
|
|
||||||
// })
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// viewabilityConfig: {
|
|
||||||
// minimumViewTime: 100,
|
|
||||||
// itemVisiblePercentThreshold: 60
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// ]
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import NetInfo from '@react-native-community/netinfo'
|
|||||||
import { store } from '@root/store'
|
import { store } from '@root/store'
|
||||||
import removeInstance from '@utils/slices/instances/remove'
|
import removeInstance from '@utils/slices/instances/remove'
|
||||||
import {
|
import {
|
||||||
getInstanceActive,
|
getInstance,
|
||||||
updateInstanceAccount
|
updateInstanceAccount
|
||||||
} from '@utils/slices/instancesSlice'
|
} from '@utils/slices/instancesSlice'
|
||||||
import log from './log'
|
import log from './log'
|
||||||
@ -14,11 +14,11 @@ const netInfo = async (): Promise<{
|
|||||||
}> => {
|
}> => {
|
||||||
log('log', 'netInfo', 'initializing')
|
log('log', 'netInfo', 'initializing')
|
||||||
const netInfo = await NetInfo.fetch()
|
const netInfo = await NetInfo.fetch()
|
||||||
const activeIndex = getInstanceActive(store.getState())
|
const instance = getInstance(store.getState())
|
||||||
|
|
||||||
if (netInfo.isConnected) {
|
if (netInfo.isConnected) {
|
||||||
log('log', 'netInfo', 'network connected')
|
log('log', 'netInfo', 'network connected')
|
||||||
if (activeIndex !== -1) {
|
if (instance) {
|
||||||
log('log', 'netInfo', 'checking locally stored credentials')
|
log('log', 'netInfo', 'checking locally stored credentials')
|
||||||
return apiInstance<Mastodon.Account>({
|
return apiInstance<Mastodon.Account>({
|
||||||
method: 'get',
|
method: 'get',
|
||||||
@ -26,12 +26,9 @@ const netInfo = async (): Promise<{
|
|||||||
})
|
})
|
||||||
.then(res => {
|
.then(res => {
|
||||||
log('log', 'netInfo', 'local credential check passed')
|
log('log', 'netInfo', 'local credential check passed')
|
||||||
if (
|
if (res.body.id !== instance.account.id) {
|
||||||
res.body.id !==
|
|
||||||
store.getState().instances.instances[activeIndex].account.id
|
|
||||||
) {
|
|
||||||
log('error', 'netInfo', 'local id does not match remote id')
|
log('error', 'netInfo', 'local id does not match remote id')
|
||||||
store.dispatch(removeInstance(activeIndex))
|
store.dispatch(removeInstance(instance))
|
||||||
return Promise.resolve({ connected: true, corruputed: '' })
|
return Promise.resolve({ connected: true, corruputed: '' })
|
||||||
} else {
|
} else {
|
||||||
store.dispatch(
|
store.dispatch(
|
||||||
@ -50,7 +47,7 @@ const netInfo = async (): Promise<{
|
|||||||
typeof error.status === 'number' &&
|
typeof error.status === 'number' &&
|
||||||
error.status === 401
|
error.status === 401
|
||||||
) {
|
) {
|
||||||
store.dispatch(removeInstance(activeIndex))
|
store.dispatch(removeInstance(instance))
|
||||||
}
|
}
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
connected: true,
|
connected: true,
|
||||||
|
@ -5,11 +5,13 @@ const push = () => {
|
|||||||
log('log', 'Push', 'initializing')
|
log('log', 'Push', 'initializing')
|
||||||
Notifications.setNotificationHandler({
|
Notifications.setNotificationHandler({
|
||||||
handleNotification: async () => ({
|
handleNotification: async () => ({
|
||||||
shouldShowAlert: true,
|
shouldShowAlert: false,
|
||||||
shouldPlaySound: false,
|
shouldPlaySound: false,
|
||||||
shouldSetBadge: false
|
shouldSetBadge: false
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
Notifications.setBadgeCountAsync(0)
|
||||||
|
Notifications.dismissAllNotificationsAsync()
|
||||||
}
|
}
|
||||||
|
|
||||||
export default push
|
export default push
|
||||||
|
@ -70,10 +70,6 @@ const addInstance = createAsyncThunk(
|
|||||||
avatarStatic: avatar_static,
|
avatarStatic: avatar_static,
|
||||||
preferences
|
preferences
|
||||||
},
|
},
|
||||||
notification: {
|
|
||||||
readTime: undefined,
|
|
||||||
latestTime: undefined
|
|
||||||
},
|
|
||||||
push: {
|
push: {
|
||||||
global: { loading: false, value: false },
|
global: { loading: false, value: false },
|
||||||
decode: { loading: false, value: false },
|
decode: { loading: false, value: false },
|
||||||
|
@ -85,8 +85,6 @@ const pushRegister = async (
|
|||||||
accountId,
|
accountId,
|
||||||
accountFull
|
accountFull
|
||||||
})
|
})
|
||||||
console.log('endpoint', serverRes.body.endpoint)
|
|
||||||
console.log('token', instance?.token)
|
|
||||||
|
|
||||||
const alerts = instancePush.alerts
|
const alerts = instancePush.alerts
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
|
@ -1,39 +1,37 @@
|
|||||||
import { createAsyncThunk } from '@reduxjs/toolkit'
|
import { createAsyncThunk } from '@reduxjs/toolkit'
|
||||||
import { RootState } from '@root/store'
|
|
||||||
import * as AuthSession from 'expo-auth-session'
|
import * as AuthSession from 'expo-auth-session'
|
||||||
|
import { Instance } from '../instancesSlice'
|
||||||
|
import { updateInstancePush } from './updatePush'
|
||||||
|
|
||||||
const removeInstance = createAsyncThunk(
|
const removeInstance = createAsyncThunk(
|
||||||
'instances/remove',
|
'instances/remove',
|
||||||
async (index: number): Promise<number> => {
|
async (instance: Instance, { dispatch }): Promise<Instance> => {
|
||||||
const { store } = require('@root/store')
|
if (instance.push.global.value) {
|
||||||
const instances = (store.getState() as RootState).instances.instances
|
dispatch(updateInstancePush(false))
|
||||||
|
|
||||||
if (index !== -1) {
|
|
||||||
const currentInstance = instances[index]
|
|
||||||
|
|
||||||
let revoked = undefined
|
|
||||||
try {
|
|
||||||
revoked = await AuthSession.revokeAsync(
|
|
||||||
{
|
|
||||||
clientId: currentInstance.appData.clientId,
|
|
||||||
clientSecret: currentInstance.appData.clientSecret,
|
|
||||||
token: currentInstance.token,
|
|
||||||
scopes: ['read', 'write', 'follow', 'push']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
revocationEndpoint: `https://${currentInstance.url}/oauth/revoke`
|
|
||||||
}
|
|
||||||
)
|
|
||||||
} catch {
|
|
||||||
console.warn('Revoking error')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!revoked) {
|
|
||||||
console.warn('Revoking error')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.resolve(index)
|
let revoked = undefined
|
||||||
|
try {
|
||||||
|
revoked = await AuthSession.revokeAsync(
|
||||||
|
{
|
||||||
|
clientId: instance.appData.clientId,
|
||||||
|
clientSecret: instance.appData.clientSecret,
|
||||||
|
token: instance.token,
|
||||||
|
scopes: ['read', 'write', 'follow', 'push']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
revocationEndpoint: `https://${instance.url}/oauth/revoke`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} catch {
|
||||||
|
console.warn('Revoking error')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!revoked) {
|
||||||
|
console.warn('Revoking error')
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve(instance)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,10 +29,6 @@ export type Instance = {
|
|||||||
avatarStatic: Mastodon.Account['avatar_static']
|
avatarStatic: Mastodon.Account['avatar_static']
|
||||||
preferences: Mastodon.Preferences
|
preferences: Mastodon.Preferences
|
||||||
}
|
}
|
||||||
notification: {
|
|
||||||
readTime?: Mastodon.Notification['created_at']
|
|
||||||
latestTime?: Mastodon.Notification['created_at']
|
|
||||||
}
|
|
||||||
push:
|
push:
|
||||||
| {
|
| {
|
||||||
global: { loading: boolean; value: true }
|
global: { loading: boolean; value: true }
|
||||||
@ -129,16 +125,6 @@ const instancesSlice = createSlice({
|
|||||||
...action.payload
|
...action.payload
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
updateInstanceNotification: (
|
|
||||||
{ instances },
|
|
||||||
action: PayloadAction<Partial<Instance['notification']>>
|
|
||||||
) => {
|
|
||||||
const activeIndex = findInstanceActive(instances)
|
|
||||||
instances[activeIndex].notification = {
|
|
||||||
...instances[activeIndex].notification,
|
|
||||||
...action.payload
|
|
||||||
}
|
|
||||||
},
|
|
||||||
updateInstanceDraft: (
|
updateInstanceDraft: (
|
||||||
{ instances },
|
{ instances },
|
||||||
action: PayloadAction<ComposeStateDraft>
|
action: PayloadAction<ComposeStateDraft>
|
||||||
@ -198,7 +184,16 @@ const instancesSlice = createSlice({
|
|||||||
})
|
})
|
||||||
|
|
||||||
.addCase(removeInstance.fulfilled, (state, action) => {
|
.addCase(removeInstance.fulfilled, (state, action) => {
|
||||||
state.instances.splice(action.payload, 1)
|
state.instances = state.instances.filter(instance => {
|
||||||
|
if (
|
||||||
|
instance.url === action.payload.url &&
|
||||||
|
instance.account.id === action.payload.account.id
|
||||||
|
) {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
})
|
||||||
state.instances.length &&
|
state.instances.length &&
|
||||||
(state.instances[state.instances.length - 1].active = true)
|
(state.instances[state.instances.length - 1].active = true)
|
||||||
|
|
||||||
@ -310,13 +305,6 @@ export const getInstanceAccount = ({ instances: { instances } }: RootState) => {
|
|||||||
return instanceActive !== -1 ? instances[instanceActive].account : null
|
return instanceActive !== -1 ? instances[instanceActive].account : null
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getInstanceNotification = ({
|
|
||||||
instances: { instances }
|
|
||||||
}: RootState) => {
|
|
||||||
const instanceActive = findInstanceActive(instances)
|
|
||||||
return instanceActive !== -1 ? instances[instanceActive].notification : null
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getInstancePush = ({ instances: { instances } }: RootState) => {
|
export const getInstancePush = ({ instances: { instances } }: RootState) => {
|
||||||
const instanceActive = findInstanceActive(instances)
|
const instanceActive = findInstanceActive(instances)
|
||||||
return instanceActive !== -1 ? instances[instanceActive].push : null
|
return instanceActive !== -1 ? instances[instanceActive].push : null
|
||||||
@ -330,7 +318,6 @@ export const getInstanceDrafts = ({ instances: { instances } }: RootState) => {
|
|||||||
export const {
|
export const {
|
||||||
updateInstanceActive,
|
updateInstanceActive,
|
||||||
updateInstanceAccount,
|
updateInstanceAccount,
|
||||||
updateInstanceNotification,
|
|
||||||
updateInstanceDraft,
|
updateInstanceDraft,
|
||||||
removeInstanceDraft
|
removeInstanceDraft
|
||||||
} = instancesSlice.actions
|
} = instancesSlice.actions
|
||||||
|
@ -8916,11 +8916,6 @@ realpath-native@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-2.0.0.tgz#7377ac429b6e1fd599dc38d08ed942d0d7beb866"
|
resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-2.0.0.tgz#7377ac429b6e1fd599dc38d08ed942d0d7beb866"
|
||||||
integrity sha512-v1SEYUOXXdbBZK8ZuNgO4TBjamPsiSgcFr0aP+tEKpQZK8vooEUqV6nm6Cv502mX4NF2EfsnVqtNAHG+/6Ur1Q==
|
integrity sha512-v1SEYUOXXdbBZK8ZuNgO4TBjamPsiSgcFr0aP+tEKpQZK8vooEUqV6nm6Cv502mX4NF2EfsnVqtNAHG+/6Ur1Q==
|
||||||
|
|
||||||
reconnecting-websocket@^4.4.0:
|
|
||||||
version "4.4.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/reconnecting-websocket/-/reconnecting-websocket-4.4.0.tgz#3b0e5b96ef119e78a03135865b8bb0af1b948783"
|
|
||||||
integrity sha512-D2E33ceRPga0NvTDhJmphEgJ7FUYF0v4lr1ki0csq06OdlxKfugGzN0dSkxM/NfqCxYELK4KcaTOUOjTV6Dcng==
|
|
||||||
|
|
||||||
redent@^2.0.0:
|
redent@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa"
|
resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user