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

Configure Feed

Select the types of activity you want to include in your feed.

Animate border radius in lightbox transition (#10272)

authored by

Samuel Newman and committed by
GitHub
e58feaeb a77b6e35

+45 -36
+2 -1
src/components/Post/Embed/ImageEmbed.tsx
··· 4 4 5 5 import {useLightboxControls} from '#/state/lightbox' 6 6 import {type Dimensions} from '#/view/com/lightbox/ImageViewing/@types' 7 - import {atoms as a} from '#/alf' 7 + import {atoms as a, tokens} from '#/alf' 8 8 import {AutoSizedImage} from '#/components/images/AutoSizedImage' 9 9 import {Gallery} from '#/components/images/Gallery' 10 10 import {ImageLayoutGrid} from '#/components/images/ImageLayoutGrid' ··· 42 42 thumbRect: null, 43 43 thumbRef: refs[i] ?? null, 44 44 thumbDimensions: fetchedDims[i] ?? null, 45 + thumbBorderRadius: tokens.borderRadius.md, 45 46 type: 'image', 46 47 })), 47 48 index,
+10
src/view/com/lightbox/ImageViewing/@types/index.ts
··· 29 29 thumbDimensions: Dimensions | null 30 30 thumbRect: MeasuredDimensions | null 31 31 thumbRef?: AnimatedRef<any> | null 32 + thumbBorderRadius?: number 32 33 alt?: string 33 34 type: 'image' | 'circle-avi' | 'rect-avi' 34 35 } ··· 37 38 TransformsStyle['transform'], 38 39 string | undefined 39 40 > 41 + 42 + export type LightboxTransforms = { 43 + scaleAndMoveTransform: Transform 44 + cropFrameTransform: Transform 45 + cropContentTransform: Transform 46 + borderRadius: number 47 + isResting: boolean 48 + isHidden: boolean 49 + }
+4 -11
src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.android.tsx
··· 19 19 import { 20 20 type Dimensions as ImageDimensions, 21 21 type ImageSource, 22 - type Transform, 22 + type LightboxTransforms, 23 23 } from '../../@types' 24 24 import { 25 25 applyRounding, ··· 53 53 imageAspect: number | undefined 54 54 imageDimensions: ImageDimensions | undefined 55 55 dismissSwipePan: PanGesture 56 - transforms: Readonly< 57 - SharedValue<{ 58 - scaleAndMoveTransform: Transform 59 - cropFrameTransform: Transform 60 - cropContentTransform: Transform 61 - isResting: boolean 62 - isHidden: boolean 63 - }> 64 - > 56 + transforms: Readonly<SharedValue<LightboxTransforms>> 65 57 } 66 58 const ImageItem = ({ 67 59 imageSrc, ··· 339 331 }) 340 332 341 333 const imageCropStyle = useAnimatedStyle(() => { 342 - const {cropFrameTransform} = transforms.get() 334 + const {cropFrameTransform, borderRadius: br} = transforms.get() 343 335 return { 344 336 flex: 1, 345 337 overflow: 'hidden', 346 338 transform: cropFrameTransform, 339 + borderRadius: br, 347 340 } 348 341 }) 349 342
+4 -11
src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.ios.tsx
··· 29 29 import { 30 30 type Dimensions as ImageDimensions, 31 31 type ImageSource, 32 - type Transform, 32 + type LightboxTransforms, 33 33 } from '../../@types' 34 34 35 35 const MAX_ORIGINAL_IMAGE_ZOOM = 2 ··· 52 52 imageAspect: number | undefined 53 53 imageDimensions: ImageDimensions | undefined 54 54 dismissSwipePan: PanGesture 55 - transforms: Readonly< 56 - SharedValue<{ 57 - scaleAndMoveTransform: Transform 58 - cropFrameTransform: Transform 59 - cropContentTransform: Transform 60 - isResting: boolean 61 - isHidden: boolean 62 - }> 63 - > 55 + transforms: Readonly<SharedValue<LightboxTransforms>> 64 56 } 65 57 66 58 const ImageItem = ({ ··· 170 162 171 163 const imageCropStyle = useAnimatedStyle(() => { 172 164 const screenSize = measureSafeArea() 173 - const {cropFrameTransform} = transforms.get() 165 + const {cropFrameTransform, borderRadius: br} = transforms.get() 174 166 return { 175 167 overflow: 'hidden', 176 168 transform: cropFrameTransform, 169 + borderRadius: br, 177 170 width: screenSize.width, 178 171 maxHeight: screenSize.height, 179 172 alignSelf: 'center',
+2 -10
src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.tsx
··· 9 9 import { 10 10 type Dimensions as ImageDimensions, 11 11 type ImageSource, 12 - type Transform, 12 + type LightboxTransforms, 13 13 } from '../../@types' 14 14 15 15 type Props = { ··· 29 29 imageAspect: number | undefined 30 30 imageDimensions: ImageDimensions | undefined 31 31 dismissSwipePan: PanGesture 32 - transforms: Readonly< 33 - SharedValue<{ 34 - scaleAndMoveTransform: Transform 35 - cropFrameTransform: Transform 36 - cropContentTransform: Transform 37 - isResting: boolean 38 - isHidden: boolean 39 - }> 40 - > 32 + transforms: Readonly<SharedValue<LightboxTransforms>> 41 33 } 42 34 43 35 const ImageItem = (_props: Props) => {
+23 -3
src/view/com/lightbox/ImageViewing/index.tsx
··· 52 52 import {setSystemUITheme} from '#/alf/util/systemUI' 53 53 import {IS_IOS} from '#/env' 54 54 import {PlatformInfo} from '../../../../../modules/expo-bluesky-swiss-army' 55 - import {type ImageSource, type Transform} from './@types' 55 + import { 56 + type ImageSource, 57 + type LightboxTransforms, 58 + type Transform, 59 + } from './@types' 56 60 import ImageDefaultHeader from './components/ImageDefaultHeader' 57 61 import ImageItem from './components/ImageItem/ImageItem' 58 62 ··· 494 498 return safeArea 495 499 }, [safeAreaRef, heightDelayedForJSThreadOnly, widthDelayedForJSThreadOnly]) 496 500 497 - const {thumbRect: thumbRectJS} = imageSrc 498 - const transforms = useDerivedValue(() => { 501 + const {thumbRect: thumbRectJS, thumbBorderRadius} = imageSrc 502 + const transforms = useDerivedValue<LightboxTransforms>(() => { 499 503 'worklet' 500 504 const safeArea = measureSafeArea() 501 505 const openProgressValue = openProgress.get() ··· 506 510 return { 507 511 isHidden: true, 508 512 isResting: false, 513 + borderRadius: 0, 509 514 scaleAndMoveTransform: [], 510 515 cropFrameTransform: [], 511 516 cropContentTransform: [], ··· 525 530 thumbRect, 526 531 safeArea, 527 532 imageAspect, 533 + thumbBorderRadius, 528 534 ) 529 535 } 530 536 } 531 537 return { 532 538 isHidden: false, 533 539 isResting: dismissTranslateY === 0, 540 + borderRadius: 0, 534 541 scaleAndMoveTransform: [{translateY: dismissTranslateY}], 535 542 cropFrameTransform: [], 536 543 cropContentTransform: [], ··· 772 779 }, 773 780 safeArea: {width: number; height: number; x: number; y: number}, 774 781 imageAspect: number, 782 + thumbBorderRadius?: number, 775 783 ): { 776 784 scaleAndMoveTransform: Transform 777 785 cropFrameTransform: Transform 778 786 cropContentTransform: Transform 787 + borderRadius: number 779 788 isResting: boolean 780 789 isHidden: boolean 781 790 } { ··· 827 836 [0, 1], 828 837 [croppedFinalHeight / finalHeight, 1], 829 838 ) 839 + // The border radius in the source thumbnail needs to be scaled to account 840 + // for the crop frame and overall scale so it visually matches at progress=0. 841 + const sourceBorderRadius = thumbBorderRadius ?? 0 842 + const initialCropScaleX = croppedFinalWidth / finalWidth 843 + const borderRadius = interpolate( 844 + progress, 845 + [0, 1], 846 + [sourceBorderRadius / (initialScale * initialCropScaleX), 0], 847 + ) 848 + 830 849 return { 831 850 isHidden: false, 832 851 isResting: progress === 1, 833 852 scaleAndMoveTransform: [{translateX}, {translateY}, {scale}], 834 853 cropFrameTransform: [{scaleX: cropScaleX}, {scaleY: cropScaleY}], 835 854 cropContentTransform: [{scaleX: 1 / cropScaleX}, {scaleY: 1 / cropScaleY}], 855 + borderRadius, 836 856 } 837 857 } 838 858