tooot/src/components/Instance.tsx

286 lines
9.1 KiB
TypeScript
Raw Normal View History

2021-01-07 19:13:09 +01:00
import Button from '@components/Button'
import Icon from '@components/Icon'
2022-12-04 00:35:13 +01:00
import browserPackage from '@helpers/browserPackage'
2021-01-11 21:36:57 +01:00
import { useAppsQuery } from '@utils/queryHooks/apps'
import { useInstanceQuery } from '@utils/queryHooks/instance'
2021-02-20 19:12:44 +01:00
import { getInstances } from '@utils/slices/instancesSlice'
2021-01-07 19:13:09 +01:00
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
2021-01-26 12:17:25 +01:00
import * as WebBrowser from 'expo-web-browser'
2021-01-07 19:13:09 +01:00
import { debounce } from 'lodash'
2021-04-09 21:43:12 +02:00
import React, { RefObject, useCallback, useMemo, useState } from 'react'
2022-06-10 19:41:51 +02:00
import { Trans, useTranslation } from 'react-i18next'
2022-11-29 23:44:11 +01:00
import { Alert, Image, KeyboardAvoidingView, Platform, TextInput, View } from 'react-native'
2021-04-09 21:43:12 +02:00
import { ScrollView } from 'react-native-gesture-handler'
2021-02-09 01:16:12 +01:00
import { useSelector } from 'react-redux'
2021-03-06 21:01:38 +01:00
import { Placeholder } from 'rn-placeholder'
2021-01-07 19:13:09 +01:00
import InstanceAuth from './Instance/Auth'
import InstanceInfo from './Instance/Info'
import CustomText from './Text'
2021-01-07 19:13:09 +01:00
export interface Props {
2021-04-09 21:43:12 +02:00
scrollViewRef?: RefObject<ScrollView>
2021-01-07 19:13:09 +01:00
disableHeaderImage?: boolean
goBack?: boolean
}
const ComponentInstance: React.FC<Props> = ({
2021-04-09 21:43:12 +02:00
scrollViewRef,
2021-01-07 19:13:09 +01:00
disableHeaderImage,
goBack = false
}) => {
2021-02-09 01:16:12 +01:00
const { t } = useTranslation('componentInstance')
2022-02-12 14:51:01 +01:00
const { colors, mode } = useTheme()
2021-01-20 12:35:24 +01:00
2021-02-20 19:12:44 +01:00
const instances = useSelector(getInstances, () => true)
const [domain, setDomain] = useState<string>()
2021-01-07 19:13:09 +01:00
2021-01-11 21:36:57 +01:00
const instanceQuery = useInstanceQuery({
2021-02-20 19:12:44 +01:00
domain,
options: { enabled: !!domain, retry: false }
2021-01-07 19:13:09 +01:00
})
2021-01-20 12:35:24 +01:00
const appsQuery = useAppsQuery({
2021-02-20 19:12:44 +01:00
domain,
2021-01-07 19:13:09 +01:00
options: { enabled: false, retry: false }
})
const onChangeText = useCallback(
debounce(
text => {
2021-02-20 19:12:44 +01:00
setDomain(text.replace(/^http(s)?\:\/\//i, ''))
2021-01-20 12:35:24 +01:00
appsQuery.remove()
2021-01-07 19:13:09 +01:00
},
1000,
2021-01-20 12:35:24 +01:00
{ trailing: true }
2021-01-07 19:13:09 +01:00
),
[]
)
const processUpdate = useCallback(() => {
2021-02-20 19:12:44 +01:00
if (domain) {
2022-11-29 23:44:11 +01:00
if (instances && instances.filter(instance => instance.url === domain).length) {
2021-02-20 19:12:44 +01:00
Alert.alert(t('update.alert.title'), t('update.alert.message'), [
{
text: t('common:buttons.cancel'),
2021-02-20 19:12:44 +01:00
style: 'cancel'
},
{
text: t('common:buttons.continue'),
2021-02-20 19:12:44 +01:00
onPress: () => {
appsQuery.refetch()
2021-02-09 01:16:12 +01:00
}
2021-02-20 19:12:44 +01:00
}
])
2021-02-09 01:16:12 +01:00
} else {
appsQuery.refetch()
2021-01-07 19:13:09 +01:00
}
}
2021-02-20 19:12:44 +01:00
}, [domain])
2021-01-07 19:13:09 +01:00
2021-01-20 12:35:24 +01:00
const requestAuth = useMemo(() => {
if (
2021-02-20 19:12:44 +01:00
domain &&
2021-01-20 12:35:24 +01:00
instanceQuery.data?.uri &&
appsQuery.data?.client_id &&
appsQuery.data.client_secret
) {
return (
<InstanceAuth
key={Math.random()}
2021-02-20 19:12:44 +01:00
instanceDomain={domain}
instance={instanceQuery.data}
2021-01-20 12:35:24 +01:00
appData={{
clientId: appsQuery.data.client_id,
clientSecret: appsQuery.data.client_secret
}}
goBack={goBack}
/>
)
}
2021-02-20 19:12:44 +01:00
}, [domain, instanceQuery.data, appsQuery.data])
2021-01-26 12:17:25 +01:00
2021-01-07 19:13:09 +01:00
return (
2021-03-06 21:01:38 +01:00
<KeyboardAvoidingView
style={{ flex: 1 }}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
>
2021-01-07 19:13:09 +01:00
{!disableHeaderImage ? (
<View style={{ flexDirection: 'row' }}>
2021-01-07 19:13:09 +01:00
<Image
2021-03-28 23:31:10 +02:00
source={require('assets/images/welcome.png')}
style={{ resizeMode: 'contain', flex: 1, aspectRatio: 16 / 9 }}
2021-01-07 19:13:09 +01:00
/>
</View>
) : null}
<View
style={{
marginTop: StyleConstants.Spacing.L,
marginHorizontal: StyleConstants.Spacing.Global.PagePadding
}}
>
<View
style={{
flexDirection: 'row',
marginHorizontal: StyleConstants.Spacing.Global.PagePadding
}}
>
<TextInput
2021-04-09 21:43:12 +02:00
accessible={false}
accessibilityRole='none'
style={{
borderBottomWidth: 1,
...StyleConstants.FontStyle.M,
color: colors.primaryDefault,
2022-11-29 23:44:11 +01:00
borderBottomColor: instanceQuery.isError ? colors.red : colors.border
}}
editable={false}
2021-05-10 23:45:54 +02:00
defaultValue='https://'
/>
2021-01-07 19:13:09 +01:00
<TextInput
style={{
flex: 1,
borderBottomWidth: 1,
...StyleConstants.FontStyle.M,
marginRight: StyleConstants.Spacing.M,
color: colors.primaryDefault,
2022-11-29 23:44:11 +01:00
borderBottomColor: instanceQuery.isError ? colors.red : colors.border
}}
2021-01-07 19:13:09 +01:00
onChangeText={onChangeText}
autoCapitalize='none'
clearButtonMode='never'
keyboardType='url'
textContentType='URL'
2022-08-07 01:18:10 +02:00
onSubmitEditing={({ nativeEvent: { text } }) => {
if (
text === domain &&
instanceQuery.isSuccess &&
instanceQuery.data &&
instanceQuery.data.uri
) {
processUpdate()
}
}}
2021-04-09 21:43:12 +02:00
placeholder={' ' + t('server.textInput.placeholder')}
2022-02-12 14:51:01 +01:00
placeholderTextColor={colors.secondary}
2021-01-07 19:13:09 +01:00
returnKeyType='go'
keyboardAppearance={mode}
2021-04-09 21:43:12 +02:00
{...(scrollViewRef && {
onFocus: () =>
2022-11-29 23:44:11 +01:00
setTimeout(() => scrollViewRef.current?.scrollTo({ y: 0, animated: true }), 150)
2021-04-09 21:43:12 +02:00
})}
autoCorrect={false}
spellCheck={false}
2021-01-07 19:13:09 +01:00
/>
<Button
type='text'
2021-02-20 19:12:44 +01:00
content={t('server.button')}
2021-01-07 19:13:09 +01:00
onPress={processUpdate}
2021-02-17 21:39:38 +01:00
disabled={!instanceQuery.data?.uri}
2021-01-20 12:35:24 +01:00
loading={instanceQuery.isFetching || appsQuery.isFetching}
2021-01-07 19:13:09 +01:00
/>
</View>
2021-01-26 12:17:25 +01:00
2021-01-07 19:13:09 +01:00
<View>
2021-03-06 21:01:38 +01:00
<Placeholder>
2021-01-07 19:13:09 +01:00
<InstanceInfo
2021-01-23 02:41:50 +01:00
header={t('server.information.name')}
content={instanceQuery.data?.title || undefined}
potentialWidth={2}
2021-01-07 19:13:09 +01:00
/>
<View style={{ flex: 1, flexDirection: 'row' }}>
2021-01-23 02:41:50 +01:00
<InstanceInfo
style={{ alignItems: 'flex-start' }}
2021-01-23 02:41:50 +01:00
header={t('server.information.accounts')}
2022-11-29 23:44:11 +01:00
content={instanceQuery.data?.stats?.user_count?.toString() || undefined}
2021-01-23 02:41:50 +01:00
potentialWidth={4}
/>
<InstanceInfo
style={{ alignItems: 'center' }}
2021-01-23 02:41:50 +01:00
header={t('server.information.statuses')}
2022-11-29 23:44:11 +01:00
content={instanceQuery.data?.stats?.status_count?.toString() || undefined}
2021-01-23 02:41:50 +01:00
potentialWidth={4}
/>
<InstanceInfo
style={{ alignItems: 'flex-end' }}
2021-01-23 02:41:50 +01:00
header={t('server.information.domains')}
2022-11-29 23:44:11 +01:00
content={instanceQuery.data?.stats?.domain_count?.toString() || undefined}
2021-01-23 02:41:50 +01:00
potentialWidth={4}
/>
</View>
</Placeholder>
<View
style={{
flexDirection: 'row',
marginHorizontal: StyleConstants.Spacing.Global.PagePadding,
2022-06-10 19:41:51 +02:00
marginTop: StyleConstants.Spacing.M
}}
>
2021-02-09 01:16:12 +01:00
<Icon
name='Lock'
size={StyleConstants.Font.Size.S}
2022-02-12 14:51:01 +01:00
color={colors.secondary}
style={{
2022-11-29 23:44:11 +01:00
marginTop: (StyleConstants.Font.LineHeight.S - StyleConstants.Font.Size.S) / 2,
marginRight: StyleConstants.Spacing.XS
}}
2021-02-09 01:16:12 +01:00
/>
2022-11-29 23:44:11 +01:00
<CustomText fontStyle='S' style={{ flex: 1, color: colors.secondary }}>
2021-02-09 01:16:12 +01:00
{t('server.disclaimer.base')}
2022-06-10 19:41:51 +02:00
</CustomText>
</View>
<View
style={{
flexDirection: 'row',
marginHorizontal: StyleConstants.Spacing.Global.PagePadding,
marginBottom: StyleConstants.Spacing.M
}}
>
<Icon
name='CheckSquare'
size={StyleConstants.Font.Size.S}
color={colors.secondary}
style={{
2022-11-29 23:44:11 +01:00
marginTop: (StyleConstants.Font.LineHeight.S - StyleConstants.Font.Size.S) / 2,
2022-06-10 19:41:51 +02:00
marginRight: StyleConstants.Spacing.XS
}}
/>
<CustomText
fontStyle='S'
style={{ flex: 1, color: colors.secondary }}
accessibilityRole='link'
>
<Trans
i18nKey='componentInstance:server.terms.base'
components={[
<CustomText
accessible
style={{ color: colors.blue }}
2022-12-04 00:35:13 +01:00
onPress={async () =>
WebBrowser.openBrowserAsync('https://tooot.app/privacy-policy', {
browserPackage: await browserPackage()
})
}
2022-06-10 19:41:51 +02:00
/>,
<CustomText
accessible
style={{ color: colors.blue }}
2022-12-04 00:35:13 +01:00
onPress={async () =>
WebBrowser.openBrowserAsync('https://tooot.app/terms-of-service', {
browserPackage: await browserPackage()
})
2022-11-29 23:44:11 +01:00
}
2022-06-10 19:41:51 +02:00
/>
]}
/>
</CustomText>
2021-02-09 01:16:12 +01:00
</View>
2021-01-07 19:13:09 +01:00
</View>
</View>
2021-02-09 01:16:12 +01:00
{requestAuth}
2021-03-06 21:01:38 +01:00
</KeyboardAvoidingView>
2021-01-07 19:13:09 +01:00
)
}
export default ComponentInstance