diff options
Diffstat (limited to 'src/view/com')
-rw-r--r-- | src/view/com/profile/ProfileCard.tsx | 59 | ||||
-rw-r--r-- | src/view/com/profile/ProfileHeader.tsx | 9 | ||||
-rw-r--r-- | src/view/com/profile/ProfileMembers.tsx | 69 | ||||
-rw-r--r-- | src/view/com/util/Selector.tsx | 2 |
4 files changed, 135 insertions, 4 deletions
diff --git a/src/view/com/profile/ProfileCard.tsx b/src/view/com/profile/ProfileCard.tsx new file mode 100644 index 000000000..cb58aec3f --- /dev/null +++ b/src/view/com/profile/ProfileCard.tsx @@ -0,0 +1,59 @@ +import React from 'react' +import {StyleSheet, Text, View} from 'react-native' +import {Link} from '../util/Link' +import {UserAvatar} from '../util/UserAvatar' +import {s, colors} from '../../lib/styles' + +export function ProfileCard({ + did, + handle, + displayName, + description, +}: { + did: string + handle: string + displayName?: string + description?: string +}) { + return ( + <Link style={styles.outer} href={`/profile/${handle}`} title={handle}> + <View style={styles.layout}> + <View style={styles.layoutAvi}> + <UserAvatar size={40} displayName={displayName} handle={handle} /> + </View> + <View style={styles.layoutContent}> + <Text style={[s.f16, s.bold]}>{displayName || handle}</Text> + <Text style={[s.f15, s.gray5]}>@{handle}</Text> + </View> + </View> + </Link> + ) +} + +const styles = StyleSheet.create({ + outer: { + marginTop: 1, + backgroundColor: colors.white, + }, + layout: { + flexDirection: 'row', + }, + layoutAvi: { + width: 60, + paddingLeft: 10, + paddingTop: 10, + paddingBottom: 10, + }, + avi: { + width: 40, + height: 40, + borderRadius: 20, + resizeMode: 'cover', + }, + layoutContent: { + flex: 1, + paddingRight: 10, + paddingTop: 12, + paddingBottom: 10, + }, +}) diff --git a/src/view/com/profile/ProfileHeader.tsx b/src/view/com/profile/ProfileHeader.tsx index 984190283..d1dcd0525 100644 --- a/src/view/com/profile/ProfileHeader.tsx +++ b/src/view/com/profile/ProfileHeader.tsx @@ -57,6 +57,9 @@ export const ProfileHeader = observer(function ProfileHeader({ const onPressFollows = () => { store.nav.navigate(`/profile/${view.handle}/follows`) } + const onPressMembers = () => { + store.nav.navigate(`/profile/${view.handle}/members`) + } // loading // = @@ -173,12 +176,12 @@ export const ProfileHeader = observer(function ProfileHeader({ {view.isScene ? ( <TouchableOpacity style={[s.flexRow, s.mr10]} - onPress={onPressFollows}> + onPress={onPressMembers}> <Text style={[s.bold, s.mr2, styles.metricsText]}> - {view.followsCount} + {view.membersCount} </Text> <Text style={[s.gray5, styles.metricsText]}> - {pluralize(view.followsCount, 'member')} + {pluralize(view.membersCount, 'member')} </Text> </TouchableOpacity> ) : undefined} diff --git a/src/view/com/profile/ProfileMembers.tsx b/src/view/com/profile/ProfileMembers.tsx new file mode 100644 index 000000000..11db02054 --- /dev/null +++ b/src/view/com/profile/ProfileMembers.tsx @@ -0,0 +1,69 @@ +import React, {useState, useEffect} from 'react' +import {observer} from 'mobx-react-lite' +import {ActivityIndicator, FlatList, Text, View} from 'react-native' +import {MembersViewModel, MemberItem} from '../../../state/models/members-view' +import {ProfileCard} from './ProfileCard' +import {useStores} from '../../../state' + +export const ProfileMembers = observer(function ProfileMembers({ + name, +}: { + name: string +}) { + const store = useStores() + const [view, setView] = useState<MembersViewModel | undefined>() + + useEffect(() => { + if (view?.params.actor === name) { + console.log('Members doing nothing') + return // no change needed? or trigger refresh? + } + console.log('Fetching members', name) + const newView = new MembersViewModel(store, {actor: name}) + setView(newView) + newView.setup().catch(err => console.error('Failed to fetch members', err)) + }, [name, view?.params.actor, store]) + + // loading + // = + if ( + !view || + (view.isLoading && !view.isRefreshing) || + view.params.actor !== name + ) { + return ( + <View> + <ActivityIndicator /> + </View> + ) + } + + // error + // = + if (view.hasError) { + return ( + <View> + <Text>{view.error}</Text> + </View> + ) + } + + // loaded + // = + const renderItem = ({item}: {item: MemberItem}) => ( + <ProfileCard + did={item.did} + handle={item.handle} + displayName={item.displayName} + /> + ) + return ( + <View> + <FlatList + data={view.members} + keyExtractor={item => item._reactKey} + renderItem={renderItem} + /> + </View> + ) +}) diff --git a/src/view/com/util/Selector.tsx b/src/view/com/util/Selector.tsx index e68310682..06e8cda80 100644 --- a/src/view/com/util/Selector.tsx +++ b/src/view/com/util/Selector.tsx @@ -41,7 +41,7 @@ export function Selector({ width: middle.width, } return [left, middle, right] - }, [selectedIndex, itemLayouts]) + }, [selectedIndex, items, itemLayouts]) const interp = swipeGestureInterp || DEFAULT_SWIPE_GESTURE_INTERP const underlinePos = useAnimatedStyle(() => { |