Skip to content

Commit

Permalink
Revert "removed unnecessary code"
Browse files Browse the repository at this point in the history
  • Loading branch information
alduzy committed Aug 23, 2024
1 parent 496a1a6 commit aee2a1f
Show file tree
Hide file tree
Showing 7 changed files with 216 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#pragma once

#include <cstdint>

namespace rnscreens {

/**
* Flags describing types of corrections to apply to Screen frame
* after layout process.
*/
class FrameCorrectionModes final {
public:
enum Mode : std::uint8_t {
/**
* No correction should be applied to layout metrics of Screen
*/
None = 0,

/**
* Screen's frame height should be corrected
*/
FrameHeightCorrection = 1 << 0,

/**
* Screen's frame origin should be corrected
*/
FrameOriginCorrection = 1 << 1,
};

inline void set(Mode mode) {
modes_ = Mode(modes_ | mode);
}

inline void unset(Mode mode) {
modes_ = Mode(modes_ & ~mode);
}

// Check whether current set of flags contains all flags set in argument.
inline bool check(Mode mode) const {
return Mode(modes_ & mode) == mode;
}

inline Mode getAll() const {
return modes_;
}

private:
Mode modes_{Mode::None};
};

} // namespace rnscreens
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
#pragma once

#ifdef ANDROID
#include <fbjni/fbjni.h>
#endif
#include <react/debug/react_native_assert.h>
#include <react/renderer/components/rnscreens/Props.h>
#include <react/renderer/core/ConcreteComponentDescriptor.h>
#include "RNSScreenShadowNode.h"
#include "utils/RectUtil.h"

