Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 52 additions & 25 deletions FabricTestExample/src/Test1649.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,41 +13,50 @@ import {
NativeStackNavigationProp,
NativeStackNavigationOptions,
} from 'react-native-screens/native-stack';
import { SheetDetentTypes } from 'react-native-screens';
import * as jotai from 'jotai';

type SheetDetent = NativeStackNavigationOptions['sheetAllowedDetents'];
type SheetUndimmedDetent =
NativeStackNavigationOptions['sheetLargestUndimmedDetent'];

type NavProp = {
navigation: NativeStackNavigationProp<ParamListBase>;
};

const Stack = createNativeStackNavigator();
type SheetOptions = {
sheetAllowedDetents: SheetDetentTypes;
sheetLargestUndimmedDetent: SheetDetentTypes;
sheetGrabberVisible: boolean;
sheetCornerRadius: number;
sheetExpandsWhenScrolledToEdge: boolean;
sheetCustomDetents: number[];
};

const initialAllowedDetentsArray = [0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9];
const Stack = createNativeStackNavigator();

/// Sheet options
// const allowedDetentsAtom = jotai.atom<SheetDetent>('all');
// const largestUndimmedDetentAtom = jotai.atom<SheetDetentTypes | number>('all');

const allowedDetentsAtom = jotai.atom<SheetDetent>(initialAllowedDetentsArray);
const largestUndimmedDetentAtom = jotai.atom<SheetUndimmedDetent>(3);

// const allowedDetentsAtom = jotai.atom<SheetDetent>([0.7]);
// const largestUndimmedDetentAtom = jotai.atom<SheetDetentTypes | number>(0);

const allowedDetentsAtom = jotai.atom<SheetDetentTypes>('custom');
const largestUndimmedDetentAtom = jotai.atom<SheetDetentTypes>('large');
const grabberVisibleAtom = jotai.atom(false);
const cornerRadiusAtom = jotai.atom(-1);
const expandsWhenScrolledToEdgeAtom = jotai.atom(false);
const customDetentsAtom = jotai.atom<number[]>([0.3, 0.6, 0.85]);

const sheetOptionsAtom = jotai.atom(get => ({
sheetAllowedDetents: get(allowedDetentsAtom),
sheetLargestUndimmedDetent: get(largestUndimmedDetentAtom),
sheetGrabberVisible: get(grabberVisibleAtom),
sheetCornerRadius: get(cornerRadiusAtom),
sheetExpandsWhenScrolledToEdge: get(expandsWhenScrolledToEdgeAtom),
}));
const sheetOptionsAtom = jotai.atom(
get => ({
sheetAllowedDetents: get(allowedDetentsAtom),
sheetLargestUndimmedDetent: get(largestUndimmedDetentAtom),
sheetGrabberVisible: get(grabberVisibleAtom),
sheetCornerRadius: get(cornerRadiusAtom),
sheetExpandsWhenScrolledToEdge: get(expandsWhenScrolledToEdgeAtom),
sheetCustomDetents: get(customDetentsAtom),
}),
(_get, set, value: SheetOptions) => {
set(allowedDetentsAtom, value.sheetAllowedDetents);
set(largestUndimmedDetentAtom, value.sheetLargestUndimmedDetent);
set(grabberVisibleAtom, value.sheetGrabberVisible);
set(cornerRadiusAtom, value.sheetCornerRadius);
set(expandsWhenScrolledToEdgeAtom, value.sheetExpandsWhenScrolledToEdge);
set(customDetentsAtom, value.sheetCustomDetents);
},
);

