react-native-screens 4.0.0-beta.5 → 4.0.0-beta.7

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.
Files changed (52) hide show
  1. package/android/src/fabric/java/com/swmansion/rnscreens/FabricEnabledHeaderConfigViewGroup.kt +61 -0
  2. package/android/src/main/java/com/swmansion/rnscreens/CustomToolbar.kt +14 -0
  3. package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +1 -1
  4. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.kt +1 -2
  5. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigShadowNode.kt +25 -0
  6. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigViewManager.kt +18 -0
  7. package/android/src/main/java/com/swmansion/rnscreens/utils/PaddingBundle.kt +8 -0
  8. package/android/src/main/jni/rnscreens.h +2 -0
  9. package/android/src/paper/java/com/swmansion/rnscreens/FabricEnabledHeaderConfigViewGroup.kt +39 -0
  10. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigComponentDescriptor.h +44 -0
  11. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigShadowNode.cpp +8 -0
  12. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigShadowNode.h +32 -0
  13. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigState.cpp +23 -0
  14. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigState.h +50 -0
  15. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewComponentDescriptor.h +27 -0
  16. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewShadowNode.cpp +8 -0
  17. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewShadowNode.h +32 -0
  18. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewState.cpp +15 -0
  19. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewState.h +40 -0
  20. package/ios/RNSScreenStack.mm +32 -0
  21. package/ios/RNSScreenStackHeaderConfig.h +63 -0
  22. package/ios/RNSScreenStackHeaderConfig.mm +126 -9
  23. package/ios/RNSScreenStackHeaderSubview.mm +26 -0
  24. package/ios/utils/UINavigationBar+RNSUtility.h +37 -0
  25. package/ios/utils/UINavigationBar+RNSUtility.mm +44 -0
  26. package/ios/utils/UIView+RNSUtility.mm +0 -1
  27. package/lib/commonjs/components/Screen.js +6 -4
  28. package/lib/commonjs/components/Screen.js.map +1 -1
  29. package/lib/commonjs/components/ScreenStackHeaderConfig.js +49 -17
  30. package/lib/commonjs/components/ScreenStackHeaderConfig.js.map +1 -1
  31. package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js +3 -1
  32. package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
  33. package/lib/commonjs/fabric/ScreenStackHeaderSubviewNativeComponent.js +3 -1
  34. package/lib/commonjs/fabric/ScreenStackHeaderSubviewNativeComponent.js.map +1 -1
  35. package/lib/module/components/Screen.js +6 -4
  36. package/lib/module/components/Screen.js.map +1 -1
  37. package/lib/module/components/ScreenStackHeaderConfig.js +46 -16
  38. package/lib/module/components/ScreenStackHeaderConfig.js.map +1 -1
  39. package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js +3 -1
  40. package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
  41. package/lib/module/fabric/ScreenStackHeaderSubviewNativeComponent.js +3 -1
  42. package/lib/module/fabric/ScreenStackHeaderSubviewNativeComponent.js.map +1 -1
  43. package/lib/typescript/components/Screen.d.ts.map +1 -1
  44. package/lib/typescript/components/ScreenStackHeaderConfig.d.ts +1 -1
  45. package/lib/typescript/components/ScreenStackHeaderConfig.d.ts.map +1 -1
  46. package/lib/typescript/fabric/ScreenStackHeaderConfigNativeComponent.d.ts.map +1 -1
  47. package/lib/typescript/fabric/ScreenStackHeaderSubviewNativeComponent.d.ts.map +1 -1
  48. package/package.json +1 -1
  49. package/src/components/Screen.tsx +6 -4
  50. package/src/components/ScreenStackHeaderConfig.tsx +55 -26
  51. package/src/fabric/ScreenStackHeaderConfigNativeComponent.ts +3 -1
  52. package/src/fabric/ScreenStackHeaderSubviewNativeComponent.ts +3 -1
