react-native-screens 4.0.0-beta.1 → 4.0.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/fabric/java/com/swmansion/rnscreens/FabricEnabledHeaderConfigViewGroup.kt +61 -0
- package/android/src/main/java/com/swmansion/rnscreens/CustomToolbar.kt +14 -0
- package/android/src/main/java/com/swmansion/rnscreens/InsetsObserverProxy.kt +2 -4
- package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +46 -7
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +24 -9
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +37 -17
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.kt +1 -2
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigShadowNode.kt +25 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigViewManager.kt +18 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +6 -1
- package/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt +1 -0
- package/android/src/main/java/com/swmansion/rnscreens/ext/ViewExt.kt +24 -0
- package/android/src/main/java/com/swmansion/rnscreens/utils/PaddingBundle.kt +8 -0
- package/android/src/main/jni/rnscreens.h +2 -0
- package/android/src/paper/java/com/swmansion/rnscreens/FabricEnabledHeaderConfigViewGroup.kt +39 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigComponentDescriptor.h +44 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigShadowNode.cpp +8 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigShadowNode.h +32 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigState.cpp +23 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigState.h +50 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewComponentDescriptor.h +27 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewShadowNode.cpp +8 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewShadowNode.h +32 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewState.cpp +15 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewState.h +40 -0
- package/ios/RNSConvert.mm +0 -1
- package/ios/RNSScreen.h +15 -0
- package/ios/RNSScreen.mm +55 -8
- package/ios/RNSScreenStack.mm +81 -2
- package/ios/RNSScreenStackHeaderConfig.h +63 -0
- package/ios/RNSScreenStackHeaderConfig.mm +135 -13
- package/ios/RNSScreenStackHeaderSubview.mm +26 -0
- package/ios/utils/UINavigationBar+RNSUtility.h +37 -0
- package/ios/utils/UINavigationBar+RNSUtility.mm +44 -0
- package/ios/utils/UIView+RNSUtility.mm +0 -1
- package/lib/commonjs/components/Screen.js +58 -7
- package/lib/commonjs/components/Screen.js.map +1 -1
- package/lib/commonjs/components/ScreenContentWrapper.web.js +11 -0
- package/lib/commonjs/components/ScreenContentWrapper.web.js.map +1 -0
- package/lib/commonjs/components/ScreenFooter.web.js +11 -0
- package/lib/commonjs/components/ScreenFooter.web.js.map +1 -0
- package/lib/commonjs/components/ScreenStackHeaderConfig.js +53 -17
- package/lib/commonjs/components/ScreenStackHeaderConfig.js.map +1 -1
- package/lib/commonjs/components/helpers/usePrevious.js +15 -0
- package/lib/commonjs/components/helpers/usePrevious.js.map +1 -0
- package/lib/commonjs/fabric/ModalScreenNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/ScreenNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js +3 -1
- package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/ScreenStackHeaderSubviewNativeComponent.js +3 -1
- package/lib/commonjs/fabric/ScreenStackHeaderSubviewNativeComponent.js.map +1 -1
- package/lib/commonjs/native-stack/views/NativeStackView.js +4 -10
- package/lib/commonjs/native-stack/views/NativeStackView.js.map +1 -1
- package/lib/module/components/Screen.js +58 -7
- package/lib/module/components/Screen.js.map +1 -1
- package/lib/module/components/ScreenContentWrapper.web.js +5 -0
- package/lib/module/components/ScreenContentWrapper.web.js.map +1 -0
- package/lib/module/components/ScreenFooter.web.js +5 -0
- package/lib/module/components/ScreenFooter.web.js.map +1 -0
- package/lib/module/components/ScreenStackHeaderConfig.js +50 -16
- package/lib/module/components/ScreenStackHeaderConfig.js.map +1 -1
- package/lib/module/components/helpers/usePrevious.js +9 -0
- package/lib/module/components/helpers/usePrevious.js.map +1 -0
- package/lib/module/fabric/ModalScreenNativeComponent.js.map +1 -1
- package/lib/module/fabric/ScreenNativeComponent.js.map +1 -1
- package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js +3 -1
- package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
- package/lib/module/fabric/ScreenStackHeaderSubviewNativeComponent.js +3 -1
- package/lib/module/fabric/ScreenStackHeaderSubviewNativeComponent.js.map +1 -1
- package/lib/module/native-stack/views/NativeStackView.js +4 -10
- package/lib/module/native-stack/views/NativeStackView.js.map +1 -1
- package/lib/typescript/components/Screen.d.ts +5 -1
- package/lib/typescript/components/Screen.d.ts.map +1 -1
- package/lib/typescript/components/ScreenContentWrapper.web.d.ts +5 -0
- package/lib/typescript/components/ScreenContentWrapper.web.d.ts.map +1 -0
- package/lib/typescript/components/ScreenFooter.web.d.ts +5 -0
- package/lib/typescript/components/ScreenFooter.web.d.ts.map +1 -0
- package/lib/typescript/components/ScreenStackHeaderConfig.d.ts +1 -1
- package/lib/typescript/components/ScreenStackHeaderConfig.d.ts.map +1 -1
- package/lib/typescript/components/helpers/usePrevious.d.ts +2 -0
- package/lib/typescript/components/helpers/usePrevious.d.ts.map +1 -0
- package/lib/typescript/fabric/ModalScreenNativeComponent.d.ts +1 -0
- package/lib/typescript/fabric/ModalScreenNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/ScreenNativeComponent.d.ts +1 -1
- package/lib/typescript/fabric/ScreenNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/ScreenStackHeaderConfigNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/ScreenStackHeaderSubviewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/native-stack/types.d.ts +2 -3
- package/lib/typescript/native-stack/types.d.ts.map +1 -1
- package/lib/typescript/native-stack/views/NativeStackView.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +26 -9
- package/lib/typescript/types.d.ts.map +1 -1
- package/native-stack/README.md +3 -2
- package/package.json +1 -1
- package/src/components/Screen.tsx +97 -12
- package/src/components/ScreenContentWrapper.web.tsx +6 -0
- package/src/components/ScreenFooter.web.tsx +6 -0
- package/src/components/ScreenStackHeaderConfig.tsx +59 -26
- package/src/components/helpers/usePrevious.tsx +11 -0
- package/src/fabric/ModalScreenNativeComponent.ts +1 -0
- package/src/fabric/ScreenNativeComponent.ts +0 -1
- package/src/fabric/ScreenStackHeaderConfigNativeComponent.ts +3 -1
- package/src/fabric/ScreenStackHeaderSubviewNativeComponent.ts +3 -1
- package/src/native-stack/types.tsx +2 -3
- package/src/native-stack/views/NativeStackView.tsx +4 -10
- package/src/types.tsx +29 -13
- package/windows/RNScreens/Screen.h +0 -1
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <jsi/jsi.h>
|
|
4
|
+
#include <react/renderer/components/rnscreens/EventEmitters.h>
|
|
5
|
+
#include <react/renderer/components/rnscreens/Props.h>
|
|
6
|
+
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
|
|
7
|
+
#include <react/renderer/core/LayoutContext.h>
|
|
8
|
+
#include "FrameCorrectionModes.h"
|
|
9
|
+
#include "RNSScreenStackHeaderConfigState.h"
|
|
10
|
+
|
|
11
|
+
namespace facebook::react {
|
|
12
|
+
|
|
13
|
+
using namespace rnscreens;
|
|
14
|
+
|
|
15
|
+
JSI_EXPORT extern const char RNSScreenStackHeaderConfigComponentName[];
|
|
16
|
+
|
|
17
|
+
class JSI_EXPORT RNSScreenStackHeaderConfigShadowNode final
|
|
18
|
+
: public ConcreteViewShadowNode<
|
|
19
|
+
RNSScreenStackHeaderConfigComponentName,
|
|
20
|
+
RNSScreenStackHeaderConfigProps,
|
|
21
|
+
RNSScreenStackHeaderConfigEventEmitter,
|
|
22
|
+
RNSScreenStackHeaderConfigState> {
|
|
23
|
+
public:
|
|
24
|
+
using ConcreteViewShadowNode::ConcreteViewShadowNode;
|
|
25
|
+
using StateData = ConcreteViewShadowNode::ConcreteStateData;
|
|
26
|
+
|
|
27
|
+
#pragma mark - ShadowNode overrides
|
|
28
|
+
|
|
29
|
+
#pragma mark - Custom interface
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#include "RNSScreenStackHeaderConfigState.h"
|
|
2
|
+
|
|
3
|
+
namespace facebook {
|
|
4
|
+
namespace react {
|
|
5
|
+
|
|
6
|
+
#ifdef ANDROID
|
|
7
|
+
folly::dynamic RNSScreenStackHeaderConfigState::getDynamic() const {
|
|
8
|
+
return folly::dynamic::object("paddingStart", paddingStart_)(
|
|
9
|
+
"paddingEnd_", paddingEnd_);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
#endif
|
|
13
|
+
|
|
14
|
+
Float RNSScreenStackHeaderConfigState::getPaddingStart() const noexcept {
|
|
15
|
+
return paddingStart_;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
Float RNSScreenStackHeaderConfigState::getPaddingEnd() const noexcept {
|
|
19
|
+
return paddingEnd_;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
} // namespace react
|
|
23
|
+
} // namespace facebook
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <react/renderer/core/graphicsConversions.h>
|
|
4
|
+
#include <react/renderer/graphics/Float.h>
|
|
5
|
+
|
|
6
|
+
#ifdef ANDROID
|
|
7
|
+
#include <folly/dynamic.h>
|
|
8
|
+
#include <react/renderer/mapbuffer/MapBuffer.h>
|
|
9
|
+
#include <react/renderer/mapbuffer/MapBufferBuilder.h>
|
|
10
|
+
#endif
|
|
11
|
+
|
|
12
|
+
namespace facebook::react {
|
|
13
|
+
|
|
14
|
+
class JSI_EXPORT RNSScreenStackHeaderConfigState final {
|
|
15
|
+
public:
|
|
16
|
+
using Shared = std::shared_ptr<const RNSScreenStackHeaderConfigState>;
|
|
17
|
+
|
|
18
|
+
RNSScreenStackHeaderConfigState() = default;
|
|
19
|
+
|
|
20
|
+
RNSScreenStackHeaderConfigState(Float paddingStart, Float paddingEnd)
|
|
21
|
+
: paddingStart_{paddingStart}, paddingEnd_{paddingEnd} {}
|
|
22
|
+
|
|
23
|
+
#ifdef ANDROID
|
|
24
|
+
RNSScreenStackHeaderConfigState(
|
|
25
|
+
RNSScreenStackHeaderConfigState const &previousState,
|
|
26
|
+
folly::dynamic data)
|
|
27
|
+
: paddingStart_{static_cast<Float>(data["paddingStart"].getDouble())},
|
|
28
|
+
paddingEnd_{static_cast<Float>(data["paddingEnd"].getDouble())} {}
|
|
29
|
+
#endif
|
|
30
|
+
|
|
31
|
+
#ifdef ANDROID
|
|
32
|
+
folly::dynamic getDynamic() const;
|
|
33
|
+
MapBuffer getMapBuffer() const {
|
|
34
|
+
return MapBufferBuilder::EMPTY();
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
#endif
|
|
38
|
+
|
|
39
|
+
#pragma mark - Getters
|
|
40
|
+
|
|
41
|
+
[[nodiscard]] Float getPaddingStart() const noexcept;
|
|
42
|
+
|
|
43
|
+
[[nodiscard]] Float getPaddingEnd() const noexcept;
|
|
44
|
+
|
|
45
|
+
private:
|
|
46
|
+
Float paddingStart_{0.f};
|
|
47
|
+
Float paddingEnd_{0.f};
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#ifdef ANDROID
|
|
4
|
+
#include <fbjni/fbjni.h>
|
|
5
|
+
#endif
|
|
6
|
+
#include <react/debug/react_native_assert.h>
|
|
7
|
+
#include <react/renderer/components/rnscreens/Props.h>
|
|
8
|
+
#include <react/renderer/components/rnscreens/utils/RectUtil.h>
|
|
9
|
+
#include <react/renderer/core/ConcreteComponentDescriptor.h>
|
|
10
|
+
#include "RNSScreenStackHeaderSubviewShadowNode.h"
|
|
11
|
+
|
|
12
|
+
namespace facebook::react {
|
|
13
|
+
|
|
14
|
+
using namespace rnscreens;
|
|
15
|
+
|
|
16
|
+
class RNSScreenStackHeaderSubviewComponentDescriptor final
|
|
17
|
+
: public ConcreteComponentDescriptor<
|
|
18
|
+
RNSScreenStackHeaderSubviewShadowNode> {
|
|
19
|
+
public:
|
|
20
|
+
using ConcreteComponentDescriptor::ConcreteComponentDescriptor;
|
|
21
|
+
|
|
22
|
+
void adopt(ShadowNode &shadowNode) const override {
|
|
23
|
+
ConcreteComponentDescriptor::adopt(shadowNode);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
} // namespace facebook::react
|
package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewShadowNode.h
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <jsi/jsi.h>
|
|
4
|
+
#include <react/renderer/components/rnscreens/EventEmitters.h>
|
|
5
|
+
#include <react/renderer/components/rnscreens/Props.h>
|
|
6
|
+
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
|
|
7
|
+
#include <react/renderer/core/LayoutContext.h>
|
|
8
|
+
#include "FrameCorrectionModes.h"
|
|
9
|
+
#include "RNSScreenStackHeaderSubviewState.h"
|
|
10
|
+
|
|
11
|
+
namespace facebook::react {
|
|
12
|
+
|
|
13
|
+
using namespace rnscreens;
|
|
14
|
+
|
|
15
|
+
JSI_EXPORT extern const char RNSScreenStackHeaderSubviewComponentName[];
|
|
16
|
+
|
|
17
|
+
class JSI_EXPORT RNSScreenStackHeaderSubviewShadowNode final
|
|
18
|
+
: public ConcreteViewShadowNode<
|
|
19
|
+
RNSScreenStackHeaderSubviewComponentName,
|
|
20
|
+
RNSScreenStackHeaderSubviewProps,
|
|
21
|
+
RNSScreenStackHeaderSubviewEventEmitter,
|
|
22
|
+
RNSScreenStackHeaderSubviewState> {
|
|
23
|
+
public:
|
|
24
|
+
using ConcreteViewShadowNode::ConcreteViewShadowNode;
|
|
25
|
+
using StateData = ConcreteViewShadowNode::ConcreteStateData;
|
|
26
|
+
|
|
27
|
+
#pragma mark - ShadowNode overrides
|
|
28
|
+
|
|
29
|
+
#pragma mark - Custom interface
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#include "RNSScreenStackHeaderSubviewState.h"
|
|
2
|
+
|
|
3
|
+
namespace facebook {
|
|
4
|
+
namespace react {
|
|
5
|
+
|
|
6
|
+
using namespace rnscreens;
|
|
7
|
+
|
|
8
|
+
#ifdef ANDROID
|
|
9
|
+
folly::dynamic RNSScreenStackHeaderSubviewState::getDynamic() const {
|
|
10
|
+
return folly::dynamic::object();
|
|
11
|
+
}
|
|
12
|
+
#endif
|
|
13
|
+
|
|
14
|
+
} // namespace react
|
|
15
|
+
} // namespace facebook
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <react/renderer/core/graphicsConversions.h>
|
|
4
|
+
#include <react/renderer/graphics/Float.h>
|
|
5
|
+
|
|
6
|
+
#ifdef ANDROID
|
|
7
|
+
#include <folly/dynamic.h>
|
|
8
|
+
#include <react/renderer/mapbuffer/MapBuffer.h>
|
|
9
|
+
#include <react/renderer/mapbuffer/MapBufferBuilder.h>
|
|
10
|
+
#endif
|
|
11
|
+
|
|
12
|
+
#include "FrameCorrectionModes.h"
|
|
13
|
+
|
|
14
|
+
namespace facebook::react {
|
|
15
|
+
|
|
16
|
+
using namespace rnscreens;
|
|
17
|
+
|
|
18
|
+
class JSI_EXPORT RNSScreenStackHeaderSubviewState final {
|
|
19
|
+
public:
|
|
20
|
+
using Shared = std::shared_ptr<const RNSScreenStackHeaderSubviewState>;
|
|
21
|
+
|
|
22
|
+
RNSScreenStackHeaderSubviewState() = default;
|
|
23
|
+
|
|
24
|
+
#ifdef ANDROID
|
|
25
|
+
RNSScreenStackHeaderSubviewState(
|
|
26
|
+
RNSScreenStackHeaderSubviewState const &previousState,
|
|
27
|
+
folly::dynamic data) {}
|
|
28
|
+
#endif
|
|
29
|
+
|
|
30
|
+
#ifdef ANDROID
|
|
31
|
+
folly::dynamic getDynamic() const;
|
|
32
|
+
MapBuffer getMapBuffer() const {
|
|
33
|
+
return MapBufferBuilder::EMPTY();
|
|
34
|
+
};
|
|
35
|
+
#endif
|
|
36
|
+
|
|
37
|
+
#pragma mark - Getters
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
} // namespace facebook::react
|
package/ios/RNSConvert.mm
CHANGED
|
@@ -53,7 +53,6 @@
|
|
|
53
53
|
switch (stackAnimation) {
|
|
54
54
|
// these four are intentionally grouped
|
|
55
55
|
case react::RNSScreenStackAnimation::Slide_from_right:
|
|
56
|
-
case react::RNSScreenStackAnimation::Ios:
|
|
57
56
|
case react::RNSScreenStackAnimation::Ios_from_right:
|
|
58
57
|
case react::RNSScreenStackAnimation::Default:
|
|
59
58
|
return RNSScreenStackAnimationDefault;
|
package/ios/RNSScreen.h
CHANGED
|
@@ -90,6 +90,7 @@ namespace react = facebook::react;
|
|
|
90
90
|
@property (nonatomic) NSNumber *sheetLargestUndimmedDetent;
|
|
91
91
|
@property (nonatomic) BOOL sheetGrabberVisible;
|
|
92
92
|
@property (nonatomic) CGFloat sheetCornerRadius;
|
|
93
|
+
@property (nonatomic) NSInteger sheetInitialDetent;
|
|
93
94
|
@property (nonatomic) BOOL sheetExpandsWhenScrolledToEdge;
|
|
94
95
|
#endif // !TARGET_OS_TV
|
|
95
96
|
|
|
@@ -99,6 +100,8 @@ namespace react = facebook::react;
|
|
|
99
100
|
@property (nonatomic) react::LayoutMetrics newLayoutMetrics;
|
|
100
101
|
@property (weak, nonatomic) RNSScreenStackHeaderConfig *config;
|
|
101
102
|
@property (nonatomic, readonly) BOOL hasHeaderConfig;
|
|
103
|
+
@property (nonatomic, readonly, getter=isMarkedForUnmountInCurrentTransaction)
|
|
104
|
+
BOOL markedForUnmountInCurrentTransaction;
|
|
102
105
|
#else
|
|
103
106
|
@property (nonatomic, copy) RCTDirectEventBlock onAppear;
|
|
104
107
|
@property (nonatomic, copy) RCTDirectEventBlock onDisappear;
|
|
@@ -123,6 +126,10 @@ namespace react = facebook::react;
|
|
|
123
126
|
- (void)updateBounds;
|
|
124
127
|
- (void)notifyDismissedWithCount:(int)dismissCount;
|
|
125
128
|
- (instancetype)initWithFrame:(CGRect)frame;
|
|
129
|
+
/// Tell `Screen` that it will be unmounted in next transaction.
|
|
130
|
+
/// The component needs this so that we can later decide whether to
|
|
131
|
+
/// replace it with snapshot or not.
|
|
132
|
+
- (void)willBeUnmountedInUpcomingTransaction;
|
|
126
133
|
#else
|
|
127
134
|
- (instancetype)initWithBridge:(RCTBridge *)bridge;
|
|
128
135
|
#endif // RCT_NEW_ARCH_ENABLED
|
|
@@ -132,6 +139,14 @@ namespace react = facebook::react;
|
|
|
132
139
|
- (BOOL)isModal;
|
|
133
140
|
- (BOOL)isPresentedAsNativeModal;
|
|
134
141
|
|
|
142
|
+
/**
|
|
143
|
+
* Tell `Screen` component that it has been removed from react state and can safely cleanup
|
|
144
|
+
* any retained resources.
|
|
145
|
+
*
|
|
146
|
+
* Note, that on old architecture this method might be called by RN via `RCTInvalidating` protocol.
|
|
147
|
+
*/
|
|
148
|
+
- (void)invalidate;
|
|
149
|
+
|
|
135
150
|
/// Looks for header configuration in instance's `reactSubviews` and returns it. If not present returns `nil`.
|
|
136
151
|
- (RNSScreenStackHeaderConfig *_Nullable)findHeaderConfig;
|
|
137
152
|
|
package/ios/RNSScreen.mm
CHANGED
|
@@ -123,6 +123,9 @@ constexpr NSInteger SHEET_LARGEST_UNDIMMED_DETENT_NONE = -1;
|
|
|
123
123
|
#endif // !TARGET_OS_TV
|
|
124
124
|
_sheetsScrollView = nil;
|
|
125
125
|
_didSetSheetAllowedDetentsOnController = NO;
|
|
126
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
127
|
+
_markedForUnmountInCurrentTransaction = NO;
|
|
128
|
+
#endif // RCT_NEW_ARCH_ENABLED
|
|
126
129
|
}
|
|
127
130
|
|
|
128
131
|
- (UIViewController *)reactViewController
|
|
@@ -304,11 +307,25 @@ constexpr NSInteger SHEET_LARGEST_UNDIMMED_DETENT_NONE = -1;
|
|
|
304
307
|
{
|
|
305
308
|
int activityState = [activityStateOrNil intValue];
|
|
306
309
|
if (activityStateOrNil != nil && activityState != -1 && activityState != _activityState) {
|
|
310
|
+
[self maybeAssertActivityStateProgressionOldValue:_activityState newValue:activityState];
|
|
307
311
|
_activityState = activityState;
|
|
308
312
|
[_reactSuperview markChildUpdated];
|
|
309
313
|
}
|
|
310
314
|
}
|
|
311
315
|
|
|
316
|
+
- (void)maybeAssertActivityStateProgressionOldValue:(int)oldValue newValue:(int)newValue
|
|
317
|
+
{
|
|
318
|
+
if (self.isNativeStackScreen && newValue < oldValue) {
|
|
319
|
+
RCTLogError(@"[RNScreens] activityState can only progress in NativeStack");
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/// Note that this method works only after the screen is actually mounted under a screen stack view.
|
|
324
|
+
- (BOOL)isNativeStackScreen
|
|
325
|
+
{
|
|
326
|
+
return [_reactSuperview isKindOfClass:RNSScreenStackView.class];
|
|
327
|
+
}
|
|
328
|
+
|
|
312
329
|
#if !TARGET_OS_TV && !TARGET_OS_VISION
|
|
313
330
|
- (void)setStatusBarStyle:(RNSStatusBarStyle)statusBarStyle
|
|
314
331
|
{
|
|
@@ -745,6 +762,12 @@ constexpr NSInteger SHEET_LARGEST_UNDIMMED_DETENT_NONE = -1;
|
|
|
745
762
|
self.controller.modalPresentationStyle == UIModalPresentationOverCurrentContext;
|
|
746
763
|
}
|
|
747
764
|
|
|
765
|
+
- (void)invalidate
|
|
766
|
+
{
|
|
767
|
+
_controller = nil;
|
|
768
|
+
[_sheetsScrollView removeObserver:self forKeyPath:@"bounds" context:nil];
|
|
769
|
+
}
|
|
770
|
+
|
|
748
771
|
#if !TARGET_OS_TV && !TARGET_OS_VISION
|
|
749
772
|
|
|
750
773
|
- (void)setPropertyForSheet:(UISheetPresentationController *)sheet
|
|
@@ -889,8 +912,8 @@ constexpr NSInteger SHEET_LARGEST_UNDIMMED_DETENT_NONE = -1;
|
|
|
889
912
|
sheet.delegate = self;
|
|
890
913
|
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_16_0) && \
|
|
891
914
|
__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_16_0
|
|
892
|
-
if (
|
|
893
|
-
if (
|
|
915
|
+
if (@available(iOS 16.0, *)) {
|
|
916
|
+
if (_sheetAllowedDetents.count > 0) {
|
|
894
917
|
if (_sheetAllowedDetents.count == 1 && [_sheetAllowedDetents[0] integerValue] == SHEET_FIT_TO_CONTENTS) {
|
|
895
918
|
// This is `fitToContents` case, where sheet should be just high to display its contents.
|
|
896
919
|
// Paper: we do not set anything here, we will set once React computed layout of our React's children, namely
|
|
@@ -944,6 +967,26 @@ constexpr NSInteger SHEET_LARGEST_UNDIMMED_DETENT_NONE = -1;
|
|
|
944
967
|
}
|
|
945
968
|
}
|
|
946
969
|
|
|
970
|
+
if (_sheetInitialDetent > 0 && _sheetInitialDetent < _sheetAllowedDetents.count) {
|
|
971
|
+
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_16_0) && \
|
|
972
|
+
__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_16_0
|
|
973
|
+
if (@available(iOS 16.0, *)) {
|
|
974
|
+
UISheetPresentationControllerDetent *detent = sheet.detents[_sheetInitialDetent];
|
|
975
|
+
[self setSelectedDetentForSheet:sheet to:detent.identifier animate:YES];
|
|
976
|
+
} else
|
|
977
|
+
#endif // Check for iOS >= 16
|
|
978
|
+
{
|
|
979
|
+
if (_sheetInitialDetent < 2) {
|
|
980
|
+
[self setSelectedDetentForSheet:sheet to:UISheetPresentationControllerDetentIdentifierLarge animate:YES];
|
|
981
|
+
} else {
|
|
982
|
+
RCTLogError(
|
|
983
|
+
@"[RNScreens] sheetInitialDetent out of bounds, on iOS versions below 16 sheetAllowedDetents is ignored in favor of an array of two system-defined detents");
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
} else if (_sheetInitialDetent != 0) {
|
|
987
|
+
RCTLogError(@"[RNScreens] sheetInitialDetent out of bounds for sheetAllowedDetents array");
|
|
988
|
+
}
|
|
989
|
+
|
|
947
990
|
sheet.prefersScrollingExpandsWhenScrolledToEdge = _sheetExpandsWhenScrolledToEdge;
|
|
948
991
|
[self setGrabberVisibleForSheet:sheet to:_sheetGrabberVisible animate:YES];
|
|
949
992
|
[self setCornerRadiusForSheet:sheet to:_sheetCornerRadius animate:YES];
|
|
@@ -1052,6 +1095,11 @@ constexpr NSInteger SHEET_LARGEST_UNDIMMED_DETENT_NONE = -1;
|
|
|
1052
1095
|
return _config != nil;
|
|
1053
1096
|
}
|
|
1054
1097
|
|
|
1098
|
+
- (void)willBeUnmountedInUpcomingTransaction
|
|
1099
|
+
{
|
|
1100
|
+
_markedForUnmountInCurrentTransaction = YES;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1055
1103
|
+ (react::ComponentDescriptorProvider)componentDescriptorProvider
|
|
1056
1104
|
{
|
|
1057
1105
|
return react::concreteComponentDescriptorProvider<react::RNSScreenComponentDescriptor>();
|
|
@@ -1151,6 +1199,10 @@ constexpr NSInteger SHEET_LARGEST_UNDIMMED_DETENT_NONE = -1;
|
|
|
1151
1199
|
[self setSheetAllowedDetents:[RNSConvert detentFractionsArrayFromVector:newScreenProps.sheetAllowedDetents]];
|
|
1152
1200
|
}
|
|
1153
1201
|
|
|
1202
|
+
if (newScreenProps.sheetInitialDetent != oldScreenProps.sheetInitialDetent) {
|
|
1203
|
+
[self setSheetInitialDetent:newScreenProps.sheetInitialDetent];
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1154
1206
|
if (newScreenProps.sheetLargestUndimmedDetent != oldScreenProps.sheetLargestUndimmedDetent) {
|
|
1155
1207
|
[self setSheetLargestUndimmedDetent:[NSNumber numberWithInt:newScreenProps.sheetLargestUndimmedDetent]];
|
|
1156
1208
|
}
|
|
@@ -1237,11 +1289,6 @@ constexpr NSInteger SHEET_LARGEST_UNDIMMED_DETENT_NONE = -1;
|
|
|
1237
1289
|
// subviews
|
|
1238
1290
|
}
|
|
1239
1291
|
|
|
1240
|
-
- (void)invalidate
|
|
1241
|
-
{
|
|
1242
|
-
_controller = nil;
|
|
1243
|
-
[_sheetsScrollView removeObserver:self forKeyPath:@"bounds" context:nil];
|
|
1244
|
-
}
|
|
1245
1292
|
#endif
|
|
1246
1293
|
|
|
1247
1294
|
@end
|
|
@@ -1864,6 +1911,7 @@ RCT_EXPORT_VIEW_PROPERTY(sheetAllowedDetents, NSArray<NSNumber *> *);
|
|
|
1864
1911
|
RCT_EXPORT_VIEW_PROPERTY(sheetLargestUndimmedDetent, NSNumber *);
|
|
1865
1912
|
RCT_EXPORT_VIEW_PROPERTY(sheetGrabberVisible, BOOL);
|
|
1866
1913
|
RCT_EXPORT_VIEW_PROPERTY(sheetCornerRadius, CGFloat);
|
|
1914
|
+
RCT_EXPORT_VIEW_PROPERTY(sheetInitialDetent, NSInteger);
|
|
1867
1915
|
RCT_EXPORT_VIEW_PROPERTY(sheetExpandsWhenScrolledToEdge, BOOL);
|
|
1868
1916
|
#endif
|
|
1869
1917
|
|
|
@@ -1936,7 +1984,6 @@ RCT_ENUM_CONVERTER(
|
|
|
1936
1984
|
@"slide_from_bottom" : @(RNSScreenStackAnimationSlideFromBottom),
|
|
1937
1985
|
@"slide_from_right" : @(RNSScreenStackAnimationDefault),
|
|
1938
1986
|
@"slide_from_left" : @(RNSScreenStackAnimationSlideFromLeft),
|
|
1939
|
-
@"ios" : @(RNSScreenStackAnimationDefault),
|
|
1940
1987
|
@"ios_from_right" : @(RNSScreenStackAnimationDefault),
|
|
1941
1988
|
@"ios_from_left" : @(RNSScreenStackAnimationSlideFromLeft),
|
|
1942
1989
|
}),
|
package/ios/RNSScreenStack.mm
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
#import "RNSScreenStackAnimator.h"
|
|
26
26
|
#import "RNSScreenStackHeaderConfig.h"
|
|
27
27
|
#import "RNSScreenWindowTraits.h"
|
|
28
|
+
#import "utils/UINavigationBar+RNSUtility.h"
|
|
28
29
|
|
|
29
30
|
#import "UIView+RNSUtility.h"
|
|
30
31
|
|
|
@@ -82,6 +83,8 @@ namespace react = facebook::react;
|
|
|
82
83
|
if (![screenController hasNestedStack] && isNotDismissingModal) {
|
|
83
84
|
[screenController calculateAndNotifyHeaderHeightChangeIsModal:NO];
|
|
84
85
|
}
|
|
86
|
+
|
|
87
|
+
[self maybeUpdateHeaderInsetsInShadowTreeForScreen:screenController];
|
|
85
88
|
}
|
|
86
89
|
}
|
|
87
90
|
|
|
@@ -94,6 +97,35 @@ namespace react = facebook::react;
|
|
|
94
97
|
{
|
|
95
98
|
return [self topViewController];
|
|
96
99
|
}
|
|
100
|
+
|
|
101
|
+
- (void)maybeUpdateHeaderInsetsInShadowTreeForScreen:(RNSScreen *)screenController
|
|
102
|
+
{
|
|
103
|
+
// This might happen e.g. if there is only native title present in navigation bar.
|
|
104
|
+
if (self.navigationBar.subviews.count < 2) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
auto headerConfig = screenController.screenView.findHeaderConfig;
|
|
109
|
+
if (headerConfig == nil || !headerConfig.shouldHeaderBeVisible) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
NSDirectionalEdgeInsets navBarMargins = [self.navigationBar directionalLayoutMargins];
|
|
114
|
+
NSDirectionalEdgeInsets navBarContentMargins =
|
|
115
|
+
[self.navigationBar.rnscreens_findContentView directionalLayoutMargins];
|
|
116
|
+
|
|
117
|
+
BOOL isDisplayingBackButton = [headerConfig shouldBackButtonBeVisibleInNavigationBar:self.navigationBar];
|
|
118
|
+
|
|
119
|
+
// 44.0 is just "closed eyes default". It is so on device I've tested with, nothing more.
|
|
120
|
+
UIView *barButtonView = isDisplayingBackButton ? self.navigationBar.rnscreens_findBackButtonWrapperView : nil;
|
|
121
|
+
CGFloat platformBackButtonWidth = barButtonView != nil ? barButtonView.frame.size.width : 44.0f;
|
|
122
|
+
|
|
123
|
+
[headerConfig updateHeaderInsetsInShadowTreeTo:NSDirectionalEdgeInsets{
|
|
124
|
+
.leading = navBarMargins.leading + navBarContentMargins.leading +
|
|
125
|
+
(isDisplayingBackButton ? platformBackButtonWidth : 0),
|
|
126
|
+
.trailing = navBarMargins.trailing + navBarContentMargins.trailing,
|
|
127
|
+
}];
|
|
128
|
+
}
|
|
97
129
|
#endif
|
|
98
130
|
|
|
99
131
|
@end
|
|
@@ -120,6 +152,13 @@ namespace react = facebook::react;
|
|
|
120
152
|
UIPercentDrivenInteractiveTransition *_interactionController;
|
|
121
153
|
__weak RNSScreenStackManager *_manager;
|
|
122
154
|
BOOL _updateScheduled;
|
|
155
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
156
|
+
/// Screens that are subject of `ShadowViewMutation::Type::Delete` mutation
|
|
157
|
+
/// in current transaction. This vector should be populated when we receive notification via
|
|
158
|
+
/// `RCTMountingObserving` protocol, that a transaction will be performed, and should
|
|
159
|
+
/// be cleaned up when we're notified that the transaction has been completed.
|
|
160
|
+
std::vector<__strong RNSScreenView *> _toBeDeletedScreens;
|
|
161
|
+
#endif // RCT_NEW_ARCH_ENABLED
|
|
123
162
|
}
|
|
124
163
|
|
|
125
164
|
#ifdef RCT_NEW_ARCH_ENABLED
|
|
@@ -641,7 +680,7 @@ namespace react = facebook::react;
|
|
|
641
680
|
NSMutableArray<UIViewController *> *pushControllers = [NSMutableArray new];
|
|
642
681
|
NSMutableArray<UIViewController *> *modalControllers = [NSMutableArray new];
|
|
643
682
|
for (RNSScreenView *screen in _reactSubviews) {
|
|
644
|
-
if (!screen.dismissed && screen.controller != nil) {
|
|
683
|
+
if (!screen.dismissed && screen.controller != nil && screen.activityState != RNSActivityStateInactive) {
|
|
645
684
|
if (pushControllers.count == 0) {
|
|
646
685
|
// first screen on the list needs to be places as "push controller"
|
|
647
686
|
[pushControllers addObject:screen.controller];
|
|
@@ -914,7 +953,8 @@ namespace react = facebook::react;
|
|
|
914
953
|
|
|
915
954
|
- (void)markChildUpdated
|
|
916
955
|
{
|
|
917
|
-
//
|
|
956
|
+
// In native stack this should be called only for `preload` purposes.
|
|
957
|
+
[self updateContainer];
|
|
918
958
|
}
|
|
919
959
|
|
|
920
960
|
- (void)didUpdateChildren
|
|
@@ -1118,6 +1158,16 @@ namespace react = facebook::react;
|
|
|
1118
1158
|
// `- [RNSScreenStackView mountingTransactionDidMount: withSurfaceTelemetry:]`
|
|
1119
1159
|
}
|
|
1120
1160
|
|
|
1161
|
+
- (nullable RNSScreenView *)childScreenForTag:(react::Tag)tag
|
|
1162
|
+
{
|
|
1163
|
+
for (RNSScreenView *child in _reactSubviews) {
|
|
1164
|
+
if (child.tag == tag) {
|
|
1165
|
+
return child;
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
return nil;
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1121
1171
|
- (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
|
|
1122
1172
|
{
|
|
1123
1173
|
RNSScreenView *screenChildComponent = (RNSScreenView *)childComponentView;
|
|
@@ -1151,6 +1201,20 @@ namespace react = facebook::react;
|
|
|
1151
1201
|
[screenChildComponent removeFromSuperview];
|
|
1152
1202
|
}
|
|
1153
1203
|
|
|
1204
|
+
- (void)mountingTransactionWillMount:(const facebook::react::MountingTransaction &)transaction
|
|
1205
|
+
withSurfaceTelemetry:(const facebook::react::SurfaceTelemetry &)surfaceTelemetry
|
|
1206
|
+
{
|
|
1207
|
+
for (const auto &mutation : transaction.getMutations()) {
|
|
1208
|
+
if (mutation.type == react::ShadowViewMutation::Delete) {
|
|
1209
|
+
RNSScreenView *_Nullable toBeRemovedChild = [self childScreenForTag:mutation.oldChildShadowView.tag];
|
|
1210
|
+
if (toBeRemovedChild != nil) {
|
|
1211
|
+
[toBeRemovedChild willBeUnmountedInUpcomingTransaction];
|
|
1212
|
+
_toBeDeletedScreens.push_back(toBeRemovedChild);
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1154
1218
|
- (void)mountingTransactionDidMount:(const facebook::react::MountingTransaction &)transaction
|
|
1155
1219
|
withSurfaceTelemetry:(const facebook::react::SurfaceTelemetry &)surfaceTelemetry
|
|
1156
1220
|
{
|
|
@@ -1167,6 +1231,21 @@ namespace react = facebook::react;
|
|
|
1167
1231
|
break;
|
|
1168
1232
|
}
|
|
1169
1233
|
}
|
|
1234
|
+
|
|
1235
|
+
if (!self->_toBeDeletedScreens.empty()) {
|
|
1236
|
+
__weak RNSScreenStackView *weakSelf = self;
|
|
1237
|
+
// We want to run after container updates are performed (transitions etc.)
|
|
1238
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
1239
|
+
RNSScreenStackView *_Nullable strongSelf = weakSelf;
|
|
1240
|
+
if (strongSelf == nil) {
|
|
1241
|
+
return;
|
|
1242
|
+
}
|
|
1243
|
+
for (RNSScreenView *screenRef : strongSelf->_toBeDeletedScreens) {
|
|
1244
|
+
[screenRef invalidate];
|
|
1245
|
+
}
|
|
1246
|
+
strongSelf->_toBeDeletedScreens.clear();
|
|
1247
|
+
});
|
|
1248
|
+
}
|
|
1170
1249
|
}
|
|
1171
1250
|
|
|
1172
1251
|
- (void)prepareForRecycle
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#ifdef RCT_NEW_ARCH_ENABLED
|
|
2
2
|
#import <React/RCTViewComponentView.h>
|
|
3
3
|
#else
|
|
4
|
+
#import <React/RCTShadowView.h>
|
|
4
5
|
#import <React/RCTViewManager.h>
|
|
5
6
|
#endif
|
|
6
7
|
|
|
@@ -61,12 +62,74 @@
|
|
|
61
62
|
animated:(BOOL)animated
|
|
62
63
|
withConfig:(RNSScreenStackHeaderConfig *)config;
|
|
63
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Allows to send information with insets to the corresponding node in shadow tree.
|
|
67
|
+
* Currently only horizontal insets are send through. Vertical ones are filtered out.
|
|
68
|
+
*/
|
|
69
|
+
- (void)updateHeaderInsetsInShadowTreeTo:(NSDirectionalEdgeInsets)insets;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Returns true iff subview of given `type` is present.
|
|
73
|
+
*
|
|
74
|
+
* **Please note that the subviews are not mounted under the header config in HostTree**
|
|
75
|
+
* This method should serve only to check whether given subview type has been rendered.
|
|
76
|
+
*/
|
|
77
|
+
- (BOOL)hasSubviewOfType:(RNSScreenStackHeaderSubviewType)type;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Returns `true` iff subview of type `left` is present.
|
|
81
|
+
*
|
|
82
|
+
* **Please note that the subviews are not mounted under the header config in HostTree**
|
|
83
|
+
* This method should serve only to check whether given subview type has been rendered.
|
|
84
|
+
*/
|
|
85
|
+
- (BOOL)hasSubviewLeft;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Returns
|
|
89
|
+
* - `YES` on Paper, when `self.hide == NO`
|
|
90
|
+
* - `YES` on Fabric, when `self.show == YES`
|
|
91
|
+
* - `NO` otherwise.
|
|
92
|
+
*
|
|
93
|
+
* Convenience method, so that we do not need ifdefs in every callsite.
|
|
94
|
+
*/
|
|
95
|
+
- (BOOL)shouldHeaderBeVisible;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @returns`true` iff the applying this header config instance to a view controller will
|
|
99
|
+
* result in visible back button if feasible.
|
|
100
|
+
*/
|
|
101
|
+
- (BOOL)shouldBackButtonBeVisibleInNavigationBar:(nullable UINavigationBar *)navBar;
|
|
102
|
+
|
|
64
103
|
@end
|
|
65
104
|
|
|
66
105
|
@interface RNSScreenStackHeaderConfigManager : RCTViewManager
|
|
67
106
|
|
|
68
107
|
@end
|
|
69
108
|
|
|
109
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
110
|
+
#else
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Used as local data send to shadow view on Paper. This helps us to provide Yoga
|
|
114
|
+
* with knowledge of native insets in the navigation bar.
|
|
115
|
+
*/
|
|
116
|
+
@interface RNSHeaderConfigInsetsPayload : NSObject
|
|
117
|
+
|
|
118
|
+
@property (nonatomic) NSDirectionalEdgeInsets insets;
|
|
119
|
+
|
|
120
|
+
- (instancetype)initWithInsets:(NSDirectionalEdgeInsets)insets NS_DESIGNATED_INITIALIZER;
|
|
121
|
+
|
|
122
|
+
@end
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Custom shadow view for header config. This is used on Paper to provide Yoga
|
|
126
|
+
* with knowledge of native header insets (horizontal padding).
|
|
127
|
+
*/
|
|
128
|
+
@interface RNSScreenStackHeaderConfigShadowView : RCTShadowView
|
|
129
|
+
|
|
130
|
+
@end
|
|
131
|
+
#endif
|
|
132
|
+
|
|
70
133
|
@interface RCTConvert (RNSScreenStackHeader)
|
|
71
134
|
|
|
72
135
|
+ (UIBlurEffectStyle)UIBlurEffectStyle:(id)json;
|