export default function App(): JSX.Element {
const sheetOptions = jotai.useAtomValue(sheetOptionsAtom);
Expand Down Expand Up @@ -139,6 +148,7 @@ function SheetScreen({ navigation }: NavProp) {
const [cornerRadius, setCornerRadius] = jotai.useAtom(cornerRadiusAtom);
const [expandsWhenScrolledToEdge, setExpandsWhenScrolledToEdge] =
jotai.useAtom(expandsWhenScrolledToEdgeAtom);
// const [customDetents, setCustomDetents] = jotai.useAtom(customDetentsAtom);

function nextDetentLevel(detent: SheetDetent): SheetDetent {
if (Array.isArray(detent)) {
Expand All @@ -147,8 +157,10 @@ function SheetScreen({ navigation }: NavProp) {
return 'medium';
} else if (detent === 'medium') {
return 'large';
} else if (detent === 'large') {
return initialAllowedDetentsArray;
} else if (currDetent === 'large') {
return 'custom';
} else if (currDetent === 'custom') {
return 'all';
} else {
return 'all';
}
Expand Down Expand Up @@ -189,6 +201,9 @@ function SheetScreen({ navigation }: NavProp) {
onPress={() => {
const newRadius = cornerRadius >= 150 ? -1.0 : cornerRadius + 50;
setCornerRadius(newRadius);
// navigation.setOptions({
// sheetCornerRadius: newRadius,
// });
}}
/>
<Text>radius: {cornerRadius}</Text>
Expand All @@ -197,21 +212,30 @@ function SheetScreen({ navigation }: NavProp) {
onPress={() => {
const newDetentLevel = nextDetentLevel(allowedDetents);
setAllowedDetents(newDetentLevel);
// navigation.setOptions({
// sheetAllowedDetents: newDetentLevel,
// });
}}
/>
<Text>detent: {allowedDetents}</Text>
<Button
title="Change largest undimmed detent"
onPress={() => {
const newDetentLevel = nextUndimmedDetentLevel(largestUndimmedDetent);
const newDetentLevel = nextDetentLevel(largestUndimmedDetent);
setLargestUndimmedDetent(newDetentLevel);
// navigation.setOptions({
// sheetLargestUndimmedDetent: newDetentLevel,
// });
}}
/>
<Text>largestUndimmedDetent: {largestUndimmedDetent}</Text>
<Button
title="Toggle sheetExpandsWhenScrolledToEdge"
onPress={() => {
setExpandsWhenScrolledToEdge(!expandsWhenScrolledToEdge);
// navigation.setOptions({
// sheetExpandsWhenScrolledToEdge: !expandsWhenScrolledToEdge,
// });
}}
/>
<Text>
Expand All @@ -222,6 +246,9 @@ function SheetScreen({ navigation }: NavProp) {
title="Toggle grabber visibility"
onPress={() => {
setGrabberVisible(!grabberVisible);
// navigation.setOptions({
// sheetGrabberVisible: !grabberVisible,
// });
}}
/>
</View>
Expand Down
2 changes: 1 addition & 1 deletion TestsExample/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,5 +96,5 @@ import Test1864 from './src/Test1864';
enableFreeze(true);

export default function App() {
return <Test42 />;
return <Test1649 />;
}
2 changes: 2 additions & 0 deletions ios/RNSConvert.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ namespace react = facebook::react;

+ (NSMutableArray<NSNumber *> *)NSNumberMutableArrayFromFloatVector:(const std::vector<CGFloat> &)vector;

+ (NSMutableArray<NSNumber *> *)arrayFromVector:(const std::vector<CGFloat> &)vector;

@end

#endif // RCT_NEW_ARCH_ENABLED
3 changes: 1 addition & 2 deletions ios/RNSConvert.mm
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ + (RNSScreenDetentType)RNSScreenDetentTypeFromAllowedDetents:(react::RNSScreenSh
return RNSScreenDetentTypeMedium;
case react::RNSScreenSheetAllowedDetents::Custom:
return RNSScreenDetentTypeCustom;

}
}

Expand Down Expand Up @@ -153,7 +152,7 @@ + (RNSSearchBarPlacement)RNSScreenSearchBarPlacementFromCppEquivalent:(react::RN
}
}

+ (NSMutableArray<NSNumber *> *)NSNumberMutableArrayFromFloatVector:(const std::vector<CGFloat> &)vector
+ (NSMutableArray<NSNumber *> *)arrayFromVector:(const std::vector<CGFloat> &)vector
{
NSMutableArray *array = [NSMutableArray arrayWithCapacity:vector.size()];
for (CGFloat val : vector) {
Expand Down
84 changes: 76 additions & 8 deletions ios/RNSScreen.mm
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,15 @@

@interface RNSScreenView ()
#ifdef RCT_NEW_ARCH_ENABLED
<RCTRNSScreenViewProtocol, UIAdaptivePresentationControllerDelegate>
<RCTRNSScreenViewProtocol, UIAdaptivePresentationControllerDelegate, CAAnimationDelegate>
#else
<UIAdaptivePresentationControllerDelegate, RCTInvalidating>
<UIAdaptivePresentationControllerDelegate, RCTInvalidating, CAAnimationDelegate>
#endif
@end

@implementation RNSScreenView {
__weak RCTBridge *_bridge;
CADisplayLink *_displayLink;
#ifdef RCT_NEW_ARCH_ENABLED
RCTSurfaceTouchHandler *_touchHandler;
react::RNSScreenShadowNode::ConcreteState::Shared _state;
Expand Down Expand Up @@ -91,6 +92,8 @@ - (void)initCommonProps
_sheetCustomDetents = [NSArray array];
_sheetCustomLargestUndimmedDetent = nil;
#endif // !TARGET_OS_TV
_displayLink = nil;
// _displayLink = [CADisplayLink displayLinkWithTarget:self selector:<#(nonnull SEL)#>]
}

- (UIViewController *)reactViewController
Expand All @@ -105,20 +108,77 @@ - (UIViewController *)reactViewController
}
#endif

- (void)setBounds:(CGRect)bounds
{
[super setBounds:bounds];
NSLog(@"setBounds (%f, %f), (%f, %f)", bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height);
}

- (void)setFrame:(CGRect)frame
{
[super setFrame:frame];
if (self->_stackPresentation == RNSScreenStackPresentationFormSheet) {
// NSLog(@"setFrame (%f, %f), (%f, %f)",
// frame.origin.x, frame.origin.y,
// frame.size.width, frame.size.height);
NSLog(@"setFrame (%f, %f)", frame.size.width, frame.size.height);
}
}

- (void)updateBounds
{
#ifdef RCT_NEW_ARCH_ENABLED
if (_state != nullptr) {
auto newState = react::RNSScreenState{RCTSizeFromCGSize(self.bounds.size)};
_state->updateState(std::move(newState));
UINavigationController *navctr = _controller.navigationController;
[navctr.view setNeedsLayout];
CAAnimation *sizeAnimation = [self.layer animationForKey:@"bounds.size"];
if (sizeAnimation != nil && self.layer.presentationLayer.bounds.size.height > self.bounds.size.height) {
CABasicAnimation *callbackOnlyAnimation = [CABasicAnimation new];
callbackOnlyAnimation.duration = sizeAnimation.duration;
callbackOnlyAnimation.beginTime = sizeAnimation.beginTime;
callbackOnlyAnimation.delegate = self;
[self.layer addAnimation:callbackOnlyAnimation forKey:@"rns_sheet_animation"];
} else {
auto newState = react::RNSScreenState{RCTSizeFromCGSize(self.bounds.size)};
_state->updateState(std::move(newState));
UINavigationController *navctr = _controller.navigationController;
[navctr.view setNeedsLayout];
}
}
#else
[_bridge.uiManager setSize:self.bounds.size forView:self];
if (self->_stackPresentation == RNSScreenStackPresentationFormSheet) {
return;
} else {
[_bridge.uiManager setSize:self.bounds.size forView:self];
}
// CAAnimation *sizeAnimation = [self.layer animationForKey:@"bounds.size"];
//// if (sizeAnimation && self.layer.presentationLayer.bounds.size.height > self.bounds.size.height) {
//// if (sizeAnimation && self.layer.presentationLayer.frame.size.height > self.bounds.size.height) {
// if (sizeAnimation) {
// CABasicAnimation *callbackOnlyAnimation = [CABasicAnimation new];
// callbackOnlyAnimation.duration = sizeAnimation.duration;
// callbackOnlyAnimation.beginTime = sizeAnimation.beginTime;
// callbackOnlyAnimation.delegate = self;
//// NSLog(@"Adding animation");
//// [self.layer addAnimation:callbackOnlyAnimation forKey:@"rns_sheet_animation"];
//// CGRect bounds = self.layer.presentationLayer.bounds;
//// NSLog(@"Sending (%f, %f) size to UIM (ANIM)", bounds.size.width, bounds.size.height);
// } else {
// NSLog(@"Sending (%f, %f) size to UIM", self.bounds.size.width, self.bounds.size.height);
//// [_bridge.uiManager setSize:self.bounds.size forView:self];
// }
#endif
}

- (void)animationDidStart:(CAAnimation *)animation
{
}

- (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)finished
{
if (finished) {
[self updateBounds];
}
}

- (void)setStackPresentation:(RNSScreenStackPresentation)stackPresentation
{
switch (stackPresentation) {
Expand Down Expand Up @@ -830,7 +890,7 @@ - (void)updateProps:(react::Props::Shared const &)props oldProps:(react::Props::

if (_stackPresentation == RNSScreenStackPresentationFormSheet) {
if (newScreenProps.sheetCustomDetents != oldScreenProps.sheetCustomDetents) {
[self setSheetCustomDetents:[RNSConvert NSNumberMutableArrayFromFloatVector:newScreenProps.sheetCustomDetents]];
[self setSheetCustomDetents:[RNSConvert arrayFromVector:newScreenProps.sheetCustomDetents]];
}
if (newScreenProps.sheetCustomLargestUndimmedDetent != oldScreenProps.sheetCustomLargestUndimmedDetent) {
[self
Expand Down Expand Up @@ -879,6 +939,13 @@ - (void)didSetProps:(NSArray<NSString *> *)changedProps
{
[super didSetProps:changedProps];
#if !TARGET_OS_TV
if ([changedProps containsObject:@"stackPresentation"] &&
self.stackPresentation == RNSScreenStackPresentationFormSheet) {
// if (_displayLink == nil) {
// _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateBounds)];
// [_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
// }
}
[self updateFormSheetPresentationStyle];
#endif // !TARGET_OS_TV
}
Expand Down Expand Up @@ -907,6 +974,7 @@ - (void)reactSetFrame:(CGRect)frame
- (void)invalidate
{
_controller = nil;
// [_displayLink invalidate];
}
#endif

Expand Down