@@ -0,0 +1,61 @@
1
+ package com.swmansion.rnscreens
2
+
3
+ import android.content.Context
4
+ import android.view.ViewGroup
5
+ import androidx.annotation.UiThread
6
+ import com.facebook.react.bridge.WritableMap
7
+ import com.facebook.react.bridge.WritableNativeMap
8
+ import com.facebook.react.uimanager.PixelUtil
9
+ import com.facebook.react.uimanager.StateWrapper
10
+ import kotlin.math.abs
11
+
12
+ abstract class FabricEnabledHeaderConfigViewGroup(
13
+ context: Context?,
14
+ ) : ViewGroup(context) {
15
+ private var mStateWrapper: StateWrapper? = null
16
+
17
+ private var lastPaddingStart = 0f
18
+ private var lastPaddingEnd = 0f
19
+
20
+ fun setStateWrapper(wrapper: StateWrapper?) {
21
+ mStateWrapper = wrapper
22
+ }
23
+
24
+ fun updatePaddingsFabric(
25
+ paddingStart: Int,
26
+ paddingEnd: Int,
27
+ ) {
28
+ updateState(paddingStart, paddingEnd)
29
+ }
30
+
31
+ @UiThread
32
+ fun updateState(
33
+ paddingStart: Int,
34
+ paddingEnd: Int,
35
+ ) {
36
+ val paddingStartDip: Float = PixelUtil.toDIPFromPixel(paddingStart.toFloat())
37
+ val paddingEndDip: Float = PixelUtil.toDIPFromPixel(paddingEnd.toFloat())
38
+
39
+ // Check incoming state values. If they're already the correct value, return early to prevent
40
+ // infinite UpdateState/SetState loop.
41
+ if (abs(lastPaddingStart - paddingStart) < DELTA &&
42
+ abs(lastPaddingEnd - paddingEnd) < DELTA
43
+ ) {
44
+ return
45
+ }
46
+
47
+ lastPaddingStart = paddingStartDip
48
+ lastPaddingEnd = paddingEndDip
49
+
50
+ val map: WritableMap =
51
+ WritableNativeMap().apply {
52
+ putDouble("paddingStart", paddingStartDip.toDouble())
53
+ putDouble("paddingEnd", paddingEndDip.toDouble())
54
+ }
55
+ mStateWrapper?.updateState(map)
56
+ }
57
+
58
+ companion object {
59
+ private const val DELTA = 0.9f
60
+ }
61
+ }
@@ -48,4 +48,18 @@ open class CustomToolbar(
48
48
  }
49
49
  }
50
50
  }
51
+
52
+ override fun onLayout(
53
+ changed: Boolean,
54
+ l: Int,
55
+ t: Int,
56
+ r: Int,
57
+ b: Int,
58
+ ) {
59
+ super.onLayout(changed, l, t, r, b)
60
+
61
+ // our children are already laid out
62
+ val contentInsetStart = if (navigationIcon != null) contentInsetStartWithNavigation else contentInsetStart
63
+ config.updatePaddingsFabric(contentInsetStart, contentInsetEnd)
64
+ }
51
65
  }
