mirror of
https://github.com/tooot-app/app
synced 2025-04-13 01:42:41 +02:00
Done profile editing
This commit is contained in:
parent
5bb77d0114
commit
fd1a6b3415
@ -69,7 +69,7 @@ const apiGeneral = async <T = unknown>({
|
|||||||
error.response.status,
|
error.response.status,
|
||||||
error.response.data.error
|
error.response.data.error
|
||||||
)
|
)
|
||||||
return Promise.reject(error.response)
|
return Promise.reject(error.response.data.error)
|
||||||
} else if (error.request) {
|
} else if (error.request) {
|
||||||
// The request was made but no response was received
|
// The request was made but no response was received
|
||||||
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
|
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
|
||||||
|
@ -98,7 +98,7 @@ const apiInstance = async <T = unknown>({
|
|||||||
error.response.status,
|
error.response.status,
|
||||||
error.response.data.error
|
error.response.data.error
|
||||||
)
|
)
|
||||||
return Promise.reject(error.response)
|
return Promise.reject(error.response.data.error)
|
||||||
} else if (error.request) {
|
} else if (error.request) {
|
||||||
// The request was made but no response was received
|
// The request was made but no response was received
|
||||||
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
|
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
|
||||||
|
@ -76,84 +76,86 @@ const MenuRow: React.FC<Props> = ({
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<View style={styles.core}>
|
<View>
|
||||||
<View style={styles.front}>
|
<View style={styles.core}>
|
||||||
{iconFront && (
|
<View style={styles.front}>
|
||||||
<Icon
|
{iconFront && (
|
||||||
name={iconFront}
|
|
||||||
size={StyleConstants.Font.Size.L}
|
|
||||||
color={theme[iconFrontColor]}
|
|
||||||
style={styles.iconFront}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{badge ? (
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
width: 8,
|
|
||||||
height: 8,
|
|
||||||
backgroundColor: theme.red,
|
|
||||||
borderRadius: 8,
|
|
||||||
marginRight: StyleConstants.Spacing.S
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
<View style={styles.main}>
|
|
||||||
<Text
|
|
||||||
style={[styles.title, { color: theme.primaryDefault }]}
|
|
||||||
numberOfLines={1}
|
|
||||||
>
|
|
||||||
{title}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
{content || switchValue !== undefined || iconBack ? (
|
|
||||||
<View style={styles.back}>
|
|
||||||
{content ? (
|
|
||||||
typeof content === 'string' ? (
|
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
styles.content,
|
|
||||||
{
|
|
||||||
color: theme.secondary,
|
|
||||||
opacity: !iconBack && loading ? 0 : 1
|
|
||||||
}
|
|
||||||
]}
|
|
||||||
numberOfLines={1}
|
|
||||||
>
|
|
||||||
{content}
|
|
||||||
</Text>
|
|
||||||
) : (
|
|
||||||
content
|
|
||||||
)
|
|
||||||
) : null}
|
|
||||||
{switchValue !== undefined ? (
|
|
||||||
<Switch
|
|
||||||
value={switchValue}
|
|
||||||
onValueChange={switchOnValueChange}
|
|
||||||
disabled={switchDisabled}
|
|
||||||
trackColor={{ true: theme.blue, false: theme.disabled }}
|
|
||||||
style={{ opacity: loading ? 0 : 1 }}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
{iconBack ? (
|
|
||||||
<Icon
|
<Icon
|
||||||
name={iconBack}
|
name={iconFront}
|
||||||
size={StyleConstants.Font.Size.L}
|
size={StyleConstants.Font.Size.L}
|
||||||
color={theme[iconBackColor]}
|
color={theme[iconFrontColor]}
|
||||||
style={[styles.iconBack, { opacity: loading ? 0 : 1 }]}
|
style={styles.iconFront}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{badge ? (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
width: 8,
|
||||||
|
height: 8,
|
||||||
|
backgroundColor: theme.red,
|
||||||
|
borderRadius: 8,
|
||||||
|
marginRight: StyleConstants.Spacing.S
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
{loading && loadingSpinkit}
|
<View style={styles.main}>
|
||||||
|
<Text
|
||||||
|
style={[styles.title, { color: theme.primaryDefault }]}
|
||||||
|
numberOfLines={1}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
{content || switchValue !== undefined || iconBack ? (
|
||||||
|
<View style={styles.back}>
|
||||||
|
{content ? (
|
||||||
|
typeof content === 'string' ? (
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
styles.content,
|
||||||
|
{
|
||||||
|
color: theme.secondary,
|
||||||
|
opacity: !iconBack && loading ? 0 : 1
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
numberOfLines={1}
|
||||||
|
>
|
||||||
|
{content}
|
||||||
|
</Text>
|
||||||
|
) : (
|
||||||
|
content
|
||||||
|
)
|
||||||
|
) : null}
|
||||||
|
{switchValue !== undefined ? (
|
||||||
|
<Switch
|
||||||
|
value={switchValue}
|
||||||
|
onValueChange={switchOnValueChange}
|
||||||
|
disabled={switchDisabled}
|
||||||
|
trackColor={{ true: theme.blue, false: theme.disabled }}
|
||||||
|
style={{ opacity: loading ? 0 : 1 }}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
{iconBack ? (
|
||||||
|
<Icon
|
||||||
|
name={iconBack}
|
||||||
|
size={StyleConstants.Font.Size.L}
|
||||||
|
color={theme[iconBackColor]}
|
||||||
|
style={[styles.iconBack, { opacity: loading ? 0 : 1 }]}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
{loading && loadingSpinkit}
|
||||||
|
</View>
|
||||||
|
) : null}
|
||||||
|
</View>
|
||||||
|
{description ? (
|
||||||
|
<Text style={[styles.description, { color: theme.secondary }]}>
|
||||||
|
{description}
|
||||||
|
</Text>
|
||||||
) : null}
|
) : null}
|
||||||
</View>
|
</View>
|
||||||
</TapGestureHandler>
|
</TapGestureHandler>
|
||||||
{description ? (
|
|
||||||
<Text style={[styles.description, { color: theme.secondary }]}>
|
|
||||||
{description}
|
|
||||||
</Text>
|
|
||||||
) : null}
|
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -102,11 +102,11 @@
|
|||||||
},
|
},
|
||||||
"avatar": {
|
"avatar": {
|
||||||
"title": "Avatar",
|
"title": "Avatar",
|
||||||
"description": "Available in next version"
|
"description": "Will be downscaled to 400x400px"
|
||||||
},
|
},
|
||||||
"banner": {
|
"header": {
|
||||||
"title": "Banner",
|
"title": "Banner",
|
||||||
"description": "Available in next version"
|
"description": "Will be downscaled to 1500x500px"
|
||||||
},
|
},
|
||||||
"note": {
|
"note": {
|
||||||
"title": "Description"
|
"title": "Description"
|
||||||
|
@ -30,7 +30,6 @@ const TabMeProfile: React.FC<StackScreenProps<
|
|||||||
>
|
>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name='Tab-Me-Profile-Root'
|
name='Tab-Me-Profile-Root'
|
||||||
component={TabMeProfileRoot}
|
|
||||||
options={{
|
options={{
|
||||||
headerTitle: t('me.stacks.profile.name'),
|
headerTitle: t('me.stacks.profile.name'),
|
||||||
...(Platform.OS === 'android' && {
|
...(Platform.OS === 'android' && {
|
||||||
@ -45,7 +44,15 @@ const TabMeProfile: React.FC<StackScreenProps<
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
/>
|
>
|
||||||
|
{({ route, navigation }) => (
|
||||||
|
<TabMeProfileRoot
|
||||||
|
messageRef={messageRef}
|
||||||
|
route={route}
|
||||||
|
navigation={navigation}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Stack.Screen>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name='Tab-Me-Profile-Name'
|
name='Tab-Me-Profile-Name'
|
||||||
options={{
|
options={{
|
||||||
|
@ -95,12 +95,13 @@ const TabMeProfileFields: React.FC<StackScreenProps<
|
|||||||
type: 'success'
|
type: 'success'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(err => {
|
||||||
displayMessage({
|
displayMessage({
|
||||||
ref: messageRef,
|
ref: messageRef,
|
||||||
message: t('me.profile.feedback.failed', {
|
message: t('me.profile.feedback.failed', {
|
||||||
type: t('me.profile.root.note.title')
|
type: t('me.profile.root.note.title')
|
||||||
}),
|
}),
|
||||||
|
...(err && { description: err }),
|
||||||
mode,
|
mode,
|
||||||
type: 'error'
|
type: 'error'
|
||||||
})
|
})
|
||||||
|
@ -77,12 +77,13 @@ const TabMeProfileName: React.FC<StackScreenProps<
|
|||||||
type: 'success'
|
type: 'success'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(err => {
|
||||||
displayMessage({
|
displayMessage({
|
||||||
ref: messageRef,
|
ref: messageRef,
|
||||||
message: t('me.profile.feedback.failed', {
|
message: t('me.profile.feedback.failed', {
|
||||||
type: t('me.profile.root.name.title')
|
type: t('me.profile.root.name.title')
|
||||||
}),
|
}),
|
||||||
|
...(err && { description: err }),
|
||||||
mode,
|
mode,
|
||||||
type: 'error'
|
type: 'error'
|
||||||
})
|
})
|
||||||
|
@ -77,12 +77,13 @@ const TabMeProfileNote: React.FC<StackScreenProps<
|
|||||||
type: 'success'
|
type: 'success'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(err => {
|
||||||
displayMessage({
|
displayMessage({
|
||||||
ref: messageRef,
|
ref: messageRef,
|
||||||
message: t('me.profile.feedback.failed', {
|
message: t('me.profile.feedback.failed', {
|
||||||
type: t('me.profile.root.note.title')
|
type: t('me.profile.root.note.title')
|
||||||
}),
|
}),
|
||||||
|
...(err && { description: err }),
|
||||||
mode,
|
mode,
|
||||||
type: 'error'
|
type: 'error'
|
||||||
})
|
})
|
||||||
|
@ -1,24 +1,26 @@
|
|||||||
import GracefullyImage from '@components/GracefullyImage'
|
|
||||||
import mediaSelector from '@components/mediaSelector'
|
|
||||||
import { MenuContainer, MenuRow } from '@components/Menu'
|
import { MenuContainer, MenuRow } from '@components/Menu'
|
||||||
|
import { displayMessage } from '@components/Message'
|
||||||
import { useActionSheet } from '@expo/react-native-action-sheet'
|
import { useActionSheet } from '@expo/react-native-action-sheet'
|
||||||
import { StackScreenProps } from '@react-navigation/stack'
|
import { StackScreenProps } from '@react-navigation/stack'
|
||||||
import { useProfileMutation, useProfileQuery } from '@utils/queryHooks/profile'
|
import { useProfileMutation, useProfileQuery } from '@utils/queryHooks/profile'
|
||||||
import * as ImagePicker from 'expo-image-picker'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import React, { useCallback } from 'react'
|
import React, { RefObject, useCallback } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import FlashMessage from 'react-native-flash-message'
|
||||||
import { ScrollView } from 'react-native-gesture-handler'
|
import { ScrollView } from 'react-native-gesture-handler'
|
||||||
|
import ProfileAvatarHeader from './Root/AvatarHeader'
|
||||||
|
|
||||||
const TabMeProfileRoot: React.FC<StackScreenProps<
|
const TabMeProfileRoot: React.FC<StackScreenProps<
|
||||||
Nav.TabMeProfileStackParamList,
|
Nav.TabMeProfileStackParamList,
|
||||||
'Tab-Me-Profile-Root'
|
'Tab-Me-Profile-Root'
|
||||||
>> = ({ navigation }) => {
|
> & { messageRef: RefObject<FlashMessage> }> = ({ messageRef, navigation }) => {
|
||||||
|
const { mode } = useTheme()
|
||||||
const { t } = useTranslation('screenTabs')
|
const { t } = useTranslation('screenTabs')
|
||||||
|
|
||||||
const { showActionSheetWithOptions } = useActionSheet()
|
const { showActionSheetWithOptions } = useActionSheet()
|
||||||
|
|
||||||
const { data, isLoading } = useProfileQuery({})
|
const { data, isLoading } = useProfileQuery({})
|
||||||
const { mutate } = useProfileMutation()
|
const { mutateAsync } = useProfileMutation()
|
||||||
|
|
||||||
const onPressVisibility = useCallback(() => {
|
const onPressVisibility = useCallback(() => {
|
||||||
showActionSheetWithOptions(
|
showActionSheetWithOptions(
|
||||||
@ -35,13 +37,46 @@ const TabMeProfileRoot: React.FC<StackScreenProps<
|
|||||||
async buttonIndex => {
|
async buttonIndex => {
|
||||||
switch (buttonIndex) {
|
switch (buttonIndex) {
|
||||||
case 0:
|
case 0:
|
||||||
mutate({ type: 'source[privacy]', data: 'public' })
|
mutateAsync({ type: 'source[privacy]', data: 'public' }).catch(
|
||||||
|
err =>
|
||||||
|
displayMessage({
|
||||||
|
ref: messageRef,
|
||||||
|
message: t('me.profile.feedback.failed', {
|
||||||
|
type: t('me.profile.root.visibility.title')
|
||||||
|
}),
|
||||||
|
...(err && { description: err }),
|
||||||
|
mode,
|
||||||
|
type: 'error'
|
||||||
|
})
|
||||||
|
)
|
||||||
break
|
break
|
||||||
case 1:
|
case 1:
|
||||||
mutate({ type: 'source[privacy]', data: 'unlisted' })
|
mutateAsync({ type: 'source[privacy]', data: 'unlisted' }).catch(
|
||||||
|
err =>
|
||||||
|
displayMessage({
|
||||||
|
ref: messageRef,
|
||||||
|
message: t('me.profile.feedback.failed', {
|
||||||
|
type: t('me.profile.root.visibility.title')
|
||||||
|
}),
|
||||||
|
...(err && { description: err }),
|
||||||
|
mode,
|
||||||
|
type: 'error'
|
||||||
|
})
|
||||||
|
)
|
||||||
break
|
break
|
||||||
case 2:
|
case 2:
|
||||||
mutate({ type: 'source[privacy]', data: 'private' })
|
mutateAsync({ type: 'source[privacy]', data: 'private' }).catch(
|
||||||
|
err =>
|
||||||
|
displayMessage({
|
||||||
|
ref: messageRef,
|
||||||
|
message: t('me.profile.feedback.failed', {
|
||||||
|
type: t('me.profile.root.visibility.title')
|
||||||
|
}),
|
||||||
|
...(err && { description: err }),
|
||||||
|
mode,
|
||||||
|
type: 'error'
|
||||||
|
})
|
||||||
|
)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,25 +85,88 @@ const TabMeProfileRoot: React.FC<StackScreenProps<
|
|||||||
|
|
||||||
const onPressSensitive = useCallback(() => {
|
const onPressSensitive = useCallback(() => {
|
||||||
if (data?.source.sensitive === undefined) {
|
if (data?.source.sensitive === undefined) {
|
||||||
mutate({ type: 'source[sensitive]', data: true })
|
mutateAsync({ type: 'source[sensitive]', data: true }).catch(err =>
|
||||||
|
displayMessage({
|
||||||
|
ref: messageRef,
|
||||||
|
message: t('me.profile.feedback.failed', {
|
||||||
|
type: t('me.profile.root.sensitive.title')
|
||||||
|
}),
|
||||||
|
...(err && { description: err }),
|
||||||
|
mode,
|
||||||
|
type: 'error'
|
||||||
|
})
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
mutate({ type: 'source[sensitive]', data: !data.source.sensitive })
|
mutateAsync({
|
||||||
|
type: 'source[sensitive]',
|
||||||
|
data: !data.source.sensitive
|
||||||
|
}).catch(err =>
|
||||||
|
displayMessage({
|
||||||
|
ref: messageRef,
|
||||||
|
message: t('me.profile.feedback.failed', {
|
||||||
|
type: t('me.profile.root.sensitive.title')
|
||||||
|
}),
|
||||||
|
...(err && { description: err }),
|
||||||
|
mode,
|
||||||
|
type: 'error'
|
||||||
|
})
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}, [data?.source.sensitive])
|
}, [data?.source.sensitive])
|
||||||
|
|
||||||
const onPressLock = useCallback(() => {
|
const onPressLock = useCallback(() => {
|
||||||
if (data?.locked === undefined) {
|
if (data?.locked === undefined) {
|
||||||
mutate({ type: 'locked', data: true })
|
mutateAsync({ type: 'locked', data: true }).catch(err =>
|
||||||
|
displayMessage({
|
||||||
|
ref: messageRef,
|
||||||
|
message: t('me.profile.feedback.failed', {
|
||||||
|
type: t('me.profile.root.lock.title')
|
||||||
|
}),
|
||||||
|
...(err && { description: err }),
|
||||||
|
mode,
|
||||||
|
type: 'error'
|
||||||
|
})
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
mutate({ type: 'locked', data: !data.locked })
|
mutateAsync({ type: 'locked', data: !data.locked }).catch(err =>
|
||||||
|
displayMessage({
|
||||||
|
ref: messageRef,
|
||||||
|
message: t('me.profile.feedback.failed', {
|
||||||
|
type: t('me.profile.root.lock.title')
|
||||||
|
}),
|
||||||
|
...(err && { description: err }),
|
||||||
|
mode,
|
||||||
|
type: 'error'
|
||||||
|
})
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}, [data?.locked])
|
}, [data?.locked])
|
||||||
|
|
||||||
const onPressBot = useCallback(() => {
|
const onPressBot = useCallback(() => {
|
||||||
if (data?.bot === undefined) {
|
if (data?.bot === undefined) {
|
||||||
mutate({ type: 'bot', data: true })
|
mutateAsync({ type: 'bot', data: true }).catch(err =>
|
||||||
|
displayMessage({
|
||||||
|
ref: messageRef,
|
||||||
|
message: t('me.profile.feedback.failed', {
|
||||||
|
type: t('me.profile.root.bot.title')
|
||||||
|
}),
|
||||||
|
...(err && { description: err }),
|
||||||
|
mode,
|
||||||
|
type: 'error'
|
||||||
|
})
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
mutate({ type: 'bot', data: !data?.bot })
|
mutateAsync({ type: 'bot', data: !data?.bot }).catch(err =>
|
||||||
|
displayMessage({
|
||||||
|
ref: messageRef,
|
||||||
|
message: t('me.profile.feedback.failed', {
|
||||||
|
type: t('me.profile.root.bot.title')
|
||||||
|
}),
|
||||||
|
...(err && { description: err }),
|
||||||
|
mode,
|
||||||
|
type: 'error'
|
||||||
|
})
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}, [data?.bot])
|
}, [data?.bot])
|
||||||
|
|
||||||
@ -87,52 +185,8 @@ const TabMeProfileRoot: React.FC<StackScreenProps<
|
|||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<MenuRow
|
<ProfileAvatarHeader type='avatar' messageRef={messageRef} />
|
||||||
title={t('me.profile.root.avatar.title')}
|
<ProfileAvatarHeader type='header' messageRef={messageRef} />
|
||||||
description={t('me.profile.root.avatar.description')}
|
|
||||||
content={
|
|
||||||
<GracefullyImage
|
|
||||||
key={data?.avatar_static}
|
|
||||||
style={{ flex: 1 }}
|
|
||||||
uri={{
|
|
||||||
original: data?.avatar_static
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
loading={isLoading}
|
|
||||||
iconBack='ChevronRight'
|
|
||||||
onPress={async () => {
|
|
||||||
const image = await mediaSelector({
|
|
||||||
showActionSheetWithOptions,
|
|
||||||
mediaTypes: ImagePicker.MediaTypeOptions.Images,
|
|
||||||
resize: { width: 400, height: 400 }
|
|
||||||
})
|
|
||||||
mutate({ type: 'avatar', data: image.uri })
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<MenuRow
|
|
||||||
title={t('me.profile.root.banner.title')}
|
|
||||||
description={t('me.profile.root.banner.description')}
|
|
||||||
content={
|
|
||||||
<GracefullyImage
|
|
||||||
key={data?.header_static}
|
|
||||||
style={{ flex: 1 }}
|
|
||||||
uri={{
|
|
||||||
original: data?.header_static
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
loading={isLoading}
|
|
||||||
iconBack='ChevronRight'
|
|
||||||
onPress={async () => {
|
|
||||||
const image = await mediaSelector({
|
|
||||||
showActionSheetWithOptions,
|
|
||||||
mediaTypes: ImagePicker.MediaTypeOptions.Images,
|
|
||||||
resize: { width: 1500, height: 500 }
|
|
||||||
})
|
|
||||||
mutate({ type: 'header', data: image.uri })
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<MenuRow
|
<MenuRow
|
||||||
title={t('me.profile.root.note.title')}
|
title={t('me.profile.root.note.title')}
|
||||||
content={data?.source.note}
|
content={data?.source.note}
|
||||||
|
66
src/screens/Tabs/Me/Profile/Root/AvatarHeader.tsx
Normal file
66
src/screens/Tabs/Me/Profile/Root/AvatarHeader.tsx
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import mediaSelector from '@components/mediaSelector'
|
||||||
|
import { MenuRow } from '@components/Menu'
|
||||||
|
import { displayMessage } from '@components/Message'
|
||||||
|
import { useActionSheet } from '@expo/react-native-action-sheet'
|
||||||
|
import { useProfileMutation, useProfileQuery } from '@utils/queryHooks/profile'
|
||||||
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
|
import * as ImagePicker from 'expo-image-picker'
|
||||||
|
import React, { RefObject } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import FlashMessage from 'react-native-flash-message'
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
type: 'avatar' | 'header'
|
||||||
|
messageRef: RefObject<FlashMessage>
|
||||||
|
}
|
||||||
|
|
||||||
|
const ProfileAvatarHeader: React.FC<Props> = ({ type, messageRef }) => {
|
||||||
|
const { mode } = useTheme()
|
||||||
|
const { t } = useTranslation('screenTabs')
|
||||||
|
|
||||||
|
const { showActionSheetWithOptions } = useActionSheet()
|
||||||
|
|
||||||
|
const query = useProfileQuery({})
|
||||||
|
const mutation = useProfileMutation()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MenuRow
|
||||||
|
title={t(`me.profile.root.${type}.title`)}
|
||||||
|
description={t(`me.profile.root.${type}.description`)}
|
||||||
|
loading={query.isLoading || mutation.isLoading}
|
||||||
|
iconBack='ChevronRight'
|
||||||
|
onPress={async () => {
|
||||||
|
const image = await mediaSelector({
|
||||||
|
showActionSheetWithOptions,
|
||||||
|
mediaTypes: ImagePicker.MediaTypeOptions.Images,
|
||||||
|
resize: { width: 400, height: 400 }
|
||||||
|
})
|
||||||
|
mutation
|
||||||
|
.mutateAsync({ type, data: image.uri })
|
||||||
|
.then(() =>
|
||||||
|
displayMessage({
|
||||||
|
ref: messageRef,
|
||||||
|
message: t('me.profile.feedback.succeed', {
|
||||||
|
type: t(`me.profile.root.${type}.title`)
|
||||||
|
}),
|
||||||
|
mode,
|
||||||
|
type: 'success'
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.catch(err =>
|
||||||
|
displayMessage({
|
||||||
|
ref: messageRef,
|
||||||
|
message: t('me.profile.feedback.failed', {
|
||||||
|
type: t(`me.profile.root.${type}.title`)
|
||||||
|
}),
|
||||||
|
...(err && { description: err }),
|
||||||
|
mode,
|
||||||
|
type: 'error'
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ProfileAvatarHeader
|
Loading…
x
Reference in New Issue
Block a user