Scope fluid zoom transition to alt text dialog only
Revert the fluid sheet transition from all dialogs except the image alt text dialog, where it works well. Restore Keyboard.dismiss() calls in LabelsBtn and ThreadgateBtn that were removed for the transitions. https://claude.ai/code/session_011cNDhEb2cDgg5QbVuzEyH1
This commit is contained in:
@@ -1,14 +1,5 @@
|
|||||||
|
import {cloneElement, Fragment, isValidElement, useMemo} from 'react'
|
||||||
import {
|
import {
|
||||||
cloneElement,
|
|
||||||
Fragment,
|
|
||||||
isValidElement,
|
|
||||||
useEffect,
|
|
||||||
useMemo,
|
|
||||||
useRef,
|
|
||||||
useState,
|
|
||||||
} from 'react'
|
|
||||||
import {
|
|
||||||
findNodeHandle,
|
|
||||||
Pressable,
|
Pressable,
|
||||||
type StyleProp,
|
type StyleProp,
|
||||||
type TextStyle,
|
type TextStyle,
|
||||||
@@ -55,11 +46,9 @@ export function Root({
|
|||||||
control?: Dialog.DialogControlProps
|
control?: Dialog.DialogControlProps
|
||||||
}>) {
|
}>) {
|
||||||
const defaultControl = Dialog.useDialogControl()
|
const defaultControl = Dialog.useDialogControl()
|
||||||
const triggerRef = useRef<View>(null)
|
|
||||||
const context = useMemo<ContextType>(
|
const context = useMemo<ContextType>(
|
||||||
() => ({
|
() => ({
|
||||||
control: control || defaultControl,
|
control: control || defaultControl,
|
||||||
triggerRef,
|
|
||||||
}),
|
}),
|
||||||
[control, defaultControl],
|
[control, defaultControl],
|
||||||
)
|
)
|
||||||
@@ -90,7 +79,7 @@ export function Trigger({
|
|||||||
pressed,
|
pressed,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
ref: context.triggerRef,
|
ref: null,
|
||||||
onPress: context.control.open,
|
onPress: context.control.open,
|
||||||
onFocus,
|
onFocus,
|
||||||
onBlur,
|
onBlur,
|
||||||
@@ -106,27 +95,17 @@ export function Trigger({
|
|||||||
export function Outer({
|
export function Outer({
|
||||||
children,
|
children,
|
||||||
showCancel,
|
showCancel,
|
||||||
enableTransition,
|
|
||||||
}: React.PropsWithChildren<{
|
}: React.PropsWithChildren<{
|
||||||
showCancel?: boolean
|
showCancel?: boolean
|
||||||
style?: StyleProp<ViewStyle>
|
style?: StyleProp<ViewStyle>
|
||||||
enableTransition?: boolean
|
|
||||||
}>) {
|
}>) {
|
||||||
const context = useMenuContext()
|
const context = useMenuContext()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const [sourceViewTag, setSourceViewTag] = useState<number>()
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (enableTransition && context.triggerRef.current) {
|
|
||||||
const tag = findNodeHandle(context.triggerRef.current)
|
|
||||||
if (tag != null) setSourceViewTag(tag)
|
|
||||||
}
|
|
||||||
}, [enableTransition, context.triggerRef])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog.Outer
|
<Dialog.Outer
|
||||||
control={context.control}
|
control={context.control}
|
||||||
nativeOptions={{preventExpansion: true, sourceViewTag}}>
|
nativeOptions={{preventExpansion: true}}>
|
||||||
<Dialog.Handle />
|
<Dialog.Handle />
|
||||||
{/* Re-wrap with context since Dialogs are portal-ed to root */}
|
{/* Re-wrap with context since Dialogs are portal-ed to root */}
|
||||||
<Context.Provider value={context}>
|
<Context.Provider value={context}>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {forwardRef, useCallback, useId, useMemo, useRef, useState} from 'react'
|
import {forwardRef, useCallback, useId, useMemo, useState} from 'react'
|
||||||
import {
|
import {
|
||||||
Pressable,
|
Pressable,
|
||||||
type StyleProp,
|
type StyleProp,
|
||||||
@@ -62,11 +62,9 @@ export function Root({
|
|||||||
}>) {
|
}>) {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const defaultControl = useMenuControl()
|
const defaultControl = useMenuControl()
|
||||||
const triggerRef = useRef<View>(null)
|
|
||||||
const context = useMemo<ContextType>(
|
const context = useMemo<ContextType>(
|
||||||
() => ({
|
() => ({
|
||||||
control: control || defaultControl,
|
control: control || defaultControl,
|
||||||
triggerRef,
|
|
||||||
}),
|
}),
|
||||||
[control, defaultControl],
|
[control, defaultControl],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import {
|
|||||||
type AccessibilityRole,
|
type AccessibilityRole,
|
||||||
type GestureResponderEvent,
|
type GestureResponderEvent,
|
||||||
type PressableProps,
|
type PressableProps,
|
||||||
type View,
|
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import type React from 'react'
|
import type React from 'react'
|
||||||
|
|
||||||
@@ -13,7 +12,6 @@ import {type Props as SVGIconProps} from '#/components/icons/common'
|
|||||||
|
|
||||||
export type ContextType = {
|
export type ContextType = {
|
||||||
control: Dialog.DialogOuterProps['control']
|
control: Dialog.DialogOuterProps['control']
|
||||||
triggerRef: React.RefObject<View | null>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ItemContextType = {
|
export type ItemContextType = {
|
||||||
@@ -63,7 +61,7 @@ export type TriggerChildProps =
|
|||||||
* object is empty.
|
* object is empty.
|
||||||
*/
|
*/
|
||||||
props: {
|
props: {
|
||||||
ref: React.RefObject<View | null>
|
ref: null
|
||||||
onPress: () => void
|
onPress: () => void
|
||||||
onFocus: () => void
|
onFocus: () => void
|
||||||
onBlur: () => void
|
onBlur: () => void
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import {memo, useCallback, useRef} from 'react'
|
import {memo, useCallback} from 'react'
|
||||||
import {findNodeHandle, View} from 'react-native'
|
import {View} from 'react-native'
|
||||||
import {msg, plural} from '@lingui/core/macro'
|
import {msg, plural} from '@lingui/core/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {Trans} from '@lingui/react/macro'
|
import {Trans} from '@lingui/react/macro'
|
||||||
@@ -41,7 +41,6 @@ let RepostButton = ({
|
|||||||
const requireAuth = useRequireAuth()
|
const requireAuth = useRequireAuth()
|
||||||
const dialogControl = Dialog.useDialogControl()
|
const dialogControl = Dialog.useDialogControl()
|
||||||
const formatPostStatCount = useFormatPostStatCount()
|
const formatPostStatCount = useFormatPostStatCount()
|
||||||
const btnRef = useRef<View>(null)
|
|
||||||
|
|
||||||
const onPress = () => requireAuth(() => dialogControl.open())
|
const onPress = () => requireAuth(() => dialogControl.open())
|
||||||
|
|
||||||
@@ -57,7 +56,6 @@ let RepostButton = ({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PostControlButton
|
<PostControlButton
|
||||||
ref={btnRef}
|
|
||||||
testID="repostBtn"
|
testID="repostBtn"
|
||||||
active={isReposted}
|
active={isReposted}
|
||||||
activeColor={t.palette.positive_500}
|
activeColor={t.palette.positive_500}
|
||||||
@@ -96,10 +94,7 @@ let RepostButton = ({
|
|||||||
</PostControlButton>
|
</PostControlButton>
|
||||||
<Dialog.Outer
|
<Dialog.Outer
|
||||||
control={dialogControl}
|
control={dialogControl}
|
||||||
nativeOptions={{
|
nativeOptions={{preventExpansion: true}}>
|
||||||
preventExpansion: true,
|
|
||||||
sourceViewTag: findNodeHandle(btnRef.current) ?? undefined,
|
|
||||||
}}>
|
|
||||||
<Dialog.Handle />
|
<Dialog.Handle />
|
||||||
<RepostButtonDialogInner
|
<RepostButtonDialogInner
|
||||||
isReposted={isReposted}
|
isReposted={isReposted}
|
||||||
|
|||||||
@@ -77,11 +77,9 @@ export type PostInteractionSettingsFormProps = {
|
|||||||
*/
|
*/
|
||||||
export function PostInteractionSettingsControlledDialog({
|
export function PostInteractionSettingsControlledDialog({
|
||||||
control,
|
control,
|
||||||
sourceViewTag,
|
|
||||||
...rest
|
...rest
|
||||||
}: PostInteractionSettingsFormProps & {
|
}: PostInteractionSettingsFormProps & {
|
||||||
control: Dialog.DialogControlProps
|
control: Dialog.DialogControlProps
|
||||||
sourceViewTag?: number
|
|
||||||
}) {
|
}) {
|
||||||
const ax = useAnalytics()
|
const ax = useAnalytics()
|
||||||
const onClose = useNonReactiveCallback(() => {
|
const onClose = useNonReactiveCallback(() => {
|
||||||
@@ -102,7 +100,6 @@ export function PostInteractionSettingsControlledDialog({
|
|||||||
nativeOptions={{
|
nativeOptions={{
|
||||||
preventExpansion: true,
|
preventExpansion: true,
|
||||||
preventDismiss: rest.isDirty && rest.persist,
|
preventDismiss: rest.isDirty && rest.persist,
|
||||||
sourceViewTag,
|
|
||||||
}}
|
}}
|
||||||
onClose={onClose}>
|
onClose={onClose}>
|
||||||
<Dialog.Handle />
|
<Dialog.Handle />
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import {useState} from 'react'
|
import {Keyboard, View} from 'react-native'
|
||||||
import {findNodeHandle, View} from 'react-native'
|
|
||||||
import {msg} from '@lingui/core/macro'
|
import {msg} from '@lingui/core/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {Trans} from '@lingui/react/macro'
|
import {Trans} from '@lingui/react/macro'
|
||||||
@@ -30,14 +29,6 @@ export function LabelsBtn({
|
|||||||
}) {
|
}) {
|
||||||
const control = Dialog.useDialogControl()
|
const control = Dialog.useDialogControl()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const [sourceViewTag, setSourceViewTag] = useState<number>()
|
|
||||||
|
|
||||||
const btnRef = (node: View | null) => {
|
|
||||||
if (node) {
|
|
||||||
const tag = findNodeHandle(node)
|
|
||||||
if (tag != null) setSourceViewTag(tag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const hasLabel = labels.length > 0
|
const hasLabel = labels.length > 0
|
||||||
|
|
||||||
@@ -60,11 +51,13 @@ export function LabelsBtn({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
ref={btnRef}
|
|
||||||
color="secondary"
|
color="secondary"
|
||||||
size="small"
|
size="small"
|
||||||
testID="labelsBtn"
|
testID="labelsBtn"
|
||||||
onPress={() => control.open()}
|
onPress={() => {
|
||||||
|
Keyboard.dismiss()
|
||||||
|
control.open()
|
||||||
|
}}
|
||||||
label={_(msg`Content warnings`)}
|
label={_(msg`Content warnings`)}
|
||||||
accessibilityHint={_(
|
accessibilityHint={_(
|
||||||
msg`Opens a dialog to add a content warning to your post`,
|
msg`Opens a dialog to add a content warning to your post`,
|
||||||
@@ -80,12 +73,7 @@ export function LabelsBtn({
|
|||||||
<ButtonIcon icon={TinyChevronIcon} size="2xs" />
|
<ButtonIcon icon={TinyChevronIcon} size="2xs" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Dialog.Outer
|
<Dialog.Outer control={control} nativeOptions={{preventExpansion: true}}>
|
||||||
control={control}
|
|
||||||
nativeOptions={{
|
|
||||||
preventExpansion: true,
|
|
||||||
sourceViewTag,
|
|
||||||
}}>
|
|
||||||
<Dialog.Handle />
|
<Dialog.Handle />
|
||||||
<DialogInner
|
<DialogInner
|
||||||
labels={labels}
|
labels={labels}
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ export function PostLanguageSelect({
|
|||||||
<LanguageBtn currentLanguages={currentLanguages} {...props} />
|
<LanguageBtn currentLanguages={currentLanguages} {...props} />
|
||||||
)}
|
)}
|
||||||
</Menu.Trigger>
|
</Menu.Trigger>
|
||||||
<Menu.Outer enableTransition>
|
<Menu.Outer>
|
||||||
<Menu.Group>
|
<Menu.Group>
|
||||||
{dedupedHistory.map(historyItem => {
|
{dedupedHistory.map(historyItem => {
|
||||||
const langCodes = historyItem.split(',')
|
const langCodes = historyItem.split(',')
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
import {useEffect, useMemo, useState} from 'react'
|
import {useEffect, useMemo, useState} from 'react'
|
||||||
import {
|
import {Keyboard, type StyleProp, type ViewStyle} from 'react-native'
|
||||||
findNodeHandle,
|
|
||||||
type StyleProp,
|
|
||||||
type View,
|
|
||||||
type ViewStyle,
|
|
||||||
} from 'react-native'
|
|
||||||
import {type AnimatedStyle} from 'react-native-reanimated'
|
import {type AnimatedStyle} from 'react-native-reanimated'
|
||||||
import {type AppBskyFeedPostgate} from '@atproto/api'
|
import {type AppBskyFeedPostgate} from '@atproto/api'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {msg} from '@lingui/core/macro'
|
||||||
@@ -31,6 +26,7 @@ import {Group3_Stroke2_Corner0_Rounded as GroupIcon} from '#/components/icons/Gr
|
|||||||
import * as Tooltip from '#/components/Tooltip'
|
import * as Tooltip from '#/components/Tooltip'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import {useAnalytics} from '#/analytics'
|
import {useAnalytics} from '#/analytics'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
import {useThreadgateNudged} from '#/storage/hooks/threadgate-nudged'
|
import {useThreadgateNudged} from '#/storage/hooks/threadgate-nudged'
|
||||||
|
|
||||||
export function ThreadgateBtn({
|
export function ThreadgateBtn({
|
||||||
@@ -50,13 +46,6 @@ export function ThreadgateBtn({
|
|||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const ax = useAnalytics()
|
const ax = useAnalytics()
|
||||||
const control = Dialog.useDialogControl()
|
const control = Dialog.useDialogControl()
|
||||||
const [sourceViewTag, setSourceViewTag] = useState<number>()
|
|
||||||
const btnRef = (node: View | null) => {
|
|
||||||
if (node) {
|
|
||||||
const tag = findNodeHandle(node)
|
|
||||||
if (tag != null) setSourceViewTag(tag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const [threadgateNudged, setThreadgateNudged] = useThreadgateNudged()
|
const [threadgateNudged, setThreadgateNudged] = useThreadgateNudged()
|
||||||
const [showTooltip, setShowTooltip] = useState(false)
|
const [showTooltip, setShowTooltip] = useState(false)
|
||||||
const [tooltipWasShown] = useState(!threadgateNudged)
|
const [tooltipWasShown] = useState(!threadgateNudged)
|
||||||
@@ -84,6 +73,10 @@ export function ThreadgateBtn({
|
|||||||
nudged: tooltipWasShown,
|
nudged: tooltipWasShown,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (IS_NATIVE && Keyboard.isVisible()) {
|
||||||
|
Keyboard.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
setShowTooltip(false)
|
setShowTooltip(false)
|
||||||
setThreadgateNudged(true)
|
setThreadgateNudged(true)
|
||||||
|
|
||||||
@@ -152,7 +145,6 @@ export function ThreadgateBtn({
|
|||||||
position="top">
|
position="top">
|
||||||
<Tooltip.Target>
|
<Tooltip.Target>
|
||||||
<Button
|
<Button
|
||||||
ref={btnRef}
|
|
||||||
color={showTooltip ? 'primary_subtle' : 'secondary'}
|
color={showTooltip ? 'primary_subtle' : 'secondary'}
|
||||||
size="small"
|
size="small"
|
||||||
testID="openReplyGateButton"
|
testID="openReplyGateButton"
|
||||||
@@ -175,7 +167,6 @@ export function ThreadgateBtn({
|
|||||||
|
|
||||||
<PostInteractionSettingsControlledDialog
|
<PostInteractionSettingsControlledDialog
|
||||||
control={control}
|
control={control}
|
||||||
sourceViewTag={sourceViewTag}
|
|
||||||
onSave={() => {
|
onSave={() => {
|
||||||
if (persist) {
|
if (persist) {
|
||||||
persistChanges({
|
persistChanges({
|
||||||
|
|||||||
Reference in New Issue
Block a user