@@ -441,7 +441,7 @@ class Screen(
441
441
  if (stackPresentation !== StackPresentation.FORM_SHEET || background == null) {
442
442
  return
443
443
  }
444
- (background as MaterialShapeDrawable?)?.let {
444
+ (background as? MaterialShapeDrawable?)?.let {
445
445
  val resolvedCornerRadius = PixelUtil.toDIPFromPixel(sheetCornerRadius)
446
446
  it.shapeAppearanceModel =
447
447
  ShapeAppearanceModel
@@ -8,7 +8,6 @@ import android.text.TextUtils
8
8
  import android.util.TypedValue
9
9
  import android.view.Gravity
10
10
  import android.view.View.OnClickListener
11
- import android.view.ViewGroup
12
11
  import android.view.WindowInsets
13
12
  import android.widget.ImageView
14
13
  import android.widget.TextView
@@ -25,7 +24,7 @@ import com.swmansion.rnscreens.events.HeaderDetachedEvent
25
24
 
26
25
  class ScreenStackHeaderConfig(
27
26
  context: Context,
28
- ) : ViewGroup(context) {
27
+ ) : FabricEnabledHeaderConfigViewGroup(context) {
29
28
  private val configSubviews = ArrayList<ScreenStackHeaderSubview>(3)
30
29
  val toolbar: CustomToolbar
31
30
  var isHeaderHidden = false // named this way to avoid conflict with platform's isHidden
@@ -0,0 +1,25 @@
1
+ package com.swmansion.rnscreens
2
+
3
+ import com.facebook.react.bridge.ReactContext
4
+ import com.facebook.react.uimanager.LayoutShadowNode
5
+ import com.facebook.react.uimanager.Spacing
6
+ import com.swmansion.rnscreens.utils.PaddingBundle
7
+
8
+ internal class ScreenStackHeaderConfigShadowNode(
9
+ private var context: ReactContext,
10
+ ) : LayoutShadowNode() {
11
+ var paddingStart: Float = 0f
12
+ var paddingEnd: Float = 0f
13
+
14
+ override fun setLocalData(data: Any?) {
15
+ if (data is PaddingBundle) {
16
+ paddingStart = data.paddingStart
17
+ paddingEnd = data.paddingEnd
18
+
19
+ setPadding(Spacing.START, paddingStart)
20
+ setPadding(Spacing.END, paddingEnd)
21
+ } else {
22
+ super.setLocalData(data)
23
+ }
24
+ }
25
+ }
@@ -3,8 +3,12 @@ package com.swmansion.rnscreens
3
3
  import android.util.Log
4
4
  import android.view.View
5
5
  import com.facebook.react.bridge.JSApplicationCausedNativeException
6
+ import com.facebook.react.bridge.ReactApplicationContext
6
7
  import com.facebook.react.common.MapBuilder
7
8
  import com.facebook.react.module.annotations.ReactModule
9
+ import com.facebook.react.uimanager.LayoutShadowNode
10
+ import com.facebook.react.uimanager.ReactStylesDiffMap
11
+ import com.facebook.react.uimanager.StateWrapper
8
12
  import com.facebook.react.uimanager.ThemedReactContext
9
13
  import com.facebook.react.uimanager.ViewGroupManager
10
14
  import com.facebook.react.uimanager.ViewManagerDelegate
@@ -29,6 +33,9 @@ class ScreenStackHeaderConfigViewManager :
29
33
 
30
34
  override fun createViewInstance(reactContext: ThemedReactContext) = ScreenStackHeaderConfig(reactContext)
31
35
 
36
+ // This works only on Paper. On Fabric the shadow node is implemented in C++ layer.
37
+ override fun createShadowNodeInstance(context: ReactApplicationContext): LayoutShadowNode = ScreenStackHeaderConfigShadowNode(context)
38
+
32
39
  override fun addView(
33
40
  parent: ScreenStackHeaderConfig,
34
41
  child: View,
@@ -42,6 +49,17 @@ class ScreenStackHeaderConfigViewManager :
42
49
  parent.addConfigSubview(child, index)
43
50
  }
44
51
 
52
+ override fun updateState(
53
+ view: ScreenStackHeaderConfig,
54
+ props: ReactStylesDiffMap?,
55
+ stateWrapper: StateWrapper?,
56
+ ): Any? {
57
+ if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
58
+ view.setStateWrapper(stateWrapper)
59
+ }
60
+ return super.updateState(view, props, stateWrapper)
61
+ }
62
+
45
63
  override fun onDropViewInstance(
46
64
  @Nonnull view: ScreenStackHeaderConfig,
47
65
  ) {
@@ -0,0 +1,8 @@
1
+ package com.swmansion.rnscreens.utils
2
+
3
+ // Used only on Paper together with `setLocalData` mechanism to pass
4
+ // the information on header paddings to shadow node.
5
+ data class PaddingBundle(
6
+ val paddingStart: Float,
7
+ val paddingEnd: Float,
8
+ )
@@ -18,6 +18,8 @@
18
18
  */
19
19
  #include <react/renderer/components/rnscreens/RNSScreenComponentDescriptor.h>
20
20
  #include <react/renderer/components/rnscreens/RNSModalScreenComponentDescriptor.h>
21
+ #include <react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewComponentDescriptor.h>
22
+ #include <react/renderer/components/rnscreens/RNSScreenStackHeaderConfigComponentDescriptor.h>
21
23
 
22
24
  namespace facebook {
23
25
  namespace react {
@@ -0,0 +1,39 @@
1
+ package com.swmansion.rnscreens
2
+
3
+ import android.content.Context
4
+ import android.view.ViewGroup
5
+ import com.facebook.react.bridge.ReactContext
6
+ import com.facebook.react.uimanager.StateWrapper
7
+ import com.facebook.react.uimanager.UIManagerModule
8
+ import com.swmansion.rnscreens.utils.PaddingBundle
9
+ import kotlin.math.abs
10
+
11
+ abstract class FabricEnabledHeaderConfigViewGroup(
12
+ context: Context,
13
+ ) : ViewGroup(context) {
14
+ private var lastPaddingStart = 0
15
+ private var lastPaddingEnd = 0
16
+
17
+ fun setStateWrapper(wrapper: StateWrapper?) = Unit
18
+
19
+ fun updatePaddingsFabric(
20
+ paddingStart: Int,
21
+ paddingEnd: Int,
22
+ ) {
23
+ // Note that on Paper we do not convert these props from px to dip. This is done internally by RN.
24
+ if (abs(lastPaddingStart - paddingStart) < DELTA && abs(lastPaddingEnd - paddingEnd) < DELTA) {
25
+ return
26
+ }
27
+
28
+ lastPaddingStart = paddingStart
29
+ lastPaddingEnd = paddingEnd
30
+
31
+ val reactContext = context as? ReactContext
32
+ val uiManagerModule = reactContext?.getNativeModule(UIManagerModule::class.java)
33
+ uiManagerModule?.setViewLocalData(this.id, PaddingBundle(paddingStart.toFloat(), paddingEnd.toFloat()))
34
+ }
35
+
36
+ companion object {
37
+ private const val DELTA = 0.9
38
+ }
39
+ }
@@ -0,0 +1,44 @@
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 "RNSScreenStackHeaderConfigShadowNode.h"
11
+
12
+ namespace facebook::react {
13
+
14
+ using namespace rnscreens;
15
+
16
+ class RNSScreenStackHeaderConfigComponentDescriptor final
17
+ : public ConcreteComponentDescriptor<RNSScreenStackHeaderConfigShadowNode> {
18
+ public:
19
+ using ConcreteComponentDescriptor::ConcreteComponentDescriptor;
20
+
21
+ void adopt(ShadowNode &shadowNode) const override {
22
+ react_native_assert(
23
+ dynamic_cast<RNSScreenStackHeaderConfigShadowNode *>(&shadowNode));
24
+ auto &configShadowNode =
25
+ static_cast<RNSScreenStackHeaderConfigShadowNode &>(shadowNode);
26
+
27
+ react_native_assert(
28
+ dynamic_cast<YogaLayoutableShadowNode *>(&configShadowNode));
29
+ auto &layoutableShadowNode =
30
+ dynamic_cast<YogaLayoutableShadowNode &>(configShadowNode);
31
+
32
+ auto state = std::static_pointer_cast<
33
+ const RNSScreenStackHeaderConfigShadowNode::ConcreteState>(
34
+ shadowNode.getState());
35
+ auto stateData = state->getData();
36
+
37
+ layoutableShadowNode.setPadding(
38
+ {stateData.getPaddingStart(), 0, stateData.getPaddingEnd(), 0});
39
+
40
+ ConcreteComponentDescriptor::adopt(shadowNode);
41
+ }
42
+ };
43
+
44
+ } // namespace facebook::react
@@ -0,0 +1,8 @@
1
+ #include "RNSScreenStackHeaderConfigShadowNode.h"
2
+
3
+ namespace facebook::react {
4
+
5
+ extern const char RNSScreenStackHeaderConfigComponentName[] =
6
+ "RNSScreenStackHeaderConfig";
7
+
8
+ }
@@ -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
@@ -0,0 +1,8 @@
1
+ #include "RNSScreenStackHeaderSubviewShadowNode.h"
2
+
3
+ namespace facebook::react {
4
+
5
+ extern const char RNSScreenStackHeaderSubviewComponentName[] =
6
+ "RNSScreenStackHeaderSubview";
7
+
8
+ }
@@ -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
@@ -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
@@ -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;