namespace facebook {
namespace react {

using namespace rnscreens;

class RNSScreenComponentDescriptor final
: public ConcreteComponentDescriptor<RNSScreenShadowNode> {
public:
Expand All @@ -30,9 +36,35 @@ class RNSScreenComponentDescriptor final
#ifdef ANDROID
if (stateData.frameSize.width != 0 && stateData.frameSize.height != 0) {
// When we receive dimensions from JVM side we can remove padding used for
// correction
// correction, and we can stop applying height correction for the frame.
// We want to leave top offset correction though intact.
// TODO: In future, when we have dynamic header height we might want to
// update Y offset correction here.

#ifdef REACT_NATIVE_DEBUG
// We use the fact that height correction is disabled once we receive
// state from the native, so when we have incoming state & height
// correction is still enabled, we know this is the very first native
// state update.
if (screenShadowNode.getFrameCorrectionModes().check(
FrameCorrectionModes::Mode::FrameHeightCorrection) &&
!checkFrameSizesEqualWithEps(
screenShadowNode.layoutMetrics_.frame.size,
stateData.frameSize)) {
LOG(ERROR)
<< "[RNScreens] The first frame received from state update: "
<< stateData.frameSize.width << "x" << stateData.frameSize.height
<< " differs from the one expected: "
<< screenShadowNode.layoutMetrics_.frame.size.width << "x"
<< screenShadowNode.layoutMetrics_.frame.size.height
<< ". This is most likely a react-native-screens library bug. Please report this at https://github.com/software-mansion/react-native-screens/issues";
}
#endif

screenShadowNode.setPadding({0, 0, 0, 0});
screenShadowNode.getFrameCorrectionModes().unset(
FrameCorrectionModes::Mode::FrameHeightCorrection);

layoutableShadowNode.setSize(
Size{stateData.frameSize.width, stateData.frameSize.height});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
namespace facebook {
namespace react {

namespace yoga = facebook::yoga;
using namespace rnscreens;

extern const char RNSScreenComponentName[] = "RNSScreen";

Point RNSScreenShadowNode::getContentOriginOffset(
Expand Down Expand Up @@ -106,12 +109,53 @@ void RNSScreenShadowNode::appendChild(const ShadowNode::Shared &child) {
.value_or(0.f);

screenShadowNode.setPadding({0, 0, 0, headerHeight});
screenShadowNode.setHeaderHeight(headerHeight);
screenShadowNode.getFrameCorrectionModes().set(
FrameCorrectionModes::Mode(
FrameCorrectionModes::Mode::FrameHeightCorrection |
FrameCorrectionModes::Mode::FrameOriginCorrection));
}
}
#endif // ANDROID
}

void RNSScreenShadowNode::layout(facebook::react::LayoutContext layoutContext) {
YogaLayoutableShadowNode::layout(layoutContext);

#ifdef ANDROID
applyFrameCorrections();
#endif // ANDROID
}

#ifdef ANDROID
void RNSScreenShadowNode::applyFrameCorrections() {
ensureUnsealed();

// On the very first layout we want to correct both Y offset and frame size.
// On consecutive layouts we want to correct only Y offset, as the frame size
// is received from JVM side. This is done so if the Screen dimensions are
// read from ShadowTree (e.g by reanimated) they have chance of being
// accurate. On JVM side we do ignore this frame anyway, because
// ScreenStackViewManager.needsCustomLayoutForChildren() == true.
const auto &stateData = getStateData();
const float lastKnownHeaderHeight = stateData.getLastKnownHeaderHeight();
const auto &headerCorrectionModes = stateData.getHeaderCorrectionModes();
layoutMetrics_.frame.origin.y += lastKnownHeaderHeight *
headerCorrectionModes.check(
FrameCorrectionModes::Mode::FrameOriginCorrection);
layoutMetrics_.frame.size.height -= lastKnownHeaderHeight *
headerCorrectionModes.check(
FrameCorrectionModes::Mode::FrameHeightCorrection);
}

void RNSScreenShadowNode::setHeaderHeight(float headerHeight) {
getStateDataMutable().setHeaderHeight(headerHeight);
}

FrameCorrectionModes &RNSScreenShadowNode::getFrameCorrectionModes() {
return getStateDataMutable().getFrameCorrectionModes();
}

RNSScreenShadowNode::StateData &RNSScreenShadowNode::getStateDataMutable() {
// We assume that this method is called to mutate the data, so we ensure
// we're unsealed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
#include <react/renderer/components/rnscreens/Props.h>
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
#include <react/renderer/core/LayoutContext.h>
#include "FrameCorrectionModes.h"
#include "RNSScreenState.h"

namespace facebook {
namespace react {

using namespace rnscreens;

JSI_EXPORT extern const char RNSScreenComponentName[];

class JSI_EXPORT RNSScreenShadowNode final : public ConcreteViewShadowNode<
Expand All @@ -27,12 +30,18 @@ class JSI_EXPORT RNSScreenShadowNode final : public ConcreteViewShadowNode<

void appendChild(const ShadowNode::Shared& child) override;

void layout(LayoutContext layoutContext) override;

#pragma mark - Custom interface

void setHeaderHeight(float headerHeight);

FrameCorrectionModes &getFrameCorrectionModes();

private:
#ifdef ANDROID
void applyFrameCorrections();

StateData &getStateDataMutable();
#endif // ANDROID
};
Expand Down
19 changes: 19 additions & 0 deletions common/cpp/react/renderer/components/rnscreens/RNSScreenState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,32 @@
namespace facebook {
namespace react {

using namespace rnscreens;

#ifdef ANDROID
folly::dynamic RNSScreenState::getDynamic() const {
return folly::dynamic::object("frameWidth", frameSize.width)(
"frameHeight", frameSize.height)("contentOffsetX", contentOffset.x)(
"contentOffsetY", contentOffset.y);
}

void RNSScreenState::setHeaderHeight(float headerHeight) {
lastKnownHeaderHeight_ = headerHeight;
}

float RNSScreenState::getLastKnownHeaderHeight() const noexcept {
return lastKnownHeaderHeight_;
}

FrameCorrectionModes &RNSScreenState::getFrameCorrectionModes() noexcept {
return headerCorrectionModes_;
}

const FrameCorrectionModes &RNSScreenState::getHeaderCorrectionModes()
const noexcept {
return headerCorrectionModes_;
}

#endif

} // namespace react
Expand Down
25 changes: 24 additions & 1 deletion common/cpp/react/renderer/components/rnscreens/RNSScreenState.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@
#include <react/renderer/mapbuffer/MapBufferBuilder.h>
#endif

#include "FrameCorrectionModes.h"

namespace facebook {
namespace react {

using namespace rnscreens;

class JSI_EXPORT RNSScreenState final {
public:
using Shared = std::shared_ptr<const RNSScreenState>;
Expand All @@ -27,7 +31,9 @@ class JSI_EXPORT RNSScreenState final {
(Float)data["frameHeight"].getDouble()}),
contentOffset(Point{
(Float)data["contentOffsetX"].getDouble(),
(Float)data["contentOffsetY"].getDouble()}){};
(Float)data["contentOffsetY"].getDouble()}),
lastKnownHeaderHeight_{previousState.lastKnownHeaderHeight_},
headerCorrectionModes_{previousState.headerCorrectionModes_} {};
#endif

const Size frameSize{};
Expand All @@ -38,8 +44,25 @@ class JSI_EXPORT RNSScreenState final {
MapBuffer getMapBuffer() const {
return MapBufferBuilder::EMPTY();
};

void setHeaderHeight(float headerHeight);

float getLastKnownHeaderHeight() const noexcept;

FrameCorrectionModes &getFrameCorrectionModes() noexcept;

const FrameCorrectionModes &getHeaderCorrectionModes() const noexcept;

#endif

private:
#ifdef ANDROID
// Header height as measured on dummy layout
float lastKnownHeaderHeight_{0.f};

FrameCorrectionModes headerCorrectionModes_{};
#endif // ANDROID

#pragma mark - Getters
};

Expand Down
36 changes: 36 additions & 0 deletions common/cpp/react/renderer/components/rnscreens/utils/RectUtil.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#pragma once

#include <react/renderer/graphics/Float.h>
#include <react/renderer/graphics/Size.h>
#include <cmath>
#include <concepts>

namespace rnscreens {

namespace react = facebook::react;

template <typename T>
requires std::is_floating_point_v<T>
inline constexpr bool equalWithRespectToEps(const T a, const T b, const T eps) {
return std::abs(a - b) <= eps;
}

/**
* Compares given two frame sizes with respect to the epsilon.
*
* @param first first frame size
* @param second second frame size
* @param eps comparison precision, defaults to 0.01, which should ensure that
* precision of comparison is under 1px
* @return whether the frame dimensions are the same with respect to given
* epsilon
*/
inline constexpr bool checkFrameSizesEqualWithEps(
const react::Size &first,
const react::Size &second,
const react::Float eps = 0.01) {
return equalWithRespectToEps(first.width, second.width, eps) &&
equalWithRespectToEps(first.height, second.height, eps);
}

} // namespace rnscreens

0 comments on commit aee2a1f

Please sign in to comment.