From 4fd92766a66042af68644b28a2400e53f45499bd Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 28 Feb 2026 23:36:26 +0000 Subject: [PATCH] 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 --- src/components/Menu/index.tsx | 27 +++---------------- src/components/Menu/index.web.tsx | 4 +-- src/components/Menu/types.ts | 4 +-- src/components/PostControls/RepostButton.tsx | 11 +++----- .../dialogs/PostInteractionSettingsDialog.tsx | 3 --- src/view/com/composer/labels/LabelsBtn.tsx | 24 +++++------------ .../select-language/PostLanguageSelect.tsx | 2 +- .../com/composer/threadgate/ThreadgateBtn.tsx | 21 +++++---------- 8 files changed, 21 insertions(+), 75 deletions(-) diff --git a/src/components/Menu/index.tsx b/src/components/Menu/index.tsx index 3f1e641baf..65d279e196 100644 --- a/src/components/Menu/index.tsx +++ b/src/components/Menu/index.tsx @@ -1,14 +1,5 @@ +import {cloneElement, Fragment, isValidElement, useMemo} from 'react' import { - cloneElement, - Fragment, - isValidElement, - useEffect, - useMemo, - useRef, - useState, -} from 'react' -import { - findNodeHandle, Pressable, type StyleProp, type TextStyle, @@ -55,11 +46,9 @@ export function Root({ control?: Dialog.DialogControlProps }>) { const defaultControl = Dialog.useDialogControl() - const triggerRef = useRef(null) const context = useMemo( () => ({ control: control || defaultControl, - triggerRef, }), [control, defaultControl], ) @@ -90,7 +79,7 @@ export function Trigger({ pressed, }, props: { - ref: context.triggerRef, + ref: null, onPress: context.control.open, onFocus, onBlur, @@ -106,27 +95,17 @@ export function Trigger({ export function Outer({ children, showCancel, - enableTransition, }: React.PropsWithChildren<{ showCancel?: boolean style?: StyleProp - enableTransition?: boolean }>) { const context = useMenuContext() const {_} = useLingui() - const [sourceViewTag, setSourceViewTag] = useState() - - useEffect(() => { - if (enableTransition && context.triggerRef.current) { - const tag = findNodeHandle(context.triggerRef.current) - if (tag != null) setSourceViewTag(tag) - } - }, [enableTransition, context.triggerRef]) return ( + nativeOptions={{preventExpansion: true}}> {/* Re-wrap with context since Dialogs are portal-ed to root */} diff --git a/src/components/Menu/index.web.tsx b/src/components/Menu/index.web.tsx index 70fdcb5687..ecb74a19e2 100644 --- a/src/components/Menu/index.web.tsx +++ b/src/components/Menu/index.web.tsx @@ -1,4 +1,4 @@ -import {forwardRef, useCallback, useId, useMemo, useRef, useState} from 'react' +import {forwardRef, useCallback, useId, useMemo, useState} from 'react' import { Pressable, type StyleProp, @@ -62,11 +62,9 @@ export function Root({ }>) { const {_} = useLingui() const defaultControl = useMenuControl() - const triggerRef = useRef(null) const context = useMemo( () => ({ control: control || defaultControl, - triggerRef, }), [control, defaultControl], ) diff --git a/src/components/Menu/types.ts b/src/components/Menu/types.ts index ab436c4c58..a0f0a1ed60 100644 --- a/src/components/Menu/types.ts +++ b/src/components/Menu/types.ts @@ -3,7 +3,6 @@ import { type AccessibilityRole, type GestureResponderEvent, type PressableProps, - type View, } from 'react-native' import type React from 'react' @@ -13,7 +12,6 @@ import {type Props as SVGIconProps} from '#/components/icons/common' export type ContextType = { control: Dialog.DialogOuterProps['control'] - triggerRef: React.RefObject } export type ItemContextType = { @@ -63,7 +61,7 @@ export type TriggerChildProps = * object is empty. */ props: { - ref: React.RefObject + ref: null onPress: () => void onFocus: () => void onBlur: () => void diff --git a/src/components/PostControls/RepostButton.tsx b/src/components/PostControls/RepostButton.tsx index 42d78e3e1f..734cafa3c8 100644 --- a/src/components/PostControls/RepostButton.tsx +++ b/src/components/PostControls/RepostButton.tsx @@ -1,5 +1,5 @@ -import {memo, useCallback, useRef} from 'react' -import {findNodeHandle, View} from 'react-native' +import {memo, useCallback} from 'react' +import {View} from 'react-native' import {msg, plural} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' @@ -41,7 +41,6 @@ let RepostButton = ({ const requireAuth = useRequireAuth() const dialogControl = Dialog.useDialogControl() const formatPostStatCount = useFormatPostStatCount() - const btnRef = useRef(null) const onPress = () => requireAuth(() => dialogControl.open()) @@ -57,7 +56,6 @@ let RepostButton = ({ return ( <> + nativeOptions={{preventExpansion: true}}> { @@ -102,7 +100,6 @@ export function PostInteractionSettingsControlledDialog({ nativeOptions={{ preventExpansion: true, preventDismiss: rest.isDirty && rest.persist, - sourceViewTag, }} onClose={onClose}> diff --git a/src/view/com/composer/labels/LabelsBtn.tsx b/src/view/com/composer/labels/LabelsBtn.tsx index 1bc5153668..0387315c9c 100644 --- a/src/view/com/composer/labels/LabelsBtn.tsx +++ b/src/view/com/composer/labels/LabelsBtn.tsx @@ -1,5 +1,4 @@ -import {useState} from 'react' -import {findNodeHandle, View} from 'react-native' +import {Keyboard, View} from 'react-native' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' @@ -30,14 +29,6 @@ export function LabelsBtn({ }) { const control = Dialog.useDialogControl() const {_} = useLingui() - const [sourceViewTag, setSourceViewTag] = useState() - - const btnRef = (node: View | null) => { - if (node) { - const tag = findNodeHandle(node) - if (tag != null) setSourceViewTag(tag) - } - } const hasLabel = labels.length > 0 @@ -60,11 +51,13 @@ export function LabelsBtn({ return ( <> - + )} - + {dedupedHistory.map(historyItem => { const langCodes = historyItem.split(',') diff --git a/src/view/com/composer/threadgate/ThreadgateBtn.tsx b/src/view/com/composer/threadgate/ThreadgateBtn.tsx index ce87074830..ed22befcd9 100644 --- a/src/view/com/composer/threadgate/ThreadgateBtn.tsx +++ b/src/view/com/composer/threadgate/ThreadgateBtn.tsx @@ -1,10 +1,5 @@ import {useEffect, useMemo, useState} from 'react' -import { - findNodeHandle, - type StyleProp, - type View, - type ViewStyle, -} from 'react-native' +import {Keyboard, type StyleProp, type ViewStyle} from 'react-native' import {type AnimatedStyle} from 'react-native-reanimated' import {type AppBskyFeedPostgate} from '@atproto/api' 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 {Text} from '#/components/Typography' import {useAnalytics} from '#/analytics' +import {IS_NATIVE} from '#/env' import {useThreadgateNudged} from '#/storage/hooks/threadgate-nudged' export function ThreadgateBtn({ @@ -50,13 +46,6 @@ export function ThreadgateBtn({ const {_} = useLingui() const ax = useAnalytics() const control = Dialog.useDialogControl() - const [sourceViewTag, setSourceViewTag] = useState() - const btnRef = (node: View | null) => { - if (node) { - const tag = findNodeHandle(node) - if (tag != null) setSourceViewTag(tag) - } - } const [threadgateNudged, setThreadgateNudged] = useThreadgateNudged() const [showTooltip, setShowTooltip] = useState(false) const [tooltipWasShown] = useState(!threadgateNudged) @@ -84,6 +73,10 @@ export function ThreadgateBtn({ nudged: tooltipWasShown, }) + if (IS_NATIVE && Keyboard.isVisible()) { + Keyboard.dismiss() + } + setShowTooltip(false) setThreadgateNudged(true) @@ -152,7 +145,6 @@ export function ThreadgateBtn({ position="top">