Skip to content

Commit

Permalink
Move FollowButton component to profile header
Browse files Browse the repository at this point in the history
- Button component with optional start/end icon elements
- Suggested follows icon's dark mode color adjusted in ProfileHeader
  • Loading branch information
tarikfp committed Nov 7, 2023
1 parent 5c6b536 commit 2b6197e
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 49 deletions.
31 changes: 24 additions & 7 deletions src/view/com/profile/FollowButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,29 @@ import {Button, ButtonType} from '../util/forms/Button'
import * as Toast from '../util/Toast'
import {FollowState} from 'state/models/cache/my-follows'
import {useFollowProfile} from 'lib/hooks/useFollowProfile'
import {s} from '#/lib/styles'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {usePalette} from '#/lib/hooks/usePalette'

type Props = {
unfollowedType?: ButtonType
followedType?: ButtonType
profile: AppBskyActorDefs.ProfileViewBasic
onToggleFollow?: (v: boolean) => void
labelStyle?: StyleProp<TextStyle>
} & React.ComponentProps<typeof Button>

export const FollowButton = observer(function FollowButtonImpl({
unfollowedType = 'inverted',
followedType = 'default',
profile,
onToggleFollow,
labelStyle,
}: {
unfollowedType?: ButtonType
followedType?: ButtonType
profile: AppBskyActorDefs.ProfileViewBasic
onToggleFollow?: (v: boolean) => void
labelStyle?: StyleProp<TextStyle>
}) {
...rest
}: Props) {
const pal = usePalette('default')
const palInverted = usePalette('inverted')

const {state, following, toggle} = useFollowProfile(profile)

const onPress = React.useCallback(async () => {
Expand All @@ -37,11 +46,19 @@ export const FollowButton = observer(function FollowButtonImpl({

return (
<Button
StartIcon={
following ? (
<FontAwesomeIcon icon="check" style={[pal.text, s.mr2]} size={14} />
) : (
<FontAwesomeIcon icon="plus" style={[palInverted.text, s.mr2]} />
)
}
type={following ? followedType : unfollowedType}
labelStyle={labelStyle}
onPress={onPress}
label={following ? 'Unfollow' : 'Follow'}
withLoading={true}
{...rest}
/>
)
})
57 changes: 20 additions & 37 deletions src/view/com/profile/ProfileHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {makeProfileLink} from 'lib/routes/links'
import {Link} from '../util/Link'
import {ProfileHeaderSuggestedFollows} from './ProfileHeaderSuggestedFollows'
import {logger} from '#/logger'
import {FollowButton} from './FollowButton'

interface Props {
view: ProfileModel
Expand Down Expand Up @@ -111,7 +112,6 @@ const ProfileHeaderLoaded = observer(function ProfileHeaderLoadedImpl({
isProfilePreview,
}: Props) {
const pal = usePalette('default')
const palInverted = usePalette('inverted')
const store = useStores()
const navigation = useNavigation<NavigationProp>()
const {track} = useAnalytics()
Expand Down Expand Up @@ -355,6 +355,8 @@ const ProfileHeaderLoaded = observer(function ProfileHeaderLoadedImpl({
const following = formatCount(view.followsCount)
const followers = formatCount(view.followersCount)
const pluralizedFollowers = pluralize(view.followersCount, 'follower')
const isFollowing =
store.me.follows.getFollowState(view.did) === FollowState.Following

return (
<View style={pal.view}>
Expand Down Expand Up @@ -413,7 +415,7 @@ const ProfileHeaderLoaded = observer(function ProfileHeaderLoadedImpl({
pal.text,
{
color: showSuggestedFollows
? colors.white
? pal.textInverted.color
: pal.text.color,
},
]}
Expand All @@ -422,41 +424,22 @@ const ProfileHeaderLoaded = observer(function ProfileHeaderLoadedImpl({
</TouchableOpacity>
)}

{store.me.follows.getFollowState(view.did) ===
FollowState.Following ? (
<TouchableOpacity
testID="unfollowBtn"
onPress={onPressToggleFollow}
style={[styles.btn, styles.mainBtn, pal.btn]}
accessibilityRole="button"
accessibilityLabel={`Unfollow ${view.handle}`}
accessibilityHint={`Hides posts from ${view.handle} in your feed`}>
<FontAwesomeIcon
icon="check"
style={[pal.text, s.mr5]}
size={14}
/>
<Text type="button" style={pal.text}>
Following
</Text>
</TouchableOpacity>
) : (
<TouchableOpacity
testID="followBtn"
onPress={onPressToggleFollow}
style={[styles.btn, styles.mainBtn, palInverted.view]}
accessibilityRole="button"
accessibilityLabel={`Follow ${view.handle}`}
accessibilityHint={`Shows posts from ${view.handle} in your feed`}>
<FontAwesomeIcon
icon="plus"
style={[palInverted.text, s.mr5]}
/>
<Text type="button" style={[palInverted.text, s.bold]}>
Follow
</Text>
</TouchableOpacity>
)}
<FollowButton
style={styles.btn}
testID={isFollowing ? 'unfollowBtn' : 'followBtn'}
unfollowedType="inverted"
profile={view}
accessibilityHint={
isFollowing
? `Hides posts from ${view.handle} in your feed`
: `Shows posts from ${view.handle} in your feed`
}
accessibilityLabel={`${isFollowing ? 'Unfollow' : 'Follow'} ${
view.handle
}`}
onToggleFollow={onPressToggleFollow}
followedType="default"
/>
</>
) : null}
{dropdownItems?.length ? (
Expand Down
27 changes: 22 additions & 5 deletions src/view/com/util/forms/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
import {Text} from '../text/Text'
import {useTheme} from 'lib/ThemeContext'
import {choose} from 'lib/functions'
import {s} from '#/lib/styles'

type Event =
| React.MouseEvent<HTMLAnchorElement, MouseEvent>
Expand Down Expand Up @@ -42,6 +43,8 @@ export function Button({
type = 'primary',
label,
style,
StartIcon,
EndIcon,
labelContainerStyle,
labelStyle,
onPress,
Expand All @@ -56,6 +59,8 @@ export function Button({
type?: ButtonType
label?: string
style?: StyleProp<ViewStyle>
StartIcon?: React.ReactElement
EndIcon?: React.ReactElement
labelContainerStyle?: StyleProp<ViewStyle>
labelStyle?: StyleProp<TextStyle>
onPress?: () => void | Promise<void>
Expand Down Expand Up @@ -169,29 +174,40 @@ export function Button({
[typeOuterStyle, style],
)

const renderChildern = React.useCallback(() => {
const renderChildren = React.useCallback(() => {
if (!label) {
return children
}

return (
<View style={[styles.labelContainer, labelContainerStyle]}>
{React.isValidElement(StartIcon) && !isLoading ? StartIcon : null}

{label && withLoading && isLoading ? (
<ActivityIndicator size={12} color={typeLabelStyle.color} />
<ActivityIndicator
style={s.mr2}
size={12}
color={typeLabelStyle.color}
/>
) : null}

<Text type="button" style={[typeLabelStyle, labelStyle]}>
{label}
</Text>

{React.isValidElement(EndIcon) && !isLoading && EndIcon}
</View>
)
}, [
children,
label,
labelContainerStyle,
StartIcon,
withLoading,
isLoading,
labelContainerStyle,
typeLabelStyle,
labelStyle,
EndIcon,
children,
])

return (
Expand All @@ -205,7 +221,7 @@ export function Button({
accessibilityHint={accessibilityHint}
accessibilityLabelledBy={accessibilityLabelledBy}
onAccessibilityEscape={onAccessibilityEscape}>
{renderChildern}
{renderChildren}
</Pressable>
)
}
Expand All @@ -217,6 +233,7 @@ const styles = StyleSheet.create({
borderRadius: 24,
},
labelContainer: {
alignItems: 'center',
flexDirection: 'row',
gap: 8,
},
Expand Down

0 comments on commit 2b6197e

Please sign in to comment.