merge in main

This commit is contained in:
Hailey
2024-06-06 14:17:54 -07:00
17 changed files with 134 additions and 161 deletions
@@ -15,8 +15,24 @@ export function SendViaChatDialog({
control: Dialog.DialogControlProps
onSelectChat: (chatId: string) => void
}) {
const {_} = useLingui()
return (
<Dialog.Outer
control={control}
testID="sendViaChatChatDialog"
nativeOptions={{sheet: {snapPoints: ['100%']}}}>
<SendViaChatDialogInner control={control} onSelectChat={onSelectChat} />
</Dialog.Outer>
)
}
function SendViaChatDialogInner({
control,
onSelectChat,
}: {
control: Dialog.DialogControlProps
onSelectChat: (chatId: string) => void
}) {
const {_} = useLingui()
const {mutate: createChat} = useGetConvoForMembers({
onSuccess: data => {
onSelectChat(data.convo.id)
@@ -39,15 +55,10 @@ export function SendViaChatDialog({
)
return (
<Dialog.Outer
control={control}
testID="sendViaChatChatDialog"
nativeOptions={{sheet: {snapPoints: ['100%']}}}>
<SearchablePeopleList
title={_(msg`Send post to...`)}
onSelectChat={onCreateChat}
showRecentConvos
/>
</Dialog.Outer>
<SearchablePeopleList
title={_(msg`Send post to...`)}
onSelectChat={onCreateChat}
showRecentConvos
/>
)
}
+3 -1
View File
@@ -3,8 +3,9 @@ import {
launchImageLibraryAsync,
MediaTypeOptions,
} from 'expo-image-picker'
import {getDataUriSize} from './util'
import * as Toast from 'view/com/util/Toast'
import {getDataUriSize} from './util'
export async function openPicker(opts?: ImagePickerOptions) {
const response = await launchImageLibraryAsync({
@@ -12,6 +13,7 @@ export async function openPicker(opts?: ImagePickerOptions) {
mediaTypes: MediaTypeOptions.Images,
quality: 1,
...opts,
legacy: true,
})
if (response.assets && response.assets.length > 4) {
+1
View File
@@ -3,4 +3,5 @@ export type Gate =
| 'request_notifications_permission_after_onboarding_v2'
| 'show_avi_follow_button'
| 'show_follow_back_label_v2'
| 'show_notification_badge_mobile_web'
| 'starter_packs_enabled'
@@ -102,6 +102,7 @@ export function StepProfile() {
mediaTypes: MediaTypeOptions.Images,
quality: 1,
...opts,
legacy: true,
})
return (response.assets ?? [])
+6 -5
View File
@@ -1,9 +1,9 @@
import React from 'react'
import {
Easing,
cancelAnimation,
SharedValue,
useSharedValue,
withTiming,
withSpring,
} from 'react-native-reanimated'
type StateContext = SharedValue<number>
@@ -22,9 +22,10 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
const setMode = React.useCallback(
(v: boolean) => {
'worklet'
mode.value = withTiming(v ? 1 : 0, {
duration: 400,
easing: Easing.bezier(0.25, 0.1, 0.25, 1),
// Cancel any existing animation
cancelAnimation(mode)
mode.value = withSpring(v ? 1 : 0, {
overshootClamping: true,
})
},
[mode],
+8 -10
View File
@@ -107,7 +107,9 @@ export const ComposePost = observer(function ComposePost({
text: initText,
imageUris: initImageUris,
cancelRef,
isModalReady,
}: Props & {
isModalReady: boolean
cancelRef?: React.RefObject<CancelRef>
}) {
const {currentAccount} = useSession()
@@ -155,12 +157,6 @@ export const ComposePost = observer(function ComposePost({
const [labels, setLabels] = useState<string[]>([])
const [threadgate, setThreadgate] = useState<ThreadgateSetting[]>([])
React.useEffect(() => {
if (!isAndroid) return
const id = setTimeout(() => textInput.current?.focus(), 100)
return () => clearTimeout(id)
}, [])
const gallery = useMemo(
() => new GalleryModel(initImageUris),
[initImageUris],
@@ -181,9 +177,7 @@ export const ComposePost = observer(function ComposePost({
const onPressCancel = useCallback(() => {
if (graphemeLength > 0 || !gallery.isEmpty || extGif) {
closeAllDialogs()
if (Keyboard) {
Keyboard.dismiss()
}
Keyboard.dismiss()
discardPromptControl.open()
} else {
onClose()
@@ -524,7 +518,11 @@ export const ComposePost = observer(function ComposePost({
ref={textInput}
richtext={richtext}
placeholder={selectTextInputPlaceholder}
autoFocus={!isAndroid}
// fixes autofocus on android
key={
isAndroid ? (isModalReady ? 'ready' : 'animating') : 'static'
}
autoFocus={isAndroid ? isModalReady : true}
setRichText={setRichText}
onPhotoPasted={onPhotoPasted}
onPressPublish={onPressPublish}
@@ -1,30 +1,36 @@
import React, {useState} from 'react'
import {ActivityIndicator, Dimensions, StyleSheet} from 'react-native'
import {Image} from 'expo-image'
import {Gesture, GestureDetector} from 'react-native-gesture-handler'
import Animated, {
runOnJS,
useAnimatedReaction,
useAnimatedRef,
useAnimatedStyle,
useAnimatedReaction,
useSharedValue,
withDecay,
withSpring,
} from 'react-native-reanimated'
import {GestureDetector, Gesture} from 'react-native-gesture-handler'
import {Image} from 'expo-image'
import type {Dimensions as ImageDimensions, ImageSource} from '../../@types'
import useImageDimensions from '../../hooks/useImageDimensions'
import {
createTransform,
readTransform,
applyRounding,
createTransform,
prependPan,
prependPinch,
prependTransform,
readTransform,
TransformMatrix,
} from '../../transforms'
import type {ImageSource, Dimensions as ImageDimensions} from '../../@types'
const SCREEN = Dimensions.get('window')
const windowDim = Dimensions.get('window')
const screenDim = Dimensions.get('screen')
const statusBarHeight = windowDim.height - screenDim.height
const SCREEN = {
width: windowDim.width,
height: windowDim.height + statusBarHeight,
}
const MIN_DOUBLE_TAP_SCALE = 2
const MAX_ORIGINAL_IMAGE_ZOOM = 2
+7 -1
View File
@@ -1,6 +1,10 @@
import React, {useCallback, useEffect} from 'react'
import {NativeScrollEvent} from 'react-native'
import {interpolate, useSharedValue} from 'react-native-reanimated'
import {
cancelAnimation,
interpolate,
useSharedValue,
} from 'react-native-reanimated'
import EventEmitter from 'eventemitter3'
import {ScrollProvider} from '#/lib/ScrollContext'
@@ -117,6 +121,8 @@ export function MainScrollProvider({children}: {children: React.ReactNode}) {
const newValue = clamp(startMode.value + dProgress, 0, 1)
if (newValue !== mode.value) {
// Manually adjust the value. This won't be (and shouldn't be) animated.
// Cancel any any existing animation
cancelAnimation(mode)
mode.value = newValue
}
} else {
+11 -1
View File
@@ -1,4 +1,4 @@
import React, {useLayoutEffect} from 'react'
import React, {useLayoutEffect, useState} from 'react'
import {Modal, View} from 'react-native'
import {GestureHandlerRootView} from 'react-native-gesture-handler'
import {RootSiblingParent} from 'react-native-root-siblings'
@@ -24,8 +24,16 @@ export const Composer = observer(function ComposerImpl({}: {
const t = useTheme()
const state = useComposerState()
const ref = useComposerCancelRef()
const [isModalReady, setIsModalReady] = useState(false)
const open = !!state
const [prevOpen, setPrevOpen] = useState(open)
if (open !== prevOpen) {
setPrevOpen(open)
if (!open) {
setIsModalReady(false)
}
}
return (
<Modal
@@ -34,10 +42,12 @@ export const Composer = observer(function ComposerImpl({}: {
visible={open}
presentationStyle="formSheet"
animationType="slide"
onShow={() => setIsModalReady(true)}
onRequestClose={() => ref.current?.onPressCancel()}>
<View style={[t.atoms.bg, a.flex_1]}>
<Providers open={open}>
<ComposePost
isModalReady={isModalReady}
cancelRef={ref}
replyTo={state?.replyTo}
onPost={state?.onPost}
+1
View File
@@ -56,6 +56,7 @@ export function Composer({}: {winHeight: number}) {
t.atoms.border_contrast_medium,
]}>
<ComposePost
isModalReady={true}
replyTo={state.replyTo}
quote={state.quote}
onPost={state.onPost}
+35 -8
View File
@@ -16,6 +16,9 @@ import {s} from '#/lib/styles'
import {useSession} from '#/state/session'
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
import {useCloseAllActiveElements} from '#/state/util'
import {useGate} from 'lib/statsig/statsig'
import {useUnreadMessageCount} from 'state/queries/messages/list-converations'
import {useUnreadNotifications} from 'state/queries/notifications/unread'
import {Button} from '#/view/com/util/forms/Button'
import {Text} from '#/view/com/util/text/Text'
import {Logo} from '#/view/icons/Logo'
@@ -46,11 +49,15 @@ export function BottomBarWeb() {
const {hasSession, currentAccount} = useSession()
const pal = usePalette('default')
const safeAreaInsets = useSafeAreaInsets()
const gate = useGate()
const {footerMinimalShellTransform} = useMinimalShellMode()
const {requestSwitchToAccount} = useLoggedOutViewControls()
const closeAllActiveElements = useCloseAllActiveElements()
const iconWidth = 26
const unreadMessageCount = useUnreadMessageCount()
const notificationCountStr = useUnreadNotifications()
const showSignIn = React.useCallback(() => {
closeAllActiveElements()
requestSwitchToAccount({requestedAccount: 'none'})
@@ -103,10 +110,20 @@ export function BottomBarWeb() {
{({isActive}) => {
const Icon = isActive ? MessageFilled : Message
return (
<Icon
width={iconWidth - 1}
style={[styles.ctrlIcon, pal.text, styles.messagesIcon]}
/>
<>
<Icon
width={iconWidth - 1}
style={[styles.ctrlIcon, pal.text, styles.messagesIcon]}
/>
{unreadMessageCount.count > 0 &&
gate('show_notification_badge_mobile_web') && (
<View style={styles.notificationCount}>
<Text style={styles.notificationCountLabel}>
{unreadMessageCount.numUnread}
</Text>
</View>
)}
</>
)
}}
</NavItem>
@@ -114,10 +131,20 @@ export function BottomBarWeb() {
{({isActive}) => {
const Icon = isActive ? BellFilled : Bell
return (
<Icon
width={iconWidth}
style={[styles.ctrlIcon, pal.text, styles.bellIcon]}
/>
<>
<Icon
width={iconWidth}
style={[styles.ctrlIcon, pal.text, styles.bellIcon]}
/>
{notificationCountStr !== '' &&
gate('show_notification_badge_mobile_web') && (
<View style={styles.notificationCount}>
<Text style={styles.notificationCountLabel}>
{notificationCountStr}
</Text>
</View>
)}
</>
)
}}
</NavItem>