Skip to content

Commit c18d130

Browse files
committed
feat: add simple profile info card
1 parent a013370 commit c18d130

File tree

4 files changed

+108
-55
lines changed

4 files changed

+108
-55
lines changed

src/screens/components/profile/ProfileInfo.tsx

Lines changed: 17 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44
import { Avatar, Text } from '@src/components'
55
import { translate } from '@src/i18n'
66
import { NavigationService, ROUTES } from '@src/navigation'
7-
import { ITheme, SylCommon, useTheme } from '@src/theme'
7+
import { useTheme } from '@src/theme'
88
import { V2exObject } from '@src/types'
99
import dayjs from 'dayjs'
1010
import React, { useMemo } from 'react'
1111
import { Image, StyleProp, TouchableOpacity, View, ViewStyle } from 'react-native'
1212
import { TextWithIconPress } from '../common'
13+
import { ProfileInfoStyle } from './profile'
1314

1415
/**
1516
* ProfileInfo props
@@ -44,7 +45,7 @@ const ProfileInfo: React.FC<ProfileInfoProps> = ({
4445

4546
const renderContent = () => {
4647
return (
47-
<View style={[styles.container(theme), containerStyle]}>
48+
<View style={[ProfileInfoStyle.container(theme), containerStyle]}>
4849
<TouchableOpacity
4950
onPress={() =>
5051
!withArrow
@@ -53,31 +54,31 @@ const ProfileInfo: React.FC<ProfileInfoProps> = ({
5354
? NavigationService.navigate(ROUTES.Profile, { username: info?.username })
5455
: NavigationService.navigate(ROUTES.SignIn)
5556
}
56-
style={styles.infoItem(theme)}>
57-
<View style={styles.baseAvatar(theme)}>
57+
style={ProfileInfoStyle.infoItem(theme)}>
58+
<View style={ProfileInfoStyle.baseAvatar(theme)}>
5859
<Avatar
5960
size={60}
6061
source={info?.avatar_normal ? { uri: info?.avatar_normal } : undefined}
6162
username={info?.username}
6263
/>
6364
</View>
64-
<View style={styles.baseRightBox(theme)}>
65-
<View style={styles.baseRightInfo(theme)}>
65+
<View style={ProfileInfoStyle.baseRightBox(theme)}>
66+
<View style={ProfileInfoStyle.baseRightInfo(theme)}>
6667
<Text
6768
style={[
68-
styles.baseRightItem(theme),
69+
ProfileInfoStyle.baseRightItem(theme),
6970
theme.typography.subheadingText,
7071
{ color: theme.colors.secondary }
7172
]}>
7273
{info?.username ?? translate('label.goLogin')}
7374
</Text>
7475
{!isLogin || (isLogin && info?.tagline) ? (
75-
<Text style={[styles.baseRightItem(theme), theme.typography.bodyText]}>
76+
<Text style={[ProfileInfoStyle.baseRightItem(theme), theme.typography.bodyText]}>
7677
{info?.tagline ?? translate('label.loginTips')}
7778
</Text>
7879
) : null}
7980
{info?.last_modified ? (
80-
<Text style={[styles.baseRightItem(theme), theme.typography.captionText]}>
81+
<Text style={[ProfileInfoStyle.baseRightItem(theme), theme.typography.captionText]}>
8182
{translate('label.profileLastModified').replace(
8283
'$',
8384
dayjs(info?.last_modified * 1000).format('YYYY-MM-DD HH:mm:ss')
@@ -86,18 +87,20 @@ const ProfileInfo: React.FC<ProfileInfoProps> = ({
8687
) : null}
8788
</View>
8889
{withArrow && (
89-
<View style={styles.baseRightArrow(theme)}>
90+
<View style={ProfileInfoStyle.baseRightArrow(theme)}>
9091
<Image source={theme.assets.images.icons.table.rightArrow} style={{ width: 14, height: 14 }} />
9192
</View>
9293
)}
9394
</View>
9495
</TouchableOpacity>
9596
{styleType === 'full' && (
9697
<>
97-
{info?.bio ? <Text style={[styles.infoItem(theme), theme.typography.bodyText]}>{info?.bio}</Text> : null}
98+
{info?.bio ? (
99+
<Text style={[ProfileInfoStyle.infoItem(theme), theme.typography.bodyText]}>{info?.bio}</Text>
100+
) : null}
98101

99102
{info && (info.location || info.website) ? (
100-
<View style={styles.infoItem(theme)}>
103+
<View style={ProfileInfoStyle.infoItem(theme)}>
101104
{info?.location ? (
102105
<TextWithIconPress
103106
containerStyle={{ marginRight: theme.spacing.small }}
@@ -118,7 +121,7 @@ const ProfileInfo: React.FC<ProfileInfoProps> = ({
118121
</View>
119122
) : null}
120123
{info && (info.github || info.telegram || info.twitter) ? (
121-
<View style={styles.infoItem(theme)}>
124+
<View style={ProfileInfoStyle.infoItem(theme)}>
122125
{info?.github ? (
123126
<TextWithIconPress
124127
onPress={() => {
@@ -149,7 +152,7 @@ const ProfileInfo: React.FC<ProfileInfoProps> = ({
149152
</View>
150153
) : null}
151154
{info?.created ? (
152-
<Text style={[styles.infoItem(theme), theme.typography.captionText]}>
155+
<Text style={[ProfileInfoStyle.infoItem(theme), theme.typography.captionText]}>
153156
{translate('label.joinV2exSinceTime')
154157
.replace('$', info?.id.toString())
155158
.replace('$', dayjs(info?.created * 1000).format())}
@@ -164,44 +167,4 @@ const ProfileInfo: React.FC<ProfileInfoProps> = ({
164167
return renderContent()
165168
}
166169

167-
const styles = {
168-
container: (theme: ITheme): ViewStyle => ({
169-
display: 'flex',
170-
alignItems: 'flex-start',
171-
flexDirection: 'column'
172-
}),
173-
infoItem: (theme: ITheme): ViewStyle => ({
174-
paddingBottom: theme.spacing.medium,
175-
display: 'flex',
176-
flexDirection: 'row',
177-
alignItems: 'flex-start',
178-
justifyContent: 'flex-start',
179-
width: '100%'
180-
}),
181-
baseAvatar: (theme: ITheme): ViewStyle => ({
182-
width: 60,
183-
height: 60,
184-
marginRight: theme.spacing.medium
185-
}),
186-
baseRightBox: (theme: ITheme): ViewStyle => ({
187-
display: 'flex',
188-
flexDirection: 'row',
189-
flex: 1
190-
}),
191-
baseRightInfo: (theme: ITheme): ViewStyle => ({
192-
display: 'flex',
193-
flexDirection: 'column',
194-
flex: 1,
195-
alignItems: 'flex-start'
196-
}),
197-
baseRightArrow: (theme: ITheme): ViewStyle => ({
198-
width: 14,
199-
display: 'flex',
200-
justifyContent: 'center'
201-
}),
202-
baseRightItem: (theme: ITheme): ViewStyle => ({
203-
paddingBottom: theme.spacing.small
204-
})
205-
}
206-
207170
export default ProfileInfo
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/**
2+
* Created by leon<[email protected]> on 22/05/27.
3+
*/
4+
import { Avatar, Text } from '@src/components'
5+
import { translate } from '@src/i18n'
6+
import { NavigationService, ROUTES } from '@src/navigation'
7+
import { ITheme, useTheme } from '@src/theme'
8+
import { V2exObject } from '@src/types'
9+
import dayjs from 'dayjs'
10+
import React from 'react'
11+
import { Image, StyleProp, TouchableOpacity, View, ViewStyle } from 'react-native'
12+
import { ProfileInfoStyle } from './profile'
13+
14+
/**
15+
* SimpleProfileInfoCard props
16+
*/
17+
export interface SimpleProfileInfoCardProps {
18+
/**
19+
* container style
20+
*/
21+
containerStyle?: StyleProp<ViewStyle>
22+
/**
23+
* profile info
24+
*/
25+
info?: V2exObject.Member
26+
/**
27+
* with right arrow
28+
*/
29+
withArrow?: boolean
30+
}
31+
32+
const SimpleProfileInfoCard: React.FC<SimpleProfileInfoCardProps> = ({
33+
info,
34+
containerStyle,
35+
withArrow = false
36+
}: SimpleProfileInfoCardProps) => {
37+
const { theme } = useTheme()
38+
39+
const renderContent = () => {
40+
return (
41+
<View style={[ProfileInfoStyle.container(theme), containerStyle]}>
42+
<TouchableOpacity
43+
onPress={() => {
44+
if (withArrow) NavigationService.navigate(ROUTES.Profile, { username: info?.username })
45+
}}
46+
style={ProfileInfoStyle.infoItem(theme)}>
47+
<View style={ProfileInfoStyle.baseAvatar(theme)}>
48+
<Avatar
49+
size={60}
50+
source={info?.avatar_normal ? { uri: info?.avatar_normal } : undefined}
51+
username={info?.username}
52+
/>
53+
</View>
54+
<View style={ProfileInfoStyle.baseRightBox(theme)}>
55+
<View style={ProfileInfoStyle.baseRightInfo(theme)}>
56+
<Text
57+
style={[
58+
ProfileInfoStyle.baseRightItem(theme),
59+
theme.typography.subheadingText,
60+
{ color: theme.colors.secondary }
61+
]}>
62+
{info?.username ?? translate('label.goLogin')}
63+
</Text>
64+
{info?.tagline ? (
65+
<Text style={[ProfileInfoStyle.baseRightItem(theme), theme.typography.bodyText]}>{info.tagline}</Text>
66+
) : null}
67+
{info?.created ? (
68+
<Text style={[ProfileInfoStyle.infoItem(theme), theme.typography.captionText]}>
69+
{translate('label.joinV2exSinceTime')
70+
.replace('$', info?.id.toString())
71+
.replace('$', dayjs(info?.created * 1000).format())}
72+
</Text>
73+
) : null}
74+
</View>
75+
{withArrow && (
76+
<View style={ProfileInfoStyle.baseRightArrow(theme)}>
77+
<Image source={theme.assets.images.icons.table.rightArrow} style={{ width: 14, height: 14 }} />
78+
</View>
79+
)}
80+
</View>
81+
</TouchableOpacity>
82+
</View>
83+
)
84+
}
85+
86+
return renderContent()
87+
}
88+
89+
export default SimpleProfileInfoCard

src/screens/components/profile/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ export { default as ProfileDetail } from './ProfileDetail'
33
export { default as ProfileGrid } from './ProfileGrid'
44
export { default as ProfileInfo } from './ProfileInfo'
55
export { default as ProfileTopics } from './ProfileTopics'
6+
export { default as SimpleProfileInfoCard } from './SimpleProfileInfoCard'

src/screens/profile/Profile.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const Profile = ({
2626

2727
useEffect(() => {
2828
navigation.setOptions({ title: member?.username })
29-
}, [username])
29+
}, [username, member])
3030

3131
useLayoutEffect(() => {
3232
navigation.setOptions({

0 commit comments

Comments
 (0)