tooot/src/screens/Tabs/Me/Push.tsx

225 lines
7.5 KiB
TypeScript

import analytics from '@components/analytics'
import Button from '@components/Button'
import Icon from '@components/Icon'
import { MenuContainer, MenuRow } from '@components/Menu'
import CustomText from '@components/Text'
import { useAppDispatch } from '@root/store'
import { isDevelopment, isRelease } from '@utils/checkEnvironment'
import { updateInstancePush } from '@utils/slices/instances/updatePush'
import { updateInstancePushAlert } from '@utils/slices/instances/updatePushAlert'
import { updateInstancePushDecode } from '@utils/slices/instances/updatePushDecode'
import {
clearPushLoading,
getInstanceAccount,
getInstancePush,
getInstanceUri
} from '@utils/slices/instancesSlice'
import { StyleConstants } from '@utils/styles/constants'
import layoutAnimation from '@utils/styles/layoutAnimation'
import { useTheme } from '@utils/styles/ThemeManager'
import * as Notifications from 'expo-notifications'
import * as WebBrowser from 'expo-web-browser'
import React, { useState, useEffect, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { AppState, Linking, ScrollView, View } from 'react-native'
import { useSelector } from 'react-redux'
const TabMePush: React.FC = () => {
const { colors } = useTheme()
const { t } = useTranslation('screenTabs')
const instanceAccount = useSelector(
getInstanceAccount,
(prev, next) => prev?.acct === next?.acct
)
const instanceUri = useSelector(getInstanceUri)
const dispatch = useAppDispatch()
const instancePush = useSelector(getInstancePush)
const [pushAvailable, setPushAvailable] =
useState<Notifications.ExpoPushToken>()
const [pushEnabled, setPushEnabled] = useState<boolean>()
const [pushCanAskAgain, setPushCanAskAgain] = useState<boolean>()
const checkPush = async () => {
const settings = await Notifications.getPermissionsAsync()
layoutAnimation()
setPushEnabled(settings.granted)
setPushCanAskAgain(settings.canAskAgain)
}
useEffect(() => {
if (isDevelopment) {
setPushAvailable({ data: '', type: 'expo' })
} else {
Notifications.getExpoPushTokenAsync({
experienceId: '@xmflsct/tooot'
})
.then(data => setPushAvailable(data))
.catch(() => setPushAvailable(undefined))
}
checkPush()
const subscription = AppState.addEventListener('change', checkPush)
return () => {
subscription.remove()
}
}, [])
useEffect(() => {
dispatch(clearPushLoading())
}, [])
const isLoading = instancePush?.global.loading || instancePush?.decode.loading
const alerts = useMemo(() => {
return instancePush?.alerts
? (
['follow', 'favourite', 'reblog', 'mention', 'poll'] as [
'follow',
'favourite',
'reblog',
'mention',
'poll'
]
).map(alert => (
<MenuRow
key={alert}
title={t(`me.push.${alert}.heading`)}
switchDisabled={
!pushEnabled || !instancePush.global.value || isLoading
}
switchValue={instancePush?.alerts[alert].value}
switchOnValueChange={() => {
analytics(`me_push_${alert}`, {
current: instancePush?.alerts[alert].value,
new: !instancePush?.alerts[alert].value
})
dispatch(
updateInstancePushAlert({
changed: alert,
alerts: {
...instancePush?.alerts,
[alert]: {
...instancePush?.alerts[alert],
value: !instancePush?.alerts[alert].value
}
}
})
)
}}
/>
))
: null
}, [pushEnabled, instancePush?.global, instancePush?.alerts, isLoading])
return (
<ScrollView>
{!!pushAvailable ? (
<>
{pushEnabled === false ? (
<MenuContainer>
<Button
type='text'
content={
pushCanAskAgain
? t('me.push.enable.direct')
: t('me.push.enable.settings')
}
style={{
marginTop: StyleConstants.Spacing.Global.PagePadding,
marginHorizontal:
StyleConstants.Spacing.Global.PagePadding * 2
}}
onPress={async () => {
if (pushCanAskAgain) {
analytics('me_push_enabled_dialogue')
const result = await Notifications.requestPermissionsAsync()
setPushEnabled(result.granted)
setPushCanAskAgain(result.canAskAgain)
} else {
analytics('me_push_enabled_setting')
Linking.openSettings()
}
}}
/>
</MenuContainer>
) : null}
<MenuContainer>
<MenuRow
title={t('me.push.global.heading', {
acct: `@${instanceAccount?.acct}@${instanceUri}`
})}
description={t('me.push.global.description')}
loading={instancePush?.global.loading}
switchDisabled={!pushEnabled || isLoading}
switchValue={
pushEnabled === false ? false : instancePush?.global.value
}
switchOnValueChange={() => {
analytics('me_push_global', {
current: instancePush?.global.value,
new: !instancePush?.global.value
})
dispatch(updateInstancePush(!instancePush?.global.value))
}}
/>
</MenuContainer>
<MenuContainer>
<MenuRow
title={t('me.push.decode.heading')}
description={t('me.push.decode.description')}
loading={instancePush?.decode.loading}
switchDisabled={
!pushEnabled || !instancePush?.global.value || isLoading
}
switchValue={instancePush?.decode.value}
switchOnValueChange={() => {
analytics('me_push_decode', {
current: instancePush?.decode.value,
new: !instancePush?.decode.value
})
dispatch(updateInstancePushDecode(!instancePush?.decode.value))
}}
/>
<MenuRow
title={t('me.push.howitworks')}
iconBack='ExternalLink'
onPress={() => {
analytics('me_push_howitworks')
WebBrowser.openBrowserAsync('https://tooot.app/how-push-works')
}}
/>
</MenuContainer>
<MenuContainer>{alerts}</MenuContainer>
{!isRelease ? (
<MenuContainer>
<CustomText fontSize='M' style={{ color: colors.primaryDefault }}>
{pushAvailable.data}
</CustomText>
</MenuContainer>
) : null}
</>
) : (
<View
style={{
flex: 1,
minHeight: '100%',
justifyContent: 'center',
alignItems: 'center'
}}
>
<Icon
name='Frown'
size={StyleConstants.Font.Size.L}
color={colors.primaryDefault}
/>
<CustomText fontStyle='M' style={{ color: colors.primaryDefault }}>
{t('me.push.notAvailable')}
</CustomText>
</View>
)}
</ScrollView>
)
}
export default TabMePush