import React, {useState} from 'react' import * as Toast from '../util/Toast' import { ActivityIndicator, StyleSheet, TouchableOpacity, View, } from 'react-native' import LinearGradient from 'react-native-linear-gradient' import {ScrollView, TextInput} from './util' import {PickedMedia} from '../../../lib/media/picker' import {Text} from '../util/text/Text' import {ErrorMessage} from '../util/error/ErrorMessage' import {useStores} from 'state/index' import {ProfileViewModel} from 'state/models/profile-view' import {s, colors, gradients} from 'lib/styles' import {enforceLen} from 'lib/strings/helpers' import {MAX_DISPLAY_NAME, MAX_DESCRIPTION} from 'lib/constants' import {compressIfNeeded} from 'lib/media/manip' import {UserBanner} from '../util/UserBanner' import {UserAvatar} from '../util/UserAvatar' import {usePalette} from 'lib/hooks/usePalette' import {useAnalytics} from 'lib/analytics' import {cleanError, isNetworkError} from 'lib/strings/errors' export const snapPoints = ['80%'] export function Component({ profileView, onUpdate, }: { profileView: ProfileViewModel onUpdate?: () => void }) { const store = useStores() const [error, setError] = useState('') const pal = usePalette('default') const {track} = useAnalytics() const [isProcessing, setProcessing] = useState(false) const [displayName, setDisplayName] = useState( profileView.displayName || '', ) const [description, setDescription] = useState( profileView.description || '', ) const [userBanner, setUserBanner] = useState( profileView.banner, ) const [userAvatar, setUserAvatar] = useState( profileView.avatar, ) const [newUserBanner, setNewUserBanner] = useState() const [newUserAvatar, setNewUserAvatar] = useState() const onPressCancel = () => { store.shell.closeModal() } const onSelectNewAvatar = async (img: PickedMedia) => { track('EditProfile:AvatarSelected') try { const finalImg = await compressIfNeeded(img, 1000000) setNewUserAvatar({mediaType: 'photo', ...finalImg}) setUserAvatar(finalImg.path) } catch (e: any) { setError(cleanError(e)) } } const onSelectNewBanner = async (img: PickedMedia) => { track('EditProfile:BannerSelected') try { const finalImg = await compressIfNeeded(img, 1000000) setNewUserBanner({mediaType: 'photo', ...finalImg}) setUserBanner(finalImg.path) } catch (e: any) { setError(cleanError(e)) } } const onPressSave = async () => { track('EditProfile:Save') setProcessing(true) if (error) { setError('') } try { await profileView.updateProfile( { displayName, description, }, newUserAvatar, newUserBanner, ) Toast.show('Profile updated') onUpdate?.() store.shell.closeModal() } catch (e: any) { if (isNetworkError(e)) { setError( 'Failed to save your profile. Check your internet connection and try again.', ) } else { setError(cleanError(e)) } } setProcessing(false) } return ( Edit my profile {error !== '' && ( )} Display Name setDisplayName(enforceLen(v, MAX_DISPLAY_NAME))} /> Description setDescription(enforceLen(v, MAX_DESCRIPTION))} /> {isProcessing ? ( ) : ( Save Changes )} Cancel ) } const styles = StyleSheet.create({ inner: { padding: 14, }, title: { textAlign: 'center', fontWeight: 'bold', fontSize: 24, marginBottom: 18, }, label: { fontWeight: 'bold', paddingHorizontal: 4, paddingBottom: 4, marginTop: 20, }, textInput: { borderWidth: 1, borderColor: colors.gray3, borderRadius: 6, paddingHorizontal: 14, paddingVertical: 10, fontSize: 16, color: colors.black, }, textArea: { borderWidth: 1, borderColor: colors.gray3, borderRadius: 6, paddingHorizontal: 12, paddingTop: 10, fontSize: 16, color: colors.black, height: 100, textAlignVertical: 'top', }, btn: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', width: '100%', borderRadius: 32, padding: 10, marginBottom: 10, }, avi: { position: 'absolute', top: 80, left: 10, width: 84, height: 84, borderWidth: 2, borderRadius: 42, borderColor: colors.white, backgroundColor: colors.white, }, photos: { marginBottom: 36, marginHorizontal: -14, }, errorContainer: {marginTop: 20}, })