From ed6bcfdb75f10be0ee0245a6b07c6484559a07c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Ferreiro?= Date: Tue, 6 Dec 2022 14:50:20 +0000 Subject: [PATCH] refactor profile pictures's state --- src/state/models/profile-view.ts | 26 ++++++++--------- src/view/com/modals/EditProfile.tsx | 16 ++++++++--- src/view/com/profile/ProfileHeader.tsx | 8 ++++-- src/view/com/util/UserAvatar.tsx | 39 ++++++++++++-------------- src/view/com/util/UserBanner.tsx | 36 +++++++++--------------- 5 files changed, 62 insertions(+), 63 deletions(-) diff --git a/src/state/models/profile-view.ts b/src/state/models/profile-view.ts index 60d9067576..5244e0912f 100644 --- a/src/state/models/profile-view.ts +++ b/src/state/models/profile-view.ts @@ -6,7 +6,6 @@ import {extractEntities} from '../../lib/strings' import {Declaration} from './_common' import {RootStoreModel} from './root-store' import * as apilib from '../lib/api' -import {Image} from 'react-native-image-crop-picker' export const ACTOR_TYPE_USER = 'app.bsky.system.actorUser' export const ACTOR_TYPE_SCENE = 'app.bsky.system.actorScene' @@ -44,13 +43,13 @@ export class ProfileViewModel { postsCount: number = 0 myState = new ProfileViewMyStateModel() + // data to be implemented in the protocol + userAvatar: string | null = null + userBanner: string | null = null + // added data descriptionEntities?: Entity[] - // temp state while imagery is not supported by the protocol - userAvatar: Image | null = null - userBanner: Image | null = null - constructor( public rootStore: RootStoreModel, params: GetProfile.QueryParams, @@ -120,22 +119,21 @@ export class ProfileViewModel { } } - async updateProfile(fn: (existing?: Profile.Record) => Profile.Record) { + async updateProfile( + fn: (existing?: Profile.Record) => Profile.Record, + userAvatar: string | null, + userBanner: string | null, + ) { await apilib.updateProfile(this.rootStore, this.did, fn) + // add userBanner & userAvatar in the protocol when suported + this.userAvatar = userAvatar + this.userBanner = userBanner await this.refresh() } // state transitions // = - updateUserAvatar(img: Image) { - this.userAvatar = img - } - - updateUserBanner(img: Image) { - this.userBanner = img - } - private _xLoading(isRefreshing = false) { this.isLoading = true this.isRefreshing = isRefreshing diff --git a/src/view/com/modals/EditProfile.tsx b/src/view/com/modals/EditProfile.tsx index 0a305115d6..af5cf27b30 100644 --- a/src/view/com/modals/EditProfile.tsx +++ b/src/view/com/modals/EditProfile.tsx @@ -33,6 +33,12 @@ export function Component({ const [description, setDescription] = useState( profileView.description || '', ) + const [userBanner, setUserBanner] = useState( + profileView.userBanner, + ) + const [userAvatar, setUserAvatar] = useState( + profileView.userAvatar, + ) const onPressCancel = () => { store.shell.closeModal() } @@ -53,6 +59,8 @@ export function Component({ description, } }, + userAvatar, + userBanner, ) Toast.show('Profile updated') onUpdate?.() @@ -72,17 +80,17 @@ export function Component({ diff --git a/src/view/com/profile/ProfileHeader.tsx b/src/view/com/profile/ProfileHeader.tsx index 0dee773546..2642868fb2 100644 --- a/src/view/com/profile/ProfileHeader.tsx +++ b/src/view/com/profile/ProfileHeader.tsx @@ -152,14 +152,18 @@ export const ProfileHeader = observer(function ProfileHeader({ } return ( - + diff --git a/src/view/com/util/UserAvatar.tsx b/src/view/com/util/UserAvatar.tsx index ed9c96d164..fbcc53e0e3 100644 --- a/src/view/com/util/UserAvatar.tsx +++ b/src/view/com/util/UserAvatar.tsx @@ -1,4 +1,4 @@ -import React, {useCallback, useState} from 'react' +import React, {useCallback} from 'react' import {StyleSheet, View, TouchableOpacity, Alert, Image} from 'react-native' import Svg, {Circle, Text, Defs, LinearGradient, Stop} from 'react-native-svg' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' @@ -10,28 +10,25 @@ import { import {getGradient} from '../../lib/asset-gen' import {colors} from '../../lib/styles' import {IMAGES_ENABLED} from '../../../build-flags' -import {ProfileViewModel} from '../../../state/models/profile-view' export function UserAvatar({ size, handle, - profileView, + userAvatar, displayName, isMe = false, - isEditable = false, + setUserAvatar, }: { size: number handle: string isMe?: boolean - isEditable?: boolean displayName: string | undefined - profileView: ProfileViewModel + userAvatar: string | null + setUserAvatar?: React.Dispatch> }) { const initials = getInitials(displayName || handle) const gradient = getGradient(handle) - const [tempUserAvatar, setTempUserAvatar] = useState(null) - const handleEditAvatar = useCallback(() => { Alert.alert('Select upload method', '', [ { @@ -44,8 +41,9 @@ export function UserAvatar({ height: 80, cropperCircleOverlay: true, }).then(item => { - profileView.updateUserAvatar(item) - setTempUserAvatar(item.path) + if (setUserAvatar != null) { + setUserAvatar(item.path) + } }) }, }, @@ -62,14 +60,15 @@ export function UserAvatar({ height: 80, cropperCircleOverlay: true, }).then(croppedItem => { - profileView.updateUserAvatar(croppedItem) - setTempUserAvatar(croppedItem.path) + if (setUserAvatar != null) { + setUserAvatar(croppedItem.path) + } }) }) }, }, ]) - }, [profileView]) + }, [setUserAvatar]) const renderSvg = (size: number, initials: string) => ( @@ -92,14 +91,12 @@ export function UserAvatar({ ) - return isEditable && IMAGES_ENABLED ? ( + // setUserAvatar is only passed as prop on the EditProfile component + return setUserAvatar != null && IMAGES_ENABLED ? ( {/* Added a react state temporary photo while the protocol does not support imagery */} - {profileView.userAvatar != null || tempUserAvatar != null ? ( - + {userAvatar != null ? ( + ) : ( renderSvg(size, initials) )} @@ -111,11 +108,11 @@ export function UserAvatar({ /> - ) : isMe && profileView.userAvatar != null ? ( + ) : isMe && userAvatar != null ? ( ) : ( renderSvg(size, initials) diff --git a/src/view/com/util/UserBanner.tsx b/src/view/com/util/UserBanner.tsx index bc2c4a9207..4a6fe246eb 100644 --- a/src/view/com/util/UserBanner.tsx +++ b/src/view/com/util/UserBanner.tsx @@ -1,4 +1,4 @@ -import React, {useCallback, useState} from 'react' +import React, {useCallback} from 'react' import {StyleSheet, View, TouchableOpacity, Alert, Image} from 'react-native' import Svg, {Rect, Defs, LinearGradient, Stop} from 'react-native-svg' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' @@ -10,23 +10,20 @@ import { openPicker, } from 'react-native-image-crop-picker' import {IMAGES_ENABLED} from '../../../build-flags' -import {ProfileViewModel} from '../../../state/models/profile-view' export function UserBanner({ handle, - profileView, + userBanner, isMe = false, - isEditable = false, + setUserBanner, }: { handle: string isMe?: boolean - profileView: ProfileViewModel - isEditable?: boolean + userBanner: string | null + setUserBanner?: React.Dispatch> }) { const gradient = getGradient(handle) - const [tempUserBanner, setTempUserBanner] = useState(null) - const handleEditBanner = useCallback(() => { Alert.alert('Select upload method', '', [ { @@ -38,8 +35,7 @@ export function UserBanner({ width: 1500, height: 500, }).then(item => { - profileView.updateUserBanner(item) - setTempUserBanner(item.path) + setUserBanner(item.path) }) }, }, @@ -55,14 +51,13 @@ export function UserBanner({ width: 1500, height: 500, }).then(croppedItem => { - profileView.updateUserBanner(croppedItem) - setTempUserBanner(croppedItem.path) + setUserBanner(croppedItem.path) }) }) }, }, ]) - }, [profileView]) + }, [setUserBanner]) const renderSvg = () => ( @@ -81,15 +76,12 @@ export function UserBanner({ ) - return isEditable && IMAGES_ENABLED ? ( + // setUserBanner is only passed as prop on the EditProfile component + return setUserBanner != null && IMAGES_ENABLED ? ( {/* Added a react state temporary photo while the protocol does not support imagery */} - {profileView.userBanner != null || tempUserBanner != null ? ( - + {userBanner != null ? ( + ) : ( renderSvg() )} @@ -101,11 +93,11 @@ export function UserBanner({ /> - ) : isMe && profileView.userBanner != null ? ( + ) : isMe && userBanner != null ? ( ) : ( renderSvg()