Bluesky app fork with some witchin' additions 💫 witchsky.app
bluesky fork client

Add iOS 26 fluid zoom transition to alt text dialog (#9970)

Co-authored-by: Claude <noreply@anthropic.com>

authored by samuel.fm

Claude and committed by
GitHub
1782a651 7fd218c9

+33 -4
+2
modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/BottomSheetModule.kt
··· 48 Prop("preventExpansion") { view: BottomSheetView, prop: Boolean -> 49 view.preventExpansion = prop 50 } 51 } 52 } 53 }
··· 48 Prop("preventExpansion") { view: BottomSheetView, prop: Boolean -> 49 view.preventExpansion = prop 50 } 51 + 52 + Prop("sourceViewTag") { _: BottomSheetView, _: Int? -> } 53 } 54 } 55 }
+4
modules/bottom-sheet/ios/BottomSheetModule.swift
··· 42 Prop("preventExpansion") { (view: SheetView, prop: Bool) in 43 view.preventExpansion = prop 44 } 45 } 46 } 47 }
··· 42 Prop("preventExpansion") { (view: SheetView, prop: Bool) in 43 view.preventExpansion = prop 44 } 45 + 46 + Prop("sourceViewTag") { (view: SheetView, prop: Int?) in 47 + view.sourceViewTag = prop 48 + } 49 } 50 } 51 }
+10
modules/bottom-sheet/ios/SheetView.swift
··· 26 var preventDismiss = false 27 var preventExpansion = false 28 var cornerRadius: CGFloat? 29 var minHeight = 0.0 30 var maxHeight: CGFloat! { 31 didSet { ··· 134 self.selectedDetentIdentifier = sheet.selectedDetentIdentifier 135 } 136 sheetVc.view.addSubview(innerView) 137 138 self.sheetVc = sheetVc 139 self.isOpening = true
··· 26 var preventDismiss = false 27 var preventExpansion = false 28 var cornerRadius: CGFloat? 29 + var sourceViewTag: Int? 30 var minHeight = 0.0 31 var maxHeight: CGFloat! { 32 didSet { ··· 135 self.selectedDetentIdentifier = sheet.selectedDetentIdentifier 136 } 137 sheetVc.view.addSubview(innerView) 138 + 139 + if #available(iOS 26.0, *), 140 + let tag = self.sourceViewTag, 141 + let bridge = self.appContext?.reactBridge, 142 + let sourceView = bridge.uiManager.view(forReactTag: NSNumber(value: tag)) { 143 + sheetVc.preferredTransition = .zoom { _ in 144 + return sourceView 145 + } 146 + } 147 148 self.sheetVc = sheetVc 149 self.isOpening = true
+2 -2
modules/bottom-sheet/src/BottomSheet.types.ts
··· 1 - import React from 'react' 2 - import {ColorValue, NativeSyntheticEvent} from 'react-native' 3 4 export type BottomSheetState = 'closed' | 'closing' | 'open' | 'opening' 5 ··· 25 backgroundColor?: ColorValue 26 containerBackgroundColor?: ColorValue 27 disableDrag?: boolean 28 29 minHeight?: number 30 maxHeight?: number
··· 1 + import {type ColorValue, type NativeSyntheticEvent} from 'react-native' 2 3 export type BottomSheetState = 'closed' | 'closing' | 'open' | 'opening' 4 ··· 24 backgroundColor?: ColorValue 25 containerBackgroundColor?: ColorValue 26 disableDrag?: boolean 27 + sourceViewTag?: number 28 29 minHeight?: number 30 maxHeight?: number
+12 -1
src/view/com/composer/photos/Gallery.tsx
··· 1 - import React from 'react' 2 import { 3 type ImageStyle, 4 Keyboard, 5 type LayoutChangeEvent, ··· 144 145 const altTextControl = Dialog.useDialogControl() 146 const editControl = Dialog.useDialogControl() 147 148 const onImageEdit = () => { 149 if (IS_NATIVE) { ··· 162 163 return ( 164 <View 165 style={imageStyle as ViewStyle} 166 // Fixes ALT and icons appearing with half opacity when the post is inactive 167 renderToHardwareTextureAndroid> ··· 240 control={altTextControl} 241 image={image} 242 onChange={onChange} 243 /> 244 245 <EditImageDialog
··· 1 + import React, {useState} from 'react' 2 import { 3 + findNodeHandle, 4 type ImageStyle, 5 Keyboard, 6 type LayoutChangeEvent, ··· 145 146 const altTextControl = Dialog.useDialogControl() 147 const editControl = Dialog.useDialogControl() 148 + const [altBtnViewTag, setAltBtnViewTag] = useState<number>() 149 + 150 + const altBtnRef = (node: View | null) => { 151 + if (node) { 152 + const tag = findNodeHandle(node) 153 + if (tag != null) setAltBtnViewTag(tag) 154 + } 155 + } 156 157 const onImageEdit = () => { 158 if (IS_NATIVE) { ··· 171 172 return ( 173 <View 174 + ref={altBtnRef} 175 style={imageStyle as ViewStyle} 176 // Fixes ALT and icons appearing with half opacity when the post is inactive 177 renderToHardwareTextureAndroid> ··· 250 control={altTextControl} 251 image={image} 252 onChange={onChange} 253 + sourceViewTag={altBtnViewTag} 254 /> 255 256 <EditImageDialog
+3 -1
src/view/com/composer/photos/ImageAltTextDialog.tsx
··· 23 control: Dialog.DialogOuterProps['control'] 24 image: ComposerImage 25 onChange: (next: ComposerImage) => void 26 } 27 28 export const ImageAltTextDialog = ({ 29 control, 30 image, 31 onChange, 32 }: Props): React.ReactNode => { 33 const {height: minHeight} = useWindowDimensions() 34 const [altText, setAltText] = useState(image.alt) ··· 42 alt: enforceLen(altText, MAX_ALT_TEXT, true), 43 }) 44 }} 45 - nativeOptions={{minHeight}}> 46 <Dialog.Handle /> 47 <ImageAltTextInner 48 control={control}
··· 23 control: Dialog.DialogOuterProps['control'] 24 image: ComposerImage 25 onChange: (next: ComposerImage) => void 26 + sourceViewTag?: number 27 } 28 29 export const ImageAltTextDialog = ({ 30 control, 31 image, 32 onChange, 33 + sourceViewTag, 34 }: Props): React.ReactNode => { 35 const {height: minHeight} = useWindowDimensions() 36 const [altText, setAltText] = useState(image.alt) ··· 44 alt: enforceLen(altText, MAX_ALT_TEXT, true), 45 }) 46 }} 47 + nativeOptions={{minHeight, sourceViewTag}}> 48 <Dialog.Handle /> 49 <ImageAltTextInner 50 control={control}