only show divider when scrolled (#4275)

zio/stable
Samuel Newman 2024-05-30 10:45:35 +03:00 committed by GitHub
parent d92036f2c5
commit cd497a3974
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 54 additions and 19 deletions

View File

@ -9,7 +9,6 @@ import React, {
import { import {
ActivityIndicator, ActivityIndicator,
Keyboard, Keyboard,
ScrollView,
StyleSheet, StyleSheet,
TouchableOpacity, TouchableOpacity,
View, View,
@ -18,6 +17,12 @@ import {
KeyboardAvoidingView, KeyboardAvoidingView,
KeyboardStickyView, KeyboardStickyView,
} from 'react-native-keyboard-controller' } from 'react-native-keyboard-controller'
import Animated, {
interpolateColor,
useAnimatedStyle,
useSharedValue,
withTiming,
} from 'react-native-reanimated'
import {useSafeAreaInsets} from 'react-native-safe-area-context' import {useSafeAreaInsets} from 'react-native-safe-area-context'
import {LinearGradient} from 'expo-linear-gradient' import {LinearGradient} from 'expo-linear-gradient'
import {RichText} from '@atproto/api' import {RichText} from '@atproto/api'
@ -30,6 +35,7 @@ import {
createGIFDescription, createGIFDescription,
parseAltFromGIFDescription, parseAltFromGIFDescription,
} from '#/lib/gif-alt-text' } from '#/lib/gif-alt-text'
import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED'
import {LikelyType} from '#/lib/link-meta/link-meta' import {LikelyType} from '#/lib/link-meta/link-meta'
import {logEvent} from '#/lib/statsig/statsig' import {logEvent} from '#/lib/statsig/statsig'
import {logger} from '#/logger' import {logger} from '#/logger'
@ -61,7 +67,7 @@ import {useDialogStateControlContext} from 'state/dialogs'
import {GalleryModel} from 'state/models/media/gallery' import {GalleryModel} from 'state/models/media/gallery'
import {ComposerOpts} from 'state/shell/composer' import {ComposerOpts} from 'state/shell/composer'
import {ComposerReplyTo} from 'view/com/composer/ComposerReplyTo' import {ComposerReplyTo} from 'view/com/composer/ComposerReplyTo'
import {atoms as a} from '#/alf' import {atoms as a, useTheme} from '#/alf'
import {Button} from '#/components/Button' import {Button} from '#/components/Button'
import {EmojiArc_Stroke2_Corner0_Rounded as EmojiSmile} from '#/components/icons/Emoji' import {EmojiArc_Stroke2_Corner0_Rounded as EmojiSmile} from '#/components/icons/Emoji'
import * as Prompt from '#/components/Prompt' import * as Prompt from '#/components/Prompt'
@ -109,7 +115,7 @@ export const ComposePost = observer(function ComposePost({
const {closeComposer} = useComposerControls() const {closeComposer} = useComposerControls()
const {track} = useAnalytics() const {track} = useAnalytics()
const pal = usePalette('default') const pal = usePalette('default')
const {isDesktop, isMobile} = useWebMediaQueries() const {isTabletOrDesktop, isMobile} = useWebMediaQueries()
const {_} = useLingui() const {_} = useLingui()
const requireAltTextEnabled = useRequireAltTextEnabled() const requireAltTextEnabled = useRequireAltTextEnabled()
const langPrefs = useLanguagePrefs() const langPrefs = useLanguagePrefs()
@ -117,6 +123,7 @@ export const ComposePost = observer(function ComposePost({
const textInput = useRef<TextInputRef>(null) const textInput = useRef<TextInputRef>(null)
const discardPromptControl = Prompt.usePromptControl() const discardPromptControl = Prompt.usePromptControl()
const {closeAllDialogs} = useDialogStateControlContext() const {closeAllDialogs} = useDialogStateControlContext()
const t = useTheme()
const [isKeyboardVisible] = useIsKeyboardVisible({iosUseWillEvents: true}) const [isKeyboardVisible] = useIsKeyboardVisible({iosUseWillEvents: true})
const [isProcessing, setIsProcessing] = useState(false) const [isProcessing, setIsProcessing] = useState(false)
@ -163,6 +170,25 @@ export const ComposePost = observer(function ComposePost({
[insets, isKeyboardVisible, isMobile], [insets, isKeyboardVisible, isMobile],
) )
const hasScrolled = useSharedValue(0)
const scrollHandler = useAnimatedScrollHandler({
onScroll: event => {
hasScrolled.value = withTiming(event.contentOffset.y > 0 ? 1 : 0)
},
})
const topBarAnimatedStyle = useAnimatedStyle(() => {
return {
borderColor: interpolateColor(
hasScrolled.value,
[0, 1],
[
'transparent',
isWeb ? t.palette.contrast_100 : t.palette.contrast_400,
],
),
}
})
const onPressCancel = useCallback(() => { const onPressCancel = useCallback(() => {
if (graphemeLength > 0 || !gallery.isEmpty) { if (graphemeLength > 0 || !gallery.isEmpty) {
closeAllDialogs() closeAllDialogs()
@ -380,7 +406,12 @@ export const ComposePost = observer(function ComposePost({
style={s.flex1} style={s.flex1}
keyboardVerticalOffset={replyTo ? 60 : isAndroid ? 120 : 100}> keyboardVerticalOffset={replyTo ? 60 : isAndroid ? 120 : 100}>
<View style={[s.flex1, viewStyles]} aria-modal accessibilityViewIsModal> <View style={[s.flex1, viewStyles]} aria-modal accessibilityViewIsModal>
<View style={[styles.topbar, isDesktop && styles.topbarDesktop]}> <Animated.View
style={[
styles.topbar,
topBarAnimatedStyle,
isWeb && isTabletOrDesktop && styles.topbarDesktop,
]}>
<TouchableOpacity <TouchableOpacity
testID="composerDiscardButton" testID="composerDiscardButton"
onPress={onPressCancel} onPress={onPressCancel}
@ -444,7 +475,7 @@ export const ComposePost = observer(function ComposePost({
)} )}
</> </>
)} )}
</View> </Animated.View>
{isAltTextRequiredAndMissing && ( {isAltTextRequiredAndMissing && (
<View style={[styles.reminderLine, pal.viewLight]}> <View style={[styles.reminderLine, pal.viewLight]}>
<View style={styles.errorIcon}> <View style={styles.errorIcon}>
@ -471,14 +502,14 @@ export const ComposePost = observer(function ComposePost({
<Text style={[s.red4, s.flex1]}>{error}</Text> <Text style={[s.red4, s.flex1]}>{error}</Text>
</View> </View>
)} )}
<ScrollView <Animated.ScrollView
onScroll={scrollHandler}
style={styles.scrollView} style={styles.scrollView}
keyboardShouldPersistTaps="always"> keyboardShouldPersistTaps="always">
{replyTo ? <ComposerReplyTo replyTo={replyTo} /> : undefined} {replyTo ? <ComposerReplyTo replyTo={replyTo} /> : undefined}
<View <View
style={[ style={[
pal.border,
styles.textInputLayout, styles.textInputLayout,
isNative && styles.textInputLayoutMobile, isNative && styles.textInputLayoutMobile,
]}> ]}>
@ -533,7 +564,7 @@ export const ComposePost = observer(function ComposePost({
)} )}
</View> </View>
) : undefined} ) : undefined}
</ScrollView> </Animated.ScrollView>
<SuggestedLanguage text={richtext.text} /> <SuggestedLanguage text={richtext.text} />
</View> </View>
</KeyboardAvoidingView> </KeyboardAvoidingView>
@ -589,15 +620,18 @@ const styles = StyleSheet.create({
topbar: { topbar: {
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
marginTop: -14, marginTop: -10,
paddingBottom: 4, paddingHorizontal: 4,
paddingHorizontal: 20, marginHorizontal: 16,
height: 50, height: 44,
gap: 4, gap: 4,
borderBottomWidth: StyleSheet.hairlineWidth,
}, },
topbarDesktop: { topbarDesktop: {
paddingTop: 10, paddingTop: 10,
paddingBottom: 10, paddingBottom: 10,
height: 50,
marginTop: 0,
}, },
postBtn: { postBtn: {
borderRadius: 20, borderRadius: 20,
@ -636,11 +670,10 @@ const styles = StyleSheet.create({
}, },
scrollView: { scrollView: {
flex: 1, flex: 1,
paddingHorizontal: 15, paddingHorizontal: 16,
}, },
textInputLayout: { textInputLayout: {
flexDirection: 'row', flexDirection: 'row',
borderTopWidth: 1,
paddingTop: 16, paddingTop: 16,
}, },
textInputLayoutMobile: { textInputLayoutMobile: {

View File

@ -1,14 +1,15 @@
import React from 'react' import React from 'react'
import {Keyboard, StyleSheet} from 'react-native' import {Keyboard, StyleSheet} from 'react-native'
import {Button} from 'view/com/util/forms/Button'
import {usePalette} from 'lib/hooks/usePalette'
import {ShieldExclamation} from 'lib/icons'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {FontAwesomeIconStyle} from '@fortawesome/react-native-fontawesome' import {FontAwesomeIconStyle} from '@fortawesome/react-native-fontawesome'
import {isNative} from 'platform/detection'
import {useLingui} from '@lingui/react'
import {msg} from '@lingui/macro' import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useModalControls} from '#/state/modals' import {useModalControls} from '#/state/modals'
import {usePalette} from 'lib/hooks/usePalette'
import {ShieldExclamation} from 'lib/icons'
import {isNative} from 'platform/detection'
import {Button} from 'view/com/util/forms/Button'
export function LabelsBtn({ export function LabelsBtn({
labels, labels,
@ -54,6 +55,7 @@ const styles = StyleSheet.create({
button: { button: {
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
paddingVertical: 2,
paddingHorizontal: 6, paddingHorizontal: 6,
}, },
dimmed: { dimmed: {