Update profile header to use design system
parent
5e07b5bbc3
commit
10f613475a
|
@ -14,7 +14,7 @@ import {
|
||||||
ProfileImageLightbox,
|
ProfileImageLightbox,
|
||||||
} from '../../../state/models/shell-ui'
|
} from '../../../state/models/shell-ui'
|
||||||
import {pluralize} from '../../../lib/strings'
|
import {pluralize} from '../../../lib/strings'
|
||||||
import {s, colors} from '../../lib/styles'
|
import {s} from '../../lib/styles'
|
||||||
import {getGradient} from '../../lib/asset-gen'
|
import {getGradient} from '../../lib/asset-gen'
|
||||||
import {DropdownButton, DropdownItem} from '../util/forms/DropdownButton'
|
import {DropdownButton, DropdownItem} from '../util/forms/DropdownButton'
|
||||||
import * as Toast from '../util/Toast'
|
import * as Toast from '../util/Toast'
|
||||||
|
@ -24,6 +24,7 @@ import {RichText} from '../util/text/RichText'
|
||||||
import {UserAvatar} from '../util/UserAvatar'
|
import {UserAvatar} from '../util/UserAvatar'
|
||||||
import {UserBanner} from '../util/UserBanner'
|
import {UserBanner} from '../util/UserBanner'
|
||||||
import {UserInfoText} from '../util/UserInfoText'
|
import {UserInfoText} from '../util/UserInfoText'
|
||||||
|
import {usePalette} from '../../lib/hooks/usePalette'
|
||||||
|
|
||||||
export const ProfileHeader = observer(function ProfileHeader({
|
export const ProfileHeader = observer(function ProfileHeader({
|
||||||
view,
|
view,
|
||||||
|
@ -32,6 +33,7 @@ export const ProfileHeader = observer(function ProfileHeader({
|
||||||
view: ProfileViewModel
|
view: ProfileViewModel
|
||||||
onRefreshAll: () => void
|
onRefreshAll: () => void
|
||||||
}) {
|
}) {
|
||||||
|
const pal = usePalette('default')
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const isMember = useMemo(
|
const isMember = useMemo(
|
||||||
() => view.isScene && view.myState.member,
|
() => view.isScene && view.myState.member,
|
||||||
|
@ -95,9 +97,10 @@ export const ProfileHeader = observer(function ProfileHeader({
|
||||||
// =
|
// =
|
||||||
if (!view || !view.hasLoaded) {
|
if (!view || !view.hasLoaded) {
|
||||||
return (
|
return (
|
||||||
<View style={styles.outer}>
|
<View style={pal.view}>
|
||||||
<LoadingPlaceholder width="100%" height={120} />
|
<LoadingPlaceholder width="100%" height={120} />
|
||||||
<View style={styles.avi}>
|
<View
|
||||||
|
style={[pal.view, {borderColor: pal.colors.background}, styles.avi]}>
|
||||||
<LoadingPlaceholder
|
<LoadingPlaceholder
|
||||||
width={80}
|
width={80}
|
||||||
height={80}
|
height={80}
|
||||||
|
@ -113,7 +116,7 @@ export const ProfileHeader = observer(function ProfileHeader({
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.displayNameLine}>
|
<View style={styles.displayNameLine}>
|
||||||
<Text style={styles.displayName}>
|
<Text type="h2" style={[pal.text, {lineHeight: 38}]}>
|
||||||
{view.displayName || view.handle}
|
{view.displayName || view.handle}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
@ -161,24 +164,32 @@ export const ProfileHeader = observer(function ProfileHeader({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<View style={styles.outer}>
|
<View style={pal.view}>
|
||||||
<UserBanner handle={view.handle} banner={view.banner} />
|
<UserBanner handle={view.handle} banner={view.banner} />
|
||||||
<View style={styles.content}>
|
<View style={styles.content}>
|
||||||
<View style={[styles.buttonsLine]}>
|
<View style={[styles.buttonsLine]}>
|
||||||
{isMe ? (
|
{isMe ? (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
onPress={onPressEditProfile}
|
onPress={onPressEditProfile}
|
||||||
style={[styles.btn, styles.mainBtn]}>
|
style={[styles.btn, styles.mainBtn, pal.btn]}>
|
||||||
<Text style={[s.fw400, s.f14, s.black]}>Edit Profile</Text>
|
<Text type="button" style={pal.text}>
|
||||||
|
Edit Profile
|
||||||
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{view.myState.follow ? (
|
{view.myState.follow ? (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
onPress={onPressToggleFollow}
|
onPress={onPressToggleFollow}
|
||||||
style={[styles.btn, styles.mainBtn]}>
|
style={[styles.btn, styles.mainBtn, pal.btn]}>
|
||||||
<FontAwesomeIcon icon="check" style={[s.mr5]} size={14} />
|
<FontAwesomeIcon
|
||||||
<Text style={[s.fw400, s.f14, s.black]}>Following</Text>
|
icon="check"
|
||||||
|
style={[pal.text, s.mr5]}
|
||||||
|
size={14}
|
||||||
|
/>
|
||||||
|
<Text type="button" style={pal.text}>
|
||||||
|
Following
|
||||||
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
) : (
|
) : (
|
||||||
<TouchableOpacity onPress={onPressToggleFollow}>
|
<TouchableOpacity onPress={onPressToggleFollow}>
|
||||||
|
@ -188,7 +199,9 @@ export const ProfileHeader = observer(function ProfileHeader({
|
||||||
end={{x: 1, y: 1}}
|
end={{x: 1, y: 1}}
|
||||||
style={[styles.btn, styles.gradientBtn]}>
|
style={[styles.btn, styles.gradientBtn]}>
|
||||||
<FontAwesomeIcon icon="plus" style={[s.white, s.mr5]} />
|
<FontAwesomeIcon icon="plus" style={[s.white, s.mr5]} />
|
||||||
<Text style={[s.white, s.fw600, s.f16]}>Follow</Text>
|
<Text type="button" style={[s.white, s.bold]}>
|
||||||
|
Follow
|
||||||
|
</Text>
|
||||||
</LinearGradient>
|
</LinearGradient>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
)}
|
)}
|
||||||
|
@ -196,33 +209,38 @@ export const ProfileHeader = observer(function ProfileHeader({
|
||||||
)}
|
)}
|
||||||
{dropdownItems?.length ? (
|
{dropdownItems?.length ? (
|
||||||
<DropdownButton
|
<DropdownButton
|
||||||
|
type="bare"
|
||||||
items={dropdownItems}
|
items={dropdownItems}
|
||||||
style={[styles.btn, styles.secondaryBtn]}>
|
style={[styles.btn, styles.secondaryBtn, pal.btn]}>
|
||||||
<FontAwesomeIcon icon="ellipsis" style={[s.gray5]} />
|
<FontAwesomeIcon icon="ellipsis" style={[pal.text]} />
|
||||||
</DropdownButton>
|
</DropdownButton>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.displayNameLine}>
|
<View style={styles.displayNameLine}>
|
||||||
<Text style={[styles.displayName, s.black]}>
|
<Text type="h2" style={[pal.text, {lineHeight: 38}]}>
|
||||||
{view.displayName || view.handle}
|
{view.displayName || view.handle}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.handleLine}>
|
<View style={styles.handleLine}>
|
||||||
{view.isScene ? (
|
{view.isScene ? (
|
||||||
<View style={styles.typeLabelWrapper}>
|
<View
|
||||||
<Text style={styles.typeLabel}>Scene</Text>
|
style={[
|
||||||
|
styles.typeLabelWrapper,
|
||||||
|
{backgroundColor: pal.colors.backgroundLight},
|
||||||
|
]}>
|
||||||
|
<Text style={[styles.typeLabel, pal.textLight]}>Scene</Text>
|
||||||
</View>
|
</View>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
<Text style={styles.handle}>@{view.handle}</Text>
|
<Text style={pal.textLight}>@{view.handle}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.metricsLine}>
|
<View style={styles.metricsLine}>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={[s.flexRow, s.mr10]}
|
style={[s.flexRow, s.mr10]}
|
||||||
onPress={onPressFollowers}>
|
onPress={onPressFollowers}>
|
||||||
<Text style={[s.bold, s.mr2, styles.metricsText, s.black]}>
|
<Text type="body2" style={[s.bold, s.mr2, pal.text]}>
|
||||||
{view.followersCount}
|
{view.followersCount}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={[s.gray5, styles.metricsText]}>
|
<Text type="body2" style={[pal.textLight]}>
|
||||||
{pluralize(view.followersCount, 'follower')}
|
{pluralize(view.followersCount, 'follower')}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
@ -230,36 +248,38 @@ export const ProfileHeader = observer(function ProfileHeader({
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={[s.flexRow, s.mr10]}
|
style={[s.flexRow, s.mr10]}
|
||||||
onPress={onPressFollows}>
|
onPress={onPressFollows}>
|
||||||
<Text style={[s.bold, s.mr2, styles.metricsText, s.black]}>
|
<Text type="body2" style={[s.bold, s.mr2, pal.text]}>
|
||||||
{view.followsCount}
|
{view.followsCount}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={[s.gray5, styles.metricsText]}>following</Text>
|
<Text type="body2" style={[pal.textLight]}>
|
||||||
|
following
|
||||||
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
{view.isScene ? (
|
{view.isScene ? (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={[s.flexRow, s.mr10]}
|
style={[s.flexRow, s.mr10]}
|
||||||
onPress={onPressMembers}>
|
onPress={onPressMembers}>
|
||||||
<Text style={[s.bold, s.mr2, styles.metricsText, s.black]}>
|
<Text type="body2" style={[s.bold, s.mr2, pal.text]}>
|
||||||
{view.membersCount}
|
{view.membersCount}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={[s.gray5, styles.metricsText]}>
|
<Text type="body2" style={[pal.textLight]}>
|
||||||
{pluralize(view.membersCount, 'member')}
|
{pluralize(view.membersCount, 'member')}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
<View style={[s.flexRow, s.mr10]}>
|
<View style={[s.flexRow, s.mr10]}>
|
||||||
<Text style={[s.bold, s.mr2, styles.metricsText, s.black]}>
|
<Text type="body2" style={[s.bold, s.mr2, pal.text]}>
|
||||||
{view.postsCount}
|
{view.postsCount}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={[s.gray5, styles.metricsText]}>
|
<Text type="body2" style={[pal.textLight]}>
|
||||||
{pluralize(view.postsCount, 'post')}
|
{pluralize(view.postsCount, 'post')}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
{view.description ? (
|
{view.description ? (
|
||||||
<RichText
|
<RichText
|
||||||
style={styles.description}
|
style={[styles.description, pal.text]}
|
||||||
numberOfLines={3}
|
numberOfLines={3}
|
||||||
text={view.description}
|
text={view.description}
|
||||||
entities={view.descriptionEntities}
|
entities={view.descriptionEntities}
|
||||||
|
@ -267,10 +287,16 @@ export const ProfileHeader = observer(function ProfileHeader({
|
||||||
) : undefined}
|
) : undefined}
|
||||||
{view.isScene && view.creator ? (
|
{view.isScene && view.creator ? (
|
||||||
<View style={styles.relationshipsLine}>
|
<View style={styles.relationshipsLine}>
|
||||||
<FontAwesomeIcon icon={['far', 'user']} style={[s.gray5, s.mr5]} />
|
<FontAwesomeIcon
|
||||||
<Text style={[s.mr2, s.gray5, s.f15]}>Created by</Text>
|
icon={['far', 'user']}
|
||||||
|
style={[pal.textLight, s.mr5]}
|
||||||
|
/>
|
||||||
|
<Text type="body2" style={[s.mr2, pal.textLight]}>
|
||||||
|
Created by
|
||||||
|
</Text>
|
||||||
<UserInfoText
|
<UserInfoText
|
||||||
style={[s.blue3, s.f15]}
|
type="body2"
|
||||||
|
style={[pal.link]}
|
||||||
did={view.creator}
|
did={view.creator}
|
||||||
prefix="@"
|
prefix="@"
|
||||||
asLink
|
asLink
|
||||||
|
@ -281,14 +307,16 @@ export const ProfileHeader = observer(function ProfileHeader({
|
||||||
<View style={styles.relationshipsLine}>
|
<View style={styles.relationshipsLine}>
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
icon={['far', 'circle-check']}
|
icon={['far', 'circle-check']}
|
||||||
style={[s.gray5, s.mr5]}
|
style={[pal.textLight, s.mr5]}
|
||||||
/>
|
/>
|
||||||
<Text style={[s.mr2, s.gray5, s.f15]}>You are a member</Text>
|
<Text type="body2" style={[s.mr2, pal.textLight]}>
|
||||||
|
You are a member
|
||||||
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
</View>
|
</View>
|
||||||
{view.isScene && view.creator === store.me.did ? (
|
{view.isScene && view.creator === store.me.did ? (
|
||||||
<View style={styles.sceneAdminContainer}>
|
<View style={[styles.sceneAdminContainer, pal.border]}>
|
||||||
<TouchableOpacity onPress={onPressInviteMembers}>
|
<TouchableOpacity onPress={onPressInviteMembers}>
|
||||||
<LinearGradient
|
<LinearGradient
|
||||||
colors={[gradient[1], gradient[0]]}
|
colors={[gradient[1], gradient[0]]}
|
||||||
|
@ -300,12 +328,16 @@ export const ProfileHeader = observer(function ProfileHeader({
|
||||||
style={[s.mr5, s.white]}
|
style={[s.mr5, s.white]}
|
||||||
size={15}
|
size={15}
|
||||||
/>
|
/>
|
||||||
<Text style={[s.bold, s.f15, s.white]}>Invite Members</Text>
|
<Text type="button" style={[s.bold, s.white]}>
|
||||||
|
Invite Members
|
||||||
|
</Text>
|
||||||
</LinearGradient>
|
</LinearGradient>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
<TouchableOpacity style={styles.avi} onPress={onPressAvi}>
|
<TouchableOpacity
|
||||||
|
style={[pal.view, {borderColor: pal.colors.background}, styles.avi]}
|
||||||
|
onPress={onPressAvi}>
|
||||||
<UserAvatar
|
<UserAvatar
|
||||||
size={80}
|
size={80}
|
||||||
handle={view.handle}
|
handle={view.handle}
|
||||||
|
@ -318,9 +350,6 @@ export const ProfileHeader = observer(function ProfileHeader({
|
||||||
})
|
})
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
outer: {
|
|
||||||
backgroundColor: colors.white,
|
|
||||||
},
|
|
||||||
banner: {
|
banner: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: 120,
|
height: 120,
|
||||||
|
@ -333,8 +362,6 @@ const styles = StyleSheet.create({
|
||||||
height: 84,
|
height: 84,
|
||||||
borderRadius: 42,
|
borderRadius: 42,
|
||||||
borderWidth: 2,
|
borderWidth: 2,
|
||||||
borderColor: colors.white,
|
|
||||||
backgroundColor: colors.white,
|
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
paddingTop: 8,
|
paddingTop: 8,
|
||||||
|
@ -363,7 +390,6 @@ const styles = StyleSheet.create({
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
paddingVertical: 7,
|
paddingVertical: 7,
|
||||||
borderRadius: 50,
|
borderRadius: 50,
|
||||||
backgroundColor: colors.gray1,
|
|
||||||
marginLeft: 6,
|
marginLeft: 6,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -371,22 +397,12 @@ const styles = StyleSheet.create({
|
||||||
// paddingLeft: 86,
|
// paddingLeft: 86,
|
||||||
// marginBottom: 14,
|
// marginBottom: 14,
|
||||||
},
|
},
|
||||||
displayName: {
|
|
||||||
fontSize: 28,
|
|
||||||
fontWeight: 'bold',
|
|
||||||
},
|
|
||||||
|
|
||||||
handleLine: {
|
handleLine: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
marginBottom: 8,
|
marginBottom: 8,
|
||||||
},
|
},
|
||||||
handle: {
|
|
||||||
fontSize: 15,
|
|
||||||
fontWeight: 'bold',
|
|
||||||
color: colors.gray5,
|
|
||||||
},
|
|
||||||
typeLabelWrapper: {
|
typeLabelWrapper: {
|
||||||
backgroundColor: colors.gray1,
|
|
||||||
paddingHorizontal: 4,
|
paddingHorizontal: 4,
|
||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
marginRight: 5,
|
marginRight: 5,
|
||||||
|
@ -394,22 +410,15 @@ const styles = StyleSheet.create({
|
||||||
typeLabel: {
|
typeLabel: {
|
||||||
fontSize: 15,
|
fontSize: 15,
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
color: colors.gray5,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
metricsLine: {
|
metricsLine: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
marginBottom: 8,
|
marginBottom: 8,
|
||||||
},
|
},
|
||||||
metricsText: {
|
|
||||||
fontSize: 15,
|
|
||||||
},
|
|
||||||
|
|
||||||
description: {
|
description: {
|
||||||
marginBottom: 8,
|
marginBottom: 8,
|
||||||
fontSize: 16,
|
|
||||||
lineHeight: 20.8, // 1.3 of 16px
|
|
||||||
color: colors.black,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
relationshipsLine: {
|
relationshipsLine: {
|
||||||
|
@ -419,7 +428,6 @@ const styles = StyleSheet.create({
|
||||||
},
|
},
|
||||||
|
|
||||||
sceneAdminContainer: {
|
sceneAdminContainer: {
|
||||||
borderColor: colors.gray1,
|
|
||||||
borderTopWidth: 1,
|
borderTopWidth: 1,
|
||||||
borderBottomWidth: 1,
|
borderBottomWidth: 1,
|
||||||
paddingVertical: 12,
|
paddingVertical: 12,
|
||||||
|
|
|
@ -4,6 +4,7 @@ import {useTheme, PaletteColorName, PaletteColor} from '../ThemeContext'
|
||||||
export interface UsePaletteValue {
|
export interface UsePaletteValue {
|
||||||
colors: PaletteColor
|
colors: PaletteColor
|
||||||
view: ViewStyle
|
view: ViewStyle
|
||||||
|
btn: ViewStyle
|
||||||
border: ViewStyle
|
border: ViewStyle
|
||||||
text: TextStyle
|
text: TextStyle
|
||||||
textLight: TextStyle
|
textLight: TextStyle
|
||||||
|
@ -17,6 +18,9 @@ export function usePalette(color: PaletteColorName): UsePaletteValue {
|
||||||
view: {
|
view: {
|
||||||
backgroundColor: palette.background,
|
backgroundColor: palette.background,
|
||||||
},
|
},
|
||||||
|
btn: {
|
||||||
|
backgroundColor: palette.backgroundLight,
|
||||||
|
},
|
||||||
border: {
|
border: {
|
||||||
borderColor: palette.border,
|
borderColor: palette.border,
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue