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:
parent
4d39ef2e19
commit
165feedb86
17 changed files with 376 additions and 285 deletions
|
|
@ -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,
|
||||
},
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue