Use ALF for post controls (#3400)

* alf the repost dropdown on web + import icons

* alf like icon

* convert other post controls

* add missing padding to share button

* refine buttons and use better icons

* revert buttonicon changes

* remove ButtonIcon and ButtonText from repost dialog

* use 15px font size when not big

* reduce size and use contrast_25

* add hover state to logged out view

* add `userSelect: 'none'` to buttons

* use width rather than height

* fix quote close behaviour

* prettier

* Fix Esc on repost

* Use new icons for placeholder

* Fix placeholder

---------

Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
This commit is contained in:
Samuel Newman 2024-05-30 03:25:11 +03:00 committed by GitHub
parent 4d39ef2e19
commit 165feedb86
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 376 additions and 285 deletions

View file

@ -1,10 +1,10 @@
import React, {memo, useCallback} from 'react'
import {
StyleProp,
StyleSheet,
TouchableOpacity,
Pressable,
type PressableStateCallbackType,
type StyleProp,
View,
ViewStyle,
type ViewStyle,
} from 'react-native'
import {
AppBskyFeedDefs,
@ -16,12 +16,11 @@ import {msg, plural} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {HITSLOP_10, HITSLOP_20} from '#/lib/constants'
import {CommentBottomArrow, HeartIcon, HeartIconSolid} from '#/lib/icons'
import {useHaptics} from '#/lib/haptics'
import {makeProfileLink} from '#/lib/routes/links'
import {shareUrl} from '#/lib/sharing'
import {toShareUrl} from '#/lib/strings/url-helpers'
import {s} from '#/lib/styles'
import {useTheme} from '#/lib/ThemeContext'
import {Shadow} from '#/state/cache/types'
import {useFeedFeedbackContext} from '#/state/feed-feedback'
import {useModalControls} from '#/state/modals'
@ -31,9 +30,14 @@ import {
} from '#/state/queries/post'
import {useRequireAuth} from '#/state/session'
import {useComposerControls} from '#/state/shell/composer'
import {useHaptics} from 'lib/haptics'
import {atoms as a, useTheme} from '#/alf'
import {useDialogControl} from '#/components/Dialog'
import {ArrowOutOfBox_Stroke2_Corner0_Rounded as ArrowOutOfBox} from '#/components/icons/ArrowOutOfBox'
import {Bubble_Stroke2_Corner2_Rounded as Bubble} from '#/components/icons/Bubble'
import {
Heart2_Filled_Stroke2_Corner0_Rounded as HeartIconFilled,
Heart2_Stroke2_Corner0_Rounded as HeartIconOutline,
} from '#/components/icons/Heart2'
import * as Prompt from '#/components/Prompt'
import {PostDropdownBtn} from '../forms/PostDropdownBtn'
import {Text} from '../text/Text'
@ -58,7 +62,7 @@ let PostCtrls = ({
onPressReply: () => void
logContext: 'FeedItem' | 'PostThreadItem' | 'Post'
}): React.ReactNode => {
const theme = useTheme()
const t = useTheme()
const {_} = useLingui()
const {openComposer} = useComposerControls()
const {closeModal} = useModalControls()
@ -80,9 +84,9 @@ let PostCtrls = ({
const defaultCtrlColor = React.useMemo(
() => ({
color: theme.palette.default.postCtrl,
color: t.palette.contrast_500,
}),
[theme],
[t],
) as StyleProp<ViewStyle>
const onPressToggleLike = React.useCallback(async () => {
@ -185,57 +189,70 @@ let PostCtrls = ({
})
}, [post.uri, post.author, sendInteraction, feedContext])
const btnStyle = React.useCallback(
({pressed, hovered}: PressableStateCallbackType) => [
a.gap_xs,
a.rounded_full,
a.flex_row,
a.align_center,
a.justify_center,
{padding: 5},
(pressed || hovered) && t.atoms.bg_contrast_25,
],
[t.atoms.bg_contrast_25],
)
return (
<View style={[styles.ctrls, style]}>
<View style={[a.flex_row, a.justify_between, a.align_center, style]}>
<View
style={[
big ? styles.ctrlBig : styles.ctrl,
big ? a.align_center : [a.flex_1, a.align_start, {marginLeft: -5}],
post.viewer?.replyDisabled ? {opacity: 0.5} : undefined,
]}>
<TouchableOpacity
<Pressable
testID="replyBtn"
style={[styles.btn, !big && styles.btnPad, {paddingLeft: 0}]}
style={btnStyle}
onPress={() => {
if (!post.viewer?.replyDisabled) {
requireAuth(() => onPressReply())
}
}}
accessibilityRole="button"
accessibilityLabel={plural(post.replyCount || 0, {
one: 'Reply (# reply)',
other: 'Reply (# replies)',
})}
accessibilityHint=""
hitSlop={big ? HITSLOP_20 : HITSLOP_10}>
<CommentBottomArrow
style={[defaultCtrlColor, big ? s.mt2 : styles.mt1]}
strokeWidth={3}
size={big ? 20 : 15}
<Bubble
style={[defaultCtrlColor, {pointerEvents: 'none'}]}
width={big ? 22 : 18}
/>
{typeof post.replyCount !== 'undefined' && post.replyCount > 0 ? (
<Text style={[defaultCtrlColor, s.ml5, s.f15]}>
<Text
style={[
defaultCtrlColor,
big ? a.text_md : {fontSize: 15},
a.user_select_none,
]}>
{post.replyCount}
</Text>
) : undefined}
</TouchableOpacity>
</Pressable>
</View>
<View style={big ? styles.ctrlBig : styles.ctrl}>
<View style={big ? a.align_center : [a.flex_1, a.align_start]}>
<RepostButton
big={big}
isReposted={!!post.viewer?.repost}
repostCount={post.repostCount}
onRepost={onRepost}
onQuote={onQuote}
big={big}
/>
</View>
<View style={big ? styles.ctrlBig : styles.ctrl}>
<TouchableOpacity
<View style={big ? a.align_center : [a.flex_1, a.align_start]}>
<Pressable
testID="likeBtn"
style={[styles.btn, !big && styles.btnPad]}
onPress={() => {
requireAuth(() => onPressToggleLike())
}}
accessibilityRole="button"
style={btnStyle}
onPress={() => requireAuth(() => onPressToggleLike())}
accessibilityLabel={
post.viewer?.like
? plural(post.likeCount || 0, {
@ -250,33 +267,36 @@ let PostCtrls = ({
accessibilityHint=""
hitSlop={big ? HITSLOP_20 : HITSLOP_10}>
{post.viewer?.like ? (
<HeartIconSolid style={s.likeColor} size={big ? 22 : 16} />
<HeartIconFilled style={s.likeColor} width={big ? 22 : 18} />
) : (
<HeartIcon
style={[defaultCtrlColor, big ? styles.mt1 : undefined]}
strokeWidth={3}
size={big ? 20 : 16}
<HeartIconOutline
style={[defaultCtrlColor, {pointerEvents: 'none'}]}
width={big ? 22 : 18}
/>
)}
{typeof post.likeCount !== 'undefined' && post.likeCount > 0 ? (
<Text
testID="likeCount"
style={
post.viewer?.like
? [s.bold, s.likeColor, s.f15, s.ml5]
: [defaultCtrlColor, s.f15, s.ml5]
}>
style={[
[
big ? a.text_md : {fontSize: 15},
a.user_select_none,
post.viewer?.like
? [a.font_bold, s.likeColor]
: defaultCtrlColor,
],
]}>
{post.likeCount}
</Text>
) : undefined}
</TouchableOpacity>
</Pressable>
</View>
{big && (
<>
<View style={styles.ctrlBig}>
<TouchableOpacity
<View style={a.align_center}>
<Pressable
testID="shareBtn"
style={[styles.btn]}
style={btnStyle}
onPress={() => {
if (shouldShowLoggedOutWarning) {
loggedOutWarningPromptControl.open()
@ -284,15 +304,14 @@ let PostCtrls = ({
onShare()
}
}}
accessibilityRole="button"
accessibilityLabel={`${_(msg`Share`)}`}
accessibilityLabel={_(msg`Share`)}
accessibilityHint=""
hitSlop={big ? HITSLOP_20 : HITSLOP_10}>
<ArrowOutOfBox
style={[defaultCtrlColor, styles.mt1]}
style={[defaultCtrlColor, {pointerEvents: 'none'}]}
width={22}
/>
</TouchableOpacity>
</Pressable>
</View>
<Prompt.Basic
control={loggedOutWarningPromptControl}
@ -305,7 +324,7 @@ let PostCtrls = ({
/>
</>
)}
<View style={big ? styles.ctrlBig : styles.ctrl}>
<View style={big ? a.align_center : [a.flex_1, a.align_start]}>
<PostDropdownBtn
testID="postDropdownBtn"
postAuthor={post.author}
@ -314,7 +333,7 @@ let PostCtrls = ({
postFeedContext={feedContext}
record={record}
richText={richText}
style={styles.btnPad}
style={{padding: 5}}
hitSlop={big ? HITSLOP_20 : HITSLOP_10}
timestamp={post.indexedAt}
/>
@ -324,31 +343,3 @@ let PostCtrls = ({
}
PostCtrls = memo(PostCtrls)
export {PostCtrls}
const styles = StyleSheet.create({
ctrls: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
ctrl: {
flex: 1,
alignItems: 'flex-start',
},
ctrlBig: {
alignItems: 'center',
},
btn: {
flexDirection: 'row',
alignItems: 'center',
},
btnPad: {
paddingTop: 5,
paddingBottom: 5,
paddingLeft: 5,
paddingRight: 5,
},
mt1: {
marginTop: 1,
},
})