Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Improve style of reply bar (#5447)

Co-authored-by: Samuel Newman <mozzius@protonmail.com>

authored by

Hailey
Samuel Newman
and committed by
GitHub
be3c6ab9 2296ea33

+107 -41
+53
src/lib/custom-animations/PressableScale.tsx
··· 1 + import React from 'react' 2 + import {Pressable, PressableProps} from 'react-native' 3 + import Animated, { 4 + cancelAnimation, 5 + runOnJS, 6 + useAnimatedStyle, 7 + useSharedValue, 8 + withTiming, 9 + } from 'react-native-reanimated' 10 + 11 + import {isTouchDevice} from '#/lib/browser' 12 + import {isNative} from '#/platform/detection' 13 + 14 + const DEFAULT_TARGET_SCALE = isNative || isTouchDevice ? 0.98 : 1 15 + 16 + export function PressableScale({ 17 + targetScale = DEFAULT_TARGET_SCALE, 18 + children, 19 + ...rest 20 + }: {targetScale?: number} & Exclude< 21 + PressableProps, 22 + 'onPressIn' | 'onPressOut' 23 + >) { 24 + const scale = useSharedValue(1) 25 + 26 + const style = useAnimatedStyle(() => ({ 27 + transform: [{scale: scale.value}], 28 + })) 29 + 30 + return ( 31 + <Pressable 32 + accessibilityRole="button" 33 + onPressIn={e => { 34 + 'worklet' 35 + if (rest.onPressIn) { 36 + runOnJS(rest.onPressIn)(e) 37 + } 38 + cancelAnimation(scale) 39 + scale.value = withTiming(targetScale, {duration: 100}) 40 + }} 41 + onPressOut={e => { 42 + 'worklet' 43 + if (rest.onPressOut) { 44 + runOnJS(rest.onPressOut)(e) 45 + } 46 + cancelAnimation(scale) 47 + scale.value = withTiming(1, {duration: 100}) 48 + }} 49 + {...rest}> 50 + <Animated.View style={style}>{children as React.ReactNode}</Animated.View> 51 + </Pressable> 52 + ) 53 + }
+54 -41
src/view/com/post-thread/PostThreadComposePrompt.tsx
··· 1 1 import React from 'react' 2 - import {StyleSheet, TouchableOpacity} from 'react-native' 2 + import {View} from 'react-native' 3 3 import {msg, Trans} from '@lingui/macro' 4 4 import {useLingui} from '@lingui/react' 5 5 6 + import {PressableScale} from '#/lib/custom-animations/PressableScale' 7 + import {useHaptics} from '#/lib/haptics' 8 + import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' 9 + import {useHapticsDisabled} from '#/state/preferences' 6 10 import {useProfileQuery} from '#/state/queries/profile' 7 11 import {useSession} from '#/state/session' 8 - import {usePalette} from 'lib/hooks/usePalette' 9 - import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' 10 - import {Text} from '../util/text/Text' 11 - import {UserAvatar} from '../util/UserAvatar' 12 + import {UserAvatar} from '#/view/com/util/UserAvatar' 13 + import {atoms as a, useTheme} from '#/alf' 14 + import {Text} from '#/components/Typography' 12 15 13 16 export function PostThreadComposePrompt({ 14 17 onPressCompose, ··· 17 20 }) { 18 21 const {currentAccount} = useSession() 19 22 const {data: profile} = useProfileQuery({did: currentAccount?.did}) 20 - const pal = usePalette('default') 21 23 const {_} = useLingui() 22 - const {isDesktop} = useWebMediaQueries() 24 + const {isTabletOrDesktop} = useWebMediaQueries() 25 + const t = useTheme() 26 + const playHaptics = useHaptics() 27 + const isHapticsDisabled = useHapticsDisabled() 28 + 29 + const onPress = () => { 30 + playHaptics('Light') 31 + setTimeout( 32 + () => { 33 + onPressCompose() 34 + }, 35 + isHapticsDisabled ? 0 : 75, 36 + ) 37 + } 38 + 23 39 return ( 24 - <TouchableOpacity 25 - testID="replyPromptBtn" 26 - style={[pal.view, pal.border, styles.prompt]} 27 - onPress={() => onPressCompose()} 40 + <PressableScale 28 41 accessibilityRole="button" 29 42 accessibilityLabel={_(msg`Compose reply`)} 30 - accessibilityHint={_(msg`Opens composer`)}> 31 - <UserAvatar 32 - avatar={profile?.avatar} 33 - size={38} 34 - type={profile?.associated?.labeler ? 'labeler' : 'user'} 35 - /> 36 - <Text 37 - type="xl" 43 + accessibilityHint={_(msg`Opens composer`)} 44 + style={[ 45 + {paddingTop: 8, paddingBottom: isTabletOrDesktop ? 8 : 11}, 46 + a.px_sm, 47 + a.border_t, 48 + t.atoms.border_contrast_low, 49 + t.atoms.bg, 50 + ]} 51 + onPress={onPress}> 52 + <View 38 53 style={[ 39 - pal.text, 40 - isDesktop ? styles.labelDesktopWeb : styles.labelMobile, 54 + a.flex_row, 55 + a.align_center, 56 + a.p_sm, 57 + a.gap_sm, 58 + a.rounded_full, 59 + t.atoms.bg_contrast_25, 41 60 ]}> 42 - <Trans>Write your reply</Trans> 43 - </Text> 44 - </TouchableOpacity> 61 + <UserAvatar 62 + size={22} 63 + avatar={profile?.avatar} 64 + type={profile?.associated?.labeler ? 'labeler' : 'user'} 65 + /> 66 + <Text 67 + style={[ 68 + isTabletOrDesktop ? a.text_md : a.text_sm, 69 + t.atoms.text_contrast_medium, 70 + ]}> 71 + <Trans>Write your reply</Trans> 72 + </Text> 73 + </View> 74 + </PressableScale> 45 75 ) 46 76 } 47 - 48 - const styles = StyleSheet.create({ 49 - prompt: { 50 - paddingHorizontal: 16, 51 - paddingTop: 10, 52 - paddingBottom: 10, 53 - flexDirection: 'row', 54 - alignItems: 'center', 55 - borderTopWidth: StyleSheet.hairlineWidth, 56 - }, 57 - labelMobile: { 58 - paddingLeft: 12, 59 - }, 60 - labelDesktopWeb: { 61 - paddingLeft: 12, 62 - }, 63 - })