about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/view/com/composer/Composer.tsx61
-rw-r--r--src/view/com/composer/labels/LabelsBtn.tsx12
2 files changed, 54 insertions, 19 deletions
diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx
index 5746454c2..00dbcb591 100644
--- a/src/view/com/composer/Composer.tsx
+++ b/src/view/com/composer/Composer.tsx
@@ -9,7 +9,6 @@ import React, {
 import {
   ActivityIndicator,
   Keyboard,
-  ScrollView,
   StyleSheet,
   TouchableOpacity,
   View,
@@ -18,6 +17,12 @@ import {
   KeyboardAvoidingView,
   KeyboardStickyView,
 } from 'react-native-keyboard-controller'
+import Animated, {
+  interpolateColor,
+  useAnimatedStyle,
+  useSharedValue,
+  withTiming,
+} from 'react-native-reanimated'
 import {useSafeAreaInsets} from 'react-native-safe-area-context'
 import {LinearGradient} from 'expo-linear-gradient'
 import {RichText} from '@atproto/api'
@@ -30,6 +35,7 @@ import {
   createGIFDescription,
   parseAltFromGIFDescription,
 } from '#/lib/gif-alt-text'
+import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED'
 import {LikelyType} from '#/lib/link-meta/link-meta'
 import {logEvent} from '#/lib/statsig/statsig'
 import {logger} from '#/logger'
@@ -61,7 +67,7 @@ import {useDialogStateControlContext} from 'state/dialogs'
 import {GalleryModel} from 'state/models/media/gallery'
 import {ComposerOpts} from 'state/shell/composer'
 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 {EmojiArc_Stroke2_Corner0_Rounded as EmojiSmile} from '#/components/icons/Emoji'
 import * as Prompt from '#/components/Prompt'
@@ -109,7 +115,7 @@ export const ComposePost = observer(function ComposePost({
   const {closeComposer} = useComposerControls()
   const {track} = useAnalytics()
   const pal = usePalette('default')
-  const {isDesktop, isMobile} = useWebMediaQueries()
+  const {isTabletOrDesktop, isMobile} = useWebMediaQueries()
   const {_} = useLingui()
   const requireAltTextEnabled = useRequireAltTextEnabled()
   const langPrefs = useLanguagePrefs()
@@ -117,6 +123,7 @@ export const ComposePost = observer(function ComposePost({
   const textInput = useRef<TextInputRef>(null)
   const discardPromptControl = Prompt.usePromptControl()
   const {closeAllDialogs} = useDialogStateControlContext()
+  const t = useTheme()
 
   const [isKeyboardVisible] = useIsKeyboardVisible({iosUseWillEvents: true})
   const [isProcessing, setIsProcessing] = useState(false)
@@ -163,6 +170,25 @@ export const ComposePost = observer(function ComposePost({
     [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(() => {
     if (graphemeLength > 0 || !gallery.isEmpty) {
       closeAllDialogs()
@@ -380,7 +406,12 @@ export const ComposePost = observer(function ComposePost({
         style={s.flex1}
         keyboardVerticalOffset={replyTo ? 60 : isAndroid ? 120 : 100}>
         <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
               testID="composerDiscardButton"
               onPress={onPressCancel}
@@ -444,7 +475,7 @@ export const ComposePost = observer(function ComposePost({
                 )}
               </>
             )}
-          </View>
+          </Animated.View>
           {isAltTextRequiredAndMissing && (
             <View style={[styles.reminderLine, pal.viewLight]}>
               <View style={styles.errorIcon}>
@@ -471,14 +502,14 @@ export const ComposePost = observer(function ComposePost({
               <Text style={[s.red4, s.flex1]}>{error}</Text>
             </View>
           )}
-          <ScrollView
+          <Animated.ScrollView
+            onScroll={scrollHandler}
             style={styles.scrollView}
             keyboardShouldPersistTaps="always">
             {replyTo ? <ComposerReplyTo replyTo={replyTo} /> : undefined}
 
             <View
               style={[
-                pal.border,
                 styles.textInputLayout,
                 isNative && styles.textInputLayoutMobile,
               ]}>
@@ -533,7 +564,7 @@ export const ComposePost = observer(function ComposePost({
                 )}
               </View>
             ) : undefined}
-          </ScrollView>
+          </Animated.ScrollView>
           <SuggestedLanguage text={richtext.text} />
         </View>
       </KeyboardAvoidingView>
@@ -589,15 +620,18 @@ const styles = StyleSheet.create({
   topbar: {
     flexDirection: 'row',
     alignItems: 'center',
-    marginTop: -14,
-    paddingBottom: 4,
-    paddingHorizontal: 20,
-    height: 50,
+    marginTop: -10,
+    paddingHorizontal: 4,
+    marginHorizontal: 16,
+    height: 44,
     gap: 4,
+    borderBottomWidth: StyleSheet.hairlineWidth,
   },
   topbarDesktop: {
     paddingTop: 10,
     paddingBottom: 10,
+    height: 50,
+    marginTop: 0,
   },
   postBtn: {
     borderRadius: 20,
@@ -636,11 +670,10 @@ const styles = StyleSheet.create({
   },
   scrollView: {
     flex: 1,
-    paddingHorizontal: 15,
+    paddingHorizontal: 16,
   },
   textInputLayout: {
     flexDirection: 'row',
-    borderTopWidth: 1,
     paddingTop: 16,
   },
   textInputLayoutMobile: {
diff --git a/src/view/com/composer/labels/LabelsBtn.tsx b/src/view/com/composer/labels/LabelsBtn.tsx
index b880dd330..27e3813dc 100644
--- a/src/view/com/composer/labels/LabelsBtn.tsx
+++ b/src/view/com/composer/labels/LabelsBtn.tsx
@@ -1,14 +1,15 @@
 import React from 'react'
 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 {FontAwesomeIconStyle} from '@fortawesome/react-native-fontawesome'
-import {isNative} from 'platform/detection'
-import {useLingui} from '@lingui/react'
 import {msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+
 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({
   labels,
@@ -54,6 +55,7 @@ const styles = StyleSheet.create({
   button: {
     flexDirection: 'row',
     alignItems: 'center',
+    paddingVertical: 2,
     paddingHorizontal: 6,
   },
   dimmed: {