Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: clicking on Pressable located in screen header #2466

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
0044582
remove header offset from RNSScreenStackHeaderConfigShadowNode
coado Oct 29, 2024
fa6ba8c
remove top: '-100%' from ScreenStackHeaderConfig
coado Oct 29, 2024
47212d4
rename topInsetOffset to paddingTop in RNSScreenStackHeaderConfigShad…
coado Oct 29, 2024
7aa8889
Merge branch 'main' into @dmalecki/pressable-in-header
coado Nov 13, 2024
0d80a85
header config frame
coado Nov 13, 2024
8047046
header config state
coado Nov 13, 2024
76681bb
header subview frame size update
coado Nov 13, 2024
92b899a
header subview frame corrections
coado Nov 14, 2024
cfb237e
remove unused import
coado Nov 14, 2024
83fb6f4
flattened header subviews
coado Nov 15, 2024
5d6716d
iOS frame metrics
coado Nov 15, 2024
b3ebaf5
flattening
coado Nov 19, 2024
b9e0124
fix Android
coado Nov 19, 2024
aad021a
fix layout iOS subviews
coado Nov 19, 2024
43ddcb2
header config and subviews position
coado Nov 26, 2024
eca6580
fix not completed layout
coado Nov 26, 2024
0823b03
fix subview hit test bug
coado Nov 26, 2024
61f2f9d
hit testing flattened views on iOS
coado Nov 26, 2024
3b5ee9d
sending subviews frames on fabric
coado Nov 26, 2024
f07b8de
merge
coado Nov 26, 2024
d6e1597
fix Android build paper
coado Nov 28, 2024
723e8a9
FabricEnabledHeaderSubviewGroup empty line
coado Nov 28, 2024
b71e62e
remove RNSScreenStackHeaderConfigShadowNode include
coado Nov 28, 2024
8541afc
remove unused origin from header config state
coado Nov 28, 2024
396abd4
caching header config size, iOS
coado Nov 28, 2024
9799d47
_lastSize recycle
coado Nov 28, 2024
f7bfbd7
remove sending top inset, paper
coado Nov 28, 2024
c71ce45
fix Android build
coado Nov 28, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -14,43 +14,50 @@ abstract class FabricEnabledHeaderConfigViewGroup(
) : ViewGroup(context) {
private var mStateWrapper: StateWrapper? = null

private var lastPaddingStart = 0f
private var lastPaddingEnd = 0f
private var lastWidth = 0f
private var lastHeight = 0f

fun setStateWrapper(wrapper: StateWrapper?) {
mStateWrapper = wrapper
}

fun updatePaddingsFabric(
fun updatePaddings(
paddingStart: Int,
paddingEnd: Int,
paddingEnd: Int
) {
updateState(paddingStart, paddingEnd)
// do nothing
}

fun updateHeaderConfigState(
width: Int,
height: Int,
) {
updateState(width, height)
}

@UiThread
fun updateState(
paddingStart: Int,
paddingEnd: Int,
width: Int,
height: Int,
) {
val paddingStartDip: Float = PixelUtil.toDIPFromPixel(paddingStart.toFloat())
val paddingEndDip: Float = PixelUtil.toDIPFromPixel(paddingEnd.toFloat())
val realWidth: Float = PixelUtil.toDIPFromPixel(width.toFloat())
val realHeight: Float = PixelUtil.toDIPFromPixel(height.toFloat())

// Check incoming state values. If they're already the correct value, return early to prevent
// infinite UpdateState/SetState loop.
if (abs(lastPaddingStart - paddingStart) < DELTA &&
abs(lastPaddingEnd - paddingEnd) < DELTA
if (abs(lastWidth - realWidth) < DELTA &&
abs(lastHeight - realHeight) < DELTA
) {
return
}

lastPaddingStart = paddingStartDip
lastPaddingEnd = paddingEndDip
lastWidth = realWidth
lastHeight = realHeight

val map: WritableMap =
WritableNativeMap().apply {
putDouble("paddingStart", paddingStartDip.toDouble())
putDouble("paddingEnd", paddingEndDip.toDouble())
putDouble("frameWidth", realWidth.toDouble())
putDouble("frameHeight", realHeight.toDouble())
}
mStateWrapper?.updateState(map)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.swmansion.rnscreens

import android.content.Context
import android.view.ViewGroup
import androidx.annotation.UiThread
import com.facebook.react.bridge.WritableMap
import com.facebook.react.bridge.WritableNativeMap
import com.facebook.react.uimanager.StateWrapper
import com.facebook.react.uimanager.PixelUtil

abstract class FabricEnabledHeaderSubviewGroup(context: Context?): ViewGroup(context) {
private var mStateWrapper: StateWrapper? = null

fun setStateWrapper(wrapper: StateWrapper?) {
mStateWrapper = wrapper
}

protected fun updateSubviewFrameState(
width: Int,
height: Int,
offsetX: Int,
offsetY: Int
) {
updateState(width, height, offsetX, offsetY)
}

@UiThread
fun updateState(
width: Int,
height: Int,
offsetX: Int,
offsetY: Int
) {
val realWidth: Float = PixelUtil.toDIPFromPixel(width.toFloat())
val realHeight: Float = PixelUtil.toDIPFromPixel(height.toFloat())
val offsetXDip: Float = PixelUtil.toDIPFromPixel(offsetX.toFloat())
val offsetYDip: Float = PixelUtil.toDIPFromPixel(offsetY.toFloat())

val map: WritableMap = WritableNativeMap().apply {
putDouble("frameWidth", realWidth.toDouble())
putDouble("frameHeight", realHeight.toDouble())
putDouble("contentOffsetX", offsetXDip.toDouble())
putDouble("contentOffsetY", offsetYDip.toDouble())
}

mStateWrapper?.updateState(map)
}

}
12 changes: 9 additions & 3 deletions android/src/main/java/com/swmansion/rnscreens/CustomToolbar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,14 @@ open class CustomToolbar(
) {
super.onLayout(changed, l, t, r, b)

// our children are already laid out
val contentInsetStart = if (navigationIcon != null) contentInsetStartWithNavigation else contentInsetStart
config.updatePaddingsFabric(contentInsetStart, contentInsetEnd)
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
val width = r - l;
val height = b - t;
config.updateHeaderConfigState(width, height)
} else {
// our children are already laid out
val contentInsetStart = if (navigationIcon != null) contentInsetStartWithNavigation else contentInsetStart
config.updatePaddings(contentInsetStart, contentInsetEnd)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import com.facebook.react.views.view.ReactViewGroup
@SuppressLint("ViewConstructor")
class ScreenStackHeaderSubview(
context: ReactContext?,
) : ReactViewGroup(context) {
) : FabricEnabledHeaderSubviewGroup(context) {
private var reactWidth = 0
private var reactHeight = 0
var type = Type.RIGHT
Expand Down Expand Up @@ -37,11 +37,17 @@ class ScreenStackHeaderSubview(

override fun onLayout(
changed: Boolean,
left: Int,
top: Int,
right: Int,
bottom: Int,
) = Unit
l: Int,
t: Int,
r: Int,
b: Int,
) {
if (changed && BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
val width = r - l;
val height = b - t;
updateSubviewFrameState(width, height, l, t)
}
}

enum class Type {
LEFT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package com.swmansion.rnscreens

import com.facebook.react.bridge.JSApplicationIllegalArgumentException
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.ReactStylesDiffMap
import com.facebook.react.uimanager.StateWrapper
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.ViewGroupManager
import com.facebook.react.uimanager.ViewManagerDelegate
Expand Down Expand Up @@ -39,6 +41,17 @@ class ScreenStackHeaderSubviewManager :
}
}

override fun updateState(
view: ScreenStackHeaderSubview,
props: ReactStylesDiffMap?,
stateWrapper: StateWrapper?
): Any? {
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
view.setStateWrapper(stateWrapper)
}
return super.updateState(view, props, stateWrapper)
}

protected override fun getDelegate(): ViewManagerDelegate<ScreenStackHeaderSubview> = delegate

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,14 @@ abstract class FabricEnabledHeaderConfigViewGroup(

fun setStateWrapper(wrapper: StateWrapper?) = Unit

fun updatePaddingsFabric(
fun updateHeaderConfigState(
width: Int,
height: Int,
) {
// do nothing
}

fun updatePaddings(
paddingStart: Int,
paddingEnd: Int,
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.swmansion.rnscreens

import android.content.Context
import android.view.ViewGroup
import com.facebook.react.uimanager.StateWrapper

abstract class FabricEnabledHeaderSubviewGroup(context: Context?): ViewGroup(context) {

fun setStateWrapper(wrapper: StateWrapper?) = Unit

protected fun updateSubviewFrameState(
width: Int,
height: Int,
offsetX: Int,
offsetY: Int
) {
// do nothing
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ class RNSScreenStackHeaderConfigComponentDescriptor final
shadowNode.getState());
auto stateData = state->getData();

layoutableShadowNode.setPadding(
{stateData.getPaddingStart(), 0, stateData.getPaddingEnd(), 0});
if (stateData.frameSize.width != 0 && stateData.frameSize.height != 0) {
layoutableShadowNode.setSize(Size{stateData.frameSize.width, stateData.frameSize.height});
}

ConcreteComponentDescriptor::adopt(shadowNode);
#if !defined(ANDROID) && !defined(NDEBUG)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@ namespace facebook::react {
extern const char RNSScreenStackHeaderConfigComponentName[] =
"RNSScreenStackHeaderConfig";

void RNSScreenStackHeaderConfigShadowNode::layout(LayoutContext layoutContext) {
YogaLayoutableShadowNode::layout(layoutContext);
applyFrameCorrections();
}

void RNSScreenStackHeaderConfigShadowNode::applyFrameCorrections() {
ensureUnsealed();

const auto &stateData = getStateData();
layoutMetrics_.frame.origin.y = -stateData.frameSize.height;
}

#if !defined(ANDROID) && !defined(NDEBUG)
void RNSScreenStackHeaderConfigShadowNode::setImageLoader(
std::weak_ptr<void> imageLoader) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@ class JSI_EXPORT RNSScreenStackHeaderConfigShadowNode final
using StateData = ConcreteViewShadowNode::ConcreteStateData;

#pragma mark - ShadowNode overrides
void layout(LayoutContext layoutContext) override;

#pragma mark - Custom interface

void applyFrameCorrections();

#if !defined(ANDROID) && !defined(NDEBUG)
void setImageLoader(std::weak_ptr<void> imageLoader);
#endif // !ANDROID && !NDEBUG
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@

#include "RNSScreenStackHeaderConfigState.h"

namespace facebook {
namespace react {

#ifdef ANDROID
folly::dynamic RNSScreenStackHeaderConfigState::getDynamic() const {
return folly::dynamic::object("paddingStart", paddingStart_)(
"paddingEnd_", paddingEnd_);
return folly::dynamic::object("frameWidth", frameSize.width)(
"frameHeight", frameSize.height)("contentOffsetX", contentOffset.x)(
"contentOffsetY", contentOffset.y);
}
#else // ANDROID
#ifndef NDEBUG
Expand All @@ -22,13 +24,6 @@ std::weak_ptr<void> RNSScreenStackHeaderConfigState::getImageLoader()
#endif // !NDEBUG
#endif // ANDROID

Float RNSScreenStackHeaderConfigState::getPaddingStart() const noexcept {
return paddingStart_;
}

Float RNSScreenStackHeaderConfigState::getPaddingEnd() const noexcept {
return paddingEnd_;
}

} // namespace react
} // namespace facebook
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@ class JSI_EXPORT RNSScreenStackHeaderConfigState final {

RNSScreenStackHeaderConfigState() = default;

RNSScreenStackHeaderConfigState(Float paddingStart, Float paddingEnd)
: paddingStart_{paddingStart}, paddingEnd_{paddingEnd} {}
RNSScreenStackHeaderConfigState(Size frameSize_)
: frameSize(frameSize_) {}

#ifdef ANDROID
RNSScreenStackHeaderConfigState(
RNSScreenStackHeaderConfigState const &previousState,
folly::dynamic data)
: paddingStart_{static_cast<Float>(data["paddingStart"].getDouble())},
paddingEnd_{static_cast<Float>(data["paddingEnd"].getDouble())} {}
: frameSize(Size{
(Float)data["frameWidth"].getDouble(),
(Float)data["frameHeight"].getDouble()}){}
#endif

#ifdef ANDROID
Expand All @@ -40,15 +41,12 @@ class JSI_EXPORT RNSScreenStackHeaderConfigState final {
#endif // !NDEBUG
#endif // ANDROID

#pragma mark - Getters

[[nodiscard]] Float getPaddingStart() const noexcept;
const Size frameSize{};
Point contentOffset;

[[nodiscard]] Float getPaddingEnd() const noexcept;
#pragma mark - Getters

private:
Float paddingStart_{0.f};
Float paddingEnd_{0.f};
#if !defined(ANDROID) && !defined(NDEBUG)
std::weak_ptr<void> imageLoader_;
#endif // !ANDROID && !NDEBUG
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,25 @@ class RNSScreenStackHeaderSubviewComponentDescriptor final
using ConcreteComponentDescriptor::ConcreteComponentDescriptor;

void adopt(ShadowNode &shadowNode) const override {
react_native_assert(
dynamic_cast<RNSScreenStackHeaderSubviewShadowNode *>(&shadowNode));
auto &subviewShadowNode =
static_cast<RNSScreenStackHeaderSubviewShadowNode &>(shadowNode);

react_native_assert(
dynamic_cast<YogaLayoutableShadowNode *>(&subviewShadowNode));
auto &layoutableShadowNode =
dynamic_cast<YogaLayoutableShadowNode &>(subviewShadowNode);

auto state = std::static_pointer_cast<
const RNSScreenStackHeaderSubviewShadowNode::ConcreteState>(
shadowNode.getState());
auto stateData = state->getData();

if (stateData.frameSize.width != 0 && stateData.frameSize.height != 0) {
layoutableShadowNode.setSize(Size{stateData.frameSize.width, stateData.frameSize.height});
}

ConcreteComponentDescriptor::adopt(shadowNode);
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,18 @@ namespace facebook::react {
extern const char RNSScreenStackHeaderSubviewComponentName[] =
"RNSScreenStackHeaderSubview";

} // namespace facebook::react
void RNSScreenStackHeaderSubviewShadowNode::layout(LayoutContext layoutContext) {
YogaLayoutableShadowNode::layout(layoutContext);
applyFrameCorrections();
}

void RNSScreenStackHeaderSubviewShadowNode::applyFrameCorrections() {
ensureUnsealed();

const auto &stateData = getStateData();
layoutMetrics_.frame.origin.x = stateData.contentOffset.x;
layoutMetrics_.frame.origin.y = stateData.contentOffset.y;
}

}

Loading